first commit
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
$app=require __DIR__.'/../bootstrap/app.php';$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
if(!\App\Modules\Identity\Services\LocalDatabaseGuard::allows())throw new RuntimeException('Own SGF development database required.');
|
||||
$db=\Illuminate\Support\Facades\DB::class;
|
||||
$before=in_array('--before',$argv,true);$grants=in_array('--after-grants',$argv,true);
|
||||
$file=storage_path('app/invoice-dev-preservation-before.json');
|
||||
$baseline=$before?null:json_decode(file_get_contents($file),true,64,JSON_THROW_ON_ERROR);
|
||||
$tables=$before?array_map(fn($r)=>$r->tablename,$db::select("SELECT tablename FROM pg_tables WHERE schemaname='public' AND (tablename ~ '^(a_|b_|ca_|sf_|doc_|document_|service_calculation_)' OR tablename IN ('users','tenants','companies','units','company_memberships','permission_grants','identity_audit')) ORDER BY tablename")):array_keys($baseline['tables']);
|
||||
$summary=[];
|
||||
foreach($tables as $table){
|
||||
if(!preg_match('/^[a-z_]+$/D',$table))throw new RuntimeException('Unexpected table identifier.');
|
||||
$where='';if($grants&&in_array($table,['permission_grants','identity_audit'],true))$where=' WHERE id <= '.(int)$baseline['max'][$table];
|
||||
$r=$db::selectOne('SELECT count(*) AS n, md5(COALESCE(string_agg(row_to_json(t)::text, E\'\\n\' ORDER BY row_to_json(t)::text),\'\')) AS h FROM (SELECT * FROM "'.$table.'"'.$where.') t');
|
||||
$summary[$table]=['count'=>(int)$r->n,'hash'=>$r->h];
|
||||
}
|
||||
if($before){
|
||||
file_put_contents($file,json_encode(['tables'=>$summary,'max'=>['permission_grants'=>(int)$db::table('permission_grants')->max('id'),'identity_audit'=>(int)$db::table('identity_audit')->max('id')],'guard_file_hash'=>hash_file('sha256',base_path('app/Modules/Services/ServiceInvoicing.php'))],JSON_THROW_ON_ERROR));
|
||||
echo 'Fingerprinted '.count($summary)." preexisting tables; no record contents disclosed.\n";exit;
|
||||
}
|
||||
if($summary!==$baseline['tables'])throw new RuntimeException('Preexisting data or grants changed; review before proceeding.');
|
||||
if(hash_file('sha256',base_path('app/Modules/Services/ServiceInvoicing.php'))!==$baseline['guard_file_hash'])throw new RuntimeException('Issuance guard code changed.');
|
||||
$counts=[];foreach(['si_proposals','si_decisions','si_counters','si_invoices','si_events','si_outbox','si_commands','si_correction_requests'] as $table){$counts[$table]=$db::table($table)->count();if($counts[$table]!==0)throw new RuntimeException('New series/document tables not empty.');}
|
||||
$denials=[];
|
||||
foreach(['guard','issue','propose'] as $entry){
|
||||
try{
|
||||
if($entry==='guard')\App\Modules\Services\ServiceInvoicing::guard();
|
||||
elseif($entry==='issue')app(\App\Modules\Services\ServiceInvoicing::class)->issue(0,1,[],'blocked-verification');
|
||||
else app(\App\Modules\Services\ServiceInvoicing::class)->propose(1,['kind'=>'series']);
|
||||
throw new RuntimeException('Real issuance entry did not refuse.');
|
||||
}catch(\Symfony\Component\HttpKernel\Exception\HttpException $e){if($e->getStatusCode()!==403||!str_contains($e->getMessage(),'conformidade'))throw $e;$denials[$entry]=403;}
|
||||
}
|
||||
if($grants){
|
||||
$expected=[];foreach([1=>['invoice_series.view','invoice_series.propose','service_invoices.view','service_invoices.issue','service_invoices.correction_request'],2=>['invoice_series.view','invoice_series.approve','service_invoices.view']] as $user=>$rights)foreach($rights as $right)$expected[]=['user_id'=>$user,'tenant_id'=>1,'company_id'=>1,'unit_id'=>str_starts_with($right,'service_invoices.')?1:null,'permission'=>$right];
|
||||
usort($expected,fn($a,$b)=>[$a['user_id'],$a['permission']]<=>[$b['user_id'],$b['permission']]);
|
||||
$actual=$db::table('permission_grants')->where(fn($q)=>$q->where('permission','like','invoice_series.%')->orWhere('permission','like','service_invoices.%'))->orderBy('user_id')->orderBy('permission')->get(['user_id','tenant_id','company_id','unit_id','permission'])->map(fn($r)=>(array)$r)->all();
|
||||
if($actual!==$expected)throw new RuntimeException('Grants differ from the eight specifically approved operations.');
|
||||
if($db::table('identity_audit')->where('id','>',$baseline['max']['identity_audit'])->where('action','service_invoice.initial_grant')->count()!==8)throw new RuntimeException('Eight initial grant audit entries required.');
|
||||
app(\App\Shared\Context\CompanyContext::class)->selectFor(1,1,1,1);
|
||||
$listing=app(\App\Modules\Services\ServiceInvoicing::class)->listing(1);
|
||||
if(!$listing['real_blocked'] || $listing['test_enabled'] || $listing['invoices']!==[] || $listing['proposals']!==[])throw new RuntimeException('Normal application must report blocked.');
|
||||
}
|
||||
$proof=['database'=>'sgf_tempo_dev','preexisting_tables_checked'=>count($summary),'preexisting_records_unchanged'=>true,'prior_grants_and_audit_unchanged'=>true,'new_tables'=>$counts,'confirmed_grants_verified'=>$grants?8:0,'guard_code_unchanged'=>true,'real_entry_denials'=>$denials,'real_issuance_blocked'=>true,'real_series_created'=>false,'documents_issued'=>false];
|
||||
file_put_contents(base_path('docs/proofs/invoice-dev-preservation'.($grants?'-grants':'').'.json'),json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
|
||||
echo $grants?"Verified exactly eight audited grants, prior data preserved, all new tables empty and real issuance blocked.\n":"Verified preserved data and grants, eight empty tables and real issuance blocked.\n";
|
||||
Reference in New Issue
Block a user