Skip to content

Commit e73375b

Browse files
committed
docs(cloud): control-plane ADR-0031 + roadmap v3.3
1 parent b4c3c5f commit e73375b

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

docs/ROADMAP.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,17 @@ Goal: reliability (+ compliance) gate on every PR — entirely in the user's CI,
250250
`volo compliance build`, posts/updates the sticky comment via `gh` + `GITHUB_TOKEN`, fails
251251
the check on regression. No third-party action, no secrets.
252252
- [x] Workflow template `examples/workflows/volo-pr-check.yml`
253-
- [ ] Wave 4 remaining (needs founder call): M26 cloud control plane (paid), M27 hosted
254-
sim-minutes, M30 RBAC/SSO. M23 VS Code deferred.
253+
254+
## v3.3.0 — M26: cloud control plane MVP ✅ (commercial)
255+
Goal: the first paid tier — hosted teams / workspaces / report history over the OSS engine.
256+
257+
- [x] Commercial `cloud/` dir (`volo-cloud`, own LICENSE — NOT Apache-2.0; ADR-0001/0031)
258+
- [x] Teams, workspaces, membership, API keys (sha256-hashed, shown once), workspace report
259+
history — SQLite locally / Postgres via `VOLO_DB_URL`, no new dependency
260+
- [x] FastAPI: `/cloud/teams`, `/workspaces`, `/keys` (management via `require_principal` seam) +
261+
`X-Volo-Key`-gated `/workspaces/{id}/reports` scoped to the key's workspace
262+
- [ ] Wave 4 remaining: M23 VS Code (OSS, in progress), M27 hosted sim-minutes, M28 done, M29 done,
263+
M30 RBAC/SSO (needs auth vendor).
255264

256265
## v2.4.0 — M24: public reliability leaderboard ✅
257266
Goal: one **Volo Score** per agent — the credibility/dataset engine, deterministic and static.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# ADR 0031: the cloud control plane is a commercial `cloud/` dir; API-key auth, runs locally on SQLite
2+
3+
- Status: accepted
4+
- Date: 2026-07-08
5+
6+
## Context
7+
8+
M26 opens wave 4's paid tier: a hosted control plane (teams, workspaces, report history). ADR-0001
9+
already fixed the open-core boundary (Apache-2.0 core + a separate commercial `cloud/`); the
10+
founder authorized building it. Two constraints from the bible stay binding: everything must run
11+
**locally with zero cloud accounts** (§11), and adding a paid dependency needs sign-off (§0).
12+
13+
## Decision
14+
15+
1. **Commercial code lives in `cloud/` with its own license.** `cloud/LICENSE` is a commercial
16+
license; `cloud/pyproject.toml` declares `LicenseRef-Volo-Commercial`. The OSS engine
17+
(`packages/`, `services/api`, `apps/web`, `integrations/`) stays Apache-2.0 and imports nothing
18+
from `cloud/`. `cloud/` is a workspace member so it builds and is tested, but it is a distinct
19+
licensing island.
20+
2. **No paid dependency; the stack is what's already here.** FastAPI + SQLModel + the existing
21+
`volo_core.storage` engine factory. It runs on **SQLite locally** (zero accounts) and Postgres
22+
in production purely via `VOLO_DB_URL` — no code change. Cloud tables are prefixed `cloud_*` so
23+
they coexist with the OSS schema on one engine.
24+
3. **Two-layer auth, both pluggable.** *Data* routes (read/ingest a workspace's reports) require a
25+
workspace **API key** via `X-Volo-Key`; the key is a `volo_sk_…` token stored only as a
26+
sha256 hash and returned exactly once at mint time, scoped to its workspace (cross-workspace →
27+
403). *Management* routes (create team/workspace/key) reuse the OSS `require_principal` seam —
28+
open in local dev, and denied to anonymous callers when `VOLO_REQUIRE_AUTH=true`. That flag is
29+
the documented swap point for a real user-auth vendor (Clerk/Supabase JWT) in `auth.py`, which
30+
is a paid-dependency decision deferred to deployment, not baked into the code.
31+
32+
## Consequences
33+
34+
- The control plane is fully exercisable with `uv run` and SQLite — a contributor can develop and
35+
test the commercial tier with no accounts and no spend, keeping faith with §11.
36+
- API-key auth is real and sufficient for machine/CI access (the primary use); human SSO/RBAC is
37+
intentionally out of this MVP (that's M30) — management routes are a thin seam awaiting the
38+
vendor.
39+
- Storing only the key hash means a leaked database can't recover keys; the tradeoff is keys are
40+
unrecoverable and must be re-minted, which is the correct posture.
41+
- Because cloud tables share `SQLModel.metadata`, `init_schema` on any engine creates them too;
42+
harmless (unused tables) for OSS-only deployments, and the `cloud_*` prefix avoids collisions.
43+
44+
## Alternatives considered
45+
46+
- **A hosted GitHub-App-style service with a bundled auth vendor** — rejected for the MVP: forces
47+
a paid dependency and a specific vendor before there's a design partner; the pluggable seam +
48+
API keys deliver the workspace/history value now and let the vendor be chosen later.
49+
- **Put cloud code under `services/`** — rejected: it must be a clearly separate licensing island,
50+
not mixed with the Apache-2.0 `services/api`; a top-level `cloud/` with its own LICENSE makes the
51+
boundary unmistakable (à la Sentry/Phoenix).
52+
- **Encrypt keys instead of hashing** — rejected: hashing is simpler and strictly safer for an
53+
auth token (we never need the plaintext back); one-time display is the standard pattern.

0 commit comments

Comments
 (0)