<?php
declare(strict_types=1);$lane=getenv('COMMENT_LANE');$dm=getenv('POC_DIALECT')==='dm';$db=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='.getenv('POC_AI_CHARSET'),getenv('POC_AI_USER'),getenv('POC_AI_PASSWORD'),[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_CASE=>PDO::CASE_LOWER]);if($dm?$db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn()!=='AIZHCT_APP':($db->query('SELECT DATABASE()')->fetchColumn()!==getenv('POC_AI_SCHEMA')||strpos($db->query('SELECT VERSION()')->fetchColumn(),'5.6.')!==0))throw new RuntimeException('DB identity');$q=static function($sql)use($db){$r=$db->query($sql)->fetchAll(PDO::FETCH_ASSOC);foreach($r as &$row){foreach($row as &$v)if(is_resource($v))$v=stream_get_contents($v);ksort($row);}return $r;};$m=json_decode(file_get_contents(__DIR__.'/structure-'.$lane.'.json'),true);$white=['store_api'=>['api_id','name','url','parent_id','sort','create_time','update_time'],'store_menu'=>['menu_id','type','name','path','is_page','module_key','action_mark','parent_id','sort','create_time','update_time'],'store_menu_api'=>['id','menu_id','api_id','create_time']];$limit=['store_api'=>2000,'store_menu'=>512,'store_menu_api'=>4096];$raw=[];$summary=['lane'=>$lane,'identity_verified'=>true,'business_dml'=>0,'tables'=>[]];foreach($white as $t=>$cols){$actual=array_column($m['tables'][$t]['columns'],'column_name');sort($actual);$expected=$cols;sort($expected);if($actual!==$expected)throw new RuntimeException('Nonsecret column whitelist drift '.$t);$count=(int)$q('SELECT COUNT(*) n FROM yoshop_'.$t)[0]['n'];if($count<1||$count>$limit[$t])throw new RuntimeException('Natural bounded row limit '.$t);$pk=$t==='store_api'?'api_id':($t==='store_menu'?'menu_id':'id');$rows=$q('SELECT '.implode(',',$cols).' FROM yoshop_'.$t.' ORDER BY '.$pk.' LIMIT '.$limit[$t]);if(count($rows)!==$count)throw new RuntimeException('Natural read drift '.$t);$raw[$t]=$rows;$summary['tables'][$t]=['rows'=>$count,'max_rows'=>$limit[$t],'all_columns_whitelisted'=>true,'sha256'=>hash('sha256',json_encode($rows,JSON_PRESERVE_ZERO_FRACTION))];}
$summary['api_url_shapes']=['empty_group'=>0,'pure_relative_or_absolute_route'=>0,'non_route'=>0];foreach($raw['store_api'] as $r){if($r['url']===''){$summary['api_url_shapes']['empty_group']++;continue;}if(!is_string($r['url'])||!preg_match('#^/?[A-Za-z0-9_.*:/-]+$#D',$r['url'])||strpos($r['url'],'?')!==false||strpos($r['url'],'://')!==false)$summary['api_url_shapes']['non_route']++;else $summary['api_url_shapes']['pure_relative_or_absolute_route']++;}if($summary['api_url_shapes']['non_route']){file_put_contents(__DIR__.'/inspect-url-shapes-'.$lane.'.json',json_encode($summary,JSON_PRETTY_PRINT));throw new RuntimeException('Natural API has non-route shape; no raw persisted');}foreach($raw['store_menu'] as $r){if(preg_match('/[?&](?:token|password|secret|key)=/i',$r['path']))throw new RuntimeException('Potential secret in natural route');}$roots=array_values(array_filter($raw['store_menu'],static function($r){return (int)$r['parent_id']===0;}));if(!$roots)throw new RuntimeException('No natural positive root menu');$summary['menu_info_id']=(int)$roots[0]['menu_id'];$summary['owner_store_rows']=$m['owner_store_rows'];$summary['new_marker_collision']=$m['new_marker_collision'];$summary['password_values_read']=0;$summary['normal_store_login_denied_by_missing_store']=($m['owner_store_rows']===0);file_put_contents(__DIR__.'/private/inspect-natural.json',json_encode($raw,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_PRESERVE_ZERO_FRACTION));chmod(__DIR__.'/private/inspect-natural.json',0600);file_put_contents(__DIR__.'/inspect-'.$lane.'.json',json_encode($summary,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));echo json_encode($summary),"\n";
