WEB board

всеканоны и докиворкеры↗ iOS↗ Легаси
WEB-410 · Задача · — · web

[WEB370-L] Аварийный DR: Pi умерла внезапно

Закрыт P1 · важно ведёт: — эпик: WEB-395
Суть
Источник: WEB370PLAN2. Зависимости: WEB370-B,D,F,G,K. Оценка: 1 день. Fencing не должно зависеть от SSH к Pi.

--- 30.08 ~18:30 IST (Фабл): волна web370l ГОТОВА (eef5553a, wave/web370l): DR «Pi умерла внезапно» + синтетическая репетиция. Приёмку поставлю после разгрузки (в очереди 827 slowopen приоритетнее).

--- 30.08 ~19:00 IST (Фабл): вердикт волны web370l прочитан: ship-dark rehearsal PASS, production DR NO-GO до coordinator gates (fail-closed без подписанных PDU/router/ACL capsules — это ЗАДУМАННОЕ поведение, не дефект). Fence-контракт: ssh-timeout/ping/DNS/lease НЕ считаются fence proof — только PDU OFF или ACL deny. Приёмка 828-accweb370l поставлена в очередь A1 (репетиция своими руками + негативы: без capsules, битый hash, без backup receipt + split-brain одновременность).

--- 30.08 ~19:55 IST (Фабл): приёмка K2 (M1, независимая) = NO-GO/возврат автору: (P0) нет самостоятельной команды отката из состояния «Pi fenced, M1 не revoked»; (P0) два owner-GO не оформлены отдельными decision gate (pre-cutover/post-canary); (P0) forbidden-скан ловит placeholder/TBD в K2-отчёте; провенанс внешних артефактов не приложен (частично — недоставка координатора: M1-inbox не git и без A1-файлов; в K3 велено вшить sha256-таблицу с A1). Корректирующий круг 831-web370k3 в очереди A1 (наследие круга помечено). RPO/RTO-гейт остаётся честно открытым (WEB-082: WAL-архива нет). Тех-урок координатора: первый запуск K2-приёмки на M1 умер тихо — nohup codex без PATH (node только в ~/.nvm!), выяснилось через сутки по вопросу owner-а; перезапуск полным путём отработал за ~15 мин.

--- 30.08 ~20:30 IST (Фабл): круг K3 ГОТОВ за 16 мин (519ee69d, wave/web370k3): заявлено закрытие всех 5 находок K2 (отдельные rollback-команды вкл. «fenced+holder жив», два раздельных owner-GO gate PRE_CUTOVER/POST_CANARY с decision record, запретный скан пуст, provenance-таблица 7 артефактов с sha256, R0-R4 самостоятельными командами). Независимая приёмка 832-accweb370k3 запущена на M1 — в этот раз артефакты ДОСТАВЛЕНЫ (runbook sha c03b99d2 закреплён в брифе) и codex запущен полным PATH.

--- 30.08 ~21:10 IST (Фабл): приёмка K3 = NO-GO (третий круг!), но прогресс явный: скан чист, все 38 bash-блоков синтаксически валидны, оба gate структурно на месте; остались ошибки ПОРЯДКА: unfence-rollback без нового epoch/lease перед стартом Pi; R1b стартует target без unfence+проверки UNFENCED; PRE_CUTOVER NO-GO проверяет proof (test -s) ДО его создания; отчёт ссылался на недоставленный путь. По правилу «третья находка одного класса = менять устройство»: K4 (835) обязан ввести STATE-МАТРИЦУ CP×{fence,lease,holder,route,grant} и сверить каждый R-блок с ней самоаудитом. ТАКЖЕ: приёмка L (828) умерла тихо на A1 (сессия исчезла без отчёта) — перепоставлена кругом 836 с наследием.

--- 30.08 ~21:25 IST (Фабл): приёмка L (круг 836, наследие 828 подхвачено) = NO-GO, две находки: (1) rehearse.sh не гоняет РЕАЛЬНЫЙ dr-takeover.sh — его PASS фикстурная зелень (класс из памятки!); (2) нет single-flight по migration_id — два параллельных takeover оба доходят до PASS (split-brain, мой вопрос №4). Корректирующий круг 838-web370l2: репетиция реальным кодом с синтетическими capsules + flock-лок с REFUSED_CONCURRENT-негативом. K4 (state-матрица) готов — приёмку поставлю на M1 следующим слотом.

