make(Kernel::class)->bootstrap(); require $root.'/integrations/sgf/operational/bootstrap.php'; if (getenv('IR_RESTORE_VERIFY') === '1') { $db = DB::connection(); $budget = DB::table('cb_budgets')->first(); $scope = ['tenant_id' => $budget->tenant_id, 'company_id' => $budget->company_id, 'unit_id' => $budget->unit_id]; $actor = $budget->created_by; auth()->loginUsingId($actor); app(CompanyContext::class)->selectFor($actor, ...array_values($scope)); config(['purchasing-operational.enabled' => true, 'purchasing-operational.target' => Installation::target($db), 'purchasing-operational.scopes' => [implode(':', $scope)]]); BudgetAdapter::guard(); $receipt = $db->table('sgc_installations')->first(); if ($db->table('cb_budget_entries')->where('kind', 'reserve')->count() !== 1 || ! hash_equals($receipt->schema_signature, Installation::signature($db, Installation::tables()))) { throw new RuntimeException('Operational recovery differs.'); } if (app(Permissions::class)->has($actor, $scope['tenant_id'], $scope['company_id'], 'purchasing_budget.record', $scope['unit_id'])) { throw new RuntimeException('Restored revocation was lost.'); } echo json_encode(['verified' => true, 'production_environment' => app()->environment('production'), 'database_outside_QA_prefix' => ! str_starts_with($db->getDatabaseName(), 'budget_core_sgf_'), 'schema_receipt_and_budget_reservation_preserved' => true, 'revocation_preserved' => true], JSON_THROW_ON_ERROR); exit(0); } BudgetAdapter::guard(); require $host.'/packages/budget-control/tests/sgf-schema.php'; if (getenv('IR_CALIBRATE') === '1') { echo json_encode(['passed' => true, 'schema_signature' => Installation::signature(DB::connection(), Installation::TABLES)], JSON_THROW_ON_ERROR); exit(0); } require $host.'/packages/budget-control/tests/host-support.php'; $f = budgetQaFixture('sgf'); budgetQaCreate('sgf', $f, 1000000, true); $db = DB::connection(); $scope = $f['scope']; $ctx = app(CompanyContext::class); auth()->loginUsingId($f['actor']); $ctx->selectFor($f['actor'], $scope['tenant_id'], $scope['company_id'], $scope['unit_id']); $target = Installation::target($db); $beforeGrants = DB::table('permission_grants')->count(); $beforeBudget = DB::table('cb_budgets')->first(); $checks = []; $check = function ($ok, $name) use (&$checks) { if (! $ok) { throw new RuntimeException($name); } $checks[] = $name; }; $deny = function (callable $call, string $message) use ($check) { try { $call(); throw new LogicException('Unexpected success'); } catch (RuntimeException $error) { $check($error->getMessage() === $message, $message); } }; $cli = function (array $args) use ($host, $root) { $process = new Process(['powershell.exe', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $host.'/scripts/sgf.ps1', 'php', $root.'/scripts/sgf-internal-install.php', ...$args], $host, ['PG_RESTORE_BINARY' => 'C:/Program Files/PostgreSQL/17/bin/pg_restore.exe'], null, 60); $process->run(); return $process; }; $plan = $cli(['plan', $host]); $plan->mustRun(); $planResult = json_decode($plan->getOutput(), true, 16, JSON_THROW_ON_ERROR); $check($planResult['target_sha256'] === $target && ! $planResult['schema_prepared'] && ! $db->getSchemaBuilder()->hasTable('sgc_installations'), 'CLI plan is read-only and identifies destination'); $backup = sys_get_temp_dir().'/sgf-install-backup-'.bin2hex(random_bytes(6)).'.dump'; $connection = $db->getConfig(); $dump = new Process(['C:/Program Files/PostgreSQL/17/bin/pg_dump.exe', '--format=custom', '--file='.$backup, '--dbname='.$db->getDatabaseName()], null, ['PGHOST' => $connection['host'], 'PGPORT' => (string) $connection['port'], 'PGUSER' => $connection['username'], 'PGPASSWORD' => $connection['password']], null, 60); $dump->mustRun(); $backupHash = hash_file('sha256', $backup); $invalidBackup = $cli(['migrate', $host, $target, $backup, str_repeat('0', 64), 'Synthetic operator', $planResult['manifest_sha256']]); $check(! $invalidBackup->isSuccessful() && str_contains($invalidBackup->getErrorOutput(), 'Backup ou manifesto'), 'CLI refuses unverified backup before schema write'); $deny(fn () => Installation::migrate($db, str_repeat('0', 64), str_repeat('a', 64), 'Synthetic operator'), 'Destino, backup ou operador não conferidos.'); $deny(fn () => DB::transaction(function () use ($db, $target) { $db->getSchemaBuilder()->drop('cb_audit'); Installation::migrate($db, $target, str_repeat('a', 64), 'Synthetic operator'); }), 'Schema orçamental parcial; não completar às cegas.'); $deny(fn () => DB::transaction(function () use ($db, $target) { $db->statement('ALTER TABLE cb_budgets ADD COLUMN unexpected_field text'); Installation::migrate($db, $target, str_repeat('a', 64), 'Synthetic operator'); }), 'Schema orçamental incompatível com o contrato aceite.'); try { DB::transaction(function () use ($db, $target, $check, $scope, $f) { foreach (array_reverse(Installation::TABLES) as $table) { $db->getSchemaBuilder()->drop($table); } DB::table('permission_grants')->where('permission', 'like', 'purchasing_budget.%')->delete(); $db->statement('ALTER TABLE permission_grants DROP CONSTRAINT permission_grants_scope_check'); $db->statement("ALTER TABLE permission_grants ADD CONSTRAINT permission_grants_scope_check CHECK ((permission IN ('company.view','company.edit','unit.create','access.manage') AND unit_id IS NULL) OR (permission IN ('unit.view','unit.edit') AND unit_id IS NOT NULL))"); $result = Installation::migrate($db, $target, str_repeat('a', 64), 'Synthetic operator'); $check($result['prepared'] && DB::table('cb_budgets')->count() === 0, 'clean budget schema installed without synthetic records'); DB::table('permission_grants')->insert($scope + ['user_id' => $f['actor'], 'permission' => 'purchasing_budget.view', 'created_at' => now(), 'updated_at' => now()]); $check(true, 'clean identity catalogue supports budget rights without automatic grants'); throw new RuntimeException('Restore isolated existing fixture'); }); } catch (RuntimeException $error) { if ($error->getMessage() !== 'Restore isolated existing fixture') { throw $error; } } $fail = true; DB::listen(function ($q) use (&$fail) { if ($fail && str_contains($q->sql, 'create table "ir_events"')) { $fail = false; throw new RuntimeException('Injected operational DDL failure'); } }); $deny(fn () => Installation::migrate($db, $target, str_repeat('a', 64), 'Synthetic operator'), 'Injected operational DDL failure'); $check(! $db->getSchemaBuilder()->hasTable('ir_requests') && ! $db->getSchemaBuilder()->hasTable('sgc_installations'), 'failed installation leaves no partial module or receipt'); $check((array) DB::table('cb_budgets')->first() === (array) $beforeBudget && DB::table('permission_grants')->count() === $beforeGrants, 'failed preparation preserves existing budget and rights'); $migrate = $cli(['migrate', $host, $target, $backup, $backupHash, 'Synthetic deployment operator', $planResult['manifest_sha256']]); if (! $migrate->isSuccessful()) { throw new RuntimeException($migrate->getErrorOutput()); } $result = json_decode($migrate->getOutput(), true, 16, JSON_THROW_ON_ERROR); $check($result['prepared'] && ! $result['activated'], 'schema prepared without code activation'); $check(DB::table('sgc_installations')->value('backup_sha256') === $backupHash, 'CLI records actual verified custom backup hash'); unlink($backup); $check(Installation::migrate($db, $target, str_repeat('a', 64), 'Synthetic deployment operator')['replayed'] && DB::table('sgc_installations')->count() === 1, 'installation retry preserves one receipt'); $check(DB::table('permission_grants')->count() === $beforeGrants && (array) DB::table('cb_budgets')->first() === (array) $beforeBudget, 'successful preparation preserves grants and approved budget'); $app->detectEnvironment(fn () => 'production'); config(['purchasing-operational.enabled' => true, 'purchasing-operational.target' => $target, 'purchasing-operational.scopes' => [implode(':', $scope)]]); BudgetAdapter::guard(); $check(true, 'operational composition works outside QA environment'); $reservation = app(BudgetAdapter::class)->record(User::findOrFail($f['actor']), $f['origin'], 'reserve', 11600, 10000); $check($reservation !== null && DB::table('cb_budget_entries')->where('kind', 'reserve')->count() === 1, 'operational composition reuses existing budget reservation motor'); DB::table('permission_grants')->where($scope)->where('user_id', $f['actor'])->where('permission', 'purchasing_budget.record')->delete(); try { app(BudgetAdapter::class)->record(User::findOrFail($f['actor']), $f['origin'], 'release'); throw new LogicException('Revoked right accepted'); } catch (HttpException $error) { $check($error->getStatusCode() === 403, 'operational budget checks revoked permission'); } config(['purchasing-operational.scopes' => []]); try { BudgetAdapter::guard(); throw new LogicException('Unconfigured unit accepted'); } catch (HttpException $error) { $check($error->getStatusCode() === 403, 'unconfigured operational unit refused'); } config(['purchasing-operational.scopes' => [implode(':', $scope)]]); $db->statement('ALTER TABLE ir_requests ADD COLUMN unexpected_extension text'); try { BudgetAdapter::guard(); throw new LogicException('Divergent schema accepted'); } catch (HttpException $error) { $check($error->getStatusCode() === 503, 'divergent schema refused without rewriting it'); } $db->statement('ALTER TABLE ir_requests DROP COLUMN unexpected_extension'); try { DB::transaction(fn () => DB::table('sgc_installations')->delete()); throw new LogicException('Installation history deleted'); } catch (QueryException $error) { $check(str_contains($error->getMessage(), 'Preserve installation history'), 'schema preparation history immutable'); } $config = $db->getConfig(); $dump = new Process(['C:/Program Files/PostgreSQL/17/bin/pg_dump.exe', '--format=custom', '--file='.getenv('IR_OPERATIONAL_BACKUP'), '--dbname='.$db->getDatabaseName()], null, ['PGHOST' => $config['host'], 'PGPORT' => (string) $config['port'], 'PGUSER' => $config['username'], 'PGPASSWORD' => $config['password']], null, 60); $dump->mustRun(); echo json_encode(['passed' => true, 'checks' => $checks, 'installed_on_destination' => false, 'activated' => false], JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);