[feat] update readme.md

This commit is contained in:
Azamat 2026-04-03 09:49:14 +03:00
parent c5b6a84a4b
commit 3293bccc5b
5 changed files with 273 additions and 60 deletions

315
README.md
View file

@ -1,36 +1,268 @@
Это шаблон Python-сервиса на чистой архитектуре с заменяемым web-слоем, типизированным конфигом, явным dependency wiring и observability через порты.
# master-service
## Что это за проект
`master-service` — это control-plane сервис для sandbox-контейнеров с AI-агентом.
Он поднимает и переиспользует sandbox на чат, подключает рабочие volume, восстанавливает state после рестарта и отдает наружу минимальный HTTP API под `/api/v1`.
- Небольшой референсный сервис со слоями `domain/`, `usecase/`, `repository/` и `adapter/`
- Шаблон для сервисов на FastAPI, где FastAPI остается только во внешнем HTTP adapter
- Проект, где конфиг собирается из `config/app.yaml`, `.env` и env vars в одно дерево dataclass-конфигов
- Проект, где repository и usecase создаются один раз на старте приложения в composition root
- Проект, где логи, метрики и трейсы скрыты за интерфейсами и могут работать через `stdout`, файл или OpenTelemetry runtime
Важно: в локальном `config/app.yaml` исторически еще стоят template-имена `web-python-skelet`.
Если хочешь, чтобы `/health` и OTel service name локально тоже показывали `master-service`, переопредели:
- `APP_NAME=master-service`
- `APP_OTEL_SERVICE_NAME=master-service`
## Основные идеи
Сервис реализован на Python с Clean Architecture:
- `domain/` — сущности и доменные ошибки
- `usecase/` — сценарии приложения и порты
- `repository/` — реализации repository
- `adapter/` — HTTP, config, DI, Docker runtime и observability
- Clean Architecture и границы SOLID
- Направление зависимостей только внутрь
- Тонкие adapter-слои и явная сборка зависимостей
- Заменяемый HTTP-слой
- Observability без протекания OpenTelemetry во внутренние слои
## Что умеет сейчас
Текущий sandbox MVP покрывает:
- `GET /api/v1/health`
- `POST /api/v1/create` с `chat_id: UUID`
- одну активную sandbox на чат
- reuse активной sandbox до истечения TTL
- cleanup просроченных sandbox в фоне
- startup reconciliation по Docker labels после рестарта сервиса
- chat mount `rw`, dependencies mount `ro`, lambda-tools mount `ro`
- логи, метрики и трейсы через порты `Logger`, `Metrics`, `Tracer`
Пока вне scope:
- auth и access control
- p2p/WebSocket lease
- workspace/chat CRUD API
- central DB, artifacts, S3, quota и retention policy
## Как устроен проект
- FastAPI живет только во внешнем adapter слое
- Docker живет только во внешнем adapter слое
- конфиг собирается из `config/app.yaml`, `.env` и env vars в один dataclass tree
- repository и usecase создаются один раз на старте в `adapter/di/container.py`
- observability не протекает во внутренние слои через OpenTelemetry SDK
## Структура
- `domain/` — core model и domain errors
- `usecase/` — use cases и interfaces
- `repository/` — in-memory и другие repository implementations
- `adapter/config/` — typed config models и loader
- `adapter/docker/` — Docker sandbox runtime
- `adapter/observability/` — logger/metrics/tracer runtime factory
- `adapter/otel/` — OpenTelemetry adapters
- `adapter/di/` — composition root
- `adapter/http/fastapi/` — app, middleware, schemas, routers
- `adapter/sandbox/` — sandbox reconciliation logic
- `config/` — YAML config files
- `docs/` — ADR и проектные гайды
## Быстрый старт
### Требования
- Python 3.13
- `uv`
- локальный Docker daemon
- секреты `APP_API_TOKEN` и `APP_SIGNING_KEY`
### Установка
```bash
make install
```
### Локальный запуск
```bash
APP_API_TOKEN=local-api-token APP_SIGNING_KEY=local-signing-key make run
```
Приложение стартует на `http://0.0.0.0:8123` и публикует versioned API под `/api/v1`.
Это поднимет сам API, но для успешного `POST /api/v1/create` локально нужен еще рабочий sandbox runtime:
- Docker daemon должен быть доступен по `docker.base_url`
- образ `sandbox.image` должен существовать локально
- директории `sandbox.dependencies_host_path` и `sandbox.lambda_tools_host_path` должны существовать
В дефолтном `config/app.yaml` это значит:
```bash
mkdir -p var/sandbox/dependencies var/sandbox/lambda-tools
docker image inspect ai-agent:latest >/dev/null
```
Если у тебя нет готового `ai-agent:latest`, проще начать с Docker Compose smoke path ниже.
После старта сервис доступен на:
- `http://127.0.0.1:8123/api/v1/health`
Проверка health:
```bash
curl http://127.0.0.1:8123/api/v1/health
```
Создание или reuse sandbox:
```bash
curl -X POST http://127.0.0.1:8123/api/v1/create \
-H 'Content-Type: application/json' \
-d '{"chat_id":"11111111-1111-1111-1111-111111111111"}'
```
Пример ответа:
```json
{
"session_id": "3701cfe3-e05e-48af-8385-442dcd954ca2",
"chat_id": "11111111-1111-1111-1111-111111111111",
"container_id": "64d839c6007de9396ee08ad4af4a22a59a6410ec5f4892a9277a87eb49c3ff5d",
"status": "running",
"expires_at": "2026-04-02T21:11:38.292893Z"
}
```
## Запуск через Docker Compose
Для локального smoke-run есть `docker-compose.yml`.
Он поднимает:
- `app`
- `docker-engine` в режиме Docker-in-Docker
- `otel-collector`
При этом `app` получает compose-specific config из:
- `config/docker-compose.yml`
Запуск:
```bash
make compose-up
```
Проверка:
```bash
make compose-ps
make compose-logs
```
Остановка:
```bash
make compose-down
```
Важно:
- в `config/docker-compose.yml` сейчас для smoke-проверки стоит `sandbox.image: nginx:1.27-alpine`
- для реального agent runtime замени `sandbox.image` на образ своего sandbox/agent контейнера
- в compose auth env vars нужны для startup config, но текущий MVP API еще не проверяет request token
## Как конфигурировать
### Источники конфига
Конфиг собирается в таком порядке:
1. базовый YAML из `config/app.yaml`
2. значения из `.env`
3. process env vars поверх `.env`
То есть env vars имеют наивысший приоритет.
### Обязательные секреты
Нужны всегда:
- `APP_API_TOKEN`
- `APP_SIGNING_KEY`
Сейчас это startup config, а не активная request auth для `/api/v1/create` и `/api/v1/health`.
То есть в текущем MVP токен не нужно передавать в HTTP headers для вызова этих endpoint.
### Основные секции YAML
В `config/app.yaml` и `config/docker-compose.yml` есть секции:
- `app`
- `http`
- `logging`
- `metrics`
- `tracing`
- `otel`
- `docker`
- `sandbox`
- `security`
### Полезные env overrides
Чаще всего полезны:
#### Общие
- `APP_NAME`
- `APP_ENV`
- `APP_HTTP_HOST`
- `APP_HTTP_PORT`
#### Логирование и observability
- `APP_LOGGING_LEVEL`
- `APP_LOGGING_OUTPUT`
- `APP_LOGGING_FORMAT`
- `APP_LOGGING_FILE_PATH`
- `APP_METRICS_ENABLED`
- `APP_TRACING_ENABLED`
- `APP_OTEL_SERVICE_NAME`
- `APP_OTEL_LOGS_ENDPOINT`
- `APP_OTEL_METRICS_ENDPOINT`
- `APP_OTEL_TRACES_ENDPOINT`
#### Docker runtime
- `APP_DOCKER_BASE_URL`
#### Sandbox
- `APP_SANDBOX_IMAGE`
- `APP_SANDBOX_TTL_SECONDS`
- `APP_SANDBOX_CLEANUP_INTERVAL_SECONDS`
- `APP_SANDBOX_CHATS_ROOT`
- `APP_SANDBOX_DEPENDENCIES_HOST_PATH`
- `APP_SANDBOX_LAMBDA_TOOLS_HOST_PATH`
- `APP_SANDBOX_CHAT_MOUNT_PATH`
- `APP_SANDBOX_DEPENDENCIES_MOUNT_PATH`
- `APP_SANDBOX_LAMBDA_TOOLS_MOUNT_PATH`
#### Security
- `APP_API_TOKEN_HEADER`
- `APP_API_TOKEN`
- `APP_SIGNING_KEY`
### Что важно в sandbox config
- `docker.base_url` — адрес Docker daemon
- `sandbox.image` — образ sandbox контейнера
- `sandbox.ttl_seconds` — TTL sandbox
- `sandbox.cleanup_interval_seconds` — частота cleanup loop
- `sandbox.chats_root` — корень chat directories
- `sandbox.dependencies_host_path` — host path для dependency cache
- `sandbox.lambda_tools_host_path` — host path для read-only lambda-tools
- `sandbox.chat_mount_path` — путь внутри sandbox для chat volume
- `sandbox.dependencies_mount_path` — путь внутри sandbox для dependency cache
- `sandbox.lambda_tools_mount_path` — путь внутри sandbox для lambda-tools
## Основные команды
- `make install` — установить зависимости через `uv`
- `make run` — локальный запуск
- `make run-otel` — запуск с OTel endpoints из env
- `make test``pytest`
- `make lint``ruff`
- `make typecheck``mypy`
- `make pre-commit` — lint + typecheck + test
- `make compose-build` — собрать compose images
- `make compose-up` — поднять локальный stack
- `make compose-down` — остановить stack
- `make compose-logs` — смотреть логи
- `make compose-ps` — смотреть статус сервисов
## Документация
### Гайды
- [Правила проекта и ограничения для агента](AGENTS.md)
- [Кодстайл проекта для AI-агента](docs/CODESTYLE.md)
- [Кодстайл проекта](docs/CODESTYLE.md)
- [Чистая архитектура, SOLID, DIP, Protocol и repository](docs/CLEAN_ARCHITECTURE_RU.md)
- [Логи, метрики и трейсы в этом проекте](docs/OBSERVABILITY_RU.md)
- [Как чистая архитектура реализована здесь](docs/PROJECT_GUIDE_RU.md)
@ -43,43 +275,24 @@ APP_API_TOKEN=local-api-token APP_SIGNING_KEY=local-signing-key make run
- [003 Observability Via Interfaces](docs/003-observability-via-interfaces.md)
- [004 Versioned HTTP API](docs/004-versioned-http-api.md)
- [005 Early FastAPI OTel Instrumentation](docs/005-fastapi-otel-early-instrumentation.md)
- [006 MVP Docker Sandbox Orchestration](docs/006-mvp-docker-sandbox-orchestration.md)
- [007 Startup Sandbox Reconciliation](docs/007-startup-sandbox-reconciliation.md)
- [008 Sandbox Lifecycle Observability](docs/008-sandbox-lifecycle-observability.md)
## Структура проекта
## Для AI-агента
- `domain/` - core-сущности и доменные ошибки
- `usecase/` - прикладные сценарии и порты
- `repository/` - реализации repository
- `adapter/config/` - загрузка и модели типизированного конфига
- `adapter/observability/` - выбор runtime для logger, metrics и tracer
- `adapter/otel/` - OpenTelemetry adapters
- `adapter/di/` - composition root и singleton wiring
- `adapter/http/fastapi/` - HTTP-схемы, dependencies, middleware и routers
- `config/` - YAML-конфиг приложения и локального OTel collector
Если ты меняешь проект как AI-агент, сначала прочитай:
## Для ИИ
1. [AGENTS.md](AGENTS.md)
2. [docs/CODESTYLE.md](docs/CODESTYLE.md)
3. [docs/PROJECT_GUIDE_RU.md](docs/PROJECT_GUIDE_RU.md)
4. [docs/CLEAN_ARCHITECTURE_RU.md](docs/CLEAN_ARCHITECTURE_RU.md)
5. [docs/OBSERVABILITY_RU.md](docs/OBSERVABILITY_RU.md)
6. релевантные ADR в `docs/`
7. [tasks.md](tasks.md)
Если ты AI-агент и собираешься что-то менять в проекте, сначала прочитай документы в таком порядке:
1. [Правила проекта и ограничения агента](AGENTS.md) - обязательные правила работы в этом репозитории
2. [Кодстайл проекта для AI-агента](docs/CODESTYLE.md) - границы слоев, стиль кода и правила зависимостей
3. [Как чистая архитектура реализована здесь](docs/PROJECT_GUIDE_RU.md) - практическая карта проекта и типовые сценарии изменений
4. [Чистая архитектура, SOLID, DIP, Protocol и repository](docs/CLEAN_ARCHITECTURE_RU.md) - базовые архитектурные принципы и примеры
5. [Логи, метрики и трейсы в этом проекте](docs/OBSERVABILITY_RU.md) - читать перед любыми изменениями в observability, middleware и runtime wiring
6. [ADR в `docs/`](docs/001-composition-root-and-lifetimes.md) - читать релевантные решения перед изменением архитектуры или startup wiring
7. [План задач и история работ](tasks.md) - понять, что уже сделано, что отложено и какие ограничения были зафиксированы
Перед началом работы:
- Определи, в каком слое будет изменение: `domain/`, `usecase/`, `repository/` или `adapter/`
- Убедись, что зависимости идут только внутрь
- Не тащи FastAPI и OpenTelemetry во внутренние слои
- Сначала изучи существующий код в нужной директории, потом вноси изменения
- Если задача затрагивает архитектурное решение, сначала сверяйся с ADR и проектными правилами
## Запуск и команды
- Для локального запуска нужны `APP_API_TOKEN` и `APP_SIGNING_KEY`
- `make run` запускает приложение локально
- `make run-otel` запускает приложение с локальными OTel endpoints из env vars
- `make pre-commit` запускает `ruff`, `mypy` и `pytest`
- `make compose-up` поднимает приложение и локальный LGTM stack через Docker Compose
Главные правила:
- сначала определи слой изменения
- зависимости только внутрь
- не тащи FastAPI и OpenTelemetry во внутренние слои
- архитектурные решения сверяй с ADR