# Handoff: cleanup `activity_log_y2026_m05` после ADR-018 fix

**Что:** удалить 6 mismatches в `activity_log_y2026_m05` через re-run исправленного `audit:rebuild-chain` per ADR-018.

**Когда:** после merge всех task-коммитов плана `2026-05-29-audit-rebuild-per-tenant-fix.md` в `origin/main` и успешного deploy через `gh workflow run deploy.yml`.

**Кто:** controller / Дмитрий (mutating prod operation — требует `confirm_apply=true`).

## Pre-flight checks

1. **Deploy завершён успешно** — `gh run list --workflow=deploy.yml --limit 1` показывает `success`.

2. **Master verify падает только на 6 строках `activity_log_y2026_m05`** (baseline до cleanup'а):

   ```bash
   gh workflow run artisan-run.yml -f command=$(printf 'audit:verify-chains' | base64 -w0)
   ```

   Дождаться `success` workflow → читать output. Expected: `activity_log_y2026_m05: 6 mismatch(es), first broken id=NNN`, остальные партиции `intact`.

## Dry-run

3. **Запустить rebuild --dry-run** на проде (через artisan-run workflow whitelist):

   ```bash
   gh workflow run artisan-run.yml -f command=$(printf 'audit:rebuild-chain --partition=activity_log_y2026_m05 --from-id=NNN --dry-run' | base64 -w0)
   ```

   где `NNN` — `first broken id` из шага 2.

   Expected output (через ADR-018 fix Task 4):
   - `Партиция : activity_log_y2026_m05`
   - `Родитель : activity_log`
   - `Scope    : PARTITION BY tenant_id` ← **критично: НЕ `global`**
   - `От id    : NNN`
   - `Строк    : M`
   - `--dry-run: UPDATE не выполнен.`

   Прикинуть `M` на разумность (сотни-тысячи, не миллионы). Если `Scope` = `global` — это значит deploy не подхватил Task 4 fix, **НЕ продолжать**, открыть инцидент.

## Apply (mutating)

4. **Запустить rebuild с force + confirm_apply**:

   ```bash
   gh workflow run artisan-run.yml \
     -f command=$(printf 'audit:rebuild-chain --partition=activity_log_y2026_m05 --from-id=NNN --force' | base64 -w0) \
     -f confirm_apply=true
   ```

   Expected output: `Обновлено M строк в activity_log_y2026_m05.`

## Verify

5. **Запустить verify ещё раз** (тот же шаг 2 базовая команда):

   ```bash
   gh workflow run artisan-run.yml -f command=$(printf 'audit:verify-chains' | base64 -w0)
   ```

   Expected: `activity_log_y2026_m05: chain intact`. Все 6 audit-таблиц `intact`.

   Если ещё mismatches — **НЕ продолжать**, открыть отдельный incident (signal что rebuild не покрыл какой-то edge case).

## Post-cleanup

6. **Закрыть incident-запись** в `incidents_log` через SaaS-admin UI (Системные инциденты): `resolved_at = now()`, `root_cause = "cleanup per ADR-018 rebuild fix"`.

7. **Обновить memory** `feedback_audit_chain_algorithm_divergence.md` — статус «6 mismatches исчезли DD.MM.2026, ADR-018 implementation Stage 5 follow-up закрыт».

## Что фактически произошло 29.05.2026

Cleanup выполнен 29.05.2026 ~18:00 МСК. **3 партиции были affected, не 1 (как изначально думали)** — race condition бил по всем 3 tenant-scoped audit-таблицам:

| Партиция | first broken id | mismatches | tenants | rows rebuilt |
|----------|-----------------|------------|---------|--------------|
| `activity_log_y2026_m05` | 599 | 6 → 0 | 3 | 216 |
| `balance_transactions_y2026_m05` | 462 | 6 → 0 | 3 | 243 |
| `pd_processing_log_y2026_m05` | 191 | 6 → 0 | 3 | 220 |
| **Всего** | — | **18 → 0** | **9 scopes** | **679** |

После всех 3 rebuild'ов — `audit:verify-chains` вернул `All audit chains intact.` на всех 6 audit-таблицах × ~14 партиций каждая.

### Архитектурный найден gap: Laravel AuditRebuildChain не работает на проде

Когда попытались выполнить шаг 4 этого handoff'а (`audit:rebuild-chain ... --force` через `artisan-run.yml`), получили:

```
SQLSTATE[42501]: Insufficient privilege: permission denied to set parameter "session_replication_role"
(Connection: pgsql_supplier, Role: crm_supplier_worker)
```

**Причина:** `SET session_replication_role` требует SUPERUSER privilege. Laravel connection `pgsql_supplier` использует роль `crm_supplier_worker` (BYPASSRLS, но не superuser). Tests проходят потому что test env подключается как `postgres` superuser. **Это был первый запуск rebuild'а на проде когда-либо — никто раньше не натыкался на этот gap.**

**Workaround использованный 29.05:** новый workflow [.github/workflows/sql-rebuild-audit-chain.yml](../../.github/workflows/sql-rebuild-audit-chain.yml) выполняет ту же per-tenant логику через `sudo -u postgres psql` (постгресовый superuser) с PL/pgSQL DO-блоком, mirror'ящим `AuditRebuildChain::rebuildScope()` PHP логику. Поддерживает 4 tenant-scoped таблицы: `activity_log`, `balance_transactions`, `pd_processing_log`, `tenant_operations_log`.

**Future fix (out of scope этого handoff'а):** либо добавить `pgsql_postgres` connection в Laravel (`config/database.php`) под postgres superuser'ом + переписать `AuditRebuildChain` использовать его; либо grant'нуть `crm_supplier_worker` соответствующий privilege (если PG разрешит — `session_replication_role` обычно strictly superuser). Открыть отдельный план.

## Rollback

Если шаг 4 повёл себя неожиданно (например, обновлено существенно больше строк чем dry-run):

- **НЕ паниковать** — записи защищены `audit_block_mutation` триггером (UPDATE/DELETE невозможен извне rebuild'а через `session_replication_role = 'replica'`).
- Восстановить из бэкапа PG (последний автоматический + `audit_chain_hash`-snapshot перед запуском).
- Open incident, классифицировать root cause.

## Related

- ADR-018: [docs/adr/ADR-018-audit-chain-per-tenant-semantics.md](../adr/ADR-018-audit-chain-per-tenant-semantics.md)
- Plan: [docs/superpowers/plans/2026-05-29-audit-rebuild-per-tenant-fix.md](../superpowers/plans/2026-05-29-audit-rebuild-per-tenant-fix.md)
- Stage 5 #1 finding: [docs/superpowers/plans/2026-05-29-audit-chain-race-fix.md](../superpowers/plans/2026-05-29-audit-chain-race-fix.md)
