diff --git a/docs/design/MS22-DB-CENTRIC-ARCHITECTURE.md b/docs/design/MS22-DB-CENTRIC-ARCHITECTURE.md index fb9f58d..3400570 100644 --- a/docs/design/MS22-DB-CENTRIC-ARCHITECTURE.md +++ b/docs/design/MS22-DB-CENTRIC-ARCHITECTURE.md @@ -354,3 +354,60 @@ When a user changes settings (model, provider, personality): 1. ~~Config updates → restart?~~ **Yes.** Mosaic restarts the container, fresh config on boot. 2. ~~CLI alternative for breakglass?~~ **Yes.** Both WebUI wizard and CLI (`mosaic admin create-breakglass`). 3. ~~Config cache TTL?~~ **Yes.** Config fetched once at startup, changes trigger restart. + +## Security Isolation Model + +### Core Principle: ZERO cross-user access + +Every user is fully sandboxed. No exceptions. + +### Container Isolation + +- Each user gets their **own** OpenClaw container (separate process, PID namespace) +- Each container has its **own** Docker volume (sessions, memory, workspace) +- Containers run on an **internal-only** Docker network — no external exposure +- Users NEVER talk to OpenClaw directly — Mosaic proxies all requests +- Container gateway tokens are unique per-user and single-purpose + +### Data Isolation (enforced at API + DB level) + +| Data | Isolation | Enforcement | +| ---------------- | ------------------------- | --------------------------------------------------------------------------------- | +| LLM API keys | Per-user, encrypted | `LlmProvider.userId` — all queries scoped by authenticated user | +| Chat history | Per-user container volume | Separate Docker volume per user, not shared | +| Agent memory | Per-user container volume | Separate Docker volume per user | +| Agent config | Per-user | `UserAgentConfig.userId` — scoped queries | +| Container access | Per-user | `UserContainer.userId` — Mosaic validates user owns the container before proxying | + +### API Enforcement + +- **All user-facing endpoints** include `WHERE userId = authenticatedUser.id` +- **No admin endpoint** exposes another user's API keys (even to admins) +- **Chat proxy** validates: authenticated user → owns target container → forwards request +- **Config endpoint** validates: container token matches the container requesting config +- **Provider CRUD** is fully user-scoped — User A cannot list, read, or modify User B's providers + +### What admins CAN see + +- Container status (running/stopped) — not contents +- User list and roles +- System-level config (OIDC, system agents) +- Aggregate usage metrics (not individual conversations) + +### What admins CANNOT see + +- Other users' API keys (encrypted, no decrypt endpoint) +- Other users' chat history (in container volumes, not in Mosaic DB) +- Other users' agent memory/workspace contents + +### Future: Team Workspaces (NOT in scope) + +Team/shared workspaces are a potential future feature where users opt-in to +shared agent contexts. This requires explicit consent, shared-key management, +and a different isolation model. **Not designed here. Not built now.** + +### Attack Surface Notes + +- Docker socket access (`/var/run/docker.sock`) is required by Mosaic API for container management. This is a privileged operation — the Mosaic API container must be trusted. +- `MOSAIC_SECRET_KEY` is the root of trust for encryption. Rotation requires re-encrypting all secrets in DB. +- Container-to-container communication is blocked by default (no shared network between user containers unless explicitly configured).