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

15 KiB
Raw Blame History

Operations Workspace Contracts

1. Назначение документа

Этот документ задает точные workspace-scoped контракты для экранов:

  • Operations
  • Wizard

Документ нужен как промежуточный слой между:

  • текущим Alpine UI в apps/ui;
  • docs/backend-gap-plan.md;
  • реализацией admin-api.

2. Общие правила

Базовый префикс:

/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

Используется в каталоге операций.

{
  "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.

{
  "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.

{
  "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.

{
  "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

Ответ:

{
  "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.

Тело:

{
  "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": {}
}

Ответ:

{
  "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.

Тело:

{
  "display_name": "Create Lead",
  "category": "sales",
  "draft_document": {
    "target": {},
    "input_schema": {},
    "output_schema": {},
    "input_mapping": {},
    "output_mapping": {},
    "execution_config": {},
    "tool_description": {}
  }
}

Ответ:

{
  "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.

Тело:

{
  "source_version": 3,
  "change_note": "prepare release candidate",
  "document": {
    "target": {},
    "input_schema": {},
    "output_schema": {},
    "input_mapping": {},
    "output_mapping": {},
    "execution_config": {},
    "tool_description": {}
  }
}

Ответ:

{
  "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

Назначение:

  • опубликовать конкретную версию операции.

Тело:

{
  "version": 3
}

Ответ:

{
  "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.

Тело:

{
  "reason": "deprecated by crm_create_lead_v2"
}

Ответ:

{
  "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.

Ответ:

{
  "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

Тело:

{
  "version": 3,
  "input": {}
}

Ответ:

{
  "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

Тело:

{
  "version": 3,
  "sample": {}
}

Ответ:

{
  "operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
  "version": 3,
  "stored": true
}

POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/output-json

Тело:

{
  "version": 3,
  "sample": {}
}

Ответ:

{
  "operation_id": "op_01hr9f7q4b0w1svxv5a6j8k2np",
  "version": 3,
  "stored": true
}

POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/drafts/generate

Назначение:

  • сгенерировать черновую схему и draft mappings по samples/descriptors.

Тело:

{
  "version": 3
}

Ответ должен возвращать полный draft payload, пригодный для прямой подстановки в wizard:

{
  "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

Тело:

{
  "version": 3,
  "file_name": "crm.proto",
  "content_b64": "..."
}

Ответ:

{
  "descriptor_ref": "desc_01hr9n0m2yzdb8f8xv1gvztm2b",
  "stored": true
}

POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/descriptors/descriptor-set

Тело:

{
  "version": 3,
  "file_name": "crm-descriptor-set.bin",
  "content_b64": "..."
}

Ответ:

{
  "descriptor_ref": "desc_01hr9n0m2yzdb8f8xv1gvztm2b",
  "stored": true
}

GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}/grpc/services?version=3

Ответ:

{
  "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

Ответ:

{
  "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.