Product plane (catalog & keys)
The shared product-face commerce plane (F2). Vagary is tenant #0. Every capability is sold through this one plane; per-capability edge modules (a later wave) plug in on top. Product->capability edges only.
- Group: Sellable plane
- Contract:
contracts/product-plane/product/v1/openapi.yaml - Console: internal — operated by Vagary Labs; no customer console page for this capability.
- Runbook: operational checklist for
product-plane— internal (Vagary Labs ops; not part of this public site):docs/runbooks/capability-operations.md#product-plane - Public access: none — internal-only capability. It is NOT exposed on the public API gateway (
https://api.vagarylabs.com); it is reachable only inside the fleet (container/tailnet) by first-party callers. There is no customer-facing endpoint to call.
Endpoints
| Method | Path | Summary |
|---|---|---|
POST | /signup | Tenant self-onboarding — mint an org, provision the first user in identity, issue an org-scoped API key |
POST | /onboard | Alias of /signup (tenant self-onboarding + first key) |
GET | /api-keys | List the org's API keys (metadata only — never the raw key or hash) |
POST | /api-keys | Issue a new API key scoped to (org, product). Returns the raw key ONCE. |
POST | /api-keys/{prefix}/rotate | Rotate — mint a fresh raw key (preserving product/label/scopes), revoke the old prefix, chain rotated_to |
POST | /api-keys/{prefix}/suspend | Suspend an active key (ACTIVE -> SUSPENDED) |
POST | /api-keys/{prefix}/reactivate | Reactivate a suspended key (SUSPENDED -> ACTIVE) |
DELETE | /api-keys/{prefix} | Revoke a key permanently (terminal) |
GET | /api-keys/{prefix}/stats | Windowed usage stats for a key |
GET | /projects | List the org's projects (creates the default pair if the org has none) |
POST | /projects | Create a project |
GET | /projects/{project_id}/environments | List a project's environments |
POST | /projects/{project_id}/environments | Create an environment inside a project |
GET | /products | Product catalog — each product's granted capabilities (the plane owns the catalog; the edge enforces cap ∈ product.caps) |
GET | /plans | Product-face priced plan catalog (I5 — named/priced plans over billing-metering's opaque tiers) |
POST | /checkout | Create a subscription/checkout intent — delegates the charge to billing-metering (402 = charge-OFF gate) |
GET | /usage | Usage summary (proxies billing-metering /v1/usage/summary for the resolved org) |
GET | /quota/check | Quota check (proxies billing-metering /v1/quota/check) — enforce before granting a metered action |
GET | /health | liveness |
GET | /metrics | Prometheus text exposition |
Schemas
SignupRequest
| Field | Type | Description |
|---|---|---|
email | string | |
password | string | |
name | string | |
realm | string | identity realm (per-brand); defaults to the plane's DEFAULT_REALM |
organization_id | string | optional — omit to mint a fresh org (tenant self-onboarding) |
product | string | which capability/product the first key grants access to |
plan | string | product-face plan id (free/pro/enterprise) |
SignupResult
| Field | Type | Description |
|---|---|---|
organization_id | string | |
user | object | |
plan | string | |
api_key | object |
IssueKeyRequest
| Field | Type | Description |
|---|---|---|
product | string | |
label | string | |
scopes | array | |
expires_at | number | epoch seconds; omit/null for a key that never expires. Must be strictly in the future — an already-past value is rejected with 422. |
project_id | string | Scope the key to one of the org's projects. Omit to use the org's default project. A project the caller's organization does not own is 404 — the id is checked against identity, never trusted. |
environment_id | string | Scope the key to one environment WITHIN project_id. Requires project_id (422 without it: an environment belongs to a project, and pairing a lone environment with the default project would attribute the key to a project the caller never named). An environment outside the named project is 404. |
Project
| Field | Type | Description |
|---|---|---|
id | string | |
organization_id | string | |
name | string | |
slug | string | |
product_id | string |
ProjectList
| Field | Type | Description |
|---|---|---|
projects | array |
CreateProjectRequest
| Field | Type | Description |
|---|---|---|
name | string | |
slug | string | Optional; derived from name when omitted. |
Environment
| Field | Type | Description |
|---|---|---|
id | string | |
project_id | string | |
kind | string | One of identity's environment kinds — identity is the authority and validates it, so the set is not restated here where the two would drift. |
name | string | |
is_default | boolean |
EnvironmentList
| Field | Type | Description |
|---|---|---|
environments | array |
Generated by scripts/gen-capability-docs.py from contracts/product-plane/product/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page. The Edge route table section is synced from the live edge catalog snapshot (v1) — re-sync with python3 scripts/sync-edge-catalog.py.