From 18e8c2cc9fa343cdfe1258ed7fecbf2bd2141f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Fri, 29 May 2026 17:25:35 +0300 Subject: [PATCH] =?UTF-8?q?test(audit):=20drop=20pre-rebuild=20sanity-chec?= =?UTF-8?q?k=20=D0=B2=20multi-tenant=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test env (`SharesSupplierPdo` trait + postgres superuser) обходит RLS, поэтому trigger `audit_chain_hash()` в тестах пишет global chain, не per-tenant. Это расхождение с prod (где RLS активен и trigger пишет per-tenant) валидно — но делает pre-rebuild sanity-check невыполнимым assumption'ом. Multi-tenant test теперь проверяет только self-consistency post-rebuild: rebuild должен produce chain matching своему partition_clause. Pre-Task-4 (global LAG): post-rebuild verify с PARTITION BY tenant_id → mismatch → RED (текущее состояние). Post-Task-4 (per-tenant LAG): post-rebuild verify с PARTITION BY tenant_id → match → GREEN. Prod RLS-aware trigger semantics валидируется live `audit:verify-chains`, не в этом тесте. Ref: docs/superpowers/plans/2026-05-29-audit-rebuild-per-tenant-fix.md Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Feature/Audit/AuditRebuildChainTest.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/app/tests/Feature/Audit/AuditRebuildChainTest.php b/app/tests/Feature/Audit/AuditRebuildChainTest.php index d77a76a3..97c9291b 100644 --- a/app/tests/Feature/Audit/AuditRebuildChainTest.php +++ b/app/tests/Feature/Audit/AuditRebuildChainTest.php @@ -253,11 +253,16 @@ it('audit:rebuild-chain produces per-tenant chain matching trigger semantics в $partition = 'activity_log_y'.now()->format('Y').'_m'.now()->format('m'); $firstId = (int) DB::connection('pgsql_supplier')->table($partition)->min('id'); - // Sanity: верификатор должен признать целостность сразу после INSERT'а через триггер. - $preMismatches = checkPartitionIntegrity($partition, 'PARTITION BY tenant_id', ACTIVITY_LOG_ROW_EXPR); - expect($preMismatches)->toBe(0, 'Trigger writes per-tenant chains correctly'); + // NB: pre-rebuild sanity-check на trigger output опущен намеренно — в test env + // `SharesSupplierPdo` trait + postgres superuser обходят RLS, и trigger пишет + // global chain, а не per-tenant. На prod RLS активен и trigger пишет per-tenant + // (валидация — live `audit:verify-chains` на проде, не в этом тесте). + // + // Что тестируется здесь: AFTER rebuild чейн должен match семантике своего + // partition_clause (self-consistency). Pre-Task-4 rebuild делает global LAG → + // verify с PARTITION BY tenant_id обнаруживает mismatch → RED. Post-Task-4 + // rebuild делает per-tenant LAG → verify с PARTITION BY tenant_id match → GREEN. - // Запускаем rebuild с самого начала партиции. $exit = Artisan::call('audit:rebuild-chain', [ '--partition' => $partition, '--from-id' => $firstId, @@ -265,10 +270,8 @@ it('audit:rebuild-chain produces per-tenant chain matching trigger semantics в ]); expect($exit)->toBe(0); - // После rebuild цепочки должны остаться intact per-tenant. - // RED phase: global rebuild ломает chain (LAG без PARTITION BY смешивает tenants). $postMismatches = checkPartitionIntegrity($partition, 'PARTITION BY tenant_id', ACTIVITY_LOG_ROW_EXPR); - expect($postMismatches)->toBe(0, 'Rebuild должен сохранить per-tenant chain (ADR-018)'); + expect($postMismatches)->toBe(0, 'Rebuild должен produce per-tenant chain matching PARTITION BY tenant_id semantics (ADR-018)'); }); it('audit:rebuild-chain produces global chain for BYPASSRLS auth_log', function (): void {