Architecture
flowchart TB
subgraph Clients
BROWSER[Friend browser<br/>vault unlock + decrypt + charts]
HAE[Health Auto Export]
HEVY_API[Hevy API<br/>client-side pull preferred]
end
subgraph Edge
TS[Tailscale WireGuard]
CFT[Cloudflare Tunnel HTTPS]
end
subgraph ThinkCentre["ThinkCentre Ubuntu · LUKS"]
APP[Next.js SAAS-Lifebot<br/>Docker]
PG[("Postgres<br/>ciphertext + metadata")]
APP --> PG
end
subgraph External
CLERK[Clerk auth]
ANT[Anthropic API<br/>client-side preferred]
end
BROWSER -- TLS --> TS
BROWSER -- TLS --> CFT
TS & CFT --> APP
BROWSER --> CLERK
BROWSER --> ANT
HAE -- "x-lifebot-key + TLS" --> CFT
HEVY_API -. browser .-> BROWSER
APP -. seal-on-ingest .-> PGAuth model (two tiers)
- Browser — Clerk session (sign-up/sign-in). All
/api/*(except ingest) requireuserId. Health rows keyed byownerId = Clerk userId, neverorgId. - Machine ingest —
POST /ingest/healthand/ingest/hevyuse per-userx-lifebot-key(HMAC-stored). Key resolves to oneownerId; writes only for that user.
Admin-blind E2EE (core decision)
- User creates a vault (password + recovery code). Server stores public key + password-wrapped private key only.
- Durable health fields are sealed to the user’s public key. Admin
psqlsees ciphertext. - Ingest: normalize in memory → merge state under key derived from presented ingest secret (not stored) → seal display payload to user public key → write.
- Dashboard: unlock in browser → fetch sealed blobs → decrypt client-side → charts.
- Coach: decrypt client-side → aggregate summary → Anthropic (prefer browser call).
- Residual risk: malicious root instrumenting a live ingest request (plaintext briefly in RAM). Honest-but-curious host browsing DB/backups is protected.
See SAAS-Lifebot/adr/0002-admin-blind-e2ee-health-data.
Components
| Piece | Role |
|---|---|
| Next.js App Router | UI + Route Handlers |
| Clerk | Identity; org onboarding kept light; health ignores org |
| Drizzle + Postgres | Owner-scoped sealed rows |
| Vault (Web Crypto / libsodium) | Keygen, seal, unseal |
| Ingest normalizers | Port of Bobs-lifebot HAE/Hevy logic |
| Health dashboard | KPIs, energy balance, charts, workouts, goals, coach |
| Settings | Vault, ingest key, export/delete, consent |
| Docker Compose | app + db on ThinkCentre |
| Tailscale / Cloudflare Tunnel | Friend + HAE reachability |
GDPR / data protection
- Explicit consent (health processing + AI) before seed/chat/real ingest use.
- Export / delete in Settings; audit events without health values.
- Minimisation: daily aggregates + workout summaries only; no raw HAE archive in MVP.
- Subprocessors: Clerk (auth), Anthropic (coach summaries), host (ThinkCentre) as controller.
- Privacy page documents TLS, LUKS, E2EE, and operator trust limits.
Decisions
- SAAS-Lifebot/adr/0001-multi-user-saas-on-home-linux
- SAAS-Lifebot/adr/0002-admin-blind-e2ee-health-data
- SAAS-Lifebot/adr/0003-clerk-auth-not-cognito
- SAAS-Lifebot/adr/0004-anthropic-client-side-coach
- SAAS-Lifebot/adr/0005-no-study-scope-fitness-only
Non-goals
- Study/Udemy path, HIPAA BAA, public open multi-tenant marketing SaaS, team-shared health, perfect defence against malicious root on live requests.
Related
SAAS-Lifebot/README · SAAS-Lifebot/LLD · SAAS-Lifebot/security-designBobs-lifebot/HLD · Tailscale · Cloudflare-Tunnel
Compiled from
wiki/projects/SAAS-Lifebot/HLD.md · git is the source of truth