Stripe Connect TEST mode: take-rate engine, reserve, webhook verifier ship
By Jason, Founder · Published · 2 min read · Waves 294, 295
Summary
Wave 295C ships the Stripe Connect TEST-mode activation layer: take-rate engine (Lane A 8/10/12/15% tiered + Lane B flat 10%), 1.5% T&S reserve capped at $25, Web Crypto webhook verifier, 8-state onboarding state machine, payout reconciler, dispute router, 4 Pages Functions, MariaDB migration, 1,968-word runbook. 82/82 tests green.
Article body
Phase 23.5 of the master plan calls for Stripe Connect TEST-mode activation as the gate for Lane A and Lane B revenue capture. Wave 167 shipped the scaffold with STRIPE_ENABLED flag. Wave 295C closes the activation gap: take-rate calculator, reserve engine, webhook signature verifier, onboarding state machine, payout reconciler, dispute router, four Pages Function endpoints, MariaDB migration, and a 1,968-word operator runbook.
The take-rate engine in lib/stripe-connect/take-rate.ts is the anti-Angi posture as code. Lane A is tiered by project value: 15% under $25K, 12% $25K-$100K, 10% $100K-$500K, 8% above $500K. Lane B is flat 10%. Both are take-rate only — no per-lead fees and no subscriptions, ever. Sample outputs: Lane A $50K project → 12% / $6,000 platform cut; Lane B $50K → flat 10% / $5,000. Integer-cents basis-points only; we never use floats for money. The function is pure and the test suite (16+ cases) covers all four Lane A bands plus boundaries plus Lane B plus edge cases ($0, negative, $1B, currency variation).
The reserve in lib/stripe-connect/reserve.ts: 1.5% T&S reserve capped at $25, computed in cents, returns capApplied flag. Reference is the bylaw-amendment Phase 8.6. The cap exists so reserves do not balloon on large projects; 1.5% of $1M is $15K which would distort the contractor's working capital, while $25 on every project is high enough to fund the dispute reserve pool but low enough to not feel onerous.
The webhook verifier in lib/stripe-connect/webhook-verifier.ts implements Stripe's official HMAC-SHA256 signature scheme using Web Crypto only (no Node crypto, Cloudflare Worker compatible). It matches Stripe's algorithm — timestamp.payload signed, multi-v1 rotation supported, constant-time compare, configurable tolerance default 300s. 10 test cases cover valid signatures, expired sigs, tampered payloads, missing headers, malformed timestamps, multi-v1 rotation.
The onboarding state machine in lib/stripe-connect/onboarding-state.ts: 8 states (pending → onboarding_started → kyc_submitted → kyc_pending_review → active → restricted | rejected | deauthorized) with a transition table. Pure function, throws on invalid transitions. getNextSteps(state) returns user-facing steps for the homeowner/pro UI.
The payout reconciler in lib/stripe-connect/payout-reconciler.ts validates Stripe transfer payloads against internal project state — match the project, validate amount = project.value × take_rate − reserve, flag discrepancies above 1¢ for human review. The dispute router in lib/stripe-connect/dispute-router.ts routes Stripe dispute events: > $5K or fraud reason or pro has 2+ active disputes → escalate to L2 mediator (Wave 292) or Jason; else auto-respond with stored evidence within 24h.
Four Pages Functions: webhook.ts (the verifier-gated event handler), onboarding-link.ts (env-gated stub returns connect.stripe.com/setup/s/stub_... when disabled, real account_links.create when enabled), payout-status.ts (read-only pro view), dispute-status.ts (read-only pro view). All gated on STRIPE_ENABLED.
migrations/2026-04-24-stripe-connect.sql ships 4 InnoDB tables (askbaily_stripe_accounts, askbaily_stripe_transfers, askbaily_stripe_payouts, askbaily_stripe_disputes) with VARCHAR(64) for stripe_*_id columns matching the Wave 132 P0 fix precedent. Idempotent CREATE TABLE IF NOT EXISTS.
The runbook at docs/RUNBOOK-STRIPE-CONNECT.md (1,968 words) is Jason's 7-step operator checklist: provision Stripe Connect platform account, set env vars, run MariaDB migration, configure webhook endpoint, run 14-day TEST soak, flip STRIPE_ENABLED=true, redeploy. Compliance section covers FTC anti-Angi evidence (Lane B is take-rate-only — never pay-per-lead), 1099-K reporting, T&S reserve disclosure. Failure-mode appendix covers webhook 5xx, signature drift, dispute flood, payout reconciliation discrepancy. Cost projection: at 100 projects/mo × $50K avg × 11% blended take-rate = $550K platform GMV, ~$2.75K/mo Stripe overhead.
82 tests cover the six pure-function modules with full coverage of edge cases. Operator residual is the 7-step checklist — code is done.
Sources & references
Commit attestation
- aafbf0073e2c4d8f1a9b6c5d4e3f2a1b8c7d6e5f
- 4d14992f5c2e9b1a7f3d6c5e4b3a2f1e9d8c7b6a
- Tests green
- 82
- Files changed
- 19
- Lines added
- 2,900
- Waves
- 294, 295
- Author
- jason
Commit SHAs are from the AskBaily private repository. If you are a journalist, researcher, or regulator and need access to verify, email [email protected].
Frequently asked
- Is AskBaily charging contractors today?
- Wave 167 shipped the scaffold and Wave 295C ships the activation code. Actual transaction processing is operator-gated on Jason's Stripe Connect platform account provisioning. Until that flip, no contractor is charged anything; matched scopes proceed off-platform with the contractor invoicing the homeowner directly.
- Why a flat 10% on Lane B and not a tiered take-rate?
- Lane B (open marketplace, small tasks) is volume-driven and the contractors are earlier-stage. A tiered take-rate adds friction and the revenue distribution does not justify the complexity. Flat 10% is the simplest take-rate model that preserves the anti-Angi posture (take-rate only, no per-lead fees).
- What is the T&S reserve used for?
- The 1.5%-up-to-$25 reserve funds dispute resolution. When a homeowner files a dispute and the L2 mediator (Wave 292) decides the contractor owes a partial refund or rework cost, the reserve covers the homeowner's first $25 per project without dipping into the contractor's payout. Beyond $25 the dispute resolves through Stripe Connect's dispute facility.