WEB board

всеканоны и докиворкеры↗ iOS↗ Легаси
WEB-282 · Эпик · billing · web

ЭПИК: миграция Oracle A1 + включение учёта (ступени 1-6)

В работе P0 · горит ведёт: —
Суть
## План ступеней 5–6 (волна 3682, 13.09 — append, старый текст сохранён ниже)

Ступени 5 и 6 до этой волны не начинались и в карточке не было ни плана, ни критериев. Волна 3682 расписала обе пошагово. Полные планы: `3682-billing-stages-5-6-plan-out/STAGE-5-PLAN.md`, `STAGE-6-PLAN.md`; решения владельца простым языком: `OWNER-DECISIONS.md`; пробелы/противоречия: `NOTES.md`.

### Что это (восстановлено из карточки; где размыто — помечено ПРЕДЛОЖЕНИЕ)
- **Ступень 5 = ключи owner (активация/подпись) + когорта 25.** Механика owner-ключа = внешняя sidecar-аттестация `SPEND_ACTIVATION_ATTESTATION_PATH` + `SPEND_RUNTIME_ARTIFACT_SHA256`, fail-closed (комментарий 16.08 id=280, «требование №5 аудитора»); сейчас всё подписано РЕПЕТИЦИОННЫМ ключом, реальный ключ владельца не активирован. Когорта 25 = R4 §15 шаг 7 «когорта 25 + повышение по метрикам» (аудит 04.09). ПРОБЕЛ: кто эти 25, критерий отбора и механизм допуска — в карточке НЕТ → предложение в STAGE-5-PLAN.md.
- **Ступень 6 = полный катовер (формальный отчёт + когорты).** R4 §15 шаг 8: 24h/72h reviews и reviews после когорт. ПРОБЕЛ: механизм «полного» перевода и состав формального отчёта не расписаны → предложение в STAGE-6-PLAN.md.
- **Порядок:** флип enforce (п.а критерия) → ступень 5 → ступень 6. Порядок «флип раньше ключей owner» явно в карточке не вписан — помечен как предложение.

### Ступень 5 (коротко)
Готовит координатор: состав 25, механизм допуска, проверка вооружённых P01/P11/reconcile/`accounting_unhealthy` по `/proc/<pid>/environ`, kill-switch одним флагом. Владелец лично: активирует реальный ключ на ноутбуке, подписывает activation-аттестацию под prod artifactSHA256, отдаёт только подпись. Координатор: ставит аттестацию, открывает ровно 25, окно наблюдения ≥24 ч (0 расхождений reconcile, 0 `accounting_unhealthy`). Откат — kill-switch в бесплатное. Авто-остановка при превышении потолка — `accounting_unhealthy`/containment deny, сигнал владельцу+координатору (TG).

### Ступень 6 (коротко)
Порог «когда можно» — только после зелёного окна когорты 25 + 24h/72h reviews + решения владельца. Расширение по когортам (25 → следующая → все) с 24h/72h review после каждой, затем полный катовер всех + формальный отчёт (п.в критерия). Kill-switch сохраняется на всех ступенях.

### Пределы расходов (чисел в карточке НЕТ — решает владелец)
Механизм есть и вооружён: spend-containment, P01 admission, P11 журнал, reconcile (600 с), `accounting_unhealthy`, `RateLimitCounter`. Предложены: per-аккаунт дневной потолок + агрегатный дневной потолок когорты/платформы + несгораемый жёсткий потолок; при превышении — fail-closed и сигнал владельцу+координатору. Числа — решение владельца (OWNER-DECISIONS.md п.3–4).

### Критерий закрытия эпика (из тела 13.09, без изменений)
(а) флип enforce принят отдельным GO аудитора + решением owner; (б) ступень 5 выполнена; (в) ступень 6 выполнена (полный катовер с формальным отчётом); (г) дети WEB-082/470/566 и перепроверяемые WEB-300/306/032/DNS закрыты или осознанно вынесены. Каждый пункт — ссылкой на факт (PROD-FACTS, «Правила доказательства»).

---

## История (старый текст, сохранён ниже)

---

## история (тело до 13.09.2026)

# WEB-282 — ЭПИК: миграция Oracle A1 + включение учёта (ступени 1–6)

Правила обогащения: WEB-449. Это предложение нового тела карточки — координатор вставляет его целиком в `body` (append, старый текст сохранить).

---

**Якорь (13.09.2026):** прод = **l115j** `133fe00c` (посажен 08:50Z; линия l115g → l115h → l115i → l115j).

## СУТЬ
Эпик объединяет две вещи: (1) переезд прода с малинки Pi на Oracle A1 с автономным контуром; (2) включение платного учёта (billing) по лестнице ступеней 1–6 — от тёмной посадки до полного катовера. Ступени — это лестница включения учёта, переезд давно закрыт.

## ГДЕ МЫ (13.09)
**Переезд — ЗАВЕРШЁН.** Прод автономен на A1, релиз l115j `133fe00c`; БД (Postgres :55432) и Redis локально на A1; малинка Pi = дев. Двухнодовость: A2 пассив + PG16-standby (лаг ~0). Бэкапы: Hetzner WAL-поток + почасовой base. DNS nb/sixbyy.com → A1.

**Учёт — рантайм-контур открыт, но формальный флип enforce НЕ принят.**
- **Ступени 1–3 (тёмная посадка) — ✅.** Посадка b4846087 на Pi, attestation.ok=true, mode=off.
- **Ступень 4 (ре-гейт enforce) — инженерно сдана, флип формально НЕ принят.** Ре-гейт собран и B-пакет закрыт: B1 16586dae, B2 (sidecar-аттестация, fail-closed 10/10) PASS, B5 runbook отката sha 7a66c9fa; пакет GPTPRO-MONET-STEP4-REGATE-20260816.zip. **Флип enforce ждёт ОТДЕЛЬНОГО GO аудитора + решения owner — этот GO не выдан.** Рантайм уже `enforce_ready` (`paidReady=true`), вооружены P01 (admission), P11 (журнал платных операций, оба бэкенда), P19 (гейт совместимости миграций), P22 (медиахранилище R2).
- **Ступень 5 (ключи owner + когорта 25) — не начата.**
- **Ступень 6 (полный катовер) — не начата.**
- **БД на least-privilege ролях с 12.09 22:15Z:** приложение ходит ролью `web` (НЕ суперпользователь); посажены роли `web` / `web_migrator` / `web_backup` / `web_owner` (NOLOGIN) / `analytics_readonly` (см. `ops/sql/web078_roles.sql`, `ops/sql/analytics_readonly_role.sql`).

## ХРОНОЛОГИЯ (сжатая, детали — в истории карточки)
- 16–17.08: ре-гейт ступени 4 — b2fix → b2sidecar → b2prod → b2pack3 (PASS); B2 закрыт; B5 runbook.
- 21.08: посадка 30 (v4-504af77f) со второй попытки; fail-closed boot-контракт (WEB-307); гейты 1,2,3,7,8,9,10,11,12,13.
- 31.08–01.09: переезд на A1 — релиз l82 автономен (paidReady TRUE, БД+Redis локально); бэкапы Hetzner (ретенция починена после инцидента); DNS sip/nb → A1.
- 02–03.09: DR-репетиция фазы 1 на A2 (RPO 3–6 мин, RTO ≈17 мин; 5 находок, главная WEB-469); дев-стенд A2 (owner GO); l93/l94; P11 → P01.
- 04–07.09: l103 → l113o; батарея ролей r44 = 47/50.
- 10.09: P11 вооружён на ОБОИХ бэкендах без посадки; P19 принят (остановил сборку l114s); P22 (R2) закрыт; прод l114y.
- 12.09 22:15Z: прод-БД переведена на роль `web` (не суперпользователь).
- 13.09: посадка l115j `133fe00c` (08:50Z); роли БД посажены; таймер hetzbk-publish-current; дворники диска A1/A2.

## КАРТА ДОКУМЕНТОВ
- Карта эпика: M1 `board/specs/MIGRATION-EPIC.md` (обновляется координатором).
- Норматив: `~/Downloads/prodplan-20260810/PROD-MIGRATION-PLAN-R4.md` (Intel), §7 гейты 0–14, §15 шаги 1–8.
- Аудит гейтов: M4 `/Users/milamarty/work/MIGAUDIT-REPORT.md`.
- Ре-гейт ступени 4: `/Volumes/M4Ext/ops/step4-regate/` (B1/B2/B3/B5 + B2-RUNTIME/), пакет `GPTPRO-MONET-STEP4-REGATE-20260816.zip`.
- Бэкап-контур: WEB-082 (`GATE14BK-REPORT` на A1), исходники `infra/hetzbk/`.
- Роли БД: `ops/sql/web078_roles.sql`, `ops/sql/analytics_readonly_role.sql`, `docs/runbooks/DB-LEAST-PRIVILEGE-ROLES.md`.
- Карта малинки (ступень A): A1 `WEB399E-REPORT.md` + `pi-inventory-full.md` + `pi-proc-map.md`.

