9cf380f170
Append-only journal AJAX-синхронизаций с поставщиком crm.bp-gr.ru. Используется для retry, отладки rt-project-* и алертов менеджеру. - 9 columns: id, supplier_project_id (nullable FK SET NULL), action, request_payload (jsonb), response_body (jsonb), http_status, error_message, duration_ms, created_at - 1 CHECK chk_supplier_sync_log_action (create/update/delete/disable/session_refresh) - 3 индекса: supplier_project_id, action, created_at - REVOKE ALL FROM crm_app_user (DO $$ conditional) - No RLS (SaaS-level) Spec: §4.3 Plan: Task 5 Test: 4/4 passed (table, action enum, FK, no RLS). Schema v8.15 → v8.16. Метрики: 60 таблиц (+1) / 108 индексов (+3). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
2.0 KiB
PHP
71 lines
2.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
/**
|
|
* Plan 1/5 Task 5: supplier_sync_log — SaaS-level audit log синхронизаций с поставщиком.
|
|
*
|
|
* Spec: docs/superpowers/specs/2026-05-10-supplier-integration-design.md §4.3.
|
|
*/
|
|
test('supplier_sync_log table exists with required columns', function () {
|
|
expect(Schema::hasTable('supplier_sync_log'))->toBeTrue();
|
|
|
|
foreach ([
|
|
'id',
|
|
'supplier_project_id',
|
|
'action',
|
|
'request_payload',
|
|
'response_body',
|
|
'http_status',
|
|
'error_message',
|
|
'duration_ms',
|
|
'created_at',
|
|
] as $col) {
|
|
expect(Schema::hasColumn('supplier_sync_log', $col))->toBeTrue("column {$col} missing");
|
|
}
|
|
});
|
|
|
|
test('supplier_sync_log action constrained to allowed enum values', function () {
|
|
$check = DB::selectOne(
|
|
"SELECT pg_get_constraintdef(c.oid) AS def
|
|
FROM pg_constraint c
|
|
JOIN pg_class t ON c.conrelid = t.oid
|
|
WHERE t.relname = 'supplier_sync_log'
|
|
AND c.conname = 'chk_supplier_sync_log_action'"
|
|
);
|
|
|
|
expect($check)->not->toBeNull();
|
|
expect($check->def)
|
|
->toContain("'create'")
|
|
->toContain("'update'")
|
|
->toContain("'delete'")
|
|
->toContain("'disable'")
|
|
->toContain("'session_refresh'");
|
|
});
|
|
|
|
test('supplier_sync_log has nullable FK to supplier_projects', function () {
|
|
$fk = DB::selectOne(
|
|
"SELECT pg_get_constraintdef(c.oid) AS def
|
|
FROM pg_constraint c
|
|
JOIN pg_class t ON c.conrelid = t.oid
|
|
WHERE t.relname = 'supplier_sync_log' AND c.contype = 'f'
|
|
LIMIT 1"
|
|
);
|
|
|
|
expect($fk)->not->toBeNull();
|
|
expect($fk->def)
|
|
->toContain('supplier_projects')
|
|
->toContain('SET NULL');
|
|
});
|
|
|
|
test('supplier_sync_log has NO RLS policy (SaaS-level)', function () {
|
|
$rls = DB::selectOne(
|
|
"SELECT relrowsecurity FROM pg_class WHERE relname = 'supplier_sync_log'"
|
|
);
|
|
|
|
expect((bool) $rls->relrowsecurity)->toBeFalse();
|
|
});
|