# GENERATED by cmd/docsgen — do not edit by hand; run `make docs` and commit.
# Source of truth: internal/api EndpointDocs (kept in lockstep with the chi router).
openapi: 3.1.0
info:
    title: Fabric Control Plane API
    version: 0.1.0
    description: Public control-plane HTTP API served by `control` (`internal/api`), generated from api.EndpointDocs. Auth is a bearer token (Cognito OIDC in prod, `dev:<org>` in dev mode). Every route is served under BOTH `/api` (legacy) and `/v1` (versioned) — identical aliases, so clients migrate to `/v1` at will without breaking; the paths below show `/api`. Internal service-to-service and webhook routes are not part of this contract.
servers:
    - url: https://api.falconoon.com
      description: production
    - url: http://127.0.0.1:8080
      description: local dev control plane
paths:
    /api/activity:
        get:
            summary: recent security/operator actions for the caller org (who/what/when), newest-first (?limit=, default 20, max 100)
            operationId: get_api_activity
            tags:
                - activity
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/agent-workspaces:
        get:
            summary: list the caller org's agent workspaces
            operationId: get_api_agent_workspaces
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                type: array
                                items:
                                    $ref: '#/components/schemas/AgentWorkspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: group agent + model + tool services into a working-agent workspace
            operationId: post_api_agent_workspaces
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CreateAgentWorkspaceRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/AgentWorkspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/agent-workspaces/{id}:
        delete:
            summary: delete an agent workspace
            operationId: delete_api_agent_workspaces_id
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        get:
            summary: agent workspace detail
            operationId: get_api_agent_workspaces_id
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/AgentWorkspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: update an agent workspace (name, purpose)
            operationId: patch_api_agent_workspaces_id
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/agent-workspaces/{id}/access-graph:
        get:
            summary: workspace → service → node graph for the GUI
            operationId: get_api_agent_workspaces_id_access_graph
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/agent-workspaces/{id}/publish-service:
        post:
            summary: remotely publish a loopback service on a node in the network via an APPLY_RECIPE job (async)
            operationId: post_api_agent_workspaces_id_publish_service
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/agent-workspaces/{id}/services:
        delete:
            summary: detach a service (by node_id + name)
            operationId: delete_api_agent_workspaces_id_services
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: attach a service to the workspace (routed to its leg by kind)
            operationId: post_api_agent_workspaces_id_services
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/agent-workspaces/{id}/smoke-test:
        post:
            summary: run a structural reachability smoke test + store the health summary
            operationId: post_api_agent_workspaces_id_smoke_test
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/agent-workspaces/{id}/status:
        get:
            summary: current health summary + leg counts
            operationId: get_api_agent_workspaces_id_status
            tags:
                - agent-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/billing/history:
        get:
            summary: completed subscription charges, newest-first, with Toss receipt links
            operationId: get_api_billing_history
            tags:
                - billing
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/billing/pricing:
        get:
            summary: effective plan prices (store override or env seed) + currency
            operationId: get_api_billing_pricing
            tags:
                - billing
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Pricing'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/billing/toss/cancel:
        post:
            summary: stop auto-renew (billing key deleted; paid access runs to period end, then suspends)
            operationId: post_api_billing_toss_cancel
            tags:
                - billing
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/billing/toss/subscribe:
        post:
            summary: subscribe a network via Toss recurring billing (issue billing key + charge → active)
            operationId: post_api_billing_toss_subscribe
            tags:
                - billing
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/billing/toss/update-card:
        post:
            summary: replace the subscription's card (issues a new billing key; nothing is charged)
            operationId: post_api_billing_toss_update_card
            tags:
                - billing
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/capabilities:
        post:
            summary: issue a macaroon-style capability token
            operationId: post_api_capabilities
            tags:
                - capabilities
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/checkout:
        post:
            summary: start a Stripe Checkout to subscribe a network → hosted checkout URL
            operationId: post_api_checkout
            tags:
                - checkout
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/console/access:
        post:
            summary: request remote Local Console access → node-scoped capability (403 if no ACL grant)
            operationId: post_api_console_access
            tags:
                - console
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/console/grants:
        delete:
            summary: revoke a console ACL grant
            operationId: delete_api_console_grants
            tags:
                - console
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        get:
            summary: list a network's console ACL grants (?network_id=)
            operationId: get_api_console_grants
            tags:
                - console
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: grant a subject console access to a node (zero-trust ACL)
            operationId: post_api_console_grants
            tags:
                - console
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/console/verify:
        post:
            summary: 'node forwarder: verify a console capability + re-check the ACL (fail-closed)'
            operationId: post_api_console_verify
            tags:
                - console
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/control-key:
        get:
            summary: Ed25519 netmap verify key (+ key_id)
            operationId: get_api_control_key
            tags:
                - control-key
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/customer-environments:
        get:
            summary: list the caller org's customer environments
            operationId: get_api_customer_environments
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                type: array
                                items:
                                    $ref: '#/components/schemas/CustomerEnvironment'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: represent a customer VPC/on-prem environment
            operationId: post_api_customer_environments
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CreateCustomerEnvironmentRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/CustomerEnvironment'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/customer-environments/{id}:
        delete:
            summary: delete a customer environment
            operationId: delete_api_customer_environments_id
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        get:
            summary: customer environment detail
            operationId: get_api_customer_environments_id
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/CustomerEnvironment'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: update a customer environment (name, customer, type, region)
            operationId: patch_api_customer_environments_id
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/customer-environments/{id}/gateways:
        post:
            summary: attach a gateway node to the environment
            operationId: post_api_customer_environments_id_gateways
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/customer-environments/{id}/gateways/{nodeID}:
        delete:
            summary: detach a gateway node from the environment
            operationId: delete_api_customer_environments_id_gateways_nodeID
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
                - name: nodeID
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/customer-environments/{id}/preflight:
        post:
            summary: run the trust-boundary checklist + readiness check → health
            operationId: post_api_customer_environments_id_preflight
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/customer-environments/{id}/services:
        delete:
            summary: detach a service (by node_id + name) from the environment
            operationId: delete_api_customer_environments_id_services
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: attach a deployed service (node + name) to the environment
            operationId: post_api_customer_environments_id_services
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/customer-environments/{id}/trust-brief:
        get:
            summary: get the manual trust brief (markdown)
            operationId: get_api_customer_environments_id_trust_brief
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: set the manual trust brief (markdown)
            operationId: post_api_customer_environments_id_trust_brief
            tags:
                - customer-environments
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/delivery-projects:
        get:
            summary: list the caller org's delivery projects
            operationId: get_api_delivery_projects
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                type: array
                                items:
                                    $ref: '#/components/schemas/DeliveryProject'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: create an AI-SI delivery project (seeds the default checklist)
            operationId: post_api_delivery_projects
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CreateDeliveryProjectRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/DeliveryProject'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/delivery-projects/{id}:
        delete:
            summary: delete a delivery project
            operationId: delete_api_delivery_projects_id
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        get:
            summary: delivery project detail
            operationId: get_api_delivery_projects_id
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/DeliveryProject'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: update a delivery project (name, stage, owner, due date)
            operationId: patch_api_delivery_projects_id
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/delivery-projects/{id}/checklist/{key}/complete:
        post:
            summary: mark a checklist item done (optional evidence_ref)
            operationId: post_api_delivery_projects_id_checklist_key_complete
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
                - name: key
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/delivery-projects/{id}/handoff:
        get:
            summary: get the handoff document (markdown)
            operationId: get_api_delivery_projects_id_handoff
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: set the handoff document (markdown)
            operationId: post_api_delivery_projects_id_handoff
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/delivery-projects/{id}/resources:
        post:
            summary: link a resource (demo_room/agent_workspace/gpu_workspace/customer_environment)
            operationId: post_api_delivery_projects_id_resources
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/delivery-projects/{id}/resources/{type}/{resourceID}:
        delete:
            summary: unlink a resource by type + id
            operationId: delete_api_delivery_projects_id_resources_type_resourceID
            tags:
                - delivery-projects
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
                - name: type
                  in: path
                  required: true
                  schema:
                    type: string
                - name: resourceID
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/demo-rooms:
        get:
            summary: list the caller org's demo rooms
            operationId: get_api_demo_rooms
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                type: array
                                items:
                                    $ref: '#/components/schemas/DemoRoom'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: create a demo room — time-boxed customer access to a service (Idempotency-Key supported); returns a scoped connection token
            operationId: post_api_demo_rooms
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/demo-rooms/{id}:
        delete:
            summary: delete a demo room
            operationId: delete_api_demo_rooms_id
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        get:
            summary: demo room detail (derived status + control-page URL)
            operationId: get_api_demo_rooms_id
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/DemoRoom'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: update a demo room (name, usage/rate limits)
            operationId: patch_api_demo_rooms_id
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/demo-rooms/{id}/extend:
        post:
            summary: extend/reactivate a demo room → fresh connection token
            operationId: post_api_demo_rooms_id_extend
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/demo-rooms/{id}/revoke:
        post:
            summary: close a demo room (status→revoked, expiry pulled to now)
            operationId: post_api_demo_rooms_id_revoke
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/demo-rooms/{id}/status:
        get:
            summary: 'live demo health: status, expiry, node online, service present'
            operationId: get_api_demo_rooms_id_status
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/demo-rooms/{id}/token:
        post:
            summary: re-issue a connection token scoped to the remaining TTL (409 if not active)
            operationId: post_api_demo_rooms_id_token
            tags:
                - demo-rooms
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/device/approve:
        post:
            summary: approve a device-flow user code (binds it to the caller)
            operationId: post_api_device_approve
            tags:
                - device
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/device/deny:
        post:
            summary: deny a device-flow user code
            operationId: post_api_device_deny
            tags:
                - device
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/device/pending:
        get:
            summary: device-flow grant awaiting approval (client name + request IP)
            operationId: get_api_device_pending
            tags:
                - device
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/device/sessions:
        get:
            summary: list the caller's active CLI/device sessions
            operationId: get_api_device_sessions
            tags:
                - device
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/device/sessions/{id}:
        delete:
            summary: revoke a device session
            operationId: delete_api_device_sessions_id
            tags:
                - device
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/enroll:
        post:
            summary: enroll a node (device proof-of-possession optional); 402 if suspended
            operationId: post_api_enroll
            tags:
                - enroll
            security:
                - bearerAuth: []
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/EnrollRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Node'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gateway/resolve:
        post:
            summary: resolve a service via a capability; 402 if suspended
            operationId: post_api_gateway_resolve
            tags:
                - gateway
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gpu-workspaces:
        get:
            summary: list the caller org's GPU workspaces
            operationId: get_api_gpu_workspaces
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                type: array
                                items:
                                    $ref: '#/components/schemas/GpuWorkspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: register a GPU node as a team model endpoint (auto-discovers published model services)
            operationId: post_api_gpu_workspaces
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CreateGpuWorkspaceRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/GpuWorkspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gpu-workspaces/{id}:
        delete:
            summary: delete a GPU workspace
            operationId: delete_api_gpu_workspaces_id
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        get:
            summary: GPU workspace detail
            operationId: get_api_gpu_workspaces_id
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/GpuWorkspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: update a GPU workspace (name)
            operationId: patch_api_gpu_workspaces_id
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gpu-workspaces/{id}/client-config:
        get:
            summary: OpenAI-compatible base URL + scoped capability token for a model service (?service=)
            operationId: get_api_gpu_workspaces_id_client_config
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gpu-workspaces/{id}/detect:
        get:
            summary: detect the node's GPU/runtime capabilities + published model services
            operationId: get_api_gpu_workspaces_id_detect
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gpu-workspaces/{id}/publish-service:
        post:
            summary: remotely publish a loopback model service on the GPU node via an APPLY_RECIPE job (async)
            operationId: post_api_gpu_workspaces_id_publish_service
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gpu-workspaces/{id}/register-service:
        post:
            summary: link an already-published model service on the node into the workspace
            operationId: post_api_gpu_workspaces_id_register_service
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/gpu-workspaces/{id}/services/{name}:
        delete:
            summary: unlink a model service from the workspace (inverse of register-service)
            operationId: delete_api_gpu_workspaces_id_services_name
            tags:
                - gpu-workspaces
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
                - name: name
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/jobs/{id}/status:
        post:
            summary: node reports a job's reconciled state (applied|failed|rejected)
            operationId: post_api_jobs_id_status
            tags:
                - jobs
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/netmap/{id}:
        get:
            summary: signed network map (peers + entitlement envelope)
            operationId: get_api_netmap_id
            tags:
                - netmap
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/networks:
        get:
            summary: list the caller org's networks
            operationId: get_api_networks
            tags:
                - networks
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                type: array
                                items:
                                    $ref: '#/components/schemas/Network'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: create a private network
            operationId: post_api_networks
            tags:
                - networks
            security:
                - bearerAuth: []
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CreateNetworkRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Network'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/networks/{id}:
        delete:
            summary: delete an empty network (409 if nodes remain)
            operationId: delete_api_networks_id
            tags:
                - networks
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: rename a network (label change only)
            operationId: patch_api_networks_id
            tags:
                - networks
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/RenameRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Network'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/networks/{id}/billing:
        get:
            summary: network subscription status (plan, entitlement, renews_at) — no payment credential
            operationId: get_api_networks_id_billing
            tags:
                - networks
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes:
        get:
            summary: list nodes (?network_id=)
            operationId: get_api_nodes
            tags:
                - nodes
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                type: array
                                items:
                                    $ref: '#/components/schemas/Node'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes/{id}:
        delete:
            summary: delete a node (revoke membership)
            operationId: delete_api_nodes_id
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: rename a node (keeps id + overlay IP)
            operationId: patch_api_nodes_id
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/RenameRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Node'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes/{id}/capabilities:
        get:
            summary: what a node can be used as (gpu/model_server/tool_server/agent_host/gateway), derived from reported state
            operationId: get_api_nodes_id_capabilities
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes/{id}/heartbeat:
        post:
            summary: node liveness + reachability candidates
            operationId: post_api_nodes_id_heartbeat
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes/{id}/jobs:
        get:
            summary: list a node's desired-state jobs (?status=pending for the node poll)
            operationId: get_api_nodes_id_jobs
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: enqueue an allow-listed desired-state job for a node
            operationId: post_api_nodes_id_jobs
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes/{id}/revoke:
        post:
            summary: revoke a node's device identity (blocks re-enroll) + remove it
            operationId: post_api_nodes_id_revoke
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes/{id}/services:
        post:
            summary: attach a private service (mcp/a2a/llm/…)
            operationId: post_api_nodes_id_services
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/Service'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Node'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/nodes/{id}/services/{name}:
        delete:
            summary: remove a published service from a node
            operationId: delete_api_nodes_id_services_name
            tags:
                - nodes
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
                - name: name
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/notifications:
        get:
            summary: in-app notifications (console bell), newest-first with unread count
            operationId: get_api_notifications
            tags:
                - notifications
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/notifications/read:
        post:
            summary: mark the listed notifications read (everything shown when the bell was opened)
            operationId: post_api_notifications_read
            tags:
                - notifications
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/overview:
        get:
            summary: 'one-shot Home aggregate for the caller org: networks + all nodes + usage totals/events + demo rooms (avoids the dashboard N+1)'
            operationId: get_api_overview
            tags:
                - overview
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/relay/{id}:
        get:
            summary: relay endpoint + signed admission ticket; 402 if suspended
            operationId: get_api_relay_id
            tags:
                - relay
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/usage:
        get:
            summary: metering readout (totals + events)
            operationId: get_api_usage
            tags:
                - usage
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/UsageResponse'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/workspace:
        get:
            summary: workspace (org) profile — name, plan, owner
            operationId: get_api_workspace
            tags:
                - workspace
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Workspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: rename the workspace (label change only)
            operationId: patch_api_workspace
            tags:
                - workspace
            security:
                - bearerAuth: []
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/RenameRequest'
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Workspace'
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/workspace/bootstrap:
        post:
            summary: 'first-run setup: create the org + a Default network (idempotent, no-op once bootstrapped)'
            operationId: post_api_workspace_bootstrap
            tags:
                - workspace
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/workspace/invitations:
        get:
            summary: list the caller org's invitations
            operationId: get_api_workspace_invitations
            tags:
                - workspace
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        post:
            summary: invite a teammate by email + role (admin|member)
            operationId: post_api_workspace_invitations
            tags:
                - workspace
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/workspace/invitations/{id}:
        delete:
            summary: revoke an invitation
            operationId: delete_api_workspace_invitations_id
            tags:
                - workspace
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/workspace/invitations/{id}/accept:
        post:
            summary: accept an invitation addressed to your email — join the inviting org
            operationId: post_api_workspace_invitations_id_accept
            tags:
                - workspace
            security:
                - bearerAuth: []
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/workspace/members:
        get:
            summary: workspace roster — owner + invitations
            operationId: get_api_workspace_members
            tags:
                - workspace
            security:
                - bearerAuth: []
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /api/workspace/members/{subject}:
        delete:
            summary: remove a member (owner-only); the last owner cannot be removed
            operationId: delete_api_workspace_members_subject
            tags:
                - workspace
            security:
                - bearerAuth: []
            parameters:
                - name: subject
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
        patch:
            summary: change a member's role (owner-only; owner|member); the last owner cannot be demoted
            operationId: patch_api_workspace_members_subject
            tags:
                - workspace
            security:
                - bearerAuth: []
            parameters:
                - name: subject
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                "401":
                    description: unauthorized (missing or invalid bearer token)
    /device/code:
        post:
            summary: 'device-flow: request a device + user code (RFC 8628)'
            operationId: post_device_code
            tags:
                - device
            security: []
            responses:
                "200":
                    description: OK
    /device/token:
        post:
            summary: 'device-flow: poll for tokens (grant_type=device_code|refresh_token)'
            operationId: post_device_token
            tags:
                - device
            security: []
            responses:
                "200":
                    description: OK
    /healthz:
        get:
            summary: liveness probe
            operationId: get_healthz
            tags:
                - healthz
            security: []
            responses:
                "200":
                    description: OK
    /metrics:
        get:
            summary: 'Prometheus metrics (RED: rate/errors/duration); optionally gated by AF_METRICS_TOKEN'
            operationId: get_metrics
            tags:
                - metrics
            security: []
            responses:
                "200":
                    description: OK
    /r/{slug}:
        get:
            summary: public demo connect page — mints a scoped connection token from the share slug (unauthenticated; rate-limited)
            operationId: get_r_slug
            tags:
                - r
            security: []
            parameters:
                - name: slug
                  in: path
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
    /readyz:
        get:
            summary: readiness probe — 503 until the datastore is reachable
            operationId: get_readyz
            tags:
                - readyz
            security: []
            responses:
                "200":
                    description: OK
