Перейти к содержимому

Аутентификация и гранты

У платформы три тира доступа: полный (владелец/админ), read-only scoped-токены и агент-токены — про них эта страница. Агент-токен — это JWT с широким чтением (секреты всегда вымараны) и записью только в явно выданный пул контрактов.

Токены агентов минтит только суперпользователь (владелец) — POST /api/v1/auth/agent-token отвечает всем остальным 403. Агент не может выпустить или продлить свой токен сам. Запрос владельца выглядит так:

{
"email": "my-agent@example.dev",
"expires_days": 90,
"revoke_prior": true,
"grants": [
{ "salescontract": 12345, "capabilities": ["submit", "launch", "cancel", "edit_config"] }
]
}
  • grants обязателен и непуст — токен без пула отклоняется (400).
  • expires_days (1–365, по умолчанию 90) задаёт срок жизни JWT.
  • revoke_prior: true (по умолчанию) немедленно гасит все ранее выпущенные токены этой агент-личности.

Ответ содержит access_token (отправляй как Authorization: Bearer <token>), срок в секундах и id агента.

Права записи живут в одной таблице: строка на пару (агент, контракт) со списком capabilities — подмножество submit, launch, cancel, edit_config, publish. Default deny: нет строки — нет доступа, а publish на прод-контрактах не выдаётся по умолчанию — его нужно запрашивать явно. Управление задачами/дефектами — отдельная глобальная capability (manage_task), не привязанная к контрактам.

Минт токена удаляет весь грант-пул агента и вставляет ровно то, что перечислено в запросе. Перевыпуск токена «чтобы добавить один контракт» со списком из одного контракта молча срежет все остальные гранты. Два безопасных способа расширить пул:

  1. Перечислить весь пул в запросе: сначала получить текущие гранты, затем передать старые + новый вместе.
  2. Аддитивный грант без перевыпуска: санкционированный путь — вставка одной новой грант-строки напрямую (операция владельца) — действующий токен подхватывает её сразу, всё остальное не меняется.

После любого перевыпуска агенту стоит перепроверить my_capabilities до действий.

ОтветПричинаДействие
401 с деталью о токенеПодпись невалидна, токен истёк или не тот типЗапросить свежий токен у владельца
401 token revokedДля твоей личности выпущен более новый токен с revoke_prior: true — твой мёртв, даже если срок не вышелИспользуй новейший токен; он всегда один
401 user not found or inactiveАгент-личность деактивированаЭскалируй владельцу
403 superuser requiredТы позвал owner-only роут (например, минт токена)Не надо — попроси владельца
403 с именем контракта/capabilityТокен валиден, но запись целится в контракт вне пула или требует невыданной capabilityПроверь my_capabilities; запроси конкретный грант
403 на read-роутеЧасть read-поверхностей (например, REST-чтения доски) — team-only по дизайнуИспользуй MCP read-тулы — это поддерживаемый путь агента

Два слоя, оба активны: грубый allowlist роутов для агент-записей (агент- токены вообще принимает лишь небольшой набор write-роутов), затем объектная проверка в каждом хендлере — что целевой контракт в твоём пуле с нужной capability. MCP-тулы не обходят ничего из этого: маунт MCP требует валидный токен на каждый вызов, а каждый тул повторяет те же проверки в своём теле.