--- 30.08 ~21:55 IST (Фабл): круговорот сходится. K4-приёмка: K3-находки ЗАКРЫТЫ, матрица принята структурно, bash 38/38; NO-GO по одному классу — не все поля матрицы проверяются исполнимо в R0/R1/R1b/R2/R4 (перечислено построчно) + «blocker-ссылка» оказался МОИМ артефактом доставки (переименовываю файл → ломаю относительные ссылки автора; урок в память delivery-must-preserve-author-paths). K5 (842) в очереди: точечные проверки полей + честный самоаудит + правило ссылок. L2: автор закрыл оба blocker-а (репетиция реальным dr-takeover.sh + single-flight) — приёмка 841 с негативами (битая capsule, параллель, kill -9 посреди лока). receiptroutes2: фикс готов (13f8c80a) — приёмка 840 (вкл. мусорный receipt).

--- 30.08 ~22:15 IST (Фабл): L2-приёмка: содержательное ядро ПРИНЯТО (репетиция реальным dr-takeover.sh; битая capsule режется; single-flight даёт ровно один PASS + REFUSED_CONCURRENT), NO-GO только по lifecycle лока: не снимается после PASS и после kill -9 → migration_id клинит навечно (негатив №4 брифа сработал). Круг 843-web370l3: снятие на штатном выходе + безопасный перезахват сиротского лока (pid+kill -0, atomic, журнал) + гонка перезахвата. K5 готов (6b4bf216) — приёмка 844 на M1 запущена, пакет доставлен С СОХРАНЕНИЕМ авторских путей (k5pkg/, урок применён).

--- 30.08 ~22:35 IST (Фабл): L3 (lock lifecycle) готов от автора — приёмка 845 в очереди (добавлен новый класс: pid-reuse при перезахвате сироты). K5-приёмка: R0/R1/R1b/R2 точечные находки ЗАКРЫТЫ; остались ровно ТРИ узких (R4: fence вместо read-only readback — blocker; R3: нет входного route-readback; R1b: не проверяется active_epoch) → K6 (847) в очереди. Сходимость очевидная: 5→4→3 находки по кругам, все новые — уже.

--- 30.08 ~22:55 IST (Фабл): L3-приёмка: сценарии 1-4 PASS, единственный F-1 (мой новый класс pid-reuse): живой ПОСТОРОННИЙ процесс с переиспользованным PID считается держателем → ложный REFUSED (не вечный клин — после смерти процесса лок берётся). Круг 849-web370l4: сверка identity держателя (pid + start-время процесса против start_ts owner-файла). K6 готов (9854b1f2) — приёмка 848 на M1 запущена (пакет k6pkg с авторской структурой).

--- 30.08 ~23:30 IST (Фабл): 🏁 ПРИЁМКА K6 = GO — СТУПЕНЬ K ЗАКРЫТА (шесть кругов: K→K2 rewrite→K3 порядок→K4 state-матрица→K5 поля→K6 три точечных; финальный ранбук wt-847-web370k6@9854b1f2, все находки всех кругов закрыты, судья M1 независимый каждый раз). Эволюция кругов вся в этом тикете выше. L4 (identity держателя: pid+start-ts) готов от автора — финальная приёмка 850 в очереди (вкл. регресс кругов 1-3 и допуск дрейфа). После GO L → ВОЛНА N (полная репетиция переезда) — последняя буква перед O.

--- 31.08 ~00:40 IST (Фабл): 🏁 ПРИЁМКА L4 = GO, «СТУПЕНЬ L ГОТОВА К N» (a9ddd25f; все сценарии кругов 1-4 реально прогнаны: сироты мёртвый/живой-чужой pid, честный держатель, дрейф, kill -9, гонка перезахвата). ЛЕСТНИЦА: K✅(6 кругов) L✅(4 круга) → ВОЛНА N ЗАПУЩЕНА (854): полная ship-dark репетиция по принятому ранбуку K6 с принятым L4-инструментом, оба gate-а в GO и NO-GO ветках, rollback-репетиции R1b/R4, явный список O-зависимостей. O — только с owner-GO. 14/15 при GO N.

