{
  "openapi": "3.1.0",
  "info": {
    "title": "Cial Instance API",
    "version": "1.0.0",
    "description": "The HTTP + WebSocket surface your Cial instance exposes under /.cial/api. Every route is owner-scoped: on a managed instance the caller must resolve to the verified owner (agent bearer · gate assertion · loopback identity) or it is rejected. Derived from the cial-server route modules."
  },
  "servers": [
    {
      "url": "https://{slug}.cial.app",
      "description": "Your instance"
    }
  ],
  "security": [
    {
      "ownerIdentity": []
    }
  ],
  "components": {
    "securitySchemes": {
      "ownerIdentity": {
        "type": "http",
        "scheme": "bearer",
        "description": "Owner identity (agent self-API token, gate assertion, or loopback)"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "SessionProvider": {
        "type": "string",
        "enum": [
          "claude",
          "kimi"
        ],
        "description": "Which harness drives the session."
      },
      "SessionStatus": {
        "type": "string",
        "enum": [
          "idle",
          "running",
          "error"
        ]
      },
      "MessageRole": {
        "type": "string",
        "enum": [
          "user",
          "assistant",
          "system"
        ]
      },
      "StreamingState": {
        "type": "object",
        "description": "In-flight turn snapshot (null when idle).",
        "properties": {
          "text": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "Session": {
        "type": "object",
        "description": "A chat session — the persisted row the repository materializes.",
        "required": [
          "id",
          "userId",
          "name",
          "provider",
          "status",
          "model",
          "effort",
          "options",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "provider": {
            "$ref": "#/components/schemas/SessionProvider"
          },
          "status": {
            "$ref": "#/components/schemas/SessionStatus"
          },
          "model": {
            "type": "string"
          },
          "effort": {
            "type": "string"
          },
          "options": {
            "type": "object",
            "description": "Harness option toggles, e.g. { afk: true }.",
            "additionalProperties": {
              "type": "boolean"
            }
          },
          "harnessSessionId": {
            "type": "string",
            "nullable": true
          },
          "parentSessionId": {
            "type": "string",
            "nullable": true
          },
          "cwd": {
            "type": "string",
            "nullable": true
          },
          "groupId": {
            "type": "string",
            "nullable": true
          },
          "streamingState": {
            "$ref": "#/components/schemas/StreamingState",
            "nullable": true
          },
          "createdAt": {
            "type": "integer",
            "format": "epoch-ms"
          },
          "updatedAt": {
            "type": "integer",
            "format": "epoch-ms"
          },
          "archivedAt": {
            "type": "integer",
            "format": "epoch-ms",
            "nullable": true
          }
        }
      },
      "Message": {
        "type": "object",
        "required": [
          "id",
          "role",
          "content",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "role": {
            "$ref": "#/components/schemas/MessageRole"
          },
          "content": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "createdAt": {
            "type": "integer",
            "format": "epoch-ms"
          }
        }
      },
      "BackgroundTask": {
        "type": "object",
        "description": "A background orchestration unit (subagent · workflow · background bash).",
        "required": [
          "id",
          "kind",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "agent",
              "workflow",
              "bash"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed",
              "cancelled"
            ]
          },
          "title": {
            "type": "string"
          },
          "startedAt": {
            "type": "integer",
            "format": "epoch-ms"
          }
        }
      },
      "CreateSessionInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "default": "New session",
            "description": "Display name (min 1 char)."
          },
          "provider": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SessionProvider"
              }
            ],
            "default": "claude"
          },
          "model": {
            "type": "string",
            "default": ""
          },
          "effort": {
            "type": "string",
            "default": ""
          },
          "cwd": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "AppendMessageInput": {
        "type": "object",
        "required": [
          "role",
          "content"
        ],
        "properties": {
          "role": {
            "$ref": "#/components/schemas/MessageRole"
          },
          "content": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          }
        }
      },
      "CredentialScope": {
        "type": "string",
        "enum": [
          "user",
          "instance"
        ],
        "description": "Whether the credential is the caller's personal credential or shared instance-wide."
      },
      "AnthropicCredentialView": {
        "type": "object",
        "description": "Anthropic /status view of a stored credential (OAuth fields are null for api_key credentials).",
        "properties": {
          "connected": {
            "const": true
          },
          "kind": {
            "type": "string",
            "enum": [
              "api_key",
              "oauth"
            ]
          },
          "maskedHint": {
            "type": "string",
            "description": "Masked display hint (masked key, or OAuth email/expiry)."
          },
          "addedAt": {
            "type": "integer",
            "description": "Epoch ms when the credential was stored."
          },
          "expiresAt": {
            "type": "integer",
            "nullable": true,
            "description": "OAuth access-token expiry epoch ms; null for api_key."
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": "OAuth account email; null for api_key."
          },
          "subscriptionType": {
            "type": "string",
            "nullable": true,
            "description": "OAuth subscription tier; null for api_key."
          }
        },
        "required": [
          "connected",
          "kind",
          "maskedHint",
          "addedAt",
          "expiresAt",
          "email",
          "subscriptionType"
        ]
      },
      "KimiCredentialView": {
        "type": "object",
        "description": "Kimi /status view of a stored credential (API-key only, no OAuth fields).",
        "properties": {
          "connected": {
            "const": true
          },
          "kind": {
            "type": "string",
            "enum": [
              "api_key"
            ]
          },
          "maskedHint": {
            "type": "string",
            "description": "Masked key display hint."
          },
          "addedAt": {
            "type": "integer",
            "description": "Epoch ms when the credential was stored."
          }
        },
        "required": [
          "connected",
          "kind",
          "maskedHint",
          "addedAt"
        ]
      },
      "AnthropicStatus": {
        "type": "object",
        "properties": {
          "user": {
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/AnthropicCredentialView"
              }
            ],
            "description": "Caller's user-scope credential, or null if none."
          },
          "instance": {
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/AnthropicCredentialView"
              }
            ],
            "description": "Instance-scope credential, or null if none."
          },
          "active": {
            "type": "string",
            "enum": [
              "user",
              "instance",
              "none"
            ],
            "description": "Which credential the harness would use (user wins over instance)."
          }
        },
        "required": [
          "user",
          "instance",
          "active"
        ]
      },
      "KimiStatus": {
        "type": "object",
        "properties": {
          "user": {
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/KimiCredentialView"
              }
            ],
            "description": "Caller's user-scope credential, or null if none."
          },
          "instance": {
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/KimiCredentialView"
              }
            ],
            "description": "Instance-scope credential, or null if none."
          },
          "active": {
            "type": "string",
            "enum": [
              "user",
              "instance",
              "none"
            ],
            "description": "Which credential the harness would use (user wins over instance)."
          }
        },
        "required": [
          "user",
          "instance",
          "active"
        ]
      },
      "ApiKeyRequest": {
        "type": "object",
        "properties": {
          "apiKey": {
            "type": "string",
            "description": "Provider API key; trimmed and must be at least 20 characters."
          },
          "scope": {
            "$ref": "#/components/schemas/CredentialScope"
          }
        },
        "required": [
          "apiKey"
        ]
      },
      "ApiKeyStored": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "scope": {
            "$ref": "#/components/schemas/CredentialScope"
          },
          "maskedHint": {
            "type": "string",
            "description": "Masked key display hint."
          },
          "addedAt": {
            "type": "integer",
            "description": "Epoch ms when stored."
          }
        },
        "required": [
          "ok",
          "scope",
          "maskedHint",
          "addedAt"
        ]
      },
      "DeleteResult": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "True if a credential was removed."
          },
          "scope": {
            "$ref": "#/components/schemas/CredentialScope"
          }
        },
        "required": [
          "ok",
          "scope"
        ]
      },
      "OAuthStartRequest": {
        "type": "object",
        "properties": {
          "scope": {
            "$ref": "#/components/schemas/CredentialScope"
          }
        },
        "description": "Optional body; scope defaults to 'user' when omitted or not 'instance'."
      },
      "OAuthStartResult": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "authUrl": {
            "type": "string",
            "description": "Anthropic authorize URL the user should open."
          },
          "state": {
            "type": "string",
            "description": "Opaque state token tying the eventual callback to this flow."
          }
        },
        "required": [
          "ok",
          "authUrl",
          "state"
        ]
      },
      "OAuthExchangeRequest": {
        "type": "object",
        "properties": {
          "state": {
            "type": "string",
            "description": "State token returned from /oauth/start."
          },
          "code": {
            "type": "string",
            "description": "Authorization code (may be the raw pasted code#state pair)."
          }
        },
        "required": [
          "state",
          "code"
        ]
      },
      "OAuthStored": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "scope": {
            "$ref": "#/components/schemas/CredentialScope"
          },
          "kind": {
            "const": "oauth"
          },
          "maskedHint": {
            "type": "string",
            "description": "Masked display hint (OAuth email or expiry)."
          },
          "addedAt": {
            "type": "integer",
            "description": "Epoch ms when stored."
          },
          "expiresAt": {
            "type": "integer",
            "description": "Access-token expiry epoch ms."
          }
        },
        "required": [
          "ok",
          "scope",
          "kind",
          "maskedHint",
          "addedAt",
          "expiresAt"
        ]
      },
      "KeyValidationError": {
        "type": "object",
        "properties": {
          "error": {
            "const": "key_validation_failed"
          },
          "status": {
            "type": "integer",
            "description": "HTTP status from the provider's validation call."
          },
          "message": {
            "type": "string",
            "description": "Provider-supplied validation failure message."
          }
        },
        "required": [
          "error"
        ]
      },
      "ExchangeError": {
        "type": "object",
        "properties": {
          "error": {
            "const": "OAUTH_EXCHANGE_FAILED"
          },
          "message": {
            "type": "string",
            "description": "Generic exchange-failure message (real cause is logged server-side)."
          }
        },
        "required": [
          "error",
          "message"
        ]
      },
      "BillingView": {
        "type": "object",
        "description": "Instance-side mirror of the cial-app billing response plus a `managed` flag the UI uses to decide whether to render the tier badge.",
        "properties": {
          "managed": {
            "type": "boolean",
            "description": "True only on a managed (cial-app) instance whose control plane answered."
          },
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "solo"
            ],
            "description": "The team's billing tier."
          },
          "onTrial": {
            "type": "boolean",
            "description": "Whether an internal (no-card) Solo trial is currently active."
          },
          "trialEndsAt": {
            "type": "string",
            "nullable": true,
            "description": "ISO timestamp when the trial ends, or null when not on trial."
          },
          "trialDaysLeft": {
            "type": "integer",
            "nullable": true,
            "description": "Days remaining in the trial, or null when not on trial."
          },
          "subscriptionStatus": {
            "type": "string",
            "nullable": true,
            "description": "Stripe subscription status, or null when unmanaged/no subscription."
          },
          "manageUrl": {
            "type": "string",
            "nullable": true,
            "description": "Absolute URL of the cial-app billing dashboard (manage / upgrade), or null when unmanaged."
          }
        },
        "required": [
          "managed",
          "plan",
          "onTrial",
          "trialEndsAt",
          "trialDaysLeft",
          "subscriptionStatus",
          "manageUrl"
        ]
      },
      "OwnLineRepo": {
        "type": "object",
        "description": "This instance's own (frozen) fork line — always writable.",
        "properties": {
          "kind": {
            "const": "own"
          },
          "name": {
            "type": "string"
          },
          "repoUrl": {
            "type": "string"
          },
          "youCanWrite": {
            "const": true
          }
        },
        "required": [
          "kind",
          "name",
          "repoUrl",
          "youCanWrite"
        ]
      },
      "BindingRepo": {
        "type": "object",
        "description": "A team binding repo this instance may switch its code line to.",
        "properties": {
          "kind": {
            "const": "binding"
          },
          "bindingId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "repoUrl": {
            "type": "string"
          },
          "memberCount": {
            "type": "integer"
          },
          "youCanWrite": {
            "type": "boolean"
          },
          "shared": {
            "type": "boolean"
          },
          "seeded": {
            "type": "boolean"
          },
          "updatedAt": {
            "type": "string",
            "nullable": true
          },
          "youCreated": {
            "type": "boolean",
            "description": "True when this instance created the binding, so it may delete it."
          }
        },
        "required": [
          "kind",
          "bindingId",
          "name",
          "repoUrl",
          "memberCount",
          "youCanWrite",
          "shared",
          "seeded",
          "updatedAt",
          "youCreated"
        ]
      },
      "BindableRepos": {
        "type": "object",
        "description": "The instance's bindable code lines: own line plus the team's bindings.",
        "properties": {
          "teamId": {
            "type": "string",
            "nullable": true
          },
          "teamSlug": {
            "type": "string"
          },
          "ownLine": {
            "$ref": "#/components/schemas/OwnLineRepo"
          },
          "bindings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BindingRepo"
            }
          }
        },
        "required": [
          "teamId",
          "ownLine",
          "bindings"
        ]
      },
      "CreatedBinding": {
        "type": "object",
        "description": "The newly created binding repo's id and clone URL.",
        "properties": {
          "bindingId": {
            "type": "string"
          },
          "repoUrl": {
            "type": "string"
          }
        },
        "required": [
          "bindingId",
          "repoUrl"
        ]
      },
      "GrantedBinding": {
        "type": "object",
        "description": "The granted binding's id and clone URL.",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "bindingId": {
            "type": "string"
          },
          "repoUrl": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "bindingId",
          "repoUrl"
        ]
      },
      "DeletedBinding": {
        "type": "object",
        "description": "The deleted binding's id.",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "bindingId": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "bindingId"
        ]
      },
      "ChannelMediaUploadResult": {
        "type": "object",
        "description": "Result of a channel media upload.",
        "properties": {
          "url": {
            "type": "string",
            "description": "Instance-relative media URL of the form /.cial/api/v1/channel-media?id=<blobId>."
          }
        },
        "required": [
          "url"
        ]
      },
      "FeatureKey": {
        "type": "string",
        "description": "A registered feature surface key.",
        "enum": [
          "knowledges",
          "uploads",
          "channel",
          "presence",
          "binding",
          "upstream-updates",
          "background-activity",
          "push-notifications",
          "system-health",
          "sessions",
          "onboarding",
          "harnesses",
          "tools",
          "skills",
          "self-edit",
          "model-picker",
          "session-tools"
        ]
      },
      "FeatureGroup": {
        "type": "string",
        "description": "UI grouping in the Discovery page.",
        "enum": [
          "discoverable",
          "core",
          "composer"
        ]
      },
      "FeatureToggleRequest": {
        "type": "object",
        "description": "Explicit on/off choice for the feature named in the path.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Desired visibility; must be a boolean (400 otherwise)."
          }
        },
        "required": [
          "enabled"
        ]
      },
      "FeatureView": {
        "type": "object",
        "description": "A registry entry flattened with its resolved per-user state — the shape the Discovery settings page renders.",
        "properties": {
          "key": {
            "$ref": "#/components/schemas/FeatureKey"
          },
          "label": {
            "type": "string",
            "description": "Human-readable feature name."
          },
          "description": {
            "type": "string",
            "description": "What the feature does."
          },
          "group": {
            "$ref": "#/components/schemas/FeatureGroup"
          },
          "toggleable": {
            "type": "boolean",
            "description": "Whether the user may toggle it; always-on features are locked (false)."
          },
          "defaultVisible": {
            "type": "boolean",
            "description": "Visibility when the user has set no explicit preference (ignored by always-on features)."
          },
          "enabled": {
            "type": "boolean",
            "description": "Resolved visibility for the requesting user."
          }
        },
        "required": [
          "key",
          "label",
          "description",
          "group",
          "toggleable",
          "defaultVisible",
          "enabled"
        ]
      },
      "Knowledge": {
        "type": "object",
        "description": "A knowledge base summary (manifest fields).",
        "properties": {
          "id": {
            "type": "string",
            "description": "Knowledge id (directory name / UUID, or 'cial' for the built-in)."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          },
          "icon": {
            "type": "string",
            "description": "Icon name; defaults to 'Globe'."
          },
          "color": {
            "type": "string",
            "description": "Color token; defaults to 'indigo'."
          },
          "order": {
            "type": "integer",
            "description": "Sort order."
          },
          "createdAt": {
            "type": "integer",
            "description": "Creation time, epoch milliseconds."
          },
          "updatedAt": {
            "type": "integer",
            "description": "Last update time, epoch milliseconds."
          }
        },
        "required": [
          "id",
          "name",
          "icon",
          "color",
          "order",
          "createdAt",
          "updatedAt"
        ]
      },
      "KnowledgeDetail": {
        "type": "object",
        "description": "A knowledge base plus its instructions.md content.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Knowledge"
          }
        ],
        "properties": {
          "instructions": {
            "type": "string",
            "description": "instructions.md content ('' when absent)."
          }
        },
        "required": [
          "instructions"
        ]
      },
      "KnowledgeFile": {
        "type": "object",
        "description": "A file or folder entry within a knowledge's files tree.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Entry name."
          },
          "type": {
            "type": "string",
            "enum": [
              "folder",
              "file"
            ],
            "description": "Entry kind."
          },
          "size": {
            "type": "integer",
            "nullable": true,
            "description": "Byte size for files; null for folders or on stat failure."
          },
          "mtimeMs": {
            "type": "number",
            "nullable": true,
            "description": "Modification time in epoch milliseconds; null on stat failure."
          }
        },
        "required": [
          "name",
          "type",
          "size",
          "mtimeMs"
        ]
      },
      "KnowledgeFileContent": {
        "type": "object",
        "description": "UTF-8 content of a single knowledge file.",
        "properties": {
          "content": {
            "type": "string",
            "description": "File content (up to 256 KB)."
          },
          "truncated": {
            "type": "boolean",
            "description": "True when the file exceeded 256 KB and was clipped."
          }
        },
        "required": [
          "content",
          "truncated"
        ]
      },
      "KnowledgeCreate": {
        "type": "object",
        "description": "Fields to create a knowledge base.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Required, non-blank display name."
          },
          "icon": {
            "type": "string",
            "description": "Optional icon name; defaults to 'Globe'."
          },
          "color": {
            "type": "string",
            "description": "Optional color token; defaults to 'indigo'."
          }
        },
        "required": [
          "name"
        ]
      },
      "KnowledgeUpdate": {
        "type": "object",
        "description": "Partial fields to update a knowledge base; only supplied keys are applied.",
        "properties": {
          "name": {
            "type": "string",
            "description": "New display name."
          },
          "icon": {
            "type": "string",
            "description": "New icon name."
          },
          "color": {
            "type": "string",
            "description": "New color token."
          }
        }
      },
      "ProfileView": {
        "type": "object",
        "description": "Instance-side mirror of the cial-app profile, plus a managed flag and manageUrl for UI rendering decisions.",
        "properties": {
          "managed": {
            "type": "boolean",
            "description": "True only on a managed (cial-app) instance whose control plane answered."
          },
          "user": {
            "description": "The owner's cial-app user record, or null when unmanaged.",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/ProfileUser"
              }
            ]
          },
          "team": {
            "description": "The owner's team, or null when unmanaged.",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/ProfileTeam"
              }
            ]
          },
          "billing": {
            "$ref": "#/components/schemas/ProfileBilling"
          },
          "manageUrl": {
            "type": "string",
            "nullable": true,
            "description": "Absolute cial-app billing dashboard URL for banner CTAs, or null when unmanaged."
          }
        },
        "required": [
          "managed",
          "user",
          "team",
          "billing",
          "manageUrl"
        ]
      },
      "ProfileUser": {
        "type": "object",
        "description": "The owner's cial-app dashboard user record.",
        "properties": {
          "id": {
            "type": "string",
            "description": "cial-app dashboard user id."
          },
          "citadelUserId": {
            "type": "string",
            "nullable": true,
            "description": "The owner's id inside the team's Citadel — the same value the instance sees as x-cial-user, for cross-namespace correlation."
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "image": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "country": {
            "type": "string",
            "nullable": true
          },
          "emailVerified": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "description": "ISO timestamp."
          }
        },
        "required": [
          "id",
          "citadelUserId",
          "email",
          "name",
          "image",
          "phone",
          "country",
          "emailVerified",
          "createdAt"
        ]
      },
      "ProfileTeam": {
        "type": "object",
        "description": "The owner's team within cial-app.",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "solo"
            ]
          },
          "seats": {
            "type": "integer"
          },
          "role": {
            "type": "string",
            "nullable": true,
            "enum": [
              "owner",
              "admin",
              "member"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "plan",
          "seats",
          "role"
        ]
      },
      "ProfileBilling": {
        "type": "object",
        "description": "The owner's billing and trial state.",
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "solo"
            ]
          },
          "onTrial": {
            "type": "boolean",
            "description": "Internal (no-card) Solo trial currently active."
          },
          "trialEndsAt": {
            "type": "string",
            "nullable": true
          },
          "trialDaysLeft": {
            "type": "integer",
            "nullable": true
          },
          "subscriptionStatus": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "plan",
          "onTrial",
          "trialEndsAt",
          "trialDaysLeft",
          "subscriptionStatus"
        ]
      },
      "VapidPublicKey": {
        "type": "object",
        "description": "VAPID discovery response; only the public key is ever served to clients.",
        "properties": {
          "configured": {
            "type": "boolean",
            "const": true,
            "description": "Always true — push is always configured (keys are auto-generated if unset)."
          },
          "publicKey": {
            "type": "string",
            "description": "The VAPID public key used by clients as `applicationServerKey`."
          }
        },
        "required": [
          "configured",
          "publicKey"
        ]
      },
      "PushSubscription": {
        "type": "object",
        "description": "A browser `PushSubscription` as serialized by `subscription.toJSON()`.",
        "properties": {
          "endpoint": {
            "type": "string",
            "format": "uri",
            "description": "The push service endpoint URL (must be a valid URL)."
          },
          "keys": {
            "type": "object",
            "description": "The subscription's client encryption keys.",
            "properties": {
              "p256dh": {
                "type": "string",
                "description": "Base64url ECDH P-256 public key (min length 1)."
              },
              "auth": {
                "type": "string",
                "description": "Base64url auth secret (min length 1)."
              }
            },
            "required": [
              "p256dh",
              "auth"
            ]
          }
        },
        "required": [
          "endpoint",
          "keys"
        ]
      },
      "UnsubscribeRequest": {
        "type": "object",
        "description": "Unsubscribe payload; only the endpoint is read.",
        "properties": {
          "endpoint": {
            "type": "string",
            "description": "The push subscription endpoint to remove (required, non-empty)."
          }
        },
        "required": [
          "endpoint"
        ]
      },
      "BuildEntry": {
        "type": "object",
        "description": "One recorded client build in the dist manifest.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Build id (e.g. <shortSha>-<timestamp>)."
          },
          "sha": {
            "type": "string",
            "description": "Short git SHA the build was made from."
          },
          "line": {
            "type": "string",
            "description": "Code line the build belongs to: the Cial Binding repo URL while bound, else 'personal'."
          },
          "builtAt": {
            "type": "integer",
            "description": "Epoch ms when the build was committed."
          },
          "confirmedGoodAt": {
            "type": "integer",
            "nullable": true,
            "description": "Epoch ms when the build was confirmed-good (booted in a browser), or null."
          }
        },
        "required": [
          "id",
          "sha",
          "line",
          "builtAt",
          "confirmedGoodAt"
        ]
      },
      "DistState": {
        "type": "object",
        "description": "Line-scoped manifest snapshot returned to the recover page.",
        "properties": {
          "current": {
            "type": "string",
            "nullable": true,
            "description": "Id of the currently served build, or null."
          },
          "lastConfirmedGood": {
            "type": "string",
            "nullable": true,
            "description": "Id of the line's most recent confirmed-good build, or null."
          },
          "history": {
            "type": "array",
            "description": "Builds for the currently checked-out code line.",
            "items": {
              "$ref": "#/components/schemas/BuildEntry"
            }
          },
          "hasRollback": {
            "type": "boolean",
            "description": "Whether a non-current same-line build exists to roll back to."
          },
          "line": {
            "type": "string",
            "description": "The currently checked-out code line (binding repo URL while bound, else 'personal')."
          }
        },
        "required": [
          "current",
          "lastConfirmedGood",
          "history",
          "hasRollback",
          "line"
        ]
      },
      "RollbackRequest": {
        "type": "object",
        "description": "Optional explicit rollback target; omitted/empty selects the line-scoped default (last confirmed-good, else most recent other build).",
        "properties": {
          "to": {
            "type": "string",
            "description": "Explicit build id to roll the served dist symlink to."
          }
        }
      },
      "RollbackResult": {
        "type": "object",
        "description": "Outcome of a dist rollback.",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "Whether the rollback succeeded."
          },
          "to": {
            "type": "string",
            "description": "Build id rolled to (present on success)."
          },
          "error": {
            "type": "string",
            "description": "Failure reason (present on failure)."
          }
        },
        "required": [
          "ok"
        ]
      },
      "BootOkRequest": {
        "type": "object",
        "description": "Confirms a build booted in a browser; omitted build defaults to the current build.",
        "properties": {
          "build": {
            "type": "string",
            "description": "Build id to mark confirmed-good (defaults to current when omitted)."
          }
        }
      },
      "DeployRequest": {
        "type": "object",
        "description": "Optional originating session, echoed onto the broadcast deploy lifecycle events.",
        "properties": {
          "sessionId": {
            "type": "string",
            "description": "Source session id that triggered the deploy."
          }
        }
      },
      "DeployResponse": {
        "type": "object",
        "description": "Outcome of the rebuild; logTail is the last ~2000 chars of build output.",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "Whether the build succeeded."
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "error"
            ],
            "description": "Coarse status mirroring ok."
          },
          "logTail": {
            "type": "string",
            "description": "Tail of the build output (last ~2000 chars)."
          }
        },
        "required": [
          "ok",
          "status",
          "logTail"
        ]
      },
      "OkResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true,
            "description": "Always true on success."
          }
        },
        "required": [
          "ok"
        ]
      },
      "CommitRequest": {
        "type": "object",
        "description": "Optional commit message; defaults to 'cial: self-edit'.",
        "properties": {
          "message": {
            "type": "string",
            "default": "cial: self-edit",
            "description": "Commit message."
          }
        }
      },
      "CommitResult": {
        "type": "object",
        "description": "Outcome of staging/committing the working tree and pushing to origin.",
        "properties": {
          "committed": {
            "type": "boolean",
            "description": "Whether a new commit was created."
          },
          "pushed": {
            "type": "boolean",
            "description": "Whether the branch was pushed to origin."
          },
          "output": {
            "type": "string",
            "description": "Git command output / status detail."
          }
        },
        "required": [
          "committed",
          "pushed",
          "output"
        ]
      },
      "Skill": {
        "type": "object",
        "description": "A slash-command entry the composer can autocomplete, discovered from an on-disk `.claude/skills` or `.claude/commands` root.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Frontmatter `name`, already namespaced for tenant skills (e.g. `cial:self-edit`)."
          },
          "description": {
            "type": "string",
            "default": "",
            "description": "Frontmatter `description` — the short blurb shown in the dropdown."
          },
          "command": {
            "type": "string",
            "description": "The slash command the user types / that gets inserted: `/${name}`."
          },
          "source": {
            "type": "string",
            "enum": [
              "tenant",
              "plugin",
              "command"
            ],
            "description": "Where the entry was found: `tenant` = `.claude/skills/*`, `command` = `.claude/commands/**`."
          }
        },
        "required": [
          "name",
          "command",
          "source"
        ]
      },
      "ListSkillsResponse": {
        "type": "object",
        "description": "The skill catalog returned for the composer's autocomplete.",
        "properties": {
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Skill"
            }
          }
        },
        "required": [
          "skills"
        ]
      },
      "MetricUsage": {
        "type": "object",
        "description": "A single resource gauge with absolute byte figures and a normalized fraction.",
        "properties": {
          "usedBytes": {
            "type": "integer",
            "description": "Bytes currently used."
          },
          "totalBytes": {
            "type": "integer",
            "description": "Total bytes available."
          },
          "pct": {
            "type": "number",
            "description": "Fraction used, clamped to 0..1."
          }
        },
        "required": [
          "usedBytes",
          "totalBytes",
          "pct"
        ]
      },
      "SystemHealth": {
        "type": "object",
        "description": "CPU, memory and disk usage of this instance's container plus the sample timestamp.",
        "properties": {
          "cpu": {
            "type": "object",
            "description": "CPU utilisation across all cores.",
            "properties": {
              "pct": {
                "type": "number",
                "description": "CPU utilisation fraction, 0..1."
              }
            },
            "required": [
              "pct"
            ]
          },
          "mem": {
            "$ref": "#/components/schemas/MetricUsage"
          },
          "disk": {
            "$ref": "#/components/schemas/MetricUsage"
          },
          "at": {
            "type": "integer",
            "description": "Epoch milliseconds when the metrics were sampled."
          }
        },
        "required": [
          "cpu",
          "mem",
          "disk",
          "at"
        ]
      },
      "RuntimeHealth": {
        "type": "object",
        "description": "Runtime liveness response.",
        "properties": {
          "ok": {
            "const": true,
            "description": "Always true when the runtime responds."
          },
          "service": {
            "const": "instance",
            "description": "Identifies the responding service."
          },
          "ts": {
            "type": "integer",
            "description": "Epoch milliseconds when the probe was answered."
          }
        },
        "required": [
          "ok",
          "service",
          "ts"
        ]
      },
      "ToolScope": {
        "type": "string",
        "enum": [
          "instance",
          "user"
        ],
        "description": "Tool visibility scope: instance-wide (admin-managed) or per-owner (private)."
      },
      "ToolType": {
        "type": "string",
        "enum": [
          "env_var",
          "mcp",
          "md"
        ],
        "description": "Tool kind, derived from config.type."
      },
      "McpServerConfig": {
        "description": "An MCP server definition — stdio (spawned) or http/sse (remote). Discriminated on transport.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "transport": {
                "const": "stdio"
              },
              "command": {
                "type": "string",
                "description": "Executable to spawn (min length 1)."
              },
              "args": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "default": []
              },
              "env": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "default": {}
              }
            },
            "required": [
              "transport",
              "command"
            ]
          },
          {
            "type": "object",
            "properties": {
              "transport": {
                "const": "http"
              },
              "url": {
                "type": "string",
                "format": "uri",
                "description": "Remote server URL."
              },
              "headers": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "default": {}
              }
            },
            "required": [
              "transport",
              "url"
            ]
          },
          {
            "type": "object",
            "properties": {
              "transport": {
                "const": "sse"
              },
              "url": {
                "type": "string",
                "format": "uri",
                "description": "Remote server URL."
              },
              "headers": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "default": {}
              }
            },
            "required": [
              "transport",
              "url"
            ]
          }
        ]
      },
      "ToolConfig": {
        "description": "Raw, secret-bearing tool config — discriminated on type. Only ever returned by the manage-gated config endpoint; list/summary endpoints mask it.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "const": "env_var"
              },
              "key": {
                "type": "string",
                "description": "Env var name (min length 1)."
              },
              "value": {
                "type": "string",
                "description": "Secret value (masked in summaries)."
              }
            },
            "required": [
              "type",
              "key",
              "value"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "const": "mcp"
              },
              "name": {
                "type": "string",
                "description": "MCP server name the model addresses it by (min length 1)."
              },
              "server": {
                "$ref": "#/components/schemas/McpServerConfig"
              }
            },
            "required": [
              "type",
              "name",
              "server"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "const": "md"
              },
              "name": {
                "type": "string",
                "description": "Tool name the model calls; returns the markdown body (min length 1)."
              },
              "description": {
                "type": "string",
                "default": ""
              },
              "markdown": {
                "type": "string",
                "description": "Markdown body returned when the tool is called."
              }
            },
            "required": [
              "type",
              "name",
              "markdown"
            ]
          }
        ]
      },
      "ToolSummary": {
        "type": "object",
        "description": "Metadata view of a tool, safe to return to any caller who can see it; secret config is reduced to maskedHint.",
        "properties": {
          "id": {
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/ToolScope"
          },
          "ownerId": {
            "type": "string",
            "nullable": true,
            "description": "null for instance tools; the owner's user id for personal tools."
          },
          "label": {
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/ToolType"
          },
          "icon": {
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabledDefault": {
            "type": "boolean",
            "description": "Auto-enabled in new sessions."
          },
          "sortOrder": {
            "type": "number"
          },
          "maskedHint": {
            "type": "string",
            "nullable": true,
            "description": "Non-secret summary of the config (e.g. \"WHATSAPP_TOKEN=****a1b2\")."
          },
          "createdBy": {
            "type": "string"
          },
          "createdAt": {
            "type": "number"
          },
          "updatedAt": {
            "type": "number"
          }
        },
        "required": [
          "id",
          "scope",
          "ownerId",
          "label",
          "type",
          "icon",
          "tags",
          "enabledDefault",
          "sortOrder",
          "maskedHint",
          "createdBy",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateToolRequest": {
        "type": "object",
        "description": "Body for creating a tool; config.type is the single source of truth for the tool's type.",
        "properties": {
          "scope": {
            "$ref": "#/components/schemas/ToolScope"
          },
          "label": {
            "type": "string",
            "description": "Display label (length 1-200)."
          },
          "icon": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabledDefault": {
            "type": "boolean"
          },
          "sortOrder": {
            "type": "number"
          },
          "config": {
            "$ref": "#/components/schemas/ToolConfig"
          }
        },
        "required": [
          "scope",
          "label",
          "config"
        ]
      },
      "UpdateToolRequest": {
        "type": "object",
        "description": "Body for updating a tool; all fields optional, config is a full replace whose type must match the existing tool's type.",
        "properties": {
          "label": {
            "type": "string",
            "description": "Display label (length 1-200)."
          },
          "icon": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabledDefault": {
            "type": "boolean"
          },
          "sortOrder": {
            "type": "number"
          },
          "config": {
            "$ref": "#/components/schemas/ToolConfig"
          }
        },
        "required": []
      },
      "UploadResult": {
        "type": "object",
        "description": "Attachment reference returned after a successful upload.",
        "properties": {
          "fileId": {
            "type": "string",
            "description": "Generated id: <timestamp>-<4hex>-<safe-name>."
          },
          "name": {
            "type": "string",
            "description": "Original filename."
          },
          "mime": {
            "type": "string",
            "description": "MIME type of the stored file."
          },
          "isImage": {
            "type": "boolean",
            "description": "True when the MIME type starts with 'image/'."
          },
          "size": {
            "type": "integer",
            "description": "Stored byte length."
          }
        },
        "required": [
          "fileId",
          "name",
          "mime",
          "isImage",
          "size"
        ]
      }
    }
  },
  "tags": [
    {
      "name": "Sessions",
      "x-cial-icon": "messages",
      "x-cial-tone": "indigo",
      "description": "Create, list and drive chat sessions, their message history, and the background tasks a turn spawns. REST-created sessions broadcast over the WS so they appear live in the sidebar."
    },
    {
      "name": "Knowledges",
      "x-cial-icon": "database",
      "x-cial-tone": "violet",
      "description": "Instance-wide, filesystem-backed knowledge bases with per-knowledge instructions and a files tree, injected as harness context."
    },
    {
      "name": "Tools & vault",
      "x-cial-icon": "wrench",
      "x-cial-tone": "amber",
      "description": "Two-tier tool/secret vault — instance-wide and per-owner env-var, MCP, and markdown tools whose secret config is masked in responses and only readable via the manage-gated config endpoint."
    },
    {
      "name": "Uploads",
      "x-cial-icon": "upload",
      "x-cial-tone": "emerald",
      "description": "Store and retrieve per-owner attachment files in a sandboxed on-disk uploads directory."
    },
    {
      "name": "Skills",
      "x-cial-icon": "sparkles",
      "x-cial-tone": "indigo",
      "description": "Enumerates the instance's on-disk `.claude/skills` and `.claude/commands` catalog for the composer's slash-command autocomplete."
    },
    {
      "name": "Model accounts",
      "x-cial-icon": "lock",
      "x-cial-tone": "rose",
      "description": "Manage the Anthropic and Kimi model-provider credentials (API keys and Anthropic OAuth) the harness uses, scoped per-user or instance-wide."
    },
    {
      "name": "Discovery",
      "x-cial-icon": "settings",
      "x-cial-tone": "indigo",
      "description": "Per-user feature visibility (Cial Discovery): the surface registry plus each user's resolved on/off state, with live re-broadcast on toggle."
    },
    {
      "name": "Profile",
      "x-cial-icon": "user",
      "x-cial-tone": "violet",
      "description": "Reads the owner's full managed identity (name, avatar, contact, team and billing/trial) from the cial-app control plane, degrading to an unmanaged fallback off-platform."
    },
    {
      "name": "Billing",
      "x-cial-icon": "billing",
      "x-cial-tone": "emerald",
      "description": "Display-only tier view for the in-instance billing badge, resolved control-plane side from the cial-app managed-instance API."
    },
    {
      "name": "Push notifications",
      "x-cial-icon": "bell",
      "x-cial-tone": "amber",
      "description": "Web Push subscription management and VAPID public-key discovery for owner-authed devices."
    },
    {
      "name": "Channel media",
      "x-cial-icon": "radio",
      "x-cial-tone": "violet",
      "description": "Instance-side proxy that fronts the Citadel blob plane so channel message images can be uploaded and re-served per member instance."
    },
    {
      "name": "Binding",
      "x-cial-icon": "branch",
      "x-cial-tone": "indigo",
      "description": "Discover, create, grant and delete the binding repos this instance can switch its code line to, proxied server-side to the cial-app control plane."
    },
    {
      "name": "Self-edit",
      "x-cial-icon": "terminal",
      "x-cial-tone": "amber",
      "description": "Loopback-only self-edit API the agent's CLI skills curl to rebuild, restart, roll back, and commit the instance's own source."
    },
    {
      "name": "Recovery",
      "x-cial-icon": "lifebuoy",
      "x-cial-tone": "rose",
      "description": "Bundle-independent client-failure recovery page and served-dist rollback for a white-screened-but-authenticated instance."
    },
    {
      "name": "System & health",
      "x-cial-icon": "server",
      "x-cial-tone": "slate",
      "description": "Liveness and resource-usage telemetry for this instance container — CPU, memory and data-volume metrics plus a runtime liveness probe."
    },
    {
      "name": "Realtime",
      "x-cial-icon": "radio",
      "x-cial-tone": "violet",
      "description": "One socket carries everything live — turns and their streaming output, the team channel, presence, and shared sessions."
    }
  ],
  "paths": {
    "/.cial/api/v1/sessions": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "List sessions",
        "operationId": "listSessions",
        "description": "Every session owned by the caller, decorated with share metadata.",
        "responses": {
          "200": {
            "description": "Sessions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Session"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Sessions"
        ],
        "summary": "Create a session",
        "operationId": "createSession",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSessionInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/sessions/background-tasks": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "All sessions' background tasks",
        "operationId": "allBackgroundTasks",
        "description": "Bulk preload keyed by session id, so the sidebar can show task chevrons without opening each session.",
        "responses": {
          "200": {
            "description": "Map of sessionId → tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/BackgroundTask"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/sessions/{id}": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "Get a session",
        "operationId": "getSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Sessions"
        ],
        "summary": "Rename a session",
        "operationId": "renameSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "New name (min 1 char)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Sessions"
        ],
        "summary": "Delete a session",
        "operationId": "deleteSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/sessions/{id}/messages": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "List messages",
        "operationId": "listMessages",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "Cursor — return messages before this id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (max 200, default 50).",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Messages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Message"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Sessions"
        ],
        "summary": "Append a message",
        "operationId": "appendMessage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppendMessageInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Appended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/sessions/{id}/background-tasks": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "Session background tasks",
        "operationId": "sessionBackgroundTasks",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BackgroundTask"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/sessions/{id}/background-tasks/{taskId}/stop": {
      "post": {
        "tags": [
          "Sessions"
        ],
        "summary": "Stop a background task",
        "operationId": "stopBackgroundTask",
        "description": "SIGTERMs the detached process(es) and marks the task cancelled. Safe for in-turn subagents (won't kill the live turn).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stopped",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/auth/anthropic/status": {
      "get": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Anthropic status",
        "description": "Report the connected Anthropic credential for both the caller's user scope and the instance scope, and which one is active.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current Anthropic credential status per scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnthropicStatus"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/auth/anthropic/api-key": {
      "post": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Set Anthropic key",
        "description": "Validate a pasted Anthropic API key against the provider and store it for the chosen scope (user or instance).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key validated and stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyStored"
                }
              }
            }
          },
          "400": {
            "description": "Key is missing or shorter than 20 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Key failed live validation against Anthropic.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Delete Anthropic credential",
        "description": "Remove the stored Anthropic credential for the selected scope (defaults to the caller's user scope).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "Credential scope to delete; any value other than 'instance' resolves to 'user'.",
            "schema": {
              "type": "string",
              "enum": [
                "user",
                "instance"
              ],
              "default": "user"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Credential deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResult"
                }
              }
            }
          },
          "404": {
            "description": "No credential existed for the scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResult"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/auth/anthropic/oauth/start": {
      "post": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Start OAuth",
        "description": "Begin the Anthropic OAuth flow: mint a PKCE challenge and state, store the pending entry, and return the provider authorize URL.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthStartRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authorize URL and state for the pending OAuth flow.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthStartResult"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/auth/anthropic/oauth/exchange": {
      "post": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Exchange OAuth code",
        "description": "Complete the Anthropic OAuth flow by exchanging the returned authorization code for tokens and storing the OAuth credential for the originating scope.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthExchangeRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tokens exchanged and OAuth credential stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthStored"
                }
              }
            }
          },
          "400": {
            "description": "Missing params, unknown/expired state, or state mismatch in the pasted code.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Pending OAuth state belongs to a different caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Authorization code exchange with Anthropic failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExchangeError"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/auth/kimi/status": {
      "get": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Kimi status",
        "description": "Report the connected Kimi credential for both the caller's user scope and the instance scope, and which one is active.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current Kimi credential status per scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KimiStatus"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/auth/kimi/api-key": {
      "post": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Set Kimi key",
        "description": "Validate a pasted Kimi API key against the provider and store it for the chosen scope (user or instance).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key validated and stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyStored"
                }
              }
            }
          },
          "400": {
            "description": "Key is missing or shorter than 20 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Key failed live validation against Kimi.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Model accounts"
        ],
        "summary": "Delete Kimi credential",
        "description": "Remove the stored Kimi credential for the selected scope (defaults to the caller's user scope).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "Credential scope to delete; any value other than 'instance' resolves to 'user'.",
            "schema": {
              "type": "string",
              "enum": [
                "user",
                "instance"
              ],
              "default": "user"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Credential deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResult"
                }
              }
            }
          },
          "404": {
            "description": "No credential existed for the scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResult"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/billing": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get billing view",
        "description": "Returns the display-only billing tier view for the in-instance badge, resolved from the cial-app control plane and degrading silently to an unmanaged view on any failure.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "The resolved billing view (always succeeds; degrades to an unmanaged view when no instance token is present or the control plane is unreachable).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingView"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/binding/repos": {
      "get": {
        "tags": [
          "Binding"
        ],
        "summary": "List bindable repos",
        "description": "Returns the repos this instance can switch to: its own fork line plus the team's binding repos.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "Own line + team bindings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BindableRepos"
                }
              }
            }
          },
          "502": {
            "description": "Control-plane request failed or returned a non-JSON response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Not a managed instance (CIAL_INSTANCE_TOKEN unset).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/binding/create": {
      "post": {
        "tags": [
          "Binding"
        ],
        "summary": "Create binding",
        "description": "Self-serve creates a new binding repo for the team and grants this instance write access.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Optional desired binding name (trimmed; empty when omitted).",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Desired binding repo name; trimmed server-side, treated as empty if missing or non-string."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Binding repo created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedBinding"
                }
              }
            }
          },
          "502": {
            "description": "Control-plane request failed or returned a non-JSON response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Not a managed instance (CIAL_INSTANCE_TOKEN unset).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/binding/grant": {
      "post": {
        "tags": [
          "Binding"
        ],
        "summary": "Grant binding",
        "description": "Grants this instance write access on an existing team binding so it can switch to it.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The target binding repo name (trimmed server-side).",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Existing binding repo name to grant write on; trimmed server-side, empty if missing."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Write access granted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GrantedBinding"
                }
              }
            }
          },
          "404": {
            "description": "Binding repo not found (control-plane passthrough status).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Control-plane request failed or returned a non-JSON response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Not a managed instance (CIAL_INSTANCE_TOKEN unset).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/binding/delete": {
      "post": {
        "tags": [
          "Binding"
        ],
        "summary": "Delete binding",
        "description": "Deletes a binding repo; the control plane enforces creator-only deletion.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The binding repo name to delete (trimmed server-side).",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Binding repo name to delete; trimmed server-side, empty if missing."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Binding repo deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedBinding"
                }
              }
            }
          },
          "403": {
            "description": "Not the creator of the binding (control-plane passthrough status).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Binding repo not found (control-plane passthrough status).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Control-plane request failed or returned a non-JSON response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Not a managed instance (CIAL_INSTANCE_TOKEN unset).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/channel-media": {
      "post": {
        "tags": [
          "Channel media"
        ],
        "summary": "Upload channel image",
        "description": "Accepts raw image bytes and stores them as a Citadel blob scoped to the caller's team channel, returning an instance-relative URL embedded in the channel message record.",
        "parameters": [
          {
            "name": "x-cial-mime",
            "in": "header",
            "required": false,
            "description": "MIME type of the upload; falls back to the request Content-Type header, then image/jpeg.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Raw image bytes (max 8 MiB / 8388608 bytes; empty body rejected).",
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Blob stored; returns the instance-relative media URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelMediaUploadResult"
                }
              }
            }
          },
          "400": {
            "description": "Empty upload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Upload exceeds the 8 MiB limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Upstream Citadel blob upload failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Channel media requires a configured Citadel URL and an active team relay identity.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerIdentity": []
          }
        ]
      },
      "get": {
        "tags": [
          "Channel media"
        ],
        "summary": "Fetch channel image",
        "description": "Proxies the bytes for a stored Citadel blob by id and serves them with an immutable long-lived cache header.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "Citadel blob id to fetch.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Blob bytes, served with the upstream content-type (or application/octet-stream) and an immutable cache-control.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "description": "Upstream Citadel denied access to the blob.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Missing id, no Citadel URL configured, or blob not found upstream.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerIdentity": []
          }
        ]
      }
    },
    "/.cial/api/v1/features": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "summary": "List features",
        "description": "Returns the full feature registry flattened with each entry's resolved visibility for the calling owner, for the Settings -> Discovery page.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "The feature registry with resolved per-user state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "features": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FeatureView"
                      }
                    }
                  },
                  "required": [
                    "features"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/features/{key}": {
      "post": {
        "tags": [
          "Discovery"
        ],
        "summary": "Toggle feature",
        "description": "Sets an explicit on/off preference for a toggleable feature (no-op for always-on features), then re-broadcasts the resolved map over features.updated so every open tab re-gates live.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "Registry feature key to toggle; must be a known FeatureKey.",
            "schema": {
              "$ref": "#/components/schemas/FeatureKey"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeatureToggleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The refreshed feature registry with resolved per-user state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "features": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FeatureView"
                      }
                    }
                  },
                  "required": [
                    "features"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Body was not valid JSON, or `enabled` was missing / not a boolean.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The path `key` is not a known feature.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/knowledges": {
      "get": {
        "tags": [
          "Knowledges"
        ],
        "summary": "List knowledges",
        "description": "Lists all knowledge bases, sorted by order then creation time.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "All knowledge bases.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "knowledges": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Knowledge"
                      }
                    }
                  },
                  "required": [
                    "knowledges"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Knowledges"
        ],
        "summary": "Create knowledge",
        "description": "Creates a new knowledge base; name is required and must be non-blank.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KnowledgeCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created knowledge base.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "knowledge": {
                      "$ref": "#/components/schemas/Knowledge"
                    }
                  },
                  "required": [
                    "knowledge"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing or blank name / invalid input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/knowledges/reorder": {
      "post": {
        "tags": [
          "Knowledges"
        ],
        "summary": "Reorder knowledges",
        "description": "Reassigns the order field of each knowledge to match the supplied id sequence.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orderedIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Knowledge ids in the desired order; defaults to [] when omitted."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The full list after reordering.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "knowledges": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Knowledge"
                      }
                    }
                  },
                  "required": [
                    "knowledges"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/knowledges/{id}": {
      "get": {
        "tags": [
          "Knowledges"
        ],
        "summary": "Get knowledge detail",
        "description": "Returns a knowledge base with its instructions content.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Knowledge id (rejected if it contains slashes, backslashes, or '..')."
          }
        ],
        "responses": {
          "200": {
            "description": "Knowledge detail including instructions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "knowledge": {
                      "$ref": "#/components/schemas/KnowledgeDetail"
                    }
                  },
                  "required": [
                    "knowledge"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid knowledge id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Knowledges"
        ],
        "summary": "Update knowledge",
        "description": "Updates a knowledge base's name, icon, and/or color; only supplied fields change.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Knowledge id."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KnowledgeUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated knowledge base.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "knowledge": {
                      "$ref": "#/components/schemas/Knowledge"
                    }
                  },
                  "required": [
                    "knowledge"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid knowledge id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Knowledges"
        ],
        "summary": "Delete knowledge",
        "description": "Permanently removes a knowledge base directory and all its files.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Knowledge id."
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion acknowledged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid knowledge id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/knowledges/{id}/files": {
      "get": {
        "tags": [
          "Knowledges"
        ],
        "summary": "List files",
        "description": "Lists files and folders at a subpath within a knowledge's files tree, sorted folders-first then by mtime.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Knowledge id."
          },
          {
            "name": "path",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": ""
            },
            "description": "Relative subpath inside the knowledge files tree; traversal outside the tree is rejected. Defaults to the root."
          }
        ],
        "responses": {
          "200": {
            "description": "Directory listing.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KnowledgeFile"
                      }
                    }
                  },
                  "required": [
                    "files"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid id or path escapes the files directory.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/knowledges/{id}/file": {
      "get": {
        "tags": [
          "Knowledges"
        ],
        "summary": "Read file",
        "description": "Reads a single file's UTF-8 content (capped at 256 KB) from a knowledge's files tree.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Knowledge id."
          },
          {
            "name": "path",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": ""
            },
            "description": "Relative path to the file inside the knowledge files tree; traversal is rejected. Defaults to the root (which is not a file)."
          }
        ],
        "responses": {
          "200": {
            "description": "File content, truncated when larger than 256 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeFileContent"
                }
              }
            }
          },
          "400": {
            "description": "Invalid id/path, path escapes the files directory, or target is not a file.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/knowledges/{id}/instructions": {
      "put": {
        "tags": [
          "Knowledges"
        ],
        "summary": "Save instructions",
        "description": "Overwrites the knowledge's instructions.md with the supplied content and bumps updatedAt.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Knowledge id."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "string",
                    "description": "Markdown instructions body; defaults to an empty string when omitted."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Save acknowledged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid knowledge id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/profile/": {
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get owner profile",
        "description": "Returns the owner's full profile (name, avatar, contact, team and billing/trial) fetched from the cial-app managed-instance API, or an unmanaged fallback when no instance token or the control plane is unreachable.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "The owner's profile view.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileView"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/push-notifications/vapid-public-key": {
      "get": {
        "tags": [
          "Push notifications"
        ],
        "summary": "VAPID public key",
        "description": "Returns the VAPID public key so the client can build its `applicationServerKey`.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "VAPID public key for the push application server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VapidPublicKey"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/push-notifications/subscribe": {
      "post": {
        "tags": [
          "Push notifications"
        ],
        "summary": "Subscribe device",
        "description": "Registers (or refreshes) the caller's browser/device push subscription, deduped by endpoint.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushSubscription"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Subscription stored; no content returned."
          },
          "400": {
            "description": "Body was not valid JSON or failed PushSubscription validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/push-notifications/unsubscribe": {
      "post": {
        "tags": [
          "Push notifications"
        ],
        "summary": "Unsubscribe device",
        "description": "Removes the caller's push subscription for the given endpoint (scoped to the caller).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnsubscribeRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Subscription removed (or did not exist); no content returned."
          },
          "400": {
            "description": "Body was not valid JSON, or `endpoint` was missing/empty/non-string.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/recover": {
      "get": {
        "tags": [
          "Recovery"
        ],
        "summary": "Recovery page",
        "description": "Returns the inline, bundle-independent recovery HTML page reached when the built SPA fails to boot.",
        "security": [],
        "parameters": [
          {
            "name": "reason",
            "in": "query",
            "required": false,
            "description": "Client-side failure reason label rendered in the page (read by the page's inline script, not the server).",
            "schema": {
              "type": "string",
              "default": "unknown"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The recovery HTML page.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/recover/state": {
      "get": {
        "tags": [
          "Recovery"
        ],
        "summary": "Build state",
        "description": "Returns the line-scoped dist manifest snapshot (current build, history, last confirmed-good, rollback availability) for the recover page.",
        "security": [],
        "responses": {
          "200": {
            "description": "Line-scoped manifest snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DistState"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/recover/rollback": {
      "post": {
        "tags": [
          "Recovery"
        ],
        "summary": "Roll back dist",
        "description": "Atomically swaps the served client dist symlink back to a prior build (line-scoped default, or an explicit target) with no rebuild; loopback-only on a managed instance.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RollbackRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rollback succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RollbackResult"
                }
              }
            }
          },
          "400": {
            "description": "Rollback failed (no previous build, or target not found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RollbackResult"
                }
              }
            }
          },
          "403": {
            "description": "Non-loopback caller on a managed instance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/recover/boot-ok": {
      "post": {
        "tags": [
          "Recovery"
        ],
        "summary": "Mark boot good",
        "description": "Pinged by the SPA on its first successful render to mark a build confirmed-good so rollback prefers a build that really ran in a browser; loopback-only on a managed instance.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BootOkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Build marked confirmed-good.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Non-loopback caller on a managed instance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/self/deploy": {
      "post": {
        "tags": [
          "Self-edit"
        ],
        "summary": "Rebuild and restart",
        "description": "Rebuilds the Vite client into a versioned dist, atomically swaps the served symlink, then schedules a process exit so the supervisor respawns with the new code; loopback-guarded (true-loopback peer + managed agent bearer).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeployRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Build succeeded; restart scheduled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeployResponse"
                }
              }
            }
          },
          "500": {
            "description": "Build failed (log tail returned).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeployResponse"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/self/restart": {
      "post": {
        "tags": [
          "Self-edit"
        ],
        "summary": "Restart process",
        "description": "Schedules an exit-75 restart without rebuilding so the supervisor respawns the server; loopback-guarded (RCE-adjacent self-edit door).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "Restart scheduled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OkResponse"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/self/rollback": {
      "post": {
        "tags": [
          "Self-edit"
        ],
        "summary": "Rollback dist",
        "description": "Atomically swaps the served client dist symlink back to a prior build (no rebuild), defaulting to the current code line's last confirmed-good build; loopback-guarded agent/cli recovery door.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RollbackRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rolled back to the resolved build.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RollbackResult"
                }
              }
            }
          },
          "400": {
            "description": "No previous build, or the requested build was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RollbackResult"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/self/dist": {
      "get": {
        "tags": [
          "Self-edit"
        ],
        "summary": "Dist state",
        "description": "Returns the manifest snapshot (current build, last-confirmed-good, line-scoped history, and whether a rollback is possible) for the currently checked-out code line; loopback-guarded.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current dist/build manifest snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DistState"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/self/commit": {
      "post": {
        "tags": [
          "Self-edit"
        ],
        "summary": "Commit self-edits",
        "description": "Stages and commits the working tree (and pushes to origin if a remote exists, announcing the head when bound) so self-edits persist beyond the ephemeral container; loopback-guarded.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommitRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Committed (or nothing to commit) successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommitResult"
                }
              }
            }
          },
          "500": {
            "description": "Commit/push failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommitResult"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/skills": {
      "get": {
        "tags": [
          "Skills"
        ],
        "summary": "List skills",
        "description": "Scans the instance's `.claude/skills/*` and `.claude/commands/**` roots (name + description from each file's frontmatter), TTL-cached, for the composer's `/skill` autocomplete dropdown.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "The discovered skill catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSkillsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/system/health": {
      "get": {
        "tags": [
          "System & health"
        ],
        "summary": "Instance health snapshot",
        "description": "Returns a live snapshot of this instance's CPU, memory and disk (data-volume) usage, read straight from the OS.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current resource-usage snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemHealth"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/runtime/health": {
      "get": {
        "tags": [
          "System & health"
        ],
        "summary": "Runtime liveness probe",
        "description": "Always-open liveness probe confirming the instance runtime is up.",
        "security": [],
        "responses": {
          "200": {
            "description": "Runtime is alive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuntimeHealth"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/tools": {
      "get": {
        "tags": [
          "Tools & vault"
        ],
        "summary": "List visible tools",
        "description": "Returns the tool summaries visible to the caller (instance-scope tools union the caller's own user-scope tools), with secret config reduced to a masked hint.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "Visible tool summaries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tools": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ToolSummary"
                      }
                    }
                  },
                  "required": [
                    "tools"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Tools & vault"
        ],
        "summary": "Create tool",
        "description": "Creates an instance- or user-scope tool from the supplied secret-bearing config; an in-turn agent caller also gets the new tool added to its live token snapshot so it can immediately manage what it just made.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateToolRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tool created; returns its masked summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "$ref": "#/components/schemas/ToolSummary"
                    }
                  },
                  "required": [
                    "tool"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error (bad body / Zod failure).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/tools/{id}": {
      "put": {
        "tags": [
          "Tools & vault"
        ],
        "summary": "Update tool",
        "description": "Updates a manageable tool's metadata and/or full config; the config's type must match the existing tool's type (otherwise delete and recreate).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Opaque tool id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateToolRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated tool summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "$ref": "#/components/schemas/ToolSummary"
                    }
                  },
                  "required": [
                    "tool"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error (bad body, type change, or unreadable config).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Tool not found or not manageable by the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Tools & vault"
        ],
        "summary": "Delete tool",
        "description": "Deletes a manageable tool and cascades its per-session enablement rows in a transaction.",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Opaque tool id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Tool not found or not manageable by the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/tools/{id}/config": {
      "get": {
        "tags": [
          "Tools & vault"
        ],
        "summary": "Read raw config",
        "description": "Returns the unmasked secret-bearing config of a manageable tool (unsealed at rest; fails closed on a key/tamper fault).",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Opaque tool id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The raw tool config.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "config": {
                      "$ref": "#/components/schemas/ToolConfig"
                    }
                  },
                  "required": [
                    "config"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Config could not be read/unsealed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Tool not found or not manageable by the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.cial/api/v1/uploads": {
      "post": {
        "tags": [
          "Uploads"
        ],
        "summary": "Upload file",
        "description": "Stores a raw binary body as a per-owner attachment, with filename and MIME supplied via headers.",
        "parameters": [
          {
            "name": "x-cial-filename",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "file"
            },
            "description": "URL-encoded original filename; defaults to 'file' when absent."
          },
          {
            "name": "x-cial-mime",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "application/octet-stream"
            },
            "description": "MIME type of the upload; defaults to application/octet-stream."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Raw binary file contents (not JSON). Capped at CIAL_UPLOAD_MAX_BYTES (default 50 MiB); larger bodies return 413.",
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "File stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadResult"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds the maximum upload size.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerIdentity": []
          }
        ]
      }
    },
    "/.cial/api/v1/uploads/file": {
      "get": {
        "tags": [
          "Uploads"
        ],
        "summary": "Download file",
        "description": "Returns the raw bytes of a previously uploaded file, resolved within the caller's sandboxed upload directory.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The fileId returned by the upload endpoint."
          }
        ],
        "responses": {
          "200": {
            "description": "File bytes with a content-type inferred from the file extension.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Missing the required id query parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No file matches the id for this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "ownerIdentity": []
          }
        ]
      }
    },
    "/.cial/api/ws": {
      "get": {
        "tags": [
          "Realtime"
        ],
        "summary": "Realtime stream",
        "operationId": "ws",
        "description": "WebSocket upgrade. Drives turns and streams their output, plus the team channel, presence, and shared sessions. A real instance-content channel — on a managed instance the upgrade is rejected unless it presents the verified owner identity.",
        "x-cial-protocol": "websocket",
        "security": [
          {
            "ownerIdentity": []
          }
        ],
        "responses": {
          "101": {
            "description": "Switching Protocols — the socket is established."
          }
        }
      }
    }
  }
}