# Архитектура проекта

Цель: предсказуемое развитие `kodex` как платформы управления агентами, задачами, runtime и delivery-процессами в Kubernetes.

База: DDD (bounded contexts) + Clean Architecture (зависимости “снаружи внутрь”) + явный инвентарь деплоя + единый каркас директорий.

Устаревшие и архивные каталоги не считаются активной структурой проекта. Новая реализация создаётся в целевой структуре, а не восстанавливается переносом старого кода.

## Архитектурные ограничения kodex

- Оркестратор: только Kubernetes.
- Интеграция с Kubernetes: Go SDK (`client-go`) через интерфейсы и адаптеры.
- Интеграция с репозиториями: интерфейсы провайдеров (`github` сейчас, `gitlab` позже).
- Процессы: webhook-driven (GitHub webhooks/внутренние события), без workflow-first модели.
- Хранилище и синхронизация multi-pod: PostgreSQL (`JSONB` + `pgvector`).
- MCP служебные ручки: реализуются в Go внутри `kodex`.
- Платформа развёрнута в live-кластере, поэтому активные изменения проектируются как live-safe evolution:
  миграции, конфиги, секреты, транспортные контракты и deploy tooling должны обновляться
  последовательными шагами, а не через переписывание истории или одноразовый reset состояния.

## Структура репозитория

Целевой верхний уровень:
- `services.yaml` или его новая согласованная замена — корневой stack inventory платформы для версий, образов, deploy inventory и install/render tooling.
- `services/` — сервисы по зонам (`internal|external|staff|jobs|dev`), создаются заново.
- `libs/` — переиспользуемый код (`go|ts|vue`), создаётся только при наличии реального переиспользования.
- `proto/` — gRPC контракты, создаётся заново при появлении внутренних gRPC API.
- `deploy/` — Kubernetes манифесты и overlays, создаются заново.
  - Манифесты и шаблоны YAML (`*.yaml.tpl`) живут в `deploy/base/**`.
  - Сложные shell-скрипты не встраиваются в YAML-шаблоны. Скрипт хранится отдельным файлом рядом
    с манифестом, а Kubernetes `ConfigMap` для него создаётся deploy-рендерером или
    `kustomize`-слоем из этого файла.
  - Рендер и применение выполняются Go-компонентами новой архитектуры; shell-скрипты
    не являются основным механизмом deploy/sync.
- Для production порядок выкладки задаётся по слоям:
  `stateful dependencies -> migrations -> internal domain services -> edge services -> frontend`.
  Ожидание зависимостей оформляется через `initContainers` в манифестах сервисов.
- Любое изменение deploy path должно сохранять возможность последовательного обновления существующего
  live-кластера. Если изменение требует нового обязательного секрета, runtime env или миграции,
  порядок применения фиксируется в inventory/runbook и не должен ломать старт старой версии до
  применения следующего шага.
- Для monorepo multi-service deploy используются раздельные образы/репозитории для каждого
  deployable-сервиса (шаблон нейминга: `KODEX_<SERVICE>_IMAGE`,
  `KODEX_<SERVICE>_INTERNAL_IMAGE_REPOSITORY`).
- `bootstrap/` — скрипты bootstrap (готовый кластер или установка k3s).
- `docs/` — документация и решения.
- `tools/` — утилиты и генерация, создаются заново при необходимости.

### Изменение состава deployable-сервисов (обязательно синхронно)

Если в монорепо добавляется/удаляется deployable-сервис, либо меняются его docker context / Dockerfile / image repository:
- обновлять сборку/зеркалирование образов в runtime/deploy контуре новой архитектуры;
- обновлять production deploy env/vars, манифесты и инвентарь сервисов;
- обновлять bootstrap-синхронизацию GitHub vars/secrets и секретов Kubernetes:
  `bootstrap/host/config.env.example`,
  `bootstrap/host/bootstrap_cluster.sh` или новые согласованные bootstrap-компоненты;
- обновлять манифесты выкладки сервиса в `deploy/base/<service>/*.yaml.tpl`
  и Dockerfile сервиса в `services/<zone>/<service>/Dockerfile`.
- если меняется набор инструментов для agent-runner (dogfooding), обновлять
  целевой runtime/toolchain bootstrap и документировать изменения в новой delivery/ops документации.

### Изменение состава PostgreSQL-БД и миграций

Если добавляется, переименовывается или удаляется БД платформенного сервиса:
- обновлять `services.yaml`: владелец БД, путь миграций, манифесты выкладки и порядок зависимостей;
- обновлять `deploy/base/postgres/secrets.yaml.tpl`, если меняются runtime DSN или секреты подключения;
- обновлять `deploy/base/postgres/bootstrap-databases.sh`, если меняется набор создаваемых БД;
- обновлять `deploy/base/postgres/postgres.yaml.tpl`, если меняется Job подготовки БД или его env;
- обновлять `deploy/base/<db-owner>/migrations.yaml.tpl`, если у владельца схемы есть отдельное
  Kubernetes-задание миграций;
- обновлять `bootstrap/host/config.env.example` и `bootstrap/host/bootstrap_cluster.sh`,
  чтобы env, DSN и image-переменные попали в runtime-секрет синхронно с кодом;
- обновлять delivery/architecture документы, где описаны владелец БД, миграции и порядок выкладки.