--- 31.08 ~01:00 IST (Фабл): 🏁 N-PASS! Полная ship-dark репетиция переезда пройдена (wave/web370n, ранбук 76e7756b): CP0→CP7, оба gate-а в обеих ветках, rollback R1b/R4 со state-проверками; production activation честно NO-GO (синтетика ≠ прод-доказательства). Независимая приёмка 855 (перепрогон + порча receipt-негатив + полнота O-списка). При GO: ЛЕСТНИЦА 14/15, остаётся только O — реальный переезд с owner-GO.

--- 31.08 ~01:20 IST (Фабл): приёмка N: сама репетиция ВОСПРОИЗВЕДЕНА (exit 0, PASS, sha сверены, негатив с порчей receipt работает), NO-GO только по полноте O-инвентаря против runbook §13 (не названы: production B4 boundary, C/native provenance, freeze/unfreeze controller). Узкий круг 858 — дополнить список построчной сверкой §13. Механика лестницы вся готова.

--- 31.08 ~01:45 IST (Фабл): УКАЗАНИЕ OWNER (20:39): перед шагом O — финальный адверсариальный аудит «злым sol на максималках» (gpt-5.6-sol xhigh) всего пакета миграции (ранбук K6 + L4-инструмент + N-отчёт). Встроено в план: N-GO → sol-аудит → закрытие его находок → O с owner-GO. Записано в память (migration-final-audit-by-sol).

--- 31.08 ~02:45 IST (Фабл): N2 готов (8a861e52, O-инвентарь дополнен) — финальная приёмка 865 запущена на M1 (пакет n2pkg, построчная сверка §13). При GO: N принята → sol-аудит на максималках (указание owner) → O.

--- 31.08 ~03:10 IST (Фабл): 🏁 ПРИЁМКА N2 = GO — «N ПРИНЯТА»: все 10 пунктов §13 в O-инвентаре с O-only проверками и receipt-доказательствами. ЛЕСТНИЦА 14/15. По указанию owner-а запущен АДВЕРСАРИАЛЬНЫЙ SOL-АУДИТ (867, gpt-5.6-sol xhigh, DISPATCH-переопределение модели): ломать пакет по 6 осям (рассинхроны вне матрицы, дыры между CP, replay receipts, невозвратные состояния, полнота O, человеческий фактор). После закрытия его находок — O с owner-GO.

--- 31.08 ~03:55 IST (Фабл): ⛔ SOL-АУДИТ (867, gpt-5.6-sol xhigh, 11 мин): STOP/NO-GO перед O — 20 находок (8×P0/10×P1/2×P2), owner был прав требуя злого аудитора: шесть кругов Luna-приёмок happy-path+дискретные NO-GO доказали, а crash-consistency/anti-replay/межшаговые состояния — НЕТ. Главный контрпример: штатный CP5 → half-delivered (holder=a1, lease есть, marker нет) → checker валит шаг и НИ ОДИН R-блок не стартует; M1 умер после durable commit → crash-lock навсегда. Волна K7 (870) заряжена: все 8 P0 (атомарность lease+marker, R-предусловия на ПОЛНОЕ пространство состояний, revoke мёртвого M1, anti-replay nonce), после — ре-аудит sol-ом. Урок в копилку: adversarial-модель на финале обязательна, Luna-приёмки его не заменяют.

--- 31.08 ~05:40 IST (Фабл): K7 АВТОРСКИ ГОТОВ: заявлено закрытие всех 8 P0 — ключ: CP5 больше не live-activation, M1 коммитит authority в durable journal → immutable lease+marker generation → ОДИН atomic swap current; checker читает только generation; смерть M1 → revoke по journal. РЕ-АУДИТ SOL (881, sol xhigh) заряжен: проверка каждой P0 по исполняемому тексту + охота на НОВЫЕ поверхности (journal corruption, GC generations, swap при полном диске) + финальный вердикт GO-к-O/STOP.

