Files
crank/docs/operations-workspace-contracts.md
T
2026-03-31 23:41:08 +03:00

680 lines
15 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.
# Operations Workspace Contracts
## 1. Назначение документа
Этот документ задает точные `workspace-scoped` контракты для экранов:
- `Operations`
- `Wizard`
Документ нужен как промежуточный слой между:
- текущим Alpine UI в `apps/ui`;
- `docs/backend-gap-plan.md`;
- реализацией `admin-api`.
## 2. Общие правила
Базовый префикс:
```text
/api/admin/workspaces/{workspace_id}
```
Общие принципы:
- все operation принадлежат одному workspace;
- каталог операций отдается целиком с сервера и не требует client-side merge поверх локального mock state;
- wizard работает только через backend и не опирается на `localStorage` или `sessionStorage`;
- versioning остается явным;
- текущий draft lifecycle отделен от published lifecycle;
- `PATCH /operations/{operation_id}` обновляет текущий draft;
- `POST /operations/{operation_id}/versions` создает новый explicit snapshot;
- опубликованная operation не удаляется hard delete, если на нее есть published agent bindings.
## 3. Канонические представления
### 3.1. `OperationSummary`
Используется в каталоге операций.
```json
{
"id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"name": "crm_create_lead",
"display_name": "Create Lead",
"protocol": "rest",
"status": "draft",
"category": "sales",
"current_draft_version": 3,
"latest_published_version": 2,
"updated_at": "2026-03-29T12:00:00Z",
"usage_summary": {
"calls_today": 4821,
"error_rate_pct": 1.8,
"avg_latency_ms": 187
},
"agent_refs": [
{
"agent_id": "agent_01hr9g3kgznn57d8s1q0h0g7qn",
"agent_slug": "sales-assistant",
"display_name": "Sales Assistant"
}
]
}
```
### 3.2. `OperationDetail`
Используется на detail page и как источник для edit-mode wizard.
```json
{
"id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"name": "crm_create_lead",
"display_name": "Create Lead",
"protocol": "rest",
"status": "draft",
"category": "sales",
"current_draft_version": 3,
"latest_published_version": 2,
"published_at": "2026-03-28T18:10:00Z",
"draft_version_ref": {
"version": 3,
"status": "draft"
},
"published_version_ref": {
"version": 2,
"status": "published"
},
"agent_refs": [
{
"agent_id": "agent_01hr9g3kgznn57d8s1q0h0g7qn",
"agent_slug": "sales-assistant",
"display_name": "Sales Assistant"
}
],
"created_at": "2026-03-27T09:15:00Z",
"updated_at": "2026-03-29T12:00:00Z"
}
```
### 3.3. `OperationVersionDocument`
Полная конфигурация версии. Используется wizard и detail page.
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"version": 3,
"status": "draft",
"target": {},
"input_schema": {},
"output_schema": {},
"input_mapping": {},
"output_mapping": {},
"execution_config": {},
"tool_description": {},
"samples": {
"input_json": {},
"output_json": {}
},
"generated_draft": {
"input_schema": {},
"output_schema": {},
"input_mapping": {},
"output_mapping": {}
},
"config_export": {
"format_version": "1",
"export_mode": "portable"
},
"change_note": "update request mapping",
"created_at": "2026-03-29T12:00:00Z",
"updated_at": "2026-03-29T12:45:00Z"
}
```
### 3.4. `OperationMutationResult`
Используется как ответ на create, patch, explicit version, archive и delete.
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"version": 3,
"status": "draft",
"updated_at": "2026-03-29T12:45:00Z"
}
```
## 4. Catalog endpoints
### `GET /api/admin/workspaces/{workspace_id}/operations`
Назначение:
- отдать каталог операций для списка.
Query params:
- `protocol`
- `status`
- `search`
- `category`
- `agent_id`
- `page`
- `page_size`
Ответ:
```json
{
"items": [
{
"id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"name": "crm_create_lead",
"display_name": "Create Lead",
"protocol": "rest",
"status": "draft",
"category": "sales",
"target_url": "https://api.example.com/v1/leads",
"target_action": "POST",
"current_draft_version": 3,
"latest_published_version": 2,
"updated_at": "2026-03-29T12:00:00Z",
"usage_summary": {
"calls_today": 4821,
"error_rate_pct": 1.8,
"avg_latency_ms": 187
},
"agent_refs": []
}
],
"page": 1,
"page_size": 20,
"total": 48
}
```
### `GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}`
Назначение:
- отдать `OperationDetail`.
### `GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}/versions/{version}`
Назначение:
- отдать `OperationVersionDocument`.
## 5. Create and update contracts
### `POST /api/admin/workspaces/{workspace_id}/operations`
Назначение:
- создать operation и draft version `1`.
Тело:
```json
{
"name": "crm_create_lead",
"display_name": "Create Lead",
"protocol": "rest",
"category": "sales",
"target": {},
"input_schema": {},
"output_schema": {},
"input_mapping": {},
"output_mapping": {},
"execution_config": {},
"tool_description": {}
}
```
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"version": 1,
"status": "draft",
"updated_at": "2026-03-29T12:00:00Z"
}
```
### `PATCH /api/admin/workspaces/{workspace_id}/operations/{operation_id}`
Назначение:
- обновить identity metadata;
- обновить текущий draft document без создания новой версии вручную со стороны UI.
Это endpoint для обычного wizard edit-mode.
Тело:
```json
{
"display_name": "Create Lead",
"category": "sales",
"draft_document": {
"target": {},
"input_schema": {},
"output_schema": {},
"input_mapping": {},
"output_mapping": {},
"execution_config": {},
"tool_description": {}
}
}
```
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"version": 3,
"status": "draft",
"updated_at": "2026-03-29T12:45:00Z"
}
```
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/versions`
Назначение:
- создать новую explicit draft-version snapshot.
Этот endpoint нужен для сценариев:
- `Save as new version`;
- controlled version history;
- YAML import с `mode=upsert`.
Тело:
```json
{
"source_version": 3,
"change_note": "prepare release candidate",
"document": {
"target": {},
"input_schema": {},
"output_schema": {},
"input_mapping": {},
"output_mapping": {},
"execution_config": {},
"tool_description": {}
}
}
```
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"version": 4,
"status": "draft",
"updated_at": "2026-03-29T13:05:00Z"
}
```
## 6. Lifecycle endpoints
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/publish`
Назначение:
- опубликовать конкретную версию операции.
Тело:
```json
{
"version": 3
}
```
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"version": 3,
"status": "published",
"updated_at": "2026-03-29T13:10:00Z"
}
```
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/archive`
Назначение:
- перевести operation в archived lifecycle state без hard delete.
Тело:
```json
{
"reason": "deprecated by crm_create_lead_v2"
}
```
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"version": 3,
"status": "archived",
"updated_at": "2026-03-29T13:15:00Z"
}
```
### `DELETE /api/admin/workspaces/{workspace_id}/operations/{operation_id}`
Назначение:
- hard delete для еще не опубликованной operation.
Правила:
- hard delete допустим только для draft/unpublished operation;
- если operation уже публиковалась, UI должен использовать archive;
- если operation используется published agent-ами, endpoint возвращает `409 Conflict`.
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"deleted": true
}
```
## 7. Wizard-specific endpoints
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/test-runs`
Тело:
```json
{
"version": 3,
"input": {}
}
```
Ответ:
```json
{
"status": "ok",
"request_preview": {},
"response_preview": {},
"output": {},
"runtime_labels": {
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np"
}
}
```
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/input-json`
Тело:
```json
{
"version": 3,
"sample": {}
}
```
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"version": 3,
"stored": true
}
```
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/output-json`
Тело:
```json
{
"version": 3,
"sample": {}
}
```
Ответ:
```json
{
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"version": 3,
"stored": true
}
```
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/drafts/generate`
Назначение:
- сгенерировать черновую схему и draft mappings по samples/descriptors.
Тело:
```json
{
"version": 3
}
```
Ответ должен возвращать полный draft payload, пригодный для прямой подстановки в wizard:
```json
{
"generated_draft": {
"input_schema": {},
"output_schema": {},
"input_mapping": {},
"output_mapping": {}
},
"input_schema": {},
"output_schema": {},
"input_mapping": {},
"output_mapping": {}
}
```
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/descriptors/proto`
Тело:
```json
{
"version": 3,
"file_name": "crm.proto",
"content_b64": "..."
}
```
Ответ:
```json
{
"descriptor_ref": "desc_01hr9n0m2yzdb8f8xv1gvztm2b",
"stored": true
}
```
### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/descriptors/descriptor-set`
Тело:
```json
{
"version": 3,
"file_name": "crm-descriptor-set.bin",
"content_b64": "..."
}
```
Ответ:
```json
{
"descriptor_ref": "desc_01hr9n0m2yzdb8f8xv1gvztm2b",
"stored": true
}
```
### `GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}/grpc/services?version=3`
Ответ:
```json
{
"services": [
{
"package": "crm.v1",
"service": "LeadService",
"methods": [
{
"name": "CreateLead",
"kind": "unary",
"input_schema": {},
"output_schema": {}
}
]
}
]
}
```
## 8. YAML contracts
### `GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}/export`
Query:
- `mode=portable|bundle`
- `version=<optional>`
Ответ:
- `application/yaml`
### `POST /api/admin/workspaces/{workspace_id}/operations/import`
Query:
- `mode=create|upsert`
Body:
- raw YAML document
Ответ:
```json
{
"workspace_id": "ws_01hr9dzv4s5ec1f1v3y8t1n7gr",
"operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
"version": 4,
"status": "draft",
"result": "upserted"
}
```
## 9. Wizard lifecycle semantics
### Текущее редактирование
Wizard всегда открывается на current draft version и использует:
- `GET /operations/{operation_id}`
- `GET /operations/{operation_id}/versions/{current_draft_version}`
- `PATCH /operations/{operation_id}`
Это основной сценарий редактирования.
### Явное создание новой версии
Если UI вводит действие `Save as new version`, оно должно использовать:
- `POST /operations/{operation_id}/versions`
Это уже отдельный snapshot, а не обычное сохранение формы.
### Публикация
Публикуется конкретная version, а не “текущее состояние формы”.
Поэтому UI всегда должен передавать:
- `version`
в `POST /publish`.
## 10. Конфликты, которые закрывает этот документ
### Конфликт 1. `PATCH` против explicit version snapshots
Решение:
- wizard использует `PATCH` для текущего draft;
- controlled snapshots остаются на `POST /versions`.
### Конфликт 2. Delete semantics
Решение:
- hard delete только для unpublished drafts;
- для опубликованных операций использовать archive.
### Конфликт 3. Category source of truth
Решение:
- `category` признается частью operation identity metadata и хранится на стороне backend.
### Конфликт 4. Catalog data merge
Решение:
- каталог должен возвращать все нужные поля для UI с сервера;
- локальные overlays и tombstones в целевой реализации не используются.
## 11. Следующий шаг
После этого документа следующая реализация должна идти в таком порядке:
1. обновить `admin-api` handlers и service contracts под workspace prefix;
2. добавить `category`, `workspace_id` и update/delete/archive lifecycle в storage model;
3. перевести wizard на create/patch/version semantics из этого документа;
4. только после этого подключать `Operations` и `Wizard` к реальному UI.