## ОСТАТОК (с ответственными)
1. **Флип enforce** — отдельный GO аудитора + решение owner. Отв.: аудитор + owner.
2. **Ступень 5** — ключи owner (активация/подпись) + открытие когорты 25. Отв.: owner.
3. **Ступень 6** — полный катовер (формальный отчёт + когорты). Отв.: owner + координатор.
4. **WEB-082** — бэкап-контур: де-факто WAL+base есть, приёмка с restore-drill НЕ сдана. Отв.: координатор + аудитор.
5. **WEB-470** — тёплая копия/DR: репетиция 1c с секундомером и authority-pack не закрыты. Отв.: координатор.
6. **WEB-566** — витрина/бета: решение по email-верификации (включить транспорт или снять требование для беты). Отв.: owner.
7. **Перепроверить с 01.09** (не подтверждено на 13.09): WEB-300 (privacy кэша), WEB-306 (OCI ingress 0.0.0.0/0, parked), WEB-032 (правила A1), DNS-зона+почта → Cloudflare (шаг owner: NS у регистратора).

## КРИТЕРИЙ ЗАКРЫТИЯ
Эпик закрывается, когда выполнены все: (а) флип enforce принят отдельным GO аудитора + решением owner; (б) ступень 5 выполнена (ключи owner + когорта 25 открыта); (в) ступень 6 выполнена (полный катовер с формальным отчётом); (г) открытые дети (WEB-082/470/566 и перепроверяемые WEB-300/306/032/DNS) закрыты или осознанно вынесены в отдельные тикеты.

## KNOWN ISSUES / ТРАБЛШУТИНГ
- **Ловушка «флип vs рантайм»:** рантайм `enforce_ready` / «платный контур открыт» НЕ равен формальному флипу ступени 4 — флип считается принятым только отдельным GO аудитора + решением owner. Не закрывать ступень 4 по posture.
- **Аттестационный манифест env-зависим** (собирается из BUILD, не из source): собранный в другом окружении манифест не сойдётся.
- **Standalone однажды не содержал proof-файлы** `src/lib/billing/terminal*` → enforce ready = 503 ENOENT. Проверять состав распакованного standalone, а не только его наличие.

---

## история (тело до 13.09.2026)

Карта эпика: board/specs/MIGRATION-EPIC.md (обновляется координатором). Кратко: ст.1-3 ✅ (тёмная посадка b4846087 на Pi, attestation.ok=true, mode=off), ст.4 в РЕ-ГЕЙТЕ (аудитор: NO-GO на флип / GO на шаги 1-2; B1 закрыт 16586dae; B2-репетиция на А1 нашла настоящий дефект — standalone не содержит proof-файлы src/lib/billing/terminal*, enforce ready=503 ENOENT → волна b2fix на А1: фикс упаковки + пересборка linux/arm64 + полная репетиция; B5 runbook отката написан, sha 7a66c9fa), ст.5-6 не начаты. Флип enforce ТОЛЬКО по отдельному GO аудитора + решению owner. Связанные: WEB-032 (инфра А1).

## 20.08 ~21:10 Ревизия нити по вопросу owner: «миграция готова» было про Gate0, НЕ про нить. Полная карта дыр — в спеке MIGRATION-EPIC.md (таблица §15 R4 vs факт). Кратко: ✅ только ступень 2 (spend-guard GO) + куски 1 и 3; НЕ начаты: /data-контракт+WAL-G/restic бэкап с restore-drill (решение owner: третья копия = Pi, без Hetzner), immutable candidate + RPO/RTO репетиция, юридика/privacy (AI Act!), домен/DNS/почта (CF+Resend), катовер, когорты. Телефония/видео в релиз 1 НЕ едут по R4 §13 (осознанно). План: ~/Downloads/prodplan-20260810/PROD-MIGRATION-PLAN-R4.md (Intel).

## 20.08 ~22:50 ПОЛНАЯ СВЕРКА (волна migaudit, sol, по уликам): launch-гейты §7 — ПРОЙДЕН 1/15 (Gate 0), ЧАСТИЧНО 8, НЕ НАЧАТО 6. Шаги §15 — 1/8 (шаг 2), частичны 1/3/4/5. Методика: пруф = вердикт/COVER/runtime-receipt, привязанный к точному объекту приёмки; заголовки и status=done доски пруфом НЕ считались. Полный отчёт: M4 /Users/milamarty/work/MIGAUDIT-REPORT.md. Owner уведомлён (msg 12477/12478).

## Трейл миграции (21.08)
- Ветка посадки-30: `landing30` (worktree A1 /home/ubuntu/waves/wt-landing30, от serving f1e49bca), слито 6 веток / 88 файлов, проверка дубликатов ключей в словарях: 0.
- Живой статус смены: `~/Downloads/OPS-STATUS-LIVE.md` (ноутбук) + копии на M1 `~/livepush/` и M4 `/Users/milamarty/work/`.
- Паспорт проекта: https://bugs.wool2.online/passport (обновлён 21.08: serving arm64-f1e49bca, статы из свежей ветки, дельты в stats-history.json).
- Леджер ревизора: `/Volumes/M4Ext/ops/reviser-ledger/` (пакеты + аудит-бандлы, sha сверены).
- Норматив: `~/Downloads/prodplan-20260810/PROD-MIGRATION-PLAN-R4.md` (Intel), §7 гейты 0-14, §15 шаги 1-8.
- Полный аудит: M4 `/Users/milamarty/work/MIGAUDIT-REPORT.md` (1/15 пруфом, 8 частично, 6 не начато; §15 = 1/8).
- Тикеты гейтов: WEB-069…082. Сделано за 21.08: гейт 12 (A1 `~/waves/GATE12-REPORT.md`, 418 строк расписок), гейт 11 (`GATE11-VULN-SCAN.md`), гейт 9 (`GATE9-UPLOAD-INVENTORY.md` → фикс в l30upload `28f6f33d`), гейт 4 драфты (`legal-drafts-20260820/` + OWNER-DECISIONS.md).
- В работе: гейт 10 (роли БД, волна gate10), гейты 7+8 (origin-lock + инвентарь секретов, волна gate78), гейты 5+14 (репетиция переезда на A1, волна gate514 → `~/waves/GATE514-REPORT.md`).
- Прошлые репетиции (owner помнил верно): proof-БД на A1 `nc_migration_proof`, `meeting_rooms_migration_proof_w314_*`; пакет `/Volumes/M4Ext/ops/packages/step4-rehearsal/` (README-A1.md) — это была репетиция ЛИНИИ УЧЁТА, не полного переезда.

## 21.08 ~09:50 СВОДКА ПО ГЕЙТАМ (после ночной серии волн)
| гейт | тикет | было 20.08 | стало 21.08 | пруф |
|---|---|---|---|---|
| 1 вебхуки fail-closed | WEB-069 | частично | ✅ ДОКАЗАН на проде | GATE3579-REPORT §1 |
| 3 invite-gate | WEB-071 | частично | ⚠️ выключен на проде + флаг сам по себе не включает | GATE3579-REPORT §2 |
| 5/14 переезд+restore | WEB-082 | не начат | замеры получены, гейт НЕ закрыт из-за P0 WEB-091 | GATE514-REPORT |
| 7 origin-lock | WEB-075 | не начат | ✅ конфиги+пробы готовы (не применены) | GATE78-REPORT |
| 8 санация секретов | WEB-076 | не начат | ✅ инвентарь+чеклист готовы | GATE78-REPORT |
| 9 upload-лимиты | WEB-077 | частично | ✅ закрыт кодом (ветка l30upload 28f6f33d) | GATE9-UPLOAD-INVENTORY |
| 10 роли БД | WEB-078 | не начат | ✅ 4 роли, 17/17 на живом Prisma, forward-compat | GATE10-REPORT |
| 11 vuln-скан | WEB-079 | частично | ✅ критичные закрыты; xlsx без фикса → замена отдельно | GATE11-VULN-SCAN |
| 12 host hygiene | WEB-080 | не начат | ✅ применено на A1, доступ не потерян | GATE12-REPORT |
| 13 OCI truth | WEB-081 | частично | ⛔ ждёт координатора (креды только на ноутбуке) | GATE3579-REPORT §3 |
| 4/§15.6 юридика | WEB-072 | не начат | ✅ 8 драфтов + OWNER-DECISIONS | legal-drafts-20260820/ |
НОВЫЕ БЛОКЕРЫ, найденные самими проверками: P0 WEB-091 (миграции не поднимают БД с нуля) и врущие указатели прод-релиза (отдельный тикет).
Не начаты по-прежнему: платный ARM64-fallback и открытие когорты 25 — оба требуют самого переезда.