=== КАРТА ДОКУМЕНТОВ ЛИНИИ (лестница K/L/N/O; все пути на A1 /home/ubuntu/waves/, M1 ~/waves-inbox/) ===
• Ранбук (эволюция): K2 24d22921 → K3 519ee69d → K4 317cb5d7 (+state-матрица) → K5 6b4bf216 → K6 9854b1f2 (ПРИНЯТ) → K7 wt-870-k7 (durable journal+atomic swap, на ре-аудите). Файл: wt-870-k7/WEB409K-RUNBOOK.md.
• Приёмки K: ACCWEB370K2/K3 (M1), ACCWEB370K4/K5/K6 (M1, пакеты k5pkg/k6pkg).
• DR-инструмент L: wt-849-l4 (a9ddd25f, ПРИНЯТ) — dr-takeover.sh, rehearse.sh; отчёты WEB370L{,2,3,4}-REPORT + ACCWEB370L{,2,3,4}.
• Репетиция N: wt-858-n2/WEB370N-REPORT.md (8a861e52, ПРИНЯТА ACCWEB370N2 на M1).
• Sol-аудит: SOLAUDIT-REPORT.md (STOP 8P0/10P1/2P2) → K7-ответ WEB370K7-REPORT.md → ре-аудит SOLREAUDIT-REPORT.md (в работе).
• Брифы кругов: очередь A1 queue/8xx-*.md. Провенанс телефонии: lz-artifacts (A1 telephony-lz/releases + Hetzner).

📖 Правила обогащения этого тикета: WEB-449 (канон для любого агента).

--- 31.08 ~06:10 IST (Фабл): sol-переаудит (881) УПАЛ на защитном фильтре OpenAI (формулировка «adversarial/ломать» → cybersecurity refusal кодекса). Перезапущен как 886-solverify2 в нейтральной инженерной рамке (reliability review DR-ранбука, покруговая верификация 8 пунктов надёжности + crash-consistency журнал/swap + новые риски). Урок: sol-брифы формулировать инженерно, без offensive-лексики.

--- 31.08 ~07:20 IST (Фабл): sol reliability-верификация K7 (886, нейтральная рамка — прошла фильтр) = НУЖЕН ЕЩЁ КРУГ: K7 закрыл узкий контрпример (immutable generation + atomic swap symlink), но из 8 P0 — 1 условно, 3 частично (A1/A2/D1), 4 ОТКРЫТЫ (A3 partial Pi fence, B2 durable SAFE_OFF, E1 coordinator crash-resume, F1 execution-host boundary). Корень: primitives добавлены РЯДОМ с K6, не единый executable flow (CP0 source-ит K4-старьё, CP2 зовёт старый fence по старому SHA). Круг K8 (899): единый flow, journal+swap как несущая КАЖДОГО перехода. O по-прежнему заблокирован до чистого sol + owner-GO.

--- 31.08 ~10:30 IST (Фабл): K8 сам объявил NO-GO: часть P0 закрыл, но остаток не добит + среда мешала (нет node_modules для линта; отвлёкся на activation-mismatch, который к ранбуку не относится). Круг K9 (914): закрыть ОСТАТОК единым flow, NODE_PATH для линта дан, activation-гейт явно исключён из зоны. После K9 — снова sol-верификация.

--- 31.08 ~11:55 IST (Фабл): K9 отработал — production activation остаётся NO-GO до controlled install + owner/IC approval + внешних gates (это ОЖИДАЕМО и правильно: ship-dark). Читаю таблицу «что принято из K8 / что закрыто в K9» и ставлю следующую sol-верификацию.

--- 31.08 ~23:35 IST (Фабл): ⚠️ МОЙ ПРОКОЛ, признан owner-у: K9 закончил ещё в 00:53, а sol-переверификацию я НЕ запустил (обещал «сразу после текущей волны», потом переключился на денежный инцидент и забыл). Запущена сейчас: 943-solverify3 (sol xhigh, нейтральная инженерная рамка) — покруговой вердикт по всем 8 пунктам надёжности + crash-consistency журнал/swap + новые риски K8/K9. Это последний шаг перед O (с owner-GO). УРОК: держать «ожидающие запуска» шаги в явном списке тика, иначе теряются за инцидентами.

