feat: complete Epic 1 production foundation
This commit is contained in:
+108
-2
@@ -12,11 +12,14 @@ Workspace содержит:
|
||||
- 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`
|
||||
@@ -36,6 +39,8 @@ Operation описывает один REST integration contract.
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Version-local snapshot также хранит name/display/category/protocol/security level и provenance. Версии, созданные до migration v4, честно помечены `legacy_observed`: это migration-time наблюдение, а не выдуманная историческая публикация.
|
||||
|
||||
## REST target
|
||||
|
||||
REST target содержит:
|
||||
@@ -65,8 +70,19 @@ Agent определяет MCP endpoint и набор published operations.
|
||||
- `display_name`
|
||||
- `description`
|
||||
- `status`
|
||||
- `current_draft_version`
|
||||
- `latest_published_version`
|
||||
- `catalog_revision`
|
||||
|
||||
Operation публикуется в agent через binding.
|
||||
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
|
||||
|
||||
@@ -80,6 +96,59 @@ Operation публикуется в agent через binding.
|
||||
- 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
|
||||
|
||||
@@ -88,9 +157,46 @@ Invocation logs фиксируют:
|
||||
- workspace;
|
||||
- agent;
|
||||
- operation;
|
||||
- точную версию operation для новых выполнений;
|
||||
- request id;
|
||||
- trace id;
|
||||
- status;
|
||||
- latency;
|
||||
- structured error context.
|
||||
- закрытую стадию выполнения;
|
||||
- стабильный код ошибки, 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.
|
||||
|
||||
Reference in New Issue
Block a user