Docs
Security architecture
Defense-in-depth stack: Caddy TLS → Astro CSP → Hono BFF with JWT/RBAC + ops creds → Supabase RLS → Kumo inject on Incus.
Layers
| Layer | Component | Trust boundary | Controls |
|---|---|---|---|
| 0 | DNS + domain reputation | Edge | SPF / DKIM / DMARC (see docs/domains.md) |
| 1 | Caddy (:443) | Edge reverse proxy | mTLS + HTTP/2; never proxies Kumo admin (:8000) |
| 2 | Astro CSP (apps/web) |
SSR for /app, static for marketing |
Content-Security-Policy via astro.config.mjs; secure Cookie attributes; HSTS |
| 3 | Hono BFF (apps/api) |
Service-role + JWT bearer | assertProductionProfile() blocks lab flags; rate-limit token bucket; RLS via service-role only |
| 4 | Supabase Postgres | Tenant + RLS | workspace_members, is_workspace_member(...), is_workspace_editor(...) |
| 5 | SMTP proxy (apps/smtp) |
STARTTLS :2525 (lab) / :587 (prod) | scrypt-salted password hash; mTLS to Kumo |
| 6 | Kumo + Incus | Per-node kumod | dkim_sign, bind_address, bumpConfigEpoch after every render |
| 7 | Operator panel (/app) |
Supabase Auth session | AAL2 hardening; REQUIRE_AAL2 env flag |
PMH-SEC control → layer mapping
| PMH-SEC | Layer |
|---|---|
| PMH-SEC-001 rate limit | 3 |
| PMH-SEC-002 role gating | 3, 4 |
| PMH-SEC-007 production profile guard | 3 |
| PMH-SEC-010 /v1/contact rate limit | 3 |
| PMH-SEC-012 audit logging | 4 |
| PMH-SEC-014 ALLOW_DEV_SEED block | 3 |
| PMH-SEC-015 LOCAL_OPS block | 3 |
| PMH-SEC-018 RBAC | 3, 4 |
| PMH-SEC-021 /v1/billing webhook | 3 |
| PMH-SEC-022 service_role never in browser bundle | build-time check |
| PMH-SEC-023 DKIM private key RLS | 4 |
| PMH-SEC-027 verified From gate | 3 |
| PMH-SEC-032 marketing rebrand gate | build-time |
Caddy SSR (not static-only)
infra/caddy/Caddyfile reverse-proxies SSR :4321 for /app (not just the
dist/ static bundle). This keeps middleware in scope for security headers
and SSR auth redirects.
STARTTLS edge
Production runs apps/smtp on :587; lab defaults :2525 (plaintext OK
with SMTP_ALLOW_INSECURE=1). assertProductionProfile() rejects the
insecure flag in production.
Related
- docs/hardening-checklist.md — production env flags
- trust/security — full PMH-SEC matrix
- docs/compliance-posture.md — SOC/HIPAA mapping
Last verified: Sat Jul 11 2026 17:00:00 GMT-0700 (Pacific Daylight Time). Cross-link maintained byscripts/check-docs-drift.sh (M54).