Review: T6 westside-landing /admin/jersey-orders page

review-951-2026-04-10 Doc

review approved

Verdict: APPROVED

Scope is solid, fits a single agent pass, all file targets verified, traceability complete except arch note (tracked as [SCOPE]).

Template Completeness

  • [x] Type: Feature
  • [x] Lineage (depends on basketball-api#432)
  • [x] Repo
  • [x] User Story
  • [x] Context
  • [x] File Targets (create + do-not-touch)
  • [x] Acceptance Criteria (10 items)
  • [x] Test Expectations
  • [x] Constraints
  • [x] Checklist
  • [x] Related

Traceability

  • [x] story:WS-S31 label - verified on project-westside-basketball stories-admin section (long-standing public jersey order link admin story)
  • [x] arch:jersey-intake label present
  • [ ] arch note MISSING - search_notes for "arch-jersey-intake" returned zero results. [SCOPE] Create architecture note arch-jersey-intake for the jersey intake component.
  • [x] Forgejo issue forgejo_admin/westside-landing#244 - open, well-formed body
  • [x] wave:3 label, scope:production, type:feature all present

File Targets

  • [x] src/routes/(app)/admin/jersey-orders/+page.svelte - does not exist yet (correct, this ticket creates it). Parent directory src/routes/(app)/admin/ exists with sibling routes commerce/players/schedule/teams/users/+page.svelte.
  • [x] src/routes/(app)/admin/jersey-orders/+page.js - does not exist yet (correct, this ticket creates it).
  • [x] src/routes/(app)/+layout.svelte - verified exists. Contains the exact guard pattern stated in the ticket: if (authenticated && path.startsWith('/admin') && !hasRole('admin')) { goto(getRoleRedirectPath()); } Also handles unauth -> /signin redirect. No modification needed.
  • [x] src/lib/keycloak.js - verified exists. Exports confirmed: initKeycloak, login, logout, getToken, isAuthenticated, getUserId, getUserName, getUserRoles, hasRole, getPrimaryRole, getRoleRedirectPath. getToken() is real.

Repo Placement

OK. Issue is filed on forgejo_admin/westside-landing, which owns the SvelteKit admin UI. T5 (basketball-api#432) correctly scoped to the sibling API repo.

Dependencies

  • Depends on basketball-api#432 (GET /api/jersey-public-orders admin list endpoint) - verified open on Forgejo. T5 must merge first; this is explicitly called out in Lineage and Checklist.
  • No conflicts with T1 (issue #243, jersey-public form) - explicitly hands off that path.
  • No modification to +layout.svelte - uses existing auth guard, no new auth layer.

Acceptance Criteria

10 criteria, all verifiable by a component test or manual role-switch check:
  • Unauth -> /signin (existing layout guard) - testable
  • Non-admin -> role dashboard (existing layout guard) - testable
  • Admin -> list ordered recent-first - testable
  • Status filter (5 values) - testable
  • Date range filter - testable
  • Row columns enumerated (10 fields) - testable
  • Row expand fields enumerated (5 fields) - testable
  • Empty state, pagination, loading, error states - all testable
Test expectations explicitly list three component tests plus the westside-landing runner. Good coverage for a read-only view.

Blast Radius

Minimal. New route directory, isolated from other admin pages. Sibling admin routes (commerce, players, schedule, teams, users) are untouched. No auth layer changes. No shared component edits. Only external call is a read GET to basketball-api with a Bearer token - same pattern as other admin pages presumably already use.

Decomposition

No decomposition needed. 2 new files in 1 repo, 10 ACs but all on a single read-only list page, estimated <5 min agent pass. Under the 5-minute rule threshold (>3 files across >2 repos OR >5 ACs of substantive scope). ACs here are mostly UI states on one component.

Recommendation

  • [SCOPE] Create architecture note arch-jersey-intake in pal-e-docs. The ticket references it in Lineage and Related, and the board item carries arch:jersey-intake, but the note does not exist. This is a tracking gap, not a code blocker - the ticket itself is self-contained enough that dev can proceed. Create in parallel.
Ticket is APPROVED and ready to advance to next_up once T5 (basketball-api#432) is merged. No body or label fixes required.