Files
Denozordec da301b1a94
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
feat(dependencies): add @redocly/cli and update CI workflows
- 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.
2026-08-18 17:48:41 +07:00

245 lines
12 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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.