$line) { if (str_starts_with(ltrim($line), '--')) { continue; // строки-комментарии (документация) — не код политики } if (preg_match($unsafe, $line)) { $offenders[] = 'schema.sql:'.($i + 1).' → '.trim($line); } } expect($offenders)->toBe( [], 'Небезопасное приведение GUC к bigint (без NULLIF) в schema.sql вернёт инцидент входа на Managed PG/PgBouncer:' .PHP_EOL.implode(PHP_EOL, $offenders) ); }); it('5 bootstrap-таблиц в schema.sql сохраняют ветку "NULLIF(...) IS NULL OR ..."', function () { $schema = file_get_contents(base_path('..').'/db/schema.sql'); expect($schema)->not->toBeFalse(); foreach (['users', 'auth_log', 'email_verifications', 'user_recovery_codes', 'user_sessions'] as $table) { // В пределах одного CREATE POLICY ... ON ... ; должно быть условие // NULLIF(current_setting('app.current_tenant_id', true), '') IS NULL. $pattern = '/POLICY tenant_isolation ON '.preg_quote($table, '/') ."\\b[^;]*?NULLIF\\(current_setting\\('app\\.current_tenant_id', true\\), ''\\)\\s*IS NULL/s"; expect((bool) preg_match($pattern, $schema))->toBeTrue( "Таблица {$table} должна иметь bootstrap-ветку «NULLIF(...) IS NULL OR ...» " .'(резолв до tenant-контекста на auth-роутах). Иначе вход/2FA/подтверждение почты сломаются.' ); } });