## 21.08 01:00 — ПОСАДОЧНАЯ ВЕТКА ТРИДЦАТОЙ СОБРАНА: `landing30b` HEAD `4ec03987`
Отчёт: A1 `/home/ubuntu/waves/L30B-MERGE-REPORT.md`. Итог: **99 файлов, +9428 / −365**, пять веток слиты **вручную, по одной, без единого конфликта**, без `-X theirs`/`-X ours`. `tsc --noEmit`: **2185 → 2185**, распределение ошибок по (файл, код TS) идентично до и после. Дубликатов ключей нет.
Порядок слияния и почему такой: `archp0` (инфраструктура БД) → `fcsrc2` (платный путь, чтобы пин-чексуммы миграций WEB-084 легли на уже расширенную цепочку) → `gates2` → `pdfport` → **`migfix` последним намеренно**: он единственный от другой базы (`f1e49bca`), и, идя последним, его гейты БД (`fresh-db-check`, `prisma-model-sweep`) проверились против дерева, где уже лежат две новые миграции archp0.
Попарное пересечение изменённых файлов посчитано ДО первого слияния: пусто во всех 10 парах, и `migfix` ∩ (88 файлов landing30 после f1e49bca) тоже пусто. Отсюда ноль конфликтов — пересечения были не по файлам, а по смыслу, поэтому работа волны ушла в проверки, а не в разрешение конфликтов.
⚠️ **Уточнение состава**: ветка `gates2` фактически несёт **1 коммит, 1 файл, только документацию** (`docs/PASSPORT/UNPROTECTED-AUDIT.md`, +109, вердикт по 61 маршруту UNPROTECTED). Сам код гейтов уже был в `landing30` через `l30gates` (`f4bb595c`). Не потеря — уточнение.
Пересборка артефакта запущена координатором (не волной): `/home/ubuntu/waves/build30b.sh`, лог `build30b.log`, квитанция `build30b.rc`. После сборки — греп байтов на маркеры и посадка по полному чеклисту.

## 21.08 — ГЕЙТ 13 ЗАКРЫТ РАСПИСКАМИ, НАЙДЕНА ДЫРА В ГЕЙТЕ ПЕРИМЕТРА
Гейт 13 (OCI truth, WEB-081) снят координатором с ноутбука — единственного места с кредами. Подтверждены фактом: home region **IAD, одна подписка**; A1 **4 OCPU / 24 GB / 4 Gbps**; диск — **boot volume 200 GB VPU/GB=10**, NVMe у shape нет (ревизор был прав, аудит ошибался); лимиты block-storage 61 ТБ на AD; MFA владельца включён.
Расчётный потолок тома **12 000 IOPS / ≈96 МБ/с** — это расчёт по формуле OCI, не измерение, и он же кандидат в узкое место раньше CPU.
⚠️ Попутно найдено: **облачный фаервол открыт всему миру** на 22/80/443, NSG нет → **WEB-306** (P1). Хостовой слой был закрыт гейтом 12, облачный никто не проверял.
Расписки: `~/Downloads/GATE13-OCI-TRUTH-20260821.md` sha `06e92c2a7c3462d75eef00682257f425b21229f5044070716f7e896726021c94`, сырьё `GATE13-OCI-TRUTH-RAW-20260821.json` sha `2844ab8045f670f2e57017b8748866277d264e303d8503276b9c789bbf99b7ab`. Разложено на M4 `/Users/milamarty/work/` и A1 `/home/ubuntu/waves/`.

## 21.08 — ХРОНИКА СБОРКИ ТРИДЦАТОЙ (две честные остановки подряд)
1. **Первая сборка — rc=3**, `next build` упал: `Module not found: chromium-bidi`. Корень — клиентский `DeepResearchModal.tsx` дотягивался до серверного Chromium-рендерера PDF. Починено волной `pdfsplit` + постоянный гейт (см. WEB-093).
2. **Вторая сборка — `next build` rc=0** ✅, но упала упаковка: `prepare-standalone.cjs:186` отказался — `.next/standalone/node_modules` оказался **симлинком** на общий `node_modules` соседнего worktree.
   Отказ **правильный**: артефакт, чей `node_modules` указывает наружу, не самодостаточен. Это ровно тот же класс, что сегодня же убил стенд ролей на M4 (WEB-301) — «самодостаточность, которой нет», только с другой стороны.
   Лечение в корне, а не обход: снят симлинк, в `wt-l30b` поставлен **настоящий** `node_modules` (`pnpm install --frozen-lockfile`, rc=0, 6.2 с за счёт хардлинков из store `/home/ubuntu/r13pack/pnpm-store-repro/v10`, 2.1 ГБ, 118 пакетов), `.next/standalone` удалён целиком, сборка перезапущена с нуля.
   ⚠️ Урок для следующих посадок: симлинк на общий `node_modules` годится волне для работы, но **не годится дереву, из которого собирается артефакт**.
Сборочный HEAD: `51d5b74f` (landing30b + pdfsplit). Ветки `obs1`, `gates256`, `cacheprivacy` в тридцатую **не берутся** — идут в тридцать первую, чтобы не наращивать риск уже большой посадки.

## 21.08 03:18 — ПОПЫТКА ПОСАДКИ ТРИДЦАТОЙ: ОСТАНОВЛЕНА ГЕЙТОМ, ПРОД ОТКАЧЕН, ПРОСТОЙ ~90 СЕКУНД

### Что успело пройти (и остаётся в силе)
| шаг | результат |
|---|---|
| sha артефакта на каждом хопе A1 → ноутбук → M1 → Pi | **совпал везде**: `f7b8f34f63fef98f8049f728dac23eb34b6039ed4a7e4d35f4f54acacd3a1625` |
| реестр платных точек входа тронут? | **нет** → переподпись манифеста не требовалась |
| аттестация активации v17 | сгенерирована на ноутбуке (ключ не покидал его), `manifestSha256` не изменился |
| четыре sha-пина (миграции/цена/оценщик/локфайл) | **уже совпадали** с аттестацией — не трогались |
| греп байтов релиза | `unsupported-conjunct` 10, `fresh-db-check` 1, `accounting_unhealthy` 25, «Язык отчёта» 17, `RateLimitCounter` 12, `providerCaptions` 6 |
| **миграции 3/3 применены и проверены** | `DocumentChunk_documentId_index_idx` **valid=t** (CONCURRENTLY на 1.28 ГБ прошёл чисто); `RateLimitCounter` + уникальный индекс созданы; `InlineFactcheck.verdict/textHash` стали `text`; `FactcheckVerdictCache_claimKey_key` перестал быть частичным; 8 добавленных колонок на месте |

**Миграции откатывать не нужно** — они аддитивны и совместимы со старым релизом, который сейчас и обслуживает.

### На чём остановились
Релиз не поднял HTTP-порт: fail-closed boot-контракт (WEB-070) нашёл две фатальные претензии — отсутствующий `APP_URL` и требование `TELEGRAM_CALL_ADAPTER_SECRET`, вытянутое широким триггером из обычного бот-токена. Разбор и план — **WEB-307**.

### Откат
Восстановлены из бэкапов `spend-runtime.env`, `enforce-start.sh`, drop-in; `daemon-reload` + `reset-failed` + `restart`. Итог: `active`, `NRestarts=0`, `/api/ready/paid` = **200**, `paidReady=true`, `posture=enforce_ready`, `mode=enforce`, `failures=[]`; правила nft переприменены (`nft_rc=0`, cgroup-id обновился); секрет сторожа сверен — файл и процесс дали один хеш `cbabe4a2b16008e3`.
Страховочный дамп двух таблиц, которые правились не только добавлением: `/home/pi/prelanding-backup/pre-51d5b74f-20260821T021613Z.sql` sha `bb3cd26e…` (не понадобился).

### Урок
Проверка «поднимется ли релиз с боевым окружением» **отсутствовала в чеклисте посадки**. Сборка, байты, sha и миграции проверялись, а совместимость окружения — нет. Добавить в чеклист сухой прогон boot-контракта против прод-окружения ДО переключения: это дешевле, чем 90 секунд простоя.

## 21.08 03:53 — ⭐ ТРИДЦАТАЯ СЕЛА СО ВТОРОГО ЗАХОДА

**Посадка 30 состоялась 21.08 03:53 IST.** serving = `v4-504af77f`, релиз `arm64-504af77f-20260821T025311Z`, артефакт sha `a0afc41415db60377aeb4cf399d91b98a4c407217fc8839b0b1369a2542af362`, аттестация v18. Проверено после переключения: `active`, `NRestarts=0`, `paidReady=true`, `posture=enforce_ready`, `mode=enforce`, `failures=[]`, фатальных строк boot-контракта **0**, секрет сторожа файл≡процесс (`cbabe4a2b16008e3`), nft переприменены, канон проштампован (`CANON.json: serving=504af77f marker=v4-504af77f`).

### Чем второй заход отличался от первого
Между попытками появился **недостающий шаг чеклиста** — сухой прогон boot-контракта против боевого окружения **до** переключения. Прогнан так, что секреты прода никуда не поехали: на Pi собран список **имён** переменных из тех же файлов и в том же порядке, что подключает systemd (180 имён, значения заменены заглушкой; проверено, что ни одного настоящего значения в файле нет), и по нему прогнан контракт нового релиза.
```
[boot-contract-dry-run] fatal (missing_required, missing_conditional, dev_var_in_production): none
[boot-contract-dry-run] VERDICT: boot proceeds.     rc=0
```
Фатальные коды зависят только от **наличия** переменной, поэтому санитизированный список воспроизводит их точно; `bad_secret_format` и `bad_origin` в выводе — артефакт заглушек и не блокируют.