Уже применённые миграции не редактируются и не переупорядочиваются. Изменения существующей схемы
делаются новой forward-only additive migration. Destructive/drop/rename допускаются только через
отдельный путь `expand -> migrate -> contract`, где старая и новая схема временно сосуществуют,
потребители переведены на новую форму, и только затем удаляется старое. Live drift исправляется
новой миграцией или явно описанным runbook/deploy шагом, а не ручным SQL в production.

### Источники defaults

- Корневой `services.yaml` является источником версий, образов, deploy inventory и стандартных имён артефактов платформенного стека.
- Корневой `services.yaml` отличается от проектного `services.yaml` пользовательского репозитория: проектная политика, импорт и проверенная проекция принадлежат `project-catalog`.
- Go tooling, которому нужны версии или образы платформенного стека, читает root stack inventory через `libs/go/stackinventory`; собственные YAML parsers и shell/awk разборы допустимы только как временный узкий fallback для legacy wrappers.
- Go config deployable-сервиса является источником безопасных runtime defaults самого сервиса.
- Kubernetes templates задают обязательные env, секреты, связи с другими сервисами, параметры окружения и явные overrides; они не должны повторять runtime defaults сервиса как `envOr`, если default уже задан в Go config.
- `bootstrap/host/config.env.example` остаётся минимальным локальным install-профилем: домен, namespace, локальные настройки установки и secret/bootstrap seed-поля.

Целевое ядро сервисов определяется актуальной архитектурной документацией проекта.
Устаревшие сервисы не являются базой новой реализации.

### Dockerfile deployable-сервиса

Каждый deployable-сервис, независимо от стека, обязан иметь воспроизводимый Dockerfile
с одинаковой логикой окружений:
- базовые образы берутся из зеркалированного инфраструктурного реестра, а не напрямую из публичных реестров;
- обязательные стадии: `build`, `dev`, `prod`; дополнительная стадия `deps` допустима, если она уменьшает дублирование установки зависимостей;
- стадия `build` получает все входы, нужные для сборки и генерации: код сервиса, профильные `libs/**`,
  `proto/**`, `specs/openapi/**`, `specs/asyncapi/**` и lock-файлы пакетного менеджера, если они используются сервисом;
- стадия `dev` запускает сервис в режиме разработки с hot reload, использует исходники из рабочего каталога
  и сохраняет кэши сборки/пакетного менеджера в местах, пригодных для dev-слотов;
- стадия `prod` запускает только готовый артефакт, не зависит от исходников, инструментов разработки и hot reload;
- Dockerfile не фиксирует `EXPOSE` для портов приложения. Порты объявляются в Kubernetes-манифестах
  и runtime-конфигурации сервиса, чтобы Dockerfile не расходился с фактическим контуром запуска;
- Kubernetes-манифесты dev/prod окружений выбирают нужную Dockerfile-стадию явно, а не полагаются на порядок стадий.

Профильные гайды уточняют только стековую специфику:
- Go backend использует свой hot reload инструмент, кэш компиляции и сборку бинарника;
- Vue/Vite frontend использует Vite dev server в `dev` и статический bundle в `prod`;
- если frontend генерирует или валидирует API-клиенты, в Dockerfile должны попадать соответствующие
  `libs/{ts,vue}/**`, `specs/openapi/**` и `specs/asyncapi/**`.

## Зоны сервисов: internal / external / staff / jobs / dev

### `services/internal/`
- Доменные правила платформы.
- Работа с БД, Kubernetes и repository providers через интерфейсы.
- Нет публичного ingress для бизнес-эндпоинтов.

### `services/external/`
- Публичные webhook/API точки входа.
- Валидация подписи, authn/authz, rate limiting, аудит.
- Без доменной логики orchestration внутри transport слоя.

### `services/staff/`
- Внутренняя консоль (Vue3).
- Доступ через платформенный SSO/OIDC-контур и внутреннюю матрицу прав проекта.
- Для каждого frontend-сервиса обязателен собственный Dockerfile по общим правилам выше,
  а также отдельный deploy manifest в `deploy/base/<service>/*.yaml.tpl`.

### `services/jobs/`
- Async/фоновые процессы: reconciliation, ретраи, cleanups, ротации, индексация.
- Идемпотентность и устойчивость обязательны.

### `services/dev/`
- Только dev-инструменты.
- Не деплоятся в production.

## Границы ответственности

Правила:
- Один сервис = один bounded context и одна причина для изменения.
- Домен не зависит от transport/DB SDK напрямую.
- Kubernetes/GitHub/GitLab детали изолированы в адаптерах.
- Shared DB без владельца контекста запрещён; таблицы и данные имеют явного владельца.

## Схема взаимодействия (высокоуровнево)

Конкретная схема взаимодействия определяется актуальной архитектурной документацией проекта.
Этот гайд фиксирует только общую слойность:
- `external/*` принимает внешние события, валидирует вход и маршрутизирует запросы;
- `internal/*` владеет доменной логикой и каноническим состоянием;
- `jobs/*` выполняет фоновые и долгие процессы идемпотентно;
- `staff/*` предоставляет операторский интерфейс и работает через API, а не напрямую с БД;
- интеграции с Kubernetes и repository providers идут через интерфейсы и адаптеры.
