diff --git a/docs/adr/0015-google-calendar-connection.md b/docs/adr/0015-google-calendar-connection.md index ab1ee05..32e620c 100644 --- a/docs/adr/0015-google-calendar-connection.md +++ b/docs/adr/0015-google-calendar-connection.md @@ -42,6 +42,17 @@ Calendar MCP передаёт `tenantId` и `actorId` в Connection Service. Т Google Calendar этого пользователя и возвращает короткоживущий access token. Refresh token никогда не покидает Connection Service. +Для первого среза Calendar MCP передаёт в Connection Service тот же короткоживущий service JWT, +который Action Service получил по Client Credentials и отправил через MCP Gateway. Это сохраняет +проверенный `tenant_id` без нового tenant-параметра в HTTP body. Токен содержит audience +`mcp-gateway`, `calendar-mcp` и `connection-service`, а также scopes `mcp:call`, `calendar:write` и +`connection:token`. Connection Service разрешает internal endpoint только `azp=action-service`. + +Gateway и Calendar MCP не сохраняют этот токен и не пишут его в логи. Такая делегация ограничена +коротким сроком жизни токена и доверенным backend-контуром. Если сервисы выйдут из одного trust +boundary, отдельный ADR заменит делегацию на OAuth Token Exchange либо workload identity с ещё более +узкой аудиторией. + Если подключений нет или их несколько без выбранного default, действие не выполняется скрытно. Пользователь получает понятный результат `connection_required` или выбирает календарь до нового подтверждения. @@ -65,6 +76,8 @@ Google-адаптер использует Calendar API `events.insert` и scope - Публичные OAuth start/callback/disconnect принадлежат Connection Service. - Внутренний token endpoint требует service JWT с audience `connection-service` и scope `connection:token`. +- В первом срезе `azp` этого токена равен `action-service`; Calendar MCP не получает отдельный + статический client secret. - Calendar MCP не принимает refresh token через MCP tool. - MCP Gateway не хранит токены и не выбирает календарь. - Action Service не шифрует provider credentials и не вызывает Google API. diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 5bea1fd..8523fad 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -5,6 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: + fast-uri: 3.1.7 js-yaml: 4.3.2 serialize-javascript: 7.0.3 image-size: 2.0.3 @@ -2985,8 +2986,8 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-uri@3.1.6: - resolution: {integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==} + fast-uri@3.1.7: + resolution: {integrity: sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==} fastdom@1.0.12: resolution: {integrity: sha512-LB+xjSTEbjHE1cWsxu+tN2Xqr1kpi+V9aADI7sVM5ZMaXyYGPHULQMzpJMYqOTULK/73pUkWVzzObFRBkPr+hg==} @@ -8589,7 +8590,7 @@ snapshots: ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.6 + fast-uri: 3.1.7 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -9709,7 +9710,7 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - fast-uri@3.1.6: {} + fast-uri@3.1.7: {} fastdom@1.0.12: dependencies: diff --git a/website/pnpm-workspace.yaml b/website/pnpm-workspace.yaml index 885b97f..a5046bf 100644 --- a/website/pnpm-workspace.yaml +++ b/website/pnpm-workspace.yaml @@ -1,6 +1,7 @@ allowBuilds: core-js: true overrides: + fast-uri: 3.1.7 js-yaml: 4.3.2 serialize-javascript: 7.0.3 image-size: 2.0.3