### Полный трейл посадки
| шаг | результат |
|---|---|
| sha на трёх хопах A1 → ноутбук → M1 → Pi | совпал везде: `a0afc414…` |
| реестр платных точек входа | не тронут → переподпись манифеста не требовалась |
| аттестация v18 | сгенерирована на ноутбуке, ключ его не покидал; `manifestSha256` прежний `8a915a0a…` |
| четыре sha-пина (миграции/цена/оценщик/локфайл) | совпали с аттестацией, не трогались (проверка вернула 4/4) |
| греп байтов релиза | `unsupported-conjunct` 10, `fresh-db-check` 1, `accounting_unhealthy` 25, «Язык отчёта» 17, `RateLimitCounter` 12, `telegram-call` 62 |
| миграции | применены ещё в первом заходе, 3/3, объекты проверены; bootfix миграций не добавлял |
| живая проба | `/` → 307, `/api/ready/paid` → 200, **новый роут `/api/deep-research/export` → 401** (живой, требует авторизации) |

### Что приехало на прод этой посадкой
PDF-отчёты тремя шаблонами на живых путях экспорта + локали (WEB-083, WEB-065); четыре пункта архитектуры (WEB-094 общий admission control с таблицей `RateLimitCounter`, WEB-095, WEB-096 индекс `DocumentChunk`, WEB-098); судья фактчека и разбиение составных клеймов (WEB-087); источники фактчека (WEB-066, WEB-067, WEB-068); P0 миграций (WEB-091) и починка врущих указателей релиза (WEB-092); invite-гейт (WEB-071); upload-лимиты (WEB-077); граница клиент/сервер и постоянный гейт (WEB-093); сужение триггеров boot-контракта (WEB-307).

### Не вошло намеренно
`obs1` (WEB-097 наблюдаемость), `gates256` (гейты 2/5/6), `cacheprivacy` (WEB-300), `clientbundle` — идут в тридцать первую, чтобы не наращивать риск и без того большой посадки.

## 21.08 — ⚠️ ПОСЛЕДСТВИЕ ПОСАДКИ: P0 WEB-308
Через ~45 минут после посадки `v4-504af77f` платный контур ушёл в `paidReady=false` (`TERMINAL_PROJECTION_EFFECT_MISMATCH`). Немедленная проверка после переключения была зелёной — отказ проявился, когда отработал сверочный крон (`SPEND_RECONCILE_INTERVAL_SEC=600`).
**Дополнение в чеклист посадки:** одной проверки сразу после переключения мало. Нужна вторая, отложенная — не раньше, чем отработает самое долгое периодическое задание контура. Разбор и восстановление — WEB-308.

## 22.08 12:52 UTC — КАНОН ПОСЛЕ ДЕТЕКТИВА 30/31/PDF
- Исправление хронологии: второй cutover 30-й на `504af77f` был успешен и этот commit остаётся предком всей текущей WEB-308-линии вплоть до `3dd52177`/`da501c43`. Формулировка «30-я откатана и исчезла» неверна; откатан был первый не поднявшийся заход, затем bootfix и второй успешный заход.
- Отдельная `landing31 c9eabc7b` была собрана после 30-й, но не посажена и не включена в аварийные релизы. Это 86 сохранённых файлов `obs1/gates256/clientbundle/cacheprivacy`; не считать их serving до отдельной посадки.

## 22.08 — packaging-size не относится к Oracle/DB migration epic
120 migrations занимают около 1.2M. Рост Landing31 archive до 621130003 bytes вызван полным materialized pnpm node_modules (2.2G) внутри standalone, а не rollback/migration policy. Исправление вынесено в WEB-312; границы WEB-282 и его restore/migration gates не меняются.

## 22.08 20:55 UTC — Landing 31 фактически посажена и принята системными гейтами

- serving release: `/home/pi/note-clone/releases/arm64-26116cff032ad8f015e1e2d9cba302e1e8f7ec27-20260822T202100Z`
- source/live identity: `26116cff032ad8f015e1e2d9cba302e1e8f7ec27`; SW cache: `v4-26116cff`
- artifact SHA256: `a3c1c9d623d2baa7f1a37caf85fde863cfac91785f2a61a75adf6c1416b2d595`
- service: active/running, `NRestarts=0`; local/public root HTTP 307 redirect
- paid readiness: `paidReady=true`, `failures=[]`, migrations ok
- accounting: unresolved/outbox/failedProjectionIncidents = `0/0/0`
- source-indexing worker: Result=success, ExecMainStatus=0, NRestarts=0; timer active/waiting+enabled
- pointers: `current` and root-owned `CURRENT-QW4-RELEASE` both equal systemd WorkingDirectory
- post-cutover receipt: `/home/pi/note-clone/shared/run/l31-cutover-backup-20260822T205314Z/paid-ready-postcutover.json`, SHA256 `9af59d4bb0a531751a8d3d3b6822aa407602463c35194f9efea5106e1def2e25`
- boot receipt: `/home/pi/note-clone/shared/run/l31-26116cff-precutover/boot-contract-dry-run.json`, SHA256 `906b29d860f0945eefb009d2f6581edfc0f5f18aa5093acfa06f87379e65a0c7`
- wrapper self-check receipt SHA256: `8ffd01c9229811f35296d90340fd8792b7fe09966a38f053c8b253e084934841`
- cutover script retained: `/home/pi/note-clone/shared/run/l31-final-cutover.sh.next`; local source `/Users/annakorin/l31-final-cutover.sh`

Операторская задержка зафиксирована честно: три предыдущих functional-green захода были автоматически откачены из-за ошибок сохранения evidence/pointer, не из-за кода релиза. Каждый rollback вернул предыдущий `da501c43` в paidReady=true. Финальный заход прошёл полностью; владелец уведомлён в Telegram, message_id=12852.

## 2026-08-23 PDFPOSTQA: N-A — PDF упомянут только в историческом тексте миграционного эпика; browser acceptance отсутствует.

PDFPOSTQA: бесплатные сценарии только; новые paid generation/export/import не запускались. Полный реестр и evidence: /Users/milamarty/work/PDFPOSTQA-REPORT.md; screenshots: /Users/milamarty/work/PDFPOSTQA-SHOTS/.

## 2026-08-23 BOARDSWEEP: IN_PROGRESS-LIVE
- Evidence: updatedAt=2026-08-22T20:57:22.258Z, within 24h; body is the migration/accounting epic with current landing evidence. No status change.
- buildFixed: <empty>; canonical: v4-081ff4fb5 / 081ff4fb5f6110f8001daec7ed910ccef2e395dc.
- Status preserved by sweep: in_progress.

## 01.09 14:45Z АУДИТ ПО ЗАПРОСУ OWNER (актуализация протухшего журнала)
ФАКТ: прод ПЕРЕЕХАЛ на A1 и автономен — релиз l82 (0aa0ac8f), paidReady TRUE, БД+Redis локально, Малинка=дев. Двухнодовость: A2 пассив + PG16-standby (лаг ~0), HA-RUNBOOK.md. Бэкапы: Hetzner WAL-стрим + почасовой base (после инцидента hetzbk 01.09 — ретенция починена). DNS sip/nb → A1 (31.08-01.09), прямой A1:443 валиден.
ГЕЙТЫ done: 1,2,3,4,7,8,10,11,12,13 + WEB-091/092/094-098/308/312/066. ОТКРЫТО: WEB-082 (бэкап-контур: де-факто WAL+base есть, НЕ сдан приёмкой c restore-drill), WEB-300 (privacy кэша), WEB-306 parked (OCI ingress 0.0.0.0/0), WEB-032 (правила A1), DNS-зона+почта → Cloudflare (ШАГ OWNER: NS у регистратора), формальный катовер-отчёт/когорты. Телефония-ветка — в WEB-395.

[01.09 19:50Z] ДОМЕН/DNS шаг: sixbyy.com ЗАПУЩЕН на прод — зона уже была на Cloudflare (owner прав), A/www вели на парковку Namecheap; owner поправил записи на 129.213.25.105 (DNS only), я: LE-cert (sixbyy.com+www), nginx vhost (клон nb), APP_ALLOWED_HOSTS (явный allowlist origin-lock: nb+sixbyy+www+loopback), рестарт. Паблик: / 307→/onboarding, health 200; nb=200 параллельно. Хвосты: каноника AUTH_URL остаётся nb (логин может редиректить) — смена по решению owner; CF-proxy (оранжевое облако) можно вернуть теперь с сертификатом. Почта sixbyy: mail A→A1 и Resend-верификация уже стояли.

