203 lines
9.2 KiB
Markdown
203 lines
9.2 KiB
Markdown
# Модель данных
|
||
|
||
Документ фиксирует текущую Community data model.
|
||
|
||
## Workspace
|
||
|
||
Workspace содержит:
|
||
|
||
- operations;
|
||
- agents;
|
||
- secrets;
|
||
- auth profiles;
|
||
- logs;
|
||
- usage.
|
||
- immutable local ProductEvents.
|
||
|
||
## Operation
|
||
|
||
Operation описывает один REST integration contract.
|
||
|
||
`Operation` хранит identity и availability (`active|archived`), а `OperationVersion` — самостоятельный immutable execution/export snapshot. Каждый изменённый save добавляет monotonic Draft revision; publish переводит только current Draft в Published и никогда не двигает publication pointer назад. Archive меняет только aggregate availability.
|
||
|
||
Основные поля:
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `name`
|
||
- `display_name`
|
||
- `category`
|
||
- `protocol = rest`
|
||
- `status`
|
||
- `target`
|
||
- `input_schema`
|
||
- `output_schema`
|
||
- `input_mapping`
|
||
- `output_mapping`
|
||
- `execution_config`
|
||
- `tool_description`
|
||
- `created_at`
|
||
- `updated_at`
|
||
|
||
Version-local snapshot также хранит name/display/category/protocol/security level и provenance. Версии, созданные до migration v4, честно помечены `legacy_observed`: это migration-time наблюдение, а не выдуманная историческая публикация.
|
||
|
||
## REST target
|
||
|
||
REST target содержит:
|
||
|
||
- `base_url`
|
||
- `method`
|
||
- `path_template`
|
||
- `static_headers`
|
||
|
||
Поддерживаемые методы:
|
||
|
||
- `GET`
|
||
- `POST`
|
||
- `PUT`
|
||
- `PATCH`
|
||
- `DELETE`
|
||
|
||
## Agent
|
||
|
||
Agent определяет MCP endpoint и набор published operations.
|
||
|
||
Основные поля:
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `slug`
|
||
- `display_name`
|
||
- `description`
|
||
- `status`
|
||
- `current_draft_version`
|
||
- `latest_published_version`
|
||
- `catalog_revision`
|
||
|
||
Agent catalog lifecycle (`agent-catalog-lifecycle-v9`) разделяет mutable aggregate и immutable Published Agent Version:
|
||
|
||
- Draft/current version можно редактировать до publication;
|
||
- Published Agent Version и его bindings являются append-only snapshot и не изменяются in place;
|
||
- `published_agents` хранит current published pointer и `catalog_revision`;
|
||
- `catalog_revision` монотонно увеличивается при publish/unpublish/archive и связывает MCP search result с последующей `call_tool`;
|
||
- Agent binding всегда указывает exact Published Operation Version из того же workspace.
|
||
|
||
Archive меняет availability Agent aggregate и запрещает новые публикации/bindings через Admin API, но не переписывает уже опубликованные snapshots и historical invocation evidence.
|
||
|
||
## Secrets и auth profiles
|
||
|
||
`Secret` хранит encrypted secret material.
|
||
|
||
`AuthProfile` описывает, как применить secret к REST request:
|
||
|
||
- bearer token;
|
||
- basic auth;
|
||
- API key header;
|
||
- API key query parameter.
|
||
|
||
Plaintext secret не возвращается через API после создания.
|
||
Rotation добавляет новую encrypted version и делает её текущей для следующего
|
||
execution. Operation и Auth Profile продолжают хранить только ссылки; их не
|
||
нужно переписывать при rotation.
|
||
|
||
Master-key identity — отдельный durable security contract. PostgreSQL хранит
|
||
только non-secret fingerprint, active epoch и cipher contract. Каждая новая
|
||
`secret_versions` row содержит `master_key_epoch`; legacy rows считаются epoch
|
||
`1`. Во время operator-controlled master-key rotation target ciphertext
|
||
записывается рядом с текущим ciphertext и не становится authoritative до
|
||
verification/promotion. Promotion атомарно переводит active epoch и переносит
|
||
target ciphertext в основной ciphertext. Abort до promotion оставляет текущий
|
||
epoch активным и очищает staged target fields.
|
||
|
||
## MCP и approval keys
|
||
|
||
`PlatformApiKey` хранит только metadata, bounded prefix и hash. Raw key
|
||
возвращается один раз в create response. Новые Invocation History records могут
|
||
безопасно хранить typed exact `platform_api_key_id`, полученный из verified
|
||
machine credential; сам credential и hash в history не записываются.
|
||
|
||
Ключи разделены по назначению:
|
||
|
||
- `mcp_client` — доступ MCP client к опубликованному Agent catalog;
|
||
- `approval` — approval side-channel с отдельным scope и optional
|
||
`allowed_origins`.
|
||
|
||
Lifecycle статусы:
|
||
|
||
- `active`;
|
||
- `revoked`;
|
||
- `deleted`.
|
||
|
||
`revoke` немедленно прекращает доступ. `delete` переводит revoked key в
|
||
terminal metadata state `deleted`, сохраняя provenance. Credential lifecycle
|
||
пишет bounded audit events через `AuditSink`; plaintext, raw key, ciphertext и
|
||
hash в audit payload не попадают.
|
||
|
||
## Approval requests
|
||
|
||
`approval_requests` — PostgreSQL authority для human approval side-channel.
|
||
Pending uniqueness задаётся full scope index:
|
||
`workspace_id, agent_id, operation_id, operation_version, request_fingerprint`
|
||
для `status = 'pending'`. Fingerprint считается по canonical JSON input без
|
||
служебных Crank control fields, поэтому retry с новым confirmation token не
|
||
создаёт новый pending request. `request_payload_json` хранит bounded safe summary,
|
||
а не raw payload; secret-like ключи редактируются до записи.
|
||
|
||
Execution transitions выполняются conditional update:
|
||
`pending → approved|denied|expired`, затем `approved → executing`, затем
|
||
terminal `completed|failed`. Повторный terminal approve/deny возвращает текущую
|
||
заявку и не запускает второй side effect. Если процесс прервался после dispatch,
|
||
recovery не делает автоматический retry mutating operation и сохраняет
|
||
`approval_execution_outcome_unknown`.
|
||
|
||
## Logs и usage
|
||
|
||
Invocation logs фиксируют:
|
||
|
||
- workspace;
|
||
- agent;
|
||
- operation;
|
||
- точную версию operation для новых выполнений;
|
||
- request id;
|
||
- trace id;
|
||
- status;
|
||
- latency;
|
||
- закрытую стадию выполнения;
|
||
- стабильный код ошибки, retryability и certainty результата.
|
||
- nullable exact MCP key identity для новых scoped machine invocations.
|
||
|
||
Поля классификации nullable для строк, созданных до migration v5: исторические
|
||
значения не восстанавливаются предположениями. Новые Admin Draft Test и MCP
|
||
выполнения записывают точную версию и оба correlation ID независимо от
|
||
telemetry sampling.
|
||
|
||
Usage rollups агрегируют вызовы по периодам.
|
||
Агрегация использует UTC half-open windows `[start, end)` и не группирует по
|
||
Request ID или Trace ID. Для операторского анализа Usage отдельно отдаёт
|
||
outcome groups `success`, `upstream`, `client`, `schema`, `crank`, чтобы не
|
||
смешивать ошибки внешнего сервиса, входных данных, схемы и самого Crank.
|
||
|
||
Retention применим только к строкам `invocation_logs` старше effective cutoff.
|
||
Effective cutoff вычисляется как минимум из requested cutoff и preservation
|
||
floor, который сохраняет последние 90 дней usage-данных для операторской
|
||
аналитики. Outcome retention операции typed и observable: `noop` или
|
||
`completed`, количество удалённых rows и применённая policy. Retention не
|
||
изменяет Published Operation Version, Agent snapshot, approvals или immutable
|
||
release evidence.
|
||
|
||
## Local ProductEvents
|
||
|
||
`ProductEvent` — локальное immutable versioned событие продукта. В V11 закрытый
|
||
словарь состоит из `onboarding_eligible`, `onboarding_started`,
|
||
`onboarding_resumed`, `onboarding_dismissed`, `onboarding_abandoned` и
|
||
`onboarding_completed`. Событие содержит workspace scope, `schema_version = 1`,
|
||
UTC occurrence time и bounded idempotency key; `onboarding_eligible` обязательно
|
||
несёт explicit `eligible_since`, поэтому denominator SM-11–SM-13 не выводится
|
||
из browser state.
|
||
|
||
`product_events` append-only: update/delete отклоняются PostgreSQL trigger.
|
||
Idempotency уникальна в пределах workspace. `product_event_daily_rollups`
|
||
хранит только workspace/event/day counters (`events_total`, `eligible_total`),
|
||
без raw user/object identifiers, payload, key material или usage. ProductEvents остаются
|
||
локальными и не становятся внешней analytics отправкой без отдельного opt-in.
|