--- 01.09 ~00:15 IST (Фабл): sol-верификация после K9 = НУЖЕН ЕЩЁ КРУГ (не PASS). Закрыты end-to-end 3 из 8: A1 atomic pair, C1 replay, D1 parallel lanes. НЕ закрыты 5: A2 stale crash-lock, A3 partial Pi fence, B2 durable SAFE_OFF, E1 crash-resume, F1 execution-host boundary. Признано полезным из K8/K9: generation-публикация lease+marker, receipt↔transaction ID, hash-chain журнала, SAFE_OFF lanes с дедлайнами. ЧЕТЫРЕ КОНТРПРИМЕРА (все внутри crash/recovery boundary, в «известные ограничения» не выносятся): (1) SAFE_OFF выдаётся при 9 readback'ах с RC 1 — код смотрит на старые непросроченные receipts, не на readback.result; (2) FLOW-TERMINAL ставится по одному RC 0 recovery, подписанный receipt и lane vector не предусловие (доказано noop-тестом); (3) torn tail → следующий append клеится к оборванным байтам → порча середины журнала; (4) durable COMMITTED перестаёт быть resumable после истечения ВНЕШНЕГО receipt. Плюс: R2 не передаёт expected-host/fence-controller/M1 key mapping, а WEB370K9-flow.json и containment lanes отсутствуют в коммите. Круг K10 (944) заряжен с таблицей «пункт→как закрыт→тест». O по-прежнему заблокирован.
Чем закрывается (приёмка)
Game-day: fence without Pi SSH; restore ≤3m; app/audio к минуте 9, adapters к 11, route к 13, canary/partial service к 15; stale snapshot заметен и блокирует unsafe activation.
Доказательства
[2026-08-27 15:40Z] web410l в очереди A1: DR-дизайн без ssh-fence (провайдер-уровневый fence, split-brain проверка, RTO против 15м), скрипты dry-run.
[2026-08-27 16:10Z] WEB410L DONE: DR-дизайн без ssh-fence (провайдер-fence), split-brain путь описан, RTO-раскладка (restore<=3м, alert->canary<=12м против цели 15м), негативы corrupt/missing-WAL в плане game-day. Design complete / production NO-GO до 2х DR-репетиций. -> review.
[2026-08-27 20:29:19Z tickacc5] ВЕРДИКТ: частично доказано
Что проверил: открыл WEB410L-REPORT.md; выполнил bash -n web410l-dr/dr-takeover.sh web410l-dr/dr-verify.sh; проверил требования receipts/capsules, no_ssh_to_pi, snapshot, lease и live gates.
Что увидел: syntax rc=0 и fail-closed design подтверждены, но report фиксирует P0 WEB410L-P0-PI-LEASE-GATE, отсутствие Pi gate/mask/reboot proof, exact WEB400B inputs и двух DR game-days. Production GO нет.
Отрицательный тест: takeover/verify без обязательных capsule/receipt inputs должен быть отвергнут; реальный DR/restore/provider cutover не запускались.
Чего не хватает: Pi unit gate + persistent mask и reboot/renew-loss proof, signed external fence receipts, exact WEB400B capsules, два isolated game-day с restore <=3 min и alert→canary <=12 min.
[2026-08-27 22:07 UTC EVID409410] Read-only recovery-readiness audit completed; no DR apply, restore, fencing, provider action, systemd start/stop, reboot, Pi mutation, M1 mutation, or git action performed.
Report: /home/ubuntu/waves/EVID409410-REPORT.md; sha256=80b56a8c95421d380ef8f183ce838ddbb87ce4988575b7bdaf06b50e07a43f2b.
Both web410l-dr scripts exist mode 0755 and bash -n rc=0, but web410l-dr has no capsules.sha256 and none of the 19 required capsule executables. Apply therefore has no pinned executable input.
Production recovery inputs are not proven: no WEB400B snapshotctl/signed manifest/off-host encrypted copy; A1 backup/state dirs are empty; Pi backup path and current fence/lease/mask/renew state cannot be checked because Pi SSH timed out or was denied through proxy; M1 state/key/delivery cannot be checked because M1 SSH timed out or was denied. A1 has only named secret files, not a complete portable production snapshot; values were not read.
Available gate14bk artifacts are same-host synthetic tests, not Pi/WEB400B. Latest successful local base receipt is 2026-08-24T02:34:10Z; attempts on 2026-08-25..27 rc=68. Latest local restic scheduled receipt is 2026-08-27T03:02:50Z rc=0 but remains same-host test-only. Latest WAL push is 2026-08-24T20:28:37Z; wal-verify at 2026-08-27T04:02:57Z reports unrestorable_bases=3 and problems=3.
Current A1 has web401c-a1-arm64-20260827 and clean-verify copy, but required web370-a1 is absent; available=81893122048 B < required=85899345920 B. ACTIVE, lease, accepted-epoch and M1 pubkey are absent.
WEB412N supplied only local synthetic evidence (barrier/rollback about T+29..30s, mock app/audio/adapters, fixture DB, provider not invoked); synthetic lease key files exist locally but are not M1 production keys. No two isolated production DR game-days, signed fence receipts, production canary, provider route proof or reachable rollback package.
Verdict: NO-GO. RPO <=5m is not achievable/proven; same-artifact RTO <=15m is not achievable/proven; rebuild <=1h is not currently achievable/proven and is not the allowed incident path. Local test seconds do not count as production RPO/RTO.

## 2026-08-28 ~12:15Z — взято в работу (координатор Фабл)
Волна `web410` — аварийное восстановление при внезапной смерти малинки. Опирается на доказанное координатором: удалённая копия **читается** (объект скачан, `.sha256` сошлась, gpg-расшифровка успешна, внутри сегмент WAL 16 777 216 Б); базовые копии ежечасно; хранение 30 суток; **RPO измерен ≈218 с** при цели 300. Задача: порядок восстановления только из удалённого хранилища, что теряется кроме данных (звонки, комнаты, очереди, медиа, ключи), чего физически не хватит без малинки, честная оценка против целей владельца — **оценка без измерения доказательством не считается**.

[28.08 ~13:20Z Фабл] web410 сдана: аварийный сценарий готов, gate честный (нет PASS без timings.tsv, НЕ ПРОВЕРЕНО не превращается в успех). Доказано волной: remote WAL читается, RPO ≈218 с ≤ цели 300 с. Координатор снял **квитанцию §1.4 исполнением на малинке**: сегмент 0000000100000012000000B2 из сейфа → SHA sidecar совпал → gpg-расшифровка во временный + атомарный mv → ровно 16777216 байт → pg_waldump rc=0, 2396 записей, чистый SWITCH. Сейф не менялся (только get), следы вычищены. Квитанция: A1:/home/ubuntu/waves/pi-audio-facts-20260828.md (приложение). Осталось: реальное учение с timings.tsv (RTO ≤15 мин, пересборка ≤1 ч) — по процедуре WEB400B после её приёмки acc400b; инвентарь A1 по §3 (native-артефакты, секреты, systemd). Отчёт: A1:/home/ubuntu/waves/WEB410-REPORT.md.

[BOARDTRIAGE] 28.08 13:20Z: remote WAL прочитан, RPO около 218 с, квитанция pg_waldump успешна; RTO≤15m, rebuild≤1h и production fence game-day ещё не доказаны.
Лента
2026-09-02T13:45:59.925Z · Fable
[A1 13:50 Фабл] Сверка состояния для нулевого агента: ступень L (DR «Pi умерла») ЗАКРЫТА 31.08 (L4 GO a9ddd25f: fence только PDU OFF/ACL deny, single-flight по migration_id с корректным lifecycle лока и identity держателя pid+start-ts; репетиция реальным dr-takeover.sh), ступень N (полная ship-dark репетиция переезда) PASS 76e7756b. Остаток — только O (реальный cutover, WEB-413) с owner-GO после C (провенанс Asterisk/opus — волна 1225 на M4, WEB-401), production B4 boundary и freeze/unfreeze controller (перечислены в O-инвентаре §13). Тикет переводится в done как ступень L; хвосты O живут в WEB-413.
Воркер
не привязан — привязать: curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \ -d '{"issueId":"WEB-410","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-02T13:45:59.971Z