make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Artisan; use App\Modules\Identity\Services\LocalDatabaseGuard; use App\Modules\Identity\Services\Permissions; use App\Modules\Identity\Services\Audit; use App\Modules\Workshop\DirectCosts; use App\Modules\Workshop\WorkshopWorkflow; use App\Shared\Context\CompanyContext; function ensureDirectCost(bool $ok,string $message): void { if(!$ok)throw new RuntimeException($message); } function directCostFingerprint(string $table,?int $max=null): array { ensureDirectCost((bool)preg_match('/^[a-z_]+$/D',$table),'Unexpected table identifier.'); $where=$max===null?'':' WHERE id <= '.$max; $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'); return [(int)$r->n,$r->h]; // In memory only; no record contents exported. } ensureDirectCost(LocalDatabaseGuard::allows(),'Own SGF development application connection required.'); ensureDirectCost($argv===[$argv[0],'--apply-confirmed-090000-and-four-grants'],'Exact confirmed operation argument required.'); $migration='2026_10_27_090000_create_workshop_direct_costs'; ensureDirectCost(!DB::table('migrations')->where('migration',$migration)->exists(),'090000 already installed; review changed state.'); ensureDirectCost(DB::table('migrations')->where('migration','2026_10_27_080000_create_workshop_resource_records')->exists(),'Expected workshop installation missing.'); ensureDirectCost(DB::table('migrations')->where('migration','2026_10_27_070000_create_simulated_receivables')->exists(),'Expected receivables installation missing.'); $newTables=['dc_rates','dc_calculations','dc_decisions','dc_commands','dc_events','dc_outbox']; $tables=array_map(fn($r)=>$r->tablename,DB::select("SELECT tablename FROM pg_tables WHERE schemaname='public' ORDER BY tablename")); ensureDirectCost(!array_intersect($tables,$newTables),'Receivables tables already exist; review first.'); $rights=[1=>['view','prepare'],2=>['view','validate']]; $checkScope=function(): void { foreach([1=>['Osmane Nala','nala@tempo.co.mz'],2=>['Samira Nal','onala@me.com']] as $id=>[$name,$email]){ ensureDirectCost(DB::table('users')->where(compact('id','name','email'))->exists(),'Confirmed account identity differs.'); ensureDirectCost(DB::table('company_memberships')->where(['user_id'=>$id,'tenant_id'=>1,'company_id'=>1])->exists(),'Existing membership required.'); $p=app(Permissions::class);$p->require($id,1,1,'company.view');$p->require($id,1,1,'unit.view',1); } ensureDirectCost(DB::table('companies')->where(['id'=>1,'tenant_id'=>1,'name'=>'Tempo Lda'])->exists(),'Confirmed company differs.'); ensureDirectCost(DB::table('units')->where(['id'=>1,'tenant_id'=>1,'company_id'=>1,'name'=>'SEGI'])->exists(),'Confirmed unit differs.'); ensureDirectCost(!DB::table('permission_grants')->where('permission','like','direct_costs.%')->exists(),'Unexpected existing direct cost rights; review first.'); }; $checkScope(); $baseline=[];foreach($tables as $t)$baseline[$t]=directCostFingerprint($t); $max=[];foreach(['permission_grants','identity_audit'] as $t)$max[$t]=(int)DB::table($t)->max('id'); $ledger=DB::table('migrations')->orderBy('id')->get()->map(fn($r)=>(array)$r)->all(); $sourceHashes=[];foreach(['app/Modules/Workshop/DirectCosts.php','app/Modules/Services/ServiceReceivables.php','app/Modules/Services/ServiceInvoicing.php','app/Modules/Workshop/WorkshopWorkflow.php'] as $p)$sourceHashes[$p]=hash_file('sha256',base_path($p)); $secrets=json_decode(file_get_contents('C:/laragon/data/sgf-tempo/secrets/database.json'),true,32,JSON_THROW_ON_ERROR); $owner=config('database.connections.'.config('database.default')); $owner['username']='sgf_dev_owner';$owner['password']=$secrets['dev_owner'];$owner['url']=null; config(['database.connections.sgf_direct_cost_owner'=>$owner]);unset($owner,$secrets); try { $connection=DB::connection('sgf_direct_cost_owner'); $identity=$connection->selectOne('SELECT current_database() AS db,current_user AS role,inet_server_port() AS port,rolsuper,rolcreatedb,rolcreaterole,rolbypassrls FROM pg_roles WHERE rolname=current_user'); ensureDirectCost($identity->db==='sgf_tempo_dev'&&$identity->role==='sgf_dev_owner'&&(int)$identity->port===55432&&!$identity->rolsuper&&!$identity->rolcreatedb&&!$identity->rolcreaterole&&!$identity->rolbypassrls,'Unexpected migration owner/destination.'); $connection->transaction(function()use($migration,$baseline,$newTables): void { $applicationConnection=DB::getDefaultConnection();DB::setDefaultConnection('sgf_direct_cost_owner'); try { $exit=Artisan::call('migrate',['--database'=>'sgf_direct_cost_owner','--path'=>'database/migrations/'.$migration.'.php','--force'=>true,'--no-interaction'=>true]); ensureDirectCost($exit===0,'Targeted migration failed.'); foreach($baseline as $t=>$fp)if($t!=='migrations')ensureDirectCost(directCostFingerprint($t)===$fp,'Existing records changed during migration: '.$t); foreach($newTables as $t)ensureDirectCost(DB::table($t)->count()===0,'New tables must be empty.'); } finally { DB::setDefaultConnection($applicationConnection); } }); } finally { DB::purge('sgf_direct_cost_owner');config(['database.connections.sgf_direct_cost_owner'=>null]); } ensureDirectCost(LocalDatabaseGuard::allows(),'Application must remain sgf_dev_app.'); $afterLedger=DB::table('migrations')->orderBy('id')->get()->map(fn($r)=>(array)$r)->all(); ensureDirectCost(count($afterLedger)===count($ledger)+1&&array_slice($afterLedger,0,count($ledger))===$ledger&&end($afterLedger)['migration']===$migration,'Unexpected migration ledger delta.'); $denials=[]; $grants=DB::transaction(function()use($rights,$checkScope,$baseline,$max,&$denials): array { DB::table('companies')->where('id',1)->lockForUpdate()->firstOrFail();$checkScope();$grants=[]; foreach($rights as $user=>$actions)foreach($actions as $action){ $g=['user_id'=>$user,'tenant_id'=>1,'company_id'=>1,'unit_id'=>1,'permission'=>'direct_costs.'.$action]; DB::table('permission_grants')->insert($g+['created_at'=>now(),'updated_at'=>now()]); Audit::record('direct_costs.initial_grant',null,1,1,1,subject:$user,details:['permission'=>$g['permission'],'reason'=>'Four unit grants specifically authorised; real operations remain blocked.']);$grants[]=$g; } foreach($baseline as $t=>$fp)if($t!=='migrations')ensureDirectCost(directCostFingerprint($t,$max[$t]??null)===$fp,'Prior records changed: '.$t); ensureDirectCost(DB::table('permission_grants')->where('id','>',$max['permission_grants'])->count()===4,'Exactly four new grants required.'); ensureDirectCost(DB::table('identity_audit')->where('id','>',$max['identity_audit'])->count()===4&&DB::table('identity_audit')->where('id','>',$max['identity_audit'])->where('action','direct_costs.initial_grant')->count()===4,'Exactly four grant audit entries required.'); $actual=DB::table('permission_grants')->where('permission','like','direct_costs.%')->get(['user_id','tenant_id','company_id','unit_id','permission'])->map(fn($r)=>(array)$r)->all(); $sort=fn($a,$b)=>[$a['user_id'],$a['permission']]<=>[$b['user_id'],$b['permission']];usort($actual,$sort);$expected=$grants;usort($expected,$sort);ensureDirectCost($actual===$expected,'Granted accounts/rights/scope differ.'); foreach([1,2] as $actor){app(CompanyContext::class)->selectFor($actor,1,1,1);$listing=app(DirectCosts::class)->listing($actor);ensureDirectCost($listing['blocked']&&$listing['orders']===[],'Normal direct cost listing must remain blocked.');} foreach(['guard','rate','calculate','decide','workshop','receivables','issuance'] as $entry){ try { $r=app(DirectCosts::class); match($entry){'guard'=>DirectCosts::guard(),'rate'=>$r->rate(0,1,[],'blocked-probe'),'calculate'=>$r->calculate(0,1,[],'blocked-probe'),'decide'=>$r->decide(0,2,[],'blocked-probe'),'workshop'=>WorkshopWorkflow::guard(),'receivables'=>\App\Modules\Services\ServiceReceivables::guard(),'issuance'=>\App\Modules\Services\ServiceInvoicing::guard()}; throw new RuntimeException('Operational entry did not refuse.'); }catch(\Symfony\Component\HttpKernel\Exception\HttpException $e){ensureDirectCost($e->getStatusCode()===403,'Expected operational refusal.');$denials[$entry]=403;} } app(CompanyContext::class)->selectFor(1,1,1,1);$w=app(WorkshopWorkflow::class)->listing(1);ensureDirectCost($w['blocked']&&$w['orders']===[],'Workshop operational block must remain.'); return $grants; }); foreach(['dc','sr','wo'] as $prefix){ try {DB::select('SELECT sgf_'.$prefix.'_environment()');throw new RuntimeException('SQL environment guard did not refuse.');} catch(\Illuminate\Database\QueryException $e){ensureDirectCost(str_contains($e->getMessage(),'SGF_'.strtoupper($prefix).'_TEST_DATABASE_ONLY'),'Unexpected SQL guard response.');} } foreach($sourceHashes as $p=>$hash)ensureDirectCost(hash_file('sha256',base_path($p))===$hash,'Functional source or guard changed.'); foreach($newTables as $t)ensureDirectCost(DB::table($t)->count()===0,'New direct cost tables must remain empty.'); $proof=['date'=>'2026-10-27','database'=>'sgf_tempo_dev','migration_applied'=>$migration,'only_one_migration_added'=>true,'workshop_080000_preserved'=>true,'preexisting_tables_checked'=>count($baseline),'prior_records_and_accesses_preserved'=>true,'new_empty_tables'=>$newTables,'new_grants'=>$grants,'audited_new_grants'=>4,'application_role'=>'sgf_dev_app','both_normal_account_listings_blocked'=>true,'entry_denials'=>$denials,'cost_receivables_and_workshop_sql_guards_refused'=>true,'functional_and_guard_sources_unchanged'=>true,'real_operations_created'=>false]; file_put_contents(storage_path('app/private/direct-cost-dev-install-proof.json'),json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); echo 'Applied only 090000 and four audited grants; '.count($baseline)." prior tables preserved, six new tables empty, costing, workshop and operational/fiscal guards verified.\n";