Review: Subscription UI (3-page arch)
Verdict: NEEDS_REFINEMENT
Re-review v3 — previous review was
review-1611-2026-06-27-v2 (NEEDS_REFINEMENT). This re-review evaluates the rewritten scope after all three factual errors were corrected.Summary: The rewrite fixed the critical factual errors (subscription fields acknowledged, Stripe stays, #58 correctly open). The scope is now factually accurate. However, two issues remain: (1) the arch:app-store note still does not exist, and (2) the ticket still exceeds the 5-criterion decomposition threshold with 11 AC across 8 file targets. Decomposition is still needed.
Template Completeness
- [x] Type — Feature
- [x] Lineage — depends on #65 and #58, correctly stated both are open
- [x] Repo — ldraney/westside-basketball
- [x] User Story — WS-S35, WS-S36, WS-S37
- [x] Context — three-page architecture explained, Stripe coexistence clearly stated
- [x] File Targets — 8 targets listed (reduced from 11 in v2 after removing Stripe deletion targets)
- [x] Feature Flag — "none" (correct — repo has no docs/feature-flags.md, and this is informational display)
- [x] Acceptance Criteria — 11 criteria
- [x] Test Expectations — 4 test items + run command
- [x] Constraints — 5 constraints listed
- [x] Checklist — present
- [x] Related — stories, issues, project page, prior review note
Traceability
- [x] story:WS-S35 — verified on project-westside-basketball user-stories section: "As an admin, I want to set and manage subscription pricing on a player's detail page so that I control what each family pays for their program tier"
- [x] story:WS-S36 — verified on project-westside-basketball user-stories section: "As an admin, I want to see Apple subscription lifecycle states (subscribed, grace period, billing retry, expired) per player so that I know who's current, who's in grace, and who's delinquent"
- [x] story:WS-S37 — verified on project-westside-basketball user-stories section: "As a player or parent, I want to log in and see my subscription status and payment history so that I know where I stand and can take action if needed"
- [ ] arch:app-store — label present but arch note MISSING.
search_notes(query="arch-app-store")returned empty. [SCOPE] Create architecture note arch-app-store. - [x] Forgejo issue — westside-basketball#66, open
Factual Corrections Verified
All three factual errors flagged in v2 have been corrected:
- Subscription fields: Issue now correctly states "The codebase has active Stripe integration" with stripe_customer_id, stripe_subscription_id, and subscription_status enum listed. Verified against db/schema.rb lines 266-268. FIXED.
- Stripe stays: Issue now explicitly says "Do NOT delete any Stripe code. Stripe continues to handle one-off payments. Apple handles recurring subscriptions. Both coexist." File targets section adds explicit "Files the agent should NOT touch" list including all Stripe code. FIXED.
- #58 dependency: Issue now says "#58 is still open and must be implemented first." Lineage says "Depends on #58 (admin player detail page — still open, not yet implemented)." Verified: Forgejo issue #58 is open, show.html.erb does not exist on main. FIXED.
File Targets
- [x]
app/models/player.rb— verified exists. Issue correctly describes adding apple_subscription_status enum and new fields. Existing model has no explicit enum declaration in Ruby (DB-level enum only). Correct. - [x]
db/migrate/*_add_apple_subscription_to_players.rb— new migration to create. Issue correctly says "additive — do NOT alter existing Stripe columns or subscription_status enum." Schema confirms existing subscriptionstatus enum (active/past_due/canceled/none) is separate from proposed apple_subscription_status. A new PostgreSQL enum type will be created. Correct. - [x]
app/views/admin/players/show.html.erb— correctly identified as NOT existing. Issue correctly notes "requires #58 to create this view first." Verified: show.html.erb absent from app/views/admin/players/. - [x]
app/views/admin/players/index.html.erb— verified exists (112 lines). Issue says add Apple subscription badges alongside existing badges. Correct. - [x]
app/helpers/application_helper.rb— verified exists. Currently has subscription_badge_variant and subscription_badge_label for Stripe states. Issue says add badge helpers for Apple states alongside. Correct. - [x]
app/views/players/status.html.erb— correctly identified as new file to create. Verified: does not exist. Only index.html.erb exists in app/views/players/. - [x]
app/controllers/players_controller.rb— verified exists. Currently has only index action. Issue says add status action. Correct. - [x]
config/routes.rb— verified exists. Admin players has only [:index]. Player resources also only [:index]. Both need additions. Correct.
All 8 file targets verified accurate. No factual errors in file target descriptions.
Repo Placement
OK — issue filed on westside-basketball, all file targets are in westside-basketball. Single-repo scope is correct. "Files the agent should NOT touch" correctly excludes iOS repo and webhook infrastructure (#65).
Dependencies
- depends:65 (board item #1610) — App Store webhook infrastructure. Currently in next_up. Issue open. This ticket cannot start until #65 lands the Apple webhook handler that populates the new fields.
- depends:58 (board item #1609) — Admin player detail page. Currently in next_up. Issue open. The show.html.erb view does NOT exist on main. This ticket's AC #5 and #6 (show page subscription badge + pricing UI) cannot be implemented until #58 creates the page. Correctly documented in issue.
- Sibling: Board item #1635 (issue #78, iOS StoreKit purchase flow) also depends on #65 and is in backlog. Not a blocker, but implements the client-side subscription purchase that feeds data into the fields this ticket displays.
Both dependencies correctly labeled and documented in the issue body.
Acceptance Criteria
11 acceptance criteria. Assessment:
- AC 1-2 (model enum + fields): Verifiable via schema inspection and model test.
- AC 3-4 (migration additive + reversible): Verifiable via migration inspection and rollback test.
- AC 5-6 (admin detail page): Depends on #58. Agent-verifiable but blocked until #58 merges.
- AC 7 (admin list badges): Verifiable via view test.
- AC 8-9 (player-facing status page + no-subscription state): Verifiable via controller/view test.
- AC 10 (badge colors): Verifiable via helper test.
- AC 11 (Stripe test regression): Verifiable via
bundle exec rails test. 33 Stripe/webhook-related tests exist.
All criteria are agent-verifiable. Test command is real. No missing criteria identified — the previous v2 concern about data migration for existing enum values is no longer relevant since the migration is now additive (new enum type, not altering the existing one).
Blast Radius
- Existing subscription_status references (5 controllers, 2 views, 1 helper) are UNTOUCHED by this ticket. The new apple_subscription_status is a separate field and separate PostgreSQL enum type. No blast radius on existing Stripe integration.
- The onboardingstatus enum includes "stripe_connected" — NOT affected by this ticket since Stripe stays.
- Adding badges to index.html.erb (112 lines) is low-risk — additive HTML only.
- New player-facing status page is isolated — new route, new action, new view. No interaction with existing player index page.
Blast radius is well-contained by the additive design. Previous v2 blast radius concerns are resolved.
Decomposition Assessment
NEEDS DECOMPOSITION.
- 8 file targets in 1 repo — exceeds >3 threshold
- 11 acceptance criteria — exceeds >5 threshold
- Estimated agent work: over 5 minutes (migration, model changes, 2 view modifications, 1 new view, helper additions, controller addition, route additions, tests for all)
- Natural decomposition along the three-page architecture:
- AC 11 (Stripe regression) applies to all sub-tickets as a universal constraint.
The scope is factually clean and ready for decomposition. No factual corrections needed first (unlike v2).
Recommendation
[SCOPE]Create architecture note arch-app-store. Label arch:app-store is on the board item but no backing note exists in pal-e-docs.[DECOMPOSE]11 AC across 8 file targets, estimated over 5 minutes. Scope is now factually accurate and ready for decomposition. Route to skill-decompose-ticket with the four sub-ticket breakdown above.