--- description: Инженерные правила EvoBGP — Go, API, migrations, общие стандарты alwaysApply: true --- # Engineering Guidelines — EvoBGP Специализированные правила: **Web UI** → `.cursor/rules/web-shadcn.mdc`; **BIRD2 / BGP / IP** → `.cursor/rules/networking-bird.mdc`. Карта репозитория: `AGENTS.md`, `docs/architecture.md`. HTTP-контракт: `docs/openapi.yaml`. --- ## Architecture **ARCH-01** | MUST | Новая persistence-логика — метод `store.Backend` + реализации в `repository` и `store.Memory`; SQL не в `httpapi`. *Rationale:* единая абстракция данных. *Проверка:* CI `scripts/lint-httpapi.sh`; grep SQL в `internal/httpapi` — отсутствие. **ARCH-02** | MUST | HTTP-маршруты только в `internal/httpapi`; регистрация через `http.ServeMux` с паттернами `METHOD /v1/...`. *Rationale:* один слой REST. *Проверка:* маршруты только в `routes.go`, `routes_crud.go`. **ARCH-03** | MUST | Долгие операции (refresh, apply, rollback) — `jobs.Registry`; ответ `202` + `job_id` где задано OpenAPI. *Rationale:* не блокировать HTTP worker. *Проверка:* OpenAPI + handlers. **ARCH-04** | MUST | Кросс-процессные воркеры — HTTP к API или общая БД; не shared memory (кроме `evobgp-all`). *Rationale:* `jobs.Registry` in-process only. *Проверка:* `docs/architecture.md`; review. **ARCH-05** | MUST | `birdfmt` не импортирует `httpapi` / `store`. *Rationale:* направление зависимостей вниз. *Проверка:* `go list -deps` / review imports. **ARCH-06** | MUST | Точки входа `cmd/*` — тонкий `main`: config, wiring, signal/shutdown; без бизнес-логики. *Rationale:* тестируемость `internal/`. *Проверка:* review `main.go`. **ARCH-07** | MUST | Инициализация store + jobs для API и воркеров — `httpapi.BootstrapWorkers`. *Rationale:* единый wiring. *Проверка:* `bootstrap.go`. **ARCH-08** | MUST | Ingest+render префиксов — `internal/pipeline`; генерация BIRD-текста — `internal/birdfmt`. *Rationale:* разделение data plane / control plane. *Проверка:* review пакетов. **ARCH-09** | NEVER | Прямой доступ handler'ов к `pgxpool` для CRUD; только `store.Backend`. *Rationale:* абстракция бэкенда. *Проверка:* review `httpapi`. **ARCH-10** | MUST | Подпись бандлов — `internal/bundle` + `internal/signing`; не дублировать crypto в handlers. *Rationale:* единая криптография артефактов. *Проверка:* review. --- ## Code Style **STYLE-01** | MUST | Go-код после `gofmt`; перед PR — `go vet ./...`. *Rationale:* единый стиль. *Проверка:* CI job `go`. **STYLE-02** | MUST | Экспортируемые типы/функции публичных пакетов — godoc-комментарий. *Rationale:* навигация по API пакетов. *Проверка:* review. **STYLE-03** | NEVER | `panic` в `internal/*` вне `init` и тестов. *Rationale:* предсказуемые ошибки. *Проверка:* grep `panic(`. **STYLE-04** | MUST | Ошибки пакетов с префиксом (`birdfmt:`, `db:`, `httpapi:`) и `%w` при оборачивании. *Rationale:* трассировка. *Проверка:* review. **STYLE-05** | MUST | HTTP-ошибки — `writeProblem` / `writeJSON` (`application/problem+json` для 4xx/5xx). *Rationale:* RFC 9457, OpenAPI. *Проверка:* `problem.go`; CI `scripts/lint-httpapi.sh` (5xx и 4xx store/cdn/csv). **STYLE-06** | MUST | JSON полей HTTP DTO согласованы с `docs/openapi.yaml`. *Rationale:* контракт API. *Проверка:* OpenAPI diff + review. --- ## Dependency Management **DEP-01** | MUST | Go-зависимости — через `go get` / `go.mod`; версия Go как в `go.mod` и CI (1.24). *Проверка:* `go.mod`, `.gitea/workflows/ci.yaml`. **DEP-02** | NEVER | Vendor-копирование без явного решения в репозитории. *Проверка:* review. **DEP-03** | MUST | Миграции схемы — пары `.up.sql`/`.down.sql` для **postgres** и **sqlite**, синхронная нумерация. *Проверка:* `migrations/postgres/`, `migrations/sqlite/`. **DEP-04** | MUST | Web UI-библиотеки — только экосистема shadcn-svelte/bits-ui (см. `web-shadcn.mdc`). *Проверка:* `web/package.json` review. --- ## Error Handling **ERR-01** | MUST | HTTP 5xx — без сырого `err.Error()` клиенту; detail через `writeProblem`. *Проверка:* review handlers. **ERR-02** | MUST | Публичные функции I/O — `(T, error)`; `errors.Is`/`errors.As` для sentinel. *Проверка:* review. **ERR-03** | MUST | `context.Context` — первый аргумент для I/O; таймауты на внешние HTTP (CDN, DoH, RIPEstat). *Проверка:* `pipeline`, `bootstrap.go`. --- ## Testing **TEST-01** | MUST | Перед PR: `go test ./... -race -count=1`. *Проверка:* CI job `go`. **TEST-02** | MUST | Табличные тесты — эталон для `birdfmt`, `pipeline`, `bundle`. *Проверка:* `*_test.go`. **TEST-03** | MUST | Новые BIRD-сценарии в `internal/birdfmt/testdata/scenarios/*/bird.conf` + `bird -p`. *Проверка:* CI job `bird2`. **TEST-04** | MUST | Изменения `web/` — локально `npm run check` и `npm run lint`; CI job `web` в `.gitea/workflows/ci.yaml`. *Проверка:* локальные команды. **TEST-05** | MUST | Изменения OpenAPI — `npx @redocly/cli lint docs/openapi.yaml`. *Проверка:* CI job `openapi`. --- ## Documentation **DOC-01** | MUST | Пользовательская документация в `docs/` — на русском. *Проверка:* review. **DOC-02** | MUST | Изменение HTTP API: сначала `docs/openapi.yaml`, затем handlers/store, затем `docs/api.md` при необходимости. *Проверка:* PR diff order. **DOC-03** | MUST | Расхождение spec/код — явно в `docs/access.md` или description операции OpenAPI. *Проверка:* review (напр. `X-Tenant-Id`). **DOC-04** | NEVER | Дублировать длинные фрагменты OpenAPI в комментариях; ссылка на путь/operationId. *Проверка:* review. --- ## Naming Conventions **NAME-01** | MUST | Бинарники: `cmd/evobgp-/main.go`. *Проверка:* `cmd/`. **NAME-02** | MUST | Env-переменные: префикс `EVOBGP_`. *Проверка:* `internal/config`, `docs/access.md`. **NAME-03** | MUST | Job kinds — константы в `internal/jobs/worker.go` (`module_refresh`, …). *Проверка:* grep `Kind`. **NAME-04** | MUST | ID сущностей — UUID-строки; tenant только из API-ключа (auth context), не из недокументированных заголовков. *Проверка:* `auth.go`, `docs/access.md`. --- ## Performance **PERF-01** | MUST | Списки API — пагинация `cursor` + `limit`; не unbounded выборки в handlers. *Проверка:* OpenAPI + store methods. **PERF-02** | MUST | CDN HTTP — переиспользуемый `http.Client` с таймаутом (45s в bootstrap). *Проверка:* `bootstrap.go`. **PERF-03** | MUST | Новые метрики — `internal/observability`, экспорт `/metrics`. *Проверка:* review. --- ## Security **SEC-01** | NEVER | Секреты, API-ключи, токены в Git. *Проверка:* review; `docs/access.md`. **SEC-02** | NEVER | `EVOBGP_DEV_INSECURE=1` в production. *Проверка:* ops review. **SEC-03** | MUST | Роль `node` — только node API; CRUD — `403` для `node`. *Проверка:* `auth.go`, handlers. **SEC-04** | MUST | apply/rollback/settings — operator (или выше по `roleLevel`). *Проверка:* review handlers. **SEC-05** | MUST | Бандл на ноде — `verify-bundle` перед `apply-bundle`. *Проверка:* `docs/access.md`. **SEC-06** | MUST | CORS — явный whitelist `EVOBGP_CORS_ORIGINS`. *Проверка:* `cors.go`. --- ## Documentation Sync Rules | Область | Источник | |---------|----------| | Go / net/http | https://go.dev/doc/ | | pgx v5 | https://pkg.go.dev/github.com/jackc/pgx/v5 | | OpenAPI / problem+json | `docs/openapi.yaml`, RFC 9457 | | Svelte / Kit | https://svelte.dev/docs , https://kit.svelte.dev/docs | | shadcn-svelte | https://shadcn-svelte.com/docs | | BIRD 2 | https://bird.network.cz/?get_doc | | Prometheus Go | https://pkg.go.dev/github.com/prometheus/client_golang | **DOC-SYNC-01** | MUST | Новый API библиотеки — сверка версии в `go.mod`/`package.json` с официальной документацией. **DOC-SYNC-02** | NEVER | Устаревшие примеры (Svelte 4 `export let`, deprecated pgx). **DOC-SYNC-03** | MUST | Конфликт docs: **OpenAPI (HTTP)** → **код** → обзорные `docs/`; `.cursor/plans/` не контракт. **DOC-SYNC-04** | MUST | Сомнения по Svelte — Svelte MCP / `npm run check`. **DOC-SYNC-05** | MUST | BIRD — официальная документация BIRD2 + `networking-bird.mdc` + `go test ./internal/birdfmt/...`. Приоритет при сомнениях — **официальные источники**, не блоги и не «память модели». --- ## Enforcement Strategy **CI (Gitea):** OpenAPI lint; `go vet`, `go test -race`, build `cmd/*`; `bird -p` на scenarios; Docker bake на push. **Локально перед PR:** ```powershell go vet ./... go test ./... -race -count=1 npx @redocly/cli lint docs/openapi.yaml # web: cd web; npm run check; npm run lint # birdfmt: go test ./internal/birdfmt/... -count=1 ``` **CI (Gitea):** job `web` (check + lint); job `go`: `go vet`, `scripts/lint-httpapi.sh` (ARCH-01, ERR-01), `scripts/check-migrations-pair.sh` (DEP-03), `golangci-lint`, `go test -race`, build `cmd/*`. **Рекомендуется локально:** `.golangci.yml`; `.pre-commit-config.yaml` (gofmt + prettier web). **Только code review:** слои SQL; роли; idempotency; OpenAPI bodies; secrets в compose. **Известные ограничения:** `X-Tenant-Id` в OpenAPI не реализован в handlers; `jobs.Registry` не shared между процессами API и отдельными воркерами без HTTP.