make(Kernel::class)->bootstrap(); $db = null; try { $db = DB::connection(); if ($db->getDriverName() !== 'pgsql') { throw new RuntimeException('PostgreSQL expected'); } $db->beginTransaction(); $db->statement('SET TRANSACTION READ ONLY'); $identity = $db->selectOne('select current_database() as database, inet_server_addr()::text as address, inet_server_port() as port'); $tables = array_column($db->select("select tablename from pg_tables where schemaname='public' order by tablename"), 'tablename'); $required = ['users', 'tenants', 'companies', 'units', 'company_memberships', 'permission_grants', 'identity_audit']; $budget = ['cb_centres', 'cb_origins', 'cb_budgets', 'cb_budget_entries', 'cb_budget_consumptions', 'cb_budget_reinforcements', 'cb_audit']; $internal = ['ir_requests', 'ir_steps', 'ir_events', 'ir_commands', 'ir_policies', 'ir_policy_versions', 'sgc_installations']; $column = $db->selectOne("select character_maximum_length from information_schema.columns where table_schema='public' and table_name='permission_grants' and column_name='permission'"); $constraint = $db->selectOne("select pg_get_constraintdef(oid) as definition from pg_constraint where conrelid='permission_grants'::regclass and conname='permission_grants_scope_check'"); $privileges = $db->selectOne("select has_schema_privilege(current_user,'public','CREATE') as can_create,pg_has_role(current_user,(select relowner from pg_class where oid='permission_grants'::regclass),'USAGE') as can_alter_permissions"); $preserve = []; foreach (['permission_grants', 'company_memberships', 'identity_audit'] as $table) { $rows = $db->select('select to_jsonb(t)::text as value from "'.$table.'" t order by to_jsonb(t)::text'); $preserve[$table] = ['rows' => count($rows), 'sha256' => hash('sha256', json_encode(array_column($rows, 'value'), JSON_THROW_ON_ERROR))]; } $counts = ['companies' => $db->table('companies')->count(), 'units' => $db->table('units')->count(), 'company_admin_grants' => $db->table('permission_grants')->where('permission', 'access.manage')->whereNull('unit_id')->count()]; $roles = $db->selectOne("select current_user as runtime_role,(select pg_get_userbyid(relowner) from pg_class where oid='permission_grants'::regclass) as permissions_owner"); $ownerCapabilities = $db->selectOne("select rolcanlogin as can_login,has_schema_privilege(rolname,'public','CREATE') as can_create_public from pg_roles where rolname=?", [$roles->permissions_owner]); $state = ['checked_at' => gmdate('c'), 'host' => $host, 'app_url' => config('app.url'), 'environment' => $app->environment(), 'php' => PHP_VERSION, 'database' => ['driver' => $db->getDriverName(), 'configured_host' => $db->getConfig('host'), 'configured_port' => $db->getConfig('port'), 'configured_database' => $db->getDatabaseName(), 'actual' => $identity], 'schema' => ['public_table_count' => count($tables), 'missing_foundation' => array_values(array_diff($required, $tables)), 'existing_budget_tables' => array_values(array_intersect($budget, $tables)), 'existing_integration_tables' => array_values(array_intersect($internal, $tables)), 'budget_ui_support_tables_present' => array_values(array_intersect(['cb_ui_commands', 'cb_consumption_sources'], $tables)), 'permission_column_length' => $column?->character_maximum_length, 'scope_constraint_present' => $constraint !== null, 'scope_constraint_sha256' => $constraint ? hash('sha256', $constraint->definition) : null, 'ddl_privileges' => $privileges], 'database_roles' => $roles, 'config_cached' => $app->configurationIsCached(), 'owner_capabilities' => $ownerCapabilities, 'preservation_baseline' => $preserve, 'organisation_counts' => $counts, 'purchasing_pointer' => json_decode(file_get_contents($host.'/packages/purchasing/current.json'), true, 16, JSON_THROW_ON_ERROR), 'pointer_sha256' => hash_file('sha256', $host.'/packages/purchasing/current.json'), 'bundle_exists' => is_dir($host.'/packages/internal-requisitions'), 'maintenance_marker_present' => is_file($host.'/storage/framework/down'), 'operational_config_file_present' => is_file($host.'/config/purchasing-operational.php'), 'read_only_transaction' => true, 'installed' => false]; $db->rollBack(); echo json_encode($state, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR)."\n"; } catch (Throwable $error) { if ($db && $db->transactionLevel() > 0) { $db->rollBack(); }fwrite(STDERR, 'Read-only inventory failed: '.get_class($error)."\n"); exit(1); }