Two modes — self-host and hosted
The dual-mode commitment. What stays the same and what differs across self-host and hosted-multitenant deployments.
Make_Skills runs in two deployment modes. The codebase, commands, and architecture are the same; auth and tenant-scoping differ.
The commitment
Two-mode commitment (2026-04-28): Every change considers both deployment modes (self-host and hosted-multitenant), with documentation and tests for both.
Captured as ADR-002. Enforced via the four-question PR template in CONTRIBUTING.md.
What's the same
Both modes run the same Docker stack: same FastAPI, Postgres, LanceDB, skills, subagents, UI. The repo has one platform/ directory, not separate self-host and hosted variants.
What's different
| Self-host | Hosted-multitenant | |
|---|---|---|
| Who runs the stack | The user, locally or on their VPS | Liz, on humancensys.com |
| Auth | None — single user | OAuth (provider TBD — Pillar 0 open question) |
| Data isolation | Trivial — one user | tenant_id column on every personal-toolkit row, scoped queries everywhere |
| API keys | User's own keys in their .env | User brings their own keys (BYO) |
| Cost | User pays compute + their inference | Liz pays infra; user pays their inference |
| Visibility | Localhost only (or Tailscale-shared) | Public via humancensys.com |
| Other users | n/a | Shared infrastructure, isolated data, optional public commons |
Mode detection
A single env var:
PLATFORM_MODE=self_host # or "multitenant"platform/api/auth.py (when implemented) reads this at startup and selects the auth backend. Tenant-aware code calls get_current_tenant(); in self-host mode it returns "default", in hosted it returns the auth-derived value.
What this means for contributors
Every PR is reviewed against four questions:
- What changes for a self-host user?
- What changes for the hosted-multitenant deployment?
- Tests: unit + integration for both modes (at minimum: a test with
tenant_id="default"AND a test with a synthetic non-defaulttenant_idverifying isolation) - Docs: the relevant doc explains how the change appears in both modes
Anti-patterns rejected:
- Hardcoded paths or queries without tenant scoping (outside the no-auth self-host path)
- "Multi-tenancy can come later" — once data is being written without scoping, retrofitting is a migration nightmare
- Tests that only exercise one mode
Open work
Hosted-multitenant is not yet wired. Tracked under Pillar 0:
- Tenant abstraction (
tenant_idcolumn, scoped queries, isolation tests) - Auth interface (
NoAuthBackend+ stubOAuthBackend) - Config loader abstraction (filesystem ↔ multi-tenant config store)
- Mode-aware startup wiring
PLATFORM_MODE
Self-host runs end-to-end today.
What's next
- Architecture — the layered model that makes both modes possible
- Contributing — the four-question discipline in detail