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
32 KiB
32 KiB
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; .rscbackup 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 + credsFilterRule:{ community, gateway, description, ...extra }+scopeBlobObject: logical key + body + etag + versionsUiSettingsMikrotikBackup
Критические ограничения (НЕ НАРУШАТЬ)
- Нельзя заменять 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.jsxroutes + 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*) пока фронт/интеграции их используют.
- Новый endpoint добавлять через route/service, не встраивать бизнес-логику в
- Зависимости: 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 в листинге).
- форматы payload для
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: данные справочников +
sendOkmetadata. - 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-configslist: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: nullpayload при деградации. - 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_* |
/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
staleTimedefault 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 (обязательный)
Перед изменением кода агент обязан:
- Найти все зависимости (routes/services/hooks/components/schedulers).
- Проверить влияние на API (input/output, status codes, headers).
- Проверить влияние на DB (таблицы, ключи blobs, миграции, транзакции).
- Проверить UI impact (query keys, route path, optimistic update behavior).
- Сформировать
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.
- проверять structured logs (
- Frontend:
- проверять network ошибки через
apiErrorHandler+ notify payload; - проверять retry/noRetry и cache behavior.
- проверять network ошибки через
Откат изменений
- Код: откат через VCS commit revert.
- Данные:
- blob keys:
/api/history/:resource/rollback(если поддерживается). - filters/evobgp resources: rollback через локальный history API не поддерживается; нужен внешний restore plan.
- blob keys:
Изоляция багов
- Сначала локализовать слой (UI/API/Service/Storage/External).
- Воспроизвести минимальный сценарий.
- Проверить контракт на границе слоя перед deep refactor.
Логирование проблем
- Каждый баг-репорт должен включать:
- requestId/endpoint;
- входной payload (без секретов);
- фактический vs ожидаемый ответ;
- impacted таблицы/ключи.
11. EXTENSION GUIDE
Добавление новой фичи (общий шаблон)
- Добавить/расширить service (доменная логика).
- Добавить route с валидацией и contract-consistent ответом.
- Добавить frontend hook в
useApiQuery.jsили отдельный data hook. - Подключить UI page/component + route entry.
- Добавить проверку 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/sendOkcontract. - Не обходить
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-валидация критических сценариев.