356 lines
12 KiB
Markdown
356 lines
12 KiB
Markdown
# Архитектура
|
||
|
||
## 1. Назначение проекта
|
||
|
||
Crank - платформа для публикации внешних API в виде MCP tools без написания отдельного backend-кода под каждую интеграцию. Пользователь конфигурирует интеграции через UI, а система:
|
||
|
||
- хранит и версионирует операции;
|
||
- группирует их по workspace;
|
||
- публикует их в составе конкретных agents;
|
||
- выдает LLM не глобальный каталог tools, а curated toolset на один agent;
|
||
- собирает продуктовые логи и usage по workspace, agent и operation.
|
||
|
||
## 2. Переход `As Is -> To Be`
|
||
|
||
### 2.1. As Is
|
||
|
||
Текущее ядро системы построено вокруг:
|
||
|
||
- глобальной сущности `Operation`;
|
||
- registry версий операций;
|
||
- runtime adapters `REST / GraphQL / unary gRPC`;
|
||
- `admin-api` для CRUD и тестовых вызовов;
|
||
- `mcp-server`, который публикует tools из published operations.
|
||
|
||
### 2.2. To Be
|
||
|
||
Целевая архитектура расширяет текущее ядро до модели:
|
||
|
||
- `Workspace` - tenant boundary;
|
||
- `Operation` - интеграционный контракт;
|
||
- `Agent` - curated MCP surface;
|
||
- `Agent key`, `Agent token` и `Membership` - доступ к самой платформе;
|
||
- `Invocation log` и `Usage rollup` - observability слой.
|
||
|
||
`Operation` остается фундаментом интеграции, но tools больше не публикуются глобально. MCP публикует tools в контексте конкретного `workspace` и конкретного `agent`.
|
||
|
||
## 3. Ключевые сущности и их роль
|
||
|
||
### `Workspace`
|
||
|
||
Изолирует:
|
||
|
||
- операции;
|
||
- secrets;
|
||
- auth profiles;
|
||
- agents;
|
||
- agent keys;
|
||
- short-lived agent tokens;
|
||
- logs и usage;
|
||
- пользователей и роли.
|
||
|
||
### `Operation`
|
||
|
||
Описывает один вызываемый элемент независимо от протокола:
|
||
|
||
- `name`
|
||
- `display_name`
|
||
- `protocol`
|
||
- `target`
|
||
- `input_schema`
|
||
- `input_mapping`
|
||
- `execution_config`
|
||
- `security_level`
|
||
- `output_mapping`
|
||
- `tool_description`
|
||
- `status`
|
||
|
||
Принцип:
|
||
|
||
- уровень защиты определяется самой операцией;
|
||
- агент не может ослабить обязательный режим доступа;
|
||
- для более чувствительных данных требуется более строгий вид машинного credential.
|
||
|
||
### `Agent`
|
||
|
||
Является пользовательской MCP-поверхностью для LLM.
|
||
|
||
`Agent`:
|
||
|
||
- принадлежит одному workspace;
|
||
- имеет `slug`, `display_name`, `description`, `status`;
|
||
- ссылается на ограниченный набор published operations;
|
||
- формирует отдельный MCP endpoint;
|
||
- решает проблему "одному агенту нельзя отдавать 100 tools сразу".
|
||
|
||
При этом `Agent` не определяет чувствительность операции, а только публикует ее в составе MCP-поверхности.
|
||
|
||
### `Platform access`
|
||
|
||
Отдельный слой, не связанный с upstream auth:
|
||
|
||
- `User`
|
||
- `UserSession`
|
||
- `Membership`
|
||
- `Invitation`
|
||
- `AgentKey`
|
||
- `IssuedAgentToken`
|
||
|
||
Принцип:
|
||
|
||
- пользовательская аутентификация и машинная аутентификация разделены;
|
||
- длинноживущий доступ для вызова MCP tools привязан к конкретному агенту, а не к рабочей области целиком;
|
||
- в открытой редакции базовый режим строится на статическом ключе агента;
|
||
- в более защищенных редакциях используются короткоживущие и одноразовые токены;
|
||
- промежуточная схема с workspace-scoped ключами рассматривается как переходная и подлежит замене.
|
||
|
||
### `Upstream secrets`
|
||
|
||
Отдельный слой для доступа к внешним системам:
|
||
|
||
- `Secret`
|
||
- `SecretVersion`
|
||
- `AuthProfile`
|
||
|
||
Принцип:
|
||
|
||
- секреты принадлежат workspace;
|
||
- plaintext не хранится в открытом виде;
|
||
- `AuthProfile` описывает способ применения секрета к upstream request;
|
||
- runtime резолвит `auth_profile_ref` в реальный header/query/basic auth только в момент вызова.
|
||
|
||
### `Observability`
|
||
|
||
Отдельный продуктовый слой:
|
||
|
||
- `InvocationLog`
|
||
- `InvocationEvent`
|
||
- `UsageRollup`
|
||
- `LatencyStats`
|
||
|
||
## 4. Главный принцип проектирования
|
||
|
||
Система строится в три слоя:
|
||
|
||
1. `Operation` как низкоуровневый интеграционный контракт.
|
||
2. `Agent` как curated набор published operations.
|
||
3. `Workspace` как граница данных, доступа и observability.
|
||
|
||
Это позволяет:
|
||
|
||
- переиспользовать одну operation в нескольких agents;
|
||
- ограничивать tool catalog для конкретного LLM-сценария;
|
||
- изолировать данные команд;
|
||
- строить logs и usage не глобально, а по tenant boundary.
|
||
|
||
## 5. Границы целевого продукта
|
||
|
||
### Входит
|
||
|
||
- `Workspace` как tenant boundary.
|
||
- Операции `REST`, `GraphQL`, `gRPC`, `WebSocket`, `SOAP`.
|
||
- Controlled streaming operations поверх `Streamable HTTP`, REST SSE, gRPC server-streaming и WebSocket upstream.
|
||
- `Agent` и привязка операций к агенту.
|
||
- Agent-scoped MCP endpoints.
|
||
- 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.
|
||
- Импорт и экспорт operation-конфигураций в `YAML`.
|
||
- Hot reload опубликованных agents и operations.
|
||
|
||
### Отложено
|
||
|
||
- GraphQL `subscription`.
|
||
- gRPC client-streaming и bidirectional streaming.
|
||
- raw infinite stream passthrough.
|
||
- полный стек WS-* расширений.
|
||
- Оркестрация workflow.
|
||
- Биллинг.
|
||
- Full RBAC policy engine.
|
||
- Traffic splitting и deployment orchestration.
|
||
|
||
## 6. Пользовательские сценарии
|
||
|
||
### Оператор операций
|
||
|
||
1. Выбирает workspace.
|
||
2. Создает или редактирует operation.
|
||
3. При необходимости выбирает или создает upstream secret / auth profile.
|
||
4. Выполняет test run.
|
||
5. Публикует operation version.
|
||
6. Привязывает operation к одному или нескольким agents.
|
||
|
||
### Оператор агентов
|
||
|
||
1. Создает agent.
|
||
2. Выбирает набор published operations.
|
||
3. Публикует agent.
|
||
4. Получает MCP endpoint вида `/mcp/v1/{workspace}/{agent}`.
|
||
|
||
### Администратор workspace
|
||
|
||
1. Управляет ключами AI-агентов и доверенных клиентов платформы.
|
||
2. Управляет пользователями и ролями.
|
||
3. Смотрит logs и usage.
|
||
|
||
## 7. Стратегия по протоколам
|
||
|
||
### REST
|
||
|
||
- `GET`
|
||
- `POST`
|
||
- `PUT`
|
||
- `PATCH`
|
||
- `DELETE`
|
||
- path parameters
|
||
- query parameters
|
||
- headers
|
||
- JSON request body
|
||
- JSON response body
|
||
|
||
### GraphQL
|
||
|
||
- `query`
|
||
- `mutation`
|
||
- endpoint URL
|
||
- request headers
|
||
- operation template
|
||
- variables mapping
|
||
|
||
## 8. Open-core граница
|
||
|
||
Crank развивается как open-core продукт.
|
||
|
||
Это означает:
|
||
|
||
- `Community` должна полностью собираться из этого репозитория;
|
||
- коммерческие возможности не должны храниться здесь как рабочий private code;
|
||
- различия между редакциями должны отражаться в capability model, API, UI и delivery pipeline.
|
||
|
||
Ключевые продуктовые различия зафиксированы в `docs/product-editions.md`.
|
||
|
||
## 9. Коммерческий контур
|
||
|
||
Коммерческий контур не должен защищаться "скрытием" уже опубликованного исходного кода. Правильная архитектурная граница выглядит так:
|
||
|
||
- в public repo остается Community runtime и extension seams;
|
||
- коммерческие реализации поставляются из private repositories или private artifacts;
|
||
- критичные правила лицензирования, metering и token issuance исполняются на серверной стороне.
|
||
|
||
Практические правила зафиксированы в `docs/commercial-boundaries.md`.
|
||
- извлечение результата из `data`
|
||
|
||
GraphQL в MCP публикуется как фиксированная операция с предсказуемой структурой ответа.
|
||
|
||
### gRPC
|
||
|
||
- unary RPC;
|
||
- bounded server-streaming через `window`, `session` и `async_job` execution modes;
|
||
- `.proto` и `descriptor set`;
|
||
- JSON-oriented schema model поверх protobuf;
|
||
- без client-streaming и bidi.
|
||
|
||
### WebSocket
|
||
|
||
- upstream-only adapter;
|
||
- bounded `window`, `session` и `async_job`;
|
||
- subscribe/unsubscribe messages;
|
||
- heartbeat и reconnect policy;
|
||
- не используется как downstream MCP transport.
|
||
|
||
### SOAP
|
||
|
||
- WSDL-driven request-response integration;
|
||
- service/port/operation selection;
|
||
- SOAP envelope и fault normalization;
|
||
- request-response first;
|
||
- long-running workflows через `async_job`, если upstream это поддерживает.
|
||
|
||
### Streaming
|
||
|
||
Платформа поддерживает controlled streaming model:
|
||
|
||
- downstream transport: `Streamable HTTP` с optional SSE;
|
||
- upstream streaming: REST SSE, gRPC server-streaming и WebSocket;
|
||
- execution modes: `unary`, `window`, `session`, `async_job`;
|
||
- никакого raw infinite stream passthrough в MCP client.
|
||
|
||
## 8. Работа с файлами и автогенерация черновика
|
||
|
||
Поддерживаемые источники:
|
||
|
||
- пример входного `JSON`;
|
||
- пример выходного `JSON`;
|
||
- `.proto`;
|
||
- `descriptor set`.
|
||
|
||
Ожидаемый сценарий:
|
||
|
||
1. оператор загружает артефакты;
|
||
2. система строит черновую схему и mapping;
|
||
3. оператор вручную корректирует результат;
|
||
4. готовую конфигурацию можно экспортировать в `YAML`.
|
||
|
||
## 9. Внутренняя модель данных
|
||
|
||
Базовые сущности:
|
||
|
||
- `Workspace`
|
||
- `Secret`
|
||
- `SecretVersion`
|
||
- `Operation`
|
||
- `OperationVersion`
|
||
- `Agent`
|
||
- `AgentVersion`
|
||
- `AgentOperationBinding`
|
||
- `StreamSession`
|
||
- `AsyncJobHandle`
|
||
- `AuthProfile`
|
||
- `AgentKey`
|
||
- `IssuedAgentToken`
|
||
- `UserSession`
|
||
- `InvocationLog`
|
||
- `UsageRollup`
|
||
|
||
## 10. MCP publishing model
|
||
|
||
Публикация tools строится так:
|
||
|
||
1. `Operation` проходит versioning и publish.
|
||
2. `Agent` собирает curated набор published operations.
|
||
3. `MCP server` читает published view конкретного agent.
|
||
4. `tools/list` и `tools/call` работают в контексте `workspace + agent`.
|
||
|
||
## 11. Observability
|
||
|
||
На каждый вызов tool сохраняются:
|
||
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `operation_id`
|
||
- `request_id`
|
||
- `timestamp`
|
||
- `status`
|
||
- `duration_ms`
|
||
- `error_kind`
|
||
- `request_preview`
|
||
- `response_preview`
|
||
|
||
Сверху строятся:
|
||
|
||
- logs page;
|
||
- usage page;
|
||
- периодические rollups;
|
||
- latency and error aggregates.
|
||
|
||
## 12. Модель маппинга
|
||
|
||
Платформе нужен отдельный слой маппинга:
|
||
|
||
- сопоставление поле-в-поле по `JSONPath`;
|
||
- константы;
|
||
- значения по умолчанию;
|
||
- извлечение вложенных полей из ответа.
|