Глава 29

Свяжите A2A security, tasks и tenant ownership

Agent Card может объявить API key, HTTP auth, OAuth2, OpenID Connect или mTLS. Но здесь легко успокоиться раньше времени: security scheme решает только способ authentication - кто пришёл. Он ничего не говорит о том, что этому субъекту можно. Поэтому каждый Task, Message и Artifact должен быть связан с verified principal и tenant, а не просто пройти вход.

Объявляется схема в card примерно так - через OIDC с требуемым scope.

JSON
{
  "securitySchemes": {
    "corporateOidc": {
      "openIdConnectSecurityScheme": {
        "openIdConnectUrl": "https://id.example.com/.well-known/openid-configuration"
      }
    }
  },
  "securityRequirements": [
    {
      "schemes": {
        "corporateOidc": {
          "list": [
            "release.review"
          ]
        }
      }
    }
  ]
}

А дальше начинается настоящая работа - authorization-инварианты на каждой операции.

Объект · Authorization invariant

  • Agent Card - Public card не раскрывает private skills/secrets; extended card требует auth
  • SendMessage - Principal имеет право на skill и входные данные
  • Get/List Task - Task принадлежит principal/tenant; not-found не раскрывает чужой id
  • Cancel Task - Caller владеет task и state допускает cancel
  • Artifact - Parts проходят DLP/media/size policy до возврата
  • Push config - Callback разрешен policy и привязан к task owner

Читать таблицу стоит как чек-лист, который код обязан выполнять сам. Public card не раскрывает приватные skills и секреты. SendMessage проверяет право principal на skill и входные данные. Get/List Task отдаёт только задачи этого principal/tenant, а на чужой id отвечает not-found, не раскрывая существование. Cancel проверяет владение и допустимость состояния. Artifact проходит DLP-, media- и size-политику до возврата.

Отдельно - про версии и bindings. A2A 1.0 разделяет общий data model, операции и конкретные bindings; клиент передаёт service-параметры, включая версию и extensions, по правилам binding. Не смешивайте pre-1.0 примеры с текущей card: в 1.0, например, extendedAgentCard находится внутри capabilities.

Task id не является secret. Даже UUID нельзя считать authorization. Любой Get/Cancel/List обязан проверять verified owner - иначе утечка id мгновенно превращается в утечку artifacts.

Обе границы системы собраны и защищены по отдельности. Финальный шаг - составить их в одну production-архитектуру и проверить, что они действительно независимы.

Проверка знаний

Клиент знает taskId (UUID). Можно ли на его основе разрешить Get Task?

Ссылки