feat(web): add OpenAPI TypeScript codegen and CI freshness check

Генерируем api.gen.ts из docs/openapi.yaml (openapi-typescript), добавляем scripts/check-openapi-gen.sh в CI. Закрываем решение по X-Tenant-Id как unimplemented; обновляем docs/README под React/ReUI и apps/web.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-31 12:19:02 +07:00
co-authored by Cursor
parent a0cfbcdab1
commit 13e3d21ce2
9 changed files with 6782 additions and 32 deletions
+4 -2
View File
@@ -7,7 +7,7 @@
- **ИИ-агент / ассистент в репозитории** — [../AGENTS.md](../AGENTS.md): с чего начать чтение, карта `internal/` и `cmd/`, что не тащить в контекст. **Инженерные правила:** [../.cursor/rules/engineering.mdc](../.cursor/rules/engineering.mdc) (общие), [../.cursor/rules/web-shadcn.mdc](../.cursor/rules/web-shadcn.mdc) (Web UI), [../.cursor/rules/networking-bird.mdc](../.cursor/rules/networking-bird.mdc) (BIRD2/BGP/IP).
- **Оператор / DevOps** — [quickstart.md](quickstart.md), [architecture.md](architecture.md), [access.md](access.md), [deploy/compose/docker-compose.yaml](../deploy/compose/docker-compose.yaml).
- **Разработчик бэкенда или интегратор API** — [api.md](api.md), [access.md](access.md), [openapi.yaml](openapi.yaml), исходники маршрутов в `internal/httpapi/`.
- **Разработчик фронтенда** — [quickstart.md](quickstart.md) (раздел про `web/` и CORS), [api.md](api.md), [../web/README.md](../web/README.md).
- **Разработчик фронтенда** — [quickstart.md](quickstart.md) (раздел про `apps/web/` и CORS), [api.md](api.md), [ui-design-contract.md](ui-design-contract.md), [../apps/web/](../apps/web/).
## Оглавление
@@ -22,6 +22,7 @@
| [access.md](access.md) | Выдача доступа: API-ключи, роли, нода, CORS |
| [remote-speakers.md](remote-speakers.md) | Удалённые BGP-реплики: Traefik, agent sync, compose |
| [releasing.md](releasing.md) | Автоматические релизы, Conventional Commits, CI |
| [ui-design-contract.md](ui-design-contract.md) | UI SoT: ReUI Frame, kit, KPI hybrid |
| [openapi.yaml](openapi.yaml) | Источник правды по контракту API |
| [OPENAPI-GITEA.md](OPENAPI-GITEA.md) | Как открыть HTML-документацию API (в т.ч. из Gitea) |
| [evobgp-api-sketches.md](evobgp-api-sketches.md) | Ранний черновик идей API (контекст, не замена OpenAPI) |
@@ -31,7 +32,8 @@
| Файл | Область |
|------|---------|
| [../.cursor/rules/engineering.mdc](../.cursor/rules/engineering.mdc) | Go, API, migrations, security, enforcement |
| [../.cursor/rules/web-shadcn.mdc](../.cursor/rules/web-shadcn.mdc) | SvelteKit, shadcn-svelte |
| [../.cursor/rules/web-shadcn.mdc](../.cursor/rules/web-shadcn.mdc) | React + TanStack + shadcn/ui + ReUI (`apps/web`, `packages/ui`) |
| [../.cursor/rules/reui-mcp.mdc](../.cursor/rules/reui-mcp.mdc) | ReUI PRO MCP workflow, surface `frame` |
| [../.cursor/rules/networking-bird.mdc](../.cursor/rules/networking-bird.mdc) | BIRD2, BGP policy, IP/CIDR |
| [../.cursor/rules/conventional-commits.mdc](../.cursor/rules/conventional-commits.mdc) | Conventional Commits (заголовок EN, тело RU) |
+4 -2
View File
@@ -168,9 +168,11 @@ http://localhost:5173,http://127.0.0.1:5173,https://ui.example.com
Разрешённые заголовки включают `Authorization`, `Content-Type`, `Idempotency-Key`, `Accept`, `X-Tenant-Id` (см. `internal/httpapi/cors.go`).
## Заголовок `X-Tenant-Id` (спецификация vs реализация)
## Заголовок `X-Tenant-Id` (решение: не реализован)
В [openapi.yaml](openapi.yaml) описано использование **`X-Tenant-Id`** для супер-ролей при работе от имени разных арендаторов. В **текущем коде** после аутентификации tenant берётся **только из записи API-ключа**; заголовок `X-Tenant-Id` **не переопределяет** tenant в обработчиках. До появления поддержки в коде не рассчитывайте на переключение tenant через этот заголовок.
**Решение (done):** заголовок **`X-Tenant-Id` не переключает tenant** в handlers и **не планируется** без отдельного ADR на супер-роли.
В [openapi.yaml](openapi.yaml) он помечен как reserved / unimplemented; tenant всегда из API-ключа, portal JWT claim или `EVOBGP_PORTAL_TENANT_ID`.
Клиенты **не должны** полагаться на `X-Tenant-Id`.
## Доступ к репозиторию и CI
+2 -1
View File
@@ -19,7 +19,8 @@ info:
**Роли API key** (матрица): `viewer`, `editor`, `operator`, `node`. Нода использует отдельные пути и ключ с ролью `node`.
JWT permissions мапятся на ту же лестницу (`:read`→viewer, `:write`→editor, `:admin`→operator).
Заголовок `X-Tenant-Id` допускается только для супер-ролей (явный tenant); иначе tenant берётся из API-ключа / portal tenant env.
Заголовок `X-Tenant-Id`: **не реализован в handlers** (документировано в docs/access.md).
Tenant всегда из API-ключа / portal JWT claim / `EVOBGP_PORTAL_TENANT_ID`. Спецификация сохраняет заголовок как reserved future; не полагаться на него в клиентах.
license:
name: Proprietary
identifier: LicenseRef-Proprietary