Files
crank/docs/data-model.md
T

203 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Модель данных
Документ фиксирует текущую 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-11SM-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.