Пересборка сида
Обновление каталога из легаси-консоли — только чтение, детерминированно, с ревью.
Каталог засеян из базы консоли (animated-spoon). Когда в консоли появляются языки или маппинги провайдеров, которые стоит импортировать, сид пересобирается из свежего дампа.
База консоли — это прод, и она только читается
scripts/dump_console_db.sh открывает соединение с default_transaction_read_only=on и 30-секундным statement timeout, выставленными на сервере через PGOPTIONS. Каждая инструкция в нём — SELECT. Даже опечатка, вносящая запись, была бы отклонена Postgres, а не выполнена.
Данные текут только в одну сторону: консоль → JSON-дамп → сид-файлы → собственная база этого сервиса. Пути назад нет, и само приложение никогда не держит соединения с консолью.
Пересборка
# 1. Дамп (нужен .env-console-db в корне репозитория — в gitignore, никогда не коммитится)
./scripts/dump_console_db.sh build/console-dump
# 2. Трансформация
python scripts/build_seed.py build/console-dump --out data/seed
# 3. Прочитать отчёт
$EDITOR data/seed/REPORT.md
# 4. Посмотреть дифф и закоммитить
git diff --stat data/seed/
Трансформация чистая и детерминированная: тот же дамп на входе даёт байт-в-байт те же файлы на выходе, так что дифф действительно пригоден для ревью.
Как читать отчёт
data/seed/REPORT.md перечисляет каждое решение билдера:
Multi-code (provider, language) pairs collapsed — где консоль предлагала несколько кодов: какой победил и какие были альтернативы. Каждая альтернатива остаётся входящим алиасом, так что ничто, что резолвилось, не перестаёт.
Alias contests resolved — где один код претендовал на два языка и кому он достался. fa-af, ушедший к «Farsi (Afghanistan)», а не к «Dari», — именно тот случай, что стоит второго мнения.
Merged duplicate console languages — строки, описывающие тот же язык под разными id.
Languages with no usable code — импортированы неактивными, с кодом-заглушкой, чтобы ничего не потерять.
Aliases dropped (key already owned) — курированный алиас, столкнувшийся с существующим кодом языка. Обычно корректно: de-DE — собственная строка языка, так что de не получает ещё и de-de.
Providers with no regional overrides — это не пробел. Консоль хранила коды только для региональных языков.
Применение
Коммита достаточно — деплой выполняет python -m app.cli seed после миграций. Локально:
python -m app.cli seed
python -m app.cli stats
Сид идемпотентен и работает как upsert: строки сопоставляются по естественному ключу и обновляются на месте. Он никогда не удаляет.
Для известных ему строк сид имеет приоритет
Код, закреплённый в админке для пары, которую сид тоже несёт, будет сброшен к засеянному значению на следующем деплое. Постоянные исправления должны быть в сиде — либо исправьте консоль и передампьте, либо добавьте пару в таблицу каталога в scripts/build_seed.py. Строки, о которых сид никогда не слышал, остаются нетронутыми.
Добавление провайдера в сид
CATALOG в scripts/build_seed.py зеркалит config/providers.yaml из provider_credentials. Новой записи нужны code, vendor_code, vendor_name, name, category, fallback_policy и legacy — те service_name консоли, что мапятся на него.
Правильный legacy — это то, что держит старых вызывающих рабочими: каждое названное там имя становится алиасом провайдера, и каждый маппинг консоли под этими именами вливается в таблицу этого провайдера.