<?php
declare(strict_types=1);
date_default_timezone_set('Asia/Shanghai');$lane=(string)getenv('CATEGORY_LANE');$runtime=(string)getenv('CATEGORY_RUNTIME');$base=(string)getenv('CATEGORY_BASE');$root=(string)getenv('CATEGORY_ROOT');$dm=getenv('POC_DIALECT')==='dm';$tenant=2147001321;$marker='CDXCF10A3B7';
$check=static function(bool $ok,string $why):void{if(!$ok)throw new RuntimeException($why);};$check(in_array($lane,['B','C'],true)&&preg_match('#^http://127\.0\.0\.1:1832[12]$#D',$base)===1,'Private loopback');
$connect=static function()use($dm):PDO{try{return new PDO($dm?'dm:host=127.0.0.1;port=5238;schema=AIZHCT_APP':'mysql:host='.getenv('POC_AI_HOST').';port='.getenv('POC_AI_PORT').';dbname='.getenv('POC_AI_SCHEMA').';charset=utf8',getenv('POC_AI_USER'),getenv('POC_AI_PASSWORD'),[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_CASE=>PDO::CASE_LOWER]);}catch(Throwable $e){throw new RuntimeException('Private Config/Health identity connection failed');}};
$db=$connect();if($dm)$check($db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn()==='AIZHCT_APP','DM identity');else $check(strpos((string)$db->query('SELECT VERSION()')->fetchColumn(),'5.6.')===0&&$db->query('SELECT DATABASE()')->fetchColumn()===getenv('POC_AI_SCHEMA'),'Code local MySQL5.6');
$query=static function(string $sql,array $args=[])use($db):array{$s=$db->prepare($sql);$s->execute($args);$rows=$s->fetchAll(PDO::FETCH_ASSOC);foreach($rows as &$r)foreach($r as &$v)if(is_resource($v))$v=stream_get_contents($v);unset($r,$v);return $rows;};$pks=['user'=>'user_id','staff'=>'id','athlete_master'=>'id','athlete_pal'=>'id','health'=>'id'];$owned=array_fill_keys(array_keys($pks),[]);
$gate=json_decode((string)file_get_contents(__DIR__.'/structure-'.$lane.'.json'),true);$check($gate['lane']===$lane&&$gate['business_dml']===0&&$gate['foreign_keys']===0&&$gate['triggers']===0,'Live five-table FK/trigger gate');
foreach(['athlete_master'=>['id','sport_id','sport_event_id','start_age','end_age','gender','staff_id','notes','store_id','is_delete','create_by','create_time','update_time'],'athlete_pal'=>['id','master_id','sport_id','sport_event_id','start_age','end_age','gender','staff_id','strength','pal','store_id','is_delete','create_by','create_time','update_time'],'health'=>['id','staff_id','health','store_id','is_delete','create_by','create_time','update_time']] as $t=>$expected){$cols=array_map('strtolower',array_column($gate['metadata'][$t]['columns'],'column_name'));sort($cols);sort($expected);$check($cols===$expected,'Exact fields '.$t);foreach($gate['metadata'][$t]['columns'] as $c){$k=strtolower($c['column_name']);$type=strtolower($c['data_type']);if(in_array($k,['create_time','update_time'],true))$check(in_array($type,['datetime','timestamp'],true),'Actual DATETIME time oracle');if($k==='pal')$check($type==='decimal'&&(int)($dm?$c['data_precision']:$c['numeric_precision'])===5&&(int)($dm?$c['data_scale']:$c['numeric_scale'])===2,'Actual PAL decimal5,2');if(in_array($k,['staff_id','sport_event_id'],true)&&$t!=='health')$check(in_array($type,['text','clob'],true),'Actual CSV text/CLOB');}}
foreach(['user'=>['user_id','nick_name','store_id'],'staff'=>['id','name','user_id','staff_type','sport_id','sport_event_id','gender','birthday','height','weight','store_id','create_by']] as $t=>$required){$cols=array_map('strtolower',array_column($gate['metadata'][$t]['columns'],'column_name'));foreach($required as $k)$check(in_array($k,$cols,true),'Own fixture required '.$t.'.'.$k);}
$snapshot=static function()use($connect,$dm,$pks,&$owned):array{$scan=$connect();if(!$dm)$scan->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,false);$out=[];foreach($pks+['sport'=>'id','config_enum'=>'id'] as $t=>$pk){$s=$scan->query('SELECT * FROM yoshop_'.$t.' ORDER BY '.$pk);$h=hash_init('sha256');$n=0;while($r=$s->fetch(PDO::FETCH_ASSOC)){if(in_array((int)$r[$pk],$owned[$t]??[],true))continue;foreach($r as &$v)if(is_resource($v))$v=stream_get_contents($v);unset($v);hash_update($h,serialize($r));$n++;}$s->closeCursor();$out[$t]=['rows'=>$n,'sha256'=>hash_final($h)];}return $out;};
$configSha=($argv[1]??'')==='green'?'6ad093c02710e3646e11b68abce705beb9ad15dab6bc7f6aa85f7a6fac615237':'7d40ac160b1eee2cd1ca82b47b63a531ed57c7fcaf6eb22237e2becb7f5ab85c';
$boundary=json_decode((string)file_get_contents($base.'/__poc_boundary'),true);foreach(['config_service_sha'=>$configSha,'master_model_sha'=>'04ac0e6c6da3f9a1a752e4976f477bbd651f4e1dfa3989ac42d1cfe62a9e7725','pal_model_sha'=>'27ed73ebd26478454887d443cb2c403541c96c18e37c80c785fd22f4230052e7','health_service_sha'=>'f8611bffc07c58cc939a4078abb208e35e2056a581ae99fdb109a11ecd2e1f61','health_model_sha'=>'6371c376cd278bf50cda0479f0f03badfcea1604a8b720f6a3d6c25a146f7cd9'] as $k=>$sha)$check(($boundary[$k]??'')===$sha,'Actual prewrite source SHA '.$k);$check($boundary['external_stubs']===true&&$boundary['private_cache']===true&&$boundary['all_external_calls_forbidden']===true,'Private actual boundary');
