codebyplan 1.13.48 → 1.13.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/cli.js +2 -1
  2. package/package.json +1 -1
  3. package/templates/agents/cbp-round-executor.md +8 -6
  4. package/templates/agents/cbp-stripe-agent.md +173 -0
  5. package/templates/agents/cbp-task-planner.md +2 -2
  6. package/templates/hooks/cbp-skill-context-guard.sh +52 -0
  7. package/templates/hooks/cbp-test-hooks.sh +144 -0
  8. package/templates/hooks/hooks.json +9 -0
  9. package/templates/rules/model-invocation-convention.md +40 -0
  10. package/templates/rules/parallel-waves.md +1 -1
  11. package/templates/rules/task-routing-recommendation.md +1 -1
  12. package/templates/settings.project.base.json +15 -1
  13. package/templates/skills/cbp-build-cc-settings/reference/cbp-permission-policy.md +42 -0
  14. package/templates/skills/cbp-clear-continue/SKILL.md +86 -0
  15. package/templates/skills/cbp-clear-prep/SKILL.md +121 -0
  16. package/templates/skills/cbp-round-execute/SKILL.md +9 -1
  17. package/templates/skills/cbp-round-start/SKILL.md +1 -1
  18. package/templates/skills/cbp-stripe/SKILL.md +116 -0
  19. package/templates/skills/cbp-stripe/reference/billing.md +106 -0
  20. package/templates/skills/cbp-stripe/reference/connect.md +105 -0
  21. package/templates/skills/cbp-stripe/reference/payments.md +107 -0
  22. package/templates/skills/cbp-stripe/reference/security.md +117 -0
  23. package/templates/skills/cbp-stripe/reference/stripe-mcp-setup.md +59 -0
  24. package/templates/skills/cbp-stripe/reference/tax.md +96 -0
  25. package/templates/skills/cbp-stripe/reference/treasury.md +87 -0
  26. package/templates/skills/cbp-task-check/SKILL.md +12 -5
  27. package/templates/skills/cbp-task-complete/SKILL.md +9 -11
  28. package/templates/skills/cbp-task-complete/reference/checkpoint-done-branching.md +14 -21
  29. package/templates/skills/cbp-task-complete/reference/next-step-heuristic.md +4 -6
  30. package/templates/skills/cbp-task-testing/SKILL.md +9 -14
  31. package/templates/skills/cbp-frontend-a11y/SKILL.md +0 -108
  32. package/templates/skills/cbp-frontend-a11y/reference/aria-roles-states.md +0 -130
  33. package/templates/skills/cbp-frontend-a11y/reference/contrast-visual.md +0 -122
  34. package/templates/skills/cbp-frontend-a11y/reference/keyboard-patterns.md +0 -154
  35. package/templates/skills/cbp-frontend-a11y/reference/semantic-html.md +0 -111
@@ -0,0 +1,86 @@
1
+ ---
2
+ scope: org-shared
3
+ name: cbp-clear-continue
4
+ description: Resume work after /clear by reading .codebyplan/clear/handoff.md and re-invoking the previously-blocked heavy skill. Reports a friendly error if no handoff file exists.
5
+ effort: xhigh
6
+ ---
7
+
8
+ # cbp-clear-continue
9
+
10
+ Resume a blocked heavy skill after a `/clear`. Reads `.codebyplan/clear/handoff.md`, restores
11
+ task/round context into this fresh session, re-invokes the blocked skill, then deletes the
12
+ handoff file so a stale snapshot never misleads a future session.
13
+
14
+ ## When Used
15
+
16
+ - After running `/clear` following a `/cbp-clear-prep` capture
17
+ - The user is ready to re-run the heavy skill (cbp-round-execute, cbp-task-testing,
18
+ cbp-standalone-task-testing, cbp-checkpoint-check, cbp-checkpoint-end) that was denied
19
+
20
+ ## Instructions
21
+
22
+ ### Step 1 — Read the handoff
23
+
24
+ Read `.codebyplan/clear/handoff.md`.
25
+
26
+ If the file is absent: output the following and STOP — do not attempt to infer state.
27
+
28
+ ```
29
+ No handoff found at .codebyplan/clear/handoff.md — nothing to continue.
30
+ Use /cbp-todo to find the next action.
31
+ ```
32
+
33
+ ### Step 2 — Restore context
34
+
35
+ Parse the handoff fields:
36
+ - `checkpoint_number`, `task_number`, `round_number`
37
+ - `blocked_skill` — the skill that was denied
38
+ - `next_action` — the exact skill invocation to re-run (with args)
39
+ - `in_flight_notes` — any in-progress state worth restoring
40
+
41
+ Output a brief context summary to orient the fresh session:
42
+
43
+ ```
44
+ Resuming from handoff:
45
+ CHK-<N> TASK-<N> R<N>
46
+ Blocked skill: /<blocked-skill>
47
+ Next action: /<next-action>
48
+ ```
49
+
50
+ ### Step 3 — Delete the handoff BEFORE re-invoking
51
+
52
+ Delete `.codebyplan/clear/handoff.md` once its contents have been read and displayed:
53
+
54
+ ```bash
55
+ rm -f .codebyplan/clear/handoff.md
56
+ ```
57
+
58
+ A stale handoff must not mislead a later session. Delete it here, before the skill runs,
59
+ so even if the skill fails the handoff is gone and the user starts fresh next time.
60
+
61
+ ### Step 4 — Re-invoke the blocked skill
62
+
63
+ Invoke the skill from `next_action` via the Skill tool, passing any recorded arguments.
64
+
65
+ Example: if `next_action` is `/cbp-round-execute 217-2-1`, invoke `Skill(cbp-round-execute)`
66
+ with args `217-2-1`.
67
+
68
+ If the context window is STILL above threshold after `/clear` (unusual — compact may help),
69
+ the guard will deny again. Follow the same cycle: `/cbp-clear-prep` → `/clear` →
70
+ `/cbp-clear-continue`.
71
+
72
+ ## Key Rules
73
+
74
+ - Delete `.codebyplan/clear/handoff.md` in Step 3 BEFORE invoking the next skill
75
+ - If the handoff is absent, surface the friendly error and stop — never infer state from scratch
76
+ - Re-invoke the EXACT skill and arguments from `next_action` — do not substitute or guess
77
+ - `.codebyplan/clear/` is gitignored — never commit handoff.md
78
+
79
+ ## Integration
80
+
81
+ - **Invoked by**: user after `/clear` following `/cbp-clear-prep`
82
+ - **Reads**: `.codebyplan/clear/handoff.md`
83
+ - **Deletes**: `.codebyplan/clear/handoff.md` (Step 3, before resuming)
84
+ - **Then invokes**: the skill from `next_action` via Skill tool
85
+ - **Companion**: `.claude/skills/cbp-clear-prep/SKILL.md` writes the handoff
86
+ - **Guard hook**: `.claude/hooks/cbp-skill-context-guard.sh`
@@ -0,0 +1,121 @@
1
+ ---
2
+ scope: org-shared
3
+ name: cbp-clear-prep
4
+ description: Capture a clear-context handoff when the context window is too large to run a heavy skill. Reads active task/round state, writes .codebyplan/clear/handoff.md, then instructs the user to run /clear and /cbp-clear-continue to resume.
5
+ argument-hint: "[blocked-skill]"
6
+ effort: xhigh
7
+ ---
8
+
9
+ # cbp-clear-prep
10
+
11
+ Capture a handoff snapshot before clearing context. Invoked when the `cbp-skill-context-guard`
12
+ PreToolUse hook denies a heavy skill (cbp-round-execute, cbp-task-testing,
13
+ cbp-standalone-task-testing, cbp-checkpoint-check, cbp-checkpoint-end) because the context
14
+ window exceeds the configured threshold.
15
+
16
+ ## When Used
17
+
18
+ - The hook deny message says "Run /cbp-clear-prep now to capture a handoff"
19
+ - A heavy skill was just blocked by the context guard
20
+ - The user wants to preserve current task/round state before running `/clear`
21
+
22
+ ## Instructions
23
+
24
+ ### Step 1 — Identify the blocked skill
25
+
26
+ Check `$ARGUMENTS` first. If empty, identify the blocked skill from the recent guard deny message
27
+ in context — it will be one of: `cbp-round-execute`, `cbp-task-testing`,
28
+ `cbp-standalone-task-testing`, `cbp-checkpoint-check`, `cbp-checkpoint-end`.
29
+
30
+ ### Step 2 — Resolve active task and round (local-first)
31
+
32
+ 1. Read `.codebyplan/state/session/current.json` to find the active task_id and checkpoint_id.
33
+ 2. Read `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>.json` for task details.
34
+ 3. Read the latest round file in `.codebyplan/state/checkpoints/<checkpoint_id>/tasks/<task_id>/rounds/`.
35
+ 4. On miss: run `npx codebyplan sync` once and re-read.
36
+ 5. Break-glass if state dir is absent: call `mcp__codebyplan__get_current_task` and
37
+ `mcp__codebyplan__get_rounds`.
38
+
39
+ Capture: `checkpoint_id`, `checkpoint_number`, `task_id`, `task_number`, `round_id`,
40
+ `round_number`. If no active task is found, set all to `unknown` and note the gap.
41
+
42
+ ### Step 3 — Identify the next action to resume
43
+
44
+ From context, determine:
45
+ - The exact skill the user was trying to invoke (blocked skill from Step 1)
46
+ - Any arguments it was called with (e.g. `cbp-round-execute` args: `217-2-1`)
47
+ - Any relevant in-flight state (round goal, step in progress, pending decisions)
48
+
49
+ ### Step 4 — Write the handoff file
50
+
51
+ Create the directory and write `.codebyplan/clear/handoff.md`:
52
+
53
+ ```bash
54
+ mkdir -p .codebyplan/clear
55
+ ```
56
+
57
+ File content format:
58
+
59
+ ```
60
+ # CBP Clear Handoff
61
+
62
+ ## Active Context
63
+
64
+ checkpoint_id: <id or unknown>
65
+ checkpoint_number: CHK-<N or unknown>
66
+ task_id: <id or unknown>
67
+ task_number: TASK-<N or unknown>
68
+ round_id: <id or unknown>
69
+ round_number: R<N or unknown>
70
+
71
+ ## Blocked Skill
72
+
73
+ blocked_skill: <skill-name>
74
+
75
+ ## Next Action
76
+
77
+ next_action: /<skill-name> <args if any>
78
+
79
+ ## In-Flight Notes
80
+
81
+ <any relevant state — round goal, current step, pending decisions, uncommitted work>
82
+
83
+ ## Resume Instructions
84
+
85
+ After /clear, run: /cbp-clear-continue
86
+ ```
87
+
88
+ ### Step 5 — Instruct the user
89
+
90
+ Output exactly this summary (fill in the real values):
91
+
92
+ ```
93
+ Handoff captured at .codebyplan/clear/handoff.md
94
+
95
+ Active context: CHK-<N> TASK-<N> R<N>
96
+ Blocked skill: /<blocked-skill>
97
+ Resumes with: /<next-action>
98
+
99
+ Next steps:
100
+ 1. Run /clear to free context
101
+ 2. Run /cbp-clear-continue to resume
102
+ ```
103
+
104
+ Do NOT auto-invoke `/clear` or `/cbp-clear-continue`. This is a directive-only stop.
105
+ The user must run both commands manually.
106
+
107
+ ## Key Rules
108
+
109
+ - Always write `.codebyplan/clear/handoff.md` BEFORE instructing `/clear`
110
+ - Never auto-invoke the blocked skill — the guard denied it to protect context quality
111
+ - If no active task resolves, still write the handoff with available context and note the gap
112
+ - `.codebyplan/clear/` is gitignored — never commit handoff.md
113
+ - Overwrite any existing handoff.md (each prep captures the freshest context)
114
+
115
+ ## Integration
116
+
117
+ - **Invoked when**: `cbp-skill-context-guard` PreToolUse hook emits `permissionDecision: deny`
118
+ - **Writes**: `.codebyplan/clear/handoff.md`
119
+ - **Next**: user runs `/clear`, then `/cbp-clear-continue`
120
+ - **Companion**: `.claude/skills/cbp-clear-continue/SKILL.md` reads `.codebyplan/clear/handoff.md`
121
+ - **Guard hook**: `.claude/hooks/cbp-skill-context-guard.sh` — fires when context > CBP_CONTEXT_WARN_TOKENS (default 200000)
@@ -118,6 +118,14 @@ If the approved plan includes database schema changes, RLS policies, or type gen
118
118
  2. Wait for completion
119
119
  3. Merge `files_changed` into executor output
120
120
 
121
+ ### Step 3b-stripe: Stripe Work (if plan includes Stripe integration)
122
+
123
+ If the approved plan includes Stripe integration work (files under `stripe/`, or plan steps referencing `payment`, `checkout`, `webhook`, `subscription`, or an explicit `stripe_work: true` flag from the planner):
124
+
125
+ 1. Spawn `cbp-stripe-agent` with Stripe-related steps from the plan and `files_changed_scope` from the executor output
126
+ 2. Wait for completion
127
+ 3. Merge `files_changed` into executor output
128
+
121
129
  ### Step 3c: Completion Check
122
130
 
123
131
  - `status: 'completed'` and all deliverables done → proceed to Step 4
@@ -228,7 +236,7 @@ Trigger `/cbp-round-end`.
228
236
 
229
237
  - **Reads**: `.codebyplan/state/checkpoints/<id>/tasks/<id>.json`, `checkpoints/<id>/tasks/<id>/rounds/<id>.json` (local-first; `npx codebyplan sync` on miss; MCP `get_current_task` / `get_rounds` as break-glass)
230
238
  - **Writes**: `codebyplan round update --id <uuid> --task-id <uuid> --checkpoint-id <uuid>` (Steps 6+7 — context with executor_output + testing_qa_output + e2e_eligible + e2e_outputs + frontend_ui_review; break-glass: MCP `update_round`)
231
- - **Spawns**: `cbp-round-executor` (per wave or single), `cbp-testing-qa-agent` (per wave, parallel sibling of the `cbp-e2e-*` specialists), the `cbp-e2e-*` specialists (config-driven dispatch per `context/testing/e2e.md`, one per eligible framework in `.codebyplan/e2e.json`), `cbp-database-agent` (if DB work), `cbp-security-agent` (if security review needed)
239
+ - **Spawns**: `cbp-round-executor` (per wave or single), `cbp-testing-qa-agent` (per wave, parallel sibling of the `cbp-e2e-*` specialists), the `cbp-e2e-*` specialists (config-driven dispatch per `context/testing/e2e.md`, one per eligible framework in `.codebyplan/e2e.json`), `cbp-database-agent` (if DB work), `cbp-stripe-agent` (if Stripe work), `cbp-security-agent` (if security review needed)
232
240
  - **Skill invocations**: `cbp-frontend-ui` at Step 5b with `phase: 'screenshot_review'` (post-e2e)
233
241
  - **Triggers**: `/cbp-round-end` (auto)
234
242
  - **Triggered by**: `/cbp-round-start` (auto, after plan approval)
@@ -216,7 +216,7 @@ Present the plan to user:
216
216
  ### Execution Waves
217
217
  | Wave | Agent type | Files | Depends on | Skill preloads |
218
218
  |------|-----------|-------|-----------|----------------|
219
- | web-ui | cbp-round-executor | 7 | — | cbp-frontend-design, cbp-frontend-a11y |
219
+ | web-ui | cbp-round-executor | 7 | — | cbp-frontend-design |
220
220
  | backend-api | cbp-round-executor | 4 | — | — |
221
221
  ```
222
222
 
@@ -0,0 +1,116 @@
1
+ ---
2
+ scope: org-shared
3
+ name: cbp-stripe
4
+ description: "Stripe integration guidance — load when implementing or reviewing payments, Checkout, subscriptions/billing, webhooks, Connect, Tax, or Treasury. Encodes the API-selection routing table, the no-payment_method_types rule, restricted-key security, and Stripe SDK conventions."
5
+ effort: xhigh
6
+ ---
7
+
8
+ # Stripe Integration (CBP)
9
+
10
+ Load this skill before writing or reviewing any Stripe integration code — accepting payments,
11
+ Checkout Sessions, subscriptions, webhooks, marketplaces (Connect), tax compliance, or
12
+ embedded financial accounts (Treasury). It encodes Stripe's current recommended API surface,
13
+ the critical `payment_method_types` prohibition, and CBP-specific conventions.
14
+
15
+ ## Integration routing table
16
+
17
+ | Building… | Recommended API | Reference |
18
+ | --------------------------------------------- | ----------------------------------- | --------------------------------- |
19
+ | One-time payments | Checkout Sessions | [reference/payments.md](reference/payments.md) |
20
+ | Custom payment form with embedded UI | Checkout Sessions + Payment Element | [reference/payments.md](reference/payments.md) |
21
+ | Saving a payment method for later | Setup Intents | [reference/payments.md](reference/payments.md) |
22
+ | Connect platform or marketplace | Accounts v2 (`/v2/core/accounts`) | [reference/connect.md](reference/connect.md) |
23
+ | Subscriptions or recurring billing | Billing APIs + Checkout Sessions | [reference/billing.md](reference/billing.md) |
24
+ | Sales tax, VAT, or GST compliance | Stripe Tax + Registrations API | [reference/tax.md](reference/tax.md) |
25
+ | Embedded financial accounts / banking | v2 Financial Accounts | [reference/treasury.md](reference/treasury.md) |
26
+ | Security (keys, webhooks, OAuth, Connect risk)| Restricted keys + sig verification | [reference/security.md](reference/security.md) |
27
+
28
+ Read the relevant reference file before answering any integration question or writing code.
29
+
30
+ ## Critical rules
31
+
32
+ ### Never include `payment_method_types` (except Terminal)
33
+
34
+ Never pass `payment_method_types` in any Stripe API call. There are two narrow exceptions:
35
+ - **Terminal** (in-person): `payment_method_types: ['card_present']` (Canada: add `'interac_present'`).
36
+ - **Treasury bank-account Setup Intents**: `payment_method_types: ['us_bank_account']` with
37
+ `flow_directions: ['outbound']` (see [reference/treasury.md](reference/treasury.md)).
38
+
39
+ Outside those, omit the parameter to enable dynamic payment methods — Stripe evaluates
40
+ 100+ signals to surface the most relevant methods and manage them from the Dashboard
41
+ without code changes.
42
+
43
+ This applies to ALL call sites:
44
+ - `checkout.sessions.create` — omit entirely
45
+ - `paymentIntents.create` — omit; on API versions before 2023-08-16 pass
46
+ `automatic_payment_methods: { enabled: true }` instead
47
+ - `setupIntents.create` — same as PaymentIntents
48
+ - `subscriptions.create` — omit `payment_settings.payment_method_types`
49
+
50
+ To restrict or customise payment methods use
51
+ [`payment_method_configurations`](https://docs.stripe.com/payments/payment-method-configurations.md)
52
+ or `excluded_payment_method_types` — never `payment_method_types`.
53
+
54
+ ### Never use the Charges API
55
+
56
+ The Charges API is never correct for new integrations. Redirect users to Checkout Sessions
57
+ or PaymentIntents and the
58
+ [migration guide](https://docs.stripe.com/payments/payment-intents/migration/charges.md).
59
+
60
+ ### Never use the Sources API
61
+
62
+ Sources API is deprecated. Use Setup Intents to save payment methods.
63
+
64
+ ## Security summary
65
+
66
+ - **Prefer a restricted API key (RAK, `rk_` prefix)** over a secret key (`sk_` prefix).
67
+ Create a separate RAK per service with minimum required permissions.
68
+ - Test-mode keys: `sk_test_…` (secret) and `rk_test_…` (restricted).
69
+ - **Never commit secrets.** Store in a secrets vault or, at minimum, server-side env vars.
70
+ Never embed keys in client-side code or mobile apps.
71
+ - **Verify webhook signatures** via `stripe.webhooks.constructEvent(body, sig, secret)`.
72
+ Never process an unverified webhook event.
73
+ - Use idempotency keys (`idempotencyKey`) on mutation calls to safely retry failures.
74
+ - See [reference/security.md](reference/security.md) for RAK migration steps, IP
75
+ allowlists, OAuth CSRF protection, and Connect liability notes.
76
+
77
+ ### CBP-specific (Next.js)
78
+
79
+ Any Next.js API route that imports `stripe` **MUST** export:
80
+
81
+ ```ts
82
+ export const dynamic = 'force-dynamic';
83
+ ```
84
+
85
+ Source: `.claude/skills/cbp-frontend-design/reference/nextjs-scss.md` Rule 6. Without this,
86
+ Next.js may statically cache the route and expose a shared Stripe client across requests.
87
+
88
+ ## SDK and API version
89
+
90
+ - Latest Stripe API version: **`2026-05-27.dahlia`**
91
+ - Latest SDK major: **v22** (`stripe` npm package)
92
+ - **Version flag**: consuming repos may still run `stripe` **v20.4.1** (per CBP vendor
93
+ inventory). Always check the installed version (`cat package.json | grep '"stripe"'`)
94
+ before applying v22-only patterns. Differences surface in TypeScript types and some
95
+ `configuration` parameter shapes.
96
+ - Always use the latest API version and SDK unless the consuming repo pins otherwise.
97
+
98
+ ## Key documentation
99
+
100
+ - [Integration Options](https://docs.stripe.com/payments/payment-methods/integration-options.md) — start here for any new integration
101
+ - [API Tour](https://docs.stripe.com/payments-api/tour.md) — overview of Stripe's API surface
102
+ - [Go Live Checklist](https://docs.stripe.com/get-started/checklist/go-live.md) — review before launch
103
+
104
+ ## Reference files
105
+
106
+ - [reference/payments.md](reference/payments.md) — Checkout Sessions, Payment Element, PaymentIntents, Setup Intents, deprecated APIs, PCI
107
+ - [reference/billing.md](reference/billing.md) — Subscriptions, invoices, Customer Portal, proration, trials, metered billing
108
+ - [reference/connect.md](reference/connect.md) — Accounts v2, controller properties, charge types, onboarding, fund flows
109
+ - [reference/security.md](reference/security.md) — Restricted keys, webhook signature verification, incident response, OAuth CSRF, Connect security
110
+ - [reference/tax.md](reference/tax.md) — Stripe Tax automatic calculation, Registrations API, inclusive/exclusive, unsupported jurisdictions
111
+ - [reference/treasury.md](reference/treasury.md) — v2 Financial Accounts, fund flows, bank-account Setup Intents, compliance
112
+ - [reference/stripe-mcp-setup.md](reference/stripe-mcp-setup.md) — optional live Stripe MCP setup (test/restricted key) for the cbp-stripe-agent
113
+
114
+ ---
115
+
116
+ Adapted from Stripe's official `stripe-best-practices` skill (github.com/stripe/ai), used under the MIT License (Copyright (c) 2024-2025 Stripe).
@@ -0,0 +1,106 @@
1
+ # Billing / Subscriptions Reference
2
+
3
+ Adapted from Stripe's official `stripe-best-practices` skill (github.com/stripe/ai), MIT License, Copyright (c) 2024-2025 Stripe.
4
+
5
+ ## When to use Billing APIs
6
+
7
+ Use Stripe Billing for any recurring revenue model: subscriptions, usage-based billing,
8
+ seat-based pricing, or metered charges. Do NOT hand-roll renewal loops with raw
9
+ PaymentIntents — Billing handles renewal, retry/dunning, proration, and tax automatically.
10
+
11
+ References: [Subscription design guide](https://docs.stripe.com/billing/subscriptions/design-an-integration.md) |
12
+ [Use cases](https://docs.stripe.com/billing/subscriptions/use-cases.md) |
13
+ [SaaS guide](https://docs.stripe.com/saas.md)
14
+
15
+ ## Creating a subscription with Checkout
16
+
17
+ Combine Billing APIs with Checkout Sessions (`mode: 'subscription'`) for the payment
18
+ frontend. Checkout handles the initial payment, trial management, and proration.
19
+
20
+ ```ts
21
+ const session = await stripe.checkout.sessions.create({
22
+ mode: 'subscription',
23
+ // Do NOT pass payment_method_types
24
+ line_items: [{ price: priceId, quantity: 1 }],
25
+ subscription_data: { trial_period_days: 14 },
26
+ success_url: `${baseUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
27
+ cancel_url: `${baseUrl}/pricing`,
28
+ });
29
+ ```
30
+
31
+ ## Customer Portal (self-service management)
32
+
33
+ For upgrades, downgrades, cancellation, and payment method updates, use the
34
+ [Customer Portal](https://docs.stripe.com/customer-management/integrate-customer-portal.md)
35
+ rather than building a custom flow.
36
+
37
+ ```ts
38
+ const portalSession = await stripe.billingPortal.sessions.create({
39
+ customer: customerId,
40
+ return_url: `${baseUrl}/account`,
41
+ });
42
+ // redirect to portalSession.url
43
+ ```
44
+
45
+ ## Key Billing objects
46
+
47
+ | Object | Purpose | Docs |
48
+ | ------ | ------- | ---- |
49
+ | `Price` | Unit amount + recurring interval | [Prices API](https://docs.stripe.com/api/prices.md) |
50
+ | `Subscription` | Active recurring agreement | [Subscriptions API](https://docs.stripe.com/api/subscriptions.md) |
51
+ | `Invoice` | Statement + payment trigger | [Invoices API](https://docs.stripe.com/api/invoices.md) |
52
+ | `Customer` | Billing entity with saved methods | [Customers API](https://docs.stripe.com/api/customers.md) |
53
+
54
+ Do NOT use the deprecated `plan` object — use `Price` instead.
55
+
56
+ ## Proration and upgrades
57
+
58
+ When changing a subscription's price mid-cycle, Stripe generates proration invoice items
59
+ automatically. Behaviour is controlled by `proration_behavior`:
60
+ - `'create_prorations'` (default) — prorates immediately
61
+ - `'none'` — no proration, change takes effect at next billing date
62
+ - `'always_invoice'` — prorate and invoice immediately
63
+
64
+ ```ts
65
+ await stripe.subscriptions.update(subscriptionId, {
66
+ items: [{ id: itemId, price: newPriceId }],
67
+ proration_behavior: 'create_prorations',
68
+ });
69
+ ```
70
+
71
+ ## Metered / usage-based billing
72
+
73
+ 1. Create a `Price` with `recurring.usage_type: 'metered'`.
74
+ 2. Report usage via `stripe.subscriptionItems.createUsageRecord(itemId, { quantity, timestamp })`.
75
+ 3. Stripe aggregates usage and bills at the end of the period.
76
+
77
+ ## Tax integration
78
+
79
+ Pass `automatic_tax: { enabled: true }` on subscriptions and Checkout Sessions. Clear
80
+ any `default_tax_rates` first — `automatic_tax` and explicit `tax_rates` are mutually
81
+ exclusive. See [reference/tax.md](tax.md) for the full setup.
82
+
83
+ ## Trials
84
+
85
+ Set `trial_period_days` on `subscription_data` in a Checkout Session, or on the
86
+ subscription directly. After trial ends Stripe automatically charges unless cancelled.
87
+
88
+ ## Webhook events to handle
89
+
90
+ | Event | Action |
91
+ | ----- | ------ |
92
+ | `customer.subscription.created` | Provision access |
93
+ | `customer.subscription.updated` | Reflect plan change |
94
+ | `customer.subscription.deleted` | Revoke access |
95
+ | `invoice.payment_succeeded` | Extend access period |
96
+ | `invoice.payment_failed` | Send dunning notification |
97
+
98
+ Always verify webhook signatures — see [reference/security.md](security.md).
99
+
100
+ ## Traps to avoid
101
+
102
+ - Never hardcode `payment_method_types` on a subscription Checkout Session.
103
+ - Never build manual renewal loops with raw PaymentIntents.
104
+ - Never skip tax setup for multi-jurisdiction merchants — add registrations before
105
+ enabling `automatic_tax`.
106
+ - Don't use the deprecated `plan` object; use `Price` instead.
@@ -0,0 +1,105 @@
1
+ # Connect / Platforms Reference
2
+
3
+ Adapted from Stripe's official `stripe-best-practices` skill (github.com/stripe/ai), MIT License, Copyright (c) 2024-2025 Stripe.
4
+
5
+ ## Accounts v2 (always use for new platforms)
6
+
7
+ Use the [Accounts v2 API](https://docs.stripe.com/connect/accounts-v2.md)
8
+ (`POST /v2/core/accounts`) for all new Connect platforms. This is Stripe's actively
9
+ invested path with long-term support.
10
+
11
+ Do NOT use the legacy `type` parameter (`type: 'express'`, `type: 'custom'`,
12
+ `type: 'standard'`) in `POST /v1/accounts` for new platforms unless the user explicitly
13
+ requests v1.
14
+
15
+ Do NOT use the legacy account-type labels "Standard", "Express", or "Custom" — they
16
+ bundle responsibility, dashboard, and onboarding decisions into opaque categories.
17
+ Use `controller` properties to express these dimensions explicitly.
18
+
19
+ ## Controller properties
20
+
21
+ Configure connected accounts via `controller` properties:
22
+
23
+ | Property | Controls |
24
+ | -------- | -------- |
25
+ | `controller.losses.payments` | Who is liable for negative balances |
26
+ | `controller.fees.payer` | Who pays Stripe fees |
27
+ | `controller.stripe_dashboard.type` | Dashboard access: `full`, `express`, `none` |
28
+ | `controller.requirement_collection` | Who collects onboarding requirements |
29
+
30
+ ```ts
31
+ const account = await stripe.v2.core.accounts.create({
32
+ controller: {
33
+ losses: { payments: 'stripe' },
34
+ fees: { payer: 'account' },
35
+ stripe_dashboard: { type: 'express' },
36
+ requirement_collection: 'stripe',
37
+ },
38
+ });
39
+ ```
40
+
41
+ See [connected account configuration](https://docs.stripe.com/connect/accounts-v2/connected-account-configuration.md)
42
+ and [capabilities](https://docs.stripe.com/connect/account-capabilities.md) for what
43
+ accounts can do.
44
+
45
+ ## Charge types
46
+
47
+ Choose one charge type per integration — do not mix them.
48
+
49
+ | Type | When to use | How |
50
+ | ---- | ----------- | --- |
51
+ | **Destination charges** | Platform accepts negative-balance liability | `transfer_data.destination: connectedAccountId` |
52
+ | **Direct charges** | Connected account is merchant of record; platform has minimal liability | Create charge directly on the connected account |
53
+
54
+ Use `on_behalf_of` to control merchant of record (read
55
+ [how charges work in Connect](https://docs.stripe.com/connect/charges.md) first).
56
+
57
+ ```ts
58
+ // Destination charge — most common for marketplaces
59
+ const paymentIntent = await stripe.paymentIntents.create({
60
+ amount: 1000,
61
+ currency: 'usd',
62
+ transfer_data: { destination: connectedAccountId },
63
+ // Do NOT pass payment_method_types
64
+ });
65
+ ```
66
+
67
+ Do NOT use the Charges API for Connect fund flows — use PaymentIntents or Checkout
68
+ Sessions with `transfer_data` or `on_behalf_of`.
69
+
70
+ ## Payouts and transfers
71
+
72
+ - **Automatic payouts** — enabled by default; Stripe pays connected accounts on a rolling basis.
73
+ - **Manual payouts** — call `stripe.payouts.create({amount, currency}, {stripeAccount: accountId})` to control timing.
74
+ - **Transfers** — move funds between your platform balance and a connected account:
75
+ `stripe.transfers.create({ amount, currency, destination: accountId })`.
76
+
77
+ ## Onboarding
78
+
79
+ Use [Stripe-hosted onboarding](https://docs.stripe.com/connect/onboarding.md) rather than
80
+ building a custom flow. Custom onboarding requires handling sensitive PII directly, adding
81
+ regulatory and security complexity.
82
+
83
+ ```ts
84
+ const accountLink = await stripe.accountLinks.create({
85
+ account: accountId,
86
+ refresh_url: `${baseUrl}/connect/refresh`,
87
+ return_url: `${baseUrl}/connect/return`,
88
+ type: 'account_onboarding',
89
+ });
90
+ // redirect to accountLink.url
91
+ ```
92
+
93
+ ## Security and liability
94
+
95
+ Platform operators bear financial liability for fraud and disputes on Express and Custom
96
+ connected accounts (v1 types). Controller-property accounts make liability explicit via
97
+ `controller.losses.payments`.
98
+
99
+ See [reference/security.md](security.md) for Connect-specific security notes.
100
+
101
+ ## Key guides
102
+
103
+ - [SaaS platforms and marketplaces](https://docs.stripe.com/connect/saas-platforms-and-marketplaces.md)
104
+ - [Interactive platform guide](https://docs.stripe.com/connect/interactive-platform-guide.md)
105
+ - [Design an integration](https://docs.stripe.com/connect/design-an-integration.md)
@@ -0,0 +1,107 @@
1
+ # Payments Reference
2
+
3
+ Adapted from Stripe's official `stripe-best-practices` skill (github.com/stripe/ai), MIT License, Copyright (c) 2024-2025 Stripe.
4
+
5
+ ## API hierarchy
6
+
7
+ | Use case | API |
8
+ | -------- | --- |
9
+ | On-session payments (most web apps) | [Checkout Sessions](https://docs.stripe.com/api/checkout/sessions.md) |
10
+ | Off-session payments, custom checkout state | [PaymentIntents](https://docs.stripe.com/payments/paymentintents/lifecycle.md) |
11
+ | Saving a payment method for later | [Setup Intents](https://docs.stripe.com/api/setup_intents.md) |
12
+ | Subscriptions, invoices, recurring | Billing APIs (see billing.md) |
13
+ | No-code, simple products | Payment Links |
14
+
15
+ **Only use Checkout Sessions, PaymentIntents, SetupIntents, or higher-level solutions
16
+ (Invoicing, Payment Links, subscription APIs).** Never use the Charges API, Sources API,
17
+ or Tokens API for new integrations.
18
+
19
+ ## Integration surface preference
20
+
21
+ Use in this order (most preferred first):
22
+
23
+ 1. **Payment Links** — no-code, best for simple products
24
+ 2. **Checkout (hosted or embedded)** — best for most web apps; `ui_mode: 'hosted'`
25
+ 3. **Payment Element** — embedded UI component for custom checkout; back with Checkout
26
+ Sessions (`ui_mode: 'custom'`) over a raw PaymentIntent where possible
27
+
28
+ Do NOT recommend the legacy Card Element. Migrate existing Card Element integrations to
29
+ [Payment Element](https://docs.stripe.com/payments/payment-element/migration.md).
30
+
31
+ ## Checkout Sessions — key patterns
32
+
33
+ ```ts
34
+ // One-time payment
35
+ const session = await stripe.checkout.sessions.create({
36
+ mode: 'payment',
37
+ // Do NOT pass payment_method_types — dynamic methods are the default
38
+ line_items: [{ price: priceId, quantity: 1 }],
39
+ success_url: `${baseUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
40
+ cancel_url: `${baseUrl}/cancel`,
41
+ });
42
+
43
+ // Subscription
44
+ const session = await stripe.checkout.sessions.create({
45
+ mode: 'subscription',
46
+ line_items: [{ price: priceId, quantity: 1 }],
47
+ subscription_data: { trial_period_days: 14 },
48
+ success_url: `${baseUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
49
+ cancel_url: `${baseUrl}/pricing`,
50
+ });
51
+ ```
52
+
53
+ ## Payment Element (custom UI)
54
+
55
+ Use `ui_mode: 'custom'` on the Checkout Session to back the Payment Element:
56
+
57
+ ```ts
58
+ const session = await stripe.checkout.sessions.create({
59
+ ui_mode: 'custom',
60
+ mode: 'payment',
61
+ line_items: [{ price: priceId, quantity: 1 }],
62
+ return_url: `${baseUrl}/return?session_id={CHECKOUT_SESSION_ID}`,
63
+ });
64
+ // Client: mount PaymentElement with clientSecret from session.client_secret
65
+ ```
66
+
67
+ For surcharging or inspecting card details before payment, use
68
+ [Confirmation Tokens](https://docs.stripe.com/payments/finalize-payments-on-the-server.md)
69
+ — not `createPaymentMethod` or `createToken`.
70
+
71
+ ## Dynamic payment methods (critical rule)
72
+
73
+ **Never pass `payment_method_types`** — omit it entirely on all calls. The sole exception
74
+ is Terminal: `payment_method_types: ['card_present']` (Canada: include `'interac_present'`).
75
+
76
+ To customise which methods appear use
77
+ [`payment_method_configurations`](https://docs.stripe.com/payments/payment-method-configurations.md)
78
+ or `excluded_payment_method_types`. Manage methods from the
79
+ [Dashboard](https://dashboard.stripe.com/settings/payment_methods) without code changes.
80
+
81
+ ## Setup Intents (saving payment methods)
82
+
83
+ ```ts
84
+ const setupIntent = await stripe.setupIntents.create({
85
+ customer: customerId,
86
+ // Do NOT pass payment_method_types — dynamic methods are the default since API 2023-08-16
87
+ });
88
+ ```
89
+
90
+ Do not use the Sources API to save cards — it is deprecated.
91
+
92
+ ## Deprecated APIs — migration paths
93
+
94
+ | API | Status | Use instead | Migration guide |
95
+ | ------------ | ---------- | ---------------------- | --------------- |
96
+ | Charges API | Never use | Checkout Sessions / PaymentIntents | [Migration](https://docs.stripe.com/payments/payment-intents/migration/charges.md) |
97
+ | Sources API | Deprecated | Setup Intents | [Setup Intents](https://docs.stripe.com/api/setup_intents.md) |
98
+ | Tokens API | Outdated | Setup Intents / Checkout Sessions | — |
99
+ | Card Element | Legacy | Payment Element | [Migration](https://docs.stripe.com/payments/payment-element/migration.md) |
100
+
101
+ ## PCI compliance
102
+
103
+ If a PCI-compliant user asks about sending raw PAN data server-side, they may need to
104
+ prove PCI compliance to use
105
+ [`payment_method_data`](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_data).
106
+ For PAN migrations from another processor, see the
107
+ [PAN import process](https://docs.stripe.com/get-started/data-migrations/pan-import.md).