# Интеграция router-lists-ui с EvoBGP API

Документ описывает подключение разделов `Домены`, `IP-диапазоны`, `AS`, `Community` из проекта `router-lists-ui` напрямую к EvoBGP API (`/v1`).

Источник правды по контракту: [openapi.yaml](openapi.yaml).

## 1. Базовые требования

- Base URL API: `https://<evobgp-host>/v1`
- Аутентификация: `Authorization: Bearer <api_key>`
- CORS на стороне EvoBGP: переменная `EVOBGP_CORS_ORIGINS`
- Роли:
  - чтение: `viewer+`
  - изменение данных: `editor+`
  - apply/деплой: `operator`

## 2. Маппинг legacy -> EvoBGP

| Раздел UI | Legacy endpoint | EvoBGP endpoint |
|---|---|---|
| Домены | `/api/domains-new` | `/v1/modules?type=DOMAINS` + `/v1/modules/{module_id}/domain-entries` |
| IP-диапазоны | `/api/ip-ranges` | `/v1/modules?type=IP_RANGES` + `/v1/modules/{module_id}/ip-range-entries` |
| AS | `/api/asns` | `/v1/modules?type=AS_PREFIXES` + `/v1/modules/{module_id}/as-entries` |
| Community | `/api/communities` | `/v1/communities` |

Для упрощённой интеграции доступен агрегированный endpoint: `GET /v1/router-lists/catalog` (модули + entries + communities в одном ответе).

## 3. Маппинг полей

| Legacy модель | EvoBGP модель | Комментарий |
|---|---|---|
| `{ domain, community }` | `DomainEntry { fqdn, community_id }` | `community` в UI резолвится в `community_id` через `/v1/communities` |
| `{ ipRange, community }` | `IpRangeEntry { prefix, community_id }` | Для `IP_RANGES` `community_id` обязателен |
| `{ domain, type }` (AS) | `AsEntry { asn, community_id }` | `domain` legacy = ASN |
| `{ value, name }` (Community dict) | `BgpCommunity { community, title }` | `value -> community`, `name -> title` |

## 4. Алгоритм работы по разделам

### 4.1 Домены / IP / AS (общая схема)

1. Найти модуль нужного типа через `GET /v1/modules?type=...`.
2. Если модуль отсутствует, создать через `POST /v1/modules`.
3. Загрузить entries:
   - домены: `GET /v1/modules/{module_id}/domain-entries`
   - IP: `GET /v1/modules/{module_id}/ip-range-entries`
   - AS: `GET /v1/modules/{module_id}/as-entries`
4. При сохранении:
   - удалить отсутствующие записи (`DELETE .../{entry_id}`)
   - обновить изменённые (`PATCH .../{entry_id}`)
   - добавить новые (`POST ...`)

### 4.2 Community

1. Получить список: `GET /v1/communities`
2. Для сохранения diff:
   - новые -> `POST /v1/communities`
   - изменённые -> `PATCH /v1/communities/{id}`
   - удалённые -> `DELETE /v1/communities/{id}`

## 5. Разрешение community

- Перед работой с entries загрузить `/v1/communities`.
- Основной путь: сопоставление по `id`.
- Для UI-формы использовать значение `community` (например, `65001:120`) и перед записью преобразовывать в `community_id`.
- Если community не найдена:
  - для `IP_RANGES` считать ошибкой валидации;
  - для `DOMAINS` и `AS_PREFIXES` можно передать `null` только если это допускается бизнес-логикой.

## 6. Пагинация и ошибки

- Списки используют `cursor + limit`.
- Формат ошибок: `application/problem+json` (RFC 9457).
- Базовая обработка:
  - `401` — неверный/отсутствующий токен
  - `403` — недостаточно прав
  - `404` — ресурс не найден
  - `422` — ошибка валидации

## 7. Примеры (PowerShell)

```powershell
$base = "http://localhost:8080/v1"
$token = "YOUR_API_KEY"
$h = @{ Authorization = "Bearer $token" }

# 1) Найти модуль DOMAINS
$modules = Invoke-RestMethod -Uri "$base/modules?type=DOMAINS&limit=50" -Headers $h
$moduleId = $modules.items[0].id

# 2) Прочитать домены
Invoke-RestMethod -Uri "$base/modules/$moduleId/domain-entries?limit=100" -Headers $h
```

```powershell
# Создать community
$body = @{
  community = "65001:120"
  title     = "Video"
} | ConvertTo-Json

Invoke-RestMethod -Method Post -Uri "$base/communities" -Headers $h -ContentType "application/json" -Body $body
```

## 8. Настройки router-lists-ui для прямой интеграции

Рекомендуемые переменные frontend:

- `VITE_EVOBGP_API_URL` (по умолчанию `/v1`)
- `VITE_EVOBGP_API_TOKEN` (опционально; либо хранить токен в `localStorage` как `evobgp_api_token`)

Для dev-прокси Vite добавить маршрут `/v1 -> http://localhost:8080`.

## 9. Контрольный список интеграции

- [ ] `Домены`: list/create/update/delete работают через `/v1/modules/{id}/domain-entries`
- [ ] `IP-диапазоны`: list/create/update/delete работают через `/v1/modules/{id}/ip-range-entries`
- [ ] `AS`: list/create/update/delete работают через `/v1/modules/{id}/as-entries`
- [ ] `Community`: CRUD работает через `/v1/communities`
- [ ] ошибки `problem+json` корректно отображаются в UI
