docs: add the Stripe secrets to the inventory (#762)
Billing shipped (#628/#649) and paid access levels (#703) added four Stripe secrets that docs/secrets.md never picked up, breaking its own same-PR rule. Add a Billing section (live secret key, cloud webhook secret, per-instance Connect pair) and widen the connect-broker bullet to the multi-provider registry env names (Stripe/HubSpot OAuth client secrets, not just DNSimple/GitHub).
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+36
−5
docs/secrets.md+36 −5
diff --git a/docs/secrets.md b/docs/secrets.md| index ea759c6..a9cd97c 100644 |
| --- a/docs/secrets.md |
| +++ b/docs/secrets.md |
| @@ -91,11 +91,14 @@ live in `CLAUDE.local.md` and 1Password, not here. |
| held in sidecar session state, able to decrypt exactly the threads the bot |
| was added to. *Rotate*: there is no key rotation — remove the bot member |
| (admin API) and re-provision a fresh identity via `add-bot`. |
| -- **Connect broker: admin token + provider OAuth client secrets (DNSimple, |
| - GitHub) + per-instance broker tokens** — the broker persists no OAuth user |
| - material, so the client secrets gate only the ability to *initiate* flows. |
| - *Rotate*: provider secrets at the provider dashboard + broker env swap; |
| - instance tokens via the broker admin API. |
| +- **Connect broker: admin token + provider OAuth client secrets + per-instance |
| + broker tokens** — one client id/secret pair per OAuth-capable service in the |
| + integrations registry (DNSimple under its legacy env names; every other |
| + service — GitHub, Stripe, HubSpot, … — via `LCHAT_OAUTH_<ID>_CLIENT_ID` / |
| + `_CLIENT_SECRET`). The broker persists no OAuth user material, so the client |
| + secrets gate only the ability to *initiate* flows. *Rotate*: provider |
| + secrets at the provider dashboard + broker env swap; instance tokens via the |
| + broker admin API. |
| ## Provisioning & DNS |
| @@ -109,6 +112,34 @@ live in `CLAUDE.local.md` and 1Password, not here. |
| *Rotate*: admin/control tokens by env swap + restart; caller tokens via |
| the cloud admin API. |
| +## Billing (Stripe) |
| + |
| +- **Stripe secret key** (`LCHAT_STRIPE_SECRET_KEY`) — the **live** key the |
| + cloud provisioner uses for space-upgrade Checkout, the Billing Portal, and |
| + subscription webhook reconciliation. *Blast radius*: full API access to the |
| + Stripe account — customer emails and subscription state, refunds, |
| + cancellations. No message content (Stripe never sees the product), but the |
| + worst non-signing secret to lose. *Rotate*: roll the key in the Stripe |
| + dashboard (pick a grace window so the swap is zero-downtime), swap the cloud |
| + env, restart. |
| +- **Stripe webhook signing secret** (`LCHAT_STRIPE_WEBHOOK_SECRET`) — |
| + authenticates Stripe's event posts to the cloud webhook endpoint. *Blast |
| + radius*: forge checkout/subscription events → mint or revoke space |
| + entitlements without payment; no access to the Stripe account itself. |
| + *Rotate*: roll the endpoint's signing secret in the Stripe dashboard, swap |
| + the cloud env, restart. |
| +- **Stripe Connect platform key + webhook secret** |
| + (`LCHAT_STRIPE_CONNECT_KEY`, `LCHAT_STRIPE_CONNECT_WEBHOOK_SECRET`) — |
| + per-*instance* env powering paid access levels (member subscriptions via |
| + Stripe Connect). Deliberately tri-state: both unset → feature off; a partial |
| + config warns and stays off. *Blast radius*: the platform key can also act on |
| + connected accounts (sellers' Stripe accounts) within the platform's |
| + permissions; the webhook secret forges membership entitlements on that |
| + instance. *Rotate*: same shapes as the cloud pair above. |
| +- Kept alongside but **not secrets**: `LCHAT_STRIPE_PRICES` (the price book — |
| + price ids are public by the time Checkout renders) and |
| + `LCHAT_STRIPE_PORTAL_CONFIG` (a portal configuration id). |
| + |
| ## AWS (from the #550 build-out) |
| - **`dev-agent` access key** — AdministratorAccess on the dev account, for |