Refactor project structure and improve component organization
Publish Docker image / build-and-push (push) Successful in 1m0s
Publish Docker image / build-and-push (push) Successful in 1m0s
- Restructured project files for better maintainability and clarity. - Enhanced component organization to streamline imports and improve readability. - Updated relevant documentation to reflect changes in project structure. Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,482 @@
|
||||
# AI-READY DEVELOPMENT SPEC
|
||||
|
||||
## 1. SYSTEM OVERVIEW (СИСТЕМНЫЙ КОНТЕКСТ)
|
||||
|
||||
Система `router-lists-ui` управляет сетевыми данными и конфигурациями RouterOS/MikroTik: домены, ASN, IP-диапазоны, фильтры, серверные конфиги, бэкапы и мониторинг доступности/ресурсов. UI (`React + Vite`) работает с API (`Express`) через `/api/*`.
|
||||
|
||||
Фактическая модель хранения гибридная:
|
||||
- справочники BGP (domains/asns/ip-ranges/communities/auto-urls) обслуживаются через EvoBGP API (`evobgpClient`);
|
||||
- локальные конфиги/кеш/версии хранятся в SQLite (`better-sqlite3`) через слой совместимости `s3Service`/`blobStorage`;
|
||||
- `.rsc` backup MikroTik хранится в локальной ФС (`MIKROTIK_BACKUP_DIR`).
|
||||
|
||||
### Ключевые бизнес-процессы
|
||||
- Управление BGP-справочниками (CRUD через EvoBGP).
|
||||
- Управление фильтрами (`global/simple`) в `app_filter_rules`.
|
||||
- Управление серверами, server-configs, server-filters.
|
||||
- Генерация/применение MikroTik-конфигов и диагностические операции (ping/traceroute/speed-test).
|
||||
- Планировщики: network-map, ping-services, uptime-monitor, backups.
|
||||
- История/rollback для versioned blob-объектов.
|
||||
|
||||
### Основные сущности
|
||||
- `DomainCommunity`: `{ domain, community }`
|
||||
- `AsnCommunity`: `{ domain(asn), type(community) }`
|
||||
- `IpRangeCommunity`: `{ ipRange, community }`
|
||||
- `Server`: jumphost/exit + gateways + creds
|
||||
- `FilterRule`: `{ community, gateway, description, ...extra }` + `scope`
|
||||
- `BlobObject`: logical key + body + etag + versions
|
||||
- `UiSettings`
|
||||
- `MikrotikBackup`
|
||||
|
||||
### Критические ограничения (НЕ НАРУШАТЬ)
|
||||
- Нельзя заменять EvoBGP-данные локальной SQLite-логикой для `domains-new/asns/ip-ranges/communities/auto-urls`.
|
||||
- Нельзя удалять/ломать ETag-конкурентность (`If-None-Match`, `If-Match`, `412`) в read/write API.
|
||||
- Нельзя ломать namespace/ключи blob-объектов (`servers.json`, `filter-manager/*`, `bgp_data/rt_ui_settings.json` и т.д.) без миграционного плана.
|
||||
- Нельзя отключать `journal_mode=WAL`, `foreign_keys=ON`, `busy_timeout`.
|
||||
- Нельзя менять формат ответа ошибок `{ code, message, details, requestId }`.
|
||||
|
||||
---
|
||||
|
||||
## 2. REPOSITORY MAP (КАРТА РЕПОЗИТОРИЯ)
|
||||
|
||||
> Примечание: в текущем репозитории нет отдельных top-level директорий `/db`, `/services`, `/api`, `/agents`; их роль реализована внутри `backend/`.
|
||||
|
||||
### `/frontend`
|
||||
- Назначение: UI-приложение (`React 19`, `react-router-dom`, `@tanstack/react-query`, `axios`, Tabler).
|
||||
- Ключевые зоны:
|
||||
- `src/App.jsx`: роутинг, layout, providers (`QueryClientProvider`, `NotifyProvider`, `PingProvider`, `AlertsProvider`).
|
||||
- `src/lib/api.js`: единый HTTP-клиент, retry, ETag-based GET-cache, нормализация ошибок.
|
||||
- `src/hooks/useApiQuery.js`: реактивный data-layer + optimistic updates.
|
||||
- Правила изменений:
|
||||
- Любой новый экран регистрировать в `App.jsx` routes + navigation.
|
||||
- Новые API-вызовы делать только через `src/lib/api.js`.
|
||||
- Мутации должны инвалидацировать/обновлять react-query cache.
|
||||
- Зависимости: backend `/api`, browser localStorage (theme/lang/layout), глобальный notifier.
|
||||
|
||||
### `/backend`
|
||||
- Назначение: API, интеграции, storage abstraction, schedulers.
|
||||
- Ключевые зоны:
|
||||
- `server.js`: composition root, middleware, endpoint registration.
|
||||
- `routes/*.js`: endpoint-level orchestration.
|
||||
- `services/*.js`: storage/EvoBGP/MikroTik/scheduler логика.
|
||||
- `db/sqliteDb.js` + `db/migrations/*.sql`: DB init/migrations.
|
||||
- `middleware/*`: unified errors + soft locks.
|
||||
- Правила изменений:
|
||||
- Новый endpoint добавлять через route/service, не встраивать бизнес-логику в `server.js`.
|
||||
- Для persistent данных использовать `s3Service`/`filterRulesStorage`/`backupFsService` по назначению.
|
||||
- Сохранять совместимость legacy-имен (`s3*`) пока фронт/интеграции их используют.
|
||||
- Зависимости: SQLite, EvoBGP HTTP API, локальная ФС для backups, env-конфиг.
|
||||
|
||||
### `/backend/db` (внутренний `/db`)
|
||||
- Назначение: схема и поведение SQLite.
|
||||
- Состав:
|
||||
- `migrations/001_init.sql`: blobs/meta/cache/versioning.
|
||||
- `migrations/002_filter_rules.sql`: `app_filter_rules`.
|
||||
- Правила изменений:
|
||||
- Только миграциями; прямые ручные правки существующих таблиц запрещены.
|
||||
- Миграции должны быть backward-compatible и idempotent.
|
||||
|
||||
### `/backend/services` (внутренний `/services`)
|
||||
- Назначение: слой бизнес-операций и инфраструктурных адаптеров.
|
||||
- Ключевые модули:
|
||||
- `evobgpClient.js` (внешний источник правды для BGP reference).
|
||||
- `s3Service.js` + `blobStorage.js` (SQLite-backed blob API).
|
||||
- `filterRulesStorage.js` (SQL-таблица фильтров).
|
||||
- `mikrotik*`, `*Scheduler.js` (операции и периодические задачи).
|
||||
- Правила изменений:
|
||||
- Не смешивать transport-логику endpoint с data-access.
|
||||
- Любая write-операция должна возвращать meta для `sendOk`.
|
||||
|
||||
### `/backend/routes` (внутренний `/api`)
|
||||
- Назначение: HTTP contracts + валидация входа + orchestrator.
|
||||
- Правила изменений:
|
||||
- Вход валидируется до вызова сервиса.
|
||||
- Ошибки наружу только через `sendError`.
|
||||
- ETag/Last-Modified сохранять в GET/POST где уже реализовано.
|
||||
|
||||
### `/agents`
|
||||
- В репозитории отсутствует.
|
||||
|
||||
---
|
||||
|
||||
## 3. ARCHITECTURE RULES (АРХИТЕКТУРНЫЕ ПРАВИЛА)
|
||||
|
||||
### Слои и границы
|
||||
- DO: `Route -> Service -> Storage/External API`.
|
||||
- DO: хранить валидацию запроса на route-слое, а доменную обработку в service.
|
||||
- DON'T: вызывать SQLite напрямую из UI.
|
||||
- DON'T: переносить доменную логику в `server.js`.
|
||||
|
||||
### Бизнес-логика
|
||||
- DO: для filters использовать только `filterRulesStorage` (`app_filter_rules`).
|
||||
- DO: для BGP-reference использовать только `evobgpClient`.
|
||||
- DON'T: писать domains/asns/ip-ranges в `blobs`.
|
||||
|
||||
### State management (frontend)
|
||||
- DO: network-state через React Query.
|
||||
- DO: optimistic updates + rollback на error.
|
||||
- DO: invalidation query keys после мутаций.
|
||||
- DON'T: дублировать fetch/caching logic вне `api.js`/`useApiQuery.js`.
|
||||
|
||||
### Доступ к БД
|
||||
- DO: через `s3Service`/`blobStorage`/`filterRulesStorage`.
|
||||
- DO: учитывать `etag`, `lastModified`, `contentLength`.
|
||||
- DON'T: менять ключевые `object_key` без миграции и impact map.
|
||||
|
||||
### Изменения высокой опасности
|
||||
- Запрещено менять без полной цепочки рефакторинга:
|
||||
- форматы payload для `/api/domains-new`, `/api/asns`, `/api/ip-ranges`;
|
||||
- schema ключей blob-хранилища;
|
||||
- `sendOk/sendError` формат;
|
||||
- scheduler settings endpoints и их JSON-структуры;
|
||||
- semantics `server-configs` (только jumphost в листинге).
|
||||
|
||||
---
|
||||
|
||||
## 4. BUSINESS LOGIC SPECIFICATION
|
||||
|
||||
### 4.1 Процесс: BGP Reference Sync (domains/asns/ip-ranges)
|
||||
- Inputs: HTTP GET/POST, EvoBGP env (`EVOBGP_API_URL`, `EVOBGP_API_TOKEN`), payload массив.
|
||||
- Outputs: данные справочников + `sendOk` metadata.
|
||||
- States:
|
||||
- `IDLE` -> `VALIDATE_INPUT` -> `CALL_EVOBGP` -> `NORMALIZE` -> `RESPOND_OK`
|
||||
- ветка ошибки: `VALIDATE_INPUT -> RESPOND_400` или `CALL_EVOBGP -> RESPOND_5XX`.
|
||||
- Errors: `E_BAD_REQUEST`, `E_SCHEMA`, `E_EVOBGP`, `E_EVOBGP_NOT_CONFIGURED`.
|
||||
- Side effects: запись в EvoBGP, обновление remote reference set.
|
||||
|
||||
### 4.2 Процесс: Filter Rules Replace (`global/simple`)
|
||||
- Inputs: `scope`, массив правил `{community,gateway,...}`.
|
||||
- Outputs: новый snapshot правил + meta (`etag/lastModified`).
|
||||
- States:
|
||||
- `READ_SCOPE_META` -> `VALIDATE_ARRAY` -> `TX_BEGIN` -> `DELETE_SCOPE_ROWS` -> `INSERT_ROWS_ORDERED` -> `UPDATE_META_MTIME` -> `TX_COMMIT` -> `RESPOND_OK`
|
||||
- rollback: `TX_BEGIN -> ERROR -> TX_ROLLBACK`.
|
||||
- Errors: `E_BAD_REQUEST`, `E_SCHEMA`, `E_STORAGE`.
|
||||
- Side effects: перезапись всех правил scope (full replace).
|
||||
|
||||
### 4.3 Процесс: Blob Object Write (legacy s3Service API)
|
||||
- Inputs: `object_key`, `content`.
|
||||
- Outputs: `sendOk(meta)`.
|
||||
- States:
|
||||
- `VALIDATE_KEY` -> `READ_EXISTING` -> `IF_VERSIONED_SAVE_OLD_VERSION` -> `UPSERT_BLOB` -> `TRIM_VERSIONS` -> `INVALIDATE_MEMORY_CACHE` -> `RESPOND_OK`.
|
||||
- Errors: `E_STORAGE`.
|
||||
- Side effects: изменение `blobs`, опционально `blob_versions`.
|
||||
|
||||
### 4.4 Процесс: Server Config Management
|
||||
- Inputs: `serverId`, config text / filters json.
|
||||
- Outputs: per-server config/filter data.
|
||||
- States:
|
||||
- `VALIDATE_SERVER_ID` -> `READ_OR_WRITE_BLOB_KEY` -> `RESPOND`.
|
||||
- Для `/api/server-configs` list: `READ_SERVERS` -> `FILTER_JUMPHOST` -> `MAP_ID_NAME` -> `RESPOND`.
|
||||
- Errors: `E_BAD_REQUEST`, `E_SCHEMA`, `E_S3/E_STORAGE`.
|
||||
- Side effects: запись в `filter-manager/config-*.txt` и `filter-manager/server-filters-*.json`.
|
||||
|
||||
### 4.5 Процесс: Auto URLs Ingestion
|
||||
- Inputs: список URL + community.
|
||||
- Outputs: summary counters.
|
||||
- States:
|
||||
- `LOAD_URLS` -> `FETCH_CONTENT` -> `PARSE_LINES` -> `CLASSIFY(IP/CIDR/DOMAIN)` -> `DEDUP_WITH_CURRENT` -> `SAVE_TO_EVOBGP` -> `RESPOND`.
|
||||
- Errors: `E_BAD_REQUEST`, `E_EVOBGP`.
|
||||
- Side effects: расширение списков IP/domains в EvoBGP.
|
||||
|
||||
### 4.6 Процесс: Ping Services Cache Refresh
|
||||
- Inputs: UI settings (`pingServicesSource`, cache TTL), services list.
|
||||
- Outputs: `{ byId, history }`.
|
||||
- States:
|
||||
- `LOAD_UI_SETTINGS` -> (`ROUTER_MODE` | `WEB_MODE`) -> `MEASURE_RTT` -> `WRITE_CACHE` -> `APPEND_HISTORY` -> `RESPOND`.
|
||||
- Errors: fallback на `ms: null` payload при деградации.
|
||||
- Side effects: запись в blob-ключи `ping-services/cache_*`, `ping-services/history_*`.
|
||||
|
||||
### 4.7 Процесс: History Rollback
|
||||
- Inputs: `resource`, `versionId`.
|
||||
- Outputs: `sendOk(meta)` после rollback.
|
||||
- States:
|
||||
- `MAP_RESOURCE_TO_KEY` -> `VALIDATE_SUPPORT` -> `ROLLBACK_VERSION` -> `RESPOND`.
|
||||
- Errors: `E_RESOURCE`, `E_HISTORY_EV`, `E_HISTORY_FILTERS_SQL`, `E_STORAGE`.
|
||||
- Side effects: восстановление blob из `blob_versions`.
|
||||
|
||||
---
|
||||
|
||||
## 5. API CONTRACTS (ФОРМАЛЬНЫЕ КОНТРАКТЫ)
|
||||
|
||||
### 5.1 Глобальные правила API
|
||||
- Base path: `/api`.
|
||||
- Auth level: явной auth-схемы нет (network-level trust, rate-limit, CORS, security headers).
|
||||
- Success write format: `{ ok, etag, lastModified, contentLength }`.
|
||||
- Error format: `{ code, message, details, requestId }`.
|
||||
- Конкурентность: `If-None-Match` для GET, `If-Match`/`etag` для отдельных write.
|
||||
|
||||
### 5.2 Контракты endpoint’ов
|
||||
|
||||
| Route | Method | Auth | Input schema (JSON) | Output schema | Side effects | Таблицы/ключи | Сервисы |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| `/health` | GET | public | - | `{ok:true}` | none | - | - |
|
||||
| `/ready` | GET | public | - | `{ok:true}` | none | - | - |
|
||||
| `/metrics` | GET | internal | - | Prometheus text | none | - | prom-client |
|
||||
| `/api/version` | GET | public | - | `{version,gitSha,buildAt}` | none | - | env |
|
||||
| `/api/domains` | GET/POST | public | POST: `{domains:[{domain,type}],etag?}` | GET std/raw list, POST `sendOk` | remote write/read | EvoBGP | evobgpClient |
|
||||
| `/api/asns` | GET/POST | public | POST: `{domains:[{domain,type}],etag?}` | GET/POST аналогично | remote write/read | EvoBGP | evobgpClient |
|
||||
| `/api/domains-new` | GET/POST | public | POST: `{domains:[{domain,community}],etag?}` | GET/POST аналогично | remote write/read | EvoBGP | evobgpClient |
|
||||
| `/api/ip-ranges` | GET/POST | public | POST: `{ipRanges:[{ipRange,community}],etag?}` | GET/POST аналогично | remote write/read | EvoBGP | evobgpClient |
|
||||
| `/api/servers` | GET/POST | public | POST: `{servers:[...],etag?}` | JSON list / `sendOk` | persist servers | `blobs:servers.json` | serversRoutes,s3Service |
|
||||
| `/api/server-connections` | GET/POST | public | POST: `{domains:[{from,to,tunnelType,...}]}` | list / `sendOk` | persist graph links | blob key `server-connections.json` | jsonDataRoutes |
|
||||
| `/api/billing` | GET/POST | public | POST: `{items:[...],etag?}` (route expects `domains` in factory; adapters normalize) | list / `sendOk` | persist billing | blob key `servers-billing.json` | jsonDataRoutes |
|
||||
| `/api/filters` | GET/POST | public | POST: `{domains:[{community,gateway,...}]}` | list / `sendOk` | replace scope rules | `app_filter_rules(scope=global)` | filterRulesStorage |
|
||||
| `/api/simple-filters` | GET/POST | public | POST: `{domains:[{community,gateway,...}]}` | list / `sendOk` | replace scope rules | `app_filter_rules(scope=simple)` | filterRulesStorage |
|
||||
| `/api/network-config` | GET/POST | public | POST: `{domains:{gateways?,tunnelInterfaces?,ipPools?}}` | object / `sendOk` | persist network config | blob key `network-config.json` | jsonDataRoutes |
|
||||
| `/api/communities` | GET/POST | public | POST: `{communities:[{value,name?,...}]}` | list / `sendOk` | EvoBGP write | EvoBGP | communitiesRoutes |
|
||||
| `/api/communities/stats` | GET | public | - | `{stats:[{community,count}],total}` | none | EvoBGP + `app_filter_rules` | communitiesRoutes |
|
||||
| `/api/filters/generate-config` | GET | public | query params | generated config | none/write temp | derived blobs | filtersRoutes |
|
||||
| `/api/filters/export-config` | POST | public | export params | file/content json | write export | derived blobs/fs | filtersRoutes |
|
||||
| `/api/server-filters/generate-config` | POST | public | `{serverId,...}` | generated config | none | per-server blobs | filtersRoutes |
|
||||
| `/api/server-configs` | GET/POST | public | POST: `{servers:[jumphost...]}` | jumphost list / `sendOk` | rewrite servers subset | `servers.json` | serverConfigsRoutes |
|
||||
| `/api/server-configs/:serverId` | GET/POST/DELETE | public | POST: `{config:string}` | `{config}` / `sendOk` | write/delete server config | `filter-manager/config-<id>.txt` | serverConfigsRoutes |
|
||||
| `/api/server-configs/:serverId/complete` | DELETE | public | - | `{ok:true,...}` | delete config+filters | `filter-manager/config-*`, `server-filters-*` | serverConfigsRoutes |
|
||||
| `/api/server-filters/:serverId` | GET/POST | public | POST: `{filters:[{community,gateway,...}],etag?}` | `{filters}` / `sendOk` | write server filters | `filter-manager/server-filters-<id>.json` | serverConfigsRoutes |
|
||||
| `/api/locks/:resource` | GET/POST/DELETE | public | POST:`{owner?,ttlSeconds?}` | lock status/result | in-memory lock mutate | RAM only | lockManager |
|
||||
| `/api/history/:resource` | GET | public | query:`countOnly,format` | versions list | none | `blob_versions` | miscRoutes+s3Service |
|
||||
| `/api/history/:resource/rollback` | POST | public | `{versionId}` | `sendOk` | rollback snapshot | `blobs`,`blob_versions` | miscRoutes+s3Service |
|
||||
| `/api/s3/last-modified` | GET | public | - | map metas | none | blobs/filter_rules | miscRoutes |
|
||||
| `/api/auto-urls` | GET/POST | public | POST:`{urls:[{url,community,...}]}` | list / `sendOk` | EvoBGP write | EvoBGP | miscRoutes |
|
||||
| `/api/auto-urls/process` | POST | public | optional params | process summary | pulls URLs, writes lists | EvoBGP | miscRoutes |
|
||||
| `/api/servers/availability` | GET | public | query:`ttlSeconds?` | `{online,total,statuses}` | refresh memory cache | RAM | miscRoutes |
|
||||
| `/api/update-bgp/background` | POST | public (rate limited) | passthrough body | upstream response | outbound HTTP POST | - | miscRoutes |
|
||||
| `/api/ws/url` | GET | public | - | `{url}` | none | `bgp_data/rt_ui_settings.json` | miscRoutes |
|
||||
| `/api/ui-settings` | GET/POST | public | POST:`{settings,etag?}` | settings / `sendOk` | write ui settings | `bgp_data/rt_ui_settings.json` | miscRoutes |
|
||||
| `/api/ping-services-list` | GET | public | - | `{list:[...]}` | none | ui settings | miscRoutes |
|
||||
| `/api/ping-services` | GET | public | query:`refresh|nocache` | `{byId,history}` | cache+history writes | `ping-services/cache_*`,`history_*` | miscRoutes |
|
||||
| `/api/ipsec-passwords` | GET/POST | public | POST DTO ipsec secret | list / item / `sendOk` | secret storage update | blobs/config | ipsecPasswordsRoutes |
|
||||
| `/api/ipsec-passwords/:id` | GET/PUT/DELETE | public | PUT DTO | item / `sendOk` | update/delete secret | blobs/config | ipsecPasswordsRoutes |
|
||||
| `/api/mikrotik/generate` | POST | public | generation payload | config text/json | none | derived | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/generate-interfaces` | GET | public | query | generated config | none | derived | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/generate-recursive-routes` | GET | public | query | generated config | none | derived | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/test-connection` | POST | public | connection payload | test result | network probe | - | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/ping` | GET/POST | public | POST:`{serverId,gateway,target,...}` | health/ping result | RouterOS ping | - | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/traceroute` | POST | public | traceroute payload | trace result | RouterOS command | - | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/speed-test` | POST | public | speed-test payload | throughput metrics | RouterOS command | speed cache blobs | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/apply` | POST | public | apply payload | apply report | config apply + backup | fs+blobs | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/run-script` | POST | public | script payload | execution output | RouterOS script execution | - | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/address-lists` | GET | public | query | list data | none | EvoBGP/derived | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/ospf-interface-templates` | GET | public | query | templates | none | blobs/config | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/ospf-interface-templates/apply` | POST | public | apply payload | `sendOk`/report | RouterOS mutation | - | mikrotikConfigRoutes |
|
||||
| `/api/mikrotik/address-lists/apply-summary` | POST | public | summary payload | report | RouterOS mutation | - | mikrotikConfigRoutes |
|
||||
| `/api/uptime/cache` | GET | public | query | uptime snapshot | none | uptime cache blob | mikrotikConfigRoutes |
|
||||
| `/api/uptime/check` | POST | public | check payload | status report | ping/http checks | uptime cache blob | mikrotikConfigRoutes |
|
||||
| `/api/traffic/interface-stats` | GET | public | query | traffic stats | optional cache update | cache blobs | trafficRoutes |
|
||||
| `/api/resources/stats` | GET | public | query | cpu/ram/hdd stats | optional cache update | cache blobs | resourceStatsRoutes |
|
||||
| `/api/alerts` | GET | public | query | alerts aggregate | none | combines caches | alertsRoutes |
|
||||
| `/api/mikrotik/backups` | GET/POST | public | POST backup payload | list / backup result | write/read `.rsc` | local FS + metadata | mikrotikBackupRoutes |
|
||||
| `/api/mikrotik/backups/item` | GET | public | query id/path | backup item | read FS | local FS | mikrotikBackupRoutes |
|
||||
| `/api/mikrotik/backups/diff` | POST | public | `{from,to,...}` | diff result | none | local FS | mikrotikBackupRoutes |
|
||||
| `/api/mikrotik/backups/run` | POST | public | optional | run-now result | scheduler trigger | local FS | mikrotikBackupRoutes |
|
||||
| `/api/network-map-cache` | GET | public | query | cached map | none | cache blobs | schedulerRoutes |
|
||||
| `/api/route-optimizer` | GET | public | query topology | optimization result | none | derived/cache | routeOptimizerRoutes |
|
||||
| `/api/scheduler/network-map/settings` | GET/PATCH | public | PATCH settings DTO | settings/result | update scheduler config | blobs/ui settings | schedulerRoutes |
|
||||
| `/api/scheduler/network-map/logs` | GET | public | query | logs | none | blobs/logs | schedulerRoutes |
|
||||
| `/api/scheduler/network-map/run-now` | POST | public | optional | trigger result | immediate job | cache update | schedulerRoutes |
|
||||
| `/api/scheduler/ping-services/settings` | GET/PATCH | public | PATCH settings DTO | settings/result | update scheduler config | ui settings | schedulerRoutes |
|
||||
| `/api/scheduler/ping-services/run-now` | POST | public | optional | trigger result | immediate cache refresh | ping-services cache | schedulerRoutes |
|
||||
| `/api/scheduler/uptime-monitor/settings` | GET/PATCH | public | PATCH settings DTO | settings/result | update scheduler config | ui settings | schedulerRoutes |
|
||||
| `/api/scheduler/uptime-monitor/run-now` | POST | public | optional | trigger result | immediate uptime job | uptime cache | schedulerRoutes |
|
||||
| `/api/mikrotik/validate` | POST | public | `{config:string}` | validation report | none | - | mikrotik-validator |
|
||||
|
||||
---
|
||||
|
||||
## 6. DATABASE BEHAVIOR MODEL
|
||||
|
||||
### 6.1 Критичные таблицы
|
||||
|
||||
| Таблица | Назначение | Критичность | Можно менять? |
|
||||
|---|---|---|---|
|
||||
| `blobs` | текущее состояние logical objects | very high | только через миграцию + compatibility layer |
|
||||
| `blob_versions` | история версий для rollback | high | нельзя удалять без замены rollback механизма |
|
||||
| `versioned_keys` | whitelist ключей с версионированием | high | расширять можно, удаление рискованно |
|
||||
| `app_filter_rules` | глобальные/simple фильтры | very high | менять с миграцией + route/service sync |
|
||||
| `app_meta` | meta timestamps/flags | medium | осторожно; используется для etag/mtime |
|
||||
| `cache_entries` | TTL-кеш | medium | можно расширять, не ломая purge logic |
|
||||
| `schema_migrations` | applied versions | critical | не редактировать вручную |
|
||||
|
||||
### 6.2 Cascade/relations
|
||||
- `blob_versions.object_key -> blobs.object_key ON DELETE CASCADE`.
|
||||
- Удаление blob удаляет историю версий автоматически.
|
||||
|
||||
### 6.3 Transactional boundaries
|
||||
- `blobStorage.writeBlobTx`: атомарно сохраняет новую версию + snapshot old version + trim.
|
||||
- `filterRulesStorage.replaceRules`: атомарно `DELETE scope` + `INSERT new set` + update mtime.
|
||||
- Rollback версии выполняется внутри DB write flow.
|
||||
|
||||
### 6.4 Consistency rules
|
||||
- `etag` вычисляется по SHA-256 body; должен соответствовать текущему blob содержимому.
|
||||
- `lastModified` и `contentLength` обязательны для корректной cache-конкурентности UI/API.
|
||||
- `app_filter_rules.position` определяет порядок; запись всегда full-replace.
|
||||
- `SQLITE_PATH` должен быть persistent volume в production.
|
||||
- `journal_mode=WAL` обязателен для конкурентного I/O.
|
||||
|
||||
---
|
||||
|
||||
## 7. FRONTEND RULES (UI ENGINEERING RULESET)
|
||||
|
||||
### Структура страниц
|
||||
- Все маршруты регистрируются централизованно в `App.jsx`.
|
||||
- Экран = manager/page компонент + общие UI-компоненты (`components/*`).
|
||||
|
||||
### State management rules
|
||||
- Server-state: только React Query (`useQuery/useMutation`).
|
||||
- UI-state: local component state + Context (`Language`, `Theme`, `Ping`, `Alerts`).
|
||||
- Запрещено хранить API snapshot в произвольных singleton-объектах вне React Query.
|
||||
|
||||
### Data fetching rules
|
||||
- Только через `src/lib/api.js`.
|
||||
- Для GET использовать `If-None-Match`/ETag-механику клиента.
|
||||
- Для write-путей с поддержкой ETag передавать `If-Match`/`etag`.
|
||||
|
||||
### Caching strategy
|
||||
- React Query `staleTime` default 30s.
|
||||
- Axios in-memory response cache для GET.
|
||||
- Для `/communities` отключён условный GET (всегда fresh).
|
||||
|
||||
### Routing dependencies
|
||||
- Навигация и route paths должны совпадать (sidebar/horizontal menu).
|
||||
- Любой новый route требует:
|
||||
- компонент страницы;
|
||||
- запись в nav categories;
|
||||
- route registration (оба layout блока).
|
||||
|
||||
### Запрещённые паттерны
|
||||
- Прямой `fetch` в компонентах (мимо `api.js`).
|
||||
- Изменение `queryClient` политики точечно без общего обоснования.
|
||||
- UI-изменения, которые ломают optimistic rollback сценарии.
|
||||
|
||||
---
|
||||
|
||||
## 8. AI AGENT OPERATING PROTOCOL
|
||||
|
||||
### 8.1 Роли агентов
|
||||
- `architect agent`: проверяет архитектурные границы, планирует миграции/контракты.
|
||||
- `backend agent`: реализует route/service/storage изменения с сохранением backward compatibility.
|
||||
- `frontend agent`: реализует UI/state/data-fetch изменения по правилам React Query.
|
||||
- `refactor agent`: выполняет безопасные структурные изменения с impact map.
|
||||
- `debug agent`: локализует баги, подтверждает root cause, готовит минимальный fix.
|
||||
|
||||
### 8.2 Правила работы агентов
|
||||
- Перед правками читать: `README.md`, `backend/server.js`, целевой route/service, соответствующий frontend hook/page.
|
||||
- Изменения планировать от контракта к реализации: API -> service -> storage -> UI.
|
||||
- При любом endpoint-change проверять:
|
||||
- формат success/error;
|
||||
- ETag/headers;
|
||||
- влияние на React Query keys и optimistic updates.
|
||||
- Избегать конфликтов:
|
||||
- не менять shared utility без cross-feature impact check;
|
||||
- при рефакторинге route переносить логику в service, не наоборот.
|
||||
|
||||
### 8.3 SAFE EDITING RULE (обязательный)
|
||||
Перед изменением кода агент обязан:
|
||||
1. Найти все зависимости (routes/services/hooks/components/schedulers).
|
||||
2. Проверить влияние на API (input/output, status codes, headers).
|
||||
3. Проверить влияние на DB (таблицы, ключи blobs, миграции, транзакции).
|
||||
4. Проверить UI impact (query keys, route path, optimistic update behavior).
|
||||
5. Сформировать `plan diff` (что меняется, что не меняется, как верифицируется).
|
||||
|
||||
---
|
||||
|
||||
## 9. CHANGE MANAGEMENT PROTOCOL
|
||||
|
||||
### STEP 1 — ANALYZE
|
||||
- Определить feature/bug scope.
|
||||
- Идентифицировать owner-слой (frontend/backend/storage/external).
|
||||
- Собрать baseline контрактов.
|
||||
|
||||
### STEP 2 — IMPACT MAP
|
||||
- Построить карту зависимостей:
|
||||
- endpoint -> service -> storage/external;
|
||||
- endpoint -> frontend hooks -> pages/components.
|
||||
- Классифицировать риск: low/medium/high.
|
||||
|
||||
### STEP 3 — IMPLEMENT PLAN
|
||||
- Реализовать минимально-инвазивные изменения.
|
||||
- Сохранять backward-compatible payload где возможно.
|
||||
- Для high-risk сначала добавить адаптерный слой, потом migration.
|
||||
|
||||
### STEP 4 — APPLY PATCH
|
||||
- Вносить правки атомарными логическими блоками.
|
||||
- Не смешивать функциональные и косметические изменения.
|
||||
- Фиксировать invariants в комментариях только при необходимости.
|
||||
|
||||
### STEP 5 — VERIFY CONSISTENCY
|
||||
- Проверить lint/type/build.
|
||||
- Проверить ключевые API сценарии (read/write/etag/error).
|
||||
- Проверить UI critical path (list load -> edit -> save -> refresh).
|
||||
- Проверить scheduler/side effect пути, если затронуты.
|
||||
|
||||
---
|
||||
|
||||
## 10. DEBUGGING & RECOVERY RULES
|
||||
|
||||
### Диагностика ошибок
|
||||
- Backend:
|
||||
- проверять structured logs (`pino-http`) с `requestId`;
|
||||
- проверять метрики (`http_errors_total`, `http_request_duration_seconds`);
|
||||
- валидировать env для EvoBGP/MikroTik.
|
||||
- Frontend:
|
||||
- проверять network ошибки через `apiErrorHandler` + notify payload;
|
||||
- проверять retry/noRetry и cache behavior.
|
||||
|
||||
### Откат изменений
|
||||
- Код: откат через VCS commit revert.
|
||||
- Данные:
|
||||
- blob keys: `/api/history/:resource/rollback` (если поддерживается).
|
||||
- filters/evobgp resources: rollback через локальный history API не поддерживается; нужен внешний restore plan.
|
||||
|
||||
### Изоляция багов
|
||||
- Сначала локализовать слой (UI/API/Service/Storage/External).
|
||||
- Воспроизвести минимальный сценарий.
|
||||
- Проверить контракт на границе слоя перед deep refactor.
|
||||
|
||||
### Логирование проблем
|
||||
- Каждый баг-репорт должен включать:
|
||||
- requestId/endpoint;
|
||||
- входной payload (без секретов);
|
||||
- фактический vs ожидаемый ответ;
|
||||
- impacted таблицы/ключи.
|
||||
|
||||
---
|
||||
|
||||
## 11. EXTENSION GUIDE
|
||||
|
||||
### Добавление новой фичи (общий шаблон)
|
||||
1. Добавить/расширить service (доменная логика).
|
||||
2. Добавить route с валидацией и contract-consistent ответом.
|
||||
3. Добавить frontend hook в `useApiQuery.js` или отдельный data hook.
|
||||
4. Подключить UI page/component + route entry.
|
||||
5. Добавить проверку impact на ETag/cache/retry.
|
||||
|
||||
### Расширение API
|
||||
- Предпочитать additive changes (новые поля/роуты) вместо breaking.
|
||||
- Для breaking change:
|
||||
- ввести transitional endpoint или feature flag;
|
||||
- обновить frontend и consumers синхронно;
|
||||
- подготовить rollback plan.
|
||||
|
||||
### Добавление новой таблицы
|
||||
- Только новой миграцией `00X_*.sql`.
|
||||
- Определить:
|
||||
- primary key + indexes;
|
||||
- relation/cascade policy;
|
||||
- transaction boundaries;
|
||||
- read/write service API.
|
||||
|
||||
### Как не ломать текущую систему
|
||||
- Не удалять legacy aliases без full usage audit.
|
||||
- Не менять ключи объектов в `blobs` без map миграции.
|
||||
- Не менять `sendError/sendOk` contract.
|
||||
- Не обходить `evobgpClient` для BGP-reference данных.
|
||||
|
||||
---
|
||||
|
||||
## OPERATIONAL CHECKLIST FOR LLM AGENTS
|
||||
|
||||
- [ ] Прочитан `README.md` и целевые route/service/frontend файлы.
|
||||
- [ ] Сформирован `plan diff` и impact map.
|
||||
- [ ] Проверены API contract invariants (status/errors/headers).
|
||||
- [ ] Проверены DB invariants (transactions/etag/versioning).
|
||||
- [ ] Проверен UI flow (query cache + optimistic updates).
|
||||
- [ ] Выполнены lint/build/ручная smoke-валидация критических сценариев.
|
||||
|
||||
Reference in New Issue
Block a user