Validation: Add declined status to ContractStatus enum
Verdict: PASS
Ticket
forgejo_admin/basketball-api#379 — Added
declined value to ContractStatus enum so families who explicitly declined contracts are distinguishable from those never contacted. Alembic migration updated Postgres enum and set 5 players to declined.Environment
Production cluster, namespace
basketball-api, pod basketball-api-868ffc7cbf-qzpz6, image tag 7f4a9dbe97a009c84a1a2c5ce0b3231814ae1731.Tiers Executed
Tier 1 (CI pipeline) + Tier 3 (production verification). No staging environment for this repo.
Checks
| # | Criterion | How Verified | Result | Evidence |
|---|---|---|---|---|
| 1 | <code>declined = "declined"</code> added to ContractStatus enum | Python import in running container: <code>from basketball_api.models import ContractStatus; [e.value for e in ContractStatus]</code> | PASS | Enum values: ['none', 'offered', 'signed', 'declined'] |
| 2 | Alembic migration adds enum value to Postgres and updates players (ids 98, 94, 134 per issue; 89, 140 also set) | SQL query: <code>SELECT unnest(enum_range(NULL::contractstatus))::text</code> and <code>SELECT id, name, contract_status FROM players WHERE contract_status = 'declined'</code> | PASS | Postgres enum: ['none', 'offered', 'signed', 'declined']. 5 players declined: id=89 Connor Behunin, id=94 Patrick Kirschman, id=98 Boston Greenhalgh, id=134 Stein Kunic, id=140 Maureen |
| 3 | Email blast endpoints exclude <code>contract_status=declined</code> | Source inspection: <code>grep -r "declined" /app/src/</code> — email_queries.py uses <code>Player.contract_status.notin_([ContractStatus.signed, ContractStatus.declined])</code> | PASS | Filter in email_queries.py excludes both signed and declined. Same pattern in admin.py routes. |
| 4 | No regression in contract signing flow | Contract status distribution query + endpoint smoke tests. Distribution: none=5, offered=26, signed=27, declined=5. Docs endpoint returns 200. Contract endpoint returns 401 (expected — auth required). | PASS | All status values present and correctly distributed. No unexpected zeros or missing categories. |
Pipeline & Deployment
Woodpecker pipeline #404: all 5 steps green (clone, postgres, test, build-and-push, update-kustomize-tag). Pod running with 0 restarts, age 108s at validation time. ArgoCD synced new image.
Regression Check
Contract status distribution is healthy (none=5, offered=26, signed=27, declined=5 — totals 63 players). API docs endpoint responsive (HTTP 200). No crash loops or unexpected restarts.
Discovered Issues
None. Issue body listed 3 players (98, 94, 134) but migration correctly updated 5 (also 89, 140). This is correct — additional players were identified during implementation.