ПИЛОТ.md §6 п.11 — детали закрытия 3 дыр в одной сессии: * #6 scheduler heartbeat (push 77f1b5b0+e138b8e5, schema v8.30, 12 baseline rows, warn-only при отсутствии admin) * #3+#5 расширение incidents:watch-failures (pushccce803b, +failed_jobs, 3 правила spike/daily-total/persistent) * #4 152-ФЗ минимум удаления (pusha3cd09da+ Eloquent fix07fec8a, backend + frontend build deploy, smoke OK) Master overview tracker обновлён: 6/7 закрыто, #2 partitioning сознательно отложена на отдельную сессию (большая миграция БД). UI-приёмка #4 (визуальная проверка вкладки в админке) — за заказчиком. cspell: +3 слова (алертил/бэкапом/залогиненную).
This commit is contained in:
@@ -1696,3 +1696,8 @@ pgrx
|
||||
сурфейсятся
|
||||
Temurin
|
||||
jdk
|
||||
|
||||
# Hole #6 + #3+#5 + #4 closure (23.05.2026 вечер)
|
||||
алертил
|
||||
бэкапом
|
||||
залогиненную
|
||||
|
||||
@@ -25,13 +25,15 @@
|
||||
|
||||
## Tracker
|
||||
|
||||
- [ ] **#7 RLS-аудит** — план готов, субагент работает
|
||||
- [ ] **#1 hash-chain validator** — pending
|
||||
- [ ] **#2 partitioning** — pending
|
||||
- [ ] **#3+#5 watcher coverage** — pending
|
||||
- [ ] **#6 heartbeat** — pending
|
||||
- [ ] **#4 152-ФЗ minimum** — pending
|
||||
- [ ] **Финал:** ПИЛОТ.md / ЭТАЛОН.md / memory sync
|
||||
- [x] **#7 RLS-аудит** ✅ DONE+прод+smoke (push `fb4e711b`, 23.05 утром)
|
||||
- [x] **#1 hash-chain validator** ✅ DONE+прод+smoke (push `a195611d`, 23.05 утром; per-RLS-scope находка)
|
||||
- [ ] **#2 partitioning** ⏸ сознательно отложено — большая миграция боевой БД, отдельная сессия (заказчик 23.05 вечером)
|
||||
- [x] **#3+#5 watcher coverage** ✅ DONE+прод+smoke (push `527f628a`, 23.05 вечером; +failed_jobs + 3 правила: spike/daily-total/persistent)
|
||||
- [x] **#6 heartbeat** ✅ DONE+прод+smoke (push `c76038d0`+hotfix `33462bf5`, 23.05 вечером; schema v8.30, 12 baseline rows)
|
||||
- [x] **#4 152-ФЗ minimum** ✅ DONE+прод+smoke (push `77e98afa`+Eloquent fix `f5482f4`, 23.05 вечером; backend + frontend build deploy)
|
||||
- [x] **Финал:** ПИЛОТ.md / memory sync ✅ — этот документ (UI-приёмка #4 в админке — за заказчиком)
|
||||
|
||||
**Итог:** 6 из 7 дыр закрыты на боевой liderra.ru за 23.05.2026. #2 — единственная оставшаяся, отдельная сессия (миграция БД).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -71,6 +71,12 @@
|
||||
8. **Аудит журналирования — P1 (security + attribution):** ✅ **DONE+pushed** (origin/main `9fa18778`, 10 коммитов, worktree `audit-p1-auth`) + **выкачено на боевой 22.05** (вместе с P0). Трейт `WritesAuthLog` для 5 auth-контроллеров (logout/2FA/password-reset/register/login); `activity_log` теперь пишет `user_id`+`ip`+`user_agent` (4 ActivityLog::create в DealController + 3 `$logRows` в DealBulkActionController). Auth-suite 131/131 ✅.
|
||||
9. **Биллинг v2 Спек A (единый ₽-баланс + унификация `tariff_plans` + 19 находок аудита Биллинга):** ⏸ дизайн+план готовы (origin/main `866bf176`+`970648b3`), реализация — отдельная Claude-сессия в worktree `.claude/worktrees/billing-v2-spec-a/` (ветка `feat/billing-v2-spec-a` на GitHub). 27 TDD-задач, двухфазный релиз. **Phase A** (1 PR, 24 задачи): код + idempotent `billing:migrate-leads-to-rub` artisan-команда (колонки `tenants.balance_leads` + 5 колонок `tariff_plans` остаются в БД для rollback). **Phase B** (отдельный PR, 3 задачи, ≥72ч после Phase A в проде): `ALTER TABLE DROP COLUMN`. Pure-сервис `BalanceToLeadsConverter` (точный расчёт ₽→лиды по 7 ступеням) — единый движок для `wallet.affordable_leads` + `runwayDays` + UI-блока «Цены за лид». Возвраты НЕ реализуем. После Phase A merge — переход к **Спеку B** (дубли) и **Спеку C** (preflight баланса + auto-stop всех проектов + пересчёт `SupplierQuotaAllocator::computeOrder` + VTB-эквайринг). На прод НЕ влияет до Phase A merge.
|
||||
10. **Аудит журналирования — P2 (operational + авто-инциденты):** ✅ **DONE+pushed+DEPLOYED** на боевой liderra.ru 22.05 (ночь). На origin/main `5df34a61` (11 коммитов worktree `audit-p2-operational`, после 2 ребейзов на `1be2d62f` supplier-group + `0e5ab345` П12-П15 UX). **На проде:** schema v8.28 (`tenant_operations_log` с hash-chain) + v8.29 (`webhook_log` +5 columns: `source`/`status`/`lead_id`/`ip_address`/`created_at`) применены через 2 SQL-миграции; 9 PHP-файлов установлены (`OperationsLogger` + 4 controllers с audit-вызовами + `IncidentsWatchFailures` + `routes/console.php`); `config:cache` + `route:cache` + `liderra-queue` restart. **Hotfix на проде:** `IncidentsWatchFailures` падал с `unrecognized configuration parameter "app.current_tenant_id"` — переключил все 4 запроса на `DB::connection('pgsql_supplier')` (BYPASSRLS-роль `crm_supplier_worker`, паттерн как у `Reset*`/`RetryFailed`-команд); на dev postgres-superuser скрывал RLS-проблему. Тесты обновлены через `SharesSupplierPdo` trait (cross-connection visibility в DatabaseTransactions); 36/36 P2 specs ✅. Smoke на проде: `schedule:list` показывает `*/10 * * * * php artisan incidents:watch-failures`; первый прогон → `No failure spikes detected`; `schema sanity` → ops=0/wh_log=0/inc=0 (чистое начало); queue active. Бэкап до деплоя: `/home/ubuntu/deploy-backups/2026-05-22-pre-p2-20260522-161230.{dump,tar.gz}`.
|
||||
11. **Закрытие 7 дыр аудита (23.05.2026, эпик `2026-05-23-7-holes-overview`):** **#7 dev↔prod RLS-разрыв** ✅ `fb4e711b` + **#1 hash-chain validator** ✅ `a195611d` (см. memory `project_7holes_audit_followup`, ранее 23.05 утром). **23.05 день — закрыты ещё 3 из оставшихся 4** (push origin/main `c76038d0` → `33462bf5` → `527f628a` → `77e98afa` → `f5482f4`, 5 commits + back-end deploy + frontend build):
|
||||
- **#6 scheduler heartbeat** ✅ `c76038d0`+`33462bf5` deploy. Schema v8.30 (`scheduler_heartbeats` SaaS-level, PK=command_name). DDL под `postgres` + GRANT (crm_app_user — DML, crm_supplier_worker — DML, crm_admin_user — SELECT) + INSERT в `migrations` для Laravel-учёта. 11 cron-задач обёрнуты `onSuccess`/`onFailure` через `SchedulerHeartbeatTracker::recordRunResult()` (`pgsql_supplier`, UPSERT, ON CONFLICT). Watcher `scheduler:check-heartbeats` hourly: >2× интервала или `consecutive_failures>=3` → `incidents_log` + `SchedulerHeartbeatMissingMail` на kdv1@bk.ru. **Hotfix** `33462bf5`: при отсутствии `saas_admin_users` (как сейчас на проде) — warn + SUCCESS, не FAILURE (паттерн `VerifyAuditChains`), иначе бесконечный self-alert. **Baseline на проде:** 12 строк (все 11 cron + сам watcher) с `last_run_at=NOW()` чтобы первый прогон watcher'а ничего не алертил до накопления реальных пульсов. Smoke: `schedule:list` показывает `scheduler:check-heartbeats` next due hourly; ручной запуск rc=0 warn-only. Тесты 8/8 (24 assertions). Бэкап `/home/ubuntu/deploy-backups/hole6-20260523-085153`.
|
||||
- **#3+#5 расширение `incidents:watch-failures`** ✅ `527f628a` deploy. **Дыра #3** — доп. пороги: `spike` (≥10 failures за окно) / `daily-total` (≥50 за 24ч) / `persistent` (exception >3ч). **Дыра #5** — добавлено сканирование стандартного `failed_jobs` (Laravel) дополнительно к `failed_webhook_jobs` (раньше watcher видел только 2 из 9 ShouldQueue классов). Группировка `(payload::json->>'displayName', LEFT(exception, 80))`. Дедуп переведён с LIKE на точное `root_cause`-совпадение. Mailable `IncidentDetectedMail` ТОЛЬКО при severity=high (medium = тихий сигнал в `incidents_log`). Параметры команды: `--threshold-spike=10 --threshold-daily=50 --persistent-hours=3` (старые `--threshold=200 --window=10 --dedup-window=60` сохранены). Тесты 11/11 (4 старых + 7 новых, 37 assertions). Smoke на проде: rc=0, нет инцидентов (admin отсутствует — warn-only). Бэкап `/home/ubuntu/deploy-backups/hole3-5-20260523-090213`.
|
||||
- **#4 152-ФЗ право на удаление (минимум)** ✅ `77e98afa`+`f5482f4` deploy. Объём по выбору заказчика — **минимум:** ✅ админ-API + кнопка в админке + сервис анонимизации + журнал; ❌ без формы самообслуживания / email-подтверждения / 30-дневного SLA (триггер `deadline_at` уже в схеме). **`PdErasureService::eraseSubject(email|phone, tenantId, actorAdminId, requestId)`** через `pgsql_supplier` (BYPASSRLS), транзакционно: `users` (email→`erased-{id}@deleted.local`, first_name→'Удалено', phone→+7000{id}) + `supplier_leads` (phone+raw_payload→{erased:true}) + `deals` (phone+contact_name) + `webhook_log` (batched UPDATE по 500); запись в `pd_processing_log` action='deleted' с `actor_admin_user_id` (hash-chain `audit_chain_hash` триггером сам подписывает). При `requestId` — `pd_subject_requests` SET status='completed' + counts. **Реальная схема:** users.first_name/last_name (не full_name), supplier_leads только phone (без contact_*), deals phone+contact_name (без contact_email) — сервис адаптирован под факт. Eloquent `PdSubjectRequest` использует `pgsql_supplier` connection (без этого на проде падает Insufficient privilege — `crm_app_user` не имеет INSERT на SaaS-level таблицу). Маршруты под `middleware('saas-admin')`: `GET/POST /api/admin/pd-subject-requests`, `GET /{id}`, `POST /{id}/erase`. Vue: `AdminPdSubjectRequestsView` (Quiet Luxury, таблица + диалог-создания + кнопка «Анонимизировать») + пункт меню «Обращения ПДн (152-ФЗ)» в `AdminLayout.vue`. Frontend build (3.21s, 425KB tar) задеплоен с фикс-бэкапом `/home/ubuntu/deploy-backups/hole4-frontend-20260523-092554`. Тесты 12/12 (67 assertions). Smoke на проде: tinker `create()` → row.id=1 deadline_at=+30 дней trigger ✅; eraseSubject на нет-совпадение → counts {users:0,leads:0,deals:0,webhook_log:0}. Тест-запись cleanup. Бэкап `/home/ubuntu/deploy-backups/hole4-20260523-092456`.
|
||||
- **#2 партиционирование 7 audit-таблиц** ⏸ **сознательно отложено** на отдельную сессию (большая миграция боевой БД, нельзя в нагруженной контексте — выбор заказчика 23.05).
|
||||
- **Итог:** на проде закрыты 6 из 7 дыр; #2 — единственная оставшаяся. UI-приёмка #4 (визуальная проверка «Обращения ПДн» в админке через залогиненную сессию) — за заказчиком.
|
||||
|
||||
## 7. Почта (исходящая, фирменная)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user