array_replace($s['source'],['username'=>$native['role'],'password'=>$native['password']])]);$writer=DB::connection('qa_native_writer');$book=$writer->table('gl_stock_books')->where('id',$f['book_id'])->first();$item=(array)$writer->table('stock_items')->where('id',$book->stock_item_id)->first();$checks=[];$ok=function($v,$name)use(&$checks){if(!$v)throw new RuntimeException($name);$checks[]=$name;}; $hash=function()use($writer){$h=hash_init('sha256');foreach(['stock_items','warehouses','stock_movements','gl_journals','gl_lines','gl_stock_rates','gl_stock_rate_reviews']as$t){hash_update($h,$t);foreach($writer->table($t)->orderBy('id')->cursor()as$r)hash_update($h,json_encode($r,JSON_THROW_ON_ERROR));}return hash_final($h);};$before=$hash(); $socket=stream_socket_server('tcp://127.0.0.1:0');$port=(int)substr(strrchr(stream_socket_get_name($socket,false),':'),1);fclose($socket);$server=new Symfony\Component\Process\Process([PHP_BINARY,'-S','127.0.0.1:'.$port,__DIR__.'/stock-ledger-observer-router.php'],dirname(__DIR__),['STOCK_OBSERVER_SETTINGS'=>$s['root'].'/settings.json'],null,45);$server->start(); try{for($i=0;$i<80;$i++){if($sock=@fsockopen('127.0.0.1',$port,$e,$m,.1)){fclose($sock);break;}usleep(50000);}$jar=new GuzzleHttp\Cookie\CookieJar();$client=new GuzzleHttp\Client(['base_uri'=>'http://127.0.0.1:'.$port,'cookies'=>$jar,'http_errors'=>false,'timeout'=>15]);$entry=json_decode((string)$client->get('/qa/stock-observer/reader')->getBody(),true,32,JSON_THROW_ON_ERROR);$r=$client->get('/api/stock-valuation-read',['headers'=>['X-SGF-Context'=>$entry['context'],'Accept'=>'application/json']]);$data=json_decode((string)$r->getBody(),true,64,JSON_THROW_ON_ERROR);$ok($r->getStatusCode()===200&&$data['reconciliation_scope']==='physical_movement_coverage_and_rate_ids_only'&&$data['current_source_dependencies_validated']===false,'observer qualifies its reconciliation scope'); try{$writer->table('stock_items')->where('id',$item['id'])->update(['unit'=>'KG']);$r=$client->get('/api/stock-valuation-read',['headers'=>['X-SGF-Context'=>$entry['context'],'Accept'=>'application/json']]);$ok($r->getStatusCode()===503,'changed native unit refused before presenting stock value');}finally{$writer->table('stock_items')->where('id',$item['id'])->update(['unit'=>$item['unit']]);} $r=$client->get('/general-ledger/stock-valuation');$ok($r->getStatusCode()===200&&str_contains((string)$r->getBody(),'restantes dependĂȘncias'),'restored unit recovers and HTML states source conference limitation');$ok($before===$hash(),'all native metadata movements rates and journals exactly restored'); file_put_contents($s['root'].'/proof-final.json',json_encode(['passed'=>true,'checks'=>$checks,'synthetic_metadata_probe_restored'=>true,'actual_http'=>true,'not_full_source_revalidation'=>true],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo count($checks)." observer final metadata/qualification checks passed.\n"; }finally{$server->stop(2);file_put_contents($s['root'].'/http-final.log',$server->getOutput()."\n".$server->getErrorOutput());}