Review: Withdrawal Flow — Pool to Bank via Stripe Connect

review-850-2026-04-05 Doc

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — "V2 ticket. Depends on schema ticket. Part of #66."
  • [x] Repo — forgejo_admin/twitch-2k-wager
  • [x] User Story — player with winnings withdrawing to bank
  • [x] Context — explains current vs v2 approach
  • [x] File Targets — 1 new file specified
  • [x] Acceptance Criteria — 5 criteria
  • [x] Test Expectations — 3 test cases
  • [x] Constraints — dependencies and limits noted
  • [x] Checklist — standard PR checklist
  • [x] Related — parent vision #66, schema dependency

Traceability

  • [x] story:player-withdraw label — verified on board item #850
  • [x] story note verified — "player-withdraw" entry found in project-twitch-2k-wager user-stories table: "Withdraw pool balance to bank via Stripe payout anytime."
  • [x] arch:dataflow-twitch-2k-wager label — present on board item
  • [ ] arch note MISSING — [SCOPE] No note matching "arch-dataflow-twitch-2k-wager" or "dataflow-twitch-2k-wager" found in pal-e-docs. Create architecture note arch-dataflow-twitch-2k-wager for the data flow component.
  • [x] Forgejo issue — https://forgejo.tail5b443a.ts.net/forgejo_admin/twitch-2k-wager/issues/72, state: open

File Targets

  • [x] src/routes/api/withdraw/+server.ts — marked NEW. Confirmed directory does not exist in repo yet (correct). Parent path src/routes/api/ exists with sibling routes (checkout, admin, webhooks). SvelteKit route convention is valid.
  • [x] Dashboard withdraw button — correctly deferred to separate ticket (good decomposition).
Targets are specific enough for an agent to act on without guessing.

Repo Placement

OK. Issue filed on forgejo_admin/twitch-2k-wager, file target is in same repo. Single-repo change. No cross-repo concerns.

Dependencies

  • [ ] Schema ticket #67 — PENDING (backlog). The current schema has no pool/balance tables (player_pool, balance, locked columns). The withdrawal endpoint needs these v2 schema objects. Board item #845 is in backlog column — not yet reviewed or in progress. This is a hard blocker.
  • [x] Parent vision #66 — open, serves as tracking issue. Not a blocker.

Acceptance Criteria

  • [x] "Player can request withdrawal of any amount up to available balance" — testable via API call + DB assertion
  • [x] "Locked funds cannot be withdrawn" — testable with locked balance fixture
  • [x] "Stripe payout initiated successfully" — testable with Stripe mock
  • [x] "Pool balance reduced by withdrawal amount" — testable via DB assertion
  • [x] "Insufficient balance returns 400" — testable via API call
  • Missing: No auth guard criterion — unauthenticated requests should return 401. All other API routes in this repo enforce auth.
  • Missing: No mention of withdrawal record tracking — should the system maintain an audit trail of withdrawals? The v2 schema (#67) may need a withdrawals table.

Blast Radius

  • Files touched: 1 new file. Low blast radius.
  • Stripe mechanism ambiguity: Ticket title says "Stripe Connect" but the project page architecture says "Stripe payout from balance." Current codebase (src/lib/stripe.ts) uses Connect Express transfers via createTransfer() which requires a connected account per recipient. Issue #54 (done) already replaced the original Connect flow with "refund + payout portal." The v2 withdrawal flow needs to specify which Stripe API: Connect transfer (existing pattern, requires per-recipient onboarding) vs. standard Stripe payout (different API, different requirements). This ambiguity would cause an agent to guess.
  • Rollback: Straightforward — single new file, no schema migration in this ticket.

Decomposition Assessment

Apply three-thing limit and five-minute rule:
  • 1 new file — under the 3-file limit
  • 5 AC — at the boundary but all within a single endpoint
  • Single repo, single route — estimated agent time well under 5 minutes
  • No independent subtasks that could be parallelized
No decomposition needed.

Recommendation

  • [BODY] Replace "Depends on schema ticket" with "Depends on #67 (v2 schema)" in Lineage section. Add #67 explicitly to Related section.
  • [BODY] Clarify Stripe mechanism in Context section: specify whether withdrawal uses Connect Express transfer (existing createTransfer() pattern, requires connected account onboarding) or a different Stripe payout method. Resolve contradiction between title ("Stripe Connect") and project vision ("standard Stripe payouts").
  • [BODY] Add AC: "Unauthenticated request returns 401."
  • [BODY] Add AC or Constraint: specify whether a withdrawals table is needed for audit trail, or confirm this is handled by the schema ticket #67.
  • [SCOPE] Create architecture note arch-dataflow-twitch-2k-wager for the data flow component. This note is referenced by 5 board items on board-twitch-2k-wager (items #846, #847, #849, #850, and others).