openapi: 3.0.3 info: title: Dcntrlized Maestro API version: 1.0.0 description: The API of the Maestro orchestration router. Maestro manages the lifecycle of Dcntrlized service containers and routes inter-service action calls to them. components: schemas: ActionRequest: type: object properties: payload: type: object description: Action-specific parameters ActionResponse: type: object properties: status: type: string data: type: object SuccessResponse: type: object properties: status: type: string example: "success" message: type: string PendingAuthorization: type: object description: A first-contact authorization request awaiting the instance owner (M2 §3). properties: service: type: string example: "keepnote" fingerprint: type: string example: "sha256:aa:bb:cc:dd" first_seen: type: string last_seen: type: string AuthorizedKey: type: object description: An approved peer row of the auth service's trust store. properties: service: type: string fingerprint: type: string approved_by: type: string approved_at: type: string revoked_at: type: string nullable: true PeerAction: type: object required: [service, fingerprint] properties: service: type: string description: The service name (cert CN / org.dcntrlized.service). fingerprint: type: string description: The SHA256 public-key fingerprint (sha256:…) shown to the owner. Attestation: type: object description: The auth service's public signing key statement (D3). properties: public_key: type: string fingerprint: type: string example: "sha256:…" kid: type: string issued_at: type: string RegistryContainer: type: object required: [name, image] properties: name: type: string example: "keepnote" version: type: string example: "0.0.1" image: type: string example: "192.168.122.183:3000/dcntrlized/keepnote:dev" digest: type: string title: type: string example: "KeepNote" vendor: type: string author: type: string description: type: string source: type: string revision: type: string licenses: type: string url: type: string documentation: type: string created_at: type: string hidden: type: boolean description: Hidden infrastructure containers (e.g. the shared dcntrlized-db) are excluded from the service grid. example: true PortMapping: type: object properties: host: type: integer guest: type: integer IPAddress: type: object properties: version: type: string enum: [v4, v6] address: type: string Network: type: object properties: name: type: string ipAddress: $ref: '#/components/schemas/IPAddress' mode: type: string enum: [bridge, host, none, overlay, ipvlan, macvlan] ports: type: array items: $ref: '#/components/schemas/PortMapping' Container: type: object properties: id: type: string name: type: string service_name: type: string role: type: string example: "db" hidden: type: boolean description: Hidden infrastructure containers (e.g. the shared dcntrlized-db) are excluded from the service grid. capabilities: type: array items: type: string example: "database" description: Capabilities declared by the service manifest (e.g. database). has_auth: type: boolean description: >- Whether the service consumes the shared auth service (manifest has_auth). True for dcntrlized-auth itself and for auth-consuming services. public_key: type: string description: >- The auth service's RS256 public key (manifest public_key); the hook for a future Maestro dashboard auth that validates dcntrlized-auth tokens. docker_name: type: string image: type: string version: type: string status: type: string created_at: type: string network: $ref: '#/components/schemas/Network' title: type: string vendor: type: string author: type: string description: type: string source: type: string paths: /api/actions/{containerId}/{actionName}: parameters: - name: actionName in: path required: true description: The name of the specific action to execute schema: type: string - name: containerId in: path required: true description: The ID or name of the target container/service. Accepts a full or partial container ID, a container name, or the service name (matched case-insensitively). schema: type: string get: summary: Retrieve data or status from a service action tags: ["actions"] description: Forwards the request (method, headers, query string, and body) to the target container's /action/{actionName} endpoint. The target service is responsible for authentication; any client-supplied auth headers are forwarded as-is. responses: '200': description: Request successful content: application/json: schema: $ref: '#/components/schemas/ActionResponse' '400': description: Bad Request - Invalid input parameters '401': description: Unauthorized - the target service rejected the request '404': description: Action or container not found '500': description: Failed to forward the request to the container post: summary: Execute a state-changing action in the service tags: ["actions"] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ActionRequest' responses: '200': description: Action executed successfully content: application/json: schema: $ref: '#/components/schemas/ActionResponse' '400': description: Bad Request - Invalid input parameters '401': description: Unauthorized - the target service rejected the request '404': description: Action or container not found '500': description: Failed to forward the request to the container put: summary: Update configuration for a specific action tags: ["actions"] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ActionRequest' responses: '200': description: Configuration updated '400': description: Bad Request - Invalid input parameters '401': description: Unauthorized - the target service rejected the request '404': description: Action or container not found '500': description: Failed to forward the request to the container delete: tags: ["actions"] summary: Reset or remove an action's state requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ActionRequest' responses: '200': description: Action state reset '400': description: Bad Request - Invalid input parameters '401': description: Unauthorized - the target service rejected the request '404': description: Action or container not found '500': description: Failed to forward the request to the container /api/containers: get: summary: List the services Maestro manages tags: ["containers"] responses: '200': description: List of services content: application/json: schema: type: array items: $ref: '#/components/schemas/Container' '500': description: Internal server error /api/containers/install: post: summary: Install a service container (downloads the compose file and pulls the image) tags: ["containers"] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RegistryContainer' responses: '200': description: Container downloaded and image pulled successfully content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': description: Invalid JSON payload or missing required fields (name, image) '500': description: Failed to install container /api/containers/uninstall: post: summary: Uninstall a service container and remove it from the cache tags: ["containers"] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string responses: '200': description: Container uninstalled successfully content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': description: Invalid JSON payload or missing required field (name) '500': description: Failed to uninstall container /api/containers/start: post: summary: Start a previously installed service container tags: ["containers"] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string responses: '200': description: Container started successfully content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': description: Invalid JSON payload or missing required field (name) '500': description: Failed to start container /api/containers/stop: post: summary: Stop a running service container tags: ["containers"] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string responses: '200': description: Container stopped successfully content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': description: Invalid JSON payload or missing required field (name) '500': description: Failed to stop container /api/registry: get: summary: List the services available in the Dcntrlized registry tags: ["registry"] responses: '200': description: List of registry services content: application/json: schema: type: array items: $ref: '#/components/schemas/RegistryContainer' '500': description: Internal server error '502': description: Failed to connect to upstream registry /api/ws: get: summary: WebSocket endpoint for live container events tags: ["containers"] description: Establishes a WebSocket connection that streams container lifecycle events as JSON. responses: '101': description: Switching Protocols - WebSocket upgrade /api/peers: get: summary: List pending authorizations and the approved peer trust store tags: ["security"] description: > Security theme M2 §3. Returns the shared auth service's first-contact authorization requests (services whose certificate is valid but has not been approved by the instance owner yet) and the approved keys. Maestro is only the UI; the auth service owns the enforcement. responses: '200': description: Combined pending + approved trust state content: application/json: schema: type: object properties: pending: type: array items: $ref: '#/components/schemas/PendingAuthorization' authorized: type: array items: $ref: '#/components/schemas/AuthorizedKey' '500': description: Internal server error (auth management client unavailable) '502': description: Failed to reach the shared auth service /api/peers/attestation: get: summary: Read the auth service's public signing key statement tags: ["security"] description: > The auth service's RSA public key, its kid, and the sha256 fingerprint peers should pin after first contact (TOFU, D3). responses: '200': description: Auth public key attestation content: application/json: schema: $ref: '#/components/schemas/Attestation' '502': description: Failed to reach the shared auth service /api/peers/approve: post: summary: Approve a peer's fingerprint in the auth service trust store tags: ["security"] description: > Forwards the instance owner's approval for a service's identity fingerprint. After this call the service's requests to /auth/* proceed normally (enforced by the auth service itself). requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PeerAction' responses: '200': description: Peer approved '400': description: Missing service or fingerprint '502': description: Failed to reach the shared auth service /api/peers/revoke: post: summary: Revoke a peer's fingerprint (returns it to the no-op path) tags: ["security"] description: > Forwards the instance owner's revocation. Calls from that fingerprint become uniform 403 no-ops again immediately (the SSH authorized_keys "delete the line" action). requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PeerAction' responses: '200': description: Peer revoked '400': description: Missing service or fingerprint '502': description: Failed to reach the shared auth service