Validation: Fix confirmation email skipped for existing Keycloak accounts + token=None in profile URL
Verdict: PASS
Ticket
forgejo_admin/basketball-api#390 — Fix confirmation email not sending for existing Keycloak accounts during promo registration, and token=None appearing in profile URL.
Merged PR: #396 (commit
0776b49)Environment
Production cluster, namespace
basketball-api. Pod: basketball-api-6496655cfd-cgkdt, image tag 2d85242 (includes PR #396 + subsequent merges). Tailscale funnel: https://basketball-api.tail5b443a.ts.net.Tiers Executed
Tier 1 (local tests) + Tier 3 (production health check). No staging environment.
Checks
| # | Criterion | How Verified | Result | Evidence |
|---|---|---|---|---|
| 1 | Promo registration with existing Keycloak account sends confirmation email (without credentials block) | Tier 1: <code>pytest tests/ -k test_register</code> — test <code>test_promo_existing_keycloak_sends_confirmation_email</code> asserts <code>mock_email.assert_called_once()</code> and <code>credentials=None</code>. Code review: <code>send_confirmation_email()</code> moved outside <code>if keycloak_credentials:</code> block in register.py. | PASS | 85 passed, 0 failed (11.72s). Code diff confirms unconditional call at line ~1471. |
| 2 | Profile URL in email has valid token (not None) | Tier 1: test <code>test_promo_registration_generates_registration_token</code> verifies <code>parent.registration_token</code> is set. Code review: <code>secrets.token_urlsafe(32)</code> added at line ~1269 before email send. | PASS | Token generation guard added: <code>if not parent.registration_token: parent.registration_token = secrets.token_urlsafe(32)</code> |
| 3 | Webhook path with existing Keycloak account sends confirmation email | Tier 1: <code>test_webhooks.py</code> — same pattern applied in webhooks.py. <code>send_confirmation_email()</code> moved outside <code>if keycloak_credentials:</code> guard. 85 tests passed including webhook tests. | PASS | Code diff confirms webhooks.py fix mirrors register.py fix. |
| 4 | New Keycloak account still includes credentials in email (no regression) | Tier 1: test <code>test_promo_new_keycloak_includes_credentials</code> asserts <code>credentials == fake_creds</code> when <code>create_account_for_parent</code> returns credentials. | PASS | 85 passed. Credentials passthrough preserved via <code>credentials=keycloak_credentials</code> argument. |
| 5 | Woodpecker CI pipeline green on main | Tier 3: Pipeline #416 status check. | PASS | Pipeline #416: 886 passed, 27 skipped in 197.62s. Status: success. |
| 6 | Pod running and healthy in production | Tier 3: <code>kubectl get pods -n basketball-api</code> | PASS | Pod <code>basketball-api-6496655cfd-cgkdt</code> Running, 0 restarts. Image: <code>harbor.tail5b443a.ts.net/basketball-api/api:2d85242</code> |
| 7 | API endpoints responding | Tier 3: curl /docs (200), curl /api/teams (401 — expected, requires auth) | PASS | /docs=200, /api/teams=401 (auth required, correct behavior) |
Regression Check
Full test suite: 886 passed, 27 skipped on pipeline #416. Local targeted run: 85 registration+webhook tests passed. API /docs and /api/teams endpoints responding correctly. Pod healthy with 0 restarts.
Discovered Issues
None. Health endpoint returns 404 at both
/health and /api/health — this is pre-existing (no health check route defined), not a regression from this PR.