Review: Bug: parent phone missing from /admin/players list endpoint
Verdict: READY
Template Completeness
- [x] Type — Bug
- [x] Lineage — Standalone, discovered during admin CRM audit
- [x] Repo — forgejo_admin/basketball-api
- [x] What Broke — clear description of missing parent_phone field
- [x] Repro Steps — concrete steps with specific player/parent IDs
- [x] Expected Behavior — clearly stated
- [x] Environment — prod / basketball-api namespace
- [x] Acceptance Criteria — 4 criteria, all testable
- [x] Related — project reference and companion frontend ticket mentioned
Traceability
- [x] story:WS-S12 — "As an admin, I want to manage user accounts (reset passwords, view profiles) so that I can support parents directly"
- [x] story note verified — found in project-westside-basketball user-stories section (Admin stories list)
- [x] arch:basketball-api — references the basketball-api service
- [ ] arch note MISSING — [SCOPE] No arch-basketball-api note found in pal-e-docs. Platform-wide gap, not blocking this ticket.
- [x] Forgejo issue — forgejo_admin/basketball-api#276, open
File Targets
Issue does not specify exact file paths. Reviewer verified the bug location:
- [x]
src/basketball_api/routes/admin.py:290-297—AdminPlayerItemPydantic model hasparent_nameandparent_emailbut noparent_phonefield. Confirmed. - [x]
src/basketball_api/routes/admin.py:342-358— Constructor call buildsAdminPlayerItemwithoutparent_phone. Confirmed. - [x]
src/basketball_api/routes/admin.py:526— CSV export endpoint DOES includeparent_phone: p.parent.phone or "", proving the parent join already loads the phone. Fix pattern exists. - [x]
tests/test_admin_spa.py:236-249—test_response_fieldschecks expected fields but does not includeparent_phone. Test must be updated.
Repo Placement
OK. Issue is filed on forgejo_admin/basketball-api, and the fix is entirely within that repo. The companion frontend ticket (westside-app) is correctly scoped as a separate issue.
Dependencies
- [x] Parent join already loaded —
joinedload(Player.parent)at line 318. No additional query needed. - [x]
Parent.phonecolumn exists in database — no migration required. - [x] No blocking items on the board.
The westside-app companion ticket depends on THIS ticket, not the other way around. No blockers.
Acceptance Criteria
All 4 criteria are agent-verifiable:
- [x] AC1: "GET /admin/players response includes parent_phone field" — testable via existing test pattern in test_admin_spa.py
- [x] AC2: "parent_phone value matches parents.phone from database" — testable with populated_db fixture
- [x] AC3: "parent_phone is null for players with no parent phone set" — testable with fixture data (set phone=None)
- [x] AC4: "Existing admin list functionality unchanged" — existing tests cover filters, sorting, pagination
Blast Radius
- Same pattern exists:
IncompletePlayerItem(admin.py:403-409) also omitsparent_phone. Separate follow-up scope. - SubscriptionListItem (subscriptions.py:57-64) also omits
parent_phone. Different endpoint, different concern. - Roster endpoint (roster.py:24) already includes
parent_phone. No issue. - Tryouts endpoint (tryouts.py:456) already includes
parent_phone. No issue. - Rollback is trivial — revert the field addition. No data changes.
Decomposition Assessment
Apply the three-thing limit and five-minute rule:
- Discrete changes: 2 (add field to Pydantic model + pass in constructor). Well under 3.
- Test changes: 1 file (test_admin_spa.py field list update). Total: 2 files touched.
- Estimated agent time: under 2 minutes.
- No independent subtasks to parallelize.
No decomposition needed.
Recommendation
[SCOPE]Create architecture notearch-basketball-apifor the basketball-api service (platform-wide gap, not blocking this ticket).[BODY]Consider adding explicit file targets to the issue body for agent consumption:src/basketball_api/routes/admin.py(AdminPlayerItem model + constructor) andtests/test_admin_spa.py(test_response_fields).
Neither recommendation blocks dispatch. Ticket is READY.