components:
    securitySchemes:
        bearerAuth:
            scheme: bearer
            type: http
    schemas:
        AgentHealth:
            type: object
            properties:
                agent:
                    type: string
                last_smoke_test_at:
                    type: string
                    format: date-time
                model:
                    type: string
                state:
                    type: string
                tools:
                    type: string
        AgentWorkspace:
            type: object
            properties:
                agent_services:
                    type: array
                    items:
                        $ref: '#/components/schemas/ServiceRef'
                created_at:
                    type: string
                    format: date-time
                created_by:
                    type: string
                health:
                    $ref: '#/components/schemas/AgentHealth'
                id:
                    type: string
                model_services:
                    type: array
                    items:
                        $ref: '#/components/schemas/ServiceRef'
                name:
                    type: string
                network_id:
                    type: string
                purpose:
                    type: string
                tool_services:
                    type: array
                    items:
                        $ref: '#/components/schemas/ServiceRef'
        ChecklistItem:
            type: object
            properties:
                evidence_ref:
                    type: string
                key:
                    type: string
                label:
                    type: string
                status:
                    type: string
        CreateAgentWorkspaceRequest:
            type: object
            properties:
                agent_services:
                    type: array
                    items:
                        $ref: '#/components/schemas/ServiceRefInput'
                model_services:
                    type: array
                    items:
                        $ref: '#/components/schemas/ServiceRefInput'
                name:
                    type: string
                network_id:
                    type: string
                purpose:
                    type: string
                tool_services:
                    type: array
                    items:
                        $ref: '#/components/schemas/ServiceRefInput'
            required:
                - network_id
                - name
        CreateCustomerEnvironmentRequest:
            type: object
            properties:
                customer_name:
                    type: string
                environment_type:
                    type: string
                name:
                    type: string
                region:
                    type: string
            required:
                - name
        CreateDeliveryProjectRequest:
            type: object
            properties:
                customer_name:
                    type: string
                due_date:
                    type: string
                name:
                    type: string
                owner_id:
                    type: string
                stage:
                    type: string
            required:
                - name
        CreateGpuWorkspaceRequest:
            type: object
            properties:
                name:
                    type: string
                node_id:
                    type: string
            required:
                - node_id
        CreateNetworkRequest:
            type: object
            properties:
                cidr:
                    type: string
                name:
                    type: string
            required:
                - name
        CustomerEnvHealth:
            type: object
            properties:
                last_checked_at:
                    type: string
                    format: date-time
                state:
                    type: string
        CustomerEnvironment:
            type: object
            properties:
                created_at:
                    type: string
                    format: date-time
                created_by:
                    type: string
                customer_name:
                    type: string
                environment_type:
                    type: string
                gateways:
                    type: array
                    items:
                        type: string
                health:
                    $ref: '#/components/schemas/CustomerEnvHealth'
                id:
                    type: string
                name:
                    type: string
                region:
                    type: string
                services:
                    type: array
                    items:
                        $ref: '#/components/schemas/ServiceRef'
                trust_brief:
                    type: string
        DeliveryProject:
            type: object
            properties:
                checklist:
                    type: array
                    items:
                        $ref: '#/components/schemas/ChecklistItem'
                created_at:
                    type: string
                    format: date-time
                created_by:
                    type: string
                customer_name:
                    type: string
                due_date:
                    type: string
                handoff:
                    type: string
                id:
                    type: string
                name:
                    type: string
                owner_id:
                    type: string
                resource_refs:
                    $ref: '#/components/schemas/ResourceRefs'
                stage:
                    type: string
        DemoRoom:
            type: object
            properties:
                created_at:
                    type: string
                    format: date-time
                expires_at:
                    type: string
                    format: date-time
                id:
                    type: string
                kind:
                    type: string
                mode:
                    type: string
                name:
                    type: string
                service:
                    type: string
                status:
                    type: string
        EnrollRequest:
            type: object
            properties:
                name:
                    type: string
                network_id:
                    type: string
                public_key:
                    type: string
                services:
                    type: array
                    items:
                        $ref: '#/components/schemas/Service'
                type:
                    type: string
            required:
                - network_id
                - public_key
        GpuWorkspace:
            type: object
            properties:
                created_at:
                    type: string
                    format: date-time
                created_by:
                    type: string
                id:
                    type: string
                model_services:
                    type: array
                    items:
                        type: string
                name:
                    type: string
                network_id:
                    type: string
                node_id:
                    type: string
        Network:
            type: object
            description: 'An overlay network. NOTE: serialized with Go field names (no json tags) — PascalCase keys.'
            properties:
                CIDR:
                    type: string
                CreatedAt:
                    type: string
                    format: date-time
                Entitlement:
                    type: string
                Generation:
                    type: integer
                ID:
                    type: string
                Name:
                    type: string
                OrgID:
                    type: string
                Plan:
                    type: string
        Node:
            type: object
            properties:
                created_at:
                    type: string
                    format: date-time
                id:
                    type: string
                last_seen:
                    type: string
                    format: date-time
                name:
                    type: string
                network_id:
                    type: string
                online:
                    type: boolean
                org_id:
                    type: string
                overlay_ip:
                    type: string
                public_key:
                    type: string
                services:
                    type: array
                    items:
                        $ref: '#/components/schemas/Service'
                type:
                    type: string
        PlanPrice:
            type: object
            properties:
                amount:
                    type: integer
                currency:
                    type: string
                plan:
                    type: string
        Pricing:
            type: object
            properties:
                plans:
                    type: array
                    items:
                        $ref: '#/components/schemas/PlanPrice'
                source:
                    type: string
        RenameRequest:
            type: object
            properties:
                name:
                    type: string
            required:
                - name
        ResourceRefs:
            type: object
            properties:
                agent_workspace_ids:
                    type: array
                    items:
                        type: string
                customer_environment_ids:
                    type: array
                    items:
                        type: string
                demo_room_ids:
                    type: array
                    items:
                        type: string
                gpu_workspace_ids:
                    type: array
                    items:
                        type: string
        Service:
            type: object
            properties:
                addr:
                    type: string
                kind:
                    type: string
                name:
                    type: string
                scope:
                    type: string
            required:
                - name
                - kind
        ServiceRef:
            type: object
            description: a published service on a node (node + name + kind)
            properties:
                kind:
                    type: string
                name:
                    type: string
                node_id:
                    type: string
        ServiceRefInput:
            type: object
            properties:
                name:
                    type: string
                node_id:
                    type: string
            required:
                - node_id
                - name
        UsageResponse:
            type: object
            properties:
                org:
                    type: string
                totals:
                    $ref: '#/components/schemas/UsageTotals'
        UsageTotals:
            type: object
            description: metered totals keyed by usage kind
            additionalProperties:
                type: number
        Workspace:
            type: object
            properties:
                created_at:
                    type: string
                    format: date-time
                id:
                    type: string
                name:
                    type: string
                owner:
                    type: string
                plan:
                    type: string
