# Модель данных Документ фиксирует текущую 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.