5.1 KiB
DPD Parallel Portal
detmir-dpd-portal - параллельный gateway-портал DetMir. Он не заменяет
текущий detmir-portal, а повторяет его функциональность через отдельный
маршрут /dpd/.
Назначение
DPD нужен для безопасной эволюции интерфейса:
- основной HTML-портал
/portal/остаётся стабильным; /dpd/работает как полный mirror текущего портала;- будущий React/Tauri UI сможет использовать те же API-контракты;
- новые UI-решения проверяются без cutover и без дублирования бизнес-логики.
- будущий UI не парсит HTML текущего портала как источник данных.
DPD проксирует:
- вкладки;
- API;
- действия проверки;
- дела;
- расследования;
- markdown/download endpoints;
- материалы проверки.
DPD gateway сохраняет операторский контекст для симметрии с основным порталом:
X-Remote-User, X-Gateway-User, X-Forwarded-*, User-Agent, Referer,
Origin, Cookie и Authorization передаются в upstream, hop-by-hop
заголовки не передаются. Это нужно, чтобы audit/review/case-действия через
/dpd/ фиксировались так же, как через /portal/.
Архитектурное решение
Выбран зрелый путь:
detmir-portal Rust backend
|
| stable /api/contracts
v
current HTML UI + DPD mirror + future React/Tauri UI
Не используется отдельный экспериментальный UI-фреймворк в production path. Сначала фиксируются API-контракты, тестируется совместимость и только затем добавляется новый frontend.
Запуск
detmir-dpd-portal \
--bind 127.0.0.1:8722 \
--upstream-base http://127.0.0.1:8720
Переменные окружения:
DETMIR_DPD_BIND;DETMIR_DPD_UPSTREAM_BASE;DETMIR_DPD_TIMEOUT_SECONDS- по умолчанию 60 секунд, чтобы первый холодный/api/reportsпосле рестарта не выглядел как отказ DPD-портала.
Маршруты
/dpd/- полный параллельный mirror текущего портала./dpd/_dpd/health- health самого DPD gateway./dpd/preview/- компактный read-only preview-экран.
API-контракты
Контракты публикует основной detmir-portal, а DPD зеркалирует их:
/api/contracts;/api/contracts/openapi.json;/api/contracts/typescript.d.ts;/dpd/api/contracts;/dpd/api/contracts/openapi.json;/dpd/api/contracts/typescript.d.ts.
Правила совместимости:
- изменения API должны быть additive;
- клиенты React/Tauri обязаны игнорировать неизвестные поля;
- optional-поля могут отсутствовать;
nullне должен ломать UI;- breaking changes требуют version bump контракта и отдельного architecture decision;
- будущий React/Tauri UI не должен парсить HTML текущего портала.
Проверка симметрии
Минимальная проверка на сервере:
systemctl is-active detmir-dpd-portal detmir-portal nginx --no-pager
curl -sS http://127.0.0.1:8722/_dpd/health
curl -sS -o /dev/null -w 'dpd_index=%{http_code}\n' http://127.0.0.1:8722/
curl -sS -o /dev/null -w 'dpd_reports=%{http_code}\n' http://127.0.0.1:8722/api/reports
curl -sS -o /dev/null -w 'dpd_contracts=%{http_code}\n' http://127.0.0.1:8722/api/contracts
Браузерная проверка с ноутбука:
ssh -o ExitOnForwardFailure=yes -o ServerAliveInterval=15 -o ServerAliveCountMax=3 \
-N -L 18720:127.0.0.1:8720 <GATEWAY_HOST>
detmir-dpd-portal \
--bind 127.0.0.1:18722 \
--upstream-base http://127.0.0.1:18720
DETMIR_PORTAL_SMOKE_URL=http://127.0.0.1:18722/ \
DETMIR_PORTAL_SMOKE_TIMEOUT_MS=70000 \
node scripts/detmir-portal-tabs-smoke.mjs
Ожидаемый результат: ok=true, все вкладки работают, нет JS/API ошибок,
абсолютные /portal/... ссылки в HTML/JS переписаны в /dpd/....
Ограничения
- DPD gateway не добавляет новые бизнес-сущности.
- DPD gateway не заменяет текущий портал.
- Данные берутся из существующего портала/API.
- Новый React/Tauri UI должен появляться поверх контрактов, а не через копирование backend-логики.