diff --git a/README.md b/README.md index d29bd82..1c29917 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Existing routes and heading anchors are inventoried in `scripts/legacy-routes.js python3 scripts/generate-cli-reference.py --check python3 scripts/build-navigation.py --check python3 scripts/check-docs.py +python3 scripts/sync-paid-schemas.py --check npx mintlify@4.2.375 validate npx mintlify@4.2.375 broken-links ``` @@ -46,3 +47,33 @@ openapi: /openapi/rigbox-api.json GET /api/v1/workspaces Do not add top-level `openapi` to `docs.json`: Mintlify 4.2.375's file categorizer misidentifies that configuration as an API specification. Explicit page references resolve the strict validation warning. Native endpoints and playground contracts remain unchanged. App-release and volume definitions are copied from the recorded server specification. Builds/image-release routes absent from that specification remain covered by CLI guides; do not invent generated API definitions. The existing `sync-openapi.yml` workflow updates production specs. Review its output against the targeted release before incorporating it into the docs; newly split specifications also need deliberate refresh and coverage review. Contract changes belong in the server source, not hand edits to documentation schemas. + +## Paid-v1 draft + +Paid-v1 pricing, pooling, and wallet pages are upcoming documentation, with rollout +status in `verification/paid-pricing.mdx` and source provenance in +`verification/paid-pricing.json`. This draft is not publication or production +rollout evidence. Historical v0.13 verification remains unchanged. + +`verification/paid-v1-schemas.json` contains selected server-export components, +not hand-authored contracts. `scripts/sync-paid-schemas.py` copies only those +wallet and limits components into the existing gateway spec, preserving unrelated +paths and schemas. The auth spec is the complete pure auth-service library export, +verified against its recorded SHA256. Verify with `--check`. To compare a later +gateway export: + +```bash +python3 scripts/sync-paid-schemas.py --source /path/to/final-openapi.json --check +``` + +Both current exports use exact Rust 1.93.1 at primary revision +`652120cb2273c0383158cdd15136542ab59b74f1`. The gateway has an offline +`--print-openapi` branch; the auth export uses its pure `rig_auth::openapi()` +library function without invoking auth-service startup. If the primary head +changes, regenerate both sources, replace the recorded bundle/auth export and +provenance, and revalidate against final hosted CI before publishing. Several +billing responses remain generic JSON schemas in the server source. A production sync from older +binaries can reintroduce obsolete monthly wallet promises: run the paid-schema +check and review the sync diff before accepting it. Do not mark paid-v1 current +until the deployed catalog, migration, financial and Linux runtime release gates +are confirmed. diff --git a/ai/managed-wallet.mdx b/ai/managed-wallet.mdx new file mode 100644 index 0000000..775838d --- /dev/null +++ b/ai/managed-wallet.mdx @@ -0,0 +1,83 @@ +--- +title: Managed AI wallet +description: Upcoming paid-v1 balance, durable reservations, exact charges, and verified renewal behavior. +--- + + +This is the upcoming **paid-v1** wallet contract, pending rollout and final API synchronization. Check [pricing and billing](/concepts/pricing-and-billing) and your account's confirmed Billing state before purchasing or integrating. + + +Managed AI uses an account wallet shared by your workspaces. New paid compute tiers include no AI grant. **1,000 credits represent approximately $10 of upstream usage.** An active paid subscriber may buy those credits as a **$13 pack**, whose price includes a 30% managed service markup on that upstream usage. [BYOK](/guides/byok) uses separate provider billing. + +## Read the wallet + +| Value | Meaning | +| --- | --- | +| Balance | Funds remaining after completed grants, charges, and adjustments, before open holds | +| Reserved | Funds held for requests whose financial outcome is not yet finalized | +| Available | Balance minus reserved funds; the amount available for new reservations | + +For example, a 100-credit balance with 12 credits reserved has 88 available credits. A reservation is not a final charge. When confirmed usage settles to 3 credits, the 12-credit hold is removed, the balance becomes 97, and available funds become 97 if no other holds exist. + +Billing shows the three values and the latest 100 ledger entries. Entries distinguish pack purchases, preserved opening funds, verified legacy paid-period grants, reservations, settled usage, cancellations, and adjustments. This is a combined wallet: historical labels do not establish a remaining purchased-versus-included spending split. + +Use the [credits API](/api-reference/ai/get-credits) or CLI for the available balance and balance before holds: + +```bash +rig status +rig api GET /v1/users/me/credits +``` + +`remaining` means available funds; `total` means balance before holds. Neither is a monthly allowance. Use the exact `remaining_micro` and `total_micro` integers for calculations: **1,000,000 microcredits = 1 credit**. Compatibility fields `free` and `free_micro` are zero; `pro` and `pro_micro` alias the available fields. They do not identify funding provenance. + +Older CLI versions can use historical bucket labels or round small values. The authenticated wallet projection and microcredit fields are authoritative. Do not use rounded text to authorize spending or hide a negative balance. + +## Reserve before forwarding + +Before forwarding a managed request, Rigbox atomically reserves an estimated cost in the primary wallet. Concurrent requests across workspaces cannot spend the same available funds. Missing output limits receive a compatible bound used for reservation and forwarding. Unknown pricing or unsupported bounded admission is refused before forwarding. + +A reservation estimates potential usage, not a quoted final price. A request can be refused because its estimate exceeds available funds even when a typical response would cost less. Lower the request's output bound, select a cheaper supported model, buy credits, or deliberately configure BYOK. + +When provider cost is confirmed, settlement removes the hold and records the actual debit exactly once. USD usage is converted to microcredits using `ceil(cost_usd × 100 × 1,000,000)`, preserving small nonzero charges. The pack's markup is not added again during settlement. + +Provider-confirmed zero usage settles to zero. A model named `free`, missing cost fields, an empty response, or a browser error is not proof of zero cost. + +## Interrupted or uncertain requests + +| Outcome | Wallet behavior | +| --- | --- | +| Confirmed completed usage | Settle the actual charge and remove the hold | +| Explicit upstream rejection | Release the hold without charging that rejected request | +| Interrupted stream, ambiguous transport failure, or incomplete usage | Keep the durable hold while the outcome is investigated | +| Completed generation metadata recovered later | Settle once from confirmed usage | +| Missing recoverable evidence | Retain the unresolved hold for operator review | + +The proxy retains bounded generation and usage metadata for reconciliation, not prompts, response content, search text, or credentials. Recovery is bounded and uses backoff; it has no promised completion deadline. A missing upstream generation identity may require operator investigation. + +Closing the connection or switching AI mode does not cancel a charge already incurred. Avoid automatically repeating a request after an uncertain outcome: the provider may have completed the first request, and a new request can incur another charge. Inspect Billing and your application logs first. + +Native Anthropic streaming follows this reservation and reconciliation contract too. Managed speech requires a supported bounded pricing model; binary response headers alone do not prove its charge. Use BYOK deliberately when the managed endpoint refuses unsupported pricing. + +## Debt, refunds, and disputes + +Confirmed usage that exceeds the reservation remains a debit. Refund or dispute adjustments can also make the balance or available funds negative. The ledger preserves that debt instead of truncating it to zero or discarding usage. New managed requests are refused when the wallet cannot fund their reservation. + +Refund and dispute records adjust the financial projection cumulatively and idempotently. A bank refund is not a fresh AI grant. If an adjustment or open hold looks incorrect, provide the affected operation or request identifier to support; do not assume a retry or new calendar month will clear it. + +Adjustment of a subscription payment can also revoke compute eligibility for the affected paid period while retaining resources. Winning a dispute can reverse its wallet adjustment cumulatively, but compute eligibility is not automatically restored: that requires operator review. Wallet funds and permission to run compute are separate projections. + +## Purchases and legacy renewals + +Credit-pack funds appear only after the purchase is verified and its durable operation is applied. A success URL alone does not confirm a grant. There is no automatic refill. + +At cutover, previously held funds are preserved as a non-expiring opening grant. Paid-v1 new tiers receive no included AI. Legacy Pro Managed retains a 2,000-credit grant for each uniquely verified paid subscription period. Duplicate or reordered payment events do not create duplicate grants. Failed or unfunded renewal does not create a grant; later verified payment can reconcile the eligible period once. + +Only eligible non-proration initial subscription or renewal periods with positive, verified provider-funded invoice evidence create that legacy grant. Zero-total or out-of-band paid labels are review-pending, not evidence of a grant. + +Wallet funds do not reset at the beginning of a calendar month. Unspent preserved and purchased funds remain in the wallet. Plan and mode changes do not erase them, and switching to BYOK does not release pending managed holds. + +## Exhausted credits + +Insufficient available funds produce HTTP `402` for new managed requests. Buy a pack while your paid plan is active or explicitly configure your provider endpoint and key for BYOK. Upgrading a new compute plan alone does not add credits. + +An AI wallet failure does not itself stop non-AI services. Separate compute entitlement, capacity, policy, or resource failures can still affect the workspace. [Resource limits](/concepts/limits) explains those prerequisites. diff --git a/ai/overview.mdx b/ai/overview.mdx index 90a2272..4bdd703 100644 --- a/ai/overview.mdx +++ b/ai/overview.mdx @@ -5,6 +5,8 @@ description: "Run coding agents and developer services in a Rigbox workspace." Choose whether you need an interactive coding environment or an HTTP service. A CLI app has no public URL; connect over SSH and run its executable. A service app has a process, port, and health check. +Upcoming [paid-v1 compute plans](/concepts/pricing-and-billing) include no AI grant. Choose separate managed credit purchases or BYOK provider billing. The [managed wallet](/ai/managed-wallet) distinguishes funds available for requests from pending holds and confirmed charges. + ## Set up your environment 1. [Create a workspace](/guides/workspaces) with the runtime your tool needs. diff --git a/api-reference/ai/get-credits.mdx b/api-reference/ai/get-credits.mdx index bab5512..b2d03bb 100644 --- a/api-reference/ai/get-credits.mdx +++ b/api-reference/ai/get-credits.mdx @@ -3,3 +3,7 @@ title: Get AI Credits openapi: "/openapi/rigbox-api.json GET /api/v1/users/me/credits" description: "Get the authenticated user's AI credit balance and mode (managed or BYOK)." --- + + +The staged schema describes upcoming paid-v1 wallet semantics: `remaining` is available funds and `total` is balance before holds, not a monthly grant. Final server-artifact synchronization and rollout verification remain pending. See [managed wallet](/ai/managed-wallet) and [rollout status](/verification/paid-pricing). + diff --git a/api-reference/ai/get-limits.mdx b/api-reference/ai/get-limits.mdx index b13c4ed..12f5cb9 100644 --- a/api-reference/ai/get-limits.mdx +++ b/api-reference/ai/get-limits.mdx @@ -3,3 +3,7 @@ title: Get User Limits openapi: "/openapi/rigbox-api.json GET /api/v1/users/me/limits" description: Get account plan limits including workspace, app, and resource caps. --- + + +The staged schema includes upcoming paid-v1 entitlement and sustained account CPU fields. These are draft contracts pending final source synchronization and rollout. Current account responses remain authoritative; see [resource limits](/concepts/limits) and [rollout status](/verification/paid-pricing). + diff --git a/api-reference/billing/catalog.mdx b/api-reference/billing/catalog.mdx new file mode 100644 index 0000000..a482683 --- /dev/null +++ b/api-reference/billing/catalog.mdx @@ -0,0 +1,13 @@ +--- +title: Billing catalog +openapi: "/openapi/auth-api.json GET /api/v1/auth/billing/catalog" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +Inspect the upcoming paid-v1 prices and account ceilings. Catalog visibility is not paid entitlement; `checkout_enabled` reflects configured availability. Price fields use USD cents. RAM and storage allowance amounts use MiB-sized units; CPU uses millicores. The source response schema is generic JSON, so use the confirmed account response rather than assuming missing fields. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/api-reference/billing/change.mdx b/api-reference/billing/change.mdx new file mode 100644 index 0000000..d04eba0 --- /dev/null +++ b/api-reference/billing/change.mdx @@ -0,0 +1,13 @@ +--- +title: Change plan or add-ons +openapi: "/openapi/auth-api.json POST /api/v1/auth/billing/change" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +Request a plan or add-on change using the authoritative loaded subscription and a durable UUID operation ID. Upgrades require verified payment; reductions must fit retained allocations. Pending changes leave the confirmed allowance in effect. A confirmed change does not resize, start, move, or restart a workspace. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/api-reference/billing/create-checkout.mdx b/api-reference/billing/create-checkout.mdx new file mode 100644 index 0000000..df4f2fe --- /dev/null +++ b/api-reference/billing/create-checkout.mdx @@ -0,0 +1,13 @@ +--- +title: Create subscription checkout +openapi: "/openapi/auth-api.json POST /api/v1/auth/create-checkout-session" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +Choose a new paid plan with a durable UUID `operation_id` and permitted return URLs. Retry an ambiguous request with the same operation ID and intended purchase. A checkout URL or success redirect does not grant paid compute; wait for verified payment and confirmed account projection. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/api-reference/billing/create-portal.mdx b/api-reference/billing/create-portal.mdx new file mode 100644 index 0000000..aa41711 --- /dev/null +++ b/api-reference/billing/create-portal.mdx @@ -0,0 +1,13 @@ +--- +title: Create billing portal session +openapi: "/openapi/auth-api.json POST /api/v1/auth/create-portal-session" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +Open the configured portal for payment methods, invoices, or period-end cancellation. Capacity-sensitive plan and add-on changes use the Rigbox Billing flow. Portal creation does not change entitlement. Only a permitted return URL is accepted. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/api-reference/billing/credit-pack-checkout.mdx b/api-reference/billing/credit-pack-checkout.mdx new file mode 100644 index 0000000..f2ed1ac --- /dev/null +++ b/api-reference/billing/credit-pack-checkout.mdx @@ -0,0 +1,13 @@ +--- +title: Create credit-pack checkout +openapi: "/openapi/auth-api.json POST /api/v1/auth/billing/credit-packs/checkout" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +An active verified paid subscription is required to purchase optional managed AI credits. A $13 pack buys 1,000 credits representing approximately $10 of upstream usage, with 30% markup included in the pack price. The purchase is one-time; neither checkout creation nor return parameters grant wallet funds. Verify the durable operation before treating the grant as applied. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/api-reference/billing/operation-status.mdx b/api-reference/billing/operation-status.mdx new file mode 100644 index 0000000..739b463 --- /dev/null +++ b/api-reference/billing/operation-status.mdx @@ -0,0 +1,13 @@ +--- +title: Billing operation status +openapi: "/openapi/auth-api.json GET /api/v1/auth/billing/operations/{operation_id}" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +Read an operation owned by the authenticated account. Operations may be creating, pending_payment, pending_period_end, applied, expired, or failed. Verify the server-confirmed operation and relevant subscription or wallet projection; a browser marker is not a financial receipt. The generated response schema is generic JSON. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/api-reference/billing/subscription-status.mdx b/api-reference/billing/subscription-status.mdx new file mode 100644 index 0000000..34a6ce8 --- /dev/null +++ b/api-reference/billing/subscription-status.mdx @@ -0,0 +1,13 @@ +--- +title: Subscription status +openapi: "/openapi/auth-api.json GET /api/v1/auth/subscription-status" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +Read the confirmed plan, paid-through deadline, transition deadline, pending change, add-ons, and wallet projection. A pending plan or browser checkout success does not increase confirmed quota. Compute authorization comes from the limits projection, not a status label alone. The generated response schema is generic JSON. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/api-reference/billing/wallet-history.mdx b/api-reference/billing/wallet-history.mdx new file mode 100644 index 0000000..82ee183 --- /dev/null +++ b/api-reference/billing/wallet-history.mdx @@ -0,0 +1,13 @@ +--- +title: Wallet history +openapi: "/openapi/auth-api.json GET /api/v1/auth/billing/wallet/history" +description: "Upcoming paid-v1 account billing operation, pending rollout." +--- + + +This is a draft paid-v1 reference generated from the auth service at the recorded source revision. It does not confirm live rollout. See [pricing and billing](/concepts/pricing-and-billing) and [source verification](/verification/paid-pricing). + + +Read the latest 100 account-owned ledger entries, newest first. Funding, charge, and hold changes have different meanings: `credits` changes wallet balance and `held_delta` changes reserved funds. Historical grant and purchase labels do not prove a remaining purchased-versus-included allocation. Fractional and negative values must be preserved. The generated response schema is generic JSON. + +Account billing requires an authenticated account identity with appropriate billing permissions. Workspace bridge identity is not an account billing credential. See [managed wallet](/ai/managed-wallet) for the financial contract. diff --git a/cli-reference/command-notes.json b/cli-reference/command-notes.json index 37379d9..fd72ff9 100644 --- a/cli-reference/command-notes.json +++ b/cli-reference/command-notes.json @@ -277,7 +277,7 @@ ] }, "limits": { - "description": "Use this command from your local terminal. Workspace-mode syntax, when available, is listed separately below.", + "description": "Use this command from your local terminal. Under upcoming paid-v1, limits are account-pooled and compute entitlement is separate from the plan label. Stopped workspaces retain their configured RAM, storage and slots. Inspect the authoritative limits response before explicitly retrying a blocked allocation; refreshing does not start a workspace. See /concepts/limits and /concepts/pricing-and-billing.", "examples": [ { "description": "Run from your local terminal. Replace uppercase placeholders with your own values. This invocation performs the operation described above.", @@ -506,7 +506,7 @@ ] }, "status": { - "description": "Use this command from your local terminal. Workspace-mode syntax, when available, is listed separately below.", + "description": "Shows account or workspace status in the mode listed below. Under upcoming paid-v1, remaining managed credits means available wallet funds and total means balance before holds, not a monthly allowance. Older CLI labels and rounded displays can lag the contract; exact API microcredits and Billing are authoritative. New paid tiers include no AI grant. See /ai/managed-wallet.", "examples": [ { "description": "Run from your local terminal. Replace uppercase placeholders with your own values. This invocation performs the operation described above.", diff --git a/cli-reference/commands/limits.mdx b/cli-reference/commands/limits.mdx index bd34855..0e5d47a 100644 --- a/cli-reference/commands/limits.mdx +++ b/cli-reference/commands/limits.mdx @@ -6,7 +6,7 @@ description: "Show effective resource limits and current usage" Available **local and workspace**. Reference source: CLI `0.13.0-rc.5` (`824aefd6ad16`). -Use this command from your local terminal. Workspace-mode syntax, when available, is listed separately below. +Use this command from your local terminal. Under upcoming paid-v1, limits are account-pooled and compute entitlement is separate from the plan label. Stopped workspaces retain their configured RAM, storage and slots. Inspect the authoritative limits response before explicitly retrying a blocked allocation; refreshing does not start a workspace. See /concepts/limits and /concepts/pricing-and-billing. ## Examples diff --git a/cli-reference/commands/status.mdx b/cli-reference/commands/status.mdx index e40a6ca..dbe11b8 100644 --- a/cli-reference/commands/status.mdx +++ b/cli-reference/commands/status.mdx @@ -6,7 +6,7 @@ description: "Show dashboard summary for the current account" Available **local and workspace**. Reference source: CLI `0.13.0-rc.5` (`824aefd6ad16`). -Use this command from your local terminal. Workspace-mode syntax, when available, is listed separately below. +Shows account or workspace status in the mode listed below. Under upcoming paid-v1, remaining managed credits means available wallet funds and total means balance before holds, not a monthly allowance. Older CLI labels and rounded displays can lag the contract; exact API microcredits and Billing are authoritative. New paid tiers include no AI grant. See /ai/managed-wallet. ## Examples diff --git a/concepts/limits.mdx b/concepts/limits.mdx index 61b53cb..4651fc3 100644 --- a/concepts/limits.mdx +++ b/concepts/limits.mdx @@ -1,13 +1,30 @@ --- title: Resource Limits & Quotas -description: Plan tiers, workspace limits, AI credits, and rate limits. +description: Account-pooled resource ceilings, paid compute prerequisites, optional AI credits, and capacity. --- -Every Rigbox account has limits on workspaces, resources, and AI credits based on your plan tier. This page covers what's available and how to check your usage. +Every Rigbox account has resource ceilings. Managed AI uses a separate wallet, rather than being a resource allowance included in every compute plan. + + +The account-pooling and payment rules below describe the upcoming **paid-v1** rollout. They are not confirmation of live activation. Check your account's current reported allowance and [pricing and billing](/concepts/pricing-and-billing). + ## Plan tiers -Plan limits cover workspace count, per-workspace CPU/RAM/disk, apps, snapshots, SSH keys, and managed AI credits. Use your account’s reported limits as the source of truth; limits can vary by plan and account configuration. +Starter, Developer, and Pro offer account-pooled RAM, sustained CPU, retained storage, and stored workspace slots. See [the plan and add-on table](/concepts/pricing-and-billing#paid-compute-plans) for upcoming prices. Legacy subscriptions and explicit account configurations can have different allowances; the authenticated limits response is authoritative. + +| Resource | What consumes the account allowance | +| --- | --- | +| RAM | Configured RAM across stored workspaces, including stopped workspaces | +| Sustained CPU | Running workspace and builder compute sharing the account's parent CPU budget | +| Retained storage | Logical workspace roots, volumes, snapshots, and owned custom images, including stopped resources | +| Workspace slots | Stored workspaces, including stopped workspaces | + +Image builds also reserve temporary RAM and disk against the account while the builder runs and cleanup remains pending. Those reservations count alongside stored resources; a build can need headroom beyond its target workspace's retained allocation. + +Workspace processor count is distinct from available host CPU time. A Developer account's two running workspaces share one sustained core; they do not receive one dedicated core each. Extra workspace slots and RAM do not increase sustained CPU. Active compute for one account must remain on one node until distributed account CPU enforcement is available. + +The CPU usage field represents admitted allocation, not a sampled utilization percentage. Use workspace metrics to observe actual activity. An already running workspace can retain its earlier child CPU ceiling after a plan change until you explicitly restart it; Billing does not restart it for you. ## Check your limits @@ -17,13 +34,15 @@ Show your current plan limits and usage: rig limits ``` -The output includes both the maximum allowed and current usage for each resource type. +The output includes maximum allowance and current usage. A current CLI may still display compatibility vCPU fields; inspect the JSON response for the sustained account budget and entitlement projection. + +Under paid-v1, the limits API additionally reports `compute_allowed`, `entitlement_status`, `pricing_transition_until`, `billing_paid_through`, and `billing_revision`. CPU fields are `limits.sustained_cpu_millis` and `usage.running_cpu_millis`; 1,000 millicores represent one core of sustained CPU time. A plan label alone is not permission to allocate resources. See [Get User Limits](/api-reference/ai/get-limits) for the full response schema. ## Workspace resources -When creating a workspace, you specify RAM, vCPU, and disk allocation. These are validated against your plan limits: +When creating a workspace, you specify RAM, guest vCPU count, and disk allocation. Template and recipe floors, account allowance, paid entitlement, and node capacity are checked before allocation: ```bash rig workspace spawn \ @@ -36,6 +55,8 @@ rig workspace spawn \ Requests that exceed a resource limit are rejected with an error identifying the constraint. Do not assume every quota failure uses the same HTTP status. +If payment, a transition deadline, an inactive workspace, cross-node compute, or missing capacity prevents an action, resolve that prerequisite and explicitly retry. Reading Billing or refreshing account state does not start workspaces or queue your original action. A pending invoice leaves the confirmed allowance in effect. + ### Resizing You can resize a workspace after creation. The workspace must be stopped first: @@ -46,9 +67,11 @@ rig workspace resize --workspace --ram 4096 --vcpu 4 See [Update Workspace Resources](/api-reference/workspaces/update-resources) for details. +Root disk shrinking is refused; metadata alone cannot prove a smaller filesystem. Reducing a plan or add-on must fit retained allocations first. Stopping a workspace does not free its retained RAM, storage, or slot allowance. Deletion releases storage only after backing-file cleanup succeeds. + ## AI credits -AI credits fund requests through the [managed AI proxy](/guides/managed-proxy). Each credit maps to approximately $0.01 of upstream provider cost, though the exact rate depends on the model and token count. +AI credits fund requests through the [managed AI proxy](/guides/managed-proxy). New paid-v1 tiers include no AI grant. An optional $13 pack buys 1,000 credits, approximately $10 of upstream usage with a 30% managed service markup. One credit represents approximately $0.01 of upstream usage; the pack carries the markup, not an extra charge at settlement. ### Check your balance @@ -60,10 +83,14 @@ rig api GET /v1/users/me/credits { "remaining": 1800, "total": 2000, + "remaining_micro": 1800000000, + "total_micro": 2000000000, "mode": "managed" } ``` +This abbreviated example has 200 credits held: `remaining` is available funds, and `total` is balance before holds. Neither is a monthly allowance. The [managed wallet](/ai/managed-wallet) defines compatibility fields, exact precision, preserved funds, verified legacy grants, and unresolved charges. + ### View usage breakdown ```bash @@ -74,9 +101,10 @@ Shows daily usage broken down by workspace, provider, and model. ### When credits run out -- AI requests through the proxy return `402` -- Non-AI services in your workspace continue running +- New managed AI requests return `402` when available funds cannot cover the reservation +- Wallet exhaustion alone does not stop non-AI services; compute entitlement and resource rules still apply - Switch to [BYOK mode](/guides/byok) to use your own provider account, subject to its limits +- Buying a pack is separate from upgrading compute; a new-tier plan upgrade includes no AI grant ## Rate limits @@ -109,6 +137,8 @@ rig capacity Inspect the returned availability before provisioning. Capacity is a point-in-time observation, not a reservation. +Plans and add-ons are ceilings on shared hosts, not dedicated capacity promises. Admission checks node memory, sustained CPU, storage commitments, and fresh capacity observations. A full host or stale observation can refuse allocation even while your account has unused allowance. Renewing an existing subscription does not itself allocate a full plan's resources. + Rigbox also tracks per-node runtime capacity internally, including bridge IP leases for running VMs. Each compute node has 253 active VM bridge IPs available (`172.16.0.2` through `172.16.0.254`), and stopped or deleted workspaces release their active IP lease. ## Learn more diff --git a/concepts/pricing-and-billing.mdx b/concepts/pricing-and-billing.mdx new file mode 100644 index 0000000..5f69273 --- /dev/null +++ b/concepts/pricing-and-billing.mdx @@ -0,0 +1,80 @@ +--- +title: Pricing and billing +description: Upcoming paid-v1 plans, account allowances, optional AI credits, and subscription changes. +--- + + +This page describes the upcoming **paid-v1** rollout. It is draft documentation, not confirmation that these prices or controls are live. Use the catalog and confirmed allowance shown in your account's Billing page. Publication requires the release checks in [paid-v1 verification](/verification/paid-pricing). + + +## Paid compute plans + +New accounts will need a paid subscription before creating or starting compute. Paid-v1 removes the new-account free trial. All prices below are monthly, in USD. + +| Plan | Subscription | Account RAM | Sustained account CPU | Retained account storage | Stored workspace slots | +| --- | ---: | ---: | ---: | ---: | ---: | +| Starter | $5 | 1 GiB | 0.5 core | 10 GiB | 1 | +| Developer | $15 | 4 GiB | 1 core | 30 GiB | 2 | +| Pro | $25 | 8 GiB | 2 cores | 60 GiB | 4 | + +These are account ceilings on shared hosts. Every workspace has an isolated kernel and filesystem, but the subscription does not reserve dedicated physical capacity. Creation, start, build, and expansion require available fleet capacity as well as account allowance. See [resource limits](/concepts/limits) for what counts. + +An app's template or recipe may require more RAM or disk than Starter provides. Review those minimums before choosing a plan. A higher guest vCPU count does not raise the account's sustained CPU budget. + +## Recurring add-ons + +| Add-on | Monthly price | Added account allowance | +| --- | ---: | --- | +| Storage | $4 | 25 GiB retained storage | +| RAM | $3 | 1 GiB allocated RAM | +| Workspace slot | $1 | 1 stored workspace | + +Add-ons require a paid base subscription. Extra slots or RAM do not add CPU. An add-on increases an account ceiling; it does not provision a disk, start a workspace, or guarantee space on a full host. + +Retained storage includes workspace root disks, volumes, snapshots, and owned custom images, including those belonging to stopped workspaces. Stopping a workspace releases its running compute allocation but retains its RAM configuration, storage commitment, and workspace slot. Shrinking a root filesystem is not supported. Review your retained resources before requesting a reduction. + +Image builders temporarily reserve additional RAM and disk until process exit and cleanup are confirmed. Leave room for builds as well as stored workspaces; buying a larger ceiling still requires available node capacity. + +## Optional managed AI + +Starter, Developer, and Pro include **no AI credits**. You can use [BYOK](/guides/byok), or buy a managed credit pack separately while your paid subscription is active. + +**$13 buys 1,000 managed credits**, representing approximately **$10 of upstream provider usage**. The $3 difference is the managed service charge: a 30% markup on upstream usage. One credit represents approximately $0.01 of upstream usage; the pack price carries the markup, so settlement does not add it again. Model, routing, and token usage determine actual consumption. + +Packs are one-time purchases, not an automatic refill or monthly AI allowance. Changing compute plans does not create an AI grant. Purchased balances and preserved opening balances have no calendar reset or scheduled expiry under paid-v1. [Managed wallet](/ai/managed-wallet) explains holds, charges, adjustments, and remaining funds. + +BYOK requests use your provider account and its billing, quotas, rate limits, and available balance. Rigbox compute still requires its own paid entitlement; BYOK does not make compute free. + +## Existing accounts + +Eligible existing accounts receive a **30-day transition from the durable rollout timestamp**. Billing shows your actual deadline. Account creation does not begin a new trial, and this draft page does not start the transition clock. + +Previously held AI balances become a non-expiring opening grant. Existing paid subscriptions retain their legacy subscription and resource allowance until the customer explicitly changes plan. Legacy Pro Managed receives **2,000 credits for each uniquely verified paid subscription period**; there is no additional recurring 250-credit free grant or calendar reset. A subscription status label or month boundary alone does not prove a funded renewal. + +Eligible grants come from non-proration initial subscription or renewal periods with positive, verified provider-funded invoice evidence. Zero-total or out-of-band paid labels remain subject to financial review and do not automatically create grants. + +Choose a paid plan before your transition deadline to retain paid compute access. When entitlement expires, compute can stop and new compute actions are refused. The pricing transition does not delete your retained disks or volumes. Normal retention, account deletion, and enforcement rules still apply. + +## Subscribe or change your allowance + +Open Billing to inspect your confirmed plan, add-ons, paid-through date, transition deadline, pending changes, wallet, and recent financial activity. + +1. Choose a plan or edit the add-ons loaded from your confirmed subscription. +2. Review the displayed price and resulting account allowance. +3. Complete any required payment. +4. Wait until Billing confirms the operation and the account's new allowance. +5. Return to your workspace and explicitly retry the desired action. + +A checkout redirect, browser success message, or pending invoice does not grant access, extra quota, or credits. Upgrades remain pending until payment is verified. Reductions must fit retained allocations; release resources yourself or choose a sufficient allowance. Do not assume a successful checkout also started or resized a workspace. + +An already running workspace can retain an earlier CPU ceiling until an explicit restart. A plan change does not silently restart it, move it to another node, or change its configured RAM and disk. + +Use the billing portal to manage payment methods, invoices, or cancellation. Capacity-sensitive plan and add-on changes use Rigbox's Billing flow. Cancellation is scheduled for period end, with the confirmed paid-through date shown in Billing. Renewal failure can prevent an extension of paid access; resolve payment and check the confirmed projection rather than relying on the next calendar month. + +## Integration and retry behavior + +Paid-v1 billing writes use a UUID `operation_id`. Retry an ambiguous request with the **same ID and same intended purchase**; a different ID represents another operation. Inspect the authenticated operation status rather than inferring completion from return parameters. Financial operations may be `creating`, `pending_payment`, `pending_period_end`, `applied`, `expired`, or `failed`. + +Catalog, subscription status, wallet history, and operation status are account-scoped authenticated reads. Workspace bridge identity is not an account billing credential. The draft [billing API reference](/api-reference/billing/catalog) uses the actual auth-service export at the recorded source revision; several response schemas are still generic JSON objects. Use the confirmed response rather than inventing missing types, and review [verification](/verification/paid-pricing) before relying on rollout availability. + +If account permissions, payment state, or capacity cannot be verified, the app explains the missing prerequisite. Refresh or complete payment, then choose to retry. Billing refresh does not start inactive workspaces, create missing apps, queue the original action, or silently change customer resources. diff --git a/docs.json b/docs.json index 9ceb7a1..eec1f26 100644 --- a/docs.json +++ b/docs.json @@ -23,7 +23,8 @@ "introduction", "quickstart", "guides/install-cli", - "concepts/core" + "concepts/core", + "concepts/pricing-and-billing" ] }, { @@ -137,6 +138,7 @@ "ai/overview", "guides/ai-coding-tools", "guides/managed-proxy", + "ai/managed-wallet", "guides/byok", "guides/catalog", "ai/spawn", @@ -197,6 +199,7 @@ "build/api-conventions", "concepts/architecture", "concepts/security", + "verification/paid-pricing", "sandbox-api-surface", "clawd-api-surface", "clawd-runtime-services" @@ -445,6 +448,19 @@ { "group": "Account and platform", "pages": [ + { + "group": "Billing", + "pages": [ + "api-reference/billing/catalog", + "api-reference/billing/subscription-status", + "api-reference/billing/create-checkout", + "api-reference/billing/change", + "api-reference/billing/credit-pack-checkout", + "api-reference/billing/wallet-history", + "api-reference/billing/operation-status", + "api-reference/billing/create-portal" + ] + }, { "group": "User Settings", "pages": [ diff --git a/guides/ai-coding-tools.mdx b/guides/ai-coding-tools.mdx index 9a1c466..695326a 100644 --- a/guides/ai-coding-tools.mdx +++ b/guides/ai-coding-tools.mdx @@ -233,12 +233,12 @@ rig status For programmatic access (e.g. polling from a CI job), see [Get Credits](/api-reference/ai/get-credits). -Agentic tools like Claude Code and Codex can make dozens of API calls per task. A single complex refactoring session might use 50-200 credits depending on the model and codebase size. Monitor your balance if you're on the free tier. +Agentic tools like Claude Code and Codex can make many API calls per task. Consumption depends on the model, context size, output bounds, and retries. Monitor available funds and outstanding holds when using managed AI. Upcoming paid-v1 compute plans include no AI grant; see [pricing and billing](/concepts/pricing-and-billing) and the [managed wallet](/ai/managed-wallet). ## BYOK Alternative -If you burn through managed credits quickly, switch to [BYOK mode](/guides/byok) and use your own API keys for unlimited usage. Flip the workspace mode, then set your provider key as a workspace environment variable: +If you prefer provider billing, switch to [BYOK mode](/guides/byok) and configure your own key and provider endpoint. Usage remains subject to that provider's quotas, rate limits, and available balance. Flip the workspace mode, then set your provider key as a workspace environment variable: ```bash rig workspace ai mode --workspace byok @@ -270,6 +270,6 @@ For failures, start with [runtime logs](/operate/app-logs), [health checks](/ope - [Managed AI Proxy](/guides/managed-proxy) - how the OpenRouter-backed proxy and credit system work in detail - [App Catalog → CLI-shape recipes](/guides/catalog#cli-shape-catalog-reference) - what each built-in agent installs and how the routing shims translate env vars - [Rigbox CLI](/cli-reference/cli) - manage workspaces, apps, and recipes from the terminal -- [Bring Your Own Keys](/guides/byok) - use your own API keys for unlimited usage +- [Bring Your Own Keys](/guides/byok) - use your own provider billing and limits - [Setup Scripts](/guides/setup-scripts) - automate tool installation across workspaces - [Images & Templates](/guides/images-and-templates) - choose the right base image for coding diff --git a/guides/byok.mdx b/guides/byok.mdx index 79e78d1..9feba16 100644 --- a/guides/byok.mdx +++ b/guides/byok.mdx @@ -5,6 +5,10 @@ description: Use your own AI provider API keys instead of Rigbox-managed credits Bring Your Own Keys (BYOK) mode lets you use your own AI provider API keys with Rigbox workspaces. You set the workspace to BYOK mode and provide your provider key as a workspace environment variable - provider requests are billed to your provider account and remain subject to its quotas, rate limits, and available balance. + +Under upcoming [paid-v1 pricing](/concepts/pricing-and-billing), every new compute tier supports BYOK and includes no AI grant. Provider billing is separate from your paid Rigbox compute subscription. Changing mode does not erase wallet funds, settle open managed holds, or automatically change an existing process's endpoint. + + [Managed mode](/guides/managed-proxy) routes traffic through Rigbox's OpenRouter gateway and meters it against your credit balance. In BYOK mode, configure your SDK or agent with your provider key and endpoint. The selected tool and endpoint determine the route; changing the workspace mode does not intercept or rewrite every outgoing SDK request. @@ -97,9 +101,9 @@ Run `rig ai defaults` with no flags to see the current defaults. Account default |---------|---------|------| | API keys required | No | Yes | | Credit tracking | Automatic | N/A (billed by your provider) | -| Cost | Your account’s managed credit balance | Your provider billing | +| Cost | Optional $13 / 1,000-credit pack under paid-v1; no included new-tier AI | Your provider billing, separate from paid Rigbox compute | | Supported providers | Models and protocols exposed by the managed gateway | Providers supported by your SDK or agent | -| Usage limits | Credit balance | Your provider's rate limits | +| Usage limits | Available wallet funds after durable holds, plus applicable request limits | Your provider's balance, quotas, and rate limits | | Setup time | Instant | Need existing API key | | Best for | Quick start, prototyping, demos | Production, high volume, specific models | diff --git a/guides/managed-proxy.mdx b/guides/managed-proxy.mdx index fc1c8b7..0bb37b4 100644 --- a/guides/managed-proxy.mdx +++ b/guides/managed-proxy.mdx @@ -1,10 +1,14 @@ --- title: Managed AI Proxy -description: Use Rigbox-provided AI credits without managing your own API keys. +description: Use optional managed AI credits without placing provider API keys in your workspace. --- The managed AI proxy lets your workspace code call supported AI providers without putting provider API keys in the VM. Rigbox holds managed provider keys on your behalf, injects them at request time, and tracks usage against your credit balance. + +The financial rules on this page describe upcoming **paid-v1**, pending rollout. New paid plans include no AI credits. See [pricing and billing](/concepts/pricing-and-billing) and the [managed wallet](/ai/managed-wallet) for purchases, holds, legacy balances, and verified renewals. Check your account's current Billing state before relying on rollout-specific behavior. + + ## Before you begin Use the [v0.13 CLI](/guides/install-cli) and [authenticate](/cli-reference/authentication). Run workspace-management and recipe commands from your local terminal. Commands identified as running inside a workspace require its console terminal or SSH session. Replace example resource IDs with the values returned for your account. @@ -19,7 +23,7 @@ Every workspace can reach the proxy at `http://172.16.0.1:9090` from inside the 2. Resolves the workspace from the VM's source IP on the compute bridge 3. Injects Rigbox's managed OpenRouter key (your VM never sees it) 4. Forwards the request to OpenRouter, which routes to the appropriate upstream provider for the requested model -5. Logs token usage and deducts from your credit balance +5. Reserves estimated funds before forwarding and settles confirmed usage in the account wallet 6. Returns the response to your code OpenRouter acts as a single gateway in front of every supported model family, so you only point your SDK at one endpoint regardless of which provider's model you ask for. Pick the upstream provider by choosing the model slug (e.g. `anthropic/claude-sonnet-4`, `openai/gpt-4o`, `google/gemini-2.5-pro`). @@ -37,7 +41,7 @@ The proxy speaks two HTTP shapes — OpenAI-compatible (used by most SDKs and to | `http://172.16.0.1:9090/v1/chat/completions` | OpenAI | Default route for everything OpenAI-compatible. Pick the upstream model with the `model` field (`anthropic/...`, `openai/...`, `google/...`, etc.). | | `http://172.16.0.1:9090/v1/embeddings` | OpenAI | Embedding models. | | `http://172.16.0.1:9090/v1/models` | OpenAI | List models available to your account. | -| `http://172.16.0.1:9090/v1/messages` | Anthropic | Native Anthropic Messages-API passthrough used by Claude Code. Anthropic clients reach it with the proxy root as their base URL. Streams via byte forwarding; credit metering for streaming responses on this endpoint is currently deferred. | +| `http://172.16.0.1:9090/v1/messages` | Anthropic | Native Anthropic Messages-API passthrough used by Claude Code. Anthropic clients reach it with the proxy root as their base URL. Paid-v1 streams reserve funds and settle confirmed completed usage; interrupted or uncertain usage retains a durable hold for reconciliation. | | `http://172.16.0.1:9090/rig/v1/usage` | Rigbox | Per-subject AI spend over a rolling window. See [Per-subject cost and budgets](#per-subject-cost-and-budgets). | | `http://172.16.0.1:9090/brave` | Brave Search | Web Search API when configured for your environment. | @@ -46,7 +50,7 @@ OpenAI-shape responses now carry the settled rigbox-credit cost of each call (`X -A small set of free-tier models is also exposed through a `free` alias when Rigbox has the matching managed key. They consume credits at zero rate but otherwise behave identically. +A configured `free` alias is a model route, not an account free trial or promise of zero cost. Zero-credit settlement requires provider-confirmed zero usage. Missing cost metadata or a model name alone does not establish a free request. ## Base URLs for clients @@ -62,9 +66,9 @@ Don't add `/v1` to an Anthropic base URL: the client would request `/v1/v1/messa ## Credit Tiers -Use `rig status` and your account’s credit response to inspect the current balance and renewal information. Included credits depend on your plan; purchased credits and included credit buckets can have different renewal behavior. +Use `rig status`, your account's credit response, and Billing to inspect available funds, held funds, and balance. Starter, Developer, and Pro include no AI grant. An active paid subscriber may buy $13 / 1,000 credits separately, representing approximately $10 of upstream usage and a 30% service markup. BYOK remains available with provider billing. -Credits map roughly to API cost - one credit equals approximately $0.01 of upstream provider spend. The exact mapping depends on the model and token count. +One credit represents approximately $0.01 of upstream usage; the pack's markup is not added again at settlement. Existing funds are preserved as a non-expiring opening grant. Legacy Pro Managed receives 2,000 credits per uniquely verified paid period, with no recurring 250-credit free grant or calendar reset. See [the wallet contract](/ai/managed-wallet). ## Activate Managed Mode @@ -141,7 +145,7 @@ The fastest path is the CLI: rig status ``` -`rig status` prints your remaining credits, monthly total, current mode, and active workspaces. For programmatic access, see the [Credits API reference](/api-reference/ai/get-credits). +`rig status` prints your available credits, balance before holds, current mode, and active workspaces. An older CLI can retain historical bucket labels or rounded values. `remaining` and `total` are not monthly allowances; exact microcredit fields and the authenticated wallet projection are authoritative. For programmatic access, see the [Credits API reference](/api-reference/ai/get-credits). ## View Usage Breakdown @@ -292,7 +296,7 @@ On breach the call is rejected before any spend, with a `Retry-After` header and A budget breach returns **402 `subject_over_budget`**, a rate breach **429 `subject_rate_limited`** (budget is evaluated first if several trip), and a malformed limit header **400 `subject_limit_malformed`**. The full schema is in the [Chat Completion API reference](/api-reference/managed-proxy/chat-completions). -Per-subject budgets are **advisory app policy**, not a hard wall. The hard cap is your workspace's own credit balance (enforced atomically). Under concurrency a subject can overshoot a budget by roughly `(in-flight − 1) × per-request cost`, never beyond the workspace balance. `resets_at` / `retry_after` are a conservative upper bound (the window length). Because your app asserts the subject id and its limits, this guards against honest tenant over-spend, not a compromised app process. +Per-subject budgets are **advisory app policy**, not a hard wall. Concurrent calls can overshoot a subject budget because in-flight charges have not settled yet. Account-wallet reservations are serialized before forwarding, but estimates are not a guarantee of final cost: underestimated confirmed usage is retained as debt. `resets_at` / `retry_after` describe the subject's rolling window, not wallet renewal. Because your app asserts the subject ID and limits, this guards against ordinary tenant over-spend, not a compromised app process. @@ -301,11 +305,11 @@ Per-subject budgets are **advisory app policy**, not a hard wall. The hard cap i ## What Happens When Credits Run Out -When your credit balance reaches zero: +When available funds cannot cover a new managed request's reservation: 1. **API requests return HTTP 402** - the proxy rejects new managed AI calls until credits are available -2. **The UI shows an upgrade prompt** - you can upgrade to Pro or switch to [BYOK mode](/guides/byok) -3. **Existing services keep running** - only new AI API calls are blocked; your workspace and non-AI services are unaffected +2. **Billing offers separate credit purchases** while your paid plan is active, or you can deliberately configure [BYOK](/guides/byok). Upgrading a new compute plan does not include AI credits. +3. **Wallet exhaustion alone does not stop non-AI services**. Separate compute entitlement, policy, and resource limits still apply. If you have a long-running agent or automated pipeline, it will start receiving 402 errors once credits are exhausted. Consider monitoring your balance programmatically using the credits endpoint. @@ -349,7 +353,7 @@ rig api GET /v1/users/me/credits ``` -Credit deduction happens synchronously - the balance is updated before the proxy returns the response to your code, so a completed request’s settled usage can be checked after its response. +Reservation happens before forwarding. Financial settlement can complete after the response, and uncertain or interrupted requests keep a durable hold. Refresh the wallet for confirmed financial state; a received response is not proof that all holds are finalized. ## Switching Providers and Models @@ -376,6 +380,6 @@ For failures, start with [runtime logs](/operate/app-logs), [health checks](/ope - [AI Coding Tools](/guides/ai-coding-tools) - use Rigbox credits with Claude Code, Codex, OpenCode, and Kilocode - [App Catalog](/guides/catalog#cli-shape-catalog-reference) - install the built-in coding agents with one command -- [Bring Your Own Keys](/guides/byok) - use your own API keys for unlimited usage +- [Bring Your Own Keys](/guides/byok) - use provider billing and provider limits - [Setup Scripts](/guides/setup-scripts) - automate SDK installation in new workspaces - [Service Specs](/guides/service-specs) - run AI-powered services as background daemons diff --git a/openapi/auth-api.json b/openapi/auth-api.json index 03055aa..db62b8a 100644 --- a/openapi/auth-api.json +++ b/openapi/auth-api.json @@ -1,8 +1,8 @@ { "openapi": "3.1.0", "info": { - "title": "Rigbox Public API", - "description": "Gateway-owned public API for Rigbox. The gateway composes its local lifecycle API with service-owned exported specs.", + "title": "Rigbox Auth API", + "description": "Auth-service-owned public API surface exported for gateway composition.", "contact": { "name": "Rigbox", "url": "https://rigbox.dev" @@ -490,7 +490,7 @@ { "name": "max_results", "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", + "description": "Maximum items to return. Clamped to `[1, MAX_LIMIT]`. Default 50.\n\nDeserialized leniently from a string: axum's `Query` (serde_urlencoded)\ncannot coerce a *flattened* numeric field, so a struct that\n`#[serde(flatten)]`s `PageParams` (e.g. `ListAppsQuery`) would otherwise\nfail with \"invalid type: string, expected u32\" on `?max_results=50`.", "required": false, "schema": { "type": "integer", @@ -600,115 +600,37 @@ ] } }, - "/api/v1/app-catalog": { - "get": { - "tags": [ - "App Catalog" - ], - "summary": "List all available catalog apps.", - "description": "List all available catalog apps that can be installed into a workspace.", - "operationId": "list_catalog", - "responses": { - "200": { - "description": "List of available catalog app items", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogResponse" - } - } - } - } - } - } - }, - "/api/v1/apps": { - "get": { - "tags": [ - "Apps" - ], - "summary": "List apps for the authenticated user (or scoped to a workspace via\n`?workspace_id=`). Cursor-paginated under the shared `Page` envelope.", - "description": "List the user's apps, cursor-paginated and optionally scoped to one workspace.", - "operationId": "list_apps", - "parameters": [ - { - "name": "workspace_id", - "in": "query", - "description": "Restrict to one workspace", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Apps page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Page_AppView" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "post": { + "/api/v1/auth/account": { + "delete": { "tags": [ - "Apps" + "Account" ], - "summary": "Create a new app.", - "description": "Create a new app in a workspace with a unique name and subdomain.", - "operationId": "create_app", + "summary": "Delete the account and everything it owns.", + "description": "Immediately disables the account, revokes its credentials and starts deleting its workspaces, apps, snapshots, published recipes, Stripe customer and sign-in identity. `confirm_email` must equal the account email (case-insensitive). Cannot be undone.", + "operationId": "delete_account", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateAppRequest" + "$ref": "#/components/schemas/ConfirmAccountDeletion" } } }, "required": true }, "responses": { - "201": { - "description": "App created", + "202": { + "description": "Deletion started", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAppResponse" + "$ref": "#/components/schemas/AccountDeletionAccepted" } } } }, "400": { - "description": "Invalid request", + "description": "Missing or mismatched confirmation", "content": { "application/json": { "schema": { @@ -717,8 +639,8 @@ } } }, - "404": { - "description": "Workspace not found", + "401": { + "description": "Not authenticated", "content": { "application/json": { "schema": { @@ -727,8 +649,8 @@ } } }, - "409": { - "description": "Name or subdomain conflict", + "403": { + "description": "Credential cannot delete the account, or the account is disabled (`Account disabled`) or already being deleted (`Account deleted`)", "content": { "application/json": { "schema": { @@ -736,47 +658,9 @@ } } } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/apps/{id}": { - "get": { - "tags": [ - "Apps" - ], - "summary": "Get an app by ID.", - "description": "Retrieve the full details of a single app by its ID.", - "operationId": "get_app", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID (e.g. app-xxxxxxxx)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "App details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAppResponse" - } - } - } }, - "404": { - "description": "Not found", + "409": { + "description": "A deletion is already in progress", "content": { "application/json": { "schema": { @@ -791,38 +675,29 @@ "bearer": [] } ] - }, - "delete": { + } + }, + "/api/v1/auth/account/deletion-preview": { + "get": { "tags": [ - "Apps" - ], - "summary": "Delete an app.", - "description": "Delete an app; managed apps require the force query parameter.", - "operationId": "delete_app", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - } + "Account" ], + "summary": "Preview what deleting the account removes.", + "description": "Counts every resource an account deletion removes, with the subscription, GitHub App and custom-domain state to warn about. Requires a bearer session or an API key.", + "operationId": "deletion_preview", "responses": { "200": { - "description": "App deleted", + "description": "Deletion preview", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MessageResponse" + "$ref": "#/components/schemas/AccountDeletionPreview" } } } }, - "404": { - "description": "Not found", + "401": { + "description": "Not authenticated", "content": { "application/json": { "schema": { @@ -831,8 +706,8 @@ } } }, - "409": { - "description": "Managed app (requires ?force=true)", + "403": { + "description": "Credential cannot manage the account, or the account is disabled (`Account disabled`) or being deleted (`Account deleted`)", "content": { "application/json": { "schema": { @@ -847,30 +722,42 @@ "bearer": [] } ] - }, - "patch": { + } + }, + "/api/v1/auth/billing/catalog": { + "get": { "tags": [ - "Apps" + "Auth" ], - "summary": "Update an app.", - "description": "Update an app's settings, or perform a blue-green subdomain swap.", - "operationId": "update_app", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" + "operationId": "catalog", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": {} + } } } + }, + "security": [ + { + "bearer": [] + } + ] + } + }, + "/api/v1/auth/billing/change": { + "post": { + "tags": [ + "Auth" ], + "operationId": "change", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAppRequest" + "$ref": "#/components/schemas/ChangeRequest" } } }, @@ -878,32 +765,10 @@ }, "responses": { "200": { - "description": "App updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAppResponse" - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "409": { - "description": "Name conflict", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } + "schema": {} } } } @@ -915,30 +780,17 @@ ] } }, - "/api/v1/apps/{id}/env": { - "put": { + "/api/v1/auth/billing/credit-packs/checkout": { + "post": { "tags": [ - "Apps" - ], - "summary": "Replace this app's env vars and propagate them to the running VM's\ncanonical env sink.", - "description": "Replace the app's environment variables and propagate them to the running VM.", - "operationId": "update_app_env", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - } + "Auth" ], + "operationId": "credit_checkout", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAppEnvRequest" + "$ref": "#/components/schemas/PurchaseRequest" } } }, @@ -946,12 +798,10 @@ }, "responses": { "200": { - "description": "App env updated", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAppResponse" - } + "schema": {} } } } @@ -963,33 +813,29 @@ ] } }, - "/api/v1/apps/{id}/health": { + "/api/v1/auth/billing/operations/{operation_id}": { "get": { "tags": [ - "Apps" + "Auth" ], - "summary": "Check if an app's URL is live by verifying actual content is served,\nand probe the underlying service and port status.", - "description": "Probe whether the app's URL is live and its service and port are up.", - "operationId": "check_app_health", + "operationId": "operation_status", "parameters": [ { - "name": "id", + "name": "operation_id", "in": "path", - "description": "App ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { "200": { - "description": "App health", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/AppHealthResponse" - } + "schema": {} } } } @@ -1001,33 +847,18 @@ ] } }, - "/api/v1/apps/{id}/log-sources": { + "/api/v1/auth/billing/wallet/history": { "get": { "tags": [ - "Logs" - ], - "summary": "List log sources for an app.", - "description": "List the configured log sources for an app.", - "operationId": "list_app_log_sources", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - } + "Auth" ], + "operationId": "wallet_history", "responses": { "200": { - "description": "Log sources", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ListAppLogSourcesResponse" - } + "schema": {} } } } @@ -1037,30 +868,19 @@ "bearer": [] } ] - }, + } + }, + "/api/v1/auth/change-password": { "post": { "tags": [ - "Logs" - ], - "summary": "Create a log source for an app.", - "description": "Create a new log source for an app.", - "operationId": "create_app_log_source", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - } + "Auth" ], + "operationId": "change_password", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateAppLogSourceRequest" + "$ref": "#/components/schemas/ChangePasswordRequest" } } }, @@ -1068,11 +888,11 @@ }, "responses": { "200": { - "description": "Log source created", + "description": "Password changed", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAppLogSourceResponse" + "$ref": "#/components/schemas/AuthMessageResponse" } } } @@ -1085,121 +905,129 @@ ] } }, - "/api/v1/apps/{id}/log-sources/{source_id}": { - "delete": { + "/api/v1/auth/clerk-link": { + "post": { "tags": [ - "Logs" + "Auth" ], - "summary": "Delete a log source.", - "description": "Delete a configured log source from an app by its ID.", - "operationId": "delete_app_log_source", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" + "operationId": "link", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkRequest" + } } }, - { - "name": "source_id", - "in": "path", - "description": "Source ID", - "required": true, - "schema": { - "type": "string" - } - } - ], + "required": true + }, "responses": { - "200": { - "description": "Log source deleted", + "204": { + "description": "Both identities proved; reload the console" + }, + "400": { + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MessageResponse" + "$ref": "#/components/schemas/ApiErrorBody" } } } - } - }, - "security": [ + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiErrorBody" + } + } + } + }, + "409": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiErrorBody" + } + } + } + }, + "429": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiErrorBody" + } + } + } + }, + "503": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiErrorBody" + } + } + } + } + }, + "security": [ { "bearer": [] } ] - }, - "patch": { + } + }, + "/api/v1/auth/cli-session": { + "post": { "tags": [ - "Logs" - ], - "summary": "Update a log source.", - "description": "Update an existing log source for an app.", - "operationId": "update_app_log_source", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "source_id", - "in": "path", - "description": "Source ID", - "required": true, - "schema": { - "type": "string" - } - } + "Auth" ], + "summary": "Create a pending CLI session. Called by the CLI before opening the browser.", + "description": "Open a CLI login session and return a one-time approval code.", + "operationId": "create_session", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAppLogSourceRequest" + "$ref": "#/components/schemas/CreateCliSessionRequest" } } }, "required": true }, "responses": { - "200": { - "description": "Log source updated", + "201": { + "description": "CLI session created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAppLogSourceResponse" + "$ref": "#/components/schemas/CreateCliSessionResponse" } } } } - }, - "security": [ - { - "bearer": [] - } - ] + } } }, - "/api/v1/apps/{id}/logs": { + "/api/v1/auth/cli-session/{code}": { "get": { "tags": [ - "Logs" + "Auth" ], - "summary": "Fetch logs for an app.", - "description": "Fetch a paginated batch of recent log lines for an app.", - "operationId": "get_app_logs", + "summary": "Poll a CLI session. Called by the CLI while waiting for browser approval.", + "description": "Poll a CLI login session for browser approval and its issued API key.", + "operationId": "poll_session", "parameters": [ { - "name": "id", + "name": "code", "in": "path", - "description": "App ID", + "description": "CLI session code", "required": true, "schema": { "type": "string" @@ -1208,36 +1036,31 @@ ], "responses": { "200": { - "description": "App logs", + "description": "CLI session status", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAppLogsResponse" + "$ref": "#/components/schemas/PollCliSessionResponse" } } } } - }, - "security": [ - { - "bearer": [] - } - ] + } } }, - "/api/v1/apps/{id}/logs/stream": { - "get": { + "/api/v1/auth/cli-session/{code}/approve": { + "post": { "tags": [ - "Logs" + "Auth" ], - "summary": "Stream app logs via Server-Sent Events.", - "description": "Stream an app's logs in real time over Server-Sent Events.", - "operationId": "stream_app_logs", + "summary": "Approve a CLI session. Called by the web app after the user logs in.", + "description": "Approve a CLI login session from the browser and mint its API key.", + "operationId": "approve_session", "parameters": [ { - "name": "id", + "name": "code", "in": "path", - "description": "App ID", + "description": "CLI session code", "required": true, "schema": { "type": "string" @@ -1246,7 +1069,14 @@ ], "responses": { "200": { - "description": "SSE log stream" + "description": "CLI session approved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApproveCliSessionResponse" + } + } + } } }, "security": [ @@ -1256,62 +1086,28 @@ ] } }, - "/api/v1/apps/{id}/metrics": { - "get": { + "/api/v1/auth/create-checkout-session": { + "post": { "tags": [ - "Apps" + "Auth" ], - "summary": "Get app time-series metrics.", - "description": "Return time-series traffic, latency, and error metrics for an app.", - "operationId": "get_app_metrics", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" + "operationId": "create_checkout", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PurchaseRequest" + } } }, - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/AppMetricsRange" - } - } - ], + "required": true + }, "responses": { "200": { - "description": "App metrics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AppMetricsResponse" - } - } - } - }, - "502": { - "description": "Prometheus returned an invalid response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "503": { - "description": "Prometheus unavailable", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } + "schema": {} } } } @@ -1323,99 +1119,83 @@ ] } }, - "/api/v1/apps/{id}/metrics/summary": { - "get": { + "/api/v1/auth/create-portal-session": { + "post": { "tags": [ - "Apps" + "Auth" ], - "summary": "Get app summary metrics.", - "description": "Return aggregated summary metrics for an app over the requested range.", - "operationId": "get_app_metrics_summary", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" + "operationId": "portal", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortalRequest" + } } }, - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/AppMetricsRange" - } - } - ], + "required": true + }, "responses": { "200": { - "description": "App metrics summary", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/AppMetricsSummaryResponse" - } + "schema": {} } } - }, - "502": { - "description": "Prometheus returned an invalid response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } + } + }, + "security": [ + { + "bearer": [] + } + ] + } + }, + "/api/v1/auth/force-change-password": { + "post": { + "tags": [ + "Auth" + ], + "summary": "POST /auth/force-change-password - Used after admin resets a user's password.\nVerifies the temporary password, sets the new one, and clears the must_change_password flag.", + "operationId": "force_change_password", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForceChangePasswordRequest" } } }, - "503": { - "description": "Prometheus unavailable", + "required": true + }, + "responses": { + "200": { + "description": "Password changed", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiErrorBody" + "$ref": "#/components/schemas/AuthResponseWithUser" } } } } - }, - "security": [ - { - "bearer": [] - } - ] + } } }, - "/api/v1/apps/{id}/params": { + "/api/v1/auth/github/app": { "get": { "tags": [ - "Apps" - ], - "summary": "Get configurable parameters for an app.", - "description": "Get the configurable parameter specs and current values for an app.", - "operationId": "get_app_params", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - } + "GitHub Deployments" ], + "operationId": "status", "responses": { "200": { - "description": "App params", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AppParamsResponse" + "$ref": "#/components/schemas/ConnectionStatus" } } } @@ -1427,29 +1207,34 @@ } ] }, - "patch": { + "delete": { "tags": [ - "Apps" + "GitHub Deployments" ], - "summary": "Update configurable parameters for an app.", - "description": "Update an app's configurable parameter values and apply them to the app.", - "operationId": "update_app_params", - "parameters": [ + "operationId": "disconnect", + "responses": { + "204": { + "description": "GitHub disconnected from this account" + } + }, + "security": [ { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } + "bearer": [] } + ] + } + }, + "/api/v1/auth/github/app/attempts": { + "post": { + "tags": [ + "GitHub Deployments" ], + "operationId": "create", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAppParamsRequest" + "$ref": "#/components/schemas/AttemptRequest" } } }, @@ -1457,11 +1242,11 @@ }, "responses": { "200": { - "description": "App params updated", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAppResponse" + "$ref": "#/components/schemas/AttemptResponse" } } } @@ -1474,32 +1259,30 @@ ] } }, - "/api/v1/apps/{id}/restart": { - "post": { + "/api/v1/auth/github/app/attempts/{id}": { + "get": { "tags": [ - "Apps" + "GitHub Deployments" ], - "summary": "Restart an app's service.", - "description": "Enqueue a restart of the app's background service inside its workspace VM. Returns immediately; poll GET /v1/apps/{id}/health for readiness.", - "operationId": "restart_app_service", + "operationId": "get", "parameters": [ { "name": "id", "in": "path", - "description": "App ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { - "202": { - "description": "Service restart enqueued", + "200": { + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServiceActionResponse" + "$ref": "#/components/schemas/AttemptResponse" } } } @@ -1512,33 +1295,39 @@ ] } }, - "/api/v1/apps/{id}/start": { + "/api/v1/auth/github/app/attempts/{id}/deploy": { "post": { "tags": [ - "Apps" + "GitHub Deployments" ], - "summary": "Start an app's service.", - "description": "Start the app's background service inside its workspace VM.", - "operationId": "start_app_service", + "operationId": "deploy", "parameters": [ { "name": "id", "in": "path", - "description": "App ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], - "responses": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployRequest" + } + } + }, + "required": true + }, + "responses": { "200": { - "description": "Service started", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceActionResponse" - } + "schema": {} } } } @@ -1550,32 +1339,29 @@ ] } }, - "/api/v1/apps/{id}/stop": { + "/api/v1/auth/github/app/badge-fork": { "post": { "tags": [ - "Apps" + "GitHub Deployments" ], - "summary": "Stop an app's service.", - "description": "Stop the app's background service inside its workspace VM.", - "operationId": "stop_app_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" + "operationId": "fork", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForkRequest" + } } - } - ], + }, + "required": true + }, "responses": { "200": { - "description": "Service stopped", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServiceActionResponse" + "$ref": "#/components/schemas/Inspection" } } } @@ -1588,17 +1374,32 @@ ] } }, - "/api/v1/apps/{id}/verify-domain": { + "/api/v1/auth/github/app/badge-source": { "post": { "tags": [ - "Apps" + "GitHub Deployments" ], - "summary": "Re-check DNS for an app's custom domain.", - "description": "Re-verify the DNS records for an app's custom domain and report status.", - "operationId": "verify_domain", + "operationId": "source", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SourceRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Verification result" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadgeSource" + } + } + } } }, "security": [ @@ -1608,42 +1409,49 @@ ] } }, - "/api/v1/apps/{id}/visibility": { - "put": { + "/api/v1/auth/github/app/branches": { + "get": { "tags": [ - "Apps" + "GitHub Deployments" ], - "summary": "Update app visibility.", - "description": "Set an app's visibility and allowed emails, then resync its routes.", - "operationId": "update_app_visibility", + "operationId": "branches", "parameters": [ { - "name": "id", - "in": "path", - "description": "App ID", + "name": "installation_id", + "in": "query", "required": true, "schema": { - "type": "string" + "type": "integer", + "format": "int64" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAppVisibilityRequest" - } + }, + { + "name": "repository_id", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "format": "int64" } }, - "required": true - }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], "responses": { "200": { - "description": "App visibility updated", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAppResponse" + "$ref": "#/components/schemas/BranchList" } } } @@ -1656,98 +1464,88 @@ ] } }, - "/api/v1/auth/cli-session": { + "/api/v1/auth/github/app/callback": { "post": { "tags": [ - "Auth" + "GitHub Deployments" ], - "summary": "Create a pending CLI session. Called by the CLI before opening the browser.", - "description": "Open a CLI login session and return a one-time approval code.", - "operationId": "create_session", + "operationId": "callback", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateCliSessionRequest" + "$ref": "#/components/schemas/Callback" } } }, "required": true }, "responses": { - "201": { - "description": "CLI session created", + "200": { + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateCliSessionResponse" + "$ref": "#/components/schemas/ConnectionStatus" } } } } - } + }, + "security": [ + { + "bearer": [] + } + ] } }, - "/api/v1/auth/cli-session/{code}": { - "get": { + "/api/v1/auth/github/app/connect": { + "post": { "tags": [ - "Auth" - ], - "summary": "Poll a CLI session. Called by the CLI while waiting for browser approval.", - "description": "Poll a CLI login session for browser approval and its issued API key.", - "operationId": "poll_session", - "parameters": [ - { - "name": "code", - "in": "path", - "description": "CLI session code", - "required": true, - "schema": { - "type": "string" - } - } + "GitHub Deployments" ], + "operationId": "connect", "responses": { "200": { - "description": "CLI session status", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PollCliSessionResponse" + "$ref": "#/components/schemas/ConnectUrl" } } } } - } + }, + "security": [ + { + "bearer": [] + } + ] } }, - "/api/v1/auth/cli-session/{code}/approve": { + "/api/v1/auth/github/app/generate": { "post": { "tags": [ - "Auth" + "GitHub Deployments" ], - "summary": "Approve a CLI session. Called by the web app after the user logs in.", - "description": "Approve a CLI login session from the browser and mint its API key.", - "operationId": "approve_session", - "parameters": [ - { - "name": "code", - "in": "path", - "description": "CLI session code", - "required": true, - "schema": { - "type": "string" + "operationId": "generate", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GenerateRequest" + } } - } - ], + }, + "required": true + }, "responses": { "200": { - "description": "CLI session approved", + "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ApproveCliSessionResponse" - } + "schema": {} } } } @@ -1759,43 +1557,29 @@ ] } }, - "/api/v1/catalog": { - "get": { + "/api/v1/auth/github/app/inspect": { + "post": { "tags": [ - "App Catalog" + "GitHub Deployments" ], - "summary": "Cursor-paginated list of exact deployable catalog refs for the current\nuser. Same offset-under-opaque-cursor approach as `list_recipes`.", - "description": "List paginated deployable catalog refs available to the current user.", - "operationId": "list_versioned_catalog", - "parameters": [ - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 + "operationId": "inspect", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InspectRequest" + } } }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" - } - } - ], + "required": true + }, "responses": { "200": { - "description": "Catalog page", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Page_DeployPreviewResponse" + "$ref": "#/components/schemas/Inspection" } } } @@ -1808,32 +1592,29 @@ ] } }, - "/api/v1/catalog/detail": { - "get": { + "/api/v1/auth/github/app/manifest-paths": { + "post": { "tags": [ - "App Catalog" + "GitHub Deployments" ], - "summary": "Get one exact deployable catalog ref for the current user.", - "description": "Get full details for one exact deployable catalog ref.", - "operationId": "get_versioned_catalog_detail", - "parameters": [ - { - "name": "ref", - "in": "query", - "description": "Exact deploy ref, e.g. @rigbox/filebrowser@builtin or @alice/pgweb@1.2.3", - "required": true, - "schema": { - "type": "string" + "operationId": "manifest_paths", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PathsRequest" + } } - } - ], + }, + "required": true + }, "responses": { "200": { - "description": "Versioned catalog item detail", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CommunityCatalogDetailResponse" + "$ref": "#/components/schemas/ManifestPaths" } } } @@ -1846,29 +1627,29 @@ ] } }, - "/api/v1/community/app-recipes": { + "/api/v1/auth/github/app/projects": { "get": { "tags": [ - "Community" + "GitHub Deployments" + ], + "operationId": "list", + "parameters": [ + { + "name": "workspace_id", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } ], - "summary": "List all published v1 app recipes (latest version of each).", - "description": "List all visible community app recipes, latest version of each.", - "operationId": "list_app_recipes", "responses": { "200": { - "description": "List of app recipe manifests (latest version each)", - "content": { - "application/json": { - "schema": {} - } - } - }, - "403": { - "description": "Feature not enabled", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiErrorBody" + "$ref": "#/components/schemas/ProjectList" } } } @@ -1882,47 +1663,27 @@ }, "post": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "Publish a v1 App Recipe version.", - "description": "Publish a new version of a community app recipe.", - "operationId": "publish_app_recipe", + "operationId": "save", "requestBody": { "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/SaveRequest" + } } }, "required": true }, "responses": { - "201": { - "description": "Recipe published", + "200": { + "description": "", "content": { "application/json": { "schema": {} } } - }, - "400": { - "description": "Invalid recipe", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "403": { - "description": "Feature not enabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } } }, "security": [ @@ -1932,62 +1693,26 @@ ] } }, - "/api/v1/community/app-recipes/{vendor}/{slug}": { + "/api/v1/auth/github/app/projects/{id}": { "delete": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "Delete an entire v1 App Recipe (all versions) owned by the caller.", - "description": "Delete a community app recipe and all of its published versions.", - "operationId": "delete_app_recipe_all", + "operationId": "disconnect", "parameters": [ { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", + "name": "id", "in": "path", - "description": "Recipe slug", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { - "200": { - "description": "Recipe deleted", - "content": { - "application/json": { - "schema": {} - } - } - }, - "403": { - "description": "Not the vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "204": { + "description": "Disconnected" } }, "security": [ @@ -1997,65 +1722,34 @@ ] } }, - "/api/v1/community/app-recipes/{vendor}/{slug}/versions": { - "get": { + "/api/v1/auth/github/app/projects/{id}/retry": { + "post": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "List every published version of a v1 App Recipe (newest first).", - "description": "List all published versions of a community app recipe, newest first.", - "operationId": "list_app_recipe_versions", + "operationId": "retry", "parameters": [ { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", + "name": "id", "in": "path", - "description": "Recipe slug", "required": true, "schema": { - "type": "string" - } - }, - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { "200": { - "description": "Versions page (newest first)", + "description": "", "content": { "application/json": { "schema": {} } } }, - "404": { - "description": "Recipe not found", + "409": { + "description": "Workspace is inactive or not ready", "content": { "application/json": { "schema": { @@ -2072,31 +1766,63 @@ ] } }, - "/api/v1/community/app-recipes/{vendor}/{slug}/visibility": { - "patch": { + "/api/v1/auth/github/app/projects/{id}/secrets": { + "get": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "Set the visibility of an app recipe the caller owns.", - "description": "Set a community app recipe's visibility to private or community.", - "operationId": "set_app_recipe_visibility", + "operationId": "status", "parameters": [ { - "name": "vendor", + "name": "id", "in": "path", - "description": "Vendor (lowercase)", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "The secrets the connection's rig.yaml declares, and whether each has a value. Values are never returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecretStatus" + } + } } }, + "404": { + "description": "No such GitHub connection" + }, + "409": { + "description": "The connection deploys through GitHub Actions, which reads secrets from its workflow" + }, + "422": { + "description": "The branch's rig.yaml does not validate" + } + }, + "security": [ + { + "bearer": [] + } + ] + }, + "patch": { + "tags": [ + "GitHub Deployments" + ], + "operationId": "update", + "parameters": [ { - "name": "slug", + "name": "id", "in": "path", - "description": "Recipe slug", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], @@ -2104,7 +1830,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SetVisibilityRequest" + "$ref": "#/components/schemas/UpdateSecrets" } } }, @@ -2112,34 +1838,26 @@ }, "responses": { "200": { - "description": "Visibility updated", + "description": "Stored; the result lists the names whose value changed", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MessageResponse" + "$ref": "#/components/schemas/SecretStatus" } } } }, "400": { - "description": "Invalid visibility", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "description": "A name the branch's rig.yaml does not declare, or an empty or oversized value" }, - "403": { - "description": "Not the owning vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "404": { + "description": "No such GitHub connection" + }, + "409": { + "description": "The connection deploys through GitHub Actions, or its secrets kept changing during the update" + }, + "422": { + "description": "The branch's rig.yaml does not validate" } }, "security": [ @@ -2149,58 +1867,40 @@ ] } }, - "/api/v1/community/app-recipes/{vendor}/{slug}/{version}": { + "/api/v1/auth/github/app/repositories": { "get": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "Fetch a published v1 App Recipe version.", - "description": "Fetch the manifest of a specific community app recipe version.", - "operationId": "get_app_recipe", + "operationId": "repos", "parameters": [ { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "in": "path", - "description": "Recipe slug", + "name": "installation_id", + "in": "query", "required": true, "schema": { - "type": "string" + "type": "integer", + "format": "int64" } }, { - "name": "version", - "in": "path", - "description": "Exact semver", - "required": true, + "name": "page", + "in": "query", + "required": false, "schema": { - "type": "string" + "type": "integer", + "format": "int32", + "minimum": 0 } } ], "responses": { "200": { - "description": "Manifest", - "content": { - "application/json": { - "schema": {} - } - } - }, - "404": { - "description": "Not found", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiErrorBody" + "$ref": "#/components/schemas/RepoList" } } } @@ -2211,73 +1911,53 @@ "bearer": [] } ] - }, - "delete": { + } + }, + "/api/v1/auth/github/app/webhook": { + "post": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "Delete a published v1 App Recipe version.", - "description": "Delete a specific version of a community app recipe.", - "operationId": "delete_app_recipe", - "parameters": [ - { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "in": "path", - "description": "Recipe slug", - "required": true, - "schema": { - "type": "string" + "operationId": "webhook", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "string" + } } }, - { - "name": "version", - "in": "path", - "description": "Exact semver", - "required": true, - "schema": { - "type": "string" - } + "required": true + }, + "responses": { + "202": { + "description": "Event accepted" } + } + } + }, + "/api/v1/auth/github/bindings": { + "get": { + "tags": [ + "GitHub Deployments" ], + "operationId": "list_bindings", "responses": { "200": { - "description": "Recipe version deleted", + "description": "Account repository bindings", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MessageResponse" + "$ref": "#/components/schemas/GithubBindingsResponse" } } } }, "403": { - "description": "Not the vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "description": "Full-account credential required" }, "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "description": "Feature disabled" } }, "security": [ @@ -2285,75 +1965,44 @@ "bearer": [] } ] - } - }, - "/api/v1/community/app-recipes/{vendor}/{slug}/{version}/deprecate": { + }, "post": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "Deprecate a published v1 App Recipe version. Only the owning vendor can\nmutate it; the version stays installable but is flagged as deprecated.", - "description": "Mark a community app recipe version as deprecated but still installable.", - "operationId": "deprecate_app_recipe", - "parameters": [ - { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "in": "path", - "description": "Recipe slug", - "required": true, - "schema": { - "type": "string" + "operationId": "create_binding", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGithubBindingRequest" + } } }, - { - "name": "version", - "in": "path", - "description": "Exact semver", - "required": true, - "schema": { - "type": "string" - } - } - ], + "required": true + }, "responses": { "200": { - "description": "Recipe version deprecated", + "description": "Repository binding", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MessageResponse" + "$ref": "#/components/schemas/GithubBindingResponse" } } } }, + "400": { + "description": "Invalid repository name" + }, "403": { - "description": "Not the vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "description": "Full-account credential required" }, "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "description": "Workspace unavailable or feature disabled" + }, + "409": { + "description": "Repository already bound" } }, "security": [ @@ -2363,111 +2012,42 @@ ] } }, - "/api/v1/community/app-recipes/{vendor}/{slug}/{version}/yank": { - "post": { + "/api/v1/auth/github/bindings/{binding_id}": { + "delete": { "tags": [ - "Community" + "GitHub Deployments" ], - "summary": "Yank a published v1 App Recipe version. Only the owning vendor can mutate\nit; the version is hidden from new installs but existing installs survive.", - "description": "Yank a community app recipe version, hiding it from new installs.", - "operationId": "yank_app_recipe", + "operationId": "delete_binding", "parameters": [ { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", + "name": "binding_id", "in": "path", - "description": "Recipe slug", + "description": "Binding ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } }, { - "name": "version", - "in": "path", - "description": "Exact semver", - "required": true, + "name": "workspace_id", + "in": "query", + "description": "Required target when a repository has several workspace bindings", + "required": false, "schema": { "type": "string" } } ], "responses": { - "200": { - "description": "Recipe version yanked", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } + "204": { + "description": "Binding deleted and deploy tokens revoked" }, "403": { - "description": "Not the vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "description": "Full-account credential required" }, "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/community/installs/by-app/{app_id}": { - "get": { - "tags": [ - "Community" - ], - "summary": "Get the current user's community install record for an installed app.", - "description": "Get the caller's community install record for an installed app.", - "operationId": "get_community_install_by_app", - "parameters": [ - { - "name": "app_id", - "in": "path", - "description": "Installed app ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Community install record", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommunityInstallResponse" - } - } - } + "description": "Binding unavailable or feature disabled" } }, "security": [ @@ -2477,44 +2057,17 @@ ] } }, - "/api/v1/community/profile": { - "get": { - "tags": [ - "Community" - ], - "summary": "Get the current user's community profile and catalog preference.", - "description": "Get the caller's community profile, username, and catalog preference.", - "operationId": "get_community_profile", - "responses": { - "200": { - "description": "Community profile", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommunityProfileResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "put": { + "/api/v1/auth/github/token": { + "post": { "tags": [ - "Community" + "Auth" ], - "summary": "Update the current user's community username or catalog preference.", - "description": "Update the caller's community username or catalog visibility preference.", - "operationId": "update_community_profile", + "operationId": "exchange_token", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateCommunityProfileRequest" + "$ref": "#/components/schemas/ExchangeRequest" } } }, @@ -2522,83 +2075,35 @@ }, "responses": { "200": { - "description": "Updated community profile", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommunityProfileResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/community/registry/health": { - "get": { - "tags": [ - "Community" - ], - "summary": "Get aggregate community registry health and adoption metrics.", - "description": "Get aggregate community registry health and adoption metrics.", - "operationId": "get_registry_health", - "responses": { - "200": { - "description": "Community registry health", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CommunityRegistryHealthResponse" + "$ref": "#/components/schemas/ExchangeResponse" } } } + }, + "401": { + "description": "Invalid or replayed GitHub token" + }, + "403": { + "description": "No permitted repository binding" } - }, - "security": [ - { - "bearer": [] - } - ] + } } }, - "/api/v1/community/registry/verified-webhook": { + "/api/v1/auth/login": { "post": { "tags": [ - "Community" - ], - "summary": "Promote exact community recipe versions to Verified.", - "description": "Promote signed community recipe versions to Verified via registry webhook.", - "operationId": "promote_verified_versions", - "parameters": [ - { - "name": "x-github-delivery", - "in": "header", - "description": "Unique webhook delivery/event ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "x-hub-signature-256", - "in": "header", - "description": "sha256=", - "required": true, - "schema": { - "type": "string" - } - } + "Auth" ], + "operationId": "login", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifiedPromotionWebhookRequest" + "$ref": "#/components/schemas/LoginRequest" } } }, @@ -2606,11 +2111,21 @@ }, "responses": { "200": { - "description": "Verified promotion webhook processed", + "description": "Logged in", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthResponseWithUser" + } + } + } + }, + "401": { + "description": "Invalid credentials", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifiedPromotionWebhookResponse" + "$ref": "#/components/schemas/ApiErrorBody" } } } @@ -2618,29 +2133,19 @@ } } }, - "/api/v1/community/workspace-definitions": { + "/api/v1/auth/me": { "get": { "tags": [ - "Community" + "Auth" ], - "summary": "List all published v1 workspace definitions (latest version of each).", - "description": "List all visible community workspace definitions, latest version of each.", - "operationId": "list_workspace_definitions", + "operationId": "get_me", "responses": { "200": { - "description": "List of workspace definition manifests", - "content": { - "application/json": { - "schema": {} - } - } - }, - "403": { - "description": "Feature not enabled", + "description": "Current user", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiErrorBody" + "$ref": "#/components/schemas/GetMeResponse" } } } @@ -2651,33 +2156,37 @@ "bearer": [] } ] - }, + } + }, + "/api/v1/auth/signup": { "post": { "tags": [ - "Community" + "Auth" ], - "summary": "Publish a v1 Workspace Definition version.", - "description": "Publish a new version of a community workspace definition.", - "operationId": "publish_workspace_definition", + "operationId": "signup", "requestBody": { "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/SignupRequest" + } } }, "required": true }, "responses": { - "201": { - "description": "Workspace definition published", + "200": { + "description": "Signed up", "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/AuthResponseWithUser" + } } } }, "400": { - "description": "Invalid definition", + "description": "Invalid request", "content": { "application/json": { "schema": { @@ -2686,8 +2195,8 @@ } } }, - "403": { - "description": "Feature not enabled", + "409": { + "description": "Email already registered", "content": { "application/json": { "schema": { @@ -2696,70 +2205,46 @@ } } } - }, - "security": [ - { - "bearer": [] - } - ] + } } }, - "/api/v1/community/workspace-definitions/{vendor}/{slug}": { - "delete": { + "/api/v1/auth/stripe-webhook": { + "post": { "tags": [ - "Community" + "Auth" ], - "summary": "Delete an entire v1 Workspace Definition (all versions) owned by the caller.", - "description": "Delete a community workspace definition and all of its published versions.", - "operationId": "delete_workspace_definition_all", - "parameters": [ - { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" + "operationId": "webhook", + "requestBody": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } } }, - { - "name": "slug", - "in": "path", - "description": "Workspace definition slug", - "required": true, - "schema": { - "type": "string" - } + "required": true + }, + "responses": { + "200": { + "description": "Durably received Stripe event" } + } + } + }, + "/api/v1/auth/subscription-status": { + "get": { + "tags": [ + "Auth" ], + "operationId": "status", "responses": { "200": { - "description": "Workspace definition deleted", + "description": "", "content": { "application/json": { "schema": {} } } - }, - "403": { - "description": "Not the vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } } }, "security": [ @@ -2769,72 +2254,16 @@ ] } }, - "/api/v1/community/workspace-definitions/{vendor}/{slug}/versions": { + "/api/v1/auth/validate": { "get": { "tags": [ - "Community" - ], - "summary": "List every published version of a v1 Workspace Definition (newest first).", - "description": "List all published versions of a community workspace definition, newest first.", - "operationId": "list_workspace_definition_versions", - "parameters": [ - { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "in": "path", - "description": "Workspace definition slug", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" - } - } + "Auth" ], + "summary": "GET /auth/validate - Validate token for forward_auth", + "operationId": "validate_token", "responses": { "200": { - "description": "Versions page (newest first)", - "content": { - "application/json": { - "schema": {} - } - } - }, - "404": { - "description": "Definition not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } + "description": "Token valid" } }, "security": [ @@ -2843,8614 +2272,38 @@ } ] } - }, - "/api/v1/community/workspace-definitions/{vendor}/{slug}/visibility": { - "patch": { - "tags": [ - "Community" - ], - "summary": "Set the visibility of a workspace definition the caller owns.", - "description": "Set a community workspace definition's visibility to private or community.", - "operationId": "set_workspace_definition_visibility", - "parameters": [ - { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "in": "path", - "description": "Workspace definition slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetVisibilityRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Visibility updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - }, - "400": { - "description": "Invalid visibility", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "403": { - "description": "Not the owning vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/community/workspace-definitions/{vendor}/{slug}/{version}": { - "get": { - "tags": [ - "Community" - ], - "summary": "Fetch a published v1 Workspace Definition version.", - "description": "Fetch the manifest of a specific community workspace definition version.", - "operationId": "get_workspace_definition", - "parameters": [ - { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "in": "path", - "description": "Workspace definition slug", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Exact semver", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Manifest", - "content": { - "application/json": { - "schema": {} - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "delete": { - "tags": [ - "Community" - ], - "summary": "Delete a published v1 Workspace Definition version.", - "description": "Delete a specific version of a community workspace definition.", - "operationId": "delete_workspace_definition", - "parameters": [ - { - "name": "vendor", - "in": "path", - "description": "Vendor (lowercase)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "in": "path", - "description": "Workspace definition slug", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Exact semver", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace definition version deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - }, - "403": { - "description": "Not the vendor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/dashboard": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "Get composite dashboard data.", - "description": "Account dashboard summary: workspace counts, statuses, and resource totals at a glance.", - "operationId": "get_dashboard", - "responses": { - "200": { - "description": "Dashboard data including workspaces, apps, limits, and AI credits", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetDashboardResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/deploy/preview": { - "get": { - "tags": [ - "Deploy" - ], - "summary": "Preview an exact Official, private owner, or allowed community deploy ref.", - "description": "Preview what an exact deploy ref will launch before committing to it.", - "operationId": "preview_deploy", - "parameters": [ - { - "name": "ref", - "in": "query", - "description": "Exact deploy ref, e.g. @rigbox/filebrowser@builtin or @alice/pgweb@1.2.3", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Deploy preview", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeployPreviewResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/deploy/workspace-definitions/preview": { - "get": { - "tags": [ - "Community" - ], - "summary": "Preview a workspace-definition deploy.", - "description": "Preview the deploy plan for a community workspace definition reference.", - "operationId": "preview_workspace_definition_v1", - "parameters": [ - { - "name": "ref", - "in": "query", - "description": "Exact workspace definition ref, e.g. @alice/stack@1.0.0", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace definition deploy preview", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceDefinitionPreviewResponse" - } - } - } - }, - "403": { - "description": "Feature not enabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "404": { - "description": "Definition not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/feature-flags": { - "get": { - "tags": [ - "System" - ], - "summary": "Get feature flags resolved for the calling user.", - "description": "Get the set of feature flags enabled for the calling user.", - "operationId": "get_feature_flags", - "responses": { - "200": { - "description": "Feature flags for the calling user", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FeatureFlagsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/metrics": { - "post": { - "tags": [ - "CLI" - ], - "summary": "Ingest CLI OTLP metric exports.", - "description": "Ingest an OTLP/HTTP protobuf metric export from the rig CLI and forward it to the collector.", - "operationId": "ingest_metrics", - "requestBody": { - "description": "OTLP/HTTP protobuf metric export", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Metrics accepted and forwarded to the collector" - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/quick-deploy": { - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Create a workspace from a template.", - "description": "Create and boot a workspace from a template in a single call.", - "operationId": "quick_deploy", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/QuickDeployRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Workspace created from template", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/QuickDeployResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/roadmap/votes": { - "get": { - "tags": [ - "Roadmap" - ], - "summary": "Get all roadmap vote counts.", - "description": "Get roadmap feature vote counts, plus the caller's own votes if authenticated.", - "operationId": "get_roadmap_votes", - "responses": { - "200": { - "description": "Roadmap vote counts and optional user votes", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetRoadmapVotesResponse" - } - } - } - } - } - } - }, - "/api/v1/roadmap/votes/{feature_key}": { - "post": { - "tags": [ - "Roadmap" - ], - "summary": "Toggle your vote on a roadmap feature.", - "description": "Toggle the caller's vote on a roadmap feature on or off.", - "operationId": "toggle_roadmap_vote", - "parameters": [ - { - "name": "feature_key", - "in": "path", - "description": "Feature key to toggle vote on", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Vote toggled successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToggleVoteResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/service-specs": { - "get": { - "tags": [ - "Service Specs" - ], - "summary": "List all service specs.", - "description": "List all service specs belonging to the authenticated user.", - "operationId": "list_service_specs", - "responses": { - "200": { - "description": "List of service specs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceSpecsListResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "tags": [ - "Service Specs" - ], - "summary": "Create a new service spec.", - "description": "Create a new reusable service spec on the user's account.", - "operationId": "create_service_spec", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateServiceSpecRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Service spec created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceSpecResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/service-specs/{id}": { - "get": { - "tags": [ - "Service Specs" - ], - "summary": "Get a service spec by ID.", - "description": "Get details for a single service spec by ID.", - "operationId": "get_service_spec", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Service spec ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Service spec details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceSpecResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "put": { - "tags": [ - "Service Specs" - ], - "summary": "Update a service spec.", - "description": "Update an existing service spec by ID.", - "operationId": "update_service_spec", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Service spec ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateServiceSpecRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Service spec updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceSpecResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "delete": { - "tags": [ - "Service Specs" - ], - "summary": "Delete a service spec.", - "description": "Delete a service spec from the user's account by ID.", - "operationId": "delete_service_spec", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Service spec ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Service spec deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/setup-scripts": { - "get": { - "tags": [ - "Setup Scripts" - ], - "summary": "List all setup scripts.", - "description": "List all setup scripts belonging to the authenticated user.", - "operationId": "list_setup_scripts", - "responses": { - "200": { - "description": "List of setup scripts", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupScriptsListResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "tags": [ - "Setup Scripts" - ], - "summary": "Create a new setup script.", - "description": "Create a new reusable setup script on the user's account.", - "operationId": "create_setup_script", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSetupScriptRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Setup script created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupScriptResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/setup-scripts/{id}": { - "get": { - "tags": [ - "Setup Scripts" - ], - "summary": "Get a setup script by ID.", - "description": "Get details for a single setup script by ID.", - "operationId": "get_setup_script", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Script ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Setup script details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupScriptResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "put": { - "tags": [ - "Setup Scripts" - ], - "summary": "Update a setup script.", - "description": "Update an existing setup script by ID.", - "operationId": "update_setup_script", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Script ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSetupScriptRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Setup script updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupScriptResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "delete": { - "tags": [ - "Setup Scripts" - ], - "summary": "Delete a setup script.", - "description": "Delete a setup script from the user's account by ID.", - "operationId": "delete_setup_script", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Script ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Setup script deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/snapshots": { - "get": { - "tags": [ - "Snapshots" - ], - "summary": "Cursor-paginated list of all snapshots owned by the authenticated user\n(independent of workspace existence).", - "description": "List all snapshots owned by the authenticated user across workspaces.", - "operationId": "list_user_snapshots", - "parameters": [ - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "User snapshots page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Page_SnapshotView" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/snapshots/{snapshot_id}": { - "delete": { - "tags": [ - "Snapshots" - ], - "summary": "Delete a snapshot by ID.", - "description": "Delete one of the user's snapshots by ID and its disk file.", - "operationId": "delete_user_snapshot", - "parameters": [ - { - "name": "snapshot_id", - "in": "path", - "description": "Snapshot ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Snapshot deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/snapshots/{snapshot_id}/restore": { - "post": { - "tags": [ - "Snapshots" - ], - "summary": "Restore a workspace from a snapshot.", - "description": "Restore a workspace's disk from one of the user's snapshots by ID.", - "operationId": "restore_user_snapshot", - "parameters": [ - { - "name": "snapshot_id", - "in": "path", - "description": "Snapshot ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Snapshot restored", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RestoreSnapshotResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/ssh-keys": { - "get": { - "tags": [ - "SSH Keys" - ], - "summary": "List SSH keys for the authenticated user.", - "description": "List the SSH keys registered on the authenticated user's account.", - "operationId": "list_ssh_keys", - "responses": { - "200": { - "description": "List of user SSH keys", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SshKeysResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "tags": [ - "SSH Keys" - ], - "summary": "Add an SSH key to your account.\nThe key is automatically synced to all running workspaces.", - "description": "Add an SSH key to your account and sync it to running workspaces.", - "operationId": "add_ssh_key", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddSshKeyRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "SSH key added", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SshKey" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/ssh-keys/{id}": { - "delete": { - "tags": [ - "SSH Keys" - ], - "summary": "Delete an SSH key from your account.\nThe key is automatically removed from all running workspaces.", - "description": "Delete an SSH key and remove it from all running workspaces.", - "operationId": "delete_ssh_key", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "SSH key ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "SSH key deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/templates": { - "get": { - "tags": [ - "Templates" - ], - "summary": "List available workspace templates.", - "description": "List all workspace templates available for creating new workspaces.", - "operationId": "list_templates", - "responses": { - "200": { - "description": "List of available workspace templates", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TemplatesResponse" - } - } - } - } - } - } - }, - "/api/v1/traces": { - "post": { - "tags": [ - "CLI" - ], - "summary": "Ingest CLI OTLP trace exports.", - "description": "Ingest an OTLP/HTTP protobuf trace export from the rig CLI and forward it to the collector.", - "operationId": "ingest_traces", - "requestBody": { - "description": "OTLP/HTTP protobuf trace export", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Traces accepted and forwarded to the collector" - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/ai-defaults": { - "get": { - "tags": [ - "AI" - ], - "summary": "Get account-level AI defaults.", - "description": "Get the account-level default AI mode, provider, and model.", - "operationId": "get_user_ai_defaults", - "responses": { - "200": { - "description": "User AI defaults", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAiDefaultsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "put": { - "tags": [ - "AI" - ], - "summary": "Update account-level AI defaults.", - "description": "Update the account-level default AI mode, provider, and model.", - "operationId": "update_user_ai_defaults", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAiDefaultsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated AI defaults", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAiDefaultsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/ai-mode": { - "put": { - "tags": [ - "AI" - ], - "summary": "Update AI mode for the authenticated user.", - "description": "Update the account AI mode (deprecated; use ai-defaults instead).", - "operationId": "update_ai_mode", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAiModeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated AI mode", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiCredits" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/ai-usage": { - "get": { - "tags": [ - "AI" - ], - "summary": "Get AI usage history and workspace breakdown.", - "description": "Get AI usage history and per-workspace breakdown for the account.", - "operationId": "get_ai_usage", - "responses": { - "200": { - "description": "AI usage history", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAiUsageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/ai-usage/metrics": { - "get": { - "tags": [ - "AI" - ], - "summary": "Get account AI usage metric series.", - "description": "Time series of the account's AI token and credit usage for charts.", - "operationId": "get_account_ai_usage_metrics", - "parameters": [ - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsRange" - } - } - ], - "responses": { - "200": { - "description": "Account AI usage metrics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/ai-usage/metrics/summary": { - "get": { - "tags": [ - "AI" - ], - "summary": "Get account AI usage metric summary.", - "description": "Aggregated AI usage totals for the account over the selected time window.", - "operationId": "get_account_ai_usage_metrics_summary", - "parameters": [ - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsRange" - } - } - ], - "responses": { - "200": { - "description": "Account AI usage metrics summary", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsSummaryResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/credits": { - "get": { - "tags": [ - "AI" - ], - "summary": "Get AI credit balance for the authenticated user.", - "description": "Get the authenticated user's current AI credit balance.", - "operationId": "get_ai_credits", - "responses": { - "200": { - "description": "AI credit balance", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiCredits" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/limits": { - "get": { - "tags": [ - "AI" - ], - "summary": "Get effective account limits and current usage.", - "description": "Get the account's effective plan limits alongside current resource usage.", - "operationId": "get_user_limits", - "responses": { - "200": { - "description": "User limits and usage", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetUserLimitsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/regions": { - "get": { - "tags": [ - "User Settings" - ], - "summary": "List available regions.", - "description": "List the regions available for placing new workspaces.", - "operationId": "list_available_regions", - "responses": { - "200": { - "description": "Available regions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListRegionsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/users/me/settings": { - "get": { - "tags": [ - "User Settings" - ], - "summary": "Get user settings.", - "description": "Get the authenticated user's account preferences and defaults.", - "operationId": "get_user_settings", - "responses": { - "200": { - "description": "User settings", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetUserSettingsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "put": { - "tags": [ - "User Settings" - ], - "summary": "Update user settings.", - "description": "Update the authenticated user's account preferences and defaults.", - "operationId": "update_user_settings", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateUserSettingsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated user settings", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetUserSettingsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "List all workspaces.", - "description": "List all workspaces on your account with their status and resources.", - "operationId": "list_vms", - "parameters": [ - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspaces page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Page_Vm" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Create a new workspace.", - "description": "Provision a new workspace; it starts stopped, then boot it separately.", - "operationId": "create_vm", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWorkspaceRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Workspace created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/from-definition": { - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Deploy a workspace from a v1 definition.", - "description": "Deploy a workspace from a v1 definition, provisioning its image and app recipes.", - "operationId": "deploy_from_definition", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeployFromDefinitionRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Workspace definition accepted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/QuickDeployResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "Get a workspace by ID.", - "description": "Fetch one workspace's full state, resources, and installed apps by ID.", - "operationId": "get_vm", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "delete": { - "tags": [ - "Workspaces" - ], - "summary": "Delete a workspace.", - "description": "Permanently delete a workspace and its VM; this cannot be undone.", - "operationId": "delete_vm", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "force", - "in": "query", - "description": "Force delete when allowed", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Workspace deletion queued", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/ai-usage/metrics": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "Get workspace AI usage metric series.", - "description": "Time series of the workspace's AI token and credit usage for charts.", - "operationId": "get_workspace_ai_usage_metrics", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsRange" - } - } - ], - "responses": { - "200": { - "description": "Workspace AI usage metrics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/ai-usage/metrics/summary": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "Get workspace AI usage metric summary.", - "description": "Aggregated AI usage totals for the workspace over the selected time window.", - "operationId": "get_workspace_ai_usage_metrics_summary", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsRange" - } - } - ], - "responses": { - "200": { - "description": "Workspace AI usage metrics summary", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiUsageMetricsSummaryResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/cancel": { - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Cancel a provisioning workspace.", - "description": "Cancel a workspace that is still provisioning or starting up.", - "operationId": "cancel_vm", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace creation cancelled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/deploy/launch": { - "post": { - "tags": [ - "Deploy" - ], - "summary": "Launch an exact Official, private owner, or allowed community deploy ref into a workspace.", - "description": "Launch an exact deploy ref into a workspace as a running app.", - "operationId": "launch_deploy", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LaunchDeployRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Deploy launched", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeployLaunchResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/deploy/launch-from-manifest": { - "post": { - "tags": [ - "Deploy" - ], - "summary": "Install a recipe from an inline manifest, bypassing the registry.", - "description": "Launch a deploy into a workspace from an inline rig.yaml manifest.", - "operationId": "launch_deploy_from_manifest", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LaunchFromManifestRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Deploy launched", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeployLaunchResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/env": { - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Update environment variables for a workspace.\nChanges take effect immediately if the workspace is running.", - "description": "Replace workspace environment variables; a running workspace picks up changes immediately.", - "operationId": "update_workspace_env", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateWorkspaceEnvRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Environment variables updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/expose-port": { - "post": { - "tags": [ - "Apps" - ], - "summary": "Detect or expose a port as a routable app.", - "description": "Expose a workspace port as a routable app with a public subdomain.", - "operationId": "expose_port", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExposePortRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Port exposed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExposePortResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/install-app": { - "post": { - "tags": [ - "App Catalog" - ], - "summary": "Install a catalog app into a workspace.", - "description": "Install a catalog app into a workspace and wait for it to come up.", - "operationId": "install_app", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InstallAppRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Catalog app installed successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InstallAppResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/jobs/{job_id}": { - "get": { - "tags": [ - "App Catalog" - ], - "summary": "Poll the status of an async app install job.", - "description": "Poll the status of an asynchronous app install job.", - "operationId": "get_job_status", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "job_id", - "in": "path", - "description": "Job ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Job status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JobStatusResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/listening-ports": { - "get": { - "tags": [ - "Apps" - ], - "summary": "List ports with active listeners in a workspace.", - "description": "List ports with active listeners in the workspace, flagging already-exposed ones.", - "operationId": "get_listening_ports", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Listening ports", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListListeningPortsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/logs": { - "get": { - "tags": [ - "Logs" - ], - "summary": "Fetch structured logs from a workspace.", - "description": "Fetch recent structured service logs from the workspace VM.", - "operationId": "get_workspace_logs", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace logs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceLogsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/logs/stream": { - "get": { - "tags": [ - "Logs" - ], - "summary": "Stream workspace logs via Server-Sent Events.", - "description": "Stream the workspace's service logs live via Server-Sent Events.", - "operationId": "stream_workspace_logs", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "SSE log stream" - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/metrics": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "Get live resource metrics for a workspace.", - "description": "Live CPU, memory, and disk usage for the running workspace VM.", - "operationId": "get_workspace_metrics", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace resource metrics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceMetrics" - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/metrics/series": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "Get workspace resource metric series.", - "description": "Time series of the workspace's CPU, memory, and disk usage.", - "operationId": "get_workspace_metrics_series", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/WorkspaceMetricsRange" - } - } - ], - "responses": { - "200": { - "description": "Workspace metrics series", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceMetricsSeriesResponse" - } - } - } - }, - "502": { - "description": "Prometheus returned an invalid response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "503": { - "description": "Prometheus unavailable", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/metrics/summary": { - "get": { - "tags": [ - "Workspaces" - ], - "summary": "Get workspace resource metric summary.", - "description": "Aggregated resource-usage summary for the workspace over the selected time window.", - "operationId": "get_workspace_metrics_summary", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Metrics range: 1h, 6h, 24h, or 7d", - "required": false, - "schema": { - "$ref": "#/components/schemas/WorkspaceMetricsRange" - } - } - ], - "responses": { - "200": { - "description": "Workspace metrics summary", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceMetricsSummaryResponse" - } - } - } - }, - "502": { - "description": "Prometheus returned an invalid response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - }, - "503": { - "description": "Prometheus unavailable", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiErrorBody" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/mode": { - "get": { - "tags": [ - "AI" - ], - "summary": "Get the effective AI mode for a workspace.", - "description": "Get the effective AI mode for the workspace and its source.", - "operationId": "get_workspace_ai_mode", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Effective AI mode", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceAiModeResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "put": { - "tags": [ - "AI" - ], - "summary": "Set or clear the per-workspace AI mode override.", - "description": "Set or clear the per-workspace AI mode override, hot-reloading when running.", - "operationId": "update_workspace_ai_mode", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateWorkspaceAiModeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated AI mode", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceAiModeResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/reconcile-apps": { - "post": { - "tags": [ - "Apps" - ], - "summary": "Reconcile apps for a workspace against a template.", - "description": "Reconcile a workspace's apps against its resolved template definition.", - "operationId": "reconcile_apps", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Apps reconciled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReconcileAppsResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/resources": { - "put": { - "tags": [ - "Workspaces" - ], - "summary": "Update workspace resources.", - "description": "Resize the workspace's RAM, vCPU, and disk; it must be stopped first.", - "operationId": "update_workspace_resources", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace resources updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResizeWorkspaceResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/retry": { - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Retry a failed workspace.", - "description": "Retry provisioning for a workspace that previously failed to come up.", - "operationId": "retry_vm", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace retry queued", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/services": { - "get": { - "tags": [ - "Workspace Services" - ], - "summary": "List all workspace services with health status.", - "description": "List all services running in a workspace with their health status.", - "operationId": "list_services", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of workspace services", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceServicesResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/services/{name}": { - "get": { - "tags": [ - "Workspace Services" - ], - "summary": "Get a single workspace service by name.", - "description": "Get details for a single workspace service identified by name.", - "operationId": "get_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "name", - "in": "path", - "description": "Service name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Service details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkspaceService" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/services/{name}/logs": { - "get": { - "tags": [ - "Workspace Services" - ], - "summary": "Fetch logs for a specific workspace service by name.", - "description": "Fetch recent log lines for a named workspace service.", - "operationId": "get_service_logs", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "name", - "in": "path", - "description": "Service name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Service logs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceLogsResponse" - } - } - } - }, - "400": { - "description": "Service has no systemd unit" - }, - "404": { - "description": "Service not found" - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/snapshots": { - "get": { - "tags": [ - "Snapshots" - ], - "summary": "Cursor-paginated list of snapshots for one workspace.", - "description": "List the disk snapshots captured for this workspace, newest first.", - "operationId": "list_workspace_snapshots", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace snapshots page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Page_SnapshotView" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "tags": [ - "Snapshots" - ], - "summary": "Create a snapshot of a workspace.", - "description": "Create a snapshot of the workspace's disk for later restore.", - "operationId": "create_workspace_snapshot", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSnapshotRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Snapshot created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSnapshotResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/snapshots/{snapshot_id}": { - "delete": { - "tags": [ - "Snapshots" - ], - "summary": "Delete a workspace snapshot.", - "description": "Delete one snapshot belonging to this workspace and its disk file.", - "operationId": "delete_workspace_snapshot", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "snapshot_id", - "in": "path", - "description": "Snapshot ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Snapshot deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/snapshots/{snapshot_id}/restore": { - "post": { - "tags": [ - "Snapshots" - ], - "summary": "Restore a workspace from a snapshot.", - "description": "Restore the workspace's disk from a snapshot; it must be stopped.", - "operationId": "restore_workspace_snapshot", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "snapshot_id", - "in": "path", - "description": "Snapshot ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Snapshot restored", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RestoreSnapshotResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/ssh-keys": { - "get": { - "tags": [ - "SSH Keys" - ], - "summary": "Cursor-paginated list of SSH keys currently in the workspace.", - "description": "List the SSH public keys currently authorized on the running workspace.", - "operationId": "list_workspace_ssh_keys", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "max_results", - "in": "query", - "description": "Maximum number of items to return. Defaults to 50; values are clamped to the range 1\u2013200.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor returned by a prior call's `next_cursor`. Omit on the\nfirst page.", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace SSH keys page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Page_SshKeyEntry" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/ssh-keys/sync": { - "post": { - "tags": [ - "SSH Keys" - ], - "summary": "Sync all account SSH keys to the workspace.", - "description": "Sync all of the account's SSH keys onto the running workspace.", - "operationId": "sync_workspace_ssh_keys", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "SSH keys synced", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SyncSshKeysResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/start": { - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Start a workspace.", - "description": "Boot the workspace VM and wait until it reports running.", - "operationId": "start_vm", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace start queued", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/stop": { - "post": { - "tags": [ - "Workspaces" - ], - "summary": "Stop a workspace.", - "description": "Stop the workspace VM while preserving its disk and configuration.", - "operationId": "stop_vm", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace stop queued", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetWorkspaceResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/tools": { - "get": { - "tags": [ - "Tools" - ], - "summary": "List available tools and their status for a workspace.", - "description": "List the tools available in a workspace along with their status.", - "operationId": "list_tools", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of available workspace tools with status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToolsListResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/tools/{tool}/install": { - "post": { - "tags": [ - "Tools" - ], - "summary": "Install a tool asynchronously.", - "description": "Dispatch installation of a tool into a workspace.", - "operationId": "install_tool", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "tool", - "in": "path", - "description": "Tool ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Tool install dispatched", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToolInstallResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/tools/{tool}/install-status": { - "get": { - "tags": [ - "Tools" - ], - "summary": "Poll the status of an async tool install job.", - "description": "Poll the install status of a tool in a workspace.", - "operationId": "get_tool_install_status", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "tool", - "in": "path", - "description": "Tool ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Tool install status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToolInstallStatusResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/tools/{tool}/launch": { - "post": { - "tags": [ - "Tools" - ], - "summary": "Launch a tool in the workspace.", - "description": "Launch a tool inside a workspace and return its launch result.", - "operationId": "launch_tool", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "tool", - "in": "path", - "description": "Tool ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LaunchRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Tool launch result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToolLaunchResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/tools/{tool}/status": { - "get": { - "tags": [ - "Tools" - ], - "summary": "Get the status of a specific tool.", - "description": "Get the current status of a specific tool in a workspace.", - "operationId": "get_tool_status", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "tool", - "in": "path", - "description": "Tool ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Tool status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToolStatus" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/tools/{tool}/stop": { - "post": { - "tags": [ - "Tools" - ], - "summary": "Stop a running tool.", - "description": "Stop a running tool in a workspace.", - "operationId": "stop_tool", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "tool", - "in": "path", - "description": "Tool ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Tool stopped", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToolStopResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/volumes": { - "get": { - "tags": [ - "Volumes" - ], - "summary": "List a workspace's persistent volumes.", - "description": "List the persistent volumes attached to this workspace.", - "operationId": "list_workspace_volumes", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Workspace volumes", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListVolumesResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "tags": [ - "Volumes" - ], - "summary": "Create a persistent volume on a workspace.", - "description": "Create a persistent volume mounted into this workspace at a path.", - "operationId": "create_workspace_volume", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateVolumeRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Volume created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VolumeResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/volumes/{volume_id}": { - "delete": { - "tags": [ - "Volumes" - ], - "summary": "Delete a persistent volume from a workspace.", - "description": "Delete a persistent volume from this workspace; it must be stopped.", - "operationId": "delete_workspace_volume", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "volume_id", - "in": "path", - "description": "Volume ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Volume deleted" - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/v1/workspaces/{id}/volumes/{volume_id}/resize": { - "post": { - "tags": [ - "Volumes" - ], - "summary": "Resize a persistent volume on a workspace.", - "description": "Grow a persistent volume on this workspace; it must be stopped.", - "operationId": "resize_workspace_volume", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "volume_id", - "in": "path", - "description": "Volume ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResizeVolumeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Volume resized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VolumeResponse" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - } - }, - "/api/ws/terminal/{id}": { - "get": { - "tags": [ - "Workspace Runtime" - ], - "summary": "WebSocket terminal handler - upgrades HTTP to WebSocket", - "operationId": "ws_terminal_handler", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Workspace ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "token", - "in": "query", - "description": "JWT token for websocket authentication", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "cols", - "in": "query", - "description": "Initial terminal columns", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "rows", - "in": "query", - "description": "Initial terminal rows", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - ], - "responses": { - "101": { - "description": "WebSocket terminal upgrade" - } - }, - "security": [ - { - "bearer": [] - } - ] - } - } - }, - "components": { - "schemas": { - "AccessBinding": { - "type": "object", - "required": [ - "principal_ref", - "resource_ref", - "role", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "created_by_ref": { - "type": [ - "string", - "null" - ] - }, - "principal_ref": { - "type": "string" - }, - "resource_ref": { - "type": "string" - }, - "role": { - "type": "string" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "AccessControlDeleteResponse": { - "type": "object", - "required": [ - "deleted" - ], - "properties": { - "deleted": { - "type": "boolean" - } - } - }, - "AddSshKeyRequest": { - "type": "object", - "required": [ - "name", - "public_key" - ], - "properties": { - "name": { - "type": "string" - }, - "public_key": { - "type": "string" - } - } - }, - "AgentStatusResponse": { - "type": "object", - "required": [ - "workspace_id", - "workspace_status", - "vsock_socket_present", - "agent_available", - "fallback_transport" - ], - "properties": { - "agent_available": { - "type": "boolean" - }, - "detail": { - "type": [ - "string", - "null" - ] - }, - "fallback_transport": { - "type": "string" - }, - "ip_address": { - "type": [ - "string", - "null" - ] - }, - "vsock_socket_present": { - "type": "boolean" - }, - "workspace_id": { - "type": "string" - }, - "workspace_status": { - "type": "string" - } - } - }, - "AiCredits": { - "type": "object", - "required": [ - "remaining", - "total", - "remaining_micro", - "total_micro", - "free", - "pro", - "free_micro", - "pro_micro", - "mode" - ], - "properties": { - "free": { - "type": "number", - "format": "double", - "description": "Free bucket balance (resets to 250 each month, unused expires)." - }, - "free_micro": { - "type": "integer", - "format": "int64" - }, - "mode": { - "type": "string" - }, - "pro": { - "type": "number", - "format": "double", - "description": "Pro bucket balance (active pro_managed gets +2000/month, rolls over)." - }, - "pro_micro": { - "type": "integer", - "format": "int64" - }, - "remaining": { - "type": "number", - "format": "double", - "description": "Total spendable credits = free + pro." - }, - "remaining_micro": { - "type": "integer", - "format": "int64" - }, - "total": { - "type": "number", - "format": "double", - "description": "Credits granted this cycle (the monthly entitlement: 250 free, plus 2000\nfor an active pro_managed subscriber). May be below `remaining` when pro\ncredits have rolled over from prior months." - }, - "total_micro": { - "type": "integer", - "format": "int64" - } - } - }, - "AiUsageDaily": { - "type": "object", - "required": [ - "day", - "input_tokens", - "output_tokens", - "credits", - "credits_micro", - "requests" - ], - "properties": { - "credits": { - "type": "number", - "format": "double" - }, - "credits_micro": { - "type": "integer", - "format": "int64" - }, - "day": { - "type": "string" - }, - "input_tokens": { - "type": "integer", - "format": "int64" - }, - "output_tokens": { - "type": "integer", - "format": "int64" - }, - "requests": { - "type": "integer", - "format": "int64" - } - } - }, - "AiUsageMetricsRange": { - "type": "string", - "enum": [ - "1h", - "6h", - "24h", - "7d" - ] - }, - "AiUsageMetricsResponse": { - "type": "object", - "required": [ - "range", - "step_seconds", - "series" - ], - "properties": { - "range": { - "$ref": "#/components/schemas/AiUsageMetricsRange" - }, - "series": { - "$ref": "#/components/schemas/AiUsageMetricsSeries" - }, - "step_seconds": { - "type": "integer", - "format": "int64" - }, - "workspace_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "AiUsageMetricsSeries": { - "type": "object", - "required": [ - "credits", - "requests", - "input_tokens", - "output_tokens" - ], - "properties": { - "credits": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "input_tokens": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "output_tokens": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "requests": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - } - } - }, - "AiUsageMetricsSummaryResponse": { - "type": "object", - "required": [ - "range", - "total_credits", - "total_credits_micro", - "total_requests", - "input_tokens", - "output_tokens" - ], - "properties": { - "input_tokens": { - "type": "integer", - "format": "int64" - }, - "output_tokens": { - "type": "integer", - "format": "int64" - }, - "range": { - "$ref": "#/components/schemas/AiUsageMetricsRange" - }, - "total_credits": { - "type": "number", - "format": "double" - }, - "total_credits_micro": { - "type": "integer", - "format": "int64" - }, - "total_requests": { - "type": "integer", - "format": "int64" - }, - "workspace_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "AiUsageWorkspaceTotal": { - "type": "object", - "required": [ - "workspace_id", - "workspace_name", - "input_tokens", - "output_tokens", - "credits", - "credits_micro", - "requests" - ], - "properties": { - "credits": { - "type": "number", - "format": "double" - }, - "credits_micro": { - "type": "integer", - "format": "int64" - }, - "input_tokens": { - "type": "integer", - "format": "int64" - }, - "output_tokens": { - "type": "integer", - "format": "int64" - }, - "requests": { - "type": "integer", - "format": "int64" - }, - "workspace_id": { - "type": "string" - }, - "workspace_name": { - "type": "string" - } - } - }, - "ApiApp": { - "type": "object", - "description": "OpenAPI-facing mirror of the canonical app payload.\n\nResponse types can keep serializing `rig_data_store::models::App` while\npointing schema generation at this local mirror to avoid cross-crate derive\ncoupling in `utoipa`.", - "required": [ - "id", - "name", - "subdomain", - "user_id", - "node_id", - "workspace_id", - "port", - "visibility", - "allowed_emails", - "status", - "metadata", - "system_tags", - "protocol", - "app_kind", - "managed", - "depends_on", - "custom_domain_verified", - "created_at", - "updated_at" - ], - "properties": { - "allowed_emails": { - "type": "array", - "items": { - "type": "string" - } - }, - "app_kind": { - "type": "string" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "custom_domain": { - "type": [ - "string", - "null" - ] - }, - "custom_domain_verified": { - "type": "boolean" - }, - "depends_on": { - "type": "array", - "items": { - "type": "string" - } - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "string" - }, - "managed": { - "type": "boolean" - }, - "metadata": {}, - "name": { - "type": "string" - }, - "node_id": { - "type": "string" - }, - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "protocol": { - "type": "string" - }, - "status": { - "$ref": "#/components/schemas/AppStatus" - }, - "subdomain": { - "type": "string" - }, - "system_tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "user_id": { - "type": "string" - }, - "visibility": { - "$ref": "#/components/schemas/Visibility" - }, - "workspace_id": { - "type": "string" - } - } - }, - "ApiErrorBody": { - "type": "object", - "description": "JSON body returned for all errors.", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/components/schemas/ApiErrorDetail" - } - } - }, - "ApiErrorDetail": { - "type": "object", - "required": [ - "code", - "message" - ], - "properties": { - "code": { - "type": "string" - }, - "details": {}, - "message": { - "type": "string" - } - } - }, - "ApiKeyResponse": { - "type": "object", - "required": [ - "id", - "key_preview", - "created_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "id": { - "type": "string" - }, - "key_preview": { - "type": "string" - }, - "last_used_at": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "App": { - "type": "object", - "required": [ - "id", - "name", - "subdomain", - "user_id", - "node_id", - "workspace_id", - "port", - "visibility", - "allowed_emails", - "status", - "created_at", - "updated_at" - ], - "properties": { - "allowed_emails": { - "type": "array", - "items": { - "type": "string" - } - }, - "app_kind": { - "type": "string" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "custom_domain": { - "type": [ - "string", - "null" - ] - }, - "custom_domain_verified": { - "type": "boolean" - }, - "depends_on": { - "type": "array", - "items": { - "type": "string" - } - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "string" - }, - "managed": { - "type": "boolean" - }, - "metadata": {}, - "name": { - "type": "string" - }, - "node_id": { - "type": "string" - }, - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "protocol": { - "type": "string" - }, - "status": { - "$ref": "#/components/schemas/AppStatus" - }, - "subdomain": { - "type": "string" - }, - "system_tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "user_id": { - "type": "string" - }, - "visibility": { - "$ref": "#/components/schemas/Visibility" - }, - "workspace_id": { - "type": "string" - } - } - }, - "AppCatalogItem": { - "type": "object", - "required": [ - "id", - "name", - "description", - "icon", - "category", - "min_ram_mb", - "min_disk_mb" - ], - "properties": { - "app_kind": { - "$ref": "#/components/schemas/AppKind", - "description": "What kind of app this is. `Service` (default) is the daemon shape\nevery existing recipe uses. `Cli` skips systemd unit, Caddy route,\nand readiness probe \u2014 only the install script runs. See `AppKind`." - }, - "category": { - "type": "string" - }, - "configurable_params": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamSpec" - }, - "description": "User-configurable parameters for this app.\nValues are submitted at install time and resolved via `{PARAM_}`\nplaceholders in install scripts, exec_start, and config files." - }, - "description": { - "type": "string" - }, - "destructive_delete": { - "type": "boolean", - "description": "If true, deletion destroys user-modifiable files (e.g. scaffolded starter code).\nRequires `?force_delete=true` and the UI renders extra confirmation\n(type app name or check a warning box)." - }, - "icon": { - "type": "string" - }, - "id": { - "type": "string" - }, - "incompatible_templates": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Template IDs that already include this app (e.g. `[\"chat-app-starter\"]`).\nInstalling on workspaces created from these templates is blocked." - }, - "min_disk_mb": { - "type": "integer", - "format": "int32", - "description": "Minimum disk space hint (MB). Informational only - not enforced.", - "minimum": 0 - }, - "min_ram_mb": { - "type": "integer", - "format": "int32", - "description": "Minimum RAM hint (MB). Informational only - not enforced.", - "minimum": 0 - }, - "name": { - "type": "string" - }, - "preview": { - "type": "boolean", - "description": "Whether this item is in preview (feature-flagged)." - }, - "system_tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Author-declared discovery tags. Merged into the auto-generated\n`[\"catalog:{id}-{ws}\", \"catalog\"]` tags on the installed app." - } - } - }, - "AppHealthResponse": { - "type": "object", - "required": [ - "live", - "service_status", - "port_open" - ], - "properties": { - "live": { - "type": "boolean", - "description": "Whether the app responded to an HTTP probe." - }, - "port_drift": { - "type": "boolean", - "description": "True when the service is active but the expected port is not listening." - }, - "port_open": { - "type": "boolean", - "description": "Whether the expected port is listening inside the workspace." - }, - "service_status": { - "type": "string", - "description": "Systemd service status (e.g. \"active\", \"inactive\", \"unknown\", \"unmanaged\")." - } - } - }, - "AppKind": { - "oneOf": [ - { - "allOf": [ - { - "$ref": "#/components/schemas/ServiceSpec" - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "service" - ] - } - } - } - ] - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "cli" - ] - } - } - } - ], - "description": "Whether a catalog item is a long-running service or an interactive CLI.\n\n`Service(spec)` \u2014 historical default. The install script runs, a systemd\nunit is built from `spec.exec_start`, a Caddy route is registered against\n`spec.port` + `spec.subdomain_suffix`, and `spec.health` drives readiness.\nEvery existing recipe (Hermes dashboard, OpenClaw gateway, Jupyter, \u2026)\nis a `Service`. Hermes/OpenClaw are still Service items even though they\nalso install a user-invokable CLI \u2014 the registered catalog subject is the\ndaemon; the CLI in PATH is a side-effect of install.sh.\n\n`Cli` \u2014 install-only. The binary lives in `$PATH` and the user invokes it\ninteractively over SSH (claude, codex, opencode, kilocode, \u2026). No systemd\nunit, Caddy route, or health probe is produced. The App row is still\nregistered so the workspace UI shows the agent as installed." - }, - "AppLogSource": { - "type": "object", - "required": [ - "id", - "app_id", - "source_type", - "source_ref", - "is_primary", - "created_at", - "updated_at" - ], - "properties": { - "app_id": { - "type": "string" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "string" - }, - "is_primary": { - "type": "boolean" - }, - "source_ref": { - "type": "string" - }, - "source_type": { - "$ref": "#/components/schemas/AppLogSourceType" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "AppLogSourceType": { - "type": "string", - "enum": [ - "systemd_unit", - "docker_container", - "file_path" - ] - }, - "AppMetricsRange": { - "type": "string", - "enum": [ - "1h", - "6h", - "24h", - "7d" - ] - }, - "AppMetricsResponse": { - "type": "object", - "required": [ - "range", - "step_seconds", - "hosts", - "series", - "status_codes" - ], - "properties": { - "hosts": { - "type": "array", - "items": { - "type": "string" - } - }, - "range": { - "$ref": "#/components/schemas/AppMetricsRange" - }, - "series": { - "$ref": "#/components/schemas/AppMetricsSeries" - }, - "status_codes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AppStatusCodeMetric" - } - }, - "step_seconds": { - "type": "integer", - "format": "int64" - } - } - }, - "AppMetricsSeries": { - "type": "object", - "required": [ - "request_rate", - "error_rate_5xx", - "latency_p50_ms", - "latency_p95_ms", - "latency_p99_ms", - "bandwidth_out_bps" - ], - "properties": { - "bandwidth_out_bps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "error_rate_5xx": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "latency_p50_ms": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "latency_p95_ms": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "latency_p99_ms": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "request_rate": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - } - } - }, - "AppMetricsSummaryResponse": { - "type": "object", - "required": [ - "range", - "hosts", - "total_requests", - "total_errors_5xx", - "error_rate_5xx", - "request_rate_avg", - "latency_p50_ms", - "latency_p95_ms", - "latency_p99_ms", - "bandwidth_out_bytes" - ], - "properties": { - "bandwidth_out_bytes": { - "type": "number", - "format": "double" - }, - "error_rate_5xx": { - "type": "number", - "format": "double" - }, - "hosts": { - "type": "array", - "items": { - "type": "string" - } - }, - "latency_p50_ms": { - "type": "number", - "format": "double" - }, - "latency_p95_ms": { - "type": "number", - "format": "double" - }, - "latency_p99_ms": { - "type": "number", - "format": "double" - }, - "range": { - "$ref": "#/components/schemas/AppMetricsRange" - }, - "request_rate_avg": { - "type": "number", - "format": "double" - }, - "total_errors_5xx": { - "type": "number", - "format": "double" - }, - "total_requests": { - "type": "number", - "format": "double" - } - } - }, - "AppParamsResponse": { - "type": "object", - "required": [ - "specs", - "values" - ], - "properties": { - "specs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamSpec" - }, - "description": "The parameter schema (snapshotted at creation time)." - }, - "values": { - "type": "object", - "description": "Current values (from metadata.config). Sensitive values are masked.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "AppStatus": { - "type": "string", - "enum": [ - "active", - "inactive", - "installing", - "error" - ] - }, - "AppStatusCodeMetric": { - "type": "object", - "required": [ - "class", - "count", - "ratio" - ], - "properties": { - "class": { - "type": "string" - }, - "count": { - "type": "number", - "format": "double" - }, - "ratio": { - "type": "number", - "format": "double" - } - } - }, - "AppView": { - "allOf": [ - { - "$ref": "#/components/schemas/ApiApp" - } - ] - }, - "ApproveCliSessionResponse": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - } - }, - "AuthMessageResponse": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - }, - "AuthResponseWithUser": { - "type": "object", - "required": [ - "token", - "user" - ], - "properties": { - "must_change_password": { - "type": "boolean" - }, - "token": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/UserResponse" - } - } - }, - "BindingsResponse": { - "type": "object", - "required": [ - "bindings" - ], - "properties": { - "bindings": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AccessBinding" - } - } - } - }, - "CatalogResponse": { - "type": "object", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AppCatalogItem" - } - } - } - }, - "ChangePasswordRequest": { - "type": "object", - "required": [ - "current_password", - "new_password" - ], - "properties": { - "current_password": { - "type": "string" - }, - "new_password": { - "type": "string" - } - } - }, - "CheckEmailRequest": { - "type": "object", - "required": [ - "email" - ], - "properties": { - "email": { - "type": "string" - }, - "public_key": { - "type": [ - "string", - "null" - ] - } - } - }, - "CheckEmailResponse": { - "type": "object", - "required": [ - "exists", - "key_linked" - ], - "properties": { - "exists": { - "type": "boolean" - }, - "key_linked": { - "type": "boolean" - } - } - }, - "CheckKeyLinkedRequest": { - "type": "object", - "required": [ - "user_id", - "public_key" - ], - "properties": { - "public_key": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "CheckKeyLinkedResponse": { - "type": "object", - "required": [ - "linked" - ], - "properties": { - "linked": { - "type": "boolean" - } - } - }, - "CheckoutRequest": { - "type": "object", - "required": [ - "plan" - ], - "properties": { - "plan": { - "type": "string" - }, - "return_url": { - "type": [ - "string", - "null" - ] - } - } - }, - "ChildAppInstall": { - "type": "object", - "description": "Result of attempting to install a child app onto a workspace at\ndeploy time. Returned by the gateway's\n`enqueue_catalog_install_plans` for every catalog/community child\nplan, regardless of which deploy path (quick-deploy, v1 definition,\nor any future surface) created it.", - "required": [ - "deploy_ref", - "source", - "trust_tier", - "status" - ], - "properties": { - "app_id": { - "type": [ - "string", - "null" - ] - }, - "deploy_ref": { - "type": "string" - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": "string" - }, - "status": { - "type": "string" - }, - "trust_tier": { - "type": "string" - } - } - }, - "CommunityCatalogDetailResponse": { - "type": "object", - "required": [ - "item" - ], - "properties": { - "item": { - "$ref": "#/components/schemas/DeployPreviewResponse" - } - } - }, - "CommunityCatalogVersionInstallStats": { - "type": "object", - "required": [ - "version_id", - "total_installs", - "active_installs", - "unique_installers" - ], - "properties": { - "active_installs": { - "type": "integer", - "format": "int64" - }, - "last_installed_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "total_installs": { - "type": "integer", - "format": "int64" - }, - "unique_installers": { - "type": "integer", - "format": "int64" - }, - "version_id": { - "type": "string" - } - } - }, - "CommunityInstall": { - "type": "object", - "required": [ - "workspace_id", - "installer_user_id", - "version_id", - "installed_at" - ], - "properties": { - "installed_app_id": { - "type": [ - "string", - "null" - ] - }, - "installed_at": { - "type": "string", - "format": "date-time" - }, - "installer_user_id": { - "type": "string" - }, - "version_id": { - "type": "string" - }, - "workspace_id": { - "type": "string" - } - } - }, - "CommunityInstallResponse": { - "type": "object", - "required": [ - "install" - ], - "properties": { - "install": { - "$ref": "#/components/schemas/CommunityInstall" - } - } - }, - "CommunityProfile": { - "type": "object", - "required": [ - "user_id", - "community_items_preference" - ], - "properties": { - "community_items_preference": { - "type": "string" - }, - "user_id": { - "type": "string" - }, - "username": { - "type": [ - "string", - "null" - ] - } - } - }, - "CommunityProfileResponse": { - "type": "object", - "required": [ - "profile" - ], - "properties": { - "profile": { - "$ref": "#/components/schemas/CommunityProfile" - } - } - }, - "CommunityRegistryHealth": { - "type": "object", - "required": [ - "catalog_items", - "catalog_versions", - "published_versions", - "verified_versions", - "community_versions", - "private_versions", - "deprecated_versions", - "yanked_versions", - "total_installs", - "active_installs", - "unique_installers" - ], - "properties": { - "active_installs": { - "type": "integer", - "format": "int64" - }, - "catalog_items": { - "type": "integer", - "format": "int64" - }, - "catalog_versions": { - "type": "integer", - "format": "int64" - }, - "community_versions": { - "type": "integer", - "format": "int64" - }, - "deprecated_versions": { - "type": "integer", - "format": "int64" - }, - "private_versions": { - "type": "integer", - "format": "int64" - }, - "published_versions": { - "type": "integer", - "format": "int64" - }, - "total_installs": { - "type": "integer", - "format": "int64" - }, - "unique_installers": { - "type": "integer", - "format": "int64" - }, - "verified_versions": { - "type": "integer", - "format": "int64" - }, - "yanked_versions": { - "type": "integer", - "format": "int64" - } - } - }, - "CommunityRegistryHealthResponse": { - "type": "object", - "required": [ - "health" - ], - "properties": { - "health": { - "$ref": "#/components/schemas/CommunityRegistryHealth" - } - } - }, - "CompleteWithKeyRequest": { - "type": "object", - "required": [ - "token" - ], - "properties": { - "token": { - "type": "string" - } - } - }, - "CompleteWithKeyResponse": { - "type": "object", - "required": [ - "success", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "success": { - "type": "boolean" - } - } - }, - "CreateApiKeyRequest": { - "type": "object", - "properties": { - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "CreateApiKeyResponseFull": { - "type": "object", - "required": [ - "id", - "key" - ], - "properties": { - "id": { - "type": "string" - }, - "key": { - "type": "string" - } - } - }, - "CreateAppKind": { - "type": "string", - "enum": [ - "service", - "cli" - ] - }, - "CreateAppLogSourceRequest": { - "type": "object", - "required": [ - "source_type", - "source_ref" - ], - "properties": { - "display_name": { - "type": [ - "string", - "null" - ] - }, - "is_primary": { - "type": [ - "boolean", - "null" - ] - }, - "source_ref": { - "type": "string" - }, - "source_type": { - "type": "string" - } - } - }, - "CreateAppRequest": { - "type": "object", - "required": [ - "name", - "workspace_id" - ], - "properties": { - "app_kind": { - "$ref": "#/components/schemas/CreateAppKind" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "metadata": {}, - "name": { - "type": "string" - }, - "port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "protocol": { - "type": [ - "string", - "null" - ] - }, - "workspace_id": { - "type": "string" - } - } - }, - "CreateBindingRequest": { - "type": "object", - "required": [ - "principal", - "resource", - "role" - ], - "properties": { - "principal": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "role": { - "type": "string" - } - } - }, - "CreateCliSessionRequest": { - "type": "object", - "required": [ - "code" - ], - "properties": { - "code": { - "type": "string" - } - } - }, - "CreateCliSessionResponse": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - } - }, - "CreateServiceSpecRequest": { - "type": "object", - "required": [ - "name", - "exec_start" - ], - "properties": { - "auto_enable": { - "type": "boolean" - }, - "env_vars": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "environment_file": { - "type": [ - "string", - "null" - ] - }, - "exec_start": { - "type": "string" - }, - "name": { - "type": "string" - }, - "restart_policy": { - "type": "string" - }, - "setup_script": { - "type": [ - "string", - "null" - ] - } - } - }, - "CreateSetupScriptRequest": { - "type": "object", - "required": [ - "name", - "content" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "run_on": { - "type": "string" - }, - "script_order": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "CreateSnapshotRequest": { - "type": "object", - "properties": { - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "CreateSnapshotResponse": { - "type": "object", - "required": [ - "snapshot" - ], - "properties": { - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - } - } - }, - "CreateVolumeRequest": { - "type": "object", - "required": [ - "name", - "size_mb", - "mount_path" - ], - "properties": { - "mount_path": { - "type": "string" - }, - "name": { - "type": "string" - }, - "size_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - }, - "CreateWorkspaceRequest": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "catalog_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "disk_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "image": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "ram_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "service_spec_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "setup_script_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "template_id": { - "type": [ - "string", - "null" - ] - }, - "vcpu_count": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - } - }, - "DeleteBindingRequest": { - "type": "object", - "required": [ - "principal", - "resource", - "role" - ], - "properties": { - "principal": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "role": { - "type": "string" - } - } - }, - "DeleteSnapshotFileRequest": { - "type": "object", - "required": [ - "file_path" - ], - "properties": { - "file_path": { - "type": "string" - } - } - }, - "DeleteSnapshotFileResponse": { - "type": "object", - "required": [ - "deleted", - "file_path" - ], - "properties": { - "deleted": { - "type": "boolean" - }, - "file_path": { - "type": "string" - } - } - }, - "DeployExposure": { - "type": "object", - "required": [ - "port", - "protocol", - "subdomain_suffix" - ], - "properties": { - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "protocol": { - "type": "string" - }, - "subdomain_suffix": { - "type": "string" - } - } - }, - "DeployFromDefinitionRequest": { - "type": "object", - "required": [ - "definition_ref" - ], - "properties": { - "app_params": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "propertyNames": { - "type": "string" - } - }, - "definition_ref": { - "type": "string" - }, - "disk_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "env_vars": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "ram_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "service_spec_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "setup_script_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "vcpu_count": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "workspace_name": { - "type": [ - "string", - "null" - ] - } - } - }, - "DeployLaunchResponse": { - "type": "object", - "required": [ - "deploy_ref", - "source", - "trust_tier", - "catalog_id", - "install" - ], - "properties": { - "catalog_id": { - "type": "string" - }, - "deploy_ref": { - "type": "string" - }, - "install": { - "$ref": "#/components/schemas/InstallAppResponse" - }, - "source": { - "type": "string" - }, - "trust_tier": { - "type": "string" - } - } - }, - "DeployPreviewResponse": { - "type": "object", - "required": [ - "deploy_ref", - "source", - "trust_tier", - "status", - "catalog_id", - "slug", - "version", - "name", - "description", - "icon", - "category", - "resources", - "app_kind", - "configurable_params", - "credentials_declared", - "warnings" - ], - "properties": { - "app_kind": { - "type": "string", - "description": "Whether this recipe is a daemon `\"service\"` (has port + Caddy route)\nor an interactive `\"cli\"` (install-only; user invokes via SSH).\nMirrors `AppKind` on the catalog item." - }, - "catalog_id": { - "type": "string" - }, - "category": { - "type": "string" - }, - "community_version_id": { - "type": [ - "string", - "null" - ] - }, - "configurable_params": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamSpec" - } - }, - "credentials_declared": { - "type": "boolean" - }, - "depends_on": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Backing services this app expects on the workspace (community only)." - }, - "deploy_ref": { - "type": "string", - "description": "Canonical exact ref that will be installed." - }, - "description": { - "type": "string" - }, - "exposure": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DeployExposure", - "description": "Daemon-shape exposure fields. Present only when `app_kind` is\n`\"service\"`. Omitted entirely for `\"cli\"` items \u2014 the UI should\nrender a CLI-shaped affordance with no port/protocol pill." - } - ] - }, - "icon": { - "type": "string" - }, - "install_script_preview": { - "type": [ - "string", - "null" - ] - }, - "install_stats": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CommunityCatalogVersionInstallStats" - } - ] - }, - "managed": { - "type": "boolean", - "description": "True if this recipe opts into Rigbox's managed AI proxy when installed." - }, - "manifest_digest": { - "type": [ - "string", - "null" - ] - }, - "manifest_json": { - "description": "Raw manifest JSON for the \"View manifest\" affordance. Community only." - }, - "name": { - "type": "string" - }, - "resources": { - "$ref": "#/components/schemas/DeployResourceRequirements" - }, - "slug": { - "type": "string" - }, - "source": { - "type": "string", - "description": "`official` or `community`." - }, - "status": { - "type": "string" - }, - "system_tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Discovery tags from the recipe manifest (community only)." - }, - "trust_tier": { - "type": "string", - "description": "`official`, `verified`, `community`, or `private`." - }, - "usage_examples": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UsageExample" - }, - "description": "Copy-pasteable usage examples shown in the catalog detail \"Usage\" tab." - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "version": { - "type": "string" - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "DeployResourceRequirements": { - "type": "object", - "required": [ - "min_ram_mb", - "min_disk_mb" - ], - "properties": { - "min_disk_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "min_ram_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - }, - "DeployV1WorkspaceRequest": { - "type": "object", - "required": [ - "definition_ref" - ], - "properties": { - "app_params": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "propertyNames": { - "type": "string" - } - }, - "definition_ref": { - "type": "string", - "description": "Registry ref, e.g. \"@alice/my-stack@1.0.0\"." - }, - "disk_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "env_vars": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "ram_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "service_spec_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "setup_script_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "vcpu_count": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "workspace_name": { - "type": [ - "string", - "null" - ], - "description": "Optional human-readable workspace name. Defaults to the slug." - } - } - }, - "DetectResult": { - "type": "object", - "description": "Detection result for exposing ports - shows what was found before confirmation.", - "required": [ - "port", - "pid", - "command", - "cwd", - "env_vars", - "is_systemd", - "process_name", - "suggested_name" - ], - "properties": { - "command": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "env_vars": { - "type": "array", - "items": { - "type": "string" - } - }, - "is_systemd": { - "type": "boolean" - }, - "pid": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "process_name": { - "type": "string" - }, - "suggested_name": { - "type": "string" - }, - "systemd_unit": { - "type": [ - "string", - "null" - ] - } - } - }, - "DiscoveryStrategy": { - "oneOf": [ - { - "type": "object", - "description": "Search for a file by name within $HOME.", - "required": [ - "filenames", - "max_depth", - "max_projects", - "type" - ], - "properties": { - "exclude_paths": { - "type": "array", - "items": { - "type": "string" - } - }, - "filenames": { - "type": "array", - "items": { - "type": "string" - } - }, - "max_depth": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "max_projects": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "type": { - "type": "string", - "enum": [ - "FilePresence" - ] - } - } - }, - { - "type": "object", - "description": "Check if all listed binaries exist on PATH.", - "required": [ - "commands", - "type" - ], - "properties": { - "commands": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string", - "enum": [ - "CommandAvailable" - ] - } - } - }, - { - "type": "object", - "description": "Always available - no detection needed.", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "Always" - ] - } - } - } - ], - "description": "How a tool discovers whether it's available in a workspace." - }, - "EffectiveLimits": { - "type": "object", - "required": [ - "max_vms", - "max_ram_per_vm_mb", - "max_ram_total_mb", - "max_disk_total_mb", - "max_vcpu_per_vm", - "max_running_vcpus" - ], - "properties": { - "max_disk_total_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "max_ram_per_vm_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "max_ram_total_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "max_running_vcpus": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "max_vcpu_per_vm": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "max_vms": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - }, - "ExposePortRequest": { - "type": "object", - "required": [ - "port", - "step" - ], - "properties": { - "name": { - "type": [ - "string", - "null" - ] - }, - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "step": { - "type": "string" - } - } - }, - "ExposePortResponse": { - "oneOf": [ - { - "allOf": [ - { - "$ref": "#/components/schemas/DetectResult" - }, - { - "type": "object", - "required": [ - "step" - ], - "properties": { - "step": { - "type": "string", - "enum": [ - "detect" - ] - } - } - } - ] - }, - { - "type": "object", - "required": [ - "message", - "app", - "service_name", - "needs_restart", - "step" - ], - "properties": { - "app": { - "$ref": "#/components/schemas/App" - }, - "message": { - "type": "string" - }, - "needs_restart": { - "type": "boolean" - }, - "service_name": { - "type": "string" - }, - "step": { - "type": "string", - "enum": [ - "wrap" - ] - } - } - } - ] - }, - "FeatureFlagsResponse": { - "type": "object", - "required": [ - "flags" - ], - "properties": { - "flags": { - "type": "object", - "description": "Map of feature flag names to their resolved boolean values.", - "additionalProperties": { - "type": "boolean" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "ForceChangePasswordRequest": { - "type": "object", - "required": [ - "email", - "temporary_password", - "new_password" - ], - "properties": { - "email": { - "type": "string" - }, - "new_password": { - "type": "string" - }, - "temporary_password": { - "type": "string" - } - } - }, - "GetAiDefaultsResponse": { - "type": "object", - "required": [ - "default_mode", - "default_provider", - "default_model" - ], - "properties": { - "default_mode": { - "type": "string" - }, - "default_model": { - "type": "string" - }, - "default_provider": { - "type": "string" - } - } - }, - "GetAiUsageResponse": { - "type": "object", - "required": [ - "window_days", - "daily", - "by_workspace" - ], - "properties": { - "by_workspace": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiUsageWorkspaceTotal" - } - }, - "daily": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiUsageDaily" - } - }, - "window_days": { - "type": "integer", - "format": "int32" - } - } - }, - "GetAppLogSourceResponse": { - "type": "object", - "required": [ - "source" - ], - "properties": { - "source": { - "$ref": "#/components/schemas/AppLogSource" - } - } - }, - "GetAppLogsResponse": { - "type": "object", - "required": [ - "source", - "lines", - "has_more" - ], - "properties": { - "cursor": { - "type": [ - "string", - "null" - ] - }, - "has_more": { - "type": "boolean" - }, - "lines": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LogLine" - } - }, - "source": { - "$ref": "#/components/schemas/AppLogSource" - }, - "total_lines": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - } - }, - "GetAppResponse": { - "type": "object", - "required": [ - "app" - ], - "properties": { - "app": { - "$ref": "#/components/schemas/AppView" - } - } - }, - "GetDashboardResponse": { - "type": "object", - "required": [ - "workspaces", - "apps", - "limits", - "ai_credits" - ], - "properties": { - "ai_credits": { - "$ref": "#/components/schemas/AiCredits" - }, - "apps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AppView" - } - }, - "limits": { - "$ref": "#/components/schemas/GetUserLimitsResponse" - }, - "workspaces": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Vm" - } - } - } - }, - "GetMeResponse": { - "type": "object", - "required": [ - "user" - ], - "properties": { - "user": { - "$ref": "#/components/schemas/UserResponse" - } - } - }, - "GetRoadmapVotesResponse": { - "type": "object", - "required": [ - "votes", - "user_votes" - ], - "properties": { - "user_votes": { - "type": "array", - "items": { - "type": "string" - } - }, - "votes": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int64" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "GetServiceSpecResponse": { - "type": "object", - "required": [ - "spec" - ], - "properties": { - "spec": { - "$ref": "#/components/schemas/ServiceSpec" - } - } - }, - "GetSetupScriptResponse": { - "type": "object", - "required": [ - "script" - ], - "properties": { - "script": { - "$ref": "#/components/schemas/SetupScript" - } - } - }, - "GetUserLimitsResponse": { - "type": "object", - "required": [ - "plan", - "custom", - "limits", - "usage" - ], - "properties": { - "custom": { - "type": "boolean" - }, - "limits": { - "$ref": "#/components/schemas/EffectiveLimits" - }, - "plan": { - "type": "string" - }, - "usage": { - "$ref": "#/components/schemas/LimitsUsage" - } - } - }, - "GetUserSettingsResponse": { - "type": "object", - "required": [ - "settings" - ], - "properties": { - "settings": { - "$ref": "#/components/schemas/UserSettings" - } - } - }, - "GetWorkspaceLogsResponse": { - "type": "object", - "required": [ - "lines", - "has_more" - ], - "properties": { - "cursor": { - "type": [ - "string", - "null" - ] - }, - "has_more": { - "type": "boolean" - }, - "lines": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LogLine" - } - } - } - }, - "GetWorkspaceResponse": { - "type": "object", - "required": [ - "vm" - ], - "properties": { - "failure": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/WorkspaceFailure", - "description": "Structured failure info when `vm.status == Failed`. `None` otherwise.\nComputed from the workspace's `failure_code`, `failure_reason`, and\n`creation_attempts` fields plus the retryable allowlist policy." - } - ] - }, - "vm": { - "$ref": "#/components/schemas/Vm" - } - } - }, - "InstallAppRequest": { - "type": "object", - "required": [ - "catalog_id" - ], - "properties": { - "catalog_id": { - "type": "string" - }, - "params": { - "type": [ - "object", - "null" - ], - "description": "User-supplied values for the app's `configurable_params`.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "InstallAppResponse": { - "type": "object", - "required": [ - "message", - "app", - "live_installed" - ], - "properties": { - "app": { - "$ref": "#/components/schemas/AppView" - }, - "credentials": { - "type": [ - "object", - "null" - ], - "description": "Credentials generated at install time (only for apps that require login).", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "job_id": { - "type": [ - "string", - "null" - ], - "description": "Job ID for async install - frontend should poll GET /workspaces/{id}/jobs/{job_id}." - }, - "live_installed": { - "type": "boolean", - "description": "If workspace is running, whether live install was attempted." - }, - "message": { - "type": "string" - } - } - }, - "JobStatusResponse": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "app_status": { - "type": [ - "string", - "null" - ], - "description": "Final app status after finalization (only set once job completes)" - }, - "exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Exit code (only populated when done)" - }, - "status": { - "type": "string", - "description": "Job execution status: \"running\", \"done\", \"failed\", \"cancelled\", \"unknown\"" - }, - "stderr": { - "type": [ - "string", - "null" - ], - "description": "Combined stderr (only populated when done)" - }, - "stdout": { - "type": [ - "string", - "null" - ], - "description": "Combined stdout (only populated when done)" - } - } - }, - "LaunchDeployRequest": { - "type": "object", - "required": [ - "ref" - ], - "properties": { - "params": { - "type": [ - "object", - "null" - ], - "description": "User-supplied values for the resolved app's configurable params.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "ref": { - "type": "string", - "description": "Exact deploy ref, e.g. `@rigbox/filebrowser@builtin` or `@alice/pgweb@1.2.3`." - } - } - }, - "LaunchFromManifestRequest": { - "type": "object", - "description": "Install a recipe whose manifest the caller is supplying inline,\nwithout going through the recipe registry. Used by\n`rig app deploy --bluegreen ` to skip the publish step for\npreview deploys: the local rig.yaml renders straight to a manifest\nthat the workspace installs and then forgets, leaving no `@user/-@`\nrows cluttering the registry.", - "required": [ - "manifest" - ], - "properties": { - "manifest": { - "description": "Inline `AppManifest` (the same canonical JSON shape recipes\nstore under `manifest`). Validation runs server-side via\n`validate_app_recipe` with the caller's publish context." - }, - "params": { - "type": [ - "object", - "null" - ], - "description": "User-supplied values for the app's configurable params.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "LaunchRequest": { - "type": "object", - "properties": { - "max_depth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "max_projects": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "project_root": { - "type": [ - "string", - "null" - ] - } - } - }, - "LimitsUsage": { - "type": "object", - "required": [ - "workspace_count", - "running_vcpus", - "total_disk_mb", - "total_ram_mb" - ], - "properties": { - "running_vcpus": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "total_disk_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "total_ram_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "workspace_count": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - }, - "ListAppLogSourcesResponse": { - "type": "object", - "required": [ - "sources" - ], - "properties": { - "sources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AppLogSource" - } - } - } - }, - "ListListeningPortsResponse": { - "type": "object", - "required": [ - "ports" - ], - "properties": { - "ports": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ListeningPort" - } - } - } - }, - "ListRegionsResponse": { - "type": "object", - "required": [ - "regions" - ], - "properties": { - "regions": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "ListServiceSpecsResponse": { - "type": "object", - "required": [ - "specs" - ], - "properties": { - "specs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceSpec" - } - } - } - }, - "ListSetupScriptsResponse": { - "type": "object", - "required": [ - "scripts" - ], - "properties": { - "scripts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SetupScript" - } - } - } - }, - "ListVolumesResponse": { - "type": "object", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Volume" - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ], - "description": "Always `null` \u2014 volume lists are small and unpaginated. Present so the\nCLI's `{items, next_cursor}` envelope is uniform across resources." - } - } - }, - "ListWorkspacesResponse": { - "type": "object", - "required": [ - "vms" - ], - "properties": { - "vms": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Vm" - } - } - } - }, - "ListeningPort": { - "type": "object", - "description": "A port detected as listening in a workspace.", - "required": [ - "port", - "address", - "already_exposed" - ], - "properties": { - "address": { - "type": "string" - }, - "already_exposed": { - "type": "boolean" - }, - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "process": { - "type": [ - "string", - "null" - ] - } - } - }, - "LogLine": { - "type": "object", - "description": "A single log line - used by workspace logs and app logs.", - "required": [ - "line_number", - "message" - ], - "properties": { - "line_number": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "message": { - "type": "string" - }, - "timestamp": { - "type": [ - "string", - "null" - ] - } - } - }, - "LoginRequest": { - "type": "object", - "required": [ - "email", - "password" - ], - "properties": { - "email": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "LookupByEmailRequest": { - "type": "object", - "required": [ - "email" - ], - "properties": { - "email": { - "type": "string" - } - } - }, - "LookupByKeyRequest": { - "type": "object", - "required": [ - "public_key" - ], - "properties": { - "public_key": { - "type": "string" - } - } - }, - "LookupByKeyResponse": { - "type": "object", - "required": [ - "user_id", - "email" - ], - "properties": { - "email": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "MarkKeyUsedRequest": { - "type": "object", - "required": [ - "user_id", - "public_key" - ], - "properties": { - "public_key": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "MessageResponse": { - "type": "object", - "description": "Generic success envelope - used across all domains.", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - }, - "MetricPoint": { - "type": "object", - "required": [ - "t", - "v" - ], - "properties": { - "t": { - "type": "integer", - "format": "int64" - }, - "v": { - "type": "number", - "format": "double" - } - } - }, - "Page_ApiKeyResponse": { - "type": "object", - "description": "Paginated response envelope. `next_cursor: None` \u21d2 last page.", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "type": "object", - "required": [ - "id", - "key_preview", - "created_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "id": { - "type": "string" - }, - "key_preview": { - "type": "string" - }, - "last_used_at": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - } - } - }, - "Page_AppView": { - "type": "object", - "description": "Paginated response envelope. `next_cursor: None` \u21d2 last page.", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "allOf": [ - { - "$ref": "#/components/schemas/ApiApp" - } - ] - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - } - } - }, - "Page_DeployPreviewResponse": { - "type": "object", - "description": "Paginated response envelope. `next_cursor: None` \u21d2 last page.", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "type": "object", - "required": [ - "deploy_ref", - "source", - "trust_tier", - "status", - "catalog_id", - "slug", - "version", - "name", - "description", - "icon", - "category", - "resources", - "app_kind", - "configurable_params", - "credentials_declared", - "warnings" - ], - "properties": { - "app_kind": { - "type": "string", - "description": "Whether this recipe is a daemon `\"service\"` (has port + Caddy route)\nor an interactive `\"cli\"` (install-only; user invokes via SSH).\nMirrors `AppKind` on the catalog item." - }, - "catalog_id": { - "type": "string" - }, - "category": { - "type": "string" - }, - "community_version_id": { - "type": [ - "string", - "null" - ] - }, - "configurable_params": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamSpec" - } - }, - "credentials_declared": { - "type": "boolean" - }, - "depends_on": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Backing services this app expects on the workspace (community only)." - }, - "deploy_ref": { - "type": "string", - "description": "Canonical exact ref that will be installed." - }, - "description": { - "type": "string" - }, - "exposure": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DeployExposure", - "description": "Daemon-shape exposure fields. Present only when `app_kind` is\n`\"service\"`. Omitted entirely for `\"cli\"` items \u2014 the UI should\nrender a CLI-shaped affordance with no port/protocol pill." - } - ] - }, - "icon": { - "type": "string" - }, - "install_script_preview": { - "type": [ - "string", - "null" - ] - }, - "install_stats": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CommunityCatalogVersionInstallStats" - } - ] - }, - "managed": { - "type": "boolean", - "description": "True if this recipe opts into Rigbox's managed AI proxy when installed." - }, - "manifest_digest": { - "type": [ - "string", - "null" - ] - }, - "manifest_json": { - "description": "Raw manifest JSON for the \"View manifest\" affordance. Community only." - }, - "name": { - "type": "string" - }, - "resources": { - "$ref": "#/components/schemas/DeployResourceRequirements" - }, - "slug": { - "type": "string" - }, - "source": { - "type": "string", - "description": "`official` or `community`." - }, - "status": { - "type": "string" - }, - "system_tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Discovery tags from the recipe manifest (community only)." - }, - "trust_tier": { - "type": "string", - "description": "`official`, `verified`, `community`, or `private`." - }, - "usage_examples": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UsageExample" - }, - "description": "Copy-pasteable usage examples shown in the catalog detail \"Usage\" tab." - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "version": { - "type": "string" - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - } - } - }, - "Page_SnapshotView": { - "type": "object", - "description": "Paginated response envelope. `next_cursor: None` \u21d2 last page.", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "type": "object", - "description": "Read-only projection of a workspace snapshot.", - "required": [ - "id", - "workspace_id", - "name", - "size_mb", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "size_mb": { - "type": "integer", - "format": "int32" - }, - "workspace_id": { - "type": "string" - } - } - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - } - } - }, - "Page_SshKeyEntry": { - "type": "object", - "description": "Paginated response envelope. `next_cursor: None` \u21d2 last page.", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "type": "object", - "description": "An SSH key entry from a workspace's authorized_keys.", - "required": [ - "fingerprint", - "key_type", - "comment" - ], - "properties": { - "comment": { - "type": "string" - }, - "fingerprint": { - "type": "string" - }, - "key_type": { - "type": "string" - } - } - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - } - } - }, - "Page_Vm": { - "type": "object", - "description": "Paginated response envelope. `next_cursor: None` \u21d2 last page.", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "type": "object", - "required": [ - "id", - "user_id", - "node_id", - "name", - "status", - "image", - "ram_mb", - "vcpu_count", - "disk_size_mb", - "created_at", - "updated_at" - ], - "properties": { - "ai_mode": { - "type": [ - "string", - "null" - ], - "description": "Per-workspace override for the AI mode (`managed` or `byok`).\n`None` means inherit from `users.ai_mode` (the per-account default)." - }, - "cloned_from": { - "type": [ - "string", - "null" - ], - "description": "Bluegreen preview lineage. `None` = a normal workspace. `Some(source_id)`\n= this VM is a COW clone of `source_id`, booted as a hidden preview;\npromote repoints the prod subdomain's edge route to it. See\n[`Vm::is_preview`]." - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "creation_attempts": { - "type": "integer", - "format": "int32" - }, - "creation_started_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "disk_size_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "env_vars": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "failure_code": { - "type": [ - "string", - "null" - ] - }, - "failure_reason": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "string" - }, - "image": { - "type": "string" - }, - "image_digest": { - "type": [ - "string", - "null" - ], - "description": "Content-addressed image this workspace is pinned to. When set, the\nworkspace boots from this registry image (staged as the rootfs on first\nboot) instead of the named base in `image`. `None` = the named-base path." - }, - "ip_address": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "node_id": { - "type": "string" - }, - "ram_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "service_spec_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "setup_script_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "status": { - "$ref": "#/components/schemas/VmStatus" - }, - "template_id": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "user_id": { - "type": "string" - }, - "vcpu_count": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - } - } - }, - "ParamOption": { - "type": "object", - "description": "A selectable option for `ParamType::Select` fields.", - "required": [ - "value", - "label" - ], - "properties": { - "label": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "ParamSpec": { - "type": "object", - "description": "One configurable parameter declared by a template expected app or catalog item.\n\nThe `key` is used as the `{PARAM_}` placeholder (upper-cased) in\ninstall scripts, exec_start, and config_file JSON values.", - "required": [ - "key", - "label", - "param_type" - ], - "properties": { - "default": { - "type": "string", - "description": "Pre-filled value (empty string = no default)." - }, - "description": { - "type": "string", - "description": "Longer description / hint text shown below the field." - }, - "group": { - "type": [ - "string", - "null" - ], - "description": "Visual group header for related params." - }, - "help_url": { - "type": [ - "string", - "null" - ], - "description": "Help URL (e.g. docs for getting an API key)." - }, - "key": { - "type": "string", - "description": "Machine key, e.g. `\"telegram_bot_token\"`." - }, - "label": { - "type": "string", - "description": "Human-readable label for the UI." - }, - "options": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamOption" - }, - "description": "Selectable options for `ParamType::Select`." - }, - "order": { - "type": "integer", - "format": "int32", - "description": "Display order within the group (lower = higher)." - }, - "param_type": { - "$ref": "#/components/schemas/ParamType", - "description": "Determines the UI element and basic validation." - }, - "required": { - "type": "boolean", - "description": "If true, deploy is blocked when the value is empty." - }, - "sensitive": { - "type": "boolean", - "description": "If true, render as password field and mask in API responses." - }, - "validation_pattern": { - "type": [ - "string", - "null" - ], - "description": "Optional regex the submitted value must match." - } - } - }, - "ParamType": { - "type": "string", - "description": "Data type for validation + UI element selection.", - "enum": [ - "string", - "secret", - "email", - "url", - "number", - "boolean", - "select", - "textarea" - ] - }, - "PollCliSessionResponse": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "api_key": { - "type": [ - "string", - "null" - ] - }, - "email": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - } - } - }, - "PortalRequest": { - "type": "object", - "properties": { - "return_url": { - "type": [ - "string", - "null" - ] - } - } - }, - "PrincipalLookupResponse": { - "type": "object", - "required": [ - "principals" - ], - "properties": { - "principals": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PrincipalLookupResult" - } - } - } - }, - "PrincipalLookupResult": { - "type": "object", - "required": [ - "principal", - "user_id", - "email" - ], - "properties": { - "display_name": { - "type": [ - "string", - "null" - ] - }, - "email": { - "type": "string" - }, - "principal": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "QuickDeployRequest": { - "type": "object", - "required": [ - "template_id" - ], - "properties": { - "app_params": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "propertyNames": { - "type": "string" - } - }, - "catalog_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "disk_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "env_vars": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "ram_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "service_spec_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "setup_script_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "template_id": { - "type": "string" - }, - "vcpu_count": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - } - }, - "QuickDeployResponse": { - "type": "object", - "required": [ - "workspace", - "message" - ], - "properties": { - "expected_apps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/App" - } - }, - "installed_apps": { - "type": "array", - "items": { - "type": "string" - } - }, - "message": { - "type": "string" - }, - "workspace": { - "$ref": "#/components/schemas/Vm" - } - } - }, - "ReconcileAppsResponse": { - "type": "object", - "required": [ - "created", - "existing", - "install_jobs" - ], - "properties": { - "created": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AppView" - } - }, - "existing": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AppView" - } - }, - "install_jobs": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "RegisterPendingKeyRequest": { - "type": "object", - "required": [ - "email", - "public_key" - ], - "properties": { - "email": { - "type": "string" - }, - "public_key": { - "type": "string" - } - } - }, - "RegisterPendingKeyResponse": { - "type": "object", - "required": [ - "token" - ], - "properties": { - "token": { - "type": "string" - } - } - }, - "ResizeVolumeRequest": { - "type": "object", - "required": [ - "size_mb" - ], - "properties": { - "size_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - }, - "ResizeWorkspaceRequest": { - "type": "object", - "properties": { - "disk_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "ram_mb": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "vcpu_count": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - } - }, - "ResizeWorkspaceResponse": { - "type": "object", - "required": [ - "vm", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "vm": { - "$ref": "#/components/schemas/Vm" - } - } - }, - "RestoreSnapshotResponse": { - "type": "object", - "required": [ - "message", - "workspace_id" - ], - "properties": { - "message": { - "type": "string" - }, - "workspace_id": { - "type": "string" - } - } - }, - "RolePreset": { - "type": "object", - "required": [ - "scope_kind", - "role", - "permissions", - "required_resource_tags", - "match_tag_keys", - "system_managed", - "updated_at" - ], - "properties": { - "match_tag_keys": { - "type": "array", - "items": { - "type": "string" - } - }, - "permissions": { - "type": "array", - "items": { - "type": "string" - } - }, - "required_resource_tags": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "role": { - "type": "string" - }, - "scope_kind": { - "type": "string" - }, - "system_managed": { - "type": "boolean" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "RolePresetsResponse": { - "type": "object", - "required": [ - "presets" - ], - "properties": { - "presets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RolePreset" - } - } - } - }, - "ServiceActionResponse": { - "type": "object", - "required": [ - "message", - "app", - "service_name" - ], - "properties": { - "app": { - "$ref": "#/components/schemas/AppView" - }, - "message": { - "type": "string" - }, - "service_name": { - "type": "string" - } - } - }, - "ServicePatchSpec": { - "type": "object", - "description": "Specification for patching a systemd service with an EnvironmentFile.", - "required": [ - "unit_name", - "env_file_path" - ], - "properties": { - "env_file_path": { - "type": "string", - "description": "Path to the env file to add (e.g. \"/home/developer/.openclaw/.env\")." - }, - "remove_env_patterns": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Environment= lines to remove if found (e.g. [\"OPENCLAW_GATEWAY_TOKEN\"])." - }, - "unit_name": { - "type": "string", - "description": "Systemd unit name (e.g. \"rigbox-svc-openclaw-gateway.service\")." - } - } - }, - "ServiceSpec": { - "type": "object", - "description": "Account-level service spec that runs a background process inside workspaces.\nWorking directory is always /home/developer.", - "required": [ - "id", - "user_id", - "name", - "exec_start", - "setup_script", - "env_vars", - "restart_policy", - "auto_enable", - "source", - "created_at", - "updated_at" - ], - "properties": { - "app_id": { - "type": [ - "string", - "null" - ] - }, - "auto_enable": { - "type": "boolean" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "env_vars": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "environment_file": { - "type": [ - "string", - "null" - ], - "description": "Optional path to an environment file for the service." - }, - "exec_start": { - "type": "string" - }, - "id": { - "type": "string", - "format": "uuid" - }, - "name": { - "type": "string" - }, - "restart_policy": { - "type": "string" - }, - "setup_script": { - "type": "string" - }, - "source": { - "type": "string" - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "user_id": { - "type": "string" - }, - "workspace_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "ServiceSpecResponse": { - "type": "object", - "required": [ - "id", - "user_id", - "name", - "exec_start", - "env_vars", - "restart_policy", - "auto_enable", - "systemd_unit_preview", - "source", - "created_at", - "updated_at" - ], - "properties": { - "auto_enable": { - "type": "boolean" - }, - "created_at": { - "type": "string" - }, - "env_vars": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "exec_start": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "restart_policy": { - "type": "string" - }, - "source": { - "type": "string" - }, - "systemd_unit_preview": { - "type": "string", - "description": "Preview of the systemd unit that would be generated" - }, - "updated_at": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "ServiceSpecsListResponse": { - "type": "object", - "required": [ - "services" - ], - "properties": { - "services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceSpecResponse" - } - } - } - }, - "SetVisibilityRequest": { - "type": "object", - "description": "Body for the visibility PATCH endpoints.", - "required": [ - "visibility" - ], - "properties": { - "visibility": { - "type": "string", - "description": "`private` (owner-only) or `community` (listed for everyone)." - } - } - }, - "SetupScript": { - "type": "object", - "description": "Account-level setup script for reproducible workspace environments.\nScripts run once on first boot or on every start.", - "required": [ - "id", - "user_id", - "name", - "content", - "run_on", - "script_order", - "source", - "created_at", - "updated_at" - ], - "properties": { - "app_id": { - "type": [ - "string", - "null" - ] - }, - "content": { - "type": "string" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "id": { - "type": "string", - "format": "uuid" - }, - "name": { - "type": "string" - }, - "run_on": { - "type": "string" - }, - "script_order": { - "type": "integer", - "format": "int32" - }, - "source": { - "type": "string" - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "user_id": { - "type": "string" - }, - "workspace_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "SetupScriptResponse": { - "type": "object", - "required": [ - "id", - "user_id", - "name", - "content", - "run_on", - "script_order", - "source", - "created_at", - "updated_at" - ], - "properties": { - "content": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "run_on": { - "type": "string" - }, - "script_order": { - "type": "integer", - "format": "int32" - }, - "source": { - "type": "string" - }, - "updated_at": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "SetupScriptsListResponse": { - "type": "object", - "required": [ - "scripts" - ], - "properties": { - "scripts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SetupScriptResponse" - } - } - } - }, - "SignupRequest": { - "type": "object", - "required": [ - "email", - "password" - ], - "properties": { - "email": { - "type": "string" - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "password": { - "type": "string" - } - } - }, - "SimulateAccessRequest": { - "type": "object", - "required": [ - "resource", - "action" - ], - "properties": { - "action": { - "type": "string" - }, - "principal": { - "type": [ - "string", - "null" - ] - }, - "resource": { - "type": "string" - } - } - }, - "SimulateAccessResponse": { - "type": "object", - "required": [ - "principal", - "resource", - "action", - "allowed", - "reason" - ], - "properties": { - "action": { - "type": "string" - }, - "allowed": { - "type": "boolean" - }, - "principal": { - "type": "string" - }, - "reason": { - "type": "string" - }, - "resource": { - "type": "string" - } - } - }, - "SnapshotView": { - "type": "object", - "description": "Read-only projection of a workspace snapshot.", - "required": [ - "id", - "workspace_id", - "name", - "size_mb", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "size_mb": { - "type": "integer", - "format": "int32" - }, - "workspace_id": { - "type": "string" - } - } - }, - "SpanNode": { - "type": "object", - "required": [ - "span_id", - "name", - "start_ns", - "duration_ms", - "status", - "attributes" - ], - "properties": { - "attributes": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "duration_ms": { - "type": "number", - "format": "double" - }, - "name": { - "type": "string" - }, - "parent_span_id": { - "type": [ - "string", - "null" - ], - "description": "`None` for the root span." - }, - "span_id": { - "type": "string" - }, - "start_ns": { - "type": "string" - }, - "status": { - "$ref": "#/components/schemas/TraceStatus" - } - } - }, - "SshKey": { - "type": "object", - "required": [ - "id", - "user_id", - "name", - "public_key", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "id": { - "type": "string", - "format": "uuid" - }, - "name": { - "type": "string" - }, - "public_key": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "SshKeyEntry": { - "type": "object", - "description": "An SSH key entry from a workspace's authorized_keys.", - "required": [ - "fingerprint", - "key_type", - "comment" - ], - "properties": { - "comment": { - "type": "string" - }, - "fingerprint": { - "type": "string" - }, - "key_type": { - "type": "string" - } - } - }, - "SshKeyWithFingerprint": { - "type": "object", - "required": [ - "id", - "user_id", - "name", - "public_key", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "fingerprint": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "public_key": { - "type": "string" - }, - "user_id": { - "type": "string" - } - } - }, - "SshKeysResponse": { - "type": "object", - "required": [ - "ssh_keys" - ], - "properties": { - "ssh_keys": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SshKeyWithFingerprint" - } - } - } - }, - "SubscriptionStatusResponse": { - "type": "object", - "required": [ - "active", - "status", - "plan", - "trial_expired" - ], - "properties": { - "active": { - "type": "boolean" - }, - "plan": { - "type": "string" - }, - "status": { - "type": "string" - }, - "trial_expired": { - "type": "boolean" - }, - "trial_expires_at": { - "type": [ - "string", - "null" - ] - } - } - }, - "SwitchPlanResponse": { - "type": "object", - "required": [ - "message", - "plan" - ], - "properties": { - "message": { - "type": "string" - }, - "plan": { - "type": "string" - } - } - }, - "SyncSshKeysResponse": { - "type": "object", - "required": [ - "synced", - "keys" - ], - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SshKeyEntry" - } - }, - "synced": { - "type": "integer", - "minimum": 0 - } - } - }, - "TagsResponse": { - "type": "object", - "required": [ - "resource", - "tags" - ], - "properties": { - "resource": { - "type": "string" - }, - "tags": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "TemplateExpectedApp": { - "type": "object", - "required": [ - "name", - "port", - "system_tags", - "protocol", - "managed" - ], - "properties": { - "configurable_params": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamSpec" - }, - "description": "User-configurable parameters for this expected app.\nValues are submitted at deploy time via `app_params` in QuickDeployRequest." - }, - "depends_on": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Workspace services this app depends on (by name, e.g. \"postgresql\", \"redis-server\")." - }, - "managed": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "protocol": { - "type": "string" - }, - "system_tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "usage_examples": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UsageExample" - }, - "description": "Copy-pasteable API usage examples shown in the app detail \"Usage\" tab.\nPlaceholders: `{SUBDOMAIN}`, `{CRED_}` - resolved client-side." - } - } - }, - "TemplateLogSourcePreset": { - "type": "object", - "required": [ - "source_type", - "source_ref" - ], - "properties": { - "display_name": { - "type": [ - "string", - "null" - ] - }, - "is_primary": { - "type": "boolean" - }, - "source_ref": { - "type": "string" - }, - "source_type": { - "type": "string" - } - } - }, - "TemplatesResponse": { - "type": "object", - "required": [ - "templates" - ], - "properties": { - "templates": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkspaceTemplate" - } - } - } - }, - "ThrottleBindingResponse": { + } + }, + "components": { + "schemas": { + "AccessBinding": { "type": "object", "required": [ - "resource" + "principal_ref", + "resource_ref", + "role", + "created_at", + "updated_at" ], "properties": { - "profile": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "created_by_ref": { "type": [ "string", "null" ] }, - "resource": { + "principal_ref": { "type": "string" - } - } - }, - "ThrottlePreset": { - "type": "object", - "required": [ - "name", - "rules", - "system_managed", - "updated_at" - ], - "properties": { - "name": { + }, + "resource_ref": { "type": "string" }, - "rules": {}, - "system_managed": { - "type": "boolean" + "role": { + "type": "string" }, "updated_at": { "type": "string", @@ -11458,48 +2311,27 @@ } } }, - "ThrottlePresetsResponse": { - "type": "object", - "required": [ - "presets" - ], - "properties": { - "presets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ThrottlePreset" - } - } - } - }, - "ToggleVoteResponse": { + "AccessControlDeleteResponse": { "type": "object", "required": [ - "voted", - "count" + "deleted" ], "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "voted": { + "deleted": { "type": "boolean" } } }, - "ToolInstallResponse": { + "AccountDeletionAccepted": { "type": "object", "required": [ + "deletion_id", "status", "message" ], "properties": { - "job_id": { - "type": [ - "string", - "null" - ] + "deletion_id": { + "type": "string" }, "message": { "type": "string" @@ -11509,632 +2341,554 @@ } } }, - "ToolInstallStatusResponse": { + "AccountDeletionPreview": { "type": "object", + "description": "Everything a deletion would remove, shown before the user confirms.", "required": [ - "status" + "user_id", + "email", + "resource_counts", + "subscription", + "github_app_connected", + "custom_domains", + "clerk_identities" ], "properties": { - "available": { - "type": [ - "boolean", - "null" - ], - "description": "Whether the tool is now available after install" + "clerk_identities": { + "type": "integer", + "format": "int64", + "description": "Clerk identities recorded for the account: the Clerk users a deletion\nremoves. 0 means any Clerk user must be removed by hand." }, - "exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Exit code (only when done)" + "custom_domains": { + "type": "array", + "items": { + "type": "string" + } }, - "status": { - "type": "string", - "description": "\"running\", \"done\", \"failed\"" + "email": { + "type": "string" }, - "stdout_tail": { - "type": [ - "string", - "null" - ], - "description": "Tail of stdout (only when done)" + "github_app_connected": { + "type": "boolean" + }, + "resource_counts": { + "$ref": "#/components/schemas/AccountResourceCounts" + }, + "subscription": { + "$ref": "#/components/schemas/AccountSubscription" + }, + "user_id": { + "type": "string" } } }, - "ToolLaunchResponse": { + "AccountResourceCounts": { "type": "object", "required": [ - "status", - "message" - ], - "properties": { - "message": { - "type": "string" + "workspaces", + "apps", + "snapshots", + "volumes", + "api_keys", + "ssh_keys", + "setup_scripts", + "service_specs", + "published_recipes", + "github_repo_bindings", + "builds" + ], + "properties": { + "api_keys": { + "type": "integer", + "format": "int64" }, - "started_at_ms": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 + "apps": { + "type": "integer", + "format": "int64" }, - "status": { - "type": "string" + "builds": { + "type": "integer", + "format": "int64" }, - "url": { - "type": [ - "string", - "null" - ] - } - } - }, - "ToolStatus": { - "allOf": [ - { - "$ref": "#/components/schemas/WorkspaceTool" + "github_repo_bindings": { + "type": "integer", + "format": "int64" }, - { - "type": "object", - "required": [ - "available", - "running", - "project_roots_truncated" - ], - "properties": { - "available": { - "type": "boolean" - }, - "needs_install": { - "type": "boolean", - "description": "True if the tool requires setup before it can analyze/launch.\nDiscovery may still work but full functionality needs install." - }, - "project_roots": { - "type": "array", - "items": { - "type": "string" - } - }, - "project_roots_truncated": { - "type": "boolean" - }, - "running": { - "type": "boolean" - }, - "started_at_ms": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "status_sys": { - "type": [ - "string", - "null" - ], - "description": "Lifecycle state reported by the tool's background process.\nValues are tool-defined (e.g. \"analyzing\", \"installing\", \"building\").\nNone when idle or no background process is running." - }, - "unavailable_reason": { - "type": [ - "string", - "null" - ], - "description": "Brief explanation of why the tool is unavailable." - }, - "url": { - "type": [ - "string", - "null" - ] - } - } + "published_recipes": { + "type": "integer", + "format": "int64" + }, + "service_specs": { + "type": "integer", + "format": "int64" + }, + "setup_scripts": { + "type": "integer", + "format": "int64" + }, + "snapshots": { + "type": "integer", + "format": "int64" + }, + "ssh_keys": { + "type": "integer", + "format": "int64" + }, + "volumes": { + "type": "integer", + "format": "int64" + }, + "workspaces": { + "type": "integer", + "format": "int64" } - ] + } }, - "ToolStopResponse": { + "AccountSubscription": { "type": "object", "required": [ - "status", - "message" + "active", + "plan" ], "properties": { - "message": { - "type": "string" + "active": { + "type": "boolean" }, - "status": { + "plan": { "type": "string" } } }, - "ToolsListResponse": { + "ApiErrorBody": { "type": "object", + "description": "JSON body returned for all errors.", "required": [ - "tools" + "error" ], "properties": { - "tools": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ToolStatus" - } + "error": { + "$ref": "#/components/schemas/ApiErrorDetail" } } }, - "TraceDetailResponse": { + "ApiErrorDetail": { "type": "object", "required": [ - "trace_id", - "command", - "start_ns", - "duration_ms", - "status", - "spans" + "code", + "message" ], "properties": { - "command": { + "code": { "type": "string" }, - "duration_ms": { - "type": "number", - "format": "double" + "details": {}, + "message": { + "type": "string" + } + } + }, + "ApiKeyResponse": { + "type": "object", + "required": [ + "id", + "key_preview", + "created_at" + ], + "properties": { + "created_at": { + "type": "string" }, - "spans": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpanNode" - }, - "description": "Flat span list; the client builds the tree via `parent_span_id`." + "id": { + "type": "string" }, - "start_ns": { + "key_preview": { "type": "string" }, - "status": { - "$ref": "#/components/schemas/TraceStatus" + "last_used_at": { + "type": [ + "string", + "null" + ] }, - "trace_id": { - "type": "string" + "name": { + "type": [ + "string", + "null" + ] } } }, - "TraceSearchResponse": { + "ApproveCliSessionResponse": { "type": "object", "required": [ - "traces", - "range" + "status" ], "properties": { - "range": { - "type": "string", - "description": "Echo of the resolved range label (e.g. \"24h\")." - }, - "traces": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TraceSummary" - } + "status": { + "type": "string" } } }, - "TraceStatsBucket": { + "AttemptRequest": { "type": "object", "required": [ - "t", - "count", - "error_count", - "p50_ms", - "p95_ms", - "p99_ms" + "id", + "source", + "installation_id", + "repository_id", + "repository_name", + "commit", + "branch", + "name", + "content" ], "properties": { - "count": { - "type": "integer", - "format": "int32", - "minimum": 0 + "branch": { + "type": "string" }, - "error_count": { - "type": "integer", - "format": "int32", - "minimum": 0 + "commit": { + "type": "string" }, - "p50_ms": { - "type": "number", - "format": "double" + "content": { + "type": "string" }, - "p95_ms": { - "type": "number", - "format": "double" + "deployment_strategy": { + "type": [ + "string", + "null" + ] }, - "p99_ms": { - "type": "number", - "format": "double" + "id": { + "type": "string", + "format": "uuid" }, - "t": { + "installation_id": { "type": "integer", - "format": "int64", - "description": "Bucket start (unix seconds)." + "format": "int64" + }, + "name": { + "type": "string" + }, + "replace_binding_id": { + "type": [ + "string", + "null" + ], + "format": "uuid" + }, + "repository_id": { + "type": "integer", + "format": "int64" + }, + "repository_name": { + "type": "string" + }, + "source": { + "$ref": "#/components/schemas/SourceRequest" + }, + "workspace_id": { + "type": [ + "string", + "null" + ] } } }, - "TraceStatsResponse": { + "AttemptResponse": { "type": "object", - "description": "RED metrics for the trace list hero strip, aggregated server-side from the\ncaller's traces in the window. Every value is real (never an estimate);\n`total`/`error_count` are exact unless `capped` is set.", "required": [ - "range", - "total", - "capped", - "error_count", - "error_rate", - "p50_ms", - "p95_ms", - "p99_ms", - "buckets" + "id", + "workspace_id", + "existing_workspace", + "branch", + "draft" ], "properties": { - "buckets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TraceStatsBucket" - }, - "description": "Equal-width time buckets across the window (chronological), one point\nper sparkline sample." - }, - "capped": { - "type": "boolean", - "description": "True when the window held more than `MAX_STATS` traces, so `total` and\nthe aggregates are computed over the first `MAX_STATS` (a lower bound)." - }, - "error_count": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "error_rate": { - "type": "number", - "format": "double", - "description": "Errored fraction in `0.0..=1.0`." - }, - "p50_ms": { - "type": "number", - "format": "double" + "branch": { + "type": "string" }, - "p95_ms": { - "type": "number", - "format": "double" + "draft": { + "$ref": "#/components/schemas/AttemptRequest" }, - "p99_ms": { - "type": "number", - "format": "double" + "existing_workspace": { + "type": "boolean" }, - "range": { + "id": { "type": "string", - "description": "Echo of the resolved range label (e.g. \"24h\" / \"custom\")." + "format": "uuid" }, - "total": { - "type": "integer", - "format": "int32", - "description": "Trace count in the window.", - "minimum": 0 + "result": {}, + "workspace_id": { + "type": "string" } } }, - "TraceStatus": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "TraceSummary": { + "AuthMessageResponse": { "type": "object", "required": [ - "trace_id", - "command", - "start_ns", - "duration_ms", - "span_count", - "status" + "message" ], "properties": { - "command": { - "type": "string", - "description": "Root span name, e.g. `rig deploy` / `rig workspace ls`." - }, - "duration_ms": { - "type": "number", - "format": "double" - }, - "span_count": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "start_ns": { - "type": "string", - "description": "Trace start as unix nanoseconds (string to avoid JS i64 precision loss)." - }, - "status": { - "$ref": "#/components/schemas/TraceStatus" - }, - "trace_id": { + "message": { "type": "string" } } }, - "UpdateAiDefaultsRequest": { + "AuthResponseWithUser": { "type": "object", + "required": [ + "token", + "user" + ], "properties": { - "default_mode": { - "type": [ - "string", - "null" - ] + "must_change_password": { + "type": "boolean" }, - "default_model": { - "type": [ - "string", - "null" - ] + "token": { + "type": "string" }, - "default_provider": { - "type": [ - "string", - "null" - ] + "user": { + "$ref": "#/components/schemas/UserResponse" } - }, - "additionalProperties": false + } }, - "UpdateAiModeRequest": { + "BadgeSource": { "type": "object", "required": [ - "mode" + "repository", + "commit", + "fork_url" ], "properties": { - "mode": { + "commit": { "type": "string" + }, + "fork_url": { + "type": "string" + }, + "repository": { + "$ref": "#/components/schemas/Repository" } } }, - "UpdateAppEnvRequest": { + "BindingsResponse": { "type": "object", "required": [ - "env_vars" + "bindings" ], "properties": { - "env_vars": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" + "bindings": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccessBinding" } } } }, - "UpdateAppLogSourceRequest": { + "Branch": { "type": "object", + "required": [ + "name" + ], "properties": { - "display_name": { - "type": [ - "string", - "null" - ] - }, - "is_primary": { - "type": [ - "boolean", - "null" - ] - }, - "source_ref": { - "type": [ - "string", - "null" - ] - }, - "source_type": { - "type": [ - "string", - "null" - ] + "name": { + "type": "string" } } }, - "UpdateAppParamsRequest": { + "BranchList": { "type": "object", "required": [ - "values" + "branches" ], "properties": { - "values": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" + "branches": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Branch" } + }, + "next_page": { + "type": [ + "integer", + "null" + ], + "format": "int32", + "minimum": 0 } } }, - "UpdateAppRequest": { + "Build": { "type": "object", + "description": "Index row for one image build. NOT the build log —\nthe log text stays in host journald under `rigbox-build-`; this row\njust lets a user enumerate their recent builds (incl. failures) and resolve\neach `build_id` to open its journald log. Owner-scoped.", + "required": [ + "build_id", + "owner_user_id", + "status", + "created_at", + "updated_at" + ], "properties": { - "allowed_emails": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } + "build_id": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" }, - "custom_domain": { + "error": { "type": [ "string", "null" ], - "description": "Custom domain (e.g. \"api.example.com\"). Set to empty string or null to remove." + "description": "Short failure summary — set on failure." }, - "description": { + "image_digest": { "type": [ "string", "null" - ] + ], + "description": "Content digest of the produced image — set on success." }, - "metadata": {}, - "name": { + "label": { "type": [ "string", "null" - ] + ], + "description": "Best-effort app/project label from the deploy (the CLI's `rig.yaml` name)." }, - "port": { + "owner_user_id": { + "type": "string" + }, + "source_commit": { "type": [ - "integer", + "string", "null" ], - "format": "int32", - "minimum": 0 + "description": "Full git object ID requested for this build; retained on failure." }, - "status": { + "source_kind": { "type": [ "string", "null" ], - "description": "Toggle status: \"active\" or \"inactive\"" + "description": "`recipe` for every build since Dockerfile/image sources were removed;\nhistorical rows may still read `dockerfile` or `image`." }, - "swap_subdomain_with": { + "status": { + "type": "string", + "description": "`building` while in flight, then `succeeded` | `failed`." + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "workspace_id": { "type": [ "string", "null" ], - "description": "Atomically swap this app's subdomain with another app in the same\nworkspace. Both apps trade `name` (and therefore Caddy subdomain)\nin a single DB transaction + a single Caddy resync pass. Mutually\nexclusive with every other field on this body \u2014 combining them\nreturns 400.\n\nThe two apps must satisfy a blue-green sibling relationship\n(`other.name == \"{app.name}-\"` or vice versa), share the\nsame `(user_id, workspace_id)`, agree on `visibility` and\n`allowed_emails`, and neither may have a custom domain attached.\nSee the security checklist in the swap handler for full\nrejection conditions." - }, - "visibility": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/Visibility" - } - ] + "description": "Target workspace; standalone image builds have no workspace." } } }, - "UpdateAppVisibilityRequest": { + "Callback": { "type": "object", "required": [ - "visibility" + "code", + "state" ], "properties": { - "allowed_emails": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } + "code": { + "type": "string" }, - "visibility": { - "$ref": "#/components/schemas/Visibility" + "state": { + "type": "string" } } }, - "UpdateBindingRequest": { + "ChangePasswordRequest": { "type": "object", "required": [ - "principal", - "resource", - "current_role", - "new_role" + "current_password", + "new_password" ], "properties": { - "current_role": { - "type": "string" - }, - "new_role": { - "type": "string" - }, - "principal": { + "current_password": { "type": "string" }, - "resource": { + "new_password": { "type": "string" } } }, - "UpdateCommunityProfileRequest": { + "ChangeRequest": { "type": "object", + "required": [ + "operation_id", + "plan", + "addons" + ], "properties": { - "community_items_preference": { - "type": [ - "string", - "null" - ], - "description": "Community catalog visibility preference: disabled, verified_only, or enabled." + "addons": { + "type": "object" + }, + "operation_id": { + "type": "string", + "format": "uuid" + }, + "plan": { + "type": "string" }, - "username": { + "return_url": { "type": [ "string", "null" - ], - "description": "Claimable community username. Once claimed, username changes are blocked." + ] } } }, - "UpdateServiceSpecRequest": { + "ConfirmAccountDeletion": { "type": "object", + "description": "The caller retypes the account email to confirm the deletion.", + "required": [ + "confirm_email" + ], "properties": { - "auto_enable": { - "type": [ - "boolean", - "null" - ] - }, - "env_vars": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "environment_file": { - "type": [ - "string", - "null" - ] - }, - "exec_start": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] + "confirm_email": { + "type": "string", + "description": "The account email; compared trimmed and case-insensitively.", + "example": "a@example.com" + } + } + }, + "ConnectUrl": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + } + } + }, + "ConnectionStatus": { + "type": "object", + "required": [ + "configured", + "connections" + ], + "properties": { + "configured": { + "type": "boolean" }, - "restart_policy": { - "type": [ - "string", - "null" - ] + "connections": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GithubConnection" + } }, - "setup_script": { + "install_url": { "type": [ "string", "null" @@ -12142,135 +2896,160 @@ } } }, - "UpdateSetupScriptRequest": { + "CreateApiKeyRequest": { "type": "object", "properties": { - "content": { - "type": [ - "string", - "null" - ] - }, "name": { "type": [ "string", "null" ] + } + } + }, + "CreateApiKeyResponseFull": { + "type": "object", + "required": [ + "id", + "key" + ], + "properties": { + "id": { + "type": "string" }, - "run_on": { - "type": [ - "string", - "null" - ] - }, - "script_order": { - "type": [ - "integer", - "null" - ], - "format": "int32" + "key": { + "type": "string" } } }, - "UpdateTagsRequest": { + "CreateBindingRequest": { "type": "object", "required": [ + "principal", "resource", - "tags" + "role" ], "properties": { + "principal": { + "type": "string" + }, "resource": { "type": "string" }, - "tags": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } + "role": { + "type": "string" } } }, - "UpdateThrottleBindingRequest": { + "CreateCliSessionRequest": { "type": "object", "required": [ - "resource" + "code" ], "properties": { - "profile": { - "type": [ - "string", - "null" - ] - }, - "resource": { + "code": { "type": "string" } } }, - "UpdateUserSettingsRequest": { + "CreateCliSessionResponse": { "type": "object", + "required": [ + "status" + ], "properties": { - "avatar_url": { - "type": [ - "string", - "null" - ] - }, - "default_image": { - "type": [ - "string", - "null" - ] + "status": { + "type": "string" + } + } + }, + "CreateGithubBindingRequest": { + "type": "object", + "required": [ + "repository_name", + "workspace_id" + ], + "properties": { + "repository_name": { + "type": "string" }, - "default_region": { - "type": [ - "string", - "null" - ] + "workspace_id": { + "type": "string" + } + } + }, + "DeclaredSecret": { + "type": "object", + "required": [ + "name", + "from", + "optional", + "set" + ], + "properties": { + "from": { + "type": "string", + "description": "The runtime secret its value is stored and supplied under." }, - "display_name": { - "type": [ - "string", - "null" - ] + "name": { + "type": "string", + "description": "The variable the app sees." }, - "maintenance_updates": { - "type": [ - "boolean", - "null" - ] + "optional": { + "type": "boolean" }, - "usage_alerts": { - "type": [ - "boolean", - "null" - ] + "set": { + "type": "boolean", + "description": "Whether the connection holds a value for `from`." } } }, - "UpdateWorkspaceAiModeRequest": { + "DeleteBindingRequest": { "type": "object", + "required": [ + "principal", + "resource", + "role" + ], "properties": { - "mode": { - "type": [ - "string", - "null" - ], - "description": "`\"managed\"`, `\"byok\"`, or `null` to clear the per-workspace override." + "principal": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "role": { + "type": "string" } } }, - "UpdateWorkspaceEnvRequest": { + "DeployRequest": { "type": "object", "required": [ - "env_vars" + "content", + "allow_reimage" ], "properties": { - "env_vars": { - "type": "object", + "allow_reimage": { + "type": "boolean" + }, + "confirm_strategy_change": { + "type": "boolean" + }, + "content": { + "type": "string" + }, + "deployment_strategy": { + "type": [ + "string", + "null" + ] + }, + "secrets": { + "type": [ + "object", + "null" + ], "additionalProperties": { "type": "string" }, @@ -12280,606 +3059,598 @@ } } }, - "UrlResponse": { + "ExchangeRequest": { "type": "object", "required": [ - "url" + "token" ], "properties": { - "url": { + "token": { "type": "string" } } }, - "UsageExample": { + "ExchangeResponse": { "type": "object", - "description": "A copy-pasteable API usage example for a template app.", "required": [ - "language", - "label", - "code" + "token", + "expires_at", + "workspace_id", + "repository", + "source_ref", + "source_commit", + "ci_run_url", + "repository_private" ], "properties": { - "code": { - "type": "string", - "description": "Code snippet with optional placeholders" + "ci_run_url": { + "type": "string" }, - "description": { + "expires_at": { "type": "string", - "description": "Optional description shown below the code block" + "format": "date-time" }, - "label": { - "type": "string", - "description": "Human-readable label for this example" + "repository": { + "type": "string" }, - "language": { - "type": "string", - "description": "Language/format identifier: \"curl\", \"python\", \"javascript\"" + "repository_private": { + "type": "boolean" + }, + "source_commit": { + "type": "string" + }, + "source_ref": { + "type": "string" + }, + "token": { + "type": "string" + }, + "workspace_id": { + "type": "string" } } }, - "User": { + "ForceChangePasswordRequest": { "type": "object", "required": [ - "id", "email", - "created_at" + "temporary_password", + "new_password" ], "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, "email": { "type": "string" }, - "id": { + "new_password": { "type": "string" }, - "name": { - "type": [ - "string", - "null" - ] + "temporary_password": { + "type": "string" } } }, - "UserResponse": { + "ForkRequest": { "type": "object", "required": [ - "id", - "email", - "subscription" + "source_repository_id", + "installation_id", + "repository_id", + "branch", + "manifest_path" ], "properties": { - "email": { + "branch": { "type": "string" }, - "id": { + "installation_id": { + "type": "integer", + "format": "int64" + }, + "manifest_path": { "type": "string" }, - "name": { - "type": [ - "string", - "null" - ] + "repository_id": { + "type": "integer", + "format": "int64" }, - "subscription": { - "type": "string" + "source_repository_id": { + "type": "integer", + "format": "int64" } } }, - "UserSettings": { + "GenerateRequest": { "type": "object", "required": [ - "user_id", - "default_region", - "default_image", - "usage_alerts", - "maintenance_updates", - "updated_at" + "repository", + "branch", + "settings" ], "properties": { - "avatar_url": { - "type": [ - "string", - "null" - ] - }, - "default_image": { - "type": "string" - }, - "default_region": { + "branch": { "type": "string" }, - "display_name": { + "existing": { "type": [ - "string", - "null" - ] - }, - "maintenance_updates": { - "type": "boolean" - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "usage_alerts": { - "type": "boolean" + "string", + "null" + ] }, - "user_id": { + "repository": { "type": "string" + }, + "settings": { + "$ref": "#/components/schemas/Settings" } } }, - "VerifiedPromotionResult": { + "GetMeResponse": { "type": "object", "required": [ - "vendor", - "slug", - "version", - "promoted" + "user" ], "properties": { - "promoted": { - "type": "boolean" - }, - "slug": { - "type": "string" - }, - "vendor": { - "type": "string" - }, - "version": { - "type": "string" + "user": { + "$ref": "#/components/schemas/UserResponse" } } }, - "VerifiedPromotionWebhookRequest": { + "GithubBindingResponse": { "type": "object", "required": [ - "verified" + "binding" ], "properties": { - "event_id": { - "type": [ - "string", - "null" - ], - "description": "Optional event ID. `X-GitHub-Delivery` is preferred when present." - }, - "verified": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VerifiedRecipeRef" - } + "binding": { + "$ref": "#/components/schemas/GithubRepoBinding" } } }, - "VerifiedPromotionWebhookResponse": { + "GithubBindingsResponse": { "type": "object", "required": [ - "processed", - "event_id", - "results" + "bindings" ], "properties": { - "event_id": { - "type": "string" - }, - "processed": { - "type": "boolean" - }, - "results": { + "bindings": { "type": "array", "items": { - "$ref": "#/components/schemas/VerifiedPromotionResult" + "$ref": "#/components/schemas/GithubRepoBinding" } } } }, - "VerifiedRecipeRef": { + "GithubConnection": { "type": "object", "required": [ - "vendor", - "slug", - "version" + "user_id", + "installation_id", + "github_user_id", + "github_login", + "account_login" ], "properties": { - "slug": { + "account_login": { "type": "string" }, - "vendor": { + "github_login": { "type": "string" }, - "version": { + "github_user_id": { + "type": "integer", + "format": "int64" + }, + "installation_id": { + "type": "integer", + "format": "int64" + }, + "user_id": { "type": "string" } } }, - "Visibility": { - "type": "string", - "enum": [ - "private", - "public", - "privileged" - ] - }, - "Vm": { + "GithubJob": { "type": "object", "required": [ + "builds", "id", - "user_id", - "node_id", - "name", + "binding_id", + "source_commit", + "source_ref", "status", - "image", - "ram_mb", - "vcpu_count", - "disk_size_mb", - "created_at", - "updated_at" + "created_at" ], "properties": { - "ai_mode": { - "type": [ - "string", - "null" - ], - "description": "Per-workspace override for the AI mode (`managed` or `byok`).\n`None` means inherit from `users.ai_mode` (the per-account default)." + "binding_id": { + "type": "string", + "format": "uuid" }, - "cloned_from": { - "type": [ - "string", - "null" - ], - "description": "Bluegreen preview lineage. `None` = a normal workspace. `Some(source_id)`\n= this VM is a COW clone of `source_id`, booted as a hidden preview;\npromote repoints the prod subdomain's edge route to it. See\n[`Vm::is_preview`]." + "builds": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Build" + } }, "created_at": { "type": "string", "format": "date-time" }, - "creation_attempts": { - "type": "integer", - "format": "int32" + "id": { + "type": "string", + "format": "uuid" }, - "creation_started_at": { + "message": { "type": [ "string", "null" - ], - "format": "date-time" + ] }, - "disk_size_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 + "source_commit": { + "type": "string" }, - "env_vars": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } + "source_ref": { + "type": "string" }, - "failure_code": { - "type": [ - "string", - "null" - ] + "status": { + "type": "string" + } + } + }, + "GithubProject": { + "type": "object", + "required": [ + "id", + "user_id", + "workspace_id", + "repository_name", + "deployment_mode", + "deployment_strategy", + "production_branch", + "manifest_path", + "allow_reimage" + ], + "properties": { + "allow_reimage": { + "type": "boolean" + }, + "deployment_mode": { + "type": "string" }, - "failure_reason": { + "deployment_strategy": { + "type": "string" + }, + "id": { + "type": "string", + "format": "uuid" + }, + "installation_id": { "type": [ - "string", + "integer", "null" - ] + ], + "format": "int64" }, - "id": { + "manifest_path": { "type": "string" }, - "image": { + "production_branch": { "type": "string" }, - "image_digest": { + "repository_id": { "type": [ "string", "null" - ], - "description": "Content-addressed image this workspace is pinned to. When set, the\nworkspace boots from this registry image (staged as the rootfs on first\nboot) instead of the named base in `image`. `None` = the named-base path." + ] + }, + "repository_name": { + "type": "string" }, - "ip_address": { + "repository_owner_id": { "type": [ "string", "null" ] }, - "name": { + "user_id": { "type": "string" }, - "node_id": { + "workspace_id": { "type": "string" + } + } + }, + "GithubRepoBinding": { + "type": "object", + "required": [ + "id", + "user_id", + "workspace_id", + "repository_name", + "status", + "claim_expires_at", + "created_at" + ], + "properties": { + "claim_expires_at": { + "type": "string", + "format": "date-time" }, - "ram_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 + "created_at": { + "type": "string", + "format": "date-time" }, - "service_spec_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } + "id": { + "type": "string", + "format": "uuid" }, - "setup_script_ids": { + "repository_id": { "type": [ - "array", + "string", "null" - ], - "items": { - "type": "string" - } + ] }, - "status": { - "$ref": "#/components/schemas/VmStatus" + "repository_name": { + "type": "string" }, - "template_id": { + "repository_owner_id": { "type": [ "string", "null" ] }, - "updated_at": { - "type": "string", - "format": "date-time" + "status": { + "type": "string" }, "user_id": { "type": "string" }, - "vcpu_count": { - "type": "integer", - "format": "int32", - "minimum": 0 + "workspace_id": { + "type": "string" } } }, - "VmStatus": { - "type": "string", - "enum": [ - "provisioned", - "provisioning", - "starting", - "running", - "stopping", - "stopped", - "deleting", - "failed" - ] - }, - "Volume": { + "InspectRequest": { "type": "object", - "description": "A persistent volume attached to a workspace VM.\n\nBacked by a host ext4 file (`host_path`) mounted in-guest at `mount_path`\nvia a second Firecracker drive. Separate from the rootfs image, so its data\nsurvives a rootfs/image swap. Serialized over the wire for `rig volume`.", "required": [ - "id", - "workspace_id", - "node_id", - "name", - "size_mb", - "mount_path", - "host_path", - "created_at" + "installation_id", + "repository_id", + "branch", + "manifest_path" ], "properties": { - "created_at": { - "type": "string", - "format": "date-time" + "branch": { + "type": "string" + }, + "installation_id": { + "type": "integer", + "format": "int64" }, - "host_path": { + "manifest_path": { "type": "string" }, - "id": { + "repository_id": { + "type": "integer", + "format": "int64" + } + } + }, + "Inspection": { + "type": "object", + "required": [ + "repository", + "commit", + "settings", + "requires_pull_request", + "manifest_paths" + ], + "properties": { + "commit": { "type": "string" }, - "migrated_at": { + "content": { "type": [ "string", "null" - ], - "format": "date-time", - "description": "Set once the one-time rootfs->volume data copy has run (advisory; the\nin-guest sentinel on the volume is authoritative)." + ] }, - "mount_path": { - "type": "string" + "manifest_paths": { + "type": "array", + "items": { + "type": "string" + } }, - "name": { - "type": "string" + "repository": { + "$ref": "#/components/schemas/Repository" + }, + "requires_pull_request": { + "type": "boolean" }, - "node_id": { + "settings": { + "$ref": "#/components/schemas/Settings" + } + } + }, + "LinkRequest": { + "type": "object", + "required": [ + "account_email", + "current_password" + ], + "properties": { + "account_email": { "type": "string" }, - "size_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 + "current_password": { + "type": "string" + } + }, + "additionalProperties": false + }, + "LoginRequest": { + "type": "object", + "required": [ + "email", + "password" + ], + "properties": { + "email": { + "type": "string" }, - "workspace_id": { + "password": { "type": "string" } } }, - "VolumeResponse": { + "ManifestPaths": { + "type": "object", + "required": [ + "paths" + ], + "properties": { + "paths": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "Owner": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + } + } + }, + "Page_ApiKeyResponse": { "type": "object", + "description": "Paginated response envelope. `next_cursor: None` ⇒ last page.", "required": [ - "volume" + "items" ], "properties": { - "volume": { - "$ref": "#/components/schemas/Volume" + "items": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "key_preview", + "created_at" + ], + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "key_preview": { + "type": "string" + }, + "last_used_at": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "next_cursor": { + "type": [ + "string", + "null" + ] } } }, - "WorkspaceAiModeResponse": { + "PathsRequest": { "type": "object", "required": [ - "mode", - "source" + "installation_id", + "repository_id", + "branch" ], "properties": { - "mode": { - "type": "string", - "description": "Effective AI mode after resolving overrides." + "branch": { + "type": "string" }, - "source": { - "$ref": "#/components/schemas/WorkspaceAiModeSource" + "installation_id": { + "type": "integer", + "format": "int64" + }, + "repository_id": { + "type": "integer", + "format": "int64" } } }, - "WorkspaceAiModeSource": { - "type": "string", - "description": "Source of the effective AI mode for a workspace.", - "enum": [ - "workspace", - "user_default" - ] - }, - "WorkspaceDefinitionChildPreview": { + "PollCliSessionResponse": { "type": "object", "required": [ - "deploy_ref", - "source", - "trust_tier", - "status", - "catalog_id", - "slug", - "version", - "name", - "resources", - "depends_on" + "status" ], "properties": { - "catalog_id": { - "type": "string" - }, - "configurable_params": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamSpec" - }, - "description": "Configurable parameters this child app exposes. The deploy form uses\nthese to render per-app `ParamFields` editors when launching the\nworkspace definition into a workspace." - }, - "credentials_declared": { - "type": "boolean", - "description": "True if this child declares default credentials (server-generated or\npre-filled). Surfaces a \"credentials required\" hint in the deploy form." - }, - "depends_on": { - "type": "array", - "items": { - "type": "string" - } - }, - "deploy_ref": { - "type": "string" - }, - "managed": { - "type": "boolean", - "description": "True if the recipe opts into Rigbox's managed AI proxy when installed." - }, - "name": { - "type": "string" - }, - "resources": { - "$ref": "#/components/schemas/DeployResourceRequirements" - }, - "slug": { - "type": "string" + "api_key": { + "type": [ + "string", + "null" + ] }, - "source": { - "type": "string" + "email": { + "type": [ + "string", + "null" + ] }, "status": { "type": "string" - }, - "trust_tier": { - "type": "string" - }, - "vendor": { + } + } + }, + "PortalRequest": { + "type": "object", + "properties": { + "return_url": { "type": [ "string", "null" ] - }, - "version": { - "type": "string" } } }, - "WorkspaceDefinitionExpectedAppPreview": { + "PrincipalLookupResponse": { "type": "object", "required": [ - "name", - "port", - "protocol", - "managed", - "depends_on" + "principals" ], "properties": { - "configurable_params": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ParamSpec" - } - }, - "credentials_declared": { - "type": "boolean" - }, - "depends_on": { - "type": "array", - "items": { - "type": "string" - } - }, - "managed": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "protocol": { - "type": "string" - }, - "system_tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "usage_examples": { + "principals": { "type": "array", "items": { - "$ref": "#/components/schemas/UsageExample" + "$ref": "#/components/schemas/PrincipalLookupResult" } } } }, - "WorkspaceDefinitionLogSourcePreview": { + "PrincipalLookupResult": { "type": "object", "required": [ - "source_type", - "source_ref", - "is_primary" + "principal", + "user_id", + "email" ], "properties": { "display_name": { @@ -12888,824 +3659,616 @@ "null" ] }, - "is_primary": { - "type": "boolean" + "email": { + "type": "string" }, - "source_ref": { + "principal": { "type": "string" }, - "source_type": { + "user_id": { "type": "string" } } }, - "WorkspaceDefinitionPreviewResponse": { + "ProjectList": { "type": "object", "required": [ - "deploy_ref", - "source", - "trust_tier", - "effective_trust_tier", - "status", - "base_template_id", - "name", - "description", - "category", - "resources", - "apps", - "warnings" + "projects", + "jobs" ], "properties": { - "apps": { + "jobs": { "type": "array", "items": { - "$ref": "#/components/schemas/WorkspaceDefinitionChildPreview" + "$ref": "#/components/schemas/GithubJob" } }, - "base_template_id": { - "type": "string" - }, - "base_template_minimums": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/WorkspaceDefinitionResourcePlanResponse", - "description": "Floor minimums sourced from the base template (used by client UI as floors)." - } - ] - }, - "category": { - "type": "string" - }, - "deploy_ref": { - "type": "string" - }, - "description": { - "type": "string" - }, - "effective_trust_tier": { - "type": "string" - }, - "expected_apps": { + "projects": { "type": "array", "items": { - "$ref": "#/components/schemas/WorkspaceDefinitionExpectedAppPreview" - }, - "description": "Apps pre-installed in the base template image (only for built-in workspace definitions)." - }, - "image": { + "$ref": "#/components/schemas/GithubProject" + } + } + } + }, + "PurchaseRequest": { + "type": "object", + "required": [ + "operation_id" + ], + "properties": { + "cancel_url": { "type": [ "string", "null" - ], - "description": "Final image the workspace boots from (e.g. \"base\", \"firecrawl\").\nLifted from `manifest.workspace.image` so the catalog UI can show\nthe actual VM image without reading the raw manifest." - }, - "image_bound": { - "type": "boolean", - "description": "True when this workspace definition's apps/services live inside `image`\nrather than being installed via app recipes at provision time.\nImage-bound definitions (e.g. firecrawl) start faster but the\nmanifest can't fully describe what's inside the image." + ] }, - "log_sources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkspaceDefinitionLogSourcePreview" - }, - "description": "Log source presets shipped with the base template (file paths,\nsystemd units) for the workspace-level Logs panel." + "operation_id": { + "type": "string", + "format": "uuid" }, - "manifest_digest": { + "plan": { "type": [ "string", "null" ] }, - "manifest_json": { - "description": "Raw manifest JSON for the \"View manifest\" affordance." - }, - "name": { - "type": "string" - }, - "portability_notes": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Author-declared notes describing what the image carries that the\nmanifest can't fully describe. Only populated when image_bound." - }, - "resources": { - "$ref": "#/components/schemas/WorkspaceDefinitionResourcePlanResponse" + "return_url": { + "type": [ + "string", + "null" + ] }, - "service_specs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkspaceDefinitionServiceSpecPreview" - }, - "description": "Available systemd service specs shipped with the base template." + "success_url": { + "type": [ + "string", + "null" + ] + } + } + }, + "RepoList": { + "type": "object", + "required": [ + "repositories" + ], + "properties": { + "next_page": { + "type": [ + "integer", + "null" + ], + "format": "int32", + "minimum": 0 }, - "setup_scripts": { + "repositories": { "type": "array", "items": { - "$ref": "#/components/schemas/WorkspaceDefinitionSetupScriptPreview" - }, - "description": "Available setup scripts shipped with the base template." - }, - "source": { + "$ref": "#/components/schemas/Repository" + } + } + } + }, + "Repository": { + "type": "object", + "required": [ + "id", + "full_name", + "default_branch", + "private", + "owner" + ], + "properties": { + "default_branch": { "type": "string" }, - "status": { + "full_name": { "type": "string" }, - "trust_tier": { - "type": "string" + "id": { + "type": "integer", + "format": "int64" }, - "verify_binaries": { + "owner": { + "$ref": "#/components/schemas/Owner" + }, + "private": { + "type": "boolean" + } + } + }, + "RolePreset": { + "type": "object", + "required": [ + "scope_kind", + "role", + "permissions", + "required_resource_tags", + "match_tag_keys", + "system_managed", + "updated_at" + ], + "properties": { + "match_tag_keys": { "type": "array", "items": { "type": "string" - }, - "description": "Binaries the workspace expects pre-installed in `image` (checked\nat first boot via `which`). Lifted from\n`manifest.template.verify_binaries` so the catalog UI can show\nusers what binaries the image carries." + } }, - "warnings": { + "permissions": { "type": "array", "items": { "type": "string" } }, - "workspace_services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkspaceDefinitionWorkspaceServicePreview" + "required_resource_tags": { + "type": "object", + "additionalProperties": { + "type": "string" }, - "description": "Backing services (databases, brokers) provisioned by the base template." + "propertyNames": { + "type": "string" + } + }, + "role": { + "type": "string" + }, + "scope_kind": { + "type": "string" + }, + "system_managed": { + "type": "boolean" + }, + "updated_at": { + "type": "string", + "format": "date-time" } } }, - "WorkspaceDefinitionResourcePlanResponse": { + "RolePresetsResponse": { "type": "object", "required": [ - "ram_mb", - "vcpu_count", - "disk_mb" + "presets" ], "properties": { - "disk_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "ram_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "vcpu_count": { - "type": "integer", - "format": "int32", - "minimum": 0 + "presets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RolePreset" + } } } }, - "WorkspaceDefinitionServiceSpecPreview": { + "SaveRequest": { "type": "object", "required": [ - "name", - "working_directory", - "restart_policy", - "auto_enable" + "installation_id", + "repository_id", + "workspace_id", + "branch", + "manifest_path", + "expected_commit", + "content", + "pull_request", + "deployment_mode", + "allow_reimage" ], "properties": { - "auto_enable": { + "allow_reimage": { "type": "boolean" }, - "name": { + "branch": { "type": "string" }, - "restart_policy": { + "confirm_strategy_change": { + "type": "boolean" + }, + "content": { "type": "string" }, - "working_directory": { + "deployment_mode": { "type": "string" - } - } - }, - "WorkspaceDefinitionSetupScriptPreview": { - "type": "object", - "required": [ - "name", - "run_on", - "order" - ], - "properties": { - "name": { + }, + "deployment_strategy": { + "type": [ + "string", + "null" + ] + }, + "expected_commit": { + "type": "string" + }, + "installation_id": { + "type": "integer", + "format": "int64" + }, + "manifest_path": { "type": "string" }, - "order": { + "pull_request": { + "type": "boolean" + }, + "replace_binding_id": { + "type": [ + "string", + "null" + ], + "format": "uuid" + }, + "repository_id": { "type": "integer", - "format": "int32" + "format": "int64" + }, + "secrets": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + } }, - "run_on": { + "workspace_id": { "type": "string" } } }, - "WorkspaceDefinitionWorkspaceServicePreview": { + "SecretStatus": { "type": "object", "required": [ - "name", - "kind", - "exposed" + "binding_id", + "workspace_id", + "repository", + "branch", + "manifest_path", + "commit", + "secrets" ], "properties": { - "exposed": { - "type": "boolean" + "binding_id": { + "type": "string", + "format": "uuid", + "description": "The GitHub connection (repository binding) the secrets belong to." + }, + "branch": { + "type": "string" + }, + "commit": { + "type": "string", + "description": "The branch head whose rig.yaml declared `secrets`." + }, + "manifest_path": { + "type": "string" }, - "kind": { + "repository": { "type": "string" }, - "log_sources": { + "secrets": { "type": "array", "items": { - "$ref": "#/components/schemas/WorkspaceDefinitionLogSourcePreview" + "$ref": "#/components/schemas/DeclaredSecret" } }, - "name": { - "type": "string" - }, - "port": { + "updated": { "type": [ - "integer", + "array", "null" ], - "format": "int32", - "minimum": 0 + "items": { + "type": "string" + }, + "description": "Update only: the names whose stored value this request changed." + }, + "workspace_id": { + "type": "string" } } }, - "WorkspaceFailure": { + "Settings": { "type": "object", - "description": "Structured failure surface returned by the workspace API when a workspace\nis in `Failed` status. Phase 4 Task 4.3 wires this into the response.", "required": [ - "code", - "message", - "retryable", - "occurred_at", - "attempts" + "name", + "port", + "start", + "install" ], "properties": { - "attempts": { - "type": "integer", - "format": "int32" + "build": { + "type": [ + "string", + "null" + ] }, - "code": { + "install": { "type": "string" }, - "message": { + "memory_mb": { + "type": [ + "integer", + "null" + ], + "format": "int32", + "minimum": 0 + }, + "name": { "type": "string" }, - "occurred_at": { - "type": "string", - "format": "date-time" + "port": { + "type": "integer", + "format": "int32", + "minimum": 0 }, - "retryable": { - "type": "boolean" + "start": { + "type": "string" } } }, - "WorkspaceMetrics": { + "SignupRequest": { "type": "object", "required": [ - "workspace_id", - "ram_used_mb", - "ram_total_mb", - "disk_used_mb", - "disk_total_mb", - "cpu_percent", - "updated_at" + "email", + "password" ], "properties": { - "cpu_percent": { - "type": "number", - "format": "double" - }, - "disk_total_mb": { - "type": "integer", - "format": "int32" - }, - "disk_used_mb": { - "type": "integer", - "format": "int32" - }, - "ram_total_mb": { - "type": "integer", - "format": "int32" - }, - "ram_used_mb": { - "type": "integer", - "format": "int32" + "email": { + "type": "string" }, - "updated_at": { - "type": "string", - "format": "date-time" + "name": { + "type": [ + "string", + "null" + ] }, - "workspace_id": { + "password": { "type": "string" } } }, - "WorkspaceMetricsRange": { - "type": "string", - "enum": [ - "1h", - "6h", - "24h", - "7d" - ] - }, - "WorkspaceMetricsSeries": { + "SimulateAccessRequest": { "type": "object", "required": [ - "cpu_percent", - "memory_used_mb", - "memory_limit_mb", - "disk_used_mb", - "disk_total_mb", - "network_rx_bps", - "network_tx_bps" + "resource", + "action" ], "properties": { - "cpu_percent": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "disk_total_mb": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "disk_used_mb": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "memory_limit_mb": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } - }, - "memory_used_mb": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } + "action": { + "type": "string" }, - "network_rx_bps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } + "principal": { + "type": [ + "string", + "null" + ] }, - "network_tx_bps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricPoint" - } + "resource": { + "type": "string" } } }, - "WorkspaceMetricsSeriesResponse": { + "SimulateAccessResponse": { "type": "object", "required": [ - "range", - "step_seconds", - "workspace_id", - "source", - "series" + "principal", + "resource", + "action", + "allowed", + "reason" ], "properties": { - "node_id": { - "type": [ - "string", - "null" - ] - }, - "range": { - "$ref": "#/components/schemas/WorkspaceMetricsRange" + "action": { + "type": "string" }, - "series": { - "$ref": "#/components/schemas/WorkspaceMetricsSeries" + "allowed": { + "type": "boolean" }, - "source": { - "$ref": "#/components/schemas/WorkspaceMetricsSource" + "principal": { + "type": "string" }, - "step_seconds": { - "type": "integer", - "format": "int64" + "reason": { + "type": "string" }, - "workspace_id": { + "resource": { "type": "string" } } }, - "WorkspaceMetricsSource": { + "SourceRequest": { "type": "object", "required": [ - "cpu", - "network", - "memory", - "disk" + "repository", + "branch", + "manifest_path" ], "properties": { - "cpu": { + "branch": { "type": "string" }, - "disk": { + "manifest_path": { "type": "string" }, - "memory": { + "repository": { "type": "string" - }, - "network": { + } + } + }, + "TagsResponse": { + "type": "object", + "required": [ + "resource", + "tags" + ], + "properties": { + "resource": { "type": "string" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + } } } }, - "WorkspaceMetricsSummaryResponse": { + "ThrottleBindingResponse": { "type": "object", "required": [ - "range", - "workspace_id", - "cpu_avg_percent", - "cpu_p95_percent", - "memory_used_mb", - "memory_limit_mb", - "disk_used_mb", - "disk_total_mb", - "network_rx_bytes", - "network_tx_bytes", - "guest_metrics_fresh" + "resource" ], "properties": { - "cpu_avg_percent": { - "type": "number", - "format": "double" - }, - "cpu_p95_percent": { - "type": "number", - "format": "double" - }, - "disk_total_mb": { - "type": "number", - "format": "double" - }, - "disk_used_mb": { - "type": "number", - "format": "double" - }, - "guest_metrics_fresh": { - "type": "boolean" - }, - "memory_limit_mb": { - "type": "number", - "format": "double" - }, - "memory_used_mb": { - "type": "number", - "format": "double" - }, - "network_rx_bytes": { - "type": "number", - "format": "double" - }, - "network_tx_bytes": { - "type": "number", - "format": "double" - }, - "range": { - "$ref": "#/components/schemas/WorkspaceMetricsRange" - }, - "updated_at": { + "profile": { "type": [ "string", "null" ] }, - "workspace_id": { + "resource": { "type": "string" } } }, - "WorkspaceService": { + "ThrottlePreset": { "type": "object", - "description": "Runtime backing service instance tracked for health monitoring.\nDistinct from ServiceSpec (which generates systemd units for custom processes).\nWorkspaceService tracks apt-managed daemons like PostgreSQL, Redis, RabbitMQ.", "required": [ - "id", - "workspace_id", "name", - "kind", - "health_cmd", - "status", - "exposed", - "source", - "created_at", + "rules", + "system_managed", "updated_at" ], "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "exposed": { - "type": "boolean" - }, - "health_cmd": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "log_sources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkspaceServiceLogSource" - } - }, "name": { "type": "string" }, - "port": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "source": { - "type": "string" - }, - "status": { - "type": "string" - }, - "unit_name": { - "type": [ - "string", - "null" - ] + "rules": {}, + "system_managed": { + "type": "boolean" }, "updated_at": { "type": "string", "format": "date-time" - }, - "workspace_id": { - "type": "string" } } }, - "WorkspaceServiceLogSource": { + "ThrottlePresetsResponse": { "type": "object", "required": [ - "source_type", - "source_ref" + "presets" ], "properties": { - "display_name": { - "type": [ - "string", - "null" - ] - }, - "is_primary": { - "type": "boolean" - }, - "source_ref": { - "type": "string" - }, - "source_type": { - "type": "string" + "presets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ThrottlePreset" + } } } }, - "WorkspaceServiceSpec": { + "UpdateBindingRequest": { "type": "object", - "description": "A backing service required by the workspace (database, cache, broker).\nCreated as workspace_services records during quick-deploy.", "required": [ - "name", - "kind", - "unit_name", - "health_cmd", - "exposed" + "principal", + "resource", + "current_role", + "new_role" ], "properties": { - "exposed": { - "type": "boolean" - }, - "health_cmd": { + "current_role": { "type": "string" }, - "kind": { + "new_role": { "type": "string" }, - "log_sources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TemplateLogSourcePreset" - } - }, - "name": { + "principal": { "type": "string" }, - "port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "unit_name": { + "resource": { "type": "string" } } }, - "WorkspaceServicesResponse": { + "UpdateSecrets": { "type": "object", "required": [ - "services" + "secrets" ], "properties": { - "services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkspaceService" + "secrets": { + "type": "object", + "description": "Values keyed by the runtime-secret names rig.yaml declares (each\nentry's `from:`, else its name). Merged into the stored secrets:\nnames not supplied keep their values.", + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" } } } }, - "WorkspaceTemplate": { + "UpdateTagsRequest": { "type": "object", "required": [ - "id", - "name", - "description", - "icon", - "image", - "ram_mb", - "vcpu_count", - "disk_size_mb", - "category", - "default_log_sources" + "resource", + "tags" ], "properties": { - "category": { - "type": "string" - }, - "coming_soon": { - "type": "boolean", - "description": "If true, template is shown in UI but cannot be deployed yet." - }, - "default_log_sources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TemplateLogSourcePreset" - } - }, - "description": { + "resource": { "type": "string" }, - "disk_size_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "env_file_copies": { - "type": "array", - "items": { + "tags": { + "type": "object", + "additionalProperties": { "type": "string" }, - "description": "Copy .env to these additional paths at first boot." - }, - "expected_apps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TemplateExpectedApp" + "propertyNames": { + "type": "string" } + } + } + }, + "UpdateThrottleBindingRequest": { + "type": "object", + "required": [ + "resource" + ], + "properties": { + "profile": { + "type": [ + "string", + "null" + ] }, - "has_tools": { - "type": "boolean", - "description": "If true, this image ships the tools binary (ArchX, Virtual Browser, etc.)." - }, - "icon": { - "type": "string" - }, - "id": { - "type": "string" - }, - "image": { - "type": "string" - }, - "image_bound": { - "type": "boolean", - "description": "True when this template's apps/services live inside the image\n(e.g. firecrawl, openclaw) rather than being installed onto a\nminimal base image at provision time. Mirrors the rule in\n`domain::community::export::image_bound` so the catalog and\n/templates UI can show the same `composable` / `image-bound`\ndistinction." - }, - "name": { + "resource": { "type": "string" - }, - "ram_mb": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "service_patches": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServicePatchSpec" - }, - "description": "Systemd services to patch with EnvironmentFile at first boot." - }, - "vcpu_count": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "verify_binaries": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Binaries to verify exist at first boot." - }, - "workspace_services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkspaceServiceSpec" - }, - "description": "Backing services (databases, caches, brokers) provisioned alongside this workspace.\nCreated as workspace_services records during quick-deploy." } } }, - "WorkspaceTool": { + "UserResponse": { "type": "object", "required": [ "id", - "name", - "description", - "icon", - "category", - "port", - "subdomain_suffix", - "discovery" + "email", + "subscription" ], "properties": { - "category": { - "type": "string" - }, - "description": { - "type": "string" - }, - "discovery": { - "$ref": "#/components/schemas/DiscoveryStrategy", - "description": "How this tool detects availability." - }, - "icon": { + "email": { "type": "string" }, "id": { "type": "string" }, - "install_hint": { + "name": { "type": [ "string", "null" - ], - "description": "User-facing install command when the tool needs setup.\nShown in the UI when the tool is unavailable or partially available." + ] }, - "name": { + "subscription": { "type": "string" - }, - "port": { - "type": "integer", - "format": "int32", - "description": "Port the tool listens on inside the VM.", - "minimum": 0 - }, - "subdomain_suffix": { - "type": "string", - "description": "Subdomain suffix - e.g. \"arch\" \u2192 arch-{ws_id}.rigbox.dev" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags indicating supported languages, runtimes, etc.", - "uniqueItems": true } } } @@ -13719,67 +4282,19 @@ }, "tags": [ { - "name": "Workspaces" - }, - { - "name": "CLI" + "name": "Auth" }, { - "name": "Observability" + "name": "Account" }, { - "name": "Auth" + "name": "GitHub Deployments" }, { "name": "API Keys" }, { "name": "Access Control" - }, - { - "name": "Apps" - }, - { - "name": "App Catalog" - }, - { - "name": "Logs" - }, - { - "name": "AI" - }, - { - "name": "Tools" - }, - { - "name": "Snapshots" - }, - { - "name": "SSH Keys" - }, - { - "name": "Templates" - }, - { - "name": "Setup Scripts" - }, - { - "name": "Service Specs" - }, - { - "name": "Deploy" - }, - { - "name": "Community" - }, - { - "name": "User Settings" - }, - { - "name": "Roadmap" - }, - { - "name": "System" } ] -} +} \ No newline at end of file diff --git a/openapi/rigbox-api.json b/openapi/rigbox-api.json index 03055aa..48a0a6e 100644 --- a/openapi/rigbox-api.json +++ b/openapi/rigbox-api.json @@ -6586,11 +6586,12 @@ "free": { "type": "number", "format": "double", - "description": "Free bucket balance (resets to 250 each month, unused expires)." + "description": "Deprecated compatibility field; always zero. Preserved legacy balances\nbelong to the canonical wallet and are not reset or expired here." }, "free_micro": { "type": "integer", - "format": "int64" + "format": "int64", + "description": "Deprecated compatibility field; always zero." }, "mode": { "type": "string" @@ -6598,29 +6599,32 @@ "pro": { "type": "number", "format": "double", - "description": "Pro bucket balance (active pro_managed gets +2000/month, rolls over)." + "description": "Deprecated compatibility alias of `remaining`; this is not a separate\npurchased or included credit bucket." }, "pro_micro": { "type": "integer", - "format": "int64" + "format": "int64", + "description": "Deprecated compatibility alias of `remaining_micro`." }, "remaining": { "type": "number", "format": "double", - "description": "Total spendable credits = free + pro." + "description": "Available managed credits: canonical wallet balance minus outstanding\nrequest holds. May be negative after a refund or dispute. New plans have\nno automatic AI credit grant." }, "remaining_micro": { "type": "integer", - "format": "int64" + "format": "int64", + "description": "Exact available wallet credits in microcredits: 1,000,000 per credit." }, "total": { "type": "number", "format": "double", - "description": "Credits granted this cycle (the monthly entitlement: 250 free, plus 2000\nfor an active pro_managed subscriber). May be below `remaining` when pro\ncredits have rolled over from prior months." + "description": "Canonical wallet balance before outstanding holds. Includes preserved\nopening balances, purchased credit packs and verified legacy paid-period\ngrants. This is not a monthly allowance and has no calendar reset." }, "total_micro": { "type": "integer", - "format": "int64" + "format": "int64", + "description": "Exact wallet balance before holds in microcredits: 1,000,000 per credit." } } }, @@ -8807,7 +8811,8 @@ "max_ram_total_mb", "max_disk_total_mb", "max_vcpu_per_vm", - "max_running_vcpus" + "max_running_vcpus", + "sustained_cpu_millis" ], "properties": { "max_disk_total_mb": { @@ -8839,6 +8844,11 @@ "type": "integer", "format": "int32", "minimum": 0 + }, + "sustained_cpu_millis": { + "type": "integer", + "format": "int32", + "minimum": 0 } } }, @@ -9153,18 +9163,43 @@ "plan", "custom", "limits", - "usage" + "usage", + "compute_allowed", + "entitlement_status", + "billing_revision" ], "properties": { + "billing_paid_through": { + "type": [ + "string", + "null" + ] + }, + "billing_revision": { + "type": "integer", + "format": "int64" + }, + "compute_allowed": { + "type": "boolean" + }, "custom": { "type": "boolean" }, + "entitlement_status": { + "type": "string" + }, "limits": { "$ref": "#/components/schemas/EffectiveLimits" }, "plan": { "type": "string" }, + "pricing_transition_until": { + "type": [ + "string", + "null" + ] + }, "usage": { "$ref": "#/components/schemas/LimitsUsage" } @@ -9415,9 +9450,15 @@ "workspace_count", "running_vcpus", "total_disk_mb", - "total_ram_mb" + "total_ram_mb", + "running_cpu_millis" ], "properties": { + "running_cpu_millis": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, "running_vcpus": { "type": "integer", "format": "int32", diff --git a/scripts/build-navigation.py b/scripts/build-navigation.py index e637f7c..000cb20 100644 --- a/scripts/build-navigation.py +++ b/scripts/build-navigation.py @@ -20,7 +20,7 @@ def area(label,pages): original=old['groups'];Path('scripts/api-navigation-base.json').write_text(json.dumps(original,indent=2)+'\n') api={g['group']:g for g in original} areas=[ -area('Start here',[group('Get started',['introduction','quickstart','guides/install-cli','concepts/core'])]), +area('Start here',[group('Get started',['introduction','quickstart','guides/install-cli','concepts/core','concepts/pricing-and-billing'])]), area('Deploy applications',[ group('Deploy',['deploy/overview','guides/deploying',group('GitHub',['guides/github-actions','guides/deploy-button'],'guides/github'),group('Multi-app projects',['deploy/dependencies','deploy/single-app'],'deploy/multi-app')]), group('App releases',['deploy/development-loop','deploy/stage-and-activate','deploy/app-rollback','deploy/release-ownership']), @@ -34,7 +34,7 @@ def area(label,pages): group('Storage',[group('Persistent volumes',['workspaces/volume-management'],'guides/persistent-volumes'),group('Snapshots',['workspaces/snapshot-restore','workspaces/recovery-limits'],'guides/snapshots')]), group('Environment',['guides/workspace-services','guides/setup-scripts','guides/service-specs'])]), area('AI and tools',[ - group('AI',['ai/overview','guides/ai-coding-tools','guides/managed-proxy','guides/byok']), + group('AI',['ai/overview','guides/ai-coding-tools','guides/managed-proxy','ai/managed-wallet','guides/byok']), group('Tools',['guides/catalog','ai/spawn','guides/virtual-browser','guides/firecrawl','guides/architecture-explorer'])]), area('Operate and troubleshoot',[ group('Observe',['operate/overview','operate/app-logs','operate/build-logs','operate/telemetry']), @@ -46,9 +46,10 @@ def area(label,pages): group('Use the CLI',['cli-reference/cli','cli-reference/authentication','guides/using-cli','cli-reference/configuration','cli-reference/execution-modes'])]), area('Build on Rigbox',[ group('Integrate',['build/overview','build/quickstart','build/workspace-lifecycle','build/deploy-monitor','guides/build-hosting-platform','build/api-conventions']), - group('Platform',['concepts/architecture','concepts/security']), + group('Platform',['concepts/architecture','concepts/security','verification/paid-pricing']), group('First-party integrations',['sandbox-api-surface','clawd-api-surface','clawd-runtime-services'])])] api_groups=[group('Start',['api-reference/overview']),group('Access',[api['API Keys'],api['Access Control']]),group('Workspaces',[api['Workspaces'],api['Workspace Services'],api['SSH Keys']]),group('Applications and releases',[api['Apps'],api['App Logs'],group('App releases',[f'api-reference/app-releases/{x}' for x in ['list','create','get','activate','logs']]),api['Local tunnels']]),group('Storage',[api['Snapshots']]),group('AI and tools',[api['AI'],api['Managed Proxy'],api['Tools']]),group('Registry',[api['App Catalog'],api['Templates'],api['Setup Scripts'],api['Service Specs']]),group('Account and platform',[api['User Settings'],api['Roadmap'],api['System']])] +api_groups[-1]['pages'].insert(0,group('Billing',[f'api-reference/billing/{name}' for name in ['catalog','subscription-status','create-checkout','change','credit-pack-checkout','wallet-history','operation-status','create-portal']])) extra=Path('scripts/deployment-api-navigation.json') if extra.exists(): for name,pages in json.loads(extra.read_text())['groups'].items(): diff --git a/scripts/sync-paid-schemas.py b/scripts/sync-paid-schemas.py new file mode 100644 index 0000000..09ee678 --- /dev/null +++ b/scripts/sync-paid-schemas.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Synchronize paid-v1 gateway components and verify the exact auth export.""" +import argparse +import hashlib +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +NAMES = ("AiCredits", "EffectiveLimits", "LimitsUsage", "GetUserLimitsResponse") +TARGETS = ("rigbox-api.json",) + + +def source_components(path): + schemas = json.loads(path.read_text())["components"]["schemas"] + selected = {name: schemas[name] for name in NAMES} + wallet = selected["AiCredits"]["properties"] + if "always zero" not in wallet["free"]["description"]: + raise ValueError("Source does not describe the canonical paid-v1 wallet") + if "compute_allowed" not in selected["GetUserLimitsResponse"]["properties"]: + raise ValueError("Source does not contain paid-v1 entitlement fields") + return selected + + +def synchronize(path, schemas, check): + spec = json.loads(path.read_text()) + current = spec["components"]["schemas"] + changed = any(current.get(name) != schema for name, schema in schemas.items()) + if check and changed: + raise ValueError(f"Paid-v1 component drift in {path.relative_to(ROOT)}") + if not check: + current.update(schemas) + path.write_text(json.dumps(spec, indent=2) + "\n") + + +def verify_auth(): + provenance = json.loads((ROOT / "verification/paid-pricing.json").read_text()) + path = ROOT / "openapi/auth-api.json" + digest = hashlib.sha256(path.read_bytes()).hexdigest() + if digest != provenance["auth_source"]["export_sha256"]: + raise ValueError("Auth schema differs from the recorded complete service export") + spec = json.loads(path.read_text()) + for endpoint in provenance["auth_source"]["billing_paths"]: + if endpoint not in spec["paths"]: + raise ValueError(f"Auth export is missing {endpoint}") + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--source", type=Path, default=ROOT / "verification/paid-v1-schemas.json") + parser.add_argument("--check", action="store_true") + args = parser.parse_args() + schemas = source_components(args.source) + for target in TARGETS: + synchronize(ROOT / "openapi" / target, schemas, args.check) + verify_auth() + print("PASS: gateway wallet/limits source and complete auth export verified") + + +if __name__ == "__main__": + main() diff --git a/verification/paid-pricing.json b/verification/paid-pricing.json new file mode 100644 index 0000000..cf39f15 --- /dev/null +++ b/verification/paid-pricing.json @@ -0,0 +1,69 @@ +{ + "target": "paid-v1", + "status": "draft-pending-rollout", + "publication_authorized": false, + "docs_base_revision": "3900f32601cd008f4e4bf4010c78842588e24d76", + "primary_source": { + "repository": "jona62/rig-mvp", + "revision": "652120cb2273c0383158cdd15136542ab59b74f1", + "runtime_schema_source_matches_commit": true, + "concurrent_worktree_changes": "cfg(test)-only auth fixtures; excluded from exports", + "models_sha256": "e5e68fed1e36a82de29239f221f6b2d73d58b0938d9e06f1fde509fce48dd671", + "cargo_lock_sha256": "b090e4d587ad3dbf8c832679fe422ddd71ceb3764ee9be8fcb525b05c8232d59" + }, + "api_source": { + "kind": "offline-gateway-print-openapi", + "actual_toolchain": "rustc 1.93.1 (01f6ddf75 2026-02-11)", + "repository_toolchain": "1.93.1", + "export_sha256": "f32fd24d869dc562f53257209251d6636daaa97a2e6b42e4a9a2f7af609436cf", + "export_bytes": 459272, + "selected_components": [ + "AiCredits", + "EffectiveLimits", + "LimitsUsage", + "GetUserLimitsResponse" + ], + "component_bundle_sha256": "91f3230116329725c05b3b590ac8e413204b1cba3d7d3140ecebe89ad87d91ee", + "targets": [ + "openapi/rigbox-api.json" + ], + "unrelated_gateway_paths_and_components_preserved": true, + "source_head_export_verified": true, + "hosted_final_CI_proof": false + }, + "auth_source": { + "kind": "offline-pure-rig_auth-openapi-library-harness", + "actual_toolchain": "rustc 1.93.1 (01f6ddf75 2026-02-11)", + "revision": "652120cb2273c0383158cdd15136542ab59b74f1", + "export_sha256": "9081d4a096bae9980fe58c381e0d4cda2d017e2377dbc5909d4b86d6490d977a", + "export_bytes": 101784, + "path_count": 51, + "schema_count": 80, + "target": "openapi/auth-api.json", + "replacement": "Complete actual auth service export replaces historical duplicated gateway spec", + "billing_paths": [ + "/api/v1/auth/billing/catalog", + "/api/v1/auth/billing/change", + "/api/v1/auth/billing/credit-packs/checkout", + "/api/v1/auth/billing/operations/{operation_id}", + "/api/v1/auth/billing/wallet/history", + "/api/v1/auth/create-checkout-session", + "/api/v1/auth/create-portal-session", + "/api/v1/auth/subscription-status" + ], + "responses": "Several billing handlers export generic serde_json::Value response schemas; no invented typed shapes", + "gateway_billing_coverage_gap": [ + "/api/v1/auth/create-checkout-session", + "/api/v1/auth/create-portal-session", + "/api/v1/auth/subscription-status" + ], + "runtime_services_started": false, + "database_or_provider_connections": false + }, + "pending_gates": [ + "Final-head hosted CI export comparison if primary revision advances", + "Production migration/payment/replay/wallet and Linux runtime gates", + "Native Safari keyboard, Page Zoom and orientation verification; no available simulator runtimes", + "Explicit documentation publication review after rollout status confirmation" + ] +} diff --git a/verification/paid-pricing.mdx b/verification/paid-pricing.mdx new file mode 100644 index 0000000..b254ac0 --- /dev/null +++ b/verification/paid-pricing.mdx @@ -0,0 +1,31 @@ +--- +title: Paid-v1 rollout status +description: Draft pricing documentation and the remaining source and release verification. +--- + + +Paid-v1 documentation is **pending rollout and publication review**. These pages do not confirm production checkout, pricing activation, or successful customer migration. Your account's live catalog, Billing state, and authenticated allowance remain authoritative. + + +## Documentation scope + +This draft covers [paid plans and add-ons](/concepts/pricing-and-billing), [account resource accounting](/concepts/limits), and [managed wallet behavior](/ai/managed-wallet). It removes monthly free-bucket promises from the staged wallet schema. New paid plans include no AI grant; existing funds and eligible transition access are described separately. + +## API source status + +The staged wallet and limits components come from an offline primary-server gateway export at **`652120cb2273c0383158cdd15136542ab59b74f1`**, using the exact repository and CI pin **Rust 1.93.1**. The complete auth-service schema comes from its pure library exporter at the same source revision and toolchain. Neither export starts a service, connects to a database, or fetches the live API. + +Only the selected wallet and limits components are synchronized into the existing gateway spec, preserving unrelated gateway definitions. `auth-api.json` is the complete actual auth-service export, replacing its historical duplicated gateway specification. Billing pages reference handler-exported paths and request schemas, not prose-inferred contracts. The combined gateway export omits subscription-status and the two existing checkout/portal paths; the auth export contains all eight documented billing operations. + +Several billing responses are generated as generic JSON objects because the source handlers return `serde_json::Value`. This is a schema typing limit, not permission to assume fields or grant access. Exact schemas may change before final release. The committed [provenance record](/verification/paid-pricing.json) lists both hashes, source revision, toolchain, and remaining release gates. + +## Before publication + +- Review final pricing, legacy allowances, preserved balances, and the actual durable transition timestamp. +- If the primary head changes, regenerate both exports using the exact Rust 1.93.1 toolchain, and review schema references and endpoint coverage against final hosted CI. +- Complete the financial migration, Stripe payment and renewal, webhook replay, wallet concurrency, and frontend state release gates. +- Complete isolated Linux CPU and resource-admission validation, without using customer workspaces. +- Verify native iOS Safari form focus, reduced Page Zoom, and orientation with the shared font-floor guard; JavaScript tests do not prove software-keyboard behavior. +- Confirm the deployed revision and account-specific catalog before changing these pages from upcoming to current. + +Local documentation validation establishes navigation, links, generated reference consistency, and schema provenance. It does not establish live entitlement, provider settlement, capacity, or rollout success. diff --git a/verification/paid-v1-schemas.json b/verification/paid-v1-schemas.json new file mode 100644 index 0000000..aa723f2 --- /dev/null +++ b/verification/paid-v1-schemas.json @@ -0,0 +1,199 @@ +{ + "components": { + "schemas": { + "AiCredits": { + "type": "object", + "required": [ + "remaining", + "total", + "remaining_micro", + "total_micro", + "free", + "pro", + "free_micro", + "pro_micro", + "mode" + ], + "properties": { + "free": { + "type": "number", + "format": "double", + "description": "Deprecated compatibility field; always zero. Preserved legacy balances\nbelong to the canonical wallet and are not reset or expired here." + }, + "free_micro": { + "type": "integer", + "format": "int64", + "description": "Deprecated compatibility field; always zero." + }, + "mode": { + "type": "string" + }, + "pro": { + "type": "number", + "format": "double", + "description": "Deprecated compatibility alias of `remaining`; this is not a separate\npurchased or included credit bucket." + }, + "pro_micro": { + "type": "integer", + "format": "int64", + "description": "Deprecated compatibility alias of `remaining_micro`." + }, + "remaining": { + "type": "number", + "format": "double", + "description": "Available managed credits: canonical wallet balance minus outstanding\nrequest holds. May be negative after a refund or dispute. New plans have\nno automatic AI credit grant." + }, + "remaining_micro": { + "type": "integer", + "format": "int64", + "description": "Exact available wallet credits in microcredits: 1,000,000 per credit." + }, + "total": { + "type": "number", + "format": "double", + "description": "Canonical wallet balance before outstanding holds. Includes preserved\nopening balances, purchased credit packs and verified legacy paid-period\ngrants. This is not a monthly allowance and has no calendar reset." + }, + "total_micro": { + "type": "integer", + "format": "int64", + "description": "Exact wallet balance before holds in microcredits: 1,000,000 per credit." + } + } + }, + "EffectiveLimits": { + "type": "object", + "required": [ + "max_vms", + "max_ram_per_vm_mb", + "max_ram_total_mb", + "max_disk_total_mb", + "max_vcpu_per_vm", + "max_running_vcpus", + "sustained_cpu_millis" + ], + "properties": { + "max_disk_total_mb": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "max_ram_per_vm_mb": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "max_ram_total_mb": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "max_running_vcpus": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "max_vcpu_per_vm": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "max_vms": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "sustained_cpu_millis": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + }, + "LimitsUsage": { + "type": "object", + "required": [ + "workspace_count", + "running_vcpus", + "total_disk_mb", + "total_ram_mb", + "running_cpu_millis" + ], + "properties": { + "running_cpu_millis": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "running_vcpus": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "total_disk_mb": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "total_ram_mb": { + "type": "integer", + "format": "int32", + "minimum": 0 + }, + "workspace_count": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + }, + "GetUserLimitsResponse": { + "type": "object", + "required": [ + "plan", + "custom", + "limits", + "usage", + "compute_allowed", + "entitlement_status", + "billing_revision" + ], + "properties": { + "billing_paid_through": { + "type": [ + "string", + "null" + ] + }, + "billing_revision": { + "type": "integer", + "format": "int64" + }, + "compute_allowed": { + "type": "boolean" + }, + "custom": { + "type": "boolean" + }, + "entitlement_status": { + "type": "string" + }, + "limits": { + "$ref": "#/components/schemas/EffectiveLimits" + }, + "plan": { + "type": "string" + }, + "pricing_transition_until": { + "type": [ + "string", + "null" + ] + }, + "usage": { + "$ref": "#/components/schemas/LimitsUsage" + } + } + } + } + } +}