{
  "openapi": "3.1.0",
  "info": {
    "title": "myAI Gateway API",
    "version": "0.1.0",
    "description": "REST surface of the myAI management gateway — the local orchestration hub for the AI framework. Exposes specialist agents and skill playbooks, memory/RAG search over the embedded corpus, agent sessions and message routing, cron-style schedules, the cross-repo task queue, fleet orchestration (overview + dispatch cycles), and admin-gated LLM budget/spend reporting.\n\nRBAC v1 (ADR-013): mutation routes require a capability derived from the caller's server-side role (`viewer` < `member` < `admin` < `owner`; machine principals `system`/`operator`). Capabilities: `read` (viewer+), `work` (member+, e.g. task create/update), `configure` (admin+, e.g. schedule CRUD), `members` (admin+, e.g. invites), `billing` (owner+). Each enforced operation is annotated with `x-required-capability`. Enforcement is gated by the `RBAC_ENFORCE` flag — off (default) runs in shadow mode (logs `rbac.shadow`, allows); on returns 403 FORBIDDEN. Budget routes additionally require the operator `X-Admin-Token`."
  },
  "servers": [
    {
      "url": "http://localhost:3200",
      "description": "Local gateway"
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Liveness, deep health, and gateway status"
    },
    {
      "name": "Docs",
      "description": "This spec and the HTML reference"
    },
    {
      "name": "Agents",
      "description": "Specialist agent registry"
    },
    {
      "name": "Skills",
      "description": "Skill playbook registry"
    },
    {
      "name": "Hooks",
      "description": "Event hooks"
    },
    {
      "name": "Rules",
      "description": "Framework rules"
    },
    {
      "name": "Repos",
      "description": "Managed repositories"
    },
    {
      "name": "Channels",
      "description": "Channel adapters"
    },
    {
      "name": "Memory",
      "description": "SONA memory search and context building"
    },
    {
      "name": "Vectors",
      "description": "RAG vector search and indexing"
    },
    {
      "name": "Sessions",
      "description": "Agent sessions and message routing"
    },
    {
      "name": "Budgets",
      "description": "LLM spend reporting (admin-gated)"
    },
    {
      "name": "Tenants",
      "description": "Cross-tenant provisioning (admin-gated)"
    },
    {
      "name": "Schedules",
      "description": "Cron-style schedule CRUD and manual runs"
    },
    {
      "name": "Tasks",
      "description": "Cross-repo task queue"
    },
    {
      "name": "Orchestration",
      "description": "Fleet overview and dispatch cycles"
    },
    {
      "name": "Notifications",
      "description": "Cross-channel notification delivery"
    },
    {
      "name": "Webhooks",
      "description": "Inbound webhook receivers (GitHub)"
    },
    {
      "name": "Alerts",
      "description": "Proactive health alerting"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Liveness probe — uptime + MongoDB connection state",
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Service is up",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "uptime",
                    "mongodb"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "uptime": {
                      "type": "integer",
                      "description": "Seconds since process start"
                    },
                    "mongodb": {
                      "type": "string",
                      "enum": [
                        "connected",
                        "disconnected"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/health/deep": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Deep health check across subsystems",
        "operationId": "getDeepHealth",
        "responses": {
          "200": {
            "description": "Healthy or degraded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "healthy",
                        "degraded"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "description": "Health check itself failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "unhealthy"
                      ]
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Unhealthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "unhealthy"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/status": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Gateway status — version, counts of agents/skills/hooks/rules, session totals",
        "operationId": "getStatus",
        "responses": {
          "200": {
            "description": "Status snapshot",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "name",
                    "version",
                    "uptime",
                    "mongodb",
                    "llm",
                    "agents",
                    "skills",
                    "hooks",
                    "rules",
                    "sessions"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "uptime": {
                      "type": "integer"
                    },
                    "mongodb": {
                      "type": "string",
                      "enum": [
                        "connected",
                        "disconnected"
                      ]
                    },
                    "llm": {
                      "type": "string",
                      "enum": [
                        "configured",
                        "not_configured"
                      ]
                    },
                    "agents": {
                      "type": "integer"
                    },
                    "skills": {
                      "type": "integer"
                    },
                    "hooks": {
                      "type": "integer"
                    },
                    "rules": {
                      "type": "integer"
                    },
                    "sessions": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "active": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "tags": [
          "Docs"
        ],
        "summary": "This OpenAPI 3.1 document",
        "operationId": "getOpenApiSpec",
        "responses": {
          "200": {
            "description": "The OpenAPI document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/docs": {
      "get": {
        "tags": [
          "Docs"
        ],
        "summary": "Self-contained HTML API reference (renders /api/openapi.json client-side, no CDN)",
        "operationId": "getDocs",
        "responses": {
          "200": {
            "description": "HTML documentation page",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "List agents (MongoDB first, in-memory fallback)",
        "operationId": "listAgents",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Filter by agent category",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Case-insensitive regex over name/description (MongoDB path only)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Agent list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "source",
                    "agents"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "mongodb",
                        "memory"
                      ]
                    },
                    "agents": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Agent"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/{name}": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "Get a single agent by name (includes full instructions when found)",
        "operationId": "getAgent",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "description": "Agent name",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Agent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          },
          "404": {
            "description": "Agent not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/skills": {
      "get": {
        "tags": [
          "Skills"
        ],
        "summary": "List skills (MongoDB first, in-memory fallback)",
        "operationId": "listSkills",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Case-insensitive regex over name/description/triggers (MongoDB path only)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "agent",
            "in": "query",
            "required": false,
            "description": "Filter by owning agent (in-memory fallback path only)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Skill list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "source",
                    "skills"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "mongodb",
                        "memory"
                      ]
                    },
                    "skills": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Skill"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/skills/{name}": {
      "get": {
        "tags": [
          "Skills"
        ],
        "summary": "Get a single skill by name (includes full playbook when found)",
        "operationId": "getSkill",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "description": "Skill name",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Skill",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Skill"
                }
              }
            }
          },
          "404": {
            "description": "Skill not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/hooks": {
      "get": {
        "tags": [
          "Hooks"
        ],
        "summary": "List event hooks (MongoDB first, in-memory fallback)",
        "operationId": "listHooks",
        "responses": {
          "200": {
            "description": "Hook list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "source",
                    "hooks"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "mongodb",
                        "memory"
                      ]
                    },
                    "hooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Hook"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/rules": {
      "get": {
        "tags": [
          "Rules"
        ],
        "summary": "List rules (MongoDB first, in-memory fallback)",
        "operationId": "listRules",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Filter by rule category",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rule list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "source",
                    "rules"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "mongodb",
                        "memory"
                      ]
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Rule"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/rules/{name}": {
      "get": {
        "tags": [
          "Rules"
        ],
        "summary": "Get a single rule by name (includes full content when found)",
        "operationId": "getRule",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "description": "Rule name",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rule"
                }
              }
            }
          },
          "404": {
            "description": "Rule not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/repos": {
      "get": {
        "tags": [
          "Repos"
        ],
        "summary": "List managed repositories with AI-framework compliance flags",
        "operationId": "listRepos",
        "responses": {
          "200": {
            "description": "Managed repo list (count 0 + error field when managed_repos.txt is missing)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "repos"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "repos": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Repo"
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present only when managed_repos.txt is not found"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/channels": {
      "get": {
        "tags": [
          "Channels"
        ],
        "summary": "List channel adapters and active channel session count",
        "operationId": "listChannels",
        "responses": {
          "200": {
            "description": "Channel list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "activeSessions",
                    "channels"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "activeSessions": {
                      "type": "integer"
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Channel"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/memory/search": {
      "post": {
        "tags": [
          "Memory"
        ],
        "summary": "Hybrid memory search (keyword + tags)",
        "operationId": "searchMemory",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "At least one of `query` or non-empty `tags` is required.",
                "properties": {
                  "query": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "topN": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "query or tags required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Search failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/memory/context": {
      "post": {
        "tags": [
          "Memory"
        ],
        "summary": "Build a token-bounded context block from the memory store",
        "operationId": "buildMemoryContext",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "maxTokens": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assembled context",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "query required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Context build failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/memory/export": {
      "get": {
        "tags": [
          "Memory"
        ],
        "summary": "Export the memory corpus as a portable bundle (JSON manifest + markdown files, no embeddings)",
        "operationId": "exportMemoryBundle",
        "parameters": [
          {
            "name": "repo",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "state",
                "handoff",
                "commit",
                "pr",
                "pattern",
                "bug",
                "code",
                "feature",
                "archive"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Portable memory bundle",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "manifest",
                    "files"
                  ],
                  "properties": {
                    "manifest": {
                      "type": "object"
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "content"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "content": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid source",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Export failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/memory/import": {
      "post": {
        "tags": [
          "Memory"
        ],
        "summary": "Import a memory bundle — re-embeds each entry on this gateway, dedup by content hash",
        "operationId": "importMemoryBundle",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "files"
                ],
                "properties": {
                  "manifest": {
                    "type": "object"
                  },
                  "files": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "path",
                        "content"
                      ],
                      "properties": {
                        "path": {
                          "type": "string"
                        },
                        "content": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Import summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "filesTotal": {
                      "type": "integer"
                    },
                    "parsed": {
                      "type": "integer"
                    },
                    "invalid": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "dedupedInBundle": {
                      "type": "integer"
                    },
                    "hashMismatches": {
                      "type": "integer"
                    },
                    "stored": {
                      "type": "integer"
                    },
                    "skippedExisting": {
                      "type": "integer"
                    },
                    "failed": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "files required / invalid bundle",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/vectors/search": {
      "post": {
        "tags": [
          "Vectors"
        ],
        "summary": "Semantic vector search over the embedded corpus",
        "operationId": "searchVectors",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string"
                  },
                  "repo": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "limit": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vector matches",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "query required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Vector search failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/vectors/stats": {
      "get": {
        "tags": [
          "Vectors"
        ],
        "summary": "Total stored vector count",
        "operationId": "getVectorStats",
        "responses": {
          "200": {
            "description": "Vector stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Count failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/vectors/index": {
      "post": {
        "tags": [
          "Vectors"
        ],
        "summary": "Run the embedding indexer over the master repo or all managed repos",
        "operationId": "indexVectors",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "scope": {
                    "type": "string",
                    "enum": [
                      "master",
                      "all"
                    ],
                    "description": "Any value other than \"all\" indexes the master repo only (default master)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Indexing result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "scope",
                    "totalStored",
                    "results"
                  ],
                  "properties": {
                    "scope": {
                      "type": "string"
                    },
                    "totalStored": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Indexing failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/sessions": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "List sessions (summary shape, no message bodies)",
        "operationId": "listSessions",
        "responses": {
          "200": {
            "description": "Session list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "sessions"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "sessions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Session"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Sessions"
        ],
        "summary": "Create a session bound to an agent",
        "operationId": "createSession",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "agentName"
                ],
                "properties": {
                  "agentName": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "sessionId",
                    "agentName",
                    "status"
                  ],
                  "properties": {
                    "sessionId": {
                      "type": "string"
                    },
                    "agentName": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "agentName required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Agent not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Session creation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/sessions/{id}": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "Get session detail (last 20 messages + metadata)",
        "operationId": "getSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Session id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "404": {
            "description": "Session not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Sessions"
        ],
        "summary": "Close a session",
        "operationId": "closeSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Session id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Closed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "closed"
                      ]
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Close failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/sessions/{id}/messages": {
      "post": {
        "tags": [
          "Sessions"
        ],
        "summary": "Send a message into a session and get the agent response",
        "operationId": "postSessionMessage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Session id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "content"
                ],
                "properties": {
                  "content": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Routed message + response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "sessionId",
                    "agentName",
                    "messageId",
                    "response"
                  ],
                  "properties": {
                    "sessionId": {
                      "type": "string"
                    },
                    "agentName": {
                      "type": "string"
                    },
                    "messageId": {
                      "type": "string"
                    },
                    "response": {
                      "type": "object",
                      "description": "Agent response payload"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "content required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Session not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Routing failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/budgets/status": {
      "get": {
        "tags": [
          "Budgets"
        ],
        "summary": "Global spend snapshot (MTD / today / caps / thresholds)",
        "operationId": "getBudgetStatus",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Budget status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetStatus"
                }
              }
            }
          },
          "401": {
            "description": "X-Admin-Token header missing or wrong (code UNAUTHORIZED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error (code INTERNAL_ERROR)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "ADMIN_API_TOKEN not configured on the server (code ADMIN_DISABLED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/budgets/breakdown": {
      "get": {
        "tags": [
          "Budgets"
        ],
        "summary": "Spend breakdown by provider / model / channel / member",
        "operationId": "getBudgetBreakdown",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Window start (any Date-parsable timestamp; defaults to UTC start-of-month)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Window end (any Date-parsable timestamp)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetBreakdown"
                }
              }
            }
          },
          "400": {
            "description": "Invalid from/to timestamp (code BAD_REQUEST)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "X-Admin-Token header missing or wrong (code UNAUTHORIZED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error (code INTERNAL_ERROR)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "ADMIN_API_TOKEN not configured on the server (code ADMIN_DISABLED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/budgets/usage": {
      "get": {
        "tags": [
          "Budgets"
        ],
        "summary": "Paginated raw LLM usage rows",
        "operationId": "getBudgetUsage",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Window start timestamp",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Window end timestamp",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "channelId",
            "in": "query",
            "required": false,
            "description": "Filter by channel id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "provider",
            "in": "query",
            "required": false,
            "description": "Filter by LLM provider",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "query",
            "required": false,
            "description": "Filter by tenant member (User.userId)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "ISO createdAt of the last row from the previous page",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (default 50, capped at 500)",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rows"
                  ],
                  "properties": {
                    "rows": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BudgetUsageRow"
                      }
                    },
                    "nextCursor": {
                      "type": "string",
                      "description": "Present when more rows are available"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid from/to/limit (code BAD_REQUEST)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "X-Admin-Token header missing or wrong (code UNAUTHORIZED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error (code INTERNAL_ERROR)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "ADMIN_API_TOKEN not configured on the server (code ADMIN_DISABLED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/usage/summary": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Product-usage quantity totals (grouped by type / day / repo)",
        "operationId": "getUsageSummary",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Window start (any Date-parsable timestamp; defaults to store default)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Window end (exclusive)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "groupBy",
            "in": "query",
            "required": false,
            "description": "Group key (default type)",
            "schema": {
              "type": "string",
              "enum": [
                "type",
                "day",
                "repo"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid from/to/groupBy (code BAD_REQUEST)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "X-Admin-Token header missing or wrong (code UNAUTHORIZED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error (code INTERNAL_ERROR)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "ADMIN_API_TOKEN not configured on the server (code ADMIN_DISABLED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/usage/breakdown": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Product-usage rollup by tool / member / repo / day",
        "operationId": "getUsageBreakdown",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Window start (defaults to UTC start-of-month)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Window end (exclusive)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageBreakdown"
                }
              }
            }
          },
          "400": {
            "description": "Invalid from/to timestamp (code BAD_REQUEST)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "X-Admin-Token header missing or wrong (code UNAUTHORIZED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error (code INTERNAL_ERROR)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "ADMIN_API_TOKEN not configured on the server (code ADMIN_DISABLED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/schedules": {
      "get": {
        "tags": [
          "Schedules"
        ],
        "summary": "List schedules",
        "operationId": "listSchedules",
        "parameters": [
          {
            "name": "enabled",
            "in": "query",
            "required": false,
            "description": "Filter by enabled flag (\"true\" / \"false\")",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "Filter by schedule kind",
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "skill",
                "tool"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by last run status",
            "schema": {
              "type": "string",
              "enum": [
                "never",
                "success",
                "error"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max results (store default 100)",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "schedules"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "schedules": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Schedule"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error (e.g. MongoDB not connected)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Schedules"
        ],
        "summary": "Create a schedule (5-field cron, nextRun computed server-side)",
        "operationId": "createSchedule",
        "x-required-capability": "configure",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "cronExpr",
                  "kind",
                  "target",
                  "message"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "cronExpr": {
                    "type": "string",
                    "description": "5-field cron expression, e.g. \"0 9 * * *\""
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "agent",
                      "skill",
                      "tool"
                    ]
                  },
                  "target": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "repo": {
                    "type": "string"
                  },
                  "includeMemoryContext": {
                    "type": "boolean",
                    "default": false
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created schedule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Schedule"
                }
              }
            }
          },
          "400": {
            "description": "Missing required fields, unknown kind, or invalid cron expression",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/schedules/{id}": {
      "get": {
        "tags": [
          "Schedules"
        ],
        "summary": "Get a schedule by id",
        "operationId": "getSchedule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Schedule id (sched-…)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Schedule"
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Schedules"
        ],
        "summary": "Update a schedule (nextRun recomputed only when cronExpr changes)",
        "operationId": "updateSchedule",
        "x-required-capability": "configure",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Schedule id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "cronExpr": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "repo": {
                    "type": "string"
                  },
                  "includeMemoryContext": {
                    "type": "boolean"
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated schedule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Schedule"
                }
              }
            }
          },
          "400": {
            "description": "Invalid cron expression",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Schedules"
        ],
        "summary": "Delete a schedule",
        "operationId": "deleteSchedule",
        "x-required-capability": "configure",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Schedule id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "deleted",
                    "scheduleId"
                  ],
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "scheduleId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/schedules/{id}/run": {
      "post": {
        "tags": [
          "Schedules"
        ],
        "summary": "Run a schedule immediately (delegates to the schedules_run_now MCP handler; preserves nextRun)",
        "operationId": "runScheduleNow",
        "x-required-capability": "configure",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Schedule id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Run result — dispatch failures are still 200 with dispatched: false",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dispatched": {
                      "type": "boolean"
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when the dispatch failed"
                    },
                    "schedule": {
                      "$ref": "#/components/schemas/Schedule"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Handler error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/tasks": {
      "get": {
        "tags": [
          "Tasks"
        ],
        "summary": "List tasks",
        "operationId": "listTasks",
        "parameters": [
          {
            "name": "repo",
            "in": "query",
            "required": false,
            "description": "Filter by repo",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by status",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "working",
                "review",
                "done",
                "blocked"
              ]
            }
          },
          {
            "name": "priority",
            "in": "query",
            "required": false,
            "description": "Filter by priority",
            "schema": {
              "type": "string",
              "enum": [
                "P0",
                "P1",
                "P2",
                "P3"
              ]
            }
          },
          {
            "name": "assignedAgent",
            "in": "query",
            "required": false,
            "description": "Filter by assigned agent",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max results (store default 50)",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Task list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "tasks"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "tasks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Task"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Tasks"
        ],
        "summary": "Create a task (defaults: priority P2, source manual)",
        "operationId": "createTask",
        "x-required-capability": "work",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "repo",
                  "title"
                ],
                "properties": {
                  "repo": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "P0",
                      "P1",
                      "P2",
                      "P3"
                    ],
                    "default": "P2"
                  },
                  "assignedAgent": {
                    "type": "string"
                  },
                  "recommendedModel": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "manual",
                      "connect-hub",
                      "auto-detected",
                      "scheduler",
                      "telegram"
                    ],
                    "default": "manual"
                  },
                  "sourceId": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "repo and title required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/tasks/next": {
      "get": {
        "tags": [
          "Tasks"
        ],
        "summary": "Highest-priority pending task plus a per-status queue summary",
        "operationId": "getNextTask",
        "parameters": [
          {
            "name": "repo",
            "in": "query",
            "required": false,
            "description": "Restrict to one repo",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Next task, or { message: \"No pending tasks\" } when the queue is empty",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "task": {
                      "$ref": "#/components/schemas/Task"
                    },
                    "queueSummary": {
                      "$ref": "#/components/schemas/TaskQueueSummary"
                    },
                    "message": {
                      "type": "string",
                      "description": "Only present when the queue is empty"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/tasks/{id}": {
      "patch": {
        "tags": [
          "Tasks"
        ],
        "summary": "Update a task (status transitions stamp startedAt/completedAt)",
        "operationId": "updateTask",
        "x-required-capability": "work",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Task id (task-…)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "pending",
                      "working",
                      "review",
                      "done",
                      "blocked"
                    ]
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "P0",
                      "P1",
                      "P2",
                      "P3"
                    ]
                  },
                  "assignedAgent": {
                    "type": "string"
                  },
                  "recommendedModel": {
                    "type": "string"
                  },
                  "prUrl": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "telegramMessageId": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Store error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/fleet": {
      "get": {
        "tags": [
          "Orchestration"
        ],
        "summary": "Fleet overview across managed repos (delegates to the fleet_overview MCP handler)",
        "operationId": "getFleetOverview",
        "responses": {
          "200": {
            "description": "Fleet overview (repos / tasks / schedules / spend / topRepos)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "description": "Handler error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/dispatch": {
      "post": {
        "tags": [
          "Orchestration"
        ],
        "summary": "Run a dispatch cycle (invokes specialist agents — spends real LLM budget; admin-gated)",
        "operationId": "runDispatchCycle",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "maxTasks": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "description": "Clamped 1–10 by the dispatch_cycle handler"
                  },
                  "dailySpendCapUsd": {
                    "type": "number",
                    "description": "Numeric strings also accepted"
                  },
                  "telegramChatId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dispatch cycle result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tasksProcessed": {
                      "type": "integer"
                    },
                    "tasksSucceeded": {
                      "type": "integer"
                    },
                    "tasksFailed": {
                      "type": "integer"
                    },
                    "tasksSkipped": {
                      "type": "integer"
                    },
                    "totalCostUsd": {
                      "type": "number"
                    },
                    "details": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "X-Admin-Token header missing or wrong (code UNAUTHORIZED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error (code INTERNAL_ERROR)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "ADMIN_API_TOKEN not configured on the server (code ADMIN_DISABLED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/tenants/bulk-import": {
      "post": {
        "tags": [
          "Tenants"
        ],
        "summary": "Bulk-provision tenants + owner accounts from a CSV/JSON row set (reseller/agency onboarding, admin-gated)",
        "operationId": "bulkImportTenants",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "format",
                  "data"
                ],
                "properties": {
                  "format": {
                    "type": "string",
                    "enum": [
                      "csv",
                      "json"
                    ],
                    "description": "'csv' expects a raw CSV string in `data`; 'json' expects an array (or JSON-encoded string of an array) of row objects"
                  },
                  "data": {
                    "description": "CSV text, or a JSON array of {name, plan, seats, adminEmail} rows"
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Validate/preview only, no writes. Defaults to true — pass false to actually provision."
                  },
                  "provisionedBy": {
                    "type": "string",
                    "description": "Operator identity, stamped into each created tenant’s metadata"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-row validation/provisioning report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "batchId",
                    "dryRun",
                    "totalRows",
                    "validRows",
                    "invalidRows",
                    "createdRows",
                    "failedRows",
                    "results"
                  ],
                  "properties": {
                    "batchId": {
                      "type": "string"
                    },
                    "dryRun": {
                      "type": "boolean"
                    },
                    "totalRows": {
                      "type": "integer"
                    },
                    "validRows": {
                      "type": "integer"
                    },
                    "invalidRows": {
                      "type": "integer"
                    },
                    "createdRows": {
                      "type": "integer"
                    },
                    "failedRows": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "row": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "plan": {
                            "type": "string",
                            "enum": [
                              "free",
                              "solo",
                              "team",
                              "scale"
                            ]
                          },
                          "seats": {
                            "type": "integer"
                          },
                          "adminEmail": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "valid",
                              "invalid",
                              "created",
                              "error"
                            ]
                          },
                          "tenantId": {
                            "type": "string"
                          },
                          "apiKey": {
                            "type": "string",
                            "description": "Show-once raw API key — present only on a freshly created row"
                          },
                          "errors": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "format must be 'csv'/'json', unparsable data, or over the per-batch row cap (code BAD_REQUEST)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "X-Admin-Token header missing or wrong (code UNAUTHORIZED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "ADMIN_API_TOKEN not configured on the server (code ADMIN_DISABLED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/notifications": {
      "post": {
        "tags": [
          "Notifications"
        ],
        "summary": "Send a notification to one or more channels",
        "operationId": "sendNotification",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message": {
                    "type": "string",
                    "description": "Notification body text"
                  },
                  "channels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Target channels (default: all enabled)"
                  },
                  "chatId": {
                    "type": "string",
                    "description": "Specific chat/channel ID"
                  },
                  "level": {
                    "type": "string",
                    "enum": [
                      "info",
                      "warning",
                      "error",
                      "critical"
                    ],
                    "description": "Severity level (default: info)"
                  },
                  "title": {
                    "type": "string",
                    "description": "Bold title line"
                  },
                  "source": {
                    "type": "string",
                    "description": "Source identifier (e.g. webhook, health-alert)"
                  }
                },
                "required": [
                  "message"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notification result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sent": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "totalSent": {
                      "type": "integer"
                    },
                    "totalFailed": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing message field",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Notifications"
        ],
        "summary": "Get recent notification history",
        "operationId": "listNotifications",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Notification history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/github": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Receive GitHub webhook events (issues, PRs, CI, pushes)",
        "operationId": "handleGitHubWebhook",
        "description": "Verifies HMAC-SHA256 signature against GITHUB_WEBHOOK_SECRET env var. Auto-creates tasks from issues, sends Telegram notifications for PRs and CI failures.",
        "parameters": [
          {
            "name": "x-github-event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-hub-signature-256",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-github-delivery",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "handled": {
                      "type": "boolean"
                    },
                    "event": {
                      "type": "string"
                    },
                    "action": {
                      "type": "string"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "taskCreated": {
                      "type": "string"
                    },
                    "notificationSent": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid webhook signature",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/health/alerts": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "Get health alerting status and latest check result",
        "operationId": "getHealthAlerts",
        "parameters": [
          {
            "name": "run",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Set to true to force an immediate check cycle"
          }
        ],
        "responses": {
          "200": {
            "description": "Health alert status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "latest": {
                      "type": "object",
                      "nullable": true
                    },
                    "alerting": {
                      "type": "object",
                      "properties": {
                        "active": {
                          "type": "boolean"
                        },
                        "intervalMinutes": {
                          "type": "integer"
                        },
                        "lastRun": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "lastOverall": {
                          "type": "string",
                          "nullable": true
                        },
                        "dedupWindowHours": {
                          "type": "number"
                        },
                        "trackedAlerts": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Standard error envelope. `code` is present on admin/dispatch endpoints only.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message"
          },
          "code": {
            "type": "string",
            "description": "Machine-readable code (e.g. UNAUTHORIZED, ADMIN_DISABLED, BAD_REQUEST, INTERNAL_ERROR)"
          }
        }
      },
      "Agent": {
        "type": "object",
        "description": "Specialist agent definition. MongoDB-sourced documents may carry extra fields; the in-memory fallback returns this minimal shape.",
        "required": [
          "name",
          "description",
          "category"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": true
      },
      "Skill": {
        "type": "object",
        "description": "Skill playbook summary. MongoDB-sourced documents may carry extra fields.",
        "required": [
          "name",
          "description"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "triggers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": true
      },
      "Hook": {
        "type": "object",
        "required": [
          "name",
          "events",
          "priority",
          "enabled"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "priority": {
            "type": "number"
          },
          "enabled": {
            "type": "boolean"
          },
          "source": {
            "type": "string"
          },
          "timeout": {
            "type": "number"
          }
        },
        "additionalProperties": true
      },
      "Rule": {
        "type": "object",
        "required": [
          "name",
          "description",
          "category"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "Repo": {
        "type": "object",
        "description": "A managed repository as parsed from config/managed_repos.txt.",
        "required": [
          "name",
          "path",
          "group",
          "accessible",
          "aiDir",
          "stateExists",
          "stateFresh",
          "claudeMd",
          "geminiMd"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "group": {
            "type": "string",
            "description": "Section heading the repo appears under in managed_repos.txt"
          },
          "accessible": {
            "type": "boolean"
          },
          "aiDir": {
            "type": "boolean",
            "description": "AI/ folder exists"
          },
          "stateExists": {
            "type": "boolean"
          },
          "stateFresh": {
            "type": "boolean",
            "description": "STATE.md modified within the last 72 hours"
          },
          "claudeMd": {
            "type": "boolean"
          },
          "geminiMd": {
            "type": "boolean"
          }
        }
      },
      "Channel": {
        "type": "object",
        "required": [
          "type",
          "enabled"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "Session": {
        "type": "object",
        "description": "Agent session. The list endpoint returns the summary fields; GET /api/sessions/{id} additionally includes the last 20 messages and metadata.",
        "required": [
          "id",
          "agentName",
          "status",
          "messageCount",
          "createdAt",
          "lastActivity"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "agentName": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "messageCount": {
            "type": "integer"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Last 20 messages (detail endpoint only)"
          },
          "metadata": {
            "type": "object",
            "description": "Detail endpoint only"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastActivity": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Schedule": {
        "type": "object",
        "description": "ScheduleView as returned by scheduler/schedule-store.ts.",
        "required": [
          "scheduleId",
          "name",
          "cronExpr",
          "kind",
          "target",
          "message",
          "includeMemoryContext",
          "enabled",
          "lastStatus",
          "runCount",
          "errorCount",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "scheduleId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "cronExpr": {
            "type": "string",
            "description": "5-field cron expression (min hour day month dow)"
          },
          "kind": {
            "type": "string",
            "enum": [
              "agent",
              "skill",
              "tool"
            ]
          },
          "target": {
            "type": "string",
            "description": "Agent name, skill name, or tool name to dispatch"
          },
          "message": {
            "type": "string"
          },
          "repo": {
            "type": "string"
          },
          "includeMemoryContext": {
            "type": "boolean"
          },
          "enabled": {
            "type": "boolean"
          },
          "lastRun": {
            "type": "string",
            "format": "date-time"
          },
          "nextRun": {
            "type": "string",
            "format": "date-time"
          },
          "lastStatus": {
            "type": "string",
            "enum": [
              "never",
              "success",
              "error"
            ]
          },
          "lastError": {
            "type": "string"
          },
          "lastResultSummary": {
            "type": "string"
          },
          "runCount": {
            "type": "integer"
          },
          "errorCount": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Task": {
        "type": "object",
        "description": "TaskView as returned by tasks/task-store.ts.",
        "required": [
          "taskId",
          "repo",
          "title",
          "description",
          "priority",
          "status",
          "source",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "taskId": {
            "type": "string"
          },
          "repo": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "priority": {
            "type": "string",
            "enum": [
              "P0",
              "P1",
              "P2",
              "P3"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "working",
              "review",
              "done",
              "blocked"
            ]
          },
          "assignedAgent": {
            "type": "string"
          },
          "recommendedModel": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "manual",
              "connect-hub",
              "auto-detected",
              "scheduler",
              "telegram"
            ]
          },
          "sourceId": {
            "type": "string"
          },
          "prUrl": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "telegramMessageId": {
            "type": "integer"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TaskQueueSummary": {
        "type": "object",
        "description": "Per-status task counts (countTasks).",
        "required": [
          "pending",
          "working",
          "review",
          "done",
          "blocked"
        ],
        "properties": {
          "pending": {
            "type": "integer"
          },
          "working": {
            "type": "integer"
          },
          "review": {
            "type": "integer"
          },
          "done": {
            "type": "integer"
          },
          "blocked": {
            "type": "integer"
          }
        }
      },
      "BudgetStatus": {
        "type": "object",
        "description": "Global spend snapshot from llm/budget-stats.ts.",
        "required": [
          "enabled",
          "mtd",
          "today",
          "monthlyHardCapUsd",
          "monthlyDailyCapUsd",
          "warnThreshold",
          "downgradeOpusThreshold",
          "downgradeSonnetThreshold",
          "monthStart",
          "dayStart"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Whether budget guards are enabled (BUDGETS_ENABLED)"
          },
          "mtd": {
            "type": "number",
            "description": "Month-to-date spend in USD"
          },
          "today": {
            "type": "number",
            "description": "Today's spend in USD"
          },
          "monthlyHardCapUsd": {
            "type": "number"
          },
          "monthlyDailyCapUsd": {
            "type": "number"
          },
          "perChannelMonthlyCapUsd": {
            "type": "number"
          },
          "warnThreshold": {
            "type": "number"
          },
          "downgradeOpusThreshold": {
            "type": "number"
          },
          "downgradeSonnetThreshold": {
            "type": "number"
          },
          "monthStart": {
            "type": "string",
            "format": "date-time"
          },
          "dayStart": {
            "type": "string",
            "format": "date-time"
          },
          "perChannel": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "channelId",
                "mtd"
              ],
              "properties": {
                "channelId": {
                  "type": "string"
                },
                "mtd": {
                  "type": "number"
                }
              }
            }
          }
        }
      },
      "BudgetBreakdown": {
        "type": "object",
        "required": [
          "monthStart",
          "byProvider",
          "byModel",
          "byChannel",
          "byUser"
        ],
        "properties": {
          "monthStart": {
            "type": "string",
            "format": "date-time"
          },
          "byProvider": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "provider": {
                  "type": "string"
                },
                "cost": {
                  "type": "number"
                },
                "calls": {
                  "type": "integer"
                }
              }
            }
          },
          "byModel": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "model": {
                  "type": "string"
                },
                "cost": {
                  "type": "number"
                },
                "calls": {
                  "type": "integer"
                }
              }
            }
          },
          "byChannel": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "channelId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "cost": {
                  "type": "number"
                },
                "calls": {
                  "type": "integer"
                }
              }
            }
          },
          "byUser": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "userId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "cost": {
                  "type": "number"
                },
                "calls": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "BudgetUsageRow": {
        "type": "object",
        "required": [
          "callId",
          "provider",
          "model",
          "inputTokens",
          "outputTokens",
          "costUsd",
          "createdAt"
        ],
        "properties": {
          "callId": {
            "type": "string"
          },
          "channelId": {
            "type": "string"
          },
          "channelType": {
            "type": "string"
          },
          "agentName": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "inputTokens": {
            "type": "integer"
          },
          "outputTokens": {
            "type": "integer"
          },
          "costUsd": {
            "type": "number"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "UsageSummary": {
        "type": "object",
        "description": "Product-meter (UsageEvent) quantity totals per group key. From shared/usage-store.ts::summarizeUsage.",
        "required": [
          "totals",
          "groupBy"
        ],
        "properties": {
          "totals": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Summed quantity per group key (event type, day, or repo)"
          },
          "groupBy": {
            "type": "string",
            "enum": [
              "type",
              "day",
              "repo"
            ]
          },
          "from": {
            "type": "string",
            "format": "date-time"
          },
          "to": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "UsageBreakdown": {
        "type": "object",
        "description": "Multi-dimension product-usage rollup (tool / member / repo / day). From shared/usage-store.ts::getUsageBreakdown.",
        "required": [
          "from",
          "byType",
          "byUser",
          "byRepo",
          "byDay"
        ],
        "properties": {
          "from": {
            "type": "string",
            "format": "date-time"
          },
          "to": {
            "type": "string",
            "format": "date-time"
          },
          "byType": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageBreakdownGroup"
            }
          },
          "byUser": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageBreakdownGroup"
            }
          },
          "byRepo": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageBreakdownGroup"
            }
          },
          "byDay": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "day",
                "quantity",
                "events"
              ],
              "properties": {
                "day": {
                  "type": "string",
                  "description": "YYYY-MM-DD (UTC)"
                },
                "quantity": {
                  "type": "number"
                },
                "events": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "UsageBreakdownGroup": {
        "type": "object",
        "required": [
          "key",
          "quantity",
          "events"
        ],
        "properties": {
          "key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Group value (event type / userId / repo); null when unattributed"
          },
          "quantity": {
            "type": "number"
          },
          "events": {
            "type": "integer"
          }
        }
      }
    },
    "securitySchemes": {
      "AdminToken": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Admin-Token",
        "description": "Must match the ADMIN_API_TOKEN env var. Endpoints return 503 ADMIN_DISABLED when the server has no token configured, 401 UNAUTHORIZED on a missing/wrong header."
      },
      "SessionJWT": {
        "type": "apiKey",
        "in": "cookie",
        "name": "myai_token",
        "description": "Session JWT (also accepted as `Authorization: Bearer <jwt>`). Carries the caller's role claim, which RBAC v1 (ADR-013) maps to capabilities. Routes marked `x-required-capability` return 403 FORBIDDEN when the role lacks the capability and RBAC_ENFORCE is on (shadow mode otherwise)."
      }
    }
  }
}
