Структура репозитория
Один репозиторий на все компоненты. Обоснование: контракт control plane связывает backend и агент — в монорепо изменение proto, сервера и агента происходит одним атомарным PR, версии контракта не расползаются по репозиториям.
astral/├── proto/│ └── astral/controlplane/v1/│ └── controlplane.proto # источник истины контракта (см. gRPC API)├── backend/│ ├── cmd/astral/ # main: serve | migrate | admin | recover | recovery-code | rewrap-keys | crypto reset│ ├── internal/│ │ ├── api/ # HTTP: admin, portal, public (sub, webhooks)│ │ ├── controlplane/ # gRPC-сервер, реестр стримов, рендер desired state│ │ │ └── render/xray/ # единственный пакет, знающий синтаксис Xray│ │ ├── domain/ # бизнес-логика по фичам (см. Структуру backend)│ │ ├── store/ # sqlc: запросы и репозитории│ │ ├── jobs/ # фоновые задачи (River)│ │ └── platform/ # crypto, acme, mailer, telemetry, config│ └── migrations/ # goose, go:embed├── agent/│ ├── cmd/astral-agent/│ └── internal/│ ├── link/ # соединение с backend: enrollment, стрим, reconnect│ ├── reconcile/ # diff NodeConfig ↔ Xray, применение│ ├── xray/ # процесс Xray: запуск, рестарт, API-клиент│ └── usage/ # сбор статистики, персистентный буфер отчётов├── web/│ └── src/│ ├── admin/ # /admin/* — роуты админки│ ├── portal/ # /portal/* — кабинет клиента│ └── shared/ # api-клиент (из OpenAPI), ui-kit, styles.css├── deploy/│ ├── compose/ # docker-compose панели│ └── ansible/ # роль astral-agent (см. Развёртывание)└── docs/ # этот сайт (Astro Starlight), включая decisions/ (ADR)Правила:
- Сгенерированный код (protoc, sqlc, openapi-typescript) коммитится: сборка любого компонента не требует кодогенераторов; дрейф ловится CI-проверкой «сгенерируй и сравни».
backendиagent— отдельные Go-модули с общим модулемproto. Агент не импортирует ничего изbackend/internal— граница контракта проходит строго по proto.- Версионирование релизов единое: тег репозитория задаёт версию backend, агента и web одновременно. Совместимость backend ↔ агент разных версий обеспечивается правилами эволюции proto (gRPC API), а не матрицей совместимости.