quality / commitlint (push) Skipped
quality / changes (push) Successful in 20s
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 2m54s
quality / web (push) Successful in 1m22s
quality / go (push) Successful in 3m37s
quality / bird2 (push) Successful in 15s
CD / quality (push) Successful in 8m37s
CD / publish (push) Failing after 1m51s
- Added `@redocly/cli` version 1.34.5 to `package.json` and `pnpm-lock.yaml` for OpenAPI linting. - Updated CI workflows to reflect changes in job names and processes, including adjustments to the `publish` job in the CD workflow. - Enhanced documentation to clarify the new CI/CD processes and Docker build configurations.
245 lines
12 KiB
Plaintext
245 lines
12 KiB
Plaintext
---
|
||
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 ./...`. Агент после правок Go: `gofmt -w` на изменённых файлах + `golangci-lint run` (или `scripts/lint-go.*`) до exit 0.
|
||
*Rationale:* CI job `go` включает golangci-lint (gofmt).
|
||
*Проверка:* CI job `go`; `.cursor/rules/engineering.mdc` STYLE-01.
|
||
|
||
**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/quality.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/ui (React) + ReUI (см. `web-shadcn.mdc`).
|
||
*Проверка:* `apps/web/package.json`, `packages/ui/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 | Изменения `apps/web/**` или `packages/ui/**` — локально **`pnpm --filter @evobgp/web run typecheck`, `lint`, `build`** (все три команды, exit 0); CI job `web` в `.gitea/workflows/quality.yaml`.
|
||
*Проверка:* CI job `web`; `.cursor/rules/web-shadcn.mdc` WEB-19.
|
||
|
||
**TEST-05** | MUST | Изменения OpenAPI — `pnpm exec redocly 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-<role>/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.nic.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 | Сомнения по React/shadcn/ReUI — MCP `plugin-shadcn-shadcn` + `pnpm --filter @evobgp/web run typecheck`.
|
||
**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
|
||
pnpm exec redocly lint docs/openapi.yaml
|
||
# web: pnpm --filter @evobgp/web run typecheck; pnpm --filter @evobgp/web run lint; pnpm --filter @evobgp/web run build
|
||
# go fmt/lint: gofmt -w <files>; scripts/lint-go.ps1 (gofmt + vet + golangci-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.
|