<?php
declare(strict_types=1);
require __DIR__.'/bootstrap.php';$resume=($argv[1]??'')==='resume';$prior=$resume?json_decode((string)file_get_contents($runtime.'/private-retention.json'),true):null;
if($resume){$check($prior['marker']===$marker&&$prior['tenants']===$tenants,'Exact retained context');$owned=$prior['owned_pk_tenants'];$before=$prior['before'];$check($snapshot()===$before,'Retained exact natural SHA');}
else{$before=$snapshot();$check((int)$query('SELECT COUNT(*) n FROM yoshop_express WHERE store_id IN (?,?)',array_values($tenants))[0]['n']===0,'Fresh owned tenant collision');}
define('TP_ENV','poc');define('BUSINESS','aizhct');define('ENTERPRISE_NO','10001');require $root.'/vendor/autoload.php';$app=new \think\App($root);$app->setEnvName('poc');$app->setRuntimePath($runtime.'/fixture-runtime/');$app->initialize();
$cache=new \think\cache\driver\File($app,['path'=>$runtime.'/cache/','prefix'=>'','expire'=>0]);$tokens=[];foreach($tenants as $m=>$t){$tokens[$m]=bin2hex(random_bytes(24));$cache->set($tokens[$m],['user'=>['store_user_id'=>$t,'store_id'=>$t,'real_name'=>$marker,'user_name'=>$marker,'is_super'=>1],'store_id'=>$t,'is_login'=>true],1800);}
$map=['rows'=>['yoshop_express'=>[]]];$saveMap=static function()use($runtime,&$map){file_put_contents($runtime.'/private-owned-map.json',json_encode($map));chmod($runtime.'/private-owned-map.json',0600);};$saveMap();$cases=[];$proofs=[];$responses=[];$error=null;$deleted=[];$idMap=[];$findings=[];
if($resume){$check(count($prior['cases'])===1&&count($owned)===1,'Only known first successful add resumed');$cases=$prior['cases'];$responses=$prior['responses'];$idMap=$prior['id_map'];$map['rows']['yoshop_express']=$owned;$saveMap();}
$shape=static function($v)use(&$shape){if(is_object($v)){$o=[];foreach(get_object_vars($v) as $k=>$x)$o[$k]=$shape($x);ksort($o);return ['object'=>$o];}if(is_array($v))return ['array'=>array_map($shape,$v)];return gettype($v);};
$request=static function(string $module,string $name,string $action,array $data=[])use($base,$tokens,$check,$shape,&$cases,&$responses):array{$method=in_array($action,['list','all'],true)?'GET':'POST';$scenario='PILOT_EX_'.strtoupper($module).'_'.$name;$path='/'.$module.'/setting.Express/'.$action;$headers='Host: '.$module.".express-owned.invalid\r\nAccess-Token: ".$tokens[$module]."\r\nPlatform: POC\r\nX-Pilot-Scenario: ".$scenario."\r\nContent-Type: application/json\r\n";$url=$base.$path.($method==='GET'&&$data?'?'.http_build_query($data):'');$start=time();$raw=file_get_contents($url,false,stream_context_create(['http'=>['method'=>$method,'header'=>$headers,'content'=>$method==='POST'?json_encode($data,JSON_UNESCAPED_UNICODE):'','timeout'=>30,'ignore_errors'=>true]]));$end=time();$body=json_decode((string)$raw,true);preg_match('#^HTTP/\S+\s+(\d+)#',$http_response_header[0]??'',$m);$check(is_array($body)&&strlen($raw)<1048576,'HTTP JSON transport');$case=['scenario'=>$scenario,'method'=>$method,'path'=>$path,'http_status'=>(int)($m[1]??0),'body'=>$body,'raw_json_shape'=>$shape(json_decode($raw))];$cases[]=$case;$responses[$scenario]=['raw'=>$raw,'start'=>$start,'end'=>$end];return $case;};
$success=static function(array $c)use($check){$check($c['http_status']===200&&($c['body']['status']??0)===200,'Actual business success '.$c['scenario']);};
$rowsFor=static function(string $m,string $search='')use($query,$tenants):array{return $query('SELECT * FROM yoshop_express WHERE store_id=?'.($search!==''?' AND express_name LIKE ?':'').' ORDER BY sort,express_id',$search!==''?[$tenants[$m],'%'.$search.'%']:[$tenants[$m]]);};
$verifyAll=static function(string $m)use($query,$tenants,$marker,$saveMap,&$map,&$owned,&$proofs,&$idMap):array{$rows=$query('SELECT * FROM yoshop_express WHERE store_id=? ORDER BY express_id',[$tenants[$m]]);foreach($rows as $r){if(strpos($r['express_name'],$marker)!==0)throw new RuntimeException('Unexpected owned tenant row');$id=(int)$r['express_id'];if($id<=0)throw new RuntimeException('Nonpositive express PK');$map['rows']['yoshop_express'][(string)$id]=$tenants[$m];$owned[(string)$id]=$tenants[$m];if(!isset($idMap[(string)$id]))$idMap[(string)$id]=count($idMap)+1;}$saveMap();$proofs[]=['module'=>$m,'rows'=>count($rows),'exact_owned_marker_store_and_pks'=>true];return $rows;};
$project=static function(array $r)use($check):array{foreach(['express_id','sort','store_id'] as $k){$check(is_numeric($r[$k]),'Physical integer '.$k);$r[$k]=(int)$r[$k];}foreach(['create_time','update_time'] as $k){$check(is_numeric($r[$k])&&(int)$r[$k]>0,'Physical Unix timestamp '.$k);$r[$k]=date('Y-m-d H:i:s',(int)$r[$k]);}return $r;};
$read=static function(string $m,string $name,string $action,string $search='')use($request,$success,$rowsFor,$project,$check,&$cases):void{$c=$request($m,$name,$action,$search!==''?['search'=>$search]:[]);$success($c);$rows=array_map($project,$rowsFor($m,$search));$expected=$action==='all'?['list'=>$rows]:['list'=>['total'=>count($rows),'per_page'=>15,'current_page'=>1,'last_page'=>count($rows)?1:0,'data'=>$rows]];$check($c['body']['data']===$expected,'Complete original source/wire/order '.$c['scenario']);$cases[count($cases)-1]['complete_original_projection_equal']=true;};
try{foreach($tenants as $module=>$tenant){$tag=$module==='store'?'S':'T';$forms=[['express_name'=>$marker.'_'.$tag."_甲'餐",'kuaidi100_code'=>'00'.$marker.$tag,'kdniao_code'=>'01'.$marker.$tag,'sort'=>100],['express_name'=>$marker.'_'.$tag.'_乙\\餐','kuaidi100_code'=>'02'.$marker.$tag,'kdniao_code'=>'03'.$marker.$tag,'sort'=>0],['express_name'=>$marker.'_'.$tag.'_丙餐','kuaidi100_code'=>'04'.$marker.$tag,'kdniao_code'=>'05'.$marker.$tag,'sort'=>0]];$ids=[];
    foreach($forms as $i=>$form){$c=$resume&&$module==='store'&&$i===0?$prior['cases'][0]:$request($module,'ADD_'.($i+1),'add',['form'=>$form]);$success($c);$rows=$verifyAll($module);$r=$query('SELECT * FROM yoshop_express WHERE store_id=? AND express_name=?',[$tenant,$form['express_name']]);$check(count($r)===1,'New exact source one');$id=(int)$r[0]['express_id'];$ids[]=$id;foreach($form as $k=>$v)$check($k==='sort'?(int)$r[0][$k]===$v:$r[0][$k]===$v,'Physical input persistence '.$k);$times=$responses[$c['scenario']];$check((int)$r[0]['create_time']>=$times['start']-2&&(int)$r[0]['create_time']<=$times['end']+2,'Actual creation Unix window');}
    $read($module,'LIST_THREE_SORT_PK','list');$read($module,'ALL_THREE_SORT_PK','all');$read($module,'SEARCH_QUOTE','list',"甲'餐");$read($module,'SEARCH_EMPTY','all',$marker.'_NOTFOUND');
    $prior=$query('SELECT * FROM yoshop_express WHERE express_id=? AND store_id=?',[$ids[2],$tenant]);$edit=$forms[0];$edit['express_name']=$marker.'_'.$tag."_改'中文\\餐";$edit['kuaidi100_code']='000'.$marker.$tag;$edit['sort']=2;$c=$request($module,'EDIT_OWN','edit',['expressId'=>$ids[0],'form'=>$edit]);$success($c);$r=$query('SELECT * FROM yoshop_express WHERE express_id=? AND store_id=?',[$ids[0],$tenant]);$check(count($r)===1,'Edit original source');foreach($edit as $k=>$v)$check($k==='sort'?(int)$r[0][$k]===$v:$r[0][$k]===$v,'Edited original '.$k);$check($query('SELECT * FROM yoshop_express WHERE express_id=? AND store_id=?',[$ids[2],$tenant])===$prior,'Sibling complete raw row unchanged');$verifyAll($module);$read($module,'LIST_AFTER_EDIT','list');$read($module,'ALL_AFTER_EDIT','all');
    $own=$query('SELECT * FROM yoshop_express WHERE express_id=? AND store_id=?',[$ids[1],$tenant]);$check(count($own)===1&&strpos($own[0]['express_name'],$marker)===0,'Physical delete pre-owned');
    if($deleteReferenceSupported)$check((int)$query('SELECT COUNT(*) n FROM yoshop_order WHERE express_id=? AND store_id=?',[$ids[1],$tenant])[0]['n']===0,'No order reference before delete');
    $c=$request($module,'DELETE_OWN','delete',['expressId'=>$ids[1]]);$fresh=$connect();$s=$fresh->prepare('SELECT COUNT(*) FROM yoshop_express WHERE express_id=? AND store_id=?');$s->execute([$ids[1],$tenant]);$remaining=(int)$s->fetchColumn();
    if($deleteReferenceSupported){$success($c);$check($remaining===0,'Fresh PDO actual physical delete0');$deleted[]=['module'=>$module,'exact_own_preimage_verified'=>true,'fresh_pdo_remaining'=>0,'physical_delete'=>true];}
    else{$check($c['http_status']===200&&($c['body']['status']??0)===500&&$remaining===1,'Original shared missing-column failure leaves owned row');$check($query('SELECT * FROM yoshop_express WHERE express_id=? AND store_id=?',[$ids[1],$tenant])===$own,'Failed original delete writes nothing');$findings[]=['module'=>$module,'scenario'=>$c['scenario'],'classification'=>'shared-original-order-express_id-missing-not-positive','real_http_business_status'=>500,'retained_row_unchanged'=>true];}
    $verifyAll($module);$read($module,'LIST_AFTER_DELETE','list');$read($module,'ALL_AFTER_DELETE','all');
}}
catch(Throwable $caught){$error=['class'=>get_class($caught),'message'=>$caught->getMessage(),'file'=>basename($caught->getFile()),'line'=>$caught->getLine()];}
$tokensGone=true;foreach($tokens as $t){$cache->delete($t);$tokensGone=$tokensGone&&$cache->get($t)===null;}$cache->clear();$cacheFiles=0;if(is_dir($runtime.'/cache/'))foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($runtime.'/cache/',FilesystemIterator::SKIP_DOTS)) as $f)if($f->isFile())$cacheFiles++;
$fresh=$connect();$retained=[];foreach($tenants as $m=>$tenant){$s=$fresh->prepare('SELECT * FROM yoshop_express WHERE store_id=? ORDER BY express_id');$s->execute([$tenant]);$rows=$s->fetchAll(PDO::FETCH_ASSOC);foreach($rows as $r)$check(($owned[(string)$r['express_id']]??null)===$tenant&&strpos($r['express_name'],$marker)===0,'Fresh retained exact ownership');$retained[$m]=count($rows);}$after=$snapshot();
$private=['lane'=>$lane,'marker'=>$marker,'tenants'=>$tenants,'owned_pk_tenants'=>$owned,'id_map'=>$idMap,'cases'=>$cases,'responses'=>$responses,'before'=>$before,'after'=>$after];file_put_contents($runtime.'/private-retention.json',json_encode($private,JSON_PRETTY_PRINT|JSON_PRESERVE_ZERO_FRACTION|JSON_UNESCAPED_UNICODE));chmod($runtime.'/private-retention.json',0600);
$normal=static function($x)use(&$normal,$idMap){if(!is_array($x))return $x;foreach($x as $k=>&$v){if($k==='express_id'&&is_int($v)&&isset($idMap[(string)$v]))$v=$idMap[(string)$v];elseif(in_array($k,['create_time','update_time'],true)&&is_string($v)&&preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/D',$v))$v='VERIFIED_OWN_ORIGINAL_TIME';else $v=$normal($v);}unset($v);return $x;};
foreach($cases as &$c){$t=$c['body']['trace_id']??null;$c['trace_format_valid']=is_string($t)&&preg_match('/^[0-9a-f]{13}$/D',$t)===1;if($c['trace_format_valid'])$c['body']['trace_id']='VALID_DYNAMIC_TRACE';}unset($c);$events=[];foreach(file($runtime.'/queries.jsonl',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[] as $l)$events[]=json_decode($l,true);$audit=[];foreach(file($runtime.'/write-audit.jsonl',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[] as $l)$audit[]=json_decode($l,true);
$report=['lane'=>$lane,'cases'=>$normal($cases),'original_proofs'=>$proofs,'actual_physical_deletes'=>$deleted,'findings'=>$findings,'retention'=>['mode'=>'retained-owned','fresh_exact_owned_rows'=>$retained,'natural_sha_unchanged'=>$before===$after,'exact_pk_exclusions_only'=>true,'natural_rows'=>$before['natural_rows']],'resources'=>['tokens_absent'=>$tokensGone,'cache_files'=>$cacheFiles],'error'=>$error,'events'=>$events,'write_audit'=>$audit,'loaded_boundary'=>$boundary];file_put_contents($runtime.'/report.json',json_encode($report,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE));echo json_encode(['lane'=>$lane,'http_cases'=>count($cases),'retained'=>$retained,'physical_delete_cases'=>count($deleted),'findings'=>$findings,'natural_sha_unchanged'=>$before===$after,'error'=>$error,'report'=>$runtime.'/report.json']),"\n";exit($error!==null||$before!==$after||!$tokensGone||$cacheFiles||in_array(false,array_column($audit,'owned_scope_verified'),true)?1:0);
