master/tasks.md
2026-04-02 13:41:41 +03:00

116 lines
8.8 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.

# План работ: master-service MVP sandbox
## Контекст
- Источники требований: `docs/master.md`, `meetings/meeting_1_document.md`, `README.md`, `docs/*`
- Базовый template уже готов: typed config, DI container, observability, FastAPI adapter и versioned API под `/api/v1`
- Текущая цель: минимальное управление Docker sandbox без auth
- MVP API: `POST /api/v1/create`
- Sandbox policy: TTL `300` секунд, одна активная sandbox на `chat_id`, повторный `create` переиспользует активную сессию
- Volume policy: chat volume `rw`, dependencies volume `ro`, lambda-tools volume `ro`
- Host paths вычисляются из typed config, а HTTP request передает только `chat_id`
- Cleanup выполняется периодическим in-process loop внутри master-service
## Вне текущего scope
- auth и access control
- p2p lease и WebSocket transport
- workspace/chat CRUD API
- chat files, artifacts, S3, quota и retention policy
- центральная БД и multi-node orchestration
## Правила выполнения
- Выполняем по одной задаче
- Коммиты не делаем
- Если по ходу нужна смена архитектуры, останавливаемся и согласуем решение
- `domain/` и `usecase/` не импортируют Docker, FastAPI, OpenTelemetry, env или YAML
- Inner layers работают только через минимальные domain сущности и usecase порты
## Очередь задач
### M01. ADR и минимальный sandbox scaffolding
- Исполнитель: `primary-agent`
- Статус: completed
- Зависимости: нет
- Commit required: no
- Scope: зафиксировать MVP-решение в ADR и создать минимальные сущности, ошибки и usecase-контракты для sandbox orchestration
- Файлы: `docs/006-mvp-docker-sandbox-orchestration.md`, `domain/sandbox.py`, `domain/error.py`, `usecase/interface.py`, `usecase/sandbox.py`
- Критерии приемки: в `domain/` есть минимальная `SandboxSession` и sandbox-ошибки; в `usecase/` есть порты `SandboxSessionRepository`, `SandboxRuntime` и `Clock`; созданы скелеты `CreateSandbox` и `CleanupExpiredSandboxes`; ADR занимает 10-20 строк
### M02. Typed config для sandbox runtime
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `M01`
- Commit required: no
- Scope: расширить typed-config слоем `sandbox` с настройками image, TTL, cleanup interval, host paths и container mount paths
- Файлы: `adapter/config/model.py`, `adapter/config/loader.py`, `config/app.yaml`
- Решение: chat host path строится как путь под общим `sandbox.chats_root/<chat_id>`; request не передает host path напрямую
- Критерии приемки: конфиг собирается в typed dataclass-дерево; дефолтный TTL равен `300`; есть отдельные настройки для `chats_root`, `dependencies_host_path`, `lambda_tools_host_path`, `chat_mount_path`, `dependencies_mount_path`, `lambda_tools_mount_path`, `cleanup_interval_seconds`; inner layers не читают env
### M03. Docker runtime adapter для sandbox lifecycle
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `M01`, `M02`
- Commit required: no
- Scope: реализовать outer adapter над Docker для создания и остановки sandbox контейнера с нужными labels и mount policy
- Файлы: `adapter/docker/runtime.py`, `adapter/docker/__init__.py`
- Ограничения: все Docker-детали остаются в `adapter/`; runtime не должен протекать во внутренние слои
- Критерии приемки: runtime умеет создать sandbox container по входным параметрам usecase; chat volume монтируется как `rw`; dependency и lambda-tools volumes монтируются как `ro`; контейнер получает labels с `session_id`, `chat_id` и `expires_at`; runtime переводит ошибки Docker в понятные исключения адаптера
### M04. In-memory session repository и usecase `CreateSandbox`
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `M01`, `M02`, `M03`
- Commit required: no
- Scope: реализовать in-memory registry активных sandbox-сессий и usecase создания sandbox с логикой reuse по `chat_id`
- Файлы: `repository/sandbox_session.py`, `usecase/sandbox.py`, `adapter/di/container.py`
- Решение: если по `chat_id` есть неистекшая сессия, usecase возвращает ее без нового container start; если сессия истекла, usecase инициирует stop старой sandbox и создает новую
- Критерии приемки: одна активная sandbox на `chat_id`; TTL-логика использует порт `Clock`; usecase не импортирует Docker; container wiring остается singleton-based
### M05. Cleanup expired sandboxes и lifecycle wiring
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `M04`
- Commit required: no
- Scope: реализовать usecase cleanup просроченных sandbox и подключить периодический cleanup loop в FastAPI lifecycle
- Файлы: `usecase/sandbox.py`, `adapter/di/container.py`, `adapter/http/fastapi/app.py`, при необходимости `adapter/http/fastapi/dependencies.py`
- Ограничения: не ломать ADR про раннее OTel instrumentation; lifecycle loop должен стартовать и останавливаться один раз
- Критерии приемки: cleanup находит истекшие сессии, останавливает sandbox через runtime и удаляет их из registry; интервал cleanup берется из конфига; shutdown корректно завершает фоновую задачу
### M06. HTTP endpoint `POST /api/v1/create`
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `M04`
- Commit required: no
- Scope: добавить минимальную HTTP ручку для создания или переиспользования sandbox без auth
- Файлы: `adapter/http/fastapi/schemas.py`, `adapter/http/fastapi/dependencies.py`, `adapter/http/fastapi/routers/v1/router.py`, при необходимости `adapter/di/container.py`
- Request: `{ "chat_id": "..." }`
- Response: `session_id`, `chat_id`, `container_id`, `status`, `expires_at`
- Критерии приемки: router остается тонким; handler только переводит HTTP input в команду usecase и маппит ошибки в HTTP; endpoint живет под `/api/v1/create`; auth не добавляется
### M07. Тесты для create, reuse, TTL и mount policy
- Субагент: `test-engineer`
- Статус: pending
- Зависимости: `M03`, `M04`, `M05`, `M06`
- Commit required: no
- Scope: покрыть тестами ключевое поведение MVP без запуска реального production Docker stack
- Файлы: `test/*`
- Критерии приемки: есть unit-тесты для `CreateSandbox` и `CleanupExpiredSandboxes` с fake clock; есть HTTP smoke-тест для `POST /api/v1/create`; есть adapter-level тест с mock Docker client на mount policy `chat=rw`, `deps=ro`, `tools=ro`; тесты не тащат FastAPI или Docker в inner-layer тесты
### M08. Архитектурный и boundary review по MVP sandbox
- Субагент: `code-reviewer`
- Статус: pending
- Зависимости: `M07`
- Commit required: no
- Scope: проверить соблюдение clean architecture, dependency direction и соответствие MVP-ограничениям
- Файлы: весь измененный код
- Критерии приемки: Docker остается только во внешнем adapter; FastAPI не протекает в `domain/` и `usecase/`; TTL и mount policy читаются как явные, тестируемые правила; замечания сформулированы как точечные правки или подтверждение готовности