Sprint 0 / #16: каркас монорепозитория, ADR-001..008 и линтеры #47
@@ -0,0 +1,28 @@
|
|||||||
|
# 003. Декларативный reconcile вместо императивных скриптов
|
||||||
|
|
||||||
|
- **Статус:** принято
|
||||||
|
- **Контекст/issue:** #15, #24, #27
|
||||||
|
|
||||||
|
## Контекст
|
||||||
|
|
||||||
|
PoC (`entrypoint.sh`) применяет правила императивно и только при старте: изменения не откатываются,
|
||||||
|
GeoIP не обновляется без рестарта, частичная ошибка оставляет систему в неопределённом состоянии.
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
|
||||||
|
Единый reconcile-цикл: desired state (SQLite) -> diff -> идемпотентное применение -> проверка ->
|
||||||
|
rollback при ошибке. Операции netfilter идемпотентны (проверка `-C` перед `-A`), замена больших
|
||||||
|
наборов атомарна (`ipset create tmp`, `swap`, `destroy`), применение конфига транзакционно
|
||||||
|
(validate -> stage -> apply -> rollback).
|
||||||
|
|
||||||
|
## Альтернативы
|
||||||
|
|
||||||
|
- **Скрипты по событию** (как в PoC) — быстро написать, но невозможно гарантировать сходимость после сбоя.
|
||||||
|
- **Готовый IaC-инструмент** — избыточен, требует внешнего рантайма в образе и не покрывает ipset/dnsmasq.
|
||||||
|
|
||||||
|
## Последствия
|
||||||
|
|
||||||
|
- Старт контейнера = reconcile с нуля: состояние всегда восстановимо.
|
||||||
|
- Нужны тесты на идемпотентность (повторный apply не создаёт дублей) — #41.
|
||||||
|
- Сложнее скрипта: оправдано требованиями FR-2 (смена режимов и правил без рестарта).
|
||||||
|
- Diff reconcile логируется и отдаётся в UI (`/logs`) и audit log.
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# 004. GeoIP: RIPE Stat + локальный кэш + абстракция провайдера
|
||||||
|
|
||||||
|
- **Статус:** принято
|
||||||
|
- **Контекст/issue:** #15, #25
|
||||||
|
|
||||||
|
## Контекст
|
||||||
|
|
||||||
|
Для split-tunnel нужны списки префиксов страны (в PoC — около 11 400 записей RIPE).
|
||||||
|
Варианты: RIPE Stat (бесплатно), ip2location и MaxMind (точнее, но лицензия и платный доступ).
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
|
||||||
|
Основной источник — **RIPE Stat** (`country-resource-list`, IPv4 и IPv6): бесплатно и уже проверено в PoC.
|
||||||
|
Обязательные элементы: локальный кэш-снапшот в `/data/geoip/`, расписание обновления, ручное
|
||||||
|
обновление, явный статус источника (API или кэш с датой). Внутри — интерфейс `GeoProvider`, чтобы
|
||||||
|
добавить ip2location/MaxMind без переделки маршрутизации.
|
||||||
|
|
||||||
|
## Альтернативы
|
||||||
|
|
||||||
|
- **MaxMind GeoLite2** — точнее по ASN, но требует регистрации и обновления лицензии; оставляем как опцию.
|
||||||
|
- **Собственный список в репозитории** — устаревает и не покрывает смену маршрутной политики.
|
||||||
|
|
||||||
|
## Последствия
|
||||||
|
|
||||||
|
- Старт не зависит от внешней сети: при недоступности API работаем на кэше (#25, тест #41).
|
||||||
|
- Fallback не должен молча менять политику split-tunnel: неявные переходы в режим «всё в VPN» или
|
||||||
|
«всё напрямую» запрещены, поведение задаётся явно (#23).
|
||||||
|
- Загрузка 11k+ префиксов — измеримая операция; время старта и swap — часть AC #24 и #25.
|
||||||
Reference in New Issue
Block a user