Review: Withdrawal Flow — Pool to Bank via Stripe Connect
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 pathsrc/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,lockedcolumns). 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 viacreateTransfer()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
#67explicitly 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
withdrawalstable is needed for audit trail, or confirm this is handled by the schema ticket #67. - [SCOPE] Create architecture note
arch-dataflow-twitch-2k-wagerfor the data flow component. This note is referenced by 5 board items on board-twitch-2k-wager (items #846, #847, #849, #850, and others).