docs: align agent auth model and fix session test
This commit is contained in:
+1
-1
@@ -18,4 +18,4 @@ apps/ui/vite.config.js
|
||||
apps/ui/vite.config.d.ts
|
||||
*.log
|
||||
__*.md
|
||||
diplom.docx
|
||||
diploma/
|
||||
|
||||
@@ -2,6 +2,19 @@
|
||||
|
||||
## Current
|
||||
|
||||
### `feat/agent-scoped-machine-auth`
|
||||
|
||||
Status: ready
|
||||
|
||||
DoD:
|
||||
- AI agent can receive its own long-lived agent key from the admin UI
|
||||
- operation has an explicit security level: `standard`, `elevated`, or `strict`
|
||||
- machine calls to MCP can use short-lived agent tokens for elevated operations
|
||||
- one-time token mode is defined for strict operations
|
||||
- transition path from workspace-wide keys is explicit in docs and implementation slices
|
||||
|
||||
## Next
|
||||
|
||||
### `feat/live-authenticated-staging-entry`
|
||||
|
||||
Status: ready
|
||||
|
||||
@@ -340,7 +340,7 @@ mod tests {
|
||||
Executor,
|
||||
postgres::{PgConnectOptions, PgPoolOptions},
|
||||
};
|
||||
use time::format_description::well_known::Rfc3339;
|
||||
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{
|
||||
@@ -353,6 +353,12 @@ mod tests {
|
||||
time::OffsetDateTime::parse(value, &Rfc3339).unwrap()
|
||||
}
|
||||
|
||||
fn truncate_to_micros(value: OffsetDateTime) -> OffsetDateTime {
|
||||
value
|
||||
.replace_nanosecond((value.nanosecond() / 1_000) * 1_000)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn creates_and_reads_transport_sessions() {
|
||||
let store = InMemorySessionStore::default();
|
||||
@@ -455,15 +461,15 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let created_at = timestamp("2026-05-01T10:00:00Z");
|
||||
let initialized_at = timestamp("2026-05-01T10:00:05Z");
|
||||
let created_at = OffsetDateTime::now_utc() - time::Duration::hours(1);
|
||||
let initialized_at = created_at + time::Duration::seconds(5);
|
||||
let session_id = store_a
|
||||
.create(
|
||||
"2025-11-25",
|
||||
"default",
|
||||
"sales",
|
||||
created_at,
|
||||
Some(timestamp("2026-05-02T10:00:00Z")),
|
||||
Some(created_at + time::Duration::days(30)),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -482,7 +488,7 @@ mod tests {
|
||||
|
||||
assert_eq!(session.id, session_id);
|
||||
assert!(session.initialized);
|
||||
assert_eq!(session.updated_at, initialized_at);
|
||||
assert_eq!(session.updated_at, truncate_to_micros(initialized_at));
|
||||
assert_eq!(session.workspace_slug, "default");
|
||||
assert_eq!(session.agent_slug, "sales");
|
||||
}
|
||||
|
||||
+34
-15
@@ -2,7 +2,7 @@
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует целевые HTTP-контракты административного API, через которое UI управляет workspace, operations, agents, platform access и observability.
|
||||
Этот документ фиксирует целевые HTTP-контракты административного API, через которое UI управляет workspace, operations, agents, machine access и observability.
|
||||
|
||||
Для потоковой модели детальные HTTP DTO вынесены отдельно в:
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
- `secrets`
|
||||
- `auth-profiles`
|
||||
- `agents`
|
||||
- `platform-api-keys`
|
||||
- `agent-keys`
|
||||
- `logs`
|
||||
- `usage`
|
||||
- `samples`
|
||||
@@ -110,6 +110,12 @@
|
||||
- `GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}/export`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/import`
|
||||
|
||||
Контракт дополнительно включает:
|
||||
|
||||
- у операции задается обязательный `security_level`;
|
||||
- допустимые значения: `standard`, `elevated`, `strict`;
|
||||
- этот параметр определяет минимально допустимый режим машинного доступа при вызове через MCP.
|
||||
|
||||
### 5.4. Samples and descriptors
|
||||
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/input-json`
|
||||
@@ -169,20 +175,32 @@
|
||||
- `POST /api/admin/workspaces/{workspace_id}/agents/{agent_id}/archive`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/agents/{agent_id}/bindings`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/agents/{agent_id}/bindings/{operation_id}`
|
||||
|
||||
### 5.7. Platform API keys
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/platform-api-keys`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/platform-api-keys`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/platform-api-keys/{key_id}/revoke`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/platform-api-keys/{key_id}`
|
||||
- `GET /api/admin/workspaces/{workspace_id}/agents/{agent_id}/keys`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/agents/{agent_id}/keys`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/agents/{agent_id}/keys/{key_id}/revoke`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/agents/{agent_id}/keys/{key_id}`
|
||||
|
||||
Контракт:
|
||||
|
||||
- `POST /platform-api-keys` возвращает metadata ключа и одноразовый `secret`;
|
||||
- `secret` доступен только в create-response;
|
||||
- list endpoints возвращают только metadata, `prefix`, `status`, `scopes` и `last_used_at`.
|
||||
- `last_used_at` обновляется при успешной machine-auth аутентификации этим ключом в `mcp-server`.
|
||||
- `POST /agents/{agent_id}/keys` возвращает metadata ключа и одноразовый `secret`;
|
||||
- полное значение ключа доступно только в create-response;
|
||||
- list endpoints возвращают только metadata, `prefix`, `status`, `scopes`, `expires_at` и `last_used_at`;
|
||||
- ключ агента принадлежит одному `agent` и не должен использоваться как основной рабочий токен вызова в целевой защищенной схеме;
|
||||
- ключ агента используется для получения короткоживущего токена доступа к MCP endpoint.
|
||||
|
||||
### 5.7. Token issuance
|
||||
|
||||
Для расширенных редакций платформы:
|
||||
|
||||
- `POST /mcp-auth/v1/token`
|
||||
- `POST /mcp-auth/v1/token/one-time`
|
||||
|
||||
Контракт:
|
||||
|
||||
- `POST /mcp-auth/v1/token` выдает короткоживущий токен доступа для операций уровня `elevated`;
|
||||
- `POST /mcp-auth/v1/token/one-time` выдает одноразовый токен для операций уровня `strict`;
|
||||
- открытая редакция может не использовать эти конечные точки и работать только со статическим ключом агента;
|
||||
- детальная схема уровней и режимов доступа зафиксирована в `docs/agent-auth-model.md`.
|
||||
|
||||
### 5.8. Observability
|
||||
|
||||
@@ -245,8 +263,9 @@
|
||||
|
||||
Нужны:
|
||||
|
||||
- list/create/revoke/delete platform API keys;
|
||||
- one-time reveal значения ключа при создании.
|
||||
- list/create/revoke/delete agent keys;
|
||||
- one-time reveal значения ключа при создании;
|
||||
- для расширенных редакций — выдача короткоживущих и одноразовых токенов.
|
||||
|
||||
### Secrets
|
||||
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
# Модель машинной аутентификации и уровней защиты операций
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует целевую модель машинного доступа к опубликованным инструментам платформы. Модель строится вокруг двух принципов:
|
||||
|
||||
- длинноживущий машинный доступ принадлежит конкретному AI-агенту, а не рабочей области в целом;
|
||||
- требуемый уровень защиты определяется характером данных конкретной операции.
|
||||
|
||||
Именно поэтому в системе должны быть одновременно:
|
||||
|
||||
- ключ AI-агента как базовый машинный credential;
|
||||
- режимы выдачи токенов разной строгости;
|
||||
- обязательная политика защиты на уровне операции.
|
||||
|
||||
## 2. Базовая идея
|
||||
|
||||
Внутри платформы нужно различать:
|
||||
|
||||
1. чем клиент подтверждает право подключиться к агенту;
|
||||
2. какой уровень защиты требует операция;
|
||||
3. достаточно ли текущего машинного доступа для вызова этой операции.
|
||||
|
||||
Следовательно, решение нельзя строить только вокруг одного универсального токена. Оно должно учитывать и тип credential, и чувствительность самой ручки.
|
||||
|
||||
## 3. Уровни защиты операции
|
||||
|
||||
Каждая операция получает обязательный уровень защиты.
|
||||
|
||||
### 3.1. `standard`
|
||||
|
||||
Используется для обычных данных и типовых интеграционных вызовов.
|
||||
|
||||
Разрешенный доступ:
|
||||
|
||||
- статический ключ AI-агента;
|
||||
- короткоживущий токен;
|
||||
- одноразовый токен.
|
||||
|
||||
### 3.2. `elevated`
|
||||
|
||||
Используется для чувствительных внутренних данных, для которых постоянного ключа уже недостаточно.
|
||||
|
||||
Разрешенный доступ:
|
||||
|
||||
- короткоживущий токен;
|
||||
- одноразовый токен.
|
||||
|
||||
Статический ключ AI-агента для такого уровня уже недостаточен.
|
||||
|
||||
### 3.3. `strict`
|
||||
|
||||
Используется для максимально чувствительных данных, например содержащих коммерческую тайну, персональные данные высокой категории риска или иные критичные сведения.
|
||||
|
||||
Разрешенный доступ:
|
||||
|
||||
- только одноразовый токен на вызов.
|
||||
|
||||
Ни статический ключ, ни обычный короткоживущий токен для такого вызова не должны считаться достаточными.
|
||||
|
||||
## 4. Виды машинного доступа
|
||||
|
||||
### 4.1. Статический ключ AI-агента
|
||||
|
||||
Это длинноживущий ключ, принадлежащий одному агенту.
|
||||
|
||||
Свойства:
|
||||
|
||||
- привязан к одному `workspace`;
|
||||
- привязан к одному `agent`;
|
||||
- не используется для административных действий;
|
||||
- может быть отозван и перевыпущен;
|
||||
- в открытой редакции является основным механизмом подключения.
|
||||
|
||||
### 4.2. Короткоживущий токен
|
||||
|
||||
Это временный токен, выдаваемый на ограниченный срок.
|
||||
|
||||
Свойства:
|
||||
|
||||
- небольшой срок жизни;
|
||||
- ограниченная область действия;
|
||||
- может обновляться через стандартный поток OAuth 2.0;
|
||||
- подходит для платформенного размещения, где важен баланс удобства и безопасности.
|
||||
|
||||
### 4.3. Одноразовый токен
|
||||
|
||||
Это токен, который разрешает один вызов конкретной операции или одной логической единицы доступа.
|
||||
|
||||
Свойства:
|
||||
|
||||
- очень короткий срок жизни;
|
||||
- один допустимый вызов;
|
||||
- после первого использования считается исчерпанным;
|
||||
- предназначен для максимально чувствительных операций.
|
||||
|
||||
## 5. Правило сопоставления
|
||||
|
||||
Для вызова операции сервер сравнивает:
|
||||
|
||||
- уровень машинного доступа клиента;
|
||||
- обязательный уровень защиты операции.
|
||||
|
||||
Правило простое:
|
||||
|
||||
- если уровень доступа ниже, чем требует операция, вызов запрещается;
|
||||
- если уровень доступа равен или выше, вызов разрешается.
|
||||
|
||||
Именно это правило делает политику защиты независимой от того, в каком агенте опубликована операция.
|
||||
|
||||
## 6. Роль AI-агента
|
||||
|
||||
AI-агент:
|
||||
|
||||
- группирует операции;
|
||||
- формирует MCP-поверхность;
|
||||
- имеет собственный ключ подключения.
|
||||
|
||||
AI-агент не должен:
|
||||
|
||||
- ослаблять уровень защиты операции;
|
||||
- переопределять критичность данных;
|
||||
- разрешать более слабый способ вызова, чем требует сама операция.
|
||||
|
||||
Если в одном агенте опубликованы и обычные, и критичные операции, правила доступа к ним все равно различаются по уровню защиты самих операций.
|
||||
|
||||
## 7. Поддержка по редакциям продукта
|
||||
|
||||
### 7.1. Community
|
||||
|
||||
Открытая редакция должна поддерживать только один режим:
|
||||
|
||||
- статический ключ AI-агента.
|
||||
|
||||
Соответственно, в Community допустимы только операции уровня:
|
||||
|
||||
- `standard`.
|
||||
|
||||
### 7.2. Cloud или управляемая платформа
|
||||
|
||||
Для платформенного размещения должны поддерживаться:
|
||||
|
||||
- статический ключ AI-агента как режим совместимости;
|
||||
- короткоживущие токены по OAuth 2.0 как рекомендуемый режим.
|
||||
|
||||
Соответственно, платформа может обслуживать операции уровня:
|
||||
|
||||
- `standard`;
|
||||
- `elevated`.
|
||||
|
||||
### 7.3. Enterprise
|
||||
|
||||
Для корпоративной редакции должны поддерживаться все три режима:
|
||||
|
||||
- статический ключ AI-агента;
|
||||
- короткоживущий токен;
|
||||
- одноразовый токен.
|
||||
|
||||
Соответственно, допускаются операции уровня:
|
||||
|
||||
- `standard`;
|
||||
- `elevated`;
|
||||
- `strict`.
|
||||
|
||||
## 8. Потоки аутентификации
|
||||
|
||||
### 8.1. Community
|
||||
|
||||
1. Пользователь создает AI-агента.
|
||||
2. Платформа выдает статический ключ AI-агента.
|
||||
3. Клиент `Codex`, `Claude Code` или другой MCP-клиент использует этот ключ как bearer token при подключении к MCP endpoint.
|
||||
|
||||
Это самый простой и совместимый вариант.
|
||||
|
||||
### 8.2. Cloud или управляемая платформа
|
||||
|
||||
1. Пользователь или клиент проходит машинную аутентификацию.
|
||||
2. Сервер авторизации выдает короткоживущий токен доступа.
|
||||
3. Клиент использует его при работе с MCP endpoint.
|
||||
4. По истечении срока действия токен обновляется через стандартный механизм обновления.
|
||||
|
||||
Этот вариант должен опираться на OAuth 2.0 и обычный механизм refresh.
|
||||
|
||||
### 8.3. Enterprise
|
||||
|
||||
1. Клиент получает разрешение на вызов чувствительной операции.
|
||||
2. Сервер выдает одноразовый токен.
|
||||
3. Клиент выполняет один вызов.
|
||||
4. Токен становится недействительным.
|
||||
|
||||
Этот режим должен использоваться только там, где характер данных действительно требует такого уровня защиты.
|
||||
|
||||
## 9. Опорные стандарты
|
||||
|
||||
Для реализации расширенных режимов разумно опираться на готовые стандарты.
|
||||
|
||||
### OAuth 2.0
|
||||
|
||||
Используется как основа для короткоживущих токенов и их обновления.
|
||||
|
||||
### RFC 8693
|
||||
|
||||
Может использоваться как ориентир для схемы обмена одного вида machine credential на другой токен доступа.
|
||||
|
||||
### RFC 9449
|
||||
|
||||
Может использоваться как ориентир для будущей привязки токена к ключевой паре клиента, если потребуется дополнительная защита от повторного использования перехваченного токена.
|
||||
|
||||
## 10. Модель данных
|
||||
|
||||
Для этой схемы достаточно следующих базовых сущностей.
|
||||
|
||||
### `AgentKey`
|
||||
|
||||
Поля:
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `name`
|
||||
- `prefix`
|
||||
- `secret_hash`
|
||||
- `status`
|
||||
- `created_at`
|
||||
- `last_used_at`
|
||||
- `expires_at`
|
||||
|
||||
### `IssuedAgentToken`
|
||||
|
||||
Поля:
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `token_kind`
|
||||
- `status`
|
||||
- `expires_at`
|
||||
- `used_at`
|
||||
- `max_uses`
|
||||
- `used_count`
|
||||
- `created_at`
|
||||
|
||||
### Поля операции
|
||||
|
||||
На уровне операции должна появиться обязательная политика:
|
||||
|
||||
- `security_level`
|
||||
|
||||
Допустимые значения:
|
||||
|
||||
- `standard`
|
||||
- `elevated`
|
||||
- `strict`
|
||||
|
||||
## 11. Административный интерфейс
|
||||
|
||||
Настройка должна быть максимально простой.
|
||||
|
||||
На этапе создания или редактирования операции пользователь выбирает:
|
||||
|
||||
- `Обычный`
|
||||
- `Повышенная защита`
|
||||
- `Максимальная защита`
|
||||
|
||||
Смысл вариантов:
|
||||
|
||||
- `Обычный` — стандартный уровень для обычных данных;
|
||||
- `Повышенная защита` — короткоживущий токен;
|
||||
- `Максимальная защита` — одноразовый токен.
|
||||
|
||||
Пользователь не должен вручную настраивать детали OAuth или внутреннюю механику выдачи токенов на уровне операции.
|
||||
|
||||
## 12. Практический итог
|
||||
|
||||
Целевая модель машинного доступа для Crank должна строиться так:
|
||||
|
||||
- в Community — статический ключ AI-агента;
|
||||
- в управляемой платформе — короткоживущие токены;
|
||||
- в Enterprise — при необходимости одноразовые токены;
|
||||
- уровень защиты определяется операцией, а не агентом;
|
||||
- агент никогда не ослабляет обязательную защиту опубликованной операции.
|
||||
@@ -1,5 +1,10 @@
|
||||
# Alpine UI Integration Plan
|
||||
|
||||
Примечание:
|
||||
|
||||
- разделы, где машинный доступ UI описан через `platform-api-keys`, требуют обновления на модель `agent keys -> short-lived tokens`;
|
||||
- источником истины по этой части следует считать `docs/agent-auth-model.md`, `docs/admin-api.md` и `docs/mcp-interface.md`.
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует, как Alpine UI в `apps/ui` подключается к реальному backend.
|
||||
|
||||
+27
-6
@@ -29,7 +29,7 @@ Crank - платформа для публикации внешних API в в
|
||||
- `Workspace` - tenant boundary;
|
||||
- `Operation` - интеграционный контракт;
|
||||
- `Agent` - curated MCP surface;
|
||||
- `Platform API key` и `Membership` - доступ к самой платформе;
|
||||
- `Agent key`, `Agent token` и `Membership` - доступ к самой платформе;
|
||||
- `Invocation log` и `Usage rollup` - observability слой.
|
||||
|
||||
`Operation` остается фундаментом интеграции, но tools больше не публикуются глобально. MCP публикует tools в контексте конкретного `workspace` и конкретного `agent`.
|
||||
@@ -44,7 +44,8 @@ Crank - платформа для публикации внешних API в в
|
||||
- secrets;
|
||||
- auth profiles;
|
||||
- agents;
|
||||
- platform API keys;
|
||||
- agent keys;
|
||||
- short-lived agent tokens;
|
||||
- logs и usage;
|
||||
- пользователей и роли.
|
||||
|
||||
@@ -59,10 +60,17 @@ Crank - платформа для публикации внешних API в в
|
||||
- `input_schema`
|
||||
- `input_mapping`
|
||||
- `execution_config`
|
||||
- `security_level`
|
||||
- `output_mapping`
|
||||
- `tool_description`
|
||||
- `status`
|
||||
|
||||
Принцип:
|
||||
|
||||
- уровень защиты определяется самой операцией;
|
||||
- агент не может ослабить обязательный режим доступа;
|
||||
- для более чувствительных данных требуется более строгий вид машинного credential.
|
||||
|
||||
### `Agent`
|
||||
|
||||
Является пользовательской MCP-поверхностью для LLM.
|
||||
@@ -75,6 +83,8 @@ Crank - платформа для публикации внешних API в в
|
||||
- формирует отдельный MCP endpoint;
|
||||
- решает проблему "одному агенту нельзя отдавать 100 tools сразу".
|
||||
|
||||
При этом `Agent` не определяет чувствительность операции, а только публикует ее в составе MCP-поверхности.
|
||||
|
||||
### `Platform access`
|
||||
|
||||
Отдельный слой, не связанный с upstream auth:
|
||||
@@ -83,7 +93,16 @@ Crank - платформа для публикации внешних API в в
|
||||
- `UserSession`
|
||||
- `Membership`
|
||||
- `Invitation`
|
||||
- `PlatformApiKey`
|
||||
- `AgentKey`
|
||||
- `IssuedAgentToken`
|
||||
|
||||
Принцип:
|
||||
|
||||
- пользовательская аутентификация и машинная аутентификация разделены;
|
||||
- длинноживущий доступ для вызова MCP tools привязан к конкретному агенту, а не к рабочей области целиком;
|
||||
- в открытой редакции базовый режим строится на статическом ключе агента;
|
||||
- в более защищенных редакциях используются короткоживущие и одноразовые токены;
|
||||
- промежуточная схема с workspace-scoped ключами рассматривается как переходная и подлежит замене.
|
||||
|
||||
### `Upstream secrets`
|
||||
|
||||
@@ -133,7 +152,8 @@ Crank - платформа для публикации внешних API в в
|
||||
- Controlled streaming operations поверх `Streamable HTTP`, REST SSE, gRPC server-streaming и WebSocket upstream.
|
||||
- `Agent` и привязка операций к агенту.
|
||||
- Agent-scoped MCP endpoints.
|
||||
- Platform API keys.
|
||||
- Agent-scoped machine credentials.
|
||||
- Short-lived MCP access tokens.
|
||||
- Workspace-scoped encrypted secrets для upstream access.
|
||||
- Workspace-scoped auth profiles для upstream access.
|
||||
- Product logs и usage aggregates.
|
||||
@@ -171,7 +191,7 @@ Crank - платформа для публикации внешних API в в
|
||||
|
||||
### Администратор workspace
|
||||
|
||||
1. Управляет API keys платформы.
|
||||
1. Управляет ключами AI-агентов и доверенных клиентов платформы.
|
||||
2. Управляет пользователями и ролями.
|
||||
3. Смотрит logs и usage.
|
||||
|
||||
@@ -266,7 +286,8 @@ GraphQL в MCP публикуется как фиксированная опер
|
||||
- `StreamSession`
|
||||
- `AsyncJobHandle`
|
||||
- `AuthProfile`
|
||||
- `PlatformApiKey`
|
||||
- `AgentKey`
|
||||
- `IssuedAgentToken`
|
||||
- `UserSession`
|
||||
- `InvocationLog`
|
||||
- `UsageRollup`
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# As Is -> To Be
|
||||
|
||||
Примечание:
|
||||
|
||||
- разделы этого документа, где машинный доступ описан через workspace-scoped `platform API keys`, следует считать устаревшими;
|
||||
- целевая модель проекта переведена на `AgentKey`, короткоживущие токены доступа и при необходимости `PlatformClientCredential`;
|
||||
- подробности переноса зафиксированы в `docs/agent-auth-model.md`.
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует переход от текущего состояния проекта к целевой продуктовой модели, отраженной в текущем Alpine UI.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Backend Gap Plan
|
||||
|
||||
Примечание:
|
||||
|
||||
- пункты этого плана, относящиеся к `PlatformApiKey` как основной машинной модели доступа, рассматриваются как переходные;
|
||||
- актуальная целевая схема машинной аутентификации описана в `docs/agent-auth-model.md`.
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ превращает целевой Alpine UI и `docs/as-is-to-be.md` в конкретный backend-план.
|
||||
|
||||
+55
-6
@@ -46,7 +46,7 @@
|
||||
- `OperationVersion`
|
||||
- `AuthProfile`
|
||||
- `Agent`
|
||||
- `PlatformApiKey`
|
||||
- `AgentKey`
|
||||
- `InvocationLog`
|
||||
- `UsageRollup`
|
||||
|
||||
@@ -81,6 +81,22 @@
|
||||
|
||||
в рамках одной общей модели runtime и MCP publishing.
|
||||
|
||||
### 2.9. Уровень защиты задается операцией
|
||||
|
||||
Обязательная политика машинного доступа задается на уровне `Operation`, а не на уровне `Agent`.
|
||||
|
||||
Допустимые значения:
|
||||
|
||||
- `standard`
|
||||
- `elevated`
|
||||
- `strict`
|
||||
|
||||
Принцип:
|
||||
|
||||
- если операция требует более строгий режим доступа, агент не может его ослабить;
|
||||
- один агент может публиковать операции с разной критичностью данных;
|
||||
- `mcp-server` сравнивает тип представленного credential с требуемым `security_level`.
|
||||
|
||||
## 3. Корневые сущности
|
||||
|
||||
### 3.1. `Workspace`
|
||||
@@ -119,6 +135,7 @@
|
||||
- `input_mapping`
|
||||
- `output_mapping`
|
||||
- `execution_config`
|
||||
- `security_level`
|
||||
- `tool_description`
|
||||
- `samples`
|
||||
- `generated_draft`
|
||||
@@ -224,27 +241,59 @@
|
||||
- config ссылается на `secret_id` или пару `secret_id`, если auth-схема составная;
|
||||
- runtime применяет profile к запросу только в момент вызова upstream.
|
||||
|
||||
### 3.9. `PlatformApiKey`
|
||||
### 3.9. `AgentKey`
|
||||
|
||||
Отдельная сущность для доступа к самой платформе.
|
||||
Отдельная сущность для машинного доступа к инструментам одного конкретного AI-агента.
|
||||
|
||||
Поля:
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `name`
|
||||
- `prefix`
|
||||
- `scopes`
|
||||
- `status`
|
||||
- `created_at`
|
||||
- `last_used_at`
|
||||
- `expires_at`
|
||||
|
||||
Секрет:
|
||||
|
||||
- полный secret показывается только один раз при создании;
|
||||
- в persistent storage сохраняется только `secret_hash`.
|
||||
- полное значение ключа показывается только один раз при создании;
|
||||
- в persistent storage сохраняется только `secret_hash`;
|
||||
- ключ не должен использоваться как основной рабочий токен вызова в целевой защищенной модели;
|
||||
- ключ используется для выпуска короткоживущего токена доступа.
|
||||
|
||||
### 3.10. `User`
|
||||
### 3.10. `IssuedAgentToken`
|
||||
|
||||
Учет выданных машинных токенов для вызова MCP-инструментов.
|
||||
|
||||
Поля:
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `agent_key_id`
|
||||
- `platform_client_id`
|
||||
- `token_kind`
|
||||
- `status`
|
||||
- `scopes`
|
||||
- `max_uses`
|
||||
- `used_count`
|
||||
- `cnf_jkt`
|
||||
- `expires_at`
|
||||
- `created_at`
|
||||
- `used_at`
|
||||
|
||||
Принцип:
|
||||
|
||||
- токен живет ограниченное время;
|
||||
- токен может быть одноразовым;
|
||||
- токен может быть привязан к ключевой паре клиента;
|
||||
- токен выражает более узкие права, чем длинноживущий ключ агента.
|
||||
|
||||
### 3.11. `User`
|
||||
|
||||
Поля:
|
||||
|
||||
|
||||
+80
-5
@@ -27,7 +27,8 @@
|
||||
### 2.5. Секреты не хранятся в открытом виде
|
||||
|
||||
- upstream secrets живут в отдельных таблицах и шифруются;
|
||||
- platform API keys хранятся как hash.
|
||||
- agent keys и credentials доверенных клиентов хранятся как hash;
|
||||
- короткоживущие токены хранятся в форме, пригодной для отзыва и учета использования.
|
||||
|
||||
## 3. Основные таблицы
|
||||
|
||||
@@ -48,7 +49,9 @@
|
||||
- `agent_versions`
|
||||
- `agent_operation_bindings`
|
||||
- `published_agents`
|
||||
- `platform_api_keys`
|
||||
- `agent_keys`
|
||||
- `issued_agent_tokens`
|
||||
- `platform_client_credentials`
|
||||
- `stream_sessions`
|
||||
- `async_jobs`
|
||||
- `invocation_logs`
|
||||
@@ -65,6 +68,7 @@
|
||||
- `display_name`
|
||||
- `protocol`
|
||||
- `status`
|
||||
- `security_level`
|
||||
- `current_draft_version`
|
||||
- `latest_published_version`
|
||||
- `created_at`
|
||||
@@ -196,6 +200,59 @@
|
||||
|
||||
- `unique (workspace_id, name)`
|
||||
|
||||
### `agent_keys`
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `name`
|
||||
- `prefix`
|
||||
- `secret_hash`
|
||||
- `scopes_json`
|
||||
- `status`
|
||||
- `expires_at`
|
||||
- `created_at`
|
||||
- `last_used_at`
|
||||
|
||||
Ограничения:
|
||||
|
||||
- `unique (agent_id, name)`
|
||||
- `prefix` уникален глобально
|
||||
|
||||
Назначение:
|
||||
|
||||
- длинноживущий ключ принадлежит одному агенту;
|
||||
- ключ используется как исходное основание для выпуска короткоживущего токена;
|
||||
- прямой вызов MCP по такому ключу допускается только в переходном режиме.
|
||||
|
||||
### `issued_agent_tokens`
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `agent_key_id`
|
||||
- `token_kind`
|
||||
- `status`
|
||||
- `scopes_json`
|
||||
- `max_uses`
|
||||
- `used_count`
|
||||
- `cnf_jkt`
|
||||
- `expires_at`
|
||||
- `created_at`
|
||||
- `used_at`
|
||||
|
||||
Индексы:
|
||||
|
||||
- `(agent_id, status, expires_at)`
|
||||
- `(workspace_id, status, expires_at)`
|
||||
- `(cnf_jkt)` при включенной привязке токена к ключевой паре клиента
|
||||
|
||||
Назначение:
|
||||
|
||||
- учет выданных короткоживущих токенов;
|
||||
- поддержка одноразовых токенов;
|
||||
- поддержка отзыва и проверки повторного использования.
|
||||
|
||||
### `stream_sessions`
|
||||
|
||||
- `id`
|
||||
@@ -336,20 +393,38 @@
|
||||
- `published_at`
|
||||
- `published_by`
|
||||
|
||||
## 9. Platform access and observability
|
||||
## 9. Machine access and observability
|
||||
|
||||
### `platform_api_keys`
|
||||
### `agent_keys`
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `name`
|
||||
- `prefix`
|
||||
- `secret_hash`
|
||||
- `scopes_json`
|
||||
- `status`
|
||||
- `expires_at`
|
||||
- `created_at`
|
||||
- `last_used_at`
|
||||
|
||||
### `issued_agent_tokens`
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `agent_id`
|
||||
- `agent_key_id`
|
||||
- `token_kind`
|
||||
- `status`
|
||||
- `scopes_json`
|
||||
- `max_uses`
|
||||
- `used_count`
|
||||
- `cnf_jkt`
|
||||
- `expires_at`
|
||||
- `created_at`
|
||||
- `used_at`
|
||||
|
||||
### `invocation_logs`
|
||||
|
||||
- `id`
|
||||
@@ -397,6 +472,6 @@
|
||||
3. добавить `secrets` и `secret_versions`;
|
||||
4. перевести `auth_profiles` на secret-backed config;
|
||||
5. добавить `agents` и `published_agents`;
|
||||
6. внедрить `platform_api_keys`;
|
||||
6. внедрить `agent_keys`, `platform_client_credentials` и `issued_agent_tokens`;
|
||||
7. добавить `invocation_logs` и `usage_rollups`;
|
||||
8. перевести MCP runtime на `published_agents`, а не на глобальный список operations.
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
- связи между доменными сущностями;
|
||||
- хранение данных в БД.
|
||||
|
||||
Примечание:
|
||||
|
||||
- диаграммы требуют следующего обновления по слою машинного доступа;
|
||||
- вместо `PlatformApiKey` целевая модель проекта теперь использует `AgentKey`, `IssuedAgentToken` и при необходимости `PlatformClientCredential`;
|
||||
- детальная схема зафиксирована в `docs/agent-auth-model.md`.
|
||||
|
||||
## 2. Компонентная диаграмма
|
||||
|
||||
```mermaid
|
||||
|
||||
+30
-14
@@ -74,19 +74,35 @@ DoD:
|
||||
- binding operations к agent работает;
|
||||
- published agent появляется в MCP runtime.
|
||||
|
||||
## 7. Этап 6. Platform access
|
||||
## 7. Этап 6. Agent-scoped machine access
|
||||
|
||||
Цель:
|
||||
|
||||
- реализовать workspace access и platform API keys.
|
||||
- реализовать machine access на уровне AI-агента и ввести обязательный уровень защиты операции.
|
||||
|
||||
DoD:
|
||||
|
||||
- UI screens `API Keys`, `Settings`, `Workspace` имеют backend-контракт;
|
||||
- platform API keys не смешиваются с upstream auth profiles;
|
||||
- tenant boundary выражен в access layer.
|
||||
- UI умеет выпускать и отзывать ключи конкретного AI-агента;
|
||||
- длинноживущий машинный доступ больше не описывается ключом рабочей области;
|
||||
- у операции появляется обязательный `security_level`;
|
||||
- machine access не смешивается с upstream auth profiles;
|
||||
- Community поддерживает базовый режим со статическим ключом AI-агента.
|
||||
|
||||
## 8. Этап 7. Observability
|
||||
## 8. Этап 7. Token exchange and short-lived auth
|
||||
|
||||
Цель:
|
||||
|
||||
- внедрить расширенные режимы доступа для операций повышенной чувствительности.
|
||||
|
||||
DoD:
|
||||
|
||||
- существует конечная точка выдачи токена по ключу агента;
|
||||
- есть модель одноразового токена для чувствительных вызовов;
|
||||
- токены ограничены по сроку жизни, области действия и числу использований;
|
||||
- операции уровня `elevated` нельзя вызвать по статическому ключу;
|
||||
- операции уровня `strict` можно вызвать только по одноразовому токену.
|
||||
|
||||
## 9. Этап 8. Observability
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -98,7 +114,7 @@ DoD:
|
||||
- есть продуктовые endpoints, а не только application logs;
|
||||
- rollups и detail views согласованы с UI.
|
||||
|
||||
## 9. Этап 8. Alpine UI integration
|
||||
## 10. Этап 9. Alpine UI integration
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -110,7 +126,7 @@ DoD:
|
||||
- mock JSON больше не используется на критическом пути;
|
||||
- UI, backend и docs синхронизированы.
|
||||
|
||||
## 10. Этап 9. Secret store and upstream auth
|
||||
## 11. Этап 10. Secret store and upstream auth
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -124,7 +140,7 @@ DoD:
|
||||
- runtime умеет применять bearer/basic/api-key auth к реальному upstream request;
|
||||
- wizard имеет auth selector и quick-create flow для secrets/auth profiles.
|
||||
|
||||
## 11. Этап 10. Hardening and demo readiness
|
||||
## 12. Этап 11. Hardening and demo readiness
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -136,7 +152,7 @@ DoD:
|
||||
- deployment и healthchecks стабильно зелёные;
|
||||
- документация и продуктовый сценарий совпадают.
|
||||
|
||||
## 12. Этап 11. MCP streaming proxy support
|
||||
## 13. Этап 12. MCP streaming proxy support
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -150,7 +166,7 @@ DoD:
|
||||
- UI умеет конфигурировать streaming limits, aggregation и lifecycle;
|
||||
- e2e сценарии покрывают window/session/job calls.
|
||||
|
||||
## 13. Этап 12. WebSocket upstream support
|
||||
## 14. Этап 13. WebSocket upstream support
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -163,7 +179,7 @@ DoD:
|
||||
- heartbeat, reconnect и subscription lifecycle конфигурируются явно;
|
||||
- docs, UI и e2e синхронизированы.
|
||||
|
||||
## 14. Этап 13. SOAP support
|
||||
## 15. Этап 14. SOAP support
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -176,7 +192,7 @@ DoD:
|
||||
- operator может выбрать service, port и operation;
|
||||
- test-run, publish и observability работают так же, как для остальных протоколов.
|
||||
|
||||
## 15. Этап 14. Detailed streaming specs
|
||||
## 16. Этап 15. Detailed streaming specs
|
||||
|
||||
Цель:
|
||||
|
||||
@@ -188,7 +204,7 @@ DoD:
|
||||
- protocol docs не противоречат общей execution model;
|
||||
- roadmap и `TASKS.md` синхронизированы с full-detail architecture.
|
||||
|
||||
## 16. Этап 15. Streaming implementation slices
|
||||
## 17. Этап 16. Streaming implementation slices
|
||||
|
||||
Цель:
|
||||
|
||||
|
||||
+20
-7
@@ -98,16 +98,29 @@
|
||||
|
||||
## 7.1. MCP authentication
|
||||
|
||||
`mcp-server` использует workspace-scoped `platform API keys` как machine credentials.
|
||||
Целевая модель машинной аутентификации для `mcp-server` строится вокруг AI-агента, а не вокруг рабочей области целиком. При этом допустимый способ вызова определяется не только агентом, но и уровнем защиты самой операции.
|
||||
|
||||
Контракт:
|
||||
|
||||
- клиент передает `Authorization: Bearer crk_...`;
|
||||
- ключ должен принадлежать workspace из path;
|
||||
- `read` разрешает `initialize`, `notifications/initialized`, `ping`, `tools/list`;
|
||||
- `write` разрешает `tools/call`;
|
||||
- `deploy` сейчас включает те же MCP права, что и `write`, и зарезервирован для deploy-scoped automation;
|
||||
- успешная аутентификация обновляет `platform_api_keys.last_used_at`.
|
||||
- каждому published agent соответствует собственный длинноживущий `agent key`;
|
||||
- `agent key` принадлежит одновременно `workspace` и `agent`;
|
||||
- в редакции `Community` вызовы допускаются по статическому `agent key`;
|
||||
- в управляемой платформе для операций уровня `elevated` должен использоваться короткоживущий токен;
|
||||
- в редакции `Enterprise` для операций уровня `strict` должен использоваться одноразовый токен;
|
||||
- операция задает обязательный `security_level`, и `mcp-server` обязан отклонять вызов, если представленный credential слабее требуемого уровня;
|
||||
- детальная модель уровней зафиксирована в `docs/agent-auth-model.md`.
|
||||
|
||||
Уровни защиты операции:
|
||||
|
||||
- `standard`
|
||||
- `elevated`
|
||||
- `strict`
|
||||
|
||||
Правило применения:
|
||||
|
||||
- `standard` допускает статический ключ агента, короткоживущий токен и одноразовый токен;
|
||||
- `elevated` допускает короткоживущий токен и одноразовый токен;
|
||||
- `strict` допускает только одноразовый токен.
|
||||
|
||||
## 8. MCP lifecycle
|
||||
|
||||
|
||||
@@ -102,9 +102,10 @@
|
||||
- хранение workspace-scoped operations и version snapshots;
|
||||
- хранение workspace-scoped secrets и secret versions;
|
||||
- хранение agents и agent versions;
|
||||
- хранение agent keys и выданных agent tokens;
|
||||
- хранение stream sessions и async jobs;
|
||||
- auth profiles;
|
||||
- platform API keys;
|
||||
- platform client credentials;
|
||||
- logs и usage aggregates;
|
||||
- metadata по sample artifacts и descriptors.
|
||||
|
||||
@@ -138,7 +139,8 @@
|
||||
- `operations`
|
||||
- `auth_profiles`
|
||||
- `agents`
|
||||
- `platform_api_keys`
|
||||
- `agent_keys`
|
||||
- `platform_clients`
|
||||
- `logs`
|
||||
- `usage`
|
||||
- `streaming`
|
||||
|
||||
Reference in New Issue
Block a user