fix(cloud): persist Stripe Connect capability booleans so fiat payouts aren't permanently rejected (#11172) - #11190
Conversation
…s aren't permanently rejected (#11172) The Connect webhook derived `status` from the account.updated capability booleans but DROPPED the booleans themselves. `payouts_enabled` defaults false (migration 0150) and the payout transfer gate reads it directly (transfer/route.ts: `if (account.status !== "active" || !account.payouts_enabled)`), so after a creator fully onboards (Stripe sends charges_enabled=true, payouts_enabled=true) we stored status='active' but left payouts_enabled=false forever → every Stripe Connect fiat payout permanently rejected, no recovery path. Launch-blocking for the fiat payout rail. Fix (option a — keep the column truthful): mapConnectWebhookEvent now returns the raw chargesEnabled/payoutsEnabled from account.updated, and the webhook route persists them alongside status via updateByAccountId (which already accepts the columns). The column now reflects reality — true when Stripe reports the caps, false when it doesn't. Tests: - stripe-connect-payout.test.ts: mapper surfaces the booleans (both true → also active; charges true / payouts false → surfaced truthfully). - stripe-connect-webhook-route.test.ts: the account.updated persist now asserts { status: "active", charges_enabled: true, payouts_enabled: true } — the regression guard (was { status: "active" } alone, which left the column false). Money-path — flagging for maintainer review/merge. [cloud-security]
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…2400s install timeout (#10839) Prod deploys run from main (production environment allows only the main branch), but main cloud-cf-deploy still had the install-hang config: bun canary + install cache under $PWD (box /tmp, slow FS) + 900s per-attempt cap. Every money-integrity-wave prod deploy hung on bun install. Ports the three fixes already merged to develop (#11235/#11268/#11304): pin bun to latest, put the install cache on local $HOME (persistent/warm), and raise the per-attempt timeout to 2400s so the slow-but-completing install finishes. With this on main, a main-push deploy installs, then migrate-db runs (branch=main satisfies the production environment policy) pending the required-reviewer approval, then Worker/Pages deploy. Ships the merged money fixes (#11190 payout gate, #11189 cron, escrow, #11163 launch gate) to prod.
…2400s install timeout (#10839) (#11314) Prod deploys run from main (production environment allows only the main branch), but main cloud-cf-deploy still had the install-hang config: bun canary + install cache under $PWD (box /tmp, slow FS) + 900s per-attempt cap. Every money-integrity-wave prod deploy hung on bun install. Ports the three fixes already merged to develop (#11235/#11268/#11304): pin bun to latest, put the install cache on local $HOME (persistent/warm), and raise the per-attempt timeout to 2400s so the slow-but-completing install finishes. With this on main, a main-push deploy installs, then migrate-db runs (branch=main satisfies the production environment policy) pending the required-reviewer approval, then Worker/Pages deploy. Ships the merged money fixes (#11190 payout gate, #11189 cron, escrow, #11163 launch gate) to prod.
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
Closes #11172.
Problem (HIGH — launch-blocking for the fiat payout rail)
The Connect
account.updatedwebhook derivedstatusfrom the capability booleans but dropped the booleans.payouts_enableddefaults false (migration 0150) and the payout transfer gate reads it directly:So a creator fully onboards → Stripe fires
account.updated(charges_enabled=true, payouts_enabled=true) → we storedstatus='active'but leftpayouts_enabled=falseforever → every Stripe Connect fiat payout permanently rejected, with no recovery path. (On-chain hot-wallet payouts are unaffected — this is the Stripe fiat rail specifically.)Fix (option a — keep the column truthful)
mapConnectWebhookEventnow returns the rawchargesEnabled/payoutsEnabledfromaccount.updated, and the webhook route persists them alongsidestatusviaupdateByAccountId(which already acceptscharges_enabled?/payouts_enabled?). The column reflects reality: true when Stripe reports the caps, false when it doesn't.Chose (a) over (b) (dropping the redundant gate check) so the persisted column stays accurate for any other reader, not just the transfer gate.
Tests
stripe-connect-payout.test.ts: mapper surfaces the booleans (both true → alsoactive; charges-true/payouts-false → surfaced truthfully).stripe-connect-webhook-route.test.ts: theaccount.updatedpersist now asserts{ status: "active", charges_enabled: true, payouts_enabled: true }— the regression guard (previously{ status: "active" }alone, which is exactly the bug).packages/cloud/shared typecheck+packages/cloud/api build+ biome all clean.Evidence
Money-path — flagging for maintainer review/merge rather than self-merge.
[cloud-security]