## ЭВОЛЮЦИЯ 04.09.2026 (карта для нулевого агента)
**Якорь прода:** живая линия **l103**, коммит **d91ebefe740ae83484c1de16710f2e6a68610432**, флип **13:51Z 04.09**. Раньше в этот же день: l101 `d825eb0d`, l102 `1b081c5a`. Ветка линии в репозитории-базе `/home/ubuntu/nc` на A1: `l103-line` (проверено `git branch -a --contains d91ebefe...` → `l103-line`).
**Доска:** живая доска — `web-board.sqlite` + HTTP API `http://127.0.0.1:8787/api/web/*` на M1 (`ssh poolpooly@192.168.1.74`). НЕ `board.sqlite` (это iOS/легаси, таблицы `issues`/`ios_issues`, 2225 строк, ключи другие).

### СЕЙЧАС
**Аудит эпика завершён.** Блокирующий шаг — **ступень 4**: провести неизменяемый прод-кандидат и платный ре-гейт до состояния **ready** на распакованном standalone, причём аттестация должна быть привязана к ТОЙ ЖЕ линии.

### ЧТО ЗАПУЩЕНО
Волна **`1772-web282stage4`**.
⚠️ Важно для нулевого агента: в очереди диспетчера A1 её **нет** — `ls /home/ubuntu/waves/queue/{active,running,done}` на 04.09 ~15:0xZ показывает 1746, 1770, 1771, 1775, 1776, но не 1772. Значит волна идёт на **втором воркере волн (M4, 192.168.1.110)** либо вне диспетчера A1. Проверять статус надо там; на момент записи M4 по ssh с ноутбука не отвечал (`Connection closed by 192.168.1.110 port 22`).

### СЛЕДУЮЩЕЕ ДЕЙСТВИЕ
1. Достучаться до M4 и снять статус 1772 (журнал волны + отчёт автора).
2. Приёмка ступени 4 должна проверять именно **ready на распакованном standalone** и **совпадение линии аттестации** — не «собралось», не «флаг стоит».

### ЛОВУШКИ
- Аттестационный манифест собирается **из BUILD, а не из source**, и он **env-зависим**: собранный в другом окружении манифест не сойдётся.
- Standalone уже один раз не содержал proof-файлы (`src/lib/billing/terminal*`) → enforce ready отдавал 503 ENOENT. Проверять состав распакованного standalone, а не только его наличие.
- Флип enforce — ТОЛЬКО по отдельному GO аудитора и решению owner.
Доказательства

[2026-08-24 ~21:55] РЕПЕТИЦИЯ переезда — DRY-RUN ПРОШЁЛ (owner: делайте репетиция). rehearse-cutover.sh --dry-run: 15 шагов T-0 плана исполнились (artifact_prepare, rebuild_from_zero, migration_118_of_118_proof, restore_latest, boot_contract, source_quiesce, final_sync, rpo/restore/rebuild_threshold, hosts_switch_t0, verify_cutover, verify_evidence_import), receipt evidence/*/cutover-timings.json, verdict DRY_RUN, безопасно (не трогает прод/DNS). Harness корректен. EXECUTE-прогон (реальные замеры RPO/RTO/rebuild/restore/file-loss против порогов owner) = следующий шаг: заполнить cutover.env прод-контрактом (APP_URL/health/version/hostnames) + одобренные GATE14BK/GATE514 хуки + служебный порт. Скрипты: scratchpad/cutover-rehearsal/ + M4.

[2026-08-25 ~10:30] AWS-резерв разблокирован (§2 п.6 остатка миграции): owner вошёл root-ом в Chrome, координатор через IAM-консоль прицепил AmazonEC2FullAccess к user/local-uploader (arn:aws:iam::310544498875:user/local-uploader, «1 policy added»). Емейл аккаунта установлен: fandyy2023@gmail.com (второй аккаунт 436069770697 = fandyy2009@gmail.com, в записях open.txt). Скрипты репетиции готовы на M4 ~/work/aws-rehearsal (provision-t4g.sh/measure-restore.sh/teardown.sh + runbook). aws CLI нигде не установлен — ставится в рамках репетиции. Сам платный прогон (t4g на день, ~$2) — ждёт слова owner «давай репетицию». Параллельно этой ночью: почтовый DNS sixbyy.com внесён в CF и резолвится (MX/A/SPF/DKIM/DMARC, старые Namecheap-записи снесены с одобрения owner).

[2026-08-25 ~11:20] AWS-репетиция: owner дал GO. Подготовка: aws CLI 2.36 на координаторе, профиль rehearsal (ключи local-uploader из open.txt, не печатались), права EC2 подтверждены живьём (describe-regions 17). Скрипты M4→A1→локально; 2 фикса скриптов: AMI_ID_OVERRIDE (ssm:GetParameter не в EC2FullAccess — AMI ubuntu-noble-24.04-arm64 ami-085135ce711ba9ff9 разрешён напрямую через describe-images) и синтаксис authorize-security-group-ingress под CLI v2.36. Keypair nc-rehearsal + SG созданы (eu-north-1). БЛОКЕР ВНЕ НАС: RunInstances → «Blocked: account not recognized as valid — account-verification» (аккаунт 310544498875 молодой, EC2 не запускал). Действие owner: саппорт-кейс верификации (инструкция tg 13372). Расход $0 (инстанс не стартовал). ПАРАЛЛЕЛЬНО: куплен Hetzner Object Storage bucket sixbyy-vault (Helsinki, Object Lock ENABLED, private, потолок €6.49/мес) — несгораемый слой сейфа по одобрению owner («можете донастроить, я в кабинете»).

[2026-08-25 ~11:50] AWS: саппорт-кейс верификации ПОДАН координатором в Chrome owner (owner заблудился в новом support-flow — доведено): case displayId 178761915400570, «Account verification to launch EC2 instances», Account and billing→Account Verification, severity General question, contact Web. Ожидание ответа: часы-сутки на fandyy2023@gmail.com. По разблокировке — немедленный прогон репетиции (всё готово, профиль rehearsal, keypair nc-rehearsal, SG, AMI ami-085135ce711ba9ff9, eu-north-1).

[2026-08-25 ~07:30] GATE-5 route passport 519/519 в проде (посадка 52, WEB-073). Привязка к serving-артефакту 446bcbf подтверждена.
[2026-08-25 19:57Z] ДЫРА НАЙДЕНА owner-ом: пакет миграции не покрывал мессенджер/звонковый стек Pi (SIP+Signal+TG-боты+мосты) — на Oracle не развёрнуто ничего. Заведён WEB-370 (P1): инвентарь → ship-dark развёртывание на A1 → сценарий бесшовного свитча → репетиция → бэкапы состояния. iMessage — исключение (Mac-only, остаётся M1).

[2026-08-27 связь] Эпик миграции Oracle A1: сегодня по нему сделано много — storage gate WEB402D ЗАКРЫТ (A1 83 GiB свободно против норматива 80; вывезено 111 бандлов на M4Ext со сверкой sha, написаны уборщики ~/wtclean.sh и M1:~/idxclean.sh); тумблер Pi<->A1 (WEB-370) реализован ship-dark, но приёмка дала NO-GO — egress «закрывался» только на бумаге (реальные TCP/DNS с пассивной стороны проходили), чинится в togglefix3. Бэкап-контур в Hetzner ВКЛЮЧЁН на проде (WEB-082): WAL-поток + часовые base, owner подтвердил «Хетцнер основной, малинка вспомогательная».

[28.08 14:30Z Фабл] Синхронизация по указанию владельца (голос 12:43): тумблер телефонии (WEB-370/409/410) — составная часть ЭТОГО эпика, не самостоятельная цель. Вопрос владельца «работает ли на Oracle почта/телефония/мессенджеры» — сейчас НЕТ; закрывается: полной картой малинки (WEB-399, круг 5 на приёмке — полнота по построению, почта включена), списком непереносимого (WEB-401), тумблером (WEB-409), аварийным восстановлением (WEB-410, RPO 218с + квитанция WAL из сейфа). Документ эпика: ~/Downloads/МИГРАЦИЯ-ОСТАТОК-20260824.md; артефакты M4Ext. Ждут решения владельца: почтовый провайдер (Resend vs SES, WEB-345), права EC2 для AWS-резерва, ступень 5 (ключи owner + когорта 25). Владельцу доложено в TG 14:20Z.

[28.08 ~16:00Z Фабл] 📚 КАРТА ДОКУМЕНТОВ ЭПИКА (по требованию владельца — нулевой агент начинает отсюда):
- Свод «что не доделано»: ноут ~/Downloads/МИГРАЦИЯ-ОСТАТОК-20260824.md (актуализация 25.08 сверху файла).
- Норматив: ~/Downloads/prodplan-20260810/PROD-MIGRATION-PLAN-R4.md (Интел). Карта эпика: M1 board/specs/MIGRATION-EPIC.md. Аудит гейтов: M4 /Users/milamarty/work/MIGAUDIT-REPORT.md.
- Карта малинки (ступень A, ПРИНЯТА 28.08): A1:/home/ubuntu/waves/WEB399E-REPORT.md + pi-inventory-full.md + pi-proc-map.md + ACC399E-REPORT.md.
- Тумблер: WEB-409 (плановый+откат, A1:WEB409B-REPORT.md) · аварийный: WEB-410 (A1:WEB410-REPORT.md + квитанция §1.4 в pi-audio-facts-20260828.md) · учение: WEB-400 (A1:WEB400C ожидается) · площадка: WEB-402 (A1:WEB402-REPORT.md, safe-off) · звук: WEB-403 · непереносимое: WEB-401.
- Почта: WEB-419 (решение владельца «оба», факты postfix в WEB-345). Бэкапы-контур: WEB-082 (GATE14BK-REPORT на A1). Артефакты объёмные: M4Ext /Volumes/M4Ext/ops/.
- Лестница Gate 0: ступени 1-4 ✅, 5-6 ждут владельца. Список ожиданий владельца: почтовый провайдер (решено 28.08: оба), EC2-права, ступень 5.

[BOARDTRIAGE] Последнее движение: 28.08 около 16:00Z. Эпик жив через миграционные подзадачи; ступени 5–6 и заявленные owner-gates не закрыты, статус in_progress сохраняется.
Дети
Лента
2026-08-16T13:28:30Z · backup-opus
Создан эпик-тикет (owner 16.08: вести доску по эпикам). Текущее: b2fix летит на А1 (лог /home/ubuntu/b2fix.log); после посадки — пакет ре-гейта ступени 4 (B1+B2+B3+B5). B5 runbook: /Volumes/M4Ext/ops/step4-regate/B5-ROLLBACK-RUNBOOK.md sha 7a66c9fa.
2026-08-16T14:20:43Z · backup-opus
16.08 ~15:55: волна b2fix села (честный BLOCKED): упаковка proof-файлов починена fail-closed (prepare-standalone копирует 3 исходника, packager требует их наличия; контрпроверка на старом артефакте rc=1), полный cwd-контракт readiness вскрыт (3 proof + 11 миграций), новый linux/arm64-артефакт собран нативно на А1: 05c4e87a… (165.9МБ), рестарты 462-464мс — числа для B5-runbook. Честный стоп: sidecar step4-run-01 привязан к старому artifactSha256 → запущена волна b2sign: репетиционная аттестация на новый артефакт + операторские prerequisites (gates accounting/global, egress guard, reconcile deadman) + enforce ready=true + синтетическая операция с повтором (нет двойного списания) + off + reconciliation. Дифф b2fix: 2 файла упаковки, sha 161c27fb.
2026-08-16T14:44:03Z · backup-opus
16.08 ~15:55: b2sign села — release-аттестация на новый тарбол принята продуктовым verifier (wrong-key отклонён), gates открыты штатно, reconcile зелёный, инварианты wallet/ledger доказаны (reserve-settlement-replay, reserve-release-replay: двойного списания нет), откат чистый. Один блокер: рантайм читает только вшитую аттестацию. Запущена b2final: сборка со вшитой release-аттестацией (двухфазная штатная механика), enforce ready=true, операция через paid HTTP gateway. Материалы: M4Ext/ops/step4-regate/B2-RUNTIME/.
2026-08-16T16:19:13Z · backup-opus
16.08 ~17:25: b2final доказала fixed-point невозможность вшивания raw-SHA тарбола в сам тарбол (двухфазная детерминированная сборка, точный mismatch-verdict) И что штатный step4-протокол сам построен на внешнем sidecar для уже выбранного SHA. Решение координатора: продуктовый фикс — runtime грузит внешнюю аттестацию (SPEND_ACTIVATION_ATTESTATION_PATH + SPEND_RUNTIME_ARTIFACT_SHA256 от деплой-скрипта, fail-closed, негативные тесты wrong-key/подмена SHA/нет файла). Волна b2sidecar запущена на А1: фикс + сборка + генератор + полный B2-цикл через paid HTTP gateway. Это же — прод-механика owner-ключей (требование №5 аудитора).
2026-08-16T17:29:52Z · backup-opus
16.08 ~18:35: ⭐ B2 ЗАКРЫТ (b2sidecar PASS): внешний sidecar-механизм аттестации реализован fail-closed (10/10 матрица), enforce paidReady=true с репетиционным ключом, учётная операция через живой paid HTTP gateway — идемпотентный повтор settlement не изменил кошелёк (канонический SHA тела совпал), release-ветка через fault-injection с полной уборкой, откат чистый, рестарт-бюджет <1с. ПАКЕТ РЕ-ГЕЙТА СТУПЕНИ 4 СОБРАН: GPTPRO-MONET-STEP4-REGATE-20260816.zip 331928346 байт digest 2dba99f122c473843369bdc3beff38c122ab042e669f9e2bf16fb1c2cc5744bb (B1 свежий 34/34 + B2 4 репетиции с обоими артефактами и диффами + B3 полные логи + B4 живой Pi-снапшот + B5 runbook v2). SHA256SUMS на распакованных байтах rc=0. Диффы b2fix+b2sidecar войдут в следующую посадку на Pi.
2026-08-16T18:18:28Z · backup-opus
16.08 ~20:40: вердикт ре-гейта — инженерный прогресс GO, крипта и sidecar-дизайн PASS независимо, НО флип NO-GO: зелёный paidReady был получен тестовым лаунчером (runtime-entry.mjs, VITEST) вне артефакта; два настоящих runtime-дефекта: egress guard module-local (теряется между chunks) и нет штатного direct-deny proof. Плюс: тонкий B1-лог, dirty-tree сборка (sourceCommit неполная provenance), кандидат не выкачен на Pi, BigInt-500 в cron reconciliation, поправки B5-формул. Вердикт заархивирован. СДЕЛАНО СРАЗУ: clean-коммиты координатора на линии (f27f002 b2fix + e820583 b2sidecar поверх b484608), волна b2prod запущена на А1: process-global guard, штатный direct-deny proof, BigInt-фикс, reconciliation из shipped-артефакта, разбор всех 17 FAIL extended-набора с полным TAP, сборка из чистой линии и ШТАТНАЯ репетиция node server.js без тест-флагов.
2026-08-16T19:27:14Z · backup-opus
16.08 ~23:50: ⭐ b2prod PASS — ШТАТНЫЙ ENFORCE ВЗЯТ: node server.js из распаковки БЕЗ тест-флагов, enforce paidReady=true с внешним sidecar, негативы 503, settlement/replay/release/off, reconciliation через SHIPPED HTTP route (BigInt починен, операторская команда curl готова для B5). Фиксы: process-global guard (Symbol-реестр, двух-чанковый red/green тест), стартовый direct-deny self-check без VITEST-веток, честный packaging manifest. Все 17 исторических FAIL разобраны с полным TAP (G3-B12 = устаревшее ожидание, доказано мутацией). Дифф закоммичен координатором: 7ccc4db (линия: f27f002→e820583→c290f10→7ccc4db, на GitHub refs/lines/prod). Запущена b2pack: пересборка exact-артефакта из ЧИСТОГО коммита + штатная репетиция на итоговом + материалы пакета v2 (п.2-4,6 вердикта). После неё: тёмный деплой кандидата на Pi с полным receipt (п.7) и пакет.
2026-08-16T20:49:36Z · backup-opus
17.08 ~02:40: ⭐ b2pack3 PASS — ФИНАЛ РЕ-ГЕЙТА: свежий activation comparandum перегенерён под 7ccc4db (3735 файлов), exact-артефакт собран, ПОЛНАЯ штатная репетиция прошла (node server.js без тест-флагов, enforce paidReady=true, settlement/replay/release/off, reconciliation через shipped route). Пакет v2 ре-гейта готов к сборке из этих материалов. Отдельно: запущена landing-сборка из HEAD линии b36d8d1 (всё: видео/голос/финмина + step4 DORMANT) для тёмной посадки продуктовых фиксов на Pi — enforce остаётся off, ждать ре-гейт не нужно.
2026-09-02T00:38:11.039Z · Fable
[02.09 00:50Z Фабл] Hetzner DR-стресс: ARM (CAX) недоступен на аккаунте во всех трёх локациях (Console: «Not available», API: unsupported location for server type; лимиты серверы 0/5, аккаунт слишком новый для запроса повышения). Owner отправил тикет в поддержку Hetzner (Technical → Other issue, текст: enable Arm64/CAX). До ответа: вариант 3 — A2 (Oracle Ashburn) как вторая нода уже покрывает «смерть аккаунта Oracle» частично; x86-сборка (вариант 2) — резерв. Скрины/факты: сессия координатора 02.09.
2026-09-02T07:33:01.476Z · Fable
[02.09 07:45Z Фабл] Резервный узел вне Oracle: AWS EC2 квота не выдана (ранее) → Hetzner ARM (CAX). Ответ поддержки Hetzner 02.09: CAX не продаётся новым заказам, без ETA/очереди. Проверено в консоли owner-а: CAX11/21/31/41 недоступны в nbg1/fsn1/hel1 (toast «Preselected server type is not available»), в sin/hil/ash ARM не предлагается. Доступно сейчас: x86 CX23 5.49€/мес (hel1/fsn1), CPX22 19.49€. Варианты: (а) x86 CX23 + отдельная amd64-цепочка сборки (1–2 дня; Asterisk на резерв не планируется); (б) ждать ARM, резерв = Oracle A2 (пассив + standby PG) + Hetzner Storage Box (бэкапы). Решение owner-а запрошено в TG (id 16401).
2026-09-02T10:19:14.496Z · Fable
[02.09 11:50Z Фабл] Репетиция аварии фаза 1 выполнена на A2 (WEB-470): сайт+БД+учёт подняты из бэкапов Hetzner; RPO ≈3–6 мин, RTO ≈17 мин без подготовки (~45 с подготовкой); 5 находок (главная — hetzbk-restore не восстанавливается из последнего base без патча, WEB-469).
2026-09-02T19:34:28.047Z · Fable
[A1 20:15 Фабл — сводка эпика для нулевого агента] Прод A1 = l92 (9bee5955) с 18:37 02.09; P11 включён 19:30 (проба 1322). Открыто: WEB-470 (тёплая копия — 1314 на доработке, DR-доки 1299, authority-pack 1300, репетиция 1c с секундомером после фикса; WEB-490 малинка как cold standby), WEB-472 (пользователь wave для волн), WEB-478 (диспетчер: утечки/лимиты), WEB-467 (таймаут проекции — перепроверить на l92 с пулом 15), WEB-489 (дев-стенд A2 — ждёт ответа owner-а). P01 — после GO пробы P11 (+30 мин). Все команды сборки/посадки l93 — в памяти координатора (compact-handoff-pointer-20260902b).
2026-09-02T21:34:47.139Z · Fable-M1
**Карта на 02.09 вечер** (волна 1373-migrationepicmap, Fable-M1). Полная карта: `board/specs/MIGRATION-EPIC.md`.

Прод: Oracle A1 arm64, релиз **l93 (02d032e4)** с 20:17.

**WEB-093 — активация P-карточек:** P04 метрики живы; P05/P15/P17/P18/P19 включены; **P11 (журнал платных операций, WEB-477) выключен** — чат 400 (клиент не шлёт idempotency-key), круг 3 = волна 1370; **P01 (admission) — после P11**.

**WEB-282 — миграция:**
- **WEB-470** репетиция из Hetzner: БД из тёплой копии ~4 мин (RESTORE PASS ×3); стадия приложения — дефект скрипта (круг 5 = 1361); DR-доки круг 2 = 1359 (M4); пороги owner RPO 5 / RTO 15. Takeover A2 02.09: RPO 3–6 мин, RTO ≈17 мин.
- **WEB-405** арбитр lease → A2: круг 3 сдан d47a7c48, приёмка 1371; authoritypack GO.
- **WEB-489** дев-стенд A2: owner GO 21:11 (волна 1362).
- **WEB-490** Pi cold standby: 1366 (M4). **WEB-472** sudo-guard: 1363. **WEB-478** диспетчер v3: 1364. **WEB-467** таймаут проекции: 1365 (Sol). **WEB-476** SIP-fence: закрыто.

**Зависимости:** P01←P11; арбитр←1371; дев-стенд←1362; полная репетиция←1361.

**Нужно от owner:** DNS dev.wool2.online; basic-auth dev; codex login M1; ротация бот-токенов WEB-413; Signal WEB-471; участники WEB-427.

**Инцидент 19:50:** два SIP-сервиса убивали друг друга — experimental выключен, правило «после restart nc-a1 → restart только ag-sip-native». Кап Codex исчерпан 20:44 → волны умерли, owner сбросил 20:57.
2026-09-02T23:32:27.196Z · Fable
[A1 03:55 Фабл] ПРОД = l94 (b1962b8d01185a77ea8df7082170d108c1c2dab2), посажен 03:50 laptop (≈00:50 UTC 03.09): релиз /home/ubuntu/prod/releases/arm64-l94-20260902T232029Z, run /home/ubuntu/prod/shared/run/l94-b1962b8d, артефакт me2-standalone-linux-arm64-b1962b8d-20260902T232029Z (sha aba29aba…6e). Состав: web401provenance5 (GO 1339), web447orphans5 (GO 1340), rolesc3chain7 (GO 1367), reseedfix 1323+1358 (GO 1375), web477idemkey4/p11fix3 (GO 1392). Сборка с полным паритетом NEXT_PUBLIC (12 ключей). Посадка: unpack/env/bootcontract/dryrun/migrate (0 миграций)/flip/verify — health/ready/paid 200, SIP native стабилен (только native рестарт). После flip: publish-release на Storage Box (app-artifact/l94-b1962b8d), HETZBK_ENV_LINE=l94-b1962b8d + env-pack. P11 включён (PAID_OP_RECORD_ENABLED=1) → живая проба 1412 → P01. Откат = l93 (arm64-l93-20260902T194823Z, run l93-02d032e4).
2026-09-03T01:20:21.790Z · Fable
[A1 10:45 Фабл] P01 (EXPENSIVE_ADMISSION_ENABLED=1) включён на проде l94 после 30-мин окна: precheck paid=200/P11=1; после рестарта nc-a1 + ag-sip-native: paid=200 posture=enforce_ready mode=enforce; SIP readiness 200, stasis=1, ep7016=200. Бэкап .env.local.bak-p01-* в run-каталоге; откат = вернуть бэкап + рестарт nc-a1 + ag-sip-native.
2026-09-04T15:08:17.187Z · coordinator
04.09 координатор: в body добавлен блок «ЭВОЛЮЦИЯ 04.09.2026» — состояние, причина с доказательством, что село, что осталось, ловушки.
2026-09-10T13:16:12.546Z · coordinator
ЭВОЛЮЦИЯ 10.09 — по учёту сдвинулись две ступени.

P11 (журнал платных операций) ВООРУЖЁН на ОБОИХ бэкендах без посадки, 06:55Z.
Ловушка, на которой я сначала обожглась и которую надо знать нулевому агенту:
оба слота (nc-a1 на 127.0.0.1:3010 и nc-a1-b на :3012) читают ОДИН общий env-файл,
а `Environment=` в drop-in ПРОИГРЫВАЕТ `EnvironmentFile=`. Вооружать надо отдельным файлом
на слот: /home/ubuntu/prod/shared/run/p11-slot-a.env и p11-slot-b.env, подключёнными через
/etc/systemd/system/nc-a1{,-b}.service.d/zz-p11-slot-*.conf с префиксом zz-, иначе порядок
загрузки съедает значение. Проверено: PAID_OP_RECORD_ENABLED=1 виден в /proc/<pid>/environ обоих слотов.
P11 пережил все семь сегодняшних посадок, включая l114y.

P19 (гейт совместимости миграций) ПРИНЯТ и работает: сегодня он остановил сборку l114s
на незадекларированной миграции — разбор в WEB-592, тикет закрыт.

P22 (медиахранилище R2) ЗАКРЫТО и доказано жёстко: через прод скачан объект, который существует
ТОЛЬКО в ведре, локальной копии у него нет.
Ловушка дня, стоившая нескольких минут битых картинок у владельца: я включила драйвер R2, сказав
«переносить почти нечего». На деле под MEDIA_STORAGE_DIR лежал 271 файл на 389 МБ. Пришлось
откатиться на локальную файловую систему, перенести все 271 в префикс generated/, сверить число
объектов в ведре и только потом включать снова.
УРОК: состояние читать из /proc/<pid>/environ живого процесса, а НЕ из конфигов — конфиг говорит
о намерении, /proc о факте.

Состояние на сейчас: прод 16e1ddaa1 (l114y), paidReady=true, enforce_ready, платный контур открыт.
2026-09-12T22:17:55.083Z · coordinator
[12.09 22:17Z координатор] МОЙКА 12.09 (3566-wash-g1-infra): эпик миграции — не закрывается, есть открытые дети (WEB-470, WEB-082, WEB-566). Ступень 4 (флип enforce) ждёт отдельного GO аудитора и решения владельца, ступени 5-6 не начаты. Код учёта в дереве есть (src/lib/billing/terminal*). Статус не меняю.
Остаток: Флип enforce (ступень 4) ждёт отдельного GO аудитора + решения владельца.; Ступени 5-6 не начаты.; Открытые дети: WEB-470, WEB-082, WEB-566.
Отчёт: /Users/milamarty/waves/3566WASH*-REPORT.md (M4), копия nc-ops-scripts/shift-20260912-resume/wash-20260912/collected/. Проверка по исходнику прода l115g (9c8a9762).
2026-09-13T10:34:55.741Z · coordinator
[13.09 10:34Z координатор] Тело карточки переписано под состояние 13.09.2026 (волна 3647). Главное, что раньше путалось: переезд на Oracle завершён, а учёт — нет. Рантайм платного контура открыт и готов, но формальное принятие ступени 4 всё ещё ждёт отдельного «да» аудитора и решения владельца. Ступени 5 и 6 не начинались. Старый текст сохранён ниже черты.
2026-09-13T10:45:16.945Z · coordinator
[13.09 10:45Z координатор] Мойка доски, волна 3653. RETURN: ступени 1–3 миграции A1 готовы (прод на l115i, автономен), но ступень 4 (флип enforce) в ре-гейте — ждёт отдельного GO аудитора и решения владельца, ступени 5–6 не начаты, открыты дети WEB-470/WEB-082/WEB-566. Остаток вне прав мойки (прод/решение владельца). Статус не меняю.
2026-09-13T12:02:06.963Z · coordinator
[13.09 12:02Z координатор] Волна 3682. 
2026-09-14T15:16:22.995Z · coordinator
[14.09 15:16Z координатор] # WEB-282 - блок для вставки

Источники, проверенные отсюда: тело тикета из live API; все 21 комментарий из локального `web-board.sqlite`, последний комментарий `id=4748` от 2026-09-13T12:02:06.963Z. Статус на live API при финальной сверке: `in_progress`. Живые контуры и owner-key отсюда не проверялись.

## Что болит словами пользователя

Это эпик переезда Oracle A1 и включения учёта: прод должен жить на A1, paid accounting должен быть включён формально и безопасно, а оставшиеся стадии должны быть понятны без знания всей истории.

## Что уже сделано и чем доказано

По телу и комментариям: миграция runtime на A1 заявлена как выполненная; прод-anchor в теле - l115j `133fe00c`; DB/Redis локальны на A1; Pi переведён в dev/standby роль; A2 passive/standby и backups существуют как части контура. Комментарий `id=280` доказывает ранний механизм sidecar/owner-key на rehearsal-контуре. Комментарий `id=3456` говорит, что paid runtime открыт и `enforce_ready` работал на l114y, но это не равно формальному принятию стадии.

## Что осталось

Стадия 4 ещё не принята формально: нужен отдельный auditor GO и owner decision. Стадия 5 не начата: реальный owner key и cohort 25. Стадия 6 не начата: full cutover, формальный отчёт, cohorts. Параллельно остаются дети и recheck: WEB-082/470/566, WEB-300/306/032/DNS.

## Противоречия между комментариями

Раннее “paid contour open/enforce_ready” легко читается как “учёт включён и стадия закрыта”. Поздние комментарии `id=4359`, `id=4628`, `id=4660` и актуальное тело отменяют это: runtime ready не равен formal flip, стадии 5-6 ещё не стартовали.

## С ЧЕГО НАЧАТЬ НУЛЕВОМУ АГЕНТУ

Смотреть: тело WEB-282 как stage map, комментарии `id=3456`, `id=4359`, `id=4628`, `id=4660`, `id=4748`, затем дочерние WEB-082/470/566 и текущий release receipt. Первым шагом составить acceptance matrix по стадиям 4-6: что уже доказано, что требует owner/auditor, что блокируется детьми.

Готово: stage 4 принят отдельным auditor/owner решением; для stage 5 есть owner-key activation и cohort 25; для stage 6 есть full cutover report и список закрытых детей/rechecks.

Нельзя: объявлять epic done по `enforce_ready`, смешивать runtime readiness с formal acceptance, трогать production или owner secret с M1, закрывать детей из родительского тикета.

Размер: несколько смен. Большим это делает owner-key, staged acceptance, дети и формальная линия cutover.

## Закрытие и связи

Не закрыто. Пересекается с WEB-082/470 по DR/backups и с WEB-561/565 по миграционным хвостам, но дублем не является.
2026-09-15T22:05:58.160Z · coordinator
ENRICH-4132-WEB-282
```markdown
## ДЕЛЬТА ОБОГАЩЕНИЯ — 2026-09-15T21:54Z, M1/4132 (DeepSeek Flash 4.1, read-only аудит), VERDICT=DRAFT_DELTA

### 1. Вердикт
Якорь прода в теле — l115j `133fe00c` (13.09 08:50Z) — устарел. Живая линия —
**l115o `68e25d8df5ae8263c5ac5466353631f57a17cfcc`**. Статус стадий 4/5/6 живёт только
в комментарии id 5033, а не в теле.

### 2. КАРТА ДОКАЗАТЕЛЬСТВ
- Тело: план ступеней 5–6, волна 3682, `3682-billing-stages-5-6-plan-out/STAGE-5-PLAN.md`,
  `STAGE-6-PLAN.md`, `OWNER-DECISIONS.md`, `NOTES.md`. Якорь в теле: l115j.
- Доска WEB-282 id 5033 (2026-09-14T15:16:22.995Z): «Стадия 4 ещё не принята формально:
  нужен отдельный auditor GO и owner decision. Стадия 5 не начата: реальный owner key и
  cohort 25. Стадия 6 не начата: full cutover, формальный отчёт, cohorts.»
- Доска WEB-282 id 280 (ранний механизм sidecar/owner-key на репетиционном контуре).
- Доска WEB-282 id 3456: paid runtime открыт, `enforce_ready` работал на l114y — **это не
  равно формальному принятию стадии** (отменено поздними id 4359/4628/4660 и телом).
- HANDOFF-LIVE.md строки 445–453 (l115o, платная проба 15.09 01:50Z прошла полностью).
- HANDOFF-LIVE.md строка 454: новая находка — расшифровка речи списывает потолок
  (`SETTLED_MAX` / `usage_missing`, `actualMicros` пуст) → тикет WEB-666.

### 3. ЭВОЛЮЦИЯ / ПОПРАВКИ (append-only)
- Якорь: l115j `133fe00c` → **l115o `68e25d8df5ae8263c5ac5466353631f57a17cfcc`**.
- 15.09 01:50Z: платная проба на l115o прошла полностью — ключ
  `3b888a9e-8ecc-4d4c-ba9c-69633f55b83e`, HTTP 200 за 5.9 с, резерв
  `resv_047ece9deae94ec38f512eedc23590d5` → `SETTLED_ACTUAL` (зарезервировано 40 724 микро,
  списано по факту 1017), терминальное событие `tse_afa117295d1bb2ac79d9d904461c` → `APPLIED`,
  ровно одно на резервирование, зависших 0. Это живое доказательство работоспособности
  платного контура, но **не формальное принятие стадии**.
- Новая находка того же дня: расшифровка речи списывает потолок резерва (провайдер не отдаёт
  usage). Вынесено в WEB-666 и является предусловием WEB-671.
- Противоречие, требующее явной пометки в теле: «runtime ready» ≠ «учёт включён формально».
  Ранние комментарии читаются как закрытие стадии; это неверно.

### 4. KNOWN ISSUES / ТРАБЛШУТИНГ
1. **«Paid runtime открыт» читается как «стадия принята».**
   - Симптом: агент считает ступень 4 закрытой и начинает ступень 5.
   - Проверка за 2 минуты: найти в карточке отдельную запись auditor GO + owner decision для
     ступени 4 → если её нет, ступень НЕ принята, независимо от состояния runtime.
   - Причина: runtime-готовность и формальное принятие — разные события, а формулировки в
     комментариях похожи.
   - Лечение/статус: в теле явно развести «работает» и «принято».
   - Ссылки: доска WEB-282 id 5033, id 3456.
2. **Списание по потолку при отсутствии usage.**
   - Симптом: `actualMicros` пуст, `SETTLED_MAX` / `usage_missing`.
   - Проверка за 2 минуты: искать в событиях счёта признаки `usage_missing` и
     `actualMicros = null` → ожидание 0 на новых операциях после починки.
   - Причина: провайдер не отдаёт usage на этом пути; код не читает альтернативу.
   - Лечение/статус: в работе, WEB-666 (+ предусловие WEB-671). Не закрывать по «деньги целы».
   - Ссылка: HANDOFF-LIVE.md строки 454, 632–642.

### 5. ТЕКУЩИЙ ОСТАТОК (ответственный)
1. Ступень 4 — формальное принятие: отдельный auditor GO + owner decision — координатор/владелец.
2. Ступень 5 — реальный owner-ключ (внешняя sidecar-аттестация
   `SPEND_ACTIVATION_ATTESTATION_PATH` + `SPEND_RUNTIME_ARTIFACT_SHA256`, fail-closed) и
   когорта 25 — владелец + координатор.
3. Ступень 6 — full cutover, формальный отчёт, cohorts — координатор.
4. Дети и перепроверки: WEB-082/470/566, WEB-300/306/032/DNS — по своим карточкам.

### 6. ПЕРВЫЙ ШАГ НУЛЕВОГО АГЕНТА (без агентов)
Открыть тело, найти запись о принятии ступени 4. Её нет — значит ступень 4 не принята,
и следующий шаг не в коде, а в приёмке. Сверить якорь тела с живым `/api/ready`. Ничего
не менять на проде: стадии 5–6 требуют владельца.
```

---
2026-09-23T12:42:41.634Z · triage-neo
РЕШЕНИЕ=in_progress
ОСНОВАНИЕ=2026-09-15, ENRICH-4132: ступень 4 ждёт GO аудитора и owner decision, ступени 5–6 не начаты; живые дети перечислены в теле эпика.
ЧТО НУЖНО=дети: done=0, в работе=4 (WEB-082/470/300/032), parked=1 (WEB-306), ждут владельца=2 (WEB-566/DNS); triage-neo 4712
Воркер
не привязан — привязать: curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \ -d '{"issueId":"WEB-282","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-13T12:02:06.958Z