71 lines
4.5 KiB
PHP
71 lines
4.5 KiB
PHP
<?php
|
|
// Read-only target inventory. No providers, job execution, schema, cache or key changes.
|
|
$root = dirname(__DIR__);
|
|
require $root.'/vendor/autoload.php';
|
|
ini_set('zend.exception_ignore_args', '1');
|
|
set_exception_handler(static function (Throwable $exception): void {
|
|
fwrite(STDERR, 'Service plan inventory stopped: '.get_class($exception).PHP_EOL);
|
|
exit(1);
|
|
});
|
|
$app = require $root.'/bootstrap/app.php';
|
|
(new Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables)->bootstrap($app);
|
|
(new Illuminate\Foundation\Bootstrap\LoadConfiguration)->bootstrap($app);
|
|
$c = config('database.connections.'.config('database.default'));
|
|
if ($c['driver'] !== 'pgsql' || ! empty($c['url']) || ! in_array($c['host'], ['127.0.0.1', 'localhost'], true)
|
|
|| (int) $c['port'] !== 5432 || $c['database'] !== 'investemoz') {
|
|
throw new RuntimeException('Target mismatch.');
|
|
}
|
|
$pdo = new PDO('pgsql:host='.$c['host'].';port=5432;dbname=investemoz', $c['username'], $c['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
|
$pdo->exec('BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY');
|
|
if ($pdo->query('SELECT current_database()')->fetchColumn() !== 'investemoz'
|
|
|| (int) $pdo->query('SELECT inet_server_port()')->fetchColumn() !== 5432) {
|
|
throw new RuntimeException('Server identity mismatch.');
|
|
}
|
|
$counts = [];
|
|
foreach (['users', 'organizations', 'memberships', 'jobs', 'failed_jobs'] as $table) {
|
|
$counts[$table] = (int) $pdo->query('SELECT count(*) FROM "'.$table.'"')->fetchColumn();
|
|
}
|
|
$jobs = $pdo->query('SELECT queue,count(*) AS count FROM jobs GROUP BY queue ORDER BY queue')->fetchAll(PDO::FETCH_ASSOC);
|
|
$eligible = 0;
|
|
foreach ($pdo->query('SELECT email,email_verified_at,two_factor_secret,two_factor_confirmed_at FROM users')->fetchAll(PDO::FETCH_ASSOC) as $user) {
|
|
if ($user['email_verified_at'] && $user['two_factor_secret'] && $user['two_factor_confirmed_at']
|
|
&& in_array(strtolower($user['email']), config('portal.managers', []), true)) {
|
|
$eligible++;
|
|
}
|
|
}
|
|
$ledger = $pdo->query("SELECT migration FROM migrations WHERE migration IN ('2026_10_09_030000_extend_opportunity_resources','2026_10_10_040000_create_portal_profile_authorization','2026_10_10_050000_extend_organization_country') ORDER BY migration")->fetchAll(PDO::FETCH_COLUMN);
|
|
$pdo->exec('ROLLBACK');
|
|
$gd = extension_loaded('gd') ? gd_info() : [];
|
|
$encoded = false;
|
|
if (function_exists('imagewebp')) {
|
|
$image = imagecreatetruecolor(8, 8);
|
|
ob_start();
|
|
imagewebp($image, null, 80);
|
|
$bytes = ob_get_clean();
|
|
$encoded = is_string($bytes) && substr($bytes, 0, 4) === 'RIFF' && substr($bytes, 8, 4) === 'WEBP';
|
|
unset($bytes, $image);
|
|
}
|
|
$proof = [
|
|
'at' => gmdate('c'), 'target' => 'investemoz:5432', 'scope' => 'CLI, static config and read-only SQL; not web SAPI or a worker proof',
|
|
'counts' => $counts, 'queues' => $jobs, 'installed' => $ledger,
|
|
'existing_verified_managers_with_mfa' => $eligible,
|
|
'php' => ['version' => PHP_VERSION, 'sapi' => PHP_SAPI, 'binary' => PHP_BINARY, 'ini' => php_ini_loaded_file(),
|
|
'ini_sha256' => hash_file('sha256', php_ini_loaded_file()),
|
|
'modules' => array_values(array_intersect(get_loaded_extensions(), ['pdo_pgsql', 'pgsql', 'openssl', 'fileinfo', 'gd', 'mbstring', 'intl', 'zip', 'curl', 'pcntl'])),
|
|
'gd' => $gd['GD Version'] ?? null, 'webp_supported' => $gd['WebP Support'] ?? false,
|
|
'webp_memory_encoding_passed' => $encoded,
|
|
'memory_limit' => ini_get('memory_limit'), 'upload_max_filesize' => ini_get('upload_max_filesize'),
|
|
'post_max_size' => ini_get('post_max_size'), 'max_execution_time' => ini_get('max_execution_time'),
|
|
'pcntl' => extension_loaded('pcntl')],
|
|
'queue' => ['driver' => config('queue.default'), 'name' => config('queue.connections.database.queue'),
|
|
'retry_after' => config('queue.connections.database.retry_after')],
|
|
'scanner' => ['host' => config('services.malware.host'), 'port' => config('services.malware.port'),
|
|
'max_signature_age_hours' => config('services.malware.max_signature_age_hours')],
|
|
'country_enabled' => (bool) config('portal.organization_country_enabled'),
|
|
'profile_enabled' => (bool) config('portal.profile_access_enabled'),
|
|
'active_database_writes' => 0, 'providers_booted' => false, 'secrets_in_output' => false,
|
|
];
|
|
$out = $root.'/storage/app/private/investmoz-v2/portal-audit/workflow-service-plan-inventory-20261011.json';
|
|
file_put_contents($out, json_encode($proof, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR));
|
|
echo json_encode($proof, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR).PHP_EOL;
|