34 lines
3.6 KiB
PHP
34 lines
3.6 KiB
PHP
<?php
|
|
require __DIR__.'/sgc-invoice-proof-bootstrap.php';
|
|
require_once $repo.'/packages/sgc-invoice-client/src/InvoiceClient.php';
|
|
use Illuminate\Support\Facades\Crypt;
|
|
use Tempo\SgcInvoiceClient\InvoiceClient;
|
|
if(!is_file($proofRoot.'/authority-result.json')||is_file($proofRoot.'/client-kernel-result.json'))throw new LogicException('Fresh client contract proof required');
|
|
$old=json_decode(file_get_contents($proofRoot.'/initial-preview.json'),true);$cut=json_decode(Crypt::decryptString($old['data']['preview']),true);
|
|
$checks=[];$ok=function($v,$name)use(&$checks){if(!$v)throw new RuntimeException($name);$checks[]=$name;};
|
|
$invoiceBefore=$native->table('invoices')->orderBy('id')->get()->toJson();$auditBefore=$native->table('audit_logs')->count();
|
|
$calls=[];
|
|
$client=new InvoiceClient('synthetic',$secret['token'],$secret['context'],['tenant_id'=>91],$f['scope'],
|
|
function($method,$url,$headers,$body)use($send,&$calls){$calls[]=['method'=>$method,'path'=>parse_url($url,PHP_URL_PATH),'key'=>$headers['X-Idempotency-Key']];
|
|
$response=$send($body??[],$headers['X-Idempotency-Key'],[],parse_url($url,PHP_URL_PATH),null,$method);
|
|
return ['status'=>$response['status'],'json'=>$response['data']];});
|
|
$mapping=['id'=>'QA-PROTOCOL-MAPPING','version'=>1,'source_scope'=>['tenant_id'=>91],'target_scope'=>$f['scope'],
|
|
'order_id'=>$cut['order_id'],'lines'=>[],'authority'=>'sgf_only'];
|
|
$document=$cut['data'];foreach($document['items']as$i=>&$line){$ref='QA-SOURCE-LINE-'.$i;$mapping['lines'][$ref]=$line['purchase_order_item_id'];unset($line['purchase_order_item_id']);$line=['source_line_ref'=>$ref]+$line;}unset($line);
|
|
$draft=['reference'=>'QA-PROTOCOL-DRAFT','version'=>'QA-v1','state'=>'unregistered_draft','document'=>$document];
|
|
$intent=$client->intent($mapping,$draft,$cut['operation_key'],$cut['reason']);
|
|
$received=$client->preview($intent,'QA-v1',InvoiceClient::mappingHash($mapping));
|
|
$ok($received['phase']==='received_pending'&&$received['receipt']['replayed'],'prepared client recovers real existing native receipt through kernel');
|
|
$ok(count($calls)===2&&$calls[0]['method']==='GET'&&$calls[1]['method']==='POST','client performs exact context read and explicit preview/recovery only');
|
|
$ok($calls[0]['key']===$cut['operation_key']&&$calls[1]['key']===$cut['operation_key'],'native protocol retains one original UUID');
|
|
$draft['document']['number']='QA-SGC-CLIENT-PREVIEW-'.substr(basename($proofRoot),-12);
|
|
$fresh=$client->intent($mapping,$draft,(string)Illuminate\Support\Str::uuid(),$cut['reason']);
|
|
$preview=$client->preview($fresh,'QA-v1',InvoiceClient::mappingHash($mapping));
|
|
$ok($preview['phase']==='previewed'&&isset($preview['approval_hash'])&&$preview['impact']['budget_consumption_minor']===0,'prepared client consumes real native impact without confirming');
|
|
$ok($invoiceBefore===$native->table('invoices')->orderBy('id')->get()->toJson()&&$auditBefore===$native->table('audit_logs')->count(),'client contract proof adds no invoice or audit rows');
|
|
$ok(!str_contains(json_encode([$received,$preview]),$secret['token']),'serialised transport states exclude bearer credential');
|
|
file_put_contents($proofRoot.'/client-kernel-result.json',json_encode(['passed'=>true,'checks'=>$checks,'new_business_rows'=>0,'kernel_http'=>true,'tcp_8085'=>false,
|
|
'new_demo'=>false,'new_database'=>false,'sender_class_sha256'=>hash_file('sha256',$repo.'/packages/sgc-invoice-client/src/InvoiceClient.php'),
|
|
'reused_endpoint_proof_sha256'=>hash_file('sha256',$repo.'/docs/proofs/sgc-invoice-endpoint-20261110.json')],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
|
|
echo json_encode(['passed'=>true,'checks'=>count($checks)]).PHP_EOL;
|