Files
SGF/scripts/sgf-assets-preservation.php
2026-11-11 15:04:01 +02:00

9 lines
3.7 KiB
PHP

<?php
$book='8085';require __DIR__.'/sgf-single-bootstrap.php';$backup=json_decode(file_get_contents($s['root'].'/assets-backup-pointer.json'),true)['root'];$before=json_decode(file_get_contents($backup.'/preservation-private.json'),true);$expected=['host.permission_grants'=>5,'host.identity_audit'=>11,'native.gl_accounts'=>5,'native.gl_rules'=>6,'native.gl_proposals'=>2,'native.gl_reviews'=>2,'native.gl_journals'=>2,'native.gl_lines'=>4,'native.gl_commands'=>6,'native.gl_events'=>6,'native.fs_versions'=>4,'native.fs_commands'=>4,'native.fs_results'=>1,'native.fs_result_lines'=>23,'native.audit_logs'=>4];$checks=[];$changes=[];$canonical=fn($r)=>Tempo\Finance\Payables\Payables::canonical((array)$r);
foreach(['host','native']as$name){$db=$name==='host'?$host:$native;foreach($before[$name]as$table=>$json){$key=$name.'.'.$table;$old=json_decode($json,true);$current=$db->table($table)->get()->map(fn($r)=>(array)$r)->all();$seen=[];foreach($current as$r)$seen[$canonical($r)]=true;foreach($old as$r)if(!isset($seen[$canonical($r)]))throw new LogicException('Original row changed: '.$key);$delta=count($current)-count($old);if($delta!==($expected[$key]??0))throw new LogicException('Unexpected append '.$key.' '.$delta.' expected '.($expected[$key]??0));$checks[]=$key;if($delta)$changes[$key]=$delta;}}
foreach($before['files']as$file=>$sha){if(hash_file('sha256',$s['root'].'/'.$file)!==$sha)throw new LogicException('Binding changed '.$file);$checks[]=$file;}
$scope=['tenant_id'=>1,'company_id'=>2,'unit_id'=>2];$grants=$host->table('permission_grants')->where($scope)->where('permission','like','fixed_assets.%')->orderBy('id')->get(['user_id','permission'])->map(fn($r)=>(array)$r)->all();$p=json_decode(file_get_contents($repo.'/docs/integration/sgf-fixed-assets-access-proposal.json'),true);if($grants!==$p['grants_per_book'])throw new LogicException('Grant perimeter differs');if($host->table('fa_versions')->count()!==6||$host->table('fa_commands')->count()!==6)throw new LogicException('Expected single asset plan quota decisions');if($native->table('gl_journals')->count()!==29||$native->table('gl_accounts')->count()!==24)throw new LogicException('Journal/chart count mismatch');if($native->table('gl_periods')->where($scope)->orderByDesc('version')->value('status')!=='open')throw new LogicException('Period must remain open');
$oldSnapshot=file_get_contents($s['root'].'/statements-frozen-export-private.csv');$oldFs=json_decode(file_get_contents($beforeFile=$s['root'].'/statements-http-progress.json'),true)['resultReview']['result']['id'];$oldData=json_decode($native->table('fs_versions')->where('id',$oldFs)->value('data'),true);if(hash('sha256',$oldSnapshot)!==$oldData['csv_sha256'])throw new LogicException('Old snapshot SHA mismatch');
$public=$host->selectOne("SELECT EXISTS(SELECT 1 FROM information_schema.table_privileges WHERE grantee='PUBLIC' AND table_name IN('fa_meta','fa_versions','fa_commands')) p")->p;if($public)throw new LogicException('Public administrative access prohibited');$checks[]='new_rights_exact';$checks[]='6administrative_versions_receipts';$checks[]='29journals24accounts';$checks[]='period_remains_open';$checks[]='old_statement_sha_preserved';$checks[]='no_public_assets_tables';
file_put_contents($work.'/assets-preservation.json',json_encode(['passed'=>true,'checks'=>$checks,'checked_original_sets'=>count($before['host'])+count($before['native']),'original_rows_identical'=>true,'approved_appends'=>$changes,'bindings_unchanged'=>3,'new_demo'=>false,'cache_cleared'=>false,'protected_records_unchanged'=>true],JSON_PRETTY_PRINT));echo json_encode(['passed'=>true,'checks'=>count($checks),'original_sets'=>count($before['host'])+count($before['native']),'proof'=>$work.'/assets-preservation.json']).PHP_EOL;