diff --git a/AGENTS.md b/AGENTS.md index 60a1570..bca15ef 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -84,6 +84,8 @@ vendor/keysat-licensing-client/ local-link Keysat SDK - **The relay owns cloud Pro/Max tier + expiry** (core-decoupling; `docs/core-decoupling-plan.md`). In multi-mode, paid status is `users.tier` — cached from the relay, keyed by the Recaps user-id — NOT a per-user Keysat license. Don't gate cloud paid features by `keysat_license`; the license only matters for self-hosted "take it home" portability. Cloud requests carry `X-Recap-User-Id` + the operator key; server-to-server tier reads/writes go through `providers/relay.js`. - **Self-serve purchase has two rails, both prepaid (no auto-renew yet).** Bitcoin = a BTCPay invoice rendered as an INLINE Lightning QR on-screen — the relay returns the BOLT11 server-to-server, so the buyer never loads BTCPay (replicate the buy-credits inline flow; do NOT redirect to a hosted checkout). Card = a Zaprite one-time hosted order (Zaprite's API has no recurring — see ROADMAP). Both settle webhooks land on the relay (it owns subscription expiry); the frontend just polls `/api/billing/status`. Expiry reminders go out via the existing System-SMTP transport (`smtp.js`): the relay enumerates who's expiring (`GET /relay/expiring-subscriptions`), Recaps maps user-id → email and sends. - **Tier credit allotments are operator-config-driven, never hardcoded.** The cards' "N relay credits each period" comes from the relay's tier-quota config (`credits_per_period` on `/relay/tier-plans`); `null` → "Unlimited". Don't bake a number or "Unlimited" into the UI. +- **`recaps.cc` IS the operator's StartOS box**, served via Start9 Pages + StartTunnel. So `make install` (after a version bump) updates the public cloud site automatically — there is no separate cloud deploy step. A frontend-only change reaches recaps.cc as soon as the box serves the new `public/` files. +- **`render()` rebuilds the whole view via `innerHTML` — preserve live media + scroll across it.** It re-attaches the live podcast `