@nebulr-group/bridge-cli 0.1.3 → 0.4.0-beta.0

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 (50) hide show
  1. package/README.md +26 -4
  2. package/dist/auth/loopback.d.ts.map +1 -1
  3. package/dist/auth/loopback.js +8 -0
  4. package/dist/auth/loopback.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +4 -0
  7. package/dist/cli.js.map +1 -1
  8. package/dist/commands/app.command.d.ts.map +1 -1
  9. package/dist/commands/app.command.js +2 -0
  10. package/dist/commands/app.command.js.map +1 -1
  11. package/dist/commands/auth/login.command.d.ts +12 -0
  12. package/dist/commands/auth/login.command.d.ts.map +1 -1
  13. package/dist/commands/auth/login.command.js +2 -1
  14. package/dist/commands/auth/login.command.js.map +1 -1
  15. package/dist/commands/flag-init.command.d.ts +13 -0
  16. package/dist/commands/flag-init.command.d.ts.map +1 -0
  17. package/dist/commands/flag-init.command.js +353 -0
  18. package/dist/commands/flag-init.command.js.map +1 -0
  19. package/dist/commands/flag.command.d.ts +92 -0
  20. package/dist/commands/flag.command.d.ts.map +1 -1
  21. package/dist/commands/flag.command.js +784 -25
  22. package/dist/commands/flag.command.js.map +1 -1
  23. package/dist/commands/guide.command.d.ts +21 -0
  24. package/dist/commands/guide.command.d.ts.map +1 -1
  25. package/dist/commands/guide.command.js +326 -18
  26. package/dist/commands/guide.command.js.map +1 -1
  27. package/dist/commands/integrate.command.js +3 -3
  28. package/dist/commands/integrate.command.js.map +1 -1
  29. package/dist/commands/ops.command.d.ts +17 -0
  30. package/dist/commands/ops.command.d.ts.map +1 -0
  31. package/dist/commands/ops.command.js +129 -0
  32. package/dist/commands/ops.command.js.map +1 -0
  33. package/dist/commands/plan.command.d.ts +31 -0
  34. package/dist/commands/plan.command.d.ts.map +1 -1
  35. package/dist/commands/plan.command.js +182 -1
  36. package/dist/commands/plan.command.js.map +1 -1
  37. package/dist/commands/stripe.command.d.ts +3 -0
  38. package/dist/commands/stripe.command.d.ts.map +1 -0
  39. package/dist/commands/stripe.command.js +43 -0
  40. package/dist/commands/stripe.command.js.map +1 -0
  41. package/dist/output.d.ts +8 -0
  42. package/dist/output.d.ts.map +1 -1
  43. package/dist/output.js +10 -0
  44. package/dist/output.js.map +1 -1
  45. package/dist/prompts/architecture.md +560 -0
  46. package/dist/prompts/auth-master-integration-prompt.md +251 -0
  47. package/dist/prompts/billing/master.md +269 -0
  48. package/dist/prompts/flags/master.md +215 -0
  49. package/dist/prompts/integration-success.md +107 -0
  50. package/package.json +4 -3
@@ -0,0 +1,251 @@
1
+ # Bridge Auth — Master Integration Prompt
2
+
3
+ You are integrating **Bridge Authentication** (auth, tenant management, RBAC) into a user's application. Your job is to detect the project structure, identify the technologies, and apply the right per-framework integration for each.
4
+
5
+ This prompt is framework-agnostic. It orchestrates discovery, confirmation, and verification — the actual install commands, file shapes, and code snippets live in the per-framework guides fetched in Step 4.
6
+
7
+ > **Related master prompts** — if the user asked for flags or billing specifically (not auth), stop here and route them:
8
+ > - Feature Flags 2.0 only → `bridge guide flags`
9
+ > - Billing 2.0 only → `bridge guide billing`
10
+ >
11
+ > If they want auth + flags + billing wired together, run this prompt first, then chain `bridge guide flags` and `bridge guide billing` at the end (or whichever subset they want).
12
+
13
+ ## Step 0 — Authenticate
14
+
15
+ Run `bridge auth login` and wait for it to print "Logged in as <email>". Once it exits, proceed to Step 1.
16
+
17
+ ---
18
+
19
+ **At the end of this integration you will output a success message that looks like this:**
20
+
21
+ ```
22
+ ██████╗ ██████╗ ██╗██████╗ ██████╗ ███████╗
23
+ ██╔══██╗██╔══██╗██║██╔══██╗██╔════╝ ██╔════╝
24
+ ██████╔╝██████╔╝██║██║ ██║██║ ███╗█████╗
25
+ ██╔══██╗██╔══██╗██║██║ ██║██║ ██║██╔══╝
26
+ ██████╔╝██║ ██║██║██████╔╝╚██████╔╝███████╗
27
+ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═════╝ ╚══════╝
28
+
29
+ ──────────────────────────────────────────────
30
+ Congratulations — [project-name] now has superpowers.
31
+ ...
32
+ ✅ You know who's calling
33
+ [token-description]
34
+ ...
35
+ ──────────────────────────────────────────────
36
+ Here is what I actually did:
37
+ [what-i-actually-did]
38
+
39
+ And here is what I changed:
40
+ [what-i-changed]
41
+ ──────────────────────────────────────────────
42
+ ```
43
+
44
+ As you work through the steps below, track the following so you have it ready:
45
+ - **`[project-name]`** — folder name and/or `package.json` name for each project integrated
46
+ - **`[token-description]`** — the identifiers the developer uses to access the authenticated user in their framework (e.g. stores for Svelte, hooks for React, decorators for NestJS)
47
+ - **`[what-i-actually-did]`** — high-level outcomes: what works now that didn't before
48
+ - **`[what-i-changed]`** — every package installed, file created or modified, and URL configured, with exact values
49
+
50
+ ## Step 1 — Discover projects
51
+
52
+ Scan the current directory and its immediate subdirectories for `package.json` files. For each one:
53
+
54
+ 1. **Detect the package manager** — check for lock files in this order:
55
+ - `bun.lock` or `bun.lockb` → use `bun`
56
+ - `pnpm-lock.yaml` → use `pnpm`
57
+ - `yarn.lock` → use `yarn`
58
+ - `package-lock.json` or none → use `npm`
59
+
60
+ 2. **Detect frontend framework** (from `dependencies` + `devDependencies`):
61
+ - `svelte` or `@sveltejs/kit` → **SvelteKit**
62
+ - `react` + `next` → **Next.js**
63
+ - `react` (without next) → **React**
64
+ - `@angular/core` → **Angular**
65
+
66
+ 3. **Detect backend framework** (from `dependencies`):
67
+ - `@nestjs/core` → **NestJS**
68
+ - `express` (without @nestjs/core) → **Express**
69
+
70
+ 4. **Detect existing auth** (from `dependencies` + `devDependencies`):
71
+ - `@nebulr/nblocks-svelte`, `@nebulr/nblocks-react`, etc. → **nblocks (predecessor to Bridge — migration needed)**
72
+ - `@nebulr-group/bridge-svelte`, `@nebulr-group/bridge-react`, `@nebulr-group/bridge-nestjs`, etc. → **Bridge already installed — check if wiring is complete (see Step 1b)**
73
+ - `next-auth`, `@auth0/*`, `@clerk/*`, `lucia`, `passport` → **third-party auth present — warn user**
74
+
75
+ 5. **Record for each project:**
76
+ - Path (relative to working directory)
77
+ - Type: `frontend` or `backend`
78
+ - Framework + version
79
+ - Package manager
80
+ - Existing auth (if any)
81
+
82
+ ## Step 1b — Check if Bridge is already integrated
83
+
84
+ If Step 1 detected a Bridge plugin (`@nebulr-group/bridge-<framework>`) in `dependencies`, the integration may already be partially or fully complete. Don't guess from the dependency alone — audit the wiring.
85
+
86
+ **Delegate the audit to the per-framework guide.** Each plugin's guide ships an "Integration audit" section that lists the exact files / providers / route shapes the framework requires. Run:
87
+
88
+ ```
89
+ bridge guide <framework> # hosted-auth audit checklist
90
+ bridge guide <framework> sdk-auth # SDK-auth audit checklist (in-app forms)
91
+ ```
92
+
93
+ The framework guide tells you precisely what must exist (bootstrap call, provider wrapping, callback routes, environment variables). Apply that checklist to the project on disk.
94
+
95
+ **General decision matrix** (independent of framework):
96
+
97
+ - **Wiring complete AND all required auth routes present** → Bridge is fully integrated. Skip to **Step 6b** and output the success message.
98
+ - **Bootstrap wiring complete BUT auth routes missing** → Bridge is partially integrated. The missing routes silently break signup verification, password reset, or SSO callback. Tell the user explicitly which files are missing (the framework guide lists them by name). Add only what's missing — do not regenerate existing routes.
99
+ - **Bootstrap wiring incomplete** (regardless of route state) → Offer to complete the initial setup (proceed to Step 4).
100
+ - **Bridge is NOT installed** → Continue with Steps 2–6 for fresh setup.
101
+
102
+ When you find missing pieces, list each one explicitly to the user — they need to know what's broken and why (e.g., "the signup verification email route is missing — every new signup is currently hitting a 404 after clicking the verification link").
103
+
104
+ ## Step 2 — Present findings and confirm
105
+
106
+ Show the user what you found. Example:
107
+
108
+ ```
109
+ I detected the following projects:
110
+
111
+ 1. ./my-app-ui — SvelteKit 5 (frontend, bun)
112
+ Existing auth: @nebulr/nblocks-svelte (will migrate to Bridge)
113
+
114
+ 2. ./my-app-api — NestJS 11 (backend, bun)
115
+ No existing auth detected
116
+
117
+ Which projects should I integrate? (all / select by number)
118
+ ```
119
+
120
+ Wait for confirmation before proceeding. If the user selects specific projects, only integrate those.
121
+
122
+ **Auth approach (frontend projects only):**
123
+
124
+ After confirming which projects to integrate, ask about the auth approach:
125
+
126
+ ```
127
+ Which auth approach do you want for the frontend?
128
+
129
+ - Hosted (default) — Bridge handles the login page. Fastest setup, zero UI to build.
130
+ - SDK — In-app login/signup forms. Full control over the auth UX.
131
+ ```
132
+
133
+ Note the user's choice. It determines which guide to fetch in Step 4:
134
+ - **Hosted** → `bridge guide <framework>` (default)
135
+ - **SDK** → `bridge guide <framework> sdk-auth`
136
+
137
+ ## Step 3 — Get Bridge app context
138
+
139
+ Run these commands to get the app configuration:
140
+
141
+ ```bash
142
+ bridge app get
143
+ bridge info auth-config
144
+ ```
145
+
146
+ Extract and note:
147
+ - `appId` — needed by both frontend and backend
148
+ - Enabled auth methods (password, magic link, SSO providers, passkeys, MFA)
149
+ - App URLs (apiUrl, uiUrl, callbackUrl)
150
+
151
+ If `bridge` CLI is not available or not configured, ask the user for the `appId` directly. They can find it in the Bridge dashboard.
152
+
153
+ ## Step 3b — Configure the Bridge app for the frontend
154
+
155
+ Detect the frontend URL from dev scripts in `package.json` (e.g., `--port 3000`, `--port 5173`). **Show the detected URL to the user and ask for confirmation before proceeding.** Then configure the Bridge app so it accepts OAuth callbacks and CORS requests from the frontend:
156
+
157
+ ```bash
158
+ bridge app update \
159
+ --ui-url <frontend-url> \
160
+ --default-callback-uri <frontend-url>/auth/oauth-callback \
161
+ --redirect-uris <frontend-url>/auth/oauth-callback \
162
+ --allowed-origins <frontend-url>
163
+ ```
164
+
165
+ If the hosted cloud-views UI is on a different origin (e.g., `http://localhost:3091` in local dev, `https://app.thebridge.dev` in prod), add it to `--allowed-origins` as well:
166
+
167
+ ```bash
168
+ bridge app update --allowed-origins <frontend-url>,<hosted-url>
169
+ ```
170
+
171
+ Without this, the Bridge API will reject the OAuth redirect (invalid redirect_uri) and block CORS requests from the frontend (origin not allowed).
172
+
173
+ ## Step 4 — Fetch and apply per-framework guides
174
+
175
+ For each confirmed project, fetch the framework-specific integration prompt.
176
+
177
+ **Frontend projects** — use the auth approach chosen in Step 2:
178
+
179
+ | Framework | Hosted (default) | SDK |
180
+ |-----------|-------------------|-----|
181
+ | SvelteKit | `bridge guide svelte` | `bridge guide svelte sdk-auth` |
182
+ | React | `bridge guide react` | `bridge guide react sdk-auth` |
183
+ | Next.js | `bridge guide nextjs` | `bridge guide nextjs sdk-auth` |
184
+ | Angular | `bridge guide angular` | `bridge guide angular sdk-auth` |
185
+
186
+ **Backend projects:**
187
+
188
+ | Framework | Command |
189
+ |-----------|---------|
190
+ | NestJS | `bridge guide nestjs` |
191
+ | Express | `bridge guide express` |
192
+
193
+ Follow the per-framework guide instructions verbatim. Pass these values from Step 3:
194
+ - `appId` — same for all projects
195
+ - `packageManager` — detected in Step 1 (use it for all install commands)
196
+
197
+ **Order:** Frontend first, then backend. This lets you verify login works before adding backend guards.
198
+
199
+ ## Step 5 — Route protection defaults
200
+
201
+ When setting up route protection, apply these sensible defaults:
202
+
203
+ **Frontend:**
204
+ - `defaultAccess: 'protected'` — everything requires login by default
205
+ - Mark as public: auth routes only (`/auth/*`) — the OAuth callback must be accessible
206
+ - Do NOT make other routes public by default. The user can relax this later for specific pages
207
+
208
+ **Backend:**
209
+ - `guard.global: true` with `defaultAccess: 'protected'`
210
+ - Mark as public: health check endpoints, public read-only APIs
211
+ - Use the framework's current-user accessor on endpoints that need user identity (the per-framework guide names it: `@CurrentUser()` for NestJS, `req.user` for Express, etc.)
212
+
213
+ Tell the user: "I've set up default route protection. You can refine which routes are public or protected using the Bridge CLI (`bridge role list`, `bridge flag list`) or by editing the route config directly."
214
+
215
+ ## Step 6 — Verify
216
+
217
+ For each integrated project:
218
+
219
+ 1. **Build check** — run the project's build command (from `package.json` scripts)
220
+ 2. **Config check** — confirm the `appId` environment variable is set
221
+ 3. **Route check** — confirm protected routes have guards and public routes are accessible
222
+
223
+ If anything fails, diagnose and fix before moving on. Once the checks pass, move on to the summary in Step 6b — do NOT just dump a list of changed files at the user.
224
+
225
+ ## Step 6b — Tell the developer what they just got
226
+
227
+ Run `bridge guide integration-success` to fetch the success message template, then output it personalised for this project.
228
+
229
+ **Substitutions (always apply):**
230
+
231
+ - `[project-name]` → the `name` field from the project's `package.json`
232
+ - `[bridge-plugin]` → the installed Bridge plugin (e.g. `bridge-svelte`, `bridge-react`, `bridge-nestjs`)
233
+ - `[dev-url]` → the frontend dev server URL detected in Step 3b (e.g. `http://localhost:5173`)
234
+
235
+ **Personalisation rules:**
236
+
237
+ - Fill in every `[placeholder]` using the substitution guide at the bottom of the template. For `[what-i-actually-did]` and `[what-i-changed]`, draw from what you actually observed and changed during Steps 1–6 — the examples in the guide are illustrative only. Strip the `AGENT SUBSTITUTION GUIDE` section before outputting — it must never be shown to the developer.
238
+ - If both a frontend and a backend were integrated, group the bottom two sections by project rather than merging them into a flat list.
239
+ - **DO NOT write any text before the banner.** The very first character of your response must be the first character of the ASCII art. No "Perfect!", no "Here's your success message:", no transition sentence, no acknowledgement — nothing. Start with the `█` character. If you find yourself typing an intro, stop and delete it.
240
+ - **If the build is broken** or auth doesn't actually work end-to-end, prepend a single "Heads up:" line before the banner. Never bury bad news under it.
241
+
242
+ After delivering the message, the integration is complete.
243
+
244
+ ## Step 7 — Offer follow-on tracks
245
+
246
+ After auth is wired and the success banner is printed, the developer commonly wants flags and billing next. Mention these one-liners so they know how to continue:
247
+
248
+ - **Feature Flags 2.0** → `bridge guide flags` (auto-detects framework, sets up flag evaluation, telemetry, realtime)
249
+ - **Billing 2.0** → `bridge guide billing` (subscriptions, plan selector, quota banners, webhook receiver)
250
+
251
+ Do not run them automatically — the developer decides when they want each track.
@@ -0,0 +1,269 @@
1
+ # Billing 2.0 — Master Integration Prompt
2
+
3
+ You are integrating **Bridge Billing** into a user's application — plan selection, Stripe Checkout, subscription state, lifecycle notices (trial / dunning / cancel), and usage quota counters.
4
+
5
+ This prompt is framework-agnostic. It orchestrates discovery, pricing model setup, and verification — the actual install commands and code snippets live in the per-framework guides fetched in Step 4.
6
+
7
+ > **Related master prompts** — if the user hasn't set up auth yet, stop here and route them:
8
+ > - Auth first → `bridge guide`
9
+ >
10
+ > If they want auth + billing wired together, run `bridge guide` first, then come back here.
11
+
12
+ ## Step 0 — Authenticate
13
+
14
+ Run `bridge auth login` and wait for it to print "Logged in as <email>". Once it exits, proceed to Step 1.
15
+
16
+ ## Step 1 — Discover projects
17
+
18
+ Scan the current directory and its immediate subdirectories for `package.json` files. For each one:
19
+
20
+ 1. **Package manager** — from lock file (`bun.lock` → `bun`, `pnpm-lock.yaml` → `pnpm`, `yarn.lock` → `yarn`, `package-lock.json` → `npm`)
21
+
22
+ 2. **Framework** — from `dependencies` + `devDependencies`:
23
+ - `svelte` or `@sveltejs/kit` → **SvelteKit**
24
+ - `react` + `next` → **Next.js**
25
+ - `react` (without next) → **React**
26
+ - `@angular/core` → **Angular**
27
+ - `@nestjs/core` → **NestJS**
28
+ - `express` (without `@nestjs/core`) → **Express**
29
+
30
+ 3. **Bridge Auth installed?** — look for `@nebulr-group/bridge-<framework>` in dependencies. Billing is scoped to a workspace/tenant and requires Bridge Auth. If not present, stop and run `bridge guide` first.
31
+
32
+ 4. **Billing already wired?** — check whether a subscription/plan route exists (typically `/subscription` or `/plan`) and whether `bridge plan list` returns at least one plan. If billing looks complete, jump to **Step 1b**.
33
+
34
+ 5. **Existing billing system?** — look for `stripe`, `@stripe/*`, `paddle-*`, `lemon-squeezy`, `chargebee`. Flag any found.
35
+
36
+ ## Step 1b — Audit existing billing wiring
37
+
38
+ If Step 1 found billing already partially or fully set up, audit it before doing anything:
39
+
40
+ - Run `bridge plan list` — are plans defined?
41
+ - Check for a subscription route with `<PlanSelector>` mounted
42
+ - Check the root layout for `<BridgeBillingNotice />`
43
+
44
+ **Decision:**
45
+ - **Fully wired** (plans exist, selector mounted, notice in layout) → skip to **Step 6** and output the success message
46
+ - **Partially wired** → tell the user exactly what's missing and only add what's absent
47
+ - **Plans missing** → continue from Step 3 (pricing model)
48
+
49
+ ## Step 2 — Present findings and confirm
50
+
51
+ Show the user what you found:
52
+
53
+ ```
54
+ I detected the following projects:
55
+
56
+ 1. ./my-app — SvelteKit 5 (frontend, bun)
57
+ Bridge Auth: ✅ installed
58
+ Billing: not yet wired
59
+ Existing billing system: none
60
+
61
+ Which projects should I wire billing into? (all / select by number)
62
+ ```
63
+
64
+ Wait for confirmation before proceeding.
65
+
66
+ ## Step 3 — Understand the pricing model
67
+
68
+ Ask the developer to describe their pricing in plain language:
69
+
70
+ > "Describe your plans — names, prices, and what each plan includes or limits. For example: 'Free plan with 100 AI completions per month. Pro at $29/month with 1000 completions and advanced analytics. 14-day free trial on Pro.'"
71
+
72
+ From their answer, map everything to confirmation tables before creating anything.
73
+
74
+ **Plans:**
75
+
76
+ | key | name | trial |
77
+ |-----|------|-------|
78
+ | `free` | Free | — |
79
+ | `pro` | Pro | 14d |
80
+
81
+ **Prices** (a plan can have several — one per currency + interval):
82
+
83
+ | plan | amount | currency | interval |
84
+ |------|--------|----------|----------|
85
+ | `pro` | 29 | USD | month |
86
+ | `pro` | 290 | USD | year |
87
+
88
+ > **A single plan can carry both a monthly and a yearly price.** When the
89
+ > developer gives two intervals for one tier (e.g. "$29/month or $290/year"),
90
+ > that is **ONE plan with two prices** — never separate `pro-monthly` /
91
+ > `pro-yearly` plans. A free plan simply has no price rows.
92
+
93
+ **Quotas** (per-resource limits that differ between plans):
94
+
95
+ | plan | metric | limit | policy |
96
+ |------|--------|-------|--------|
97
+ | `free` | `ai_completions` | 100 | hard |
98
+ | `pro` | `ai_completions` | 1000 | hard |
99
+
100
+ Use `hard` when overage should be blocked. Use `metered` when overage should bill via Stripe.
101
+
102
+ **Entitlements** (features on for some plans, off for others):
103
+
104
+ | plan | key | value |
105
+ |------|-----|-------|
106
+ | `free` | `advanced_analytics` | off |
107
+ | `pro` | `advanced_analytics` | on |
108
+
109
+ If there are no per-plan limits or feature differences, the quotas and entitlements tables are empty — skip those commands below.
110
+
111
+ **Do not create anything until the developer confirms all tables.**
112
+
113
+ ## Step 3b — Create plans, connect Stripe, then set prices
114
+
115
+ Once confirmed, create the plans (no prices here — `plan create` never takes a price):
116
+
117
+ ```bash
118
+ bridge plan create --key free --name "Free"
119
+ bridge plan create --key pro --name "Pro" --trial --trial-days 14
120
+ ```
121
+
122
+ Verify: `bridge plan list`
123
+
124
+ If any plan will have a price, connect Stripe **before** setting prices (so each price syncs to Stripe):
125
+
126
+ ```bash
127
+ bridge stripe status
128
+ ```
129
+
130
+ If not connected, ask the developer for their Stripe keys (from `dashboard.stripe.com/apikeys`):
131
+
132
+ ```bash
133
+ bridge stripe connect --secret-key sk_test_... --publishable-key pk_test_...
134
+ ```
135
+
136
+ Now set prices — **one command per Prices-table row**. `plan price set` is idempotent
137
+ (keyed on currency + interval), so a tier with monthly **and** yearly pricing is just two
138
+ calls against the same plan key:
139
+
140
+ ```bash
141
+ bridge plan price set pro --amount 29 --currency usd --interval month
142
+ bridge plan price set pro --amount 290 --currency usd --interval year
143
+ ```
144
+
145
+ Then create quotas and entitlements from the confirmed tables:
146
+
147
+ ```bash
148
+ bridge plan quota set <plan> --metric <key> --limit <n> --policy <hard|metered>
149
+ bridge plan entitlement set <plan> --key <key> --value <true|false>
150
+ ```
151
+
152
+ Run one command per row.
153
+
154
+ ## Step 4 — Fetch and apply the per-framework guide
155
+
156
+ The per-framework prompts are **not** bundled in the CLI — each plugin ships its own at
157
+ `mcp/billing-prompt.md`, which the commands below fetch. For each confirmed project, fetch the
158
+ framework-specific guide and follow it verbatim:
159
+
160
+ | Framework | Command |
161
+ |-----------|---------|
162
+ | SvelteKit | `bridge guide billing --framework svelte` |
163
+ | React | `bridge guide billing --framework react` |
164
+ | Next.js | `bridge guide billing --framework nextjs` |
165
+ | Angular | `bridge guide billing --framework angular` |
166
+ | NestJS | `bridge guide billing --framework nestjs` |
167
+ | Express | `bridge guide billing --framework express` |
168
+
169
+ If the CLI returns a 404, the plugin hasn't published its billing guide yet — tell the user, don't improvise inline.
170
+
171
+ Wire frontend first, then backend.
172
+
173
+ **When the per-framework guide is complete, do not stop — return here and continue with Step 4b.**
174
+
175
+ ## Step 4b — Plan-selection paywall (on by default)
176
+
177
+ By default, a signed-in tenant that hasn't chosen a plan is redirected to a dedicated
178
+ welcome page and can't use the app until they pick one. **Set this up unless the developer
179
+ opts out** — it's the expected first-run experience.
180
+
181
+ - The per-framework guide (Step 4) creates a welcome route that renders `<PlanSelector>`
182
+ and registers it as `billing.paywallRoute`. Confirm that part ran.
183
+ - The app-level flag `paymentsAutoRedirect` drives the redirect and is **`true` by
184
+ default** — there is nothing to switch on.
185
+
186
+ If the developer does **not** want a forced paywall, disable it with one command:
187
+
188
+ ```bash
189
+ bridge app update --payments-auto-redirect false
190
+ ```
191
+
192
+ With the paywall off, users can enter the app without choosing a plan; any `<PlanSelector>`
193
+ or `/subscription` route you mounted still works for self-serve upgrades.
194
+
195
+ ## Step 5 — Verify
196
+
197
+ For each integrated project, the agent verifies — do not hand this to the developer:
198
+
199
+ 1. Run the project's build command — no TypeScript or import errors
200
+ 2. Navigate to the subscription route — plan cards render with correct prices, and a tier with monthly + yearly pricing shows both intervals (not two separate plans)
201
+ 3. Select the free plan — subscription updates immediately, no redirect
202
+ 4. Select a paid plan — Stripe Checkout opens
203
+ 5. Complete a test payment — redirected back with the updated plan showing
204
+ 6. Cancel a payment — redirected back to the subscription page
205
+ 7. Paywall (unless opted out): sign in as a new tenant with no plan — you land on the welcome route and can't reach the app until a plan is chosen
206
+
207
+ If anything fails, diagnose and fix before moving on.
208
+
209
+ ## Step 6 — Tell the developer what they just got
210
+
211
+ **Do not skip this step.** Output the banner below, personalised. The very first character of your response must be `█` — no intro sentence, no "Here's your summary:", nothing before it. If something is broken, prepend a single "Heads up:" line before the `█`.
212
+
213
+ ```
214
+ ██████╗ ██████╗ ██╗██████╗ ██████╗ ███████╗
215
+ ██╔══██╗██╔══██╗██║██╔══██╗██╔════╝ ██╔════╝
216
+ ██████╔╝██████╔╝██║██║ ██║██║ ███╗█████╗
217
+ ██╔══██╗██╔══██╗██║██║ ██║██║ ██║██╔══╝
218
+ ██████╔╝██║ ██║██║██████╔╝╚██████╔╝███████╗
219
+ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═════╝ ╚══════╝
220
+
221
+ ──────────────────────────────────────────────
222
+ Billing is live in [project-name].
223
+
224
+ ✅ Plans — [plan-names]
225
+ ✅ Plan selector — [plan-selector-route]
226
+ ✅ Paywall — [paywall-summary]
227
+ ✅ Lifecycle notices — auto-render on trial / payment failure / cancel
228
+ ✅ Quotas and entitlements — [quota-summary]
229
+ ──────────────────────────────────────────────
230
+ Here is what I actually did:
231
+ [what-i-actually-did]
232
+
233
+ And here is what I changed:
234
+ [what-i-changed]
235
+ ──────────────────────────────────────────────
236
+ Plan selection is required by default. To let users into the app without
237
+ picking a plan first, disable the paywall:
238
+ bridge app update --payments-auto-redirect false
239
+ ──────────────────────────────────────────────
240
+ ```
241
+
242
+ Fill every `[placeholder]` with real values from the integration:
243
+ - `[project-name]` — folder name and/or `package.json` name
244
+ - `[plan-names]` — the plan keys (e.g. `free`, `premium`)
245
+ - `[plan-selector-route]` — route where `<PlanSelector>` is mounted
246
+ - `[paywall-summary]` — e.g. "new users sent to `/welcome` to pick a plan" (or "off — `paymentsAutoRedirect false`")
247
+ - `[quota-summary]` — metric keys and limits, or "none"
248
+ - `[what-i-actually-did]` / `[what-i-changed]` — every file created or modified, every command run
249
+
250
+ ## Step 7 — Offer follow-on tracks
251
+
252
+ After the success banner, mention what they can add next:
253
+
254
+ - **Webhook receiver** — receive subscription and quota events on your backend: `bridge guide billing --framework <name>`
255
+ - **Usage ingestion** — report usage from your backend: same guide, backend section
256
+ - **Portal** — let users manage their payment method or cancel: covered in the per-framework guide
257
+
258
+ Do not run these automatically — the developer decides when they want each.
259
+
260
+ ---
261
+
262
+ ## Reference — enforcement policies
263
+
264
+ | Policy | At-cap behavior | When to use |
265
+ |--------|-----------------|-------------|
266
+ | `hard` | Entitlement flips off at cap; no overage | Seat counts, included features |
267
+ | `metered` | Overage bills as a Stripe metered price; usage continues | API calls, storage |
268
+
269
+ The server always accepts `/usage/ingest` — hard policy means no metered price + entitlement gate, not server-side rejection.