Review: Seed Gmail OAuth token into oauth_tokens DB table for resilience
Verdict: APPROVED
The scope is valid and the issue is well-written. However, the reviewer notes a critical context gap: the code-level feature already exists. The remaining work is an ops-level task (running the seed script against production). This does not block approval -- the issue correctly identifies the gap and the file targets are accurate enough to guide an agent to the right place.
Template Completeness
- [x] Type -- Feature
- [x] Lineage -- discovered scope from westside-landing #169
- [x] Repo -- forgejo_admin/basketball-api
- [x] User Story -- as a superadmin, survive pod restarts
- [x] Context -- explains file-based token limitation and outage root cause
- [x] File Targets -- present (see accuracy notes below)
- [x] Test Expectations -- 3 test categories listed
- [x] Constraints -- 3 constraints documented
- [x] Acceptance Criteria -- 4 criteria listed
- [x] Checklist -- present
- [x] Related -- links to #169 and project page
Traceability
- [x] story:WS-S21 label -- password reset / auth self-service story (7 sibling items on board, including done items #223, #239, #617, #644)
- [x] arch:basketball-api label -- correct, all changes are in basketball-api
- [x] Forgejo issue -- forgejo_admin/basketball-api#242, open
File Targets
- [x]
src/basketball_api/services/email.py-- verified: exists, already contains DB-backed token loading viaget_gmail_client()(lines 29-57) with fallback to file-based tokens - [ ]
src/basketball_api/models/-- INACCURATE: nomodels/directory exists. TheOAuthTokenmodel is insrc/basketball_api/models.py(single file, line 479). Issue should saymodels.pynotmodels/ - [x] Migration script -- verified:
alembic/versions/021_add_oauth_tokens_table.pyalready exists and creates theoauth_tokenstable - [x] (Undocumented)
src/basketball_api/services/token_store.py-- already implements full token load/save/refresh/seed lifecycle (176 lines) - [x] (Undocumented)
scripts/seed_oauth_token.py-- CLI seed script already exists - [x] (Undocumented)
tests/test_token_store.py-- 12 tests covering save/load, refresh, seed, and integration
Repo Placement
OK. Issue filed on basketball-api, all code changes are in basketball-api. No cross-repo impact -- k8s secret mounting stays unchanged per constraints.
Dependencies
- [x] Board item #229 (Spike: Gmail OAuth token persistence in Postgres) -- done, closed as basketball-api#130. This spike already built the entire feature described in #242.
- [x] Board item #644 (Bug: Password reset flow not working) -- done, the outage that discovered this gap.
- [x] Phase 21 (board item #288, Enterprise Auth) -- in backlog, blocked by platform phase-28. Parent story arc, not a direct dependency.
- No in_progress blockers found.
Acceptance Criteria
All 4 acceptance criteria are already met by existing code:
- [x] "oauth_tokens table seeded on startup or via migration" -- migration 021 creates the table;
seed_from_file()+ CLI script exist. Remaining gap: run seed against prod. - [x] "Token refresh logic uses DB store as primary, file as fallback" --
get_gmail_client()lines 42-57 do exactly this. - [x] "Pod restart does not break email sending" -- DB-backed tokens persist across restarts by design.
- [x] "Monitoring/logging when token refresh fails" --
token_store.pylines 152-153 and 169-173 log failures.
The remaining work is purely operational: run
python scripts/seed_oauth_token.py westsidebasketball against prod (or equivalent kubectl exec). An agent dispatched against this issue would find nothing to code.Blast Radius
Low. Gmail OAuth is used only by basketball-api's email service. No sibling services consume
token_store.py. The pal-e-mail service uses its own gmail-sdk integration and is an archive candidate per memory.Decomposition Assessment
No decomposition needed. The actual remaining work (seed prod DB) is a single ops command, well under 5 minutes. 1 discrete change, 0 file targets to modify, 0 repos to touch with code. If the issue is reframed as an ops task rather than a feature, it is a single-step action.
Recommendation
[BODY]Fix file path:src/basketball_api/models/should besrc/basketball_api/models.py(single file, not directory)[BODY]Reframe scope: the code feature is already implemented (spike #130). The remaining work is ops -- seed the prodoauth_tokenstable by running the existing seed script. Consider changing Type from Feature to Task.[BODY]Add file targets for existing code:services/token_store.py,scripts/seed_oauth_token.py,tests/test_token_store.py-- these are the actual implementation files an agent needs to know about.