Data Flow: westside-admin
Data Flow: westside-admin
Diagram
Flow 1: Authenticated page load
Flow 2: Row mutation via form action
Components
| Component | Purpose | Notes |
|---|---|---|
| Browser | Renders SSR HTML, submits forms | No JS-accessible tokens. No keycloak-js. |
| SvelteKit Server (adapter-node) | Receives requests, runs load()/actions | Single Node process per pod. |
| hooks.server.ts | Auth gate on every request | Validates JWT, populates event.locals. |
| Keycloak | Identity provider | OIDC code+PKCE flow. JWKS cached with TTL. |
| Postgres | basketball db | Connection pool via pg. tenant_id scoping enforced by helper. |
| scopedDb helper | Tenant-scoped query builder | Wraps Drizzle db; auto-injects tenant_id WHERE clause. |
| +page.server.ts | Server-only data loading + actions | The seam. Imports Drizzle here only. |
| +page.svelte | Renders typed PageData | Cannot import from $lib/server/* (compile error). |
Key Decisions
- JWT validated on EVERY request. JWKS is cached, JWT is not. Trades CPU for security against revocation lag.
- HttpOnly cookies, no Bearer in browser. Funnel exposure forces this. Tokens never reach JS — no XSS exfiltration path.
- tenant_id sourced from constant, not claim. v1 single-tenant; constant + helper makes the future swap to claim-sourced trivial.
- Mutations use SvelteKit form actions, not REST endpoints. Form submission semantics, progressive enhancement, ActionResult typing.
- Audit row written in same transaction as data mutation. Either both succeed or both fail. No mutations without audit trail.
- Server-side token refresh. Browser never knows tokens exist; refresh happens transparently when within 30s of expiry.
Related
arch-domain-westside-admin— sibling: what entities flowarch-deployment-westside-admin— sibling: where the flow livesproject-westside-admin— parent project pagefeedback_funnel_requires_auth— drives the cookie SSR choice