docs: define operations workspace contracts
This commit is contained in:
@@ -31,6 +31,7 @@ Crank - платформа для публикации внешних API в в
|
|||||||
- `docs/architecture.md` - целевая архитектура системы.
|
- `docs/architecture.md` - целевая архитектура системы.
|
||||||
- `docs/as-is-to-be.md` - переход `as is -> to be`, page-by-page gap analysis и архитектурные конфликты.
|
- `docs/as-is-to-be.md` - переход `as is -> to be`, page-by-page gap analysis и архитектурные конфликты.
|
||||||
- `docs/backend-gap-plan.md` - конкретный backend-план: сущности, API, БД и порядок реализации.
|
- `docs/backend-gap-plan.md` - конкретный backend-план: сущности, API, БД и порядок реализации.
|
||||||
|
- `docs/operations-workspace-contracts.md` - точные `workspace-scoped` контракты для экранов `Operations` и `Wizard`.
|
||||||
- `docs/module-decomposition.md` - декомпозиция crates и модулей.
|
- `docs/module-decomposition.md` - декомпозиция crates и модулей.
|
||||||
- `docs/data-model.md` - целевая модель данных.
|
- `docs/data-model.md` - целевая модель данных.
|
||||||
- `docs/database-schema.md` - целевая схема БД.
|
- `docs/database-schema.md` - целевая схема БД.
|
||||||
|
|||||||
@@ -2,23 +2,22 @@
|
|||||||
|
|
||||||
## Current
|
## Current
|
||||||
|
|
||||||
### `feat/backend-gap-plan`
|
### `feat/operations-workspace-contracts`
|
||||||
|
|
||||||
Status: completed
|
Status: completed
|
||||||
|
|
||||||
DoD:
|
DoD:
|
||||||
|
|
||||||
- page-by-page backend gaps переведены в конкретный plan of work
|
- `workspace-scoped` контракты для `Operations` и `Wizard` зафиксированы
|
||||||
- определены новые сущности, таблицы, API-группы и MCP changes
|
- определены точные DTO и lifecycle semantics для operations
|
||||||
- зафиксирован порядок реализации по волнам
|
- `PATCH/DELETE/ARCHIVE` и wizard DTO shape документированы
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
- `feat/operations-workspace-contracts`
|
- `feat/workspace-foundation`
|
||||||
|
|
||||||
## Backlog
|
## Backlog
|
||||||
|
|
||||||
- `feat/operations-workspace-contracts`
|
|
||||||
- `feat/workspace-foundation`
|
- `feat/workspace-foundation`
|
||||||
- `feat/agent-publishing`
|
- `feat/agent-publishing`
|
||||||
- `feat/platform-access`
|
- `feat/platform-access`
|
||||||
|
|||||||
@@ -136,6 +136,10 @@
|
|||||||
- draft generation;
|
- draft generation;
|
||||||
- gRPC descriptor upload и discovery.
|
- gRPC descriptor upload и discovery.
|
||||||
|
|
||||||
|
Детальные DTO и response shapes для экранов `Operations` и `Wizard` зафиксированы отдельно в:
|
||||||
|
|
||||||
|
- `docs/operations-workspace-contracts.md`
|
||||||
|
|
||||||
### Agents
|
### Agents
|
||||||
|
|
||||||
Нужны:
|
Нужны:
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
- `workspace_id`
|
- `workspace_id`
|
||||||
- `name`
|
- `name`
|
||||||
- `display_name`
|
- `display_name`
|
||||||
|
- `category`
|
||||||
- `protocol`
|
- `protocol`
|
||||||
- `status`
|
- `status`
|
||||||
- `version`
|
- `version`
|
||||||
@@ -253,3 +254,7 @@
|
|||||||
## 6. Принцип совместимости
|
## 6. Принцип совместимости
|
||||||
|
|
||||||
Если UI требует сущность, которой нет в текущем backend, эта сущность должна быть сначала явно добавлена в эту модель данных, а уже потом в код и БД.
|
Если UI требует сущность, которой нет в текущем backend, эта сущность должна быть сначала явно добавлена в эту модель данных, а уже потом в код и БД.
|
||||||
|
|
||||||
|
Для `Operations` и `Wizard` дополнительный уровень контрактной детализации закреплен в:
|
||||||
|
|
||||||
|
- `docs/operations-workspace-contracts.md`
|
||||||
|
|||||||
@@ -0,0 +1,677 @@
|
|||||||
|
# Operations Workspace Contracts
|
||||||
|
|
||||||
|
## 1. Назначение документа
|
||||||
|
|
||||||
|
Этот документ задает точные `workspace-scoped` контракты для экранов:
|
||||||
|
|
||||||
|
- `Operations`
|
||||||
|
- `Wizard`
|
||||||
|
|
||||||
|
Документ нужен как промежуточный слой между:
|
||||||
|
|
||||||
|
- целевым UI в `test-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",
|
||||||
|
"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.
|
||||||
Reference in New Issue
Block a user