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