Files
Investidor-V2/app/Console/Commands/ReconcileMneCompatibility.php
T
nala 3dc7c5c649
tests / ci (push) Canceled after 0s
commit 30/9
2026-09-30 09:05:43 +02:00

49 lines
2.8 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
final class ReconcileMneCompatibility extends Command
{
protected $signature = 'mne:reconcile-compatibility {--fail-on-difference : Return failure while any reconciliation or activation gate remains open}';
protected $description = 'Read-only compatibility counts, fingerprints and activation blockers';
public function handle(): int
{
$report = DB::transaction(function (): array {
DB::statement('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ ONLY');
$domains = [];
foreach (['identity' => ['users', 'identity_links', 'user_id'], 'sector' => ['sectors', 'sector_links', 'sector_id'],
'business' => ['existing_businesses', 'business_links', 'legacy_business_id']] as $domain => [$source, $target, $key]) {
$checksums = [];
$stale = 0;
$missing = 0;
foreach (DB::table('public.'.$source)->orderBy('id')->cursor() as $row) {
$checksum = hash('sha256', json_encode((array) $row, JSON_THROW_ON_ERROR));
$checksums[] = $checksum;
$link = DB::table('mne.'.$target)->where($key, $row->id)->first();
$missing += $link === null ? 1 : 0;
$stale += $link !== null && $link->source_checksum !== $checksum ? 1 : 0;
}
$domains[$domain] = ['source_count' => count($checksums), 'link_count' => DB::table('mne.'.$target)->count(),
'pending_count' => DB::table('mne.'.$target)->where('status', '<>', 'active')->count(),
'missing' => $missing, 'stale_checksums' => $stale, 'checksum' => hash('sha256', implode('', $checksums))];
}
$role = DB::selectOne('SELECT rolsuper,rolcreaterole FROM pg_roles WHERE rolname=current_user');
return ['domains' => $domains, 'unresolved_rejections' => DB::table('mne.compatibility_rejections')->whereNull('resolved_at')->count(),
'runtime_is_superuser' => (bool) $role->rolsuper, 'runtime_can_create_roles' => (bool) $role->rolcreaterole,
'canonical_reads_ready' => false, 'canonical_writes_ready' => false,
'blockers' => ['Full canonical response mapping and authorization parity not certified',
'Legacy intake does not capture a sector', 'Runtime privilege separation requires verification with deployment credentials']];
});
$this->line(json_encode($report, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
// This release has no certified canonical adapter: strict gate checks cannot succeed yet.
return $this->option('fail-on-difference') ? self::FAILURE : self::SUCCESS;
}
}