Files
elmprodvpn/docs/phase-e/E3_MULTI_INTERFACE_EXECUTION_PLAN.md

92 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# E3 План реализации мультиинтерфейса (execution roadmap)
Дата: 2026-03-15
Статус: in-progress
Владелец: Engineering
## 1) Цель
- Реализовать мультиинтерфейсную архитектуру для transport-клиентов (`singbox`, далее `dnstt`, `phoenix`) без конфликтов маршрутизации.
- Сохранить инвариант: вся логика маршрутизации живёт в Go-ядре, GUI/Web/Mobile остаются тонкими клиентами API.
- Добавить безопасный path миграции без поломки текущего single-interface контура.
## 2) Инварианты реализации
- Никаких прямых мутаций `ip rule`/`ip route`/`nft` из UI.
- Один destination/intent может иметь только одного owner (до явного override).
- Сначала foundation/state/contract, потом orchestration data-plane.
- Каждый этап обратим (rollback), каждый этап проверяется `go test ./...`.
## 3) Фазы
### M1. Foundation интерфейсов (без изменения data-plane)
- Добавить логический `iface_id` в `TransportClient` (default: `shared`).
- Добавить state-файл интерфейсов (`transport-interfaces.json`) и нормализацию.
- Добавить read-only endpoint `GET /api/v1/transport/interfaces`.
- Обновить трекер и тесты миграции state.
- Критерий: поведение runtime не меняется, старые профили продолжают работать.
### M2. Interface Orchestrator core (E3.3)
- Ввести оркестратор `create/bind/start/stop/cleanup` по `iface_id`.
- Разделить "логический интерфейс" (`iface_id`) и "runtime iface" (`tunX/dev`) с явным mapping.
- Добавить lock-стратегию на уровне `iface_id`, чтобы исключить race между клиентами.
- Критерий: один API-path для оркестрации всех движков, без дублирования per-client логики.
### M3. Policy compiler per-interface
- Компилировать intents в наборы правил per `iface_id`: table/mark/pref/nft sets.
- Гарантировать непересекаемые allocator-пулы для разных интерфейсов.
- Подготовить атомарный apply-plan для группы интерфейсов.
- Критерий: отдельные интерфейсы не перетирают таблицы/правила друг друга.
### M4. Anti-mixing и ownership guardrails (E3.4/E3.5)
- Strict ownership registry (`domain/cidr/app`) с явным conflict reason.
- Destination stickiness (`conntrack mark` + owner lock).
- Predictable override-flow с подтверждением.
- Критерий: один destination не может "гулять" между двумя интерфейсами без явного switch.
### M5. Transaction pipeline (E3.6)
- Расширить apply до `validate -> plan -> confirm -> apply -> health-check -> commit`.
- На любой ошибке health-check выполнять auto-rollback на previous snapshot.
- Добавить idempotency/optimistic lock для multi-interface apply.
- Критерий: частично применённой политики не остаётся.
### M6. Unified observability API (E6.6)
- Добавить runtime endpoint для карточек/дашбордов:
- `active_iface`,
- `egress` (ip/country),
- `latency`,
- `last_error`,
- counters per engine/policy.
- Вынести метрики в единый DTO для GUI/Web/Mobile.
- Критерий: UI не склеивает статус из нескольких endpoint-ов вручную.
### M7. UI/Web адаптация после backend-ready
- Desktop: переключение iface/client через новый orchestration API.
- Web/Mobile: reuse того же backend-контракта без новой бизнес-логики.
- Добавить feature-flag/compat-mode для плавной миграции.
- Критерий: backend-контракт единый для всех фронтов.
- Текущий дизайн desktop-first зафиксирован: `docs/phase-e/E4_2_MULTI_INTERFACE_GUI_DESIGN.md`.
## 4) Что делаем прямо сейчас
- M1 завершён:
- `iface_id` + `transport-interfaces` state + `GET /transport/interfaces` + тесты.
- M2 завершён:
- добавлен per-`iface_id` lock manager для mutating lifecycle/provision (`start/stop/restart/provision`);
- добавлен mapping-layer `iface_id -> runtime_iface/netns/routing_table` (dedicated iface defaults + interface hints + apply на create/patch/lifecycle/netns-toggle/provision);
- закрыт owner-scope compile этап: `nft_set` генерируется в scope `iface+client+selector` (без shared-set mixing на одном `iface_id`).
- M3 завершён (foundation):
- добавлен compile-plan `iface_id -> table/mark/pref/nft sets` с persisted state (`transport-policies.plan.json`) и возвратом в `validate/apply/rollback/get-policy`;
- добавлен atomic apply executor foundation (`transport-policies.runtime.json` + runtime snapshot/restore) и врезан в `apply/rollback` до commit policy revision;
- подключён kernel stage в executor: per-interface CIDR nft sets apply/cleanup + optional `ip rule` stage под feature-flag;
- ownership foundation (M4-start): добавлен persisted registry `transport-ownership.json` + `GET /api/v1/transport/owners`;
- apply guardrails усилены: `force_override` допускается только для `owner_switch`, hard blocks не bypass-ятся override-флагом;
- anti-mixing foundation (M4-start): owner switch теперь блокируется runtime owner-lock (если previous owner в статусе `up|starting|degraded`);
- ownership observability: `GET /api/v1/transport/owners` аннотирует записи `owner_status/lock_active`, возвращает агрегат `lock_count` для UI/Web;
- conntrack stickiness foundation:
- kernel-stage (feature-flag `SVPN_TRANSPORT_POLICY_CONNTRACK_STICKY=1`) собирает destination-lock state из `conntrack -L -f ipv4` по `mark -> owner`;
- persisted state: `transport-owner-locks.json`;
- read-only endpoint: `GET /api/v1/transport/owner-locks`;
- validate/apply добавляют `destination_lock` block для `cidr` owner-switch, если destination ещё sticky-locked на предыдущего owner.
- owner-lock recovery:
- endpoint `POST /api/v1/transport/owner-locks/clear` (point clear by `client_id` and/or `destination_ip(s)`);
- двухшаговый confirm flow (`confirm_token`) для предотвращения случайного lock-loss.
- следующий шаг: hardening kernel stage (расширение selector coverage, guardrails/observability) + M4 stickiness (`conntrack owner lock`).