# Streaming Admin API ## 1. Назначение документа Этот документ фиксирует точные HTTP-контракты для потоковой модели Crank. Он дополняет: - [admin-api.md](/home/a.tolmachev/code/rust/mcpaas/docs/admin-api.md) - [streaming-mcp-plan.md](/home/a.tolmachev/code/rust/mcpaas/docs/streaming-mcp-plan.md) - [streaming-ui-contract.md](/home/a.tolmachev/code/rust/mcpaas/docs/streaming-ui-contract.md) - [streaming-runtime-design.md](/home/a.tolmachev/code/rust/mcpaas/docs/streaming-runtime-design.md) Цель документа: - зафиксировать DTO; - зафиксировать route groups; - зафиксировать валидацию; - зафиксировать expected error model; - зафиксировать page-to-endpoint contract для streaming configuration и test-runs. ## 2. Общие принципы - все ресурсы являются `workspace-scoped`; - streaming configuration является частью `operation version`; - `session` и `async_job` state не редактируются напрямую из UI; - test-runs могут создавать временные sessions и jobs, но не публикуют их как runtime resources; - transport errors и validation errors разделяются; - лимиты и safety-параметры валидируются на сервере, а не только в UI. Базовый префикс: ```text /api/admin/workspaces/{workspace_id} ``` ## 3. Основные ресурсы - `streaming-presets` - `streaming-validation` - `stream-test-runs` - `stream-sessions` - `async-jobs` - `protocol-capabilities` ## 4. Общие DTO ### 4.1. `ExecutionMode` ```json { "mode": "unary" } ``` Допустимые значения: - `unary` - `window` - `session` - `async_job` ### 4.2. `StreamingConfig` ```json { "mode": "window", "transport_behavior": "server_stream", "window_duration_ms": 5000, "poll_interval_ms": 2000, "upstream_timeout_ms": 10000, "idle_timeout_ms": 30000, "max_session_lifetime_ms": 300000, "max_items": 200, "max_bytes": 131072, "aggregation_mode": "summary_plus_samples", "summary_path": "$.summary", "items_path": "$.items", "cursor_path": "$.cursor", "status_path": "$.status", "done_path": "$.done", "redacted_paths": [ "$.items[*].token", "$.summary.secret" ], "truncate_item_fields": true, "max_field_length": 512, "drop_duplicates": true, "sampling_rate": 1.0, "tool_family": { "start_tool_name": "cluster_events_start", "poll_tool_name": "cluster_events_poll", "stop_tool_name": "cluster_events_stop", "status_tool_name": "deploy_status", "result_tool_name": "deploy_result", "cancel_tool_name": "deploy_cancel" } } ``` ### 4.3. `StreamingValidationError` ```json { "code": "streaming_validation_error", "message": "Streaming configuration is invalid", "details": [ { "field": "window_duration_ms", "reason": "must_be_positive" }, { "field": "max_items", "reason": "must_not_exceed_workspace_limit" } ] } ``` ### 4.4. `ProtocolCapability` ```json { "protocol": "grpc", "supports_execution_modes": [ "unary", "window", "session", "async_job" ], "supports_transport_behaviors": [ "request_response", "server_stream" ], "supports_auth_kinds": [ "none", "bearer", "basic", "api_key_header", "api_key_query" ], "supports_upload_artifacts": [ "proto", "descriptor_set" ], "supports_cursor_path": true, "supports_done_path": true, "supports_aggregation_mode": [ "raw_items", "summary_only", "summary_plus_samples", "stats", "latest_state" ] } ``` ## 5. Capabilities endpoints ### `GET /api/admin/workspaces/{workspace_id}/protocol-capabilities` Назначение: - отдать UI полную capability matrix; - убрать protocol-specific hardcode из frontend. Ответ: ```json { "items": [ { "protocol": "rest", "supports_execution_modes": ["unary", "window", "session", "async_job"], "supports_transport_behaviors": ["request_response", "server_stream"], "supports_auth_kinds": ["none", "bearer", "basic", "api_key_header", "api_key_query"], "supports_upload_artifacts": [], "supports_cursor_path": true, "supports_done_path": true, "supports_aggregation_mode": ["raw_items", "summary_only", "summary_plus_samples", "stats", "latest_state"] } ] } ``` ## 6. Streaming validation endpoints ### `POST /api/admin/workspaces/{workspace_id}/streaming/validate` Назначение: - проверить streaming config до сохранения operation; - вернуть protocol-aware ошибки. Тело: ```json { "protocol": "websocket", "target": {}, "execution_config": { "streaming": {} } } ``` Успех: ```json { "valid": true, "warnings": [ { "field": "max_bytes", "code": "may_truncate_large_event_payloads", "message": "Large event payloads may be truncated" } ] } ``` Ошибка: ```json { "valid": false, "errors": [ { "field": "transport_behavior", "code": "unsupported_transport_behavior" } ] } ``` ## 7. Streaming presets endpoints ### `GET /api/admin/workspaces/{workspace_id}/streaming-presets` Назначение: - отдать рекомендованные UI presets. Ответ: ```json { "items": [ { "preset_id": "logs_window_5s", "display_name": "Logs Window 5s", "protocols": ["rest", "grpc", "websocket"], "streaming": { "mode": "window", "window_duration_ms": 5000, "max_items": 100, "max_bytes": 65536, "aggregation_mode": "summary_plus_samples" } } ] } ``` ## 8. Streaming operation test-runs ### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/stream-test-runs` Назначение: - выполнить `window`, `session` или `async_job` test-run для draft version; - показать оператору runtime behavior до publish. Тело: ```json { "version": 4, "input": { "service": "billing", "level": "error" }, "test_mode": "window", "overrides": { "streaming": { "window_duration_ms": 3000, "max_items": 50 } } } ``` Успех для `window`: ```json { "run_id": "strun_01j0test", "mode": "window", "status": "completed", "window_complete": true, "truncated": false, "has_more": false, "summary": {}, "items": [], "cursor": null, "duration_ms": 2871 } ``` Успех для `session`: ```json { "run_id": "strun_01j0test", "mode": "session", "status": "running", "session": { "session_id": "sess_01j0stream", "expires_at": "2026-04-06T12:05:00Z", "poll_after_ms": 2000 }, "preview": { "summary": {}, "items": [] } } ``` Успех для `async_job`: ```json { "run_id": "strun_01j0test", "mode": "async_job", "status": "running", "job": { "job_id": "job_01j0deploy", "status": "running", "progress": { "pct": 12 } } } ``` ### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/stream-test-runs/{run_id}/poll` Назначение: - продолжить session-oriented test-run. Тело: ```json { "session_id": "sess_01j0stream" } ``` Ответ: ```json { "run_id": "strun_01j0test", "mode": "session", "status": "running", "window_complete": false, "truncated": false, "has_more": true, "summary": {}, "items": [], "cursor": "next_cursor" } ``` ### `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/stream-test-runs/{run_id}/stop` Назначение: - остановить test session. ### `GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}/stream-test-runs/{run_id}/result` Назначение: - получить финальный результат async-job test-run. ## 9. Runtime session resources ### `GET /api/admin/workspaces/{workspace_id}/stream-sessions` Назначение: - список активных и недавних session resources для observability/debug UI. Query params: - `operation_id` - `agent_id` - `status` - `page` - `page_size` Ответ: ```json { "items": [ { "id": "sess_01j0stream", "operation_id": "op_01j0", "agent_id": "agent_01j0", "mode": "session", "status": "running", "expires_at": "2026-04-06T12:05:00Z", "last_poll_at": "2026-04-06T12:00:10Z", "created_at": "2026-04-06T12:00:00Z" } ], "page": 1, "page_size": 20, "total": 1 } ``` ### `GET /api/admin/workspaces/{workspace_id}/stream-sessions/{session_id}` Назначение: - detail session metadata; - без возврата полного raw state. ### `POST /api/admin/workspaces/{workspace_id}/stream-sessions/{session_id}/stop` Назначение: - административно остановить runtime session. ### `DELETE /api/admin/workspaces/{workspace_id}/stream-sessions/{session_id}` Назначение: - hard cleanup завершенной session; - доступен только для `stopped`, `failed`, `expired`. ## 10. Async job resources ### `GET /api/admin/workspaces/{workspace_id}/async-jobs` Назначение: - список активных и недавних job resources. ### `GET /api/admin/workspaces/{workspace_id}/async-jobs/{job_id}` Назначение: - status/progress/result metadata. ### `POST /api/admin/workspaces/{workspace_id}/async-jobs/{job_id}/cancel` Назначение: - административная отмена long-running job. ### `GET /api/admin/workspaces/{workspace_id}/async-jobs/{job_id}/result` Назначение: - получить финальный нормализованный результат. ## 11. Integration into operation contracts `streaming` не является отдельным top-level resource для опубликованной операции. Он живет внутри: - `OperationVersionDocument.execution_config.streaming` и входит в: - `POST /operations` - `PATCH /operations/{operation_id}` - `POST /operations/{operation_id}/versions` - `GET /operations/{operation_id}/versions/{version}` ### 11.1. `OperationVersionDocument.execution_config.streaming` ```json { "execution_config": { "timeout_ms": 10000, "retries": 0, "auth_profile_ref": "auth_profile_01j0", "streaming": { "mode": "window", "transport_behavior": "server_stream", "window_duration_ms": 5000, "upstream_timeout_ms": 10000, "max_items": 100, "max_bytes": 65536, "aggregation_mode": "summary_plus_samples", "summary_path": "$.summary", "items_path": "$.items", "cursor_path": "$.cursor", "status_path": "$.status", "done_path": "$.done", "redacted_paths": [], "truncate_item_fields": true, "max_field_length": 512, "drop_duplicates": true, "sampling_rate": 1.0, "tool_family": {} } } } ``` ## 12. Validation rules ### 12.1. Общие - `mode=unary` запрещает `tool_family`; - `max_items` > 0; - `max_bytes` > 0; - `window_duration_ms` > 0 для `window`; - `idle_timeout_ms` обязателен для `session`; - `max_session_lifetime_ms` обязателен для `session`; - `tool_family.start_tool_name/poll_tool_name/stop_tool_name` обязательны для `session`; - `tool_family.start_tool_name/status_tool_name/result_tool_name/cancel_tool_name` обязательны для `async_job`. ### 12.2. Protocol-aware REST: - `transport_behavior=server_stream` допустим только при streaming-capable target. GraphQL: - `window`, `session`, `async_job` пока запрещены; - `subscription` невалиден как target type. gRPC: - `transport_behavior=server_stream` допустим только для server-streaming method. WebSocket: - `mode=unary` запрещен; - требуется `subscribe_message_template` для `session` и `window`. SOAP: - `mode=session` запрещен в первой волне; - `mode=window` допустим только при наличии polling-style status operation family; - `mode=async_job` требует status/result contract. ## 13. Error model Коды: - `streaming_validation_error` - `unsupported_execution_mode` - `unsupported_transport_behavior` - `stream_window_timeout` - `stream_window_truncated` - `stream_session_expired` - `stream_session_not_found` - `async_job_not_found` - `async_job_not_ready` - `async_job_cancelled` - `protocol_capability_mismatch` ### 13.1. Ошибка несовместимого protocol mode ```json { "code": "protocol_capability_mismatch", "message": "websocket target does not support unary execution mode", "details": [ { "field": "execution_config.streaming.mode", "reason": "unsupported_for_protocol" } ] } ``` ## 14. Route-to-service mapping Ожидаемые service handlers в `apps/admin-api`: - `list_protocol_capabilities` - `list_streaming_presets` - `validate_streaming_config` - `start_stream_test_run` - `poll_stream_test_run` - `stop_stream_test_run` - `get_stream_test_result` - `list_stream_sessions` - `get_stream_session` - `stop_stream_session` - `delete_stream_session` - `list_async_jobs` - `get_async_job` - `cancel_async_job` - `get_async_job_result` Это не route names, а service-level функции orchestration.