CI / changes (push) Successful in 11s
CI / openapi (push) Has been skipped
CI / go (push) Successful in 43s
CI / docker-web (push) Has been skipped
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Successful in 21s
CI / docker-go (push) Successful in 3m41s
- Added engineering rules references in AGENTS.md for code changes and specific areas (web, BIRD). - Enhanced README.md to include links to engineering rules for different development areas. - Updated birdfmt documentation to specify engineering rules for BIRD/BGP/IP. - Clarified UI development guidelines in web/README.md to follow shadcn-svelte documentation and repository rules.
220 lines
9.0 KiB
Plaintext
220 lines
9.0 KiB
Plaintext
---
|
|
description: EvoBGP — BIRD2, BGP policy, IP/CIDR, маршрутизация, валидация конфигов
|
|
globs:
|
|
- internal/birdfmt/**
|
|
- internal/birddeploy/**
|
|
- internal/pipeline/**
|
|
- deploy/bird/**
|
|
- "**/testdata/scenarios/**"
|
|
alwaysApply: false
|
|
---
|
|
|
|
# Networking & Routing Rules
|
|
|
|
Общие правила: `.cursor/rules/engineering.mdc`. Пакет BIRD: `internal/birdfmt/doc.go`.
|
|
|
|
## Single source of truth
|
|
|
|
| Домен | SSOT |
|
|
|-------|------|
|
|
| Префиксы для анонса | Модули tenant → materialized snapshot → ревизия (`store`, `pipeline`, `CreateRenderRevision`) |
|
|
| Текст BIRD-фрагментов | `internal/birdfmt` — только генератор `evobgp_*.conf` |
|
|
| Каркас `bird.conf` | Operator skeleton + `include` (`StandardIncludeFragments`) |
|
|
| Параметры BIRD tenant | Global settings: `bird_router_id`, `bird_local_asn`, … (`docs/manual.md`) |
|
|
| BGP peers | `BGPPeer` + `ParsePeerNeighbor` |
|
|
|
|
**BIRD2 docs:** https://bird.network.cz/?get_doc
|
|
|
|
---
|
|
|
|
## A. BIRD2 Configuration Rules
|
|
|
|
**BIRD-01** | MUST | Имена фрагментов — константы `Fragment*` (`evobgp_prefixes_v4.conf`, …); include `bird.d/<name>`.
|
|
*Rationale:* совместимость deploy.
|
|
*Проверка:* `layout.go`; `go test ./internal/birdfmt/...`
|
|
|
|
**BIRD-02** | MUST | Порядок include: filters v4/v6 → BGP template → prefixes v4/v6 → peers (`StandardIncludeFragments`).
|
|
*Rationale:* фильтры до ссылок.
|
|
*Проверка:* scenario `standard_layout`; `bird -p`
|
|
|
|
**BIRD-03** | MUST | `bird.conf` (router id, device, direct, includes) отдельно от `bird.d/evobgp_*` (политика, префиксы).
|
|
*Rationale:* атомарная подмена фрагментов.
|
|
*Проверка:* review layout.
|
|
|
|
**BIRD-04** | MUST | Новая логика фильтрации — функция в `birdfmt` + unit-тест; NEVER дублировать filter-блок в два `.conf` вручную.
|
|
*Rationale:* DRY v4/v6.
|
|
*Проверка:* `filter_test.go`; review.
|
|
|
|
**BIRD-05** | MUST | Filter: префикс `evobgp_`, суффикс `_v4`/`_v6`; templates `bgp_template` / `bgp_template_v6`.
|
|
*Проверка:* `bgp.go`, `layout.go`.
|
|
|
|
**BIRD-06** | MUST | `router id` — валидный IPv4 dotted-quad (`RenderMainBirdConf`).
|
|
*Проверка:* `birdfmt` error; `bird -p`
|
|
|
|
**BIRD-07** | MUST | Communities — `RouteCommunityAttrs`; синтаксис `((a,b))` в `add()`, не `add(65000,1)`.
|
|
*Проверка:* `community_bird_test.go`
|
|
|
|
**BIRD-08** | SHOULD | Комментарии `#` в preamble; в фрагментах — revision/module id где уместно.
|
|
*Проверка:* review.
|
|
|
|
**BIRD-09** | NEVER | Ручное редактирование `evobgp_*.conf` на ноде без ревизии/бандла в control plane.
|
|
*Rationale:* drift.
|
|
*Проверка:* `evobgp-deploy` logs.
|
|
|
|
**BIRD-10** | MUST | Новый scenario: `testdata/scenarios/<name>/bird.conf` (+ `bird.d/`) проходит `bird -p`.
|
|
*Проверка:* CI `bird2`
|
|
|
|
**BIRD-11** | MUST | Только BIRD **2.x**, не 1.6.
|
|
*Проверка:* `bird --version`
|
|
|
|
**BIRD-12** | MUST | Apply: staging → `bird -p` → atomic swap → `birdc configure`; NEVER configure без parse check.
|
|
*Проверка:* `birdctl.go`; `birddeploy` review.
|
|
|
|
---
|
|
|
|
## B. Routing Policy Rules
|
|
|
|
**RTE-01** | MUST | BGP template: `import none` на каждый AFI, если задача явно не добавляет import policy.
|
|
*Rationale:* deny-by-default.
|
|
*Проверка:* `bgp.go`
|
|
|
|
**RTE-02** | MUST | Export filter завершается `reject;`.
|
|
*Проверка:* `filter.go`; `filter_export` scenario.
|
|
|
|
**RTE-03** | MUST | Анонс только префиксов materialized revision; NEVER static `route` вне pipeline/birdfmt без operator approval.
|
|
*Проверка:* store snapshot; review.
|
|
|
|
**RTE-04** | NEVER | Анонс `0.0.0.0/0`, `::/0`, RFC1918/ULA, loopback, link-local, multicast, reserved без documented exception.
|
|
*Проверка:* ingest validation; review.
|
|
|
|
**RTE-05** | NEVER | Префиксы чужих ASN без авторизации (IRR/RPKI — ops review).
|
|
*Проверка:* ops review.
|
|
|
|
**RTE-06** | MUST | Отдельные export filters IPv4 и IPv6.
|
|
*Проверка:* `RenderExportFilterIPv4/IPv6`
|
|
|
|
**RTE-07** | SHOULD | AS_PATH match — ASN из tenant modules; дедуп `filterUniqueASNs`.
|
|
*Проверка:* unit tests.
|
|
|
|
**RTE-08** | MUST | Peer import/export overrides — расширение `birdfmt`, не ad-hoc в operator `bird.conf`.
|
|
*Проверка:* review.
|
|
|
|
**RTE-09** | SHOULD | hold 90s / keepalive 30s — менять только с обоснованием в settings/docs.
|
|
*Проверка:* review.
|
|
|
|
**RTE-10** | MUST | После apply — post-check `birdc`/метрики (`mergeBirdPostApplyMeta`, `EVOBGP_BIRDC_SOCKET`).
|
|
*Проверка:* jobs meta; observability poller.
|
|
|
|
---
|
|
|
|
## C. IP Addressing Rules
|
|
|
|
**IP-01** | MUST | CIDR в Go — `netip.Prefix`; строка — `Masked().String()`.
|
|
*Проверка:* `pipeline/parse.go`
|
|
|
|
**IP-02** | MUST | IPv4/IPv6 — отдельные fragments/filters.
|
|
*Проверка:* `layout.go`
|
|
|
|
**IP-03** | MUST | BGP neighbor — `ParsePeerNeighbor`; `/32`/`/128` нормализуются в host addr.
|
|
*Проверка:* `peer_neighbor_test.go`
|
|
|
|
**IP-04** | NEVER | Hardcoded production CIDR вне testdata/fixtures.
|
|
*Проверка:* grep; review.
|
|
|
|
**IP-05** | MUST | Fixtures/docs — TEST-NET (RFC 5737, 3849): `203.0.113.0/24`, `198.51.100.0/24`, `2001:db8::/32`.
|
|
*Проверка:* scenarios.
|
|
|
|
**IP-06** | MUST | Domain→IP: host routes `/32`, `/128` via `ipToHostPrefix`; invalid отбрасывается.
|
|
*Проверка:* `collect_parallel.go`
|
|
|
|
**IP-07** | MUST | IP range entries — валидный CIDR на границе API/store.
|
|
*Проверка:* httpapi; review.
|
|
|
|
**IP-08** | SHOULD | Множество префиксов — без дубликатов; агрегация — policy decision.
|
|
*Проверка:* snapshot dedup.
|
|
|
|
**IP-09** | MUST | `router id`, `local as` — из tenant settings, не hardcode в callers `birdfmt`.
|
|
*Проверка:* `docs/manual.md`
|
|
|
|
**IP-10** | NEVER | Reserved blocks (`0.0.0.0/8`, `127.0.0.0/8`, `169.254.0.0/16`, `224.0.0.0/4`, IPv6 analogs) в materialized prefixes.
|
|
*Проверка:* review; future validator.
|
|
|
|
---
|
|
|
|
## D. Internet Compliance
|
|
|
|
**COMP-01** | SHOULD | Policy changes — сверка RFC 4271, 4760, 7454 (обзор).
|
|
*Проверка:* review.
|
|
|
|
**COMP-02** | MUST | No excessive deaggregation без need.
|
|
*Проверка:* review prefix list.
|
|
|
|
**COMP-03** | MUST | Standard community 0..65535; large — schema store.
|
|
*Проверка:* `community_bird_test.go`
|
|
|
|
**COMP-04** | NEVER | AS_PATH/MED manipulation без product spec.
|
|
*Проверка:* review output.
|
|
|
|
**COMP-05** | SHOULD | Revision/job meta: source, counts, samples (`revisionLogEntry`).
|
|
*Проверка:* jobs.
|
|
|
|
**COMP-06** | MUST | Node: `evobgp-node verify-bundle` перед apply.
|
|
*Проверка:* `docs/access.md`
|
|
|
|
**COMP-07** | SHOULD | `bird_local_asn` = `local as` в templates/peers.
|
|
*Проверка:* settings + birdfmt.
|
|
|
|
**COMP-08** | NEVER | Default route leak без named `default-originate` policy.
|
|
*Проверка:* export filter review.
|
|
|
|
---
|
|
|
|
## Validation & Observability
|
|
|
|
**VAL-01** | MUST | Перед деплоем: `bird -c <bird.conf> -p` (main + includes).
|
|
*Проверка:* CI `bird2`; `ParseCheck`
|
|
|
|
**VAL-02** | MUST | Preview ревизии read-only; apply — jobs/apply/bundle only.
|
|
*Проверка:* OpenAPI + httpapi.
|
|
|
|
**VAL-03** | MUST | Изменения birdfmt — `go test ./internal/birdfmt/...`.
|
|
*Проверка:* CI `go`
|
|
|
|
**VAL-04** | SHOULD | Dry-run apply где API поддерживает `dry_run`.
|
|
*Проверка:* routes.go.
|
|
|
|
**VAL-05** | MUST | `/metrics` Prometheus; `EVOBGP_BIRDC_SOCKET` — BGP session poller.
|
|
*Проверка:* `observability`
|
|
|
|
**VAL-06** | MUST | Логировать job_id, revision_id, speaker_id на apply/refresh/rollback.
|
|
*Проверка:* jobs API.
|
|
|
|
**VAL-07** | SHOULD | После apply — `birdc show protocols` / parsers в `birdfmt`.
|
|
*Проверка:* `protocols.go`
|
|
|
|
**VAL-08** | MUST | Мониторить drift: `last_applied_revision_id` vs published (`evobgp-deploy`).
|
|
*Проверка:* deploy worker.
|
|
|
|
---
|
|
|
|
## Documentation Sync
|
|
|
|
**DOC-SYNC-05** | MUST | BIRD — https://bird.network.cz/?get_doc
|
|
**DOC-SYNC-08** | MUST | BGP policy — RFC 4271, 4760, 7454 + BIRD docs + `birdfmt`
|
|
**DOC-SYNC-09** | MUST | CIDR — https://pkg.go.dev/net/netip ; примеры — RFC 5737, 3849
|
|
|
|
---
|
|
|
|
## Enforcement
|
|
|
|
```powershell
|
|
go test ./internal/birdfmt/... ./internal/pipeline/... -count=1
|
|
bird -c internal/birdfmt/testdata/scenarios/<name>/bird.conf -p
|
|
```
|
|
|
|
**PR checklist `birdfmt/**`, `pipeline/**`, `deploy/bird/**`:**
|
|
- [ ] filter + unit-test + `bird -p`
|
|
- [ ] нет дубли filter logic v4/v6 без общей Go-функции
|
|
- [ ] префиксы только store/revision path
|
|
- [ ] `import none` на templates сохранён
|