feat(saas): Phase 3 — plan/seats/active model, ToS consent, signed expiring export

P3a: org carries plan/seats/active/created_at; create_user enforces seats + rejects
inactive org; verify blocks login for inactive orgs; PATCH /api/admin/orgs (super_admin)
updates plan/seats/active with audit. Fixed verify swallowing its AuthError.
P3b: export/token issues a 5-min HMAC one-time CSV link; export accepts ?token=.
P3c: setup requires accepted_terms (consent stored); Setup.vue consent checkbox.
All 8 backend suites pass. Rebuilt dist.
This commit is contained in:
Macky
2026-08-09 09:48:55 +07:00
parent 056753e8cb
commit 3d5c81fbd7
36 changed files with 230 additions and 64 deletions

View File

@@ -31,13 +31,17 @@ This plan turns it into a real multi-tenant SaaS + product hardening, in phases.
analytics.export. ✅
3. **CSV export org-scoped** — admin exports only own org's sessions. ✅
## Phase 3 — SaaS-launch readiness
1. **Account/plan model (lightweight)**: org has `plan` (trial/pay), `seats`, `active`
gating login if disabled. Pluggable later.
2. **ToS / legal page** + consc ent + privacy acceptance flag on setup.
3. **Signed, expiring tokens** for data export; per-org seats enforced on user creation.
4. Obfuscate persona "recipe" — move internal signal logic server-side so the client never
receives full latent recipe (longer-term; the strip in Phase 1 is the interim).
## Phase 3 — SaaS-launch readiness ✅ DONE
1. **Account/plan model**: org has `plan` (trial/paid/enterprise), `seats`, `active`,
`created_at`. `create_user` enforces seats + active; `verify` blocks login for
inactive orgs. `PATCH /api/admin/orgs/<id>` (super_admin) sets plan/seats/active + audit.
2. **ToS/consent**: setup now requires `accepted_terms` (stored as accepted_terms_at);
Setup.vue shows a ToS/Privacy consent checkbox (links /legal stub). ✅
3. **Signed expiring export link**: `/api/analytics/export/token` issues a 5-min HMAC
signed one-time link; `/api/analytics/export?token=` accepts it (Bearer JWT still works).
Seats/active enforced on user creation. ✅
4. Persona "recipe" server-side obfuscation: interim since strip (Phase 1); full move of
internal logic server-side remains a longer-term item (out of v1 launch).
## Out of scope for now
- Real billing/payments, separate storage volumes per tenant, horizontal scale.