116 lines
8.7 KiB
Markdown
116 lines
8.7 KiB
Markdown
# План работ: 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`
|
||
- Статус: pending
|
||
- Зависимости: `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`
|
||
- Статус: pending
|
||
- Зависимости: `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`
|
||
- Статус: pending
|
||
- Зависимости: `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`
|
||
- Статус: pending
|
||
- Зависимости: `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 читаются как явные, тестируемые правила; замечания сформулированы как точечные правки или подтверждение готовности
|