Author workspace-server/docs/openapi/management.yaml — the hand-authored,
authoritative OpenAPI 3.1 contract for the Molecule platform MANAGEMENT
surface, spanning both services in one spec:
- CP (api.moleculesai.app, /api/v1/*): orgs create/get/list/delete/export/
provision-status, public instance lookup, billing (invoices/checkout/
portal/topup), admin (admin-create-org w/ dry_run, tenant delete +
scrub w/ confirm guard, diagnostics, redeploy + fleet, workspace env
w/ force guard, ListOrgWorkspaces, admin-token, thin-ami + runtime-image
pins), provisioning (provision w/ 422 RUNTIME_PIN_MISSING, deprovision,
status).
- Tenant workspace-server: /workspaces[/:id] CRUD + restart/pause/resume,
budget, llm-billing-mode, /workspaces/:id/secrets, /settings/secrets,
/org/import, /org/templates, /org/tokens (Org API Key mint/revoke),
/templates[/import], /bundles export/import.
Defines the five security tiers as securitySchemes (workosSession cookie,
cpAdminBearer, provisionSecret [+ tenantAdminToken on deprovision], orgApiKey
+ org routing header, workspaceToken) and applies the correct scheme(s)
per-route. Dry-run / confirm / force guards modelled per-operation.
Grounded in the router + handler sources (controlplane + workspace-server),
not just the synthesis doc — notably llm-billing-mode is modelled on the
real tenant route (/admin/workspaces/:id/llm-billing-mode, AdminAuth), with
the divergence from the synthesis doc noted in the README.
Adds README.md documenting the two-service split + the security-scheme→
surface tier matrix. This is the SSOT the management MCP + CLI + docs derive
from (PLATFORM-MANAGEMENT-API.md §5c / RFC #1706). Supersedes the swaggo
/schedules stub for the management surface; runtime surface stays out of scope.
Per dev-sop Phase 1-4 + Five-Axis self-review (in PR body).
Lints clean: npx @redocly/cli lint management.yaml (0 errors, 0 warnings).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.4 KiB
Molecule Platform OpenAPI specs
This directory holds the machine-readable API contracts for the Molecule platform.
| File | Spec | Scope | Status |
|---|---|---|---|
management.yaml |
OpenAPI 3.1 | The management surface across both services (orgs, billing, admin, provisioning, workspaces, secrets, templates, org-tokens, bundles). | SSOT — hand-authored. |
swagger.yaml / swagger.json |
OpenAPI 2.0 | swaggo-generated stub, /schedules only (the per-workspace runtime surface). |
Legacy stub; superseded for management by management.yaml. |
management.yaml is the single source of truth the management tooling
derives from — the management MCP server, the management CLI (molecule-cli),
and the human-facing API docs (RFC #1706, the gap closed by
PLATFORM-MANAGEMENT-API.md §5c). Do not hand-edit those clients' route maps;
change them here and regenerate/derive.
The two-service split
One structural fact drives the whole spec: there are two services with two auth stacks, and the management surface spans both.
┌─────────────────────────────────────────┐
browser / CLI / MCP │ Control plane (CP) │
│ │ molecule-controlplane @ api.moleculesai │
│ session │ /api/v1/* (stable) [+ /cp/* sunset] │
├───────────────▶│ orgs · members · billing · provisioning │
│ admin bearer │ · fleet/admin ops · pins │
│ provision sec │ │
└────────────────┴──────────────┬───────────────────────────┘
│ edge reverse-proxy
│ (subdomain / X-Molecule-Org-Slug)
▼
┌─────────────────────────────────────────┐
Org API Key / ws tok │ Tenant workspace-server │
│ │ molecule-core/workspace-server │
└───────────────▶│ ONE EC2 per org @ <slug>.moleculesai.app│
│ workspaces · secrets · templates · │
│ org-tokens · bundles │
└─────────────────────────────────────────┘
- Control plane (CP) —
api.moleculesai.app, routes modelled under/api/v1/*(the/cp/*mirror is identical but sunset-headed per RFC #61 and is not duplicated in the spec). Owns orgs, members, billing, provisioning, fleet/admin ops. - Tenant workspace-server — one EC2 per org at
<slug>.moleculesai.app. Owns workspaces, agents, secrets, templates, org-tokens, bundles. Requests may also be sent to the CP host with anX-Molecule-Org-Slugheader; the CP edge reverse-proxies them to the tenant host (theAuthorization,X-Molecule-Org-*, and cookie headers pass through unchanged and the tenant's own middleware validates them).
The key consequence, called out in PLATFORM-MANAGEMENT-API.md: the Org API
Key is a TENANT credential, not a CP one. It is full tenant-admin over its own
org's workspace-server surface and reaches nothing on the CP (org
create/delete, billing, members, provisioning all 401/403 it). That is why
member/billing tools belong in a separate CP-admin MCP, not the org-key-authed
management MCP.
Security scheme → surface map (the tier matrix)
management.yaml defines these securitySchemes; each operation declares the
one(s) it accepts. Mirror of PLATFORM-MANAGEMENT-API.md §1:
| Scheme | What it is | Where it applies |
|---|---|---|
workosSession |
WorkOS AuthKit session cookie mcp_session (+ org membership/ownership checks) |
CP /api/v1/orgs/*, /api/v1/billing/*. Also accepted on the tenant surface via the CP-session path. |
cpAdminBearer |
CP CP_ADMIN_API_TOKEN operator bearer (AdminGate, constant-time) |
CP /api/v1/admin/* — admin-create-org, tenant teardown, workspace env, ListOrgWorkspaces, redeploy, pins. |
provisionSecret |
CP PROVISION_SHARED_SECRET bearer |
CP /api/v1/workspaces/provision, …/status. Routes unmounted when the secret is unset. |
tenantAdminToken |
Per-tenant admin_token (+ X-Molecule-Org-Id) |
CP DELETE /api/v1/workspaces/:id (deprovision) — in addition to provisionSecret (issue #118). |
orgApiKey |
Tenant Org API Key — Authorization: Bearer <key> + routing header; full tenant-admin, self-minting |
All tenant routes: /workspaces[/:id], /workspaces/:id/secrets, budget, billing-mode, /settings/secrets, /org/import, /org/templates, /org/tokens, /templates, /bundles. |
workspaceToken |
Per-workspace bearer, bound to one workspace id (+ routing header) | Read/lifecycle/secrets on a single /workspaces/:id/*. Rejected on admin list/create/delete when ADMIN_TOKEN is set — use orgApiKey. |
orgRoutingHeaderId / orgRoutingHeaderSlug |
X-Molecule-Org-Id / X-Molecule-Org-Slug |
Required on every tenant-host request so the edge / TenantGuard route + authorize against the correct org. Send one of them alongside the bearer. |
Guards worth knowing (modelled per-operation)
- Dry-run:
POST /api/v1/admin/orgs?dry_run=true— validate + echo, no org created. (The only dry-run on the whole management API.) - Confirm token:
DELETE /api/v1/admin/tenants/:slugand…/scrub-artifacts— bodyconfirmMUST equal the URL slug, else400before any teardown. - Force flag:
POST /api/v1/admin/workspaces/:id/env— keys matching the secret-keyword guard (TOKEN/SECRET/KEY/PASSWORD) requireforce=true. - Runtime-pin gate:
POST /api/v1/workspaces/provisionreturns422 RUNTIME_PIN_MISSINGwhen no runtime image pin exists. - Auto-restart side-effects: writing a workspace or global secret auto-restarts the affected workspace(s).
Security note (carried from the synthesis spec)
The Org API Key is full tenant-admin and self-minting — a management MCP
holding one holds tenant root. There is no scope-down today (TODO in
orgtoken). Per-role / per-workspace scoping should ship alongside the
management MCP.
Validate
cd workspace-server/docs/openapi
npx @redocly/cli lint management.yaml # must be clean (0 errors, 0 warnings)
Scope notes / best-effort flags
- The per-workspace runtime surface (schedules, agent, registry, a2a, memory, approvals, channels, terminal, files) is intentionally out of scope here — that's the runtime contract, not management.
- A handful of bodies are best-effort from the handlers (org-import inline
template, bundle import, list responses with open shapes) and are marked with
additionalProperties: truein the schema. Tighten as the handler structs stabilise. /cp/*deprecated mirrors are omitted (identical shapes; RFC #61 Deprecation/Sunset). Build against/api/v1/*.