make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); if(!\App\Modules\Identity\Services\LocalDatabaseGuard::allows())throw new RuntimeException('Own local development database required.'); $db=\Illuminate\Support\Facades\DB::class;$summary=[]; $afterGrants=in_array('--after-grants',$argv,true); foreach(['a_clients','a_services','a_service_drafts','a_billing_drafts','a_history','a_events','a_pending','a_outbox','a_commands','b_internal_confirmations','b_internal_confirmation_commands','doc_records','doc_history','document_preview_models','document_preview_model_history','service_calculation_profiles','service_calculation_results','permission_grants'] as $table){ if(!\Illuminate\Support\Facades\Schema::hasTable($table))continue; $query=$db::table($table); if($table==='permission_grants'&&$afterGrants)$query->whereNot(function($q){$q->where('tenant_id',1)->where('company_id',1)->whereNull('unit_id')->where(function($q){$q->where(fn($q)=>$q->where('user_id',1)->whereIn('permission',['catalogue_accounting.view','catalogue_accounting.propose']))->orWhere(fn($q)=>$q->where('user_id',2)->whereIn('permission',['catalogue_accounting.view','catalogue_accounting.approve']));});}); $rows=$query->orderBy($table==='a_outbox'?'event_id':'id')->get();$summary[$table]=['count'=>$rows->count(),'hash'=>hash('sha256',$rows->toJson())]; } foreach(['app/Modules/Services/ServiceCalculation.php','database/migrations/2026_10_26_030000_create_service_calculations.php','resources/js/DocumentPreview.jsx'] as $path)$summary['file:'.$path]=hash_file('sha256',base_path($path)); $file=storage_path('app/accounting-preservation-before.json'); if(in_array('--before',$argv,true)){file_put_contents($file,json_encode($summary,JSON_THROW_ON_ERROR));echo "Existing development records and calculation files fingerprinted; no contents disclosed.\n";exit;} if($summary!==json_decode(file_get_contents($file),true,64,JSON_THROW_ON_ERROR))throw new RuntimeException('Existing data, prior grants or calculation files changed.'); $counts=[];foreach(['ca_proposals','ca_submissions','ca_decisions','ca_resolutions','ca_commands'] as $table){$counts[$table]=$db::table($table)->count();if($counts[$table]!==0)throw new RuntimeException('Unexpected real classification rows.');} if($afterGrants){ $expected=[1=>['catalogue_accounting.view','catalogue_accounting.propose'],2=>['catalogue_accounting.view','catalogue_accounting.approve']]; foreach($expected as $user=>$rights){$actual=$db::table('permission_grants')->where('user_id',$user)->where('permission','like','catalogue_accounting.%')->get(['tenant_id','company_id','unit_id','permission']);if($actual->count()!==2)throw new RuntimeException('Unexpected classification rights.');foreach($actual as $g)if($g->tenant_id!==1||$g->company_id!==1||$g->unit_id!==null||!in_array($g->permission,$rights,true))throw new RuntimeException('Unexpected classification scope.');} file_put_contents(base_path('docs/proofs/accounting-access-results.json'),json_encode(['database'=>'sgf_tempo_dev','confirmed_grants_applied'=>4,'company_id'=>1,'proposer_id'=>1,'validator_id'=>2,'no_unit_grants'=>true,'prior_grants_unchanged'=>true,'business_records_and_calculation_files_unchanged'=>true,'real_classification_rows'=>0],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo "Exactly four confirmed company grants verified; prior grants, data and calculation unchanged; no unit grants or real classification rows.\n"; }else{ file_put_contents(base_path('docs/proofs/accounting-dev-preservation.json'),json_encode(['database'=>'sgf_tempo_dev','existing_data_hashes_unchanged'=>true,'existing_grants_unchanged'=>true,'calculation_files_unchanged'=>true,'new_table_counts'=>$counts],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo "Development migration preserved existing records, grants and calculation files; all five new tables empty.\n"; }