Story: Admin Row CRUD
story: Admin Row CRUD
Role
Admin (Lucas primarily, Marcus occasionally)
Key
admin-row-crud
Want
As an admin, I want to view and edit any row in the basketball database through a web UI gated by my existing Keycloak admin role
So That
So that I can fix data issues directly — without running raw UPDATEs in psql (banned per
feedback_never_write_prod_db after the 16U Local Queens schedule wipe), and without waiting for a new admin route to be hand-built in westside-app every time a new data shape needs touchingAcceptance Criteria
- [ ] SSO from westside-app — opening westside-admin in same browser does not require second login form
- [ ] Non-admins (no
adminrealm role) see a 403 page with logout button, never any data - [ ] Index page lists all visible tables in basketball db (sensitive tables hidden)
- [ ] Click any table → paginated, type-aware grid of rows (50/page, filter inputs, enums as badges, dates formatted, jsonb expandable)
- [ ] Click any row → editable form with type-correct inputs (text, number, date picker, enum dropdown, jsonb code editor, boolean toggle)
- [ ] Save → row updates in Postgres, audit trail row written in same transaction
- [ ] tenant_id scoping enforced in every query — URL tampering can't leak other tenants' rows
- [ ] Failed save shows Postgres error inline next to offending field
Success Metric
- Lucas: zero
kubectl exec ... psqlsessions for UPDATE statements over a 30-day window after launch - Marcus: zero "Lucas, can you fix X for me?" messages for routine data corrections over a 30-day window
Out of Scope (v1)
- INSERT (creating new rows) — too risky without a row-template convention
- DELETE — too risky without a tombstone pattern
- Bulk multi-row edit
- Cross-table joins / custom queries
- Any user role besides
admin
Safety Constraints (not separate stories — guarantees on this story)
- Keycloak admin gate. Cookie SSR auth, JWKS validation per request, HttpOnly token cookie, public funnel safe per
feedback_funnel_requires_auth. - Tenant scoping. Query helper auto-injects
WHERE tenant_id = ?; v1 hardcoded TENANT_ID=1; direct unscopeddbnot exported. - Schema introspection. Drizzle schema generated from live Postgres via
drizzle-kit pull; CI fails on drift.
What This Story Replaces
| Today | After westside-admin |
|---|---|
| Lucas sshs to archbox, kubectl exec into postgres pod, runs UPDATE statements by hand | Lucas opens westside-admin, edits row, saves |
| Marcus texts Lucas to fix a player record | Marcus opens westside-admin, fixes it himself |
| Building a custom <code>/admin/X/edit</code> route in westside-app every time a new admin need arises | Generic row editor handles it for free |
Related Architecture
arch-domain-westside-admin— entities being read/writtenarch-dataflow-westside-admin— auth + page load + mutation flowsarch-deployment-westside-admin— deployment topology
Related
project-westside-admin— parent project pageboard-westside-admin— project boardfeedback_never_write_prod_db— driving constraint (no more raw psql UPDATEs)feedback_funnel_requires_auth— driving constraint (admin gate must be airtight)