Validation: Feature #389 - Payment recovery for abandoned Stripe registrations

validation-389-2026-04-08 Doc

validation pass

Verdict: PASS

Ticket

forgejo_admin/basketball-api#389 — Payment recovery for abandoned Stripe registrations. Adds admin-triggered recovery email for PENDING Stripe registrations older than 2 hours, with fresh payment link. Merged via PR #397.
Board item: #890 on board-westside-basketball
Labels: story:WS-S17, arch:registration, type:feature

Environment

Production cluster (k3s), namespace basketball-api, funnel URL https://basketball-api.tail5b443a.ts.net. Re-validation date: 2026-04-08.

Previous Verdict

FAIL (2026-04-08 earlier) — Pipeline #415 (PR #397 merge commit) built the image but skipped update-kustomize-tag due to test step failure. Pod was running older image from PR #399. See revision history for original FAIL evidence.

Resolution

Bug fix PR #407 (validation-405-2026-04-08) changed the Woodpecker pipeline so update-kustomize-tag runs regardless of test step status. Pipeline #420 (PR #407 merge) deployed a new image that includes all prior commits, including PR #397.

Checks (Re-validation)

# Criterion How Verified Result Evidence
1 PR #397 code included in deployed image Git commit lineage of deployed SHA PASS Deployed image tag <code>e9362ade17815be398db7f2fb898bef0f8d1478c</code> (pipeline #420). PR #397 merge commit <code>16b96f547b</code> confirmed in lineage (3rd commit back).
2 Image tag propagated to pod <code>kubectl get pods -n basketball-api -o jsonpath image</code> PASS Pod running <code>harbor.tail5b443a.ts.net/basketball-api/api:e9362ade17815be398db7f2fb898bef0f8d1478c</code>
3 Pod running, restarts = 0 <code>kubectl get pods -n basketball-api</code> PASS <code>basketball-api-7784854bb9-4t7qf 1/1 Running 0</code>
4 ArgoCD synced and healthy <code>kubectl get application -n argocd basketball-api</code> PASS Sync: Synced, Health: Healthy
5 <code>/admin/send-payment-recovery</code> endpoint exists (not 404) <code>curl -X POST</code> without auth PASS POST returns HTTP 401 (auth required). GET returns HTTP 405 (method not allowed). Endpoint is live and protected.
6 Endpoint in OpenAPI spec <code>curl /openapi.json</code> PASS <code>/admin/send-payment-recovery</code> present in OpenAPI paths.
7 Smoke test API reachable <code>curl /docs</code> PASS HTTP 200 on <code>https://basketball-api.tail5b443a.ts.net/docs</code>

Verdict

PASS — All checks green. The payment recovery endpoint is live in production. The previous deployment blocker (kustomize tag skip) was resolved by PR #407 (pipeline #420), which deployed the full image including PR #397's changes. Endpoint returns 401 without auth, confirming it exists and is properly protected.

Discovered Issues

None new. The deployment blocker was resolved by board item #901 (validation-405-2026-04-08). Previously discovered datetime.utcnow() deprecation warnings remain minor and non-blocking.