26 lines
1.9 KiB
PHP
26 lines
1.9 KiB
PHP
<?php
|
|
// Negative QA fixtures only; guard pins the isolated clone before mutation.
|
|
$app = (static fn ($p) => require $p)(__DIR__.'/portal-service-followup-runtime.php');
|
|
$id = $argv[1] ?? '';
|
|
$operation = $argv[2] ?? '';
|
|
$db = Illuminate\Support\Facades\DB::connection();
|
|
$row = $db->table('portal_security_approvals')->where('id',$id)->where('kind','bootstrap')->first();
|
|
throw_unless($row && $row->consumed_at === null && (int)$row->requested_by === 15 && (int)$row->subject_user_id === 16,RuntimeException::class,'Only pending synthetic QA pair permitted');
|
|
$dir = dirname(__DIR__).'/storage/app/private/investmoz-v2/portal-audit';
|
|
$snapshot = $dir.'/service-followup-bootstrap-negative-snapshot.json';
|
|
if ($operation === 'expire' || $operation === 'code-mismatch') {
|
|
throw_if(is_file($snapshot),RuntimeException::class,'Restore prior negative fixture first');
|
|
file_put_contents($snapshot,json_encode(['id'=>$id,'scope'=>$row->scope,'expires_at'=>$row->expires_at],JSON_THROW_ON_ERROR));
|
|
if ($operation === 'expire') $db->table('portal_security_approvals')->where('id',$id)->update(['expires_at'=>now()->subMinute()]);
|
|
else {
|
|
$scope=json_decode($row->scope,true,512,JSON_THROW_ON_ERROR);$scope['code_hash']=str_repeat('0',64);
|
|
$db->table('portal_security_approvals')->where('id',$id)->update(['scope'=>json_encode($scope,JSON_THROW_ON_ERROR)]);
|
|
}
|
|
} elseif ($operation === 'restore') {
|
|
$before=json_decode(file_get_contents($snapshot),true,512,JSON_THROW_ON_ERROR);
|
|
throw_unless($before['id']===$id,RuntimeException::class);
|
|
$db->table('portal_security_approvals')->where('id',$id)->update(['scope'=>$before['scope'],'expires_at'=>$before['expires_at']]);
|
|
unlink($snapshot); // Exact own QA fixture file only.
|
|
} else throw new RuntimeException('Unknown QA fixture action');
|
|
echo json_encode(['result'=>'isolated_negative_fixture','action'=>$operation,'active_writes'=>0]).PHP_EOL;
|