add platform pages
This commit is contained in:
@@ -326,3 +326,14 @@
|
||||
- `[fam]/+layout.svelte` owns the `?checkout=return` flow (moved out of the fam page). On landing: if unlocked → welcome notice. If still gated (webhook lag) → `activating` state: paused overlay swaps to a spinner card ("Activating your subscription…"), TopNav paused announcement suppressed, and `invalidateAll()` revalidates every 1.5s (max 12 tries). The `$effect` watching `activating && !disabled` cancels polling and fires "Subscription active!" the instant the gate lifts; exhaustion degrades to a refresh-hint warning.
|
||||
- Mechanics: `pollToken` guards against stale loops; `history.replaceState` scrubs the query cosmetically + `returnHandled` flag prevents double-handling. Webhook remains the sole source of truth for `paymentMode`/`active`.
|
||||
- **Upgrade (same day): activation is event-driven, not polled.** `startActivating` subscribes the browser PB client to its own `fams` record (`pb.collection('fams').subscribe(famId)` — allowed by viewRule `id = @request.auth.famId`). Webhook (superuser) writes → PB SSE push → single `invalidateAll()`; unlock `$effect` stops the subscription + fires success. 20s timer kept purely as a degrade-gracefully fallback. Rejected: onComplete-as-source-of-truth (untrusted); optional future hardening = server-side session verification on return.
|
||||
|
||||
### 2026-08-22 — Platform admin: access-code management + richer stats
|
||||
|
||||
- `/admin` extended (same route/embedded login — env-var check + `platform_session` cookie, no PB auth or hooks involved):
|
||||
- **Access Codes card**: issue codes via `?/createCode` — blank value auto-generates `XXXX-XXXX` (unambiguous charset); fields name/duration/expiry/trialDays (`trialDays > 0` = Stripe trial code). Table shows type badge, active/disabled, **used-by count** (from fams.accessCodeId map), copy-to-clipboard. `?/toggleCode` flips active; `?/deleteCode` **blocked while in use** (must disable).
|
||||
- **Overview**: added chores completed (completions length), active subs (`paymentMode='sub'`), paused/gated (`!active || none/canceled`), active codes. Families table gained plan+paused badges.
|
||||
- All actions guarded by `requirePlatform(cookies)`; data still via `pbAdmin` superuser facade.
|
||||
- Note: `svelte-kit sync` needed after changing load return shapes or `$types` staleness doubles the error count.
|
||||
- **/admin login pattern:** action sets `platform_session` cookie + returns `{success:true}`; the form's `use:enhance` callback flips a local `authed` view state — no redirect, no reliance on inline invalidation or fetch-time Set-Cookie behavior (which proved flaky in-browser despite curl proving both response paths carried it). Cookie still covers subsequent loads; load errors surface as `data.loadError` on the login card instead of silently masquerading as logged-out.
|
||||
- **Platform-admin auth via hooks:** `hooks.server.ts` resolves `locals.platformAdmin` from the `platform_session` cookie (=== 'authenticated') on every request; `/admin` load/actions consume `event.locals.platformAdmin` (`requirePlatform(event)`) instead of raw cookie reads. Same central pattern as `pb_token` → `locals.user`.
|
||||
- **Platform-admin auth hardened (supersedes the constant-cookie version):** `/admin` login now does a real `_superusers.authWithPassword` via PB; the minted superuser JWT goes in `platform_session` (`setPlatformSession` in session.ts). `hooks.server.ts` deviates on `/admin`: verifies the token with `_superusers.authRefresh` → `locals.platformAdmin` (forged values fail authRefresh and get cleared); fam-user pb_token flow skipped on that route. FINAL login shape (user-amended, working): action returns `{success:true}` (no redirect); form's enhance callback does `goto('/admin', { invalidateAll: true })` on success — forcing the load re-run with the fresh cookie; view branches on `data.authenticated`. Verified: real token renders dashboard, forged cookie gets login.
|
||||
|
||||
Reference in New Issue
Block a user