WEB board

всеканоны и докиворкеры↗ iOS↗ Легаси
WEB-025 · Эпик · Инфраструктура · web

ЭПИК: Admin Remote Defaults — владельческие дефолты/фолбэки (модели, голоса, сервисы) из админки, живая раздача без деплоя

Закрыт P1 · важно ведёт: —
Суть
Запрос owner-а 12.08: выбор пользователя из шестерёнки — приоритет, но ДЕФОЛТЫ и ФОЛБЭКИ (что получает новый юзер, что восстанавливает reset, куда падаем при отказе модели) должен раздавать owner из админ-кабинета онлайн на всех, без деплоя. Это индустриальный паттерн remote config (Firebase Remote Config / LaunchDarkly / Statsig).

ЧТО УЖЕ ЕСТЬ (аудит 12.08): prisma RuntimeConfig (key→Json) — живой remote-config-стор, читают economyConfig/featureGate/NER/video poll; SystemSetting + /api/admin/settings; UserSettings(Json)=шестерёнка; UserAgent.isGlobal — прецедент админ-раздачи ролей. ЧЕГО НЕТ: единого резолвера, admin-GUI дефолтов, фолбэк-цепочек; модели чата/Совета/фактчека читают env+хардкод мимо RuntimeConfig.

КОНТРАКТ РАЗРЕШЕНИЯ (везде одинаково): explicit выбор в запросе > UserSettings (шестерёнка) > RuntimeConfig (admin-дефолт) > env > код-константа. Reset шестерёнки = вернуться на admin-дефолт. Провал провайдера = admin-цепочка primary→fb1→fb2.

ФАЗЫ:
Ф0 = WEB-024 (инвентаризация всех хардкодов моделей) — вход эпика.
Ф1: DefaultsService поверх RuntimeConfig (кэш 60с + инвалидация по updatedAt), подключить глобальный чат (globalChatModel), Совет (council/modelPolicy), фактчек (FACTCHECK_*_MODEL слой уже готов волной 24200ac8), переводы. Ship-dark: ADMIN_DEFAULTS_ENABLED, выкл = текущее поведение бит-в-бит.
Ф2: GUI /admin/defaults: таблица сервис→дефолт+фолбэк-цепочка, валидация слагов по каталогу моделей (registry/models.ts), сохранение = RuntimeConfig (мгновенная раздача), audit-log версий + откат в один клик.
Ф3: фолбэк-цепочки на провал провайдера + health-aware выбор; телеметрия срабатываний (правило 10 — не тихо).
Ф4: расширение на голоса/TTS/промты ролей (унести существующую админ-правку промтов под тот же механизм).

Приёмка: owner меняет дефолт-модель Совета в GUI → новый юзер и reset-юзер получают её БЕЗ деплоя ≤60с; юзер с явным выбором НЕ затронут; отказ провайдера уводит по цепочке с маячком в телеметрии; audit-log показывает кто/когда/что, откат работает.
Доказательства
ДОКИ (постоянные URL, доступны любому воркеру/провайдеру):
• Спека эпика: https://bugs.wool2.online/labs/admin-defaults/SPEC.md
• Опись хардкодов (Ф0): https://bugs.wool2.online/labs/admin-defaults/INVENTORY.md
Правило: тикет самодостаточен — вся история и ссылки здесь; при работе дописывать трейл кумулятивно.

[25.08 ~15:45Z] Взято волной web025 ф.1 (sol xhigh, от 2857a88, по спеке ADMIN-DEFAULTS-EPIC-SPEC.md с M4): typed-слой defaults поверх RuntimeConfig (zod, версия, updatedBy), runtime-чтение с кешем и fail-safe на хардкоды, GET/PUT за админ-гейтом, приоритет юзер>owner-дефолт, reset=дефолт. UI-кабинет = ф.2.

[25.08 ~18:35Z] Ф.1 СДЕЛАНА волной web025: commits 62d87b8+8c6a87e (от 2857a88, по спеке owner). Typed v1 contract (strict zod, satisfies-связка типов), runtime только валидный doc + fail-safe на env/code с маячками admin_defaults_invalid_config/missing_config (без тихих catch); LKG-кеш 30s TTL/5min (пофикшен re-read после failed refresh); precedence ДОКАЗАН тестами: explicit request > gear юзера > admin > env > code; PUT/GET/audit/rollback за fail-closed requireAdmin(); updatedBy = immutable audit actor из сессии; reset → follow_admin с немедленной материализацией. UI-кабинет = ф.2. 📎 Трейл: отчёт /home/ubuntu/waves/WEB025-REPORT.md; ветка web025. → review; кандидат посадки 55.

[25.08 ~18:40Z] Запущена ф.2 волной web025b (ветка от web025): UI-кабинет /admin/defaults — просмотр/редактирование v1-doc с zod-валидацией, diff-превью, audit+rollback, LKG-индикатор; requireAdmin, i18n en/ru/uk.

[25.08 ~21:25Z] (маркер ф.2 принят ранее — трейл) Ф.2 UI-кабинет: см. WEB025B-REPORT.md, ветка web025b. Кандидат посадки 55; независимая приёмка ф.1+ф.2 запускается волной accept025.

[25.08 ~22:05Z] accept025 = GO для ф.1 pin 8c6a87e (10/10 харнесс: 4 RBAC-негатива, битый v1→fail-safe+маячок, LKG при падении delegate, сохранность gear, reset→follow_admin, precedence с логами). ⚠️ Приёмщик отметил: ветка web025b уже ушла на bf9c207 (ф.2 GUI) — этот GO НЕ покрывает GUI-коммит, только 62d87b8+8c6a87e. Для ф.2 — отдельная приёмка. 📎 ACCEPT025-REPORT.md.
[2026-08-25 19:11Z] Независимая приёмка запущена: волна accadmdef на A1 (sol xhigh, приёмщик≠автор), worktree от прод-коммита a453b16; обязательны негативные тесты новых классов; для не-влитых тикетов волна установит факт NOT-LANDED. Бриф /home/ubuntu/waves/accadmdef-brief.md, отчёт будет в ACCADMDEF-REPORT.md.
[2026-08-25 19:33Z] ПРИНЯТО (accadmdef, приёмщик≠автор): LANDED в a453b16 (typed v1 doc, allowlist/catalog, runtime resolver, TTL/LKG, fail-safe; commit 62d87b8 ancestor). Зонный набор 41/41 + независимые негативы. GO → done. Отчёт A1:ACCADMDEF-REPORT.md.
Починено в
a453b16
Дети
Воркер
не привязан — привязать: curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \ -d '{"issueId":"WEB-025","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-08-25T19:28:49.744Z