2026-10-20 10:35:52 +08:00
import { createHash } from 'node:crypto'
import { confirmFleetLoading } from './fleet-trip-fulfillment.mjs'
2026-10-03 07:42:18 +08:00
const MODULE = 'fleet-cross-customer-acceptance'
const ROOT = '/api/platform/v1/last-leg'
const PDA = '/api/pda/v1/last-leg/dispatches'
const OPTIONS = { scenario : 'fleet-cross-customer-departure' , deploymentBlocker : true }
const id = value => value == null ? '' : String ( value )
const ok = response => response ? . http === 200 && id ( response . body ? . code ) === '200'
const encode = encodeURIComponent
const scoped = ( path , customerId ) => ` ${ path } ? ${ new URLSearchParams ({ customerId } )}`
const canonical = value => JSON . stringify ( normalize ( value ))
function normalize ( value ) {
if ( Array . isArray ( value )) return value . map ( normalize )
2026-10-20 10:35:52 +08:00
return value && typeof value === 'object' ? Object . fromEntries ( Object . keys ( value ). sort (). map ( key => [ key , normalize ( value [ key ])])) : value
2026-10-03 07:42:18 +08:00
}
function integer ( value ) {
2026-10-20 10:35:52 +08:00
if ( ! [ 'number' , 'string' ]. includes ( typeof value ) || ! /^(0|[1-9][0-9]*)$/ . test ( String ( value )) || ! Number . isSafeInteger ( Number ( value ))) throw new Error ( 'Invalid inventory integer' )
2026-10-03 07:42:18 +08:00
return Number ( value )
}
2026-10-20 10:35:52 +08:00
const buckets = [ 'availablePackages' , 'holdPackages' , 'allocatedPackages' , 'pickedPackages' , 'receivingPackages' ]
const balanceBuckets = [... buckets , 'inTransitPackages' , 'procurementPackages' ]
2026-10-03 07:42:18 +08:00
export const fixtureContract = Object . freeze ({
2026-10-20 10:35:52 +08:00
stage : 'TWO_FRESH_CUSTOMERS_ONE_REVIEWED_DISPATCH_LOADING_NOT_PICKED' ,
fixture : 'marker, warehouseId, dispatchNo, tripNo, tripProof, pdaToken, optional current-run loadingMeasurements; members[2]: marker/customerId/incomingNo/shared dispatchNo/dispatchItemId/balanceId/positionId/palletId/palletNo/receiptVerified' ,
preparation : 'Two independently qualified customers formally received one pallet/box each in the same warehouse. One native Create with both actual source selections; automatic unique Fleet record, resources and both native reviews. No picking or delivery arrangement.' ,
reader : 'readInventory(scope) returns all raw balances/positions/immutable movements including zero, exact marker/customer/warehouse and CUSTOMER_WAREHOUSE_COMPLETE coverage.' ,
boundary : 'Prerequisite rejection is separate from an explicitly injected real mid-transaction rollback. Actual loading needs actual evidence; absent measurement fields block. No environment loader, SQL or implicit account lifecycle.' ,
2026-10-03 07:42:18 +08:00
})
2026-10-20 10:35:52 +08:00
export const afterLoadingContinuationContract = Object . freeze ({
... fixtureContract ,
stage : 'TWO_OWNED_CUSTOMERS_ONE_DISPATCH_AFTER_LOADING_NOT_ARRANGED' ,
preparation : 'Explicit continuation only: prior failed proof with verified gate and complete AFTER_PICK_1; original successful loadingCommand/confirmedLoad; current AFTER_LOADING with no arrangement or execution documents.' ,
boundary : 'Reconcile original identities, complete picked inventory and original loading receipt through current reads before any new write. Never repeat picking/loading or rewrite the prior proof.' ,
})
export async function verifyFleetCrossCustomer ( context , fixture , { execute = false , readInventory , verifyDepartureRollback , completionPolling } = {}) {
2026-10-03 07:42:18 +08:00
if ( ! execute ) return fixtureContract
2026-10-20 10:35:52 +08:00
return runCrossCustomerCore ( context , fixture , { readInventory , verifyDepartureRollback , completionPolling })
}
export async function continueFleetCrossCustomerAfterLoading ( context , fixture , { execute = false , readInventory , verifyDepartureRollback , priorProof , completionPolling } = {}) {
if ( ! execute ) return afterLoadingContinuationContract
if ( ! priorProof ) throw new Error ( 'Explicit prior cross-customer proof is required for AFTER_LOADING continuation' )
return runCrossCustomerCore ( context , { ... fixture , members : structuredClone ( fixture ? . members ) },
{ readInventory , verifyDepartureRollback , priorProof , completionPolling })
}
async function runCrossCustomerCore ( context , fixture , { readInventory , verifyDepartureRollback , priorProof , completionPolling }) {
const continuation = priorProof !== undefined
const contract = continuation ? afterLoadingContinuationContract : fixtureContract
if ( ! context ? . marker || fixture ? . marker !== context . marker || fixture . stage !== contract . stage
|| ! fixture . dispatchNo || ! fixture . tripNo || fixture . tripProof ? . dispatchNo !== fixture . dispatchNo || fixture . tripProof . tripNo !== fixture . tripNo
|| ! context . createdResources ? . fleetTrips ? . includes ( fixture . tripProof )
|| ! fixture . warehouseId || ! fixture . pdaToken || typeof readInventory !== 'function' || fixture . members ? . length !== 2
|| new Set ( fixture . members . map ( row => row . customerId )). size !== 2
|| fixture . members . some ( row => row . marker !== context . marker || row . receiptVerified !== true || row . dispatchNo !== fixture . dispatchNo
|| [ 'customerId' , 'incomingNo' , 'dispatchItemId' , 'balanceId' , 'positionId' , 'palletId' , 'palletNo' ]. some ( field => ! id ( row [ field ]))))
throw new Error ( 'Requires two distinct current-run customers and one reviewed native dispatch with complete raw inventory evidence' )
for ( const field of [ 'incomingNo' , 'dispatchItemId' , 'positionId' , 'palletId' , 'balanceId' ])
if ( new Set ( fixture . members . map ( row => id ( row [ field ]))). size !== 2 ) throw new Error ( `Cross-customer fixture reuses ${ field } ` )
const polling = { maxAttempts : 41 , intervalMs : 500 , deadlineMs : 20000 , ... completionPolling }
if ( ! Number . isSafeInteger ( polling . maxAttempts ) || polling . maxAttempts < 1 || polling . maxAttempts > 121
|| ! Number . isSafeInteger ( polling . intervalMs ) || polling . intervalMs < 1 || polling . intervalMs > 2000
|| ! Number . isSafeInteger ( polling . deadlineMs ) || polling . deadlineMs < 1 || polling . deadlineMs > 60000 )
throw new Error ( 'Finite completion polling bounds are required' )
context . createdResources ??= {}
2026-10-03 07:42:18 +08:00
if ( context . createdResources . fleetCrossCustomer ) throw new Error ( 'Proof already exists; retain failed run and reconcile explicitly' )
2026-10-20 10:35:52 +08:00
const proof = context . createdResources . fleetCrossCustomer = { marker : context . marker , dispatchNo : fixture . dispatchNo , tripNo : fixture . tripNo ,
warehouseId : fixture . warehouseId , members : fixture . members . map (({ marker , customerId , incomingNo , dispatchNo , dispatchItemId , balanceId , positionId , palletId , palletNo }) =>
({ marker , customerId , incomingNo , dispatchNo , dispatchItemId , balanceId , positionId , palletId , palletNo })),
status : 'CHECKING' , requests : [], snapshots : {}, gateProof : 'NOT_RUN' , midTransactionRollback : 'NOT_TESTED' , cleanup : 'Caller owns account/session lifecycle; retain all business fixtures' }
const check = ( name , passed ) => { context . assert ( MODULE , name , null , Boolean ( passed ), '' , OPTIONS ); if ( ! passed ) throw new Error ( name ) }
const equal = ( a , b , name ) => check ( name , canonical ( a ) === canonical ( b ))
2026-10-03 07:42:18 +08:00
const key = suffix => ` ${ context . marker } -CROSS- ${ suffix } `
2026-10-20 10:35:52 +08:00
const path = ` ${ ROOT } /dispatches/ ${ encode ( fixture . dispatchNo ) } ` , pdaPath = ` ${ PDA } / ${ encode ( fixture . dispatchNo ) } `
2026-10-03 07:42:18 +08:00
const tripPath = ` ${ ROOT } /fleet/trips/ ${ encode ( fixture . tripNo ) } `
2026-10-20 10:35:52 +08:00
const request = async ( method , target , body , label , pda = false , rejection ) => {
const entry = { method , path : target , body , label , status : 'SENDING' }; proof . requests . push ( entry ); await context . checkpoint ? .()
let response
try { response = await context . request ( method , target , body , pda ? fixture . pdaToken : context . token , {}) }
catch ( error ) { entry . status = 'UNKNOWN_RESULT' ; await context . checkpoint ? .(); throw error }
Object . assign ( entry , { status : 'RESPONDED' , http : response ? . http , code : response ? . body ? . code , requestId : response ? . requestId , traceId : response ? . traceId })
await context . checkpoint ? .()
const denied = response ? . http === 409 || ( response ? . http === 200 && id ( response . body ? . code ) === 'A0409' )
const actorDenied = [ 200 , 403 ]. includes ( response ? . http ) && id ( response . body ? . code ) === 'A0403'
check ( label , Boolean ( response ? . requestId && response ? . traceId )
&& ( rejection === 'ACTOR_FORBIDDEN' ? actorDenied : rejection ? denied && rejection ( id ( response . body ? . message )) : ok ( response )))
2026-10-03 07:42:18 +08:00
return response . body ? . data
}
const stock = async member => {
const scope = { marker : context . marker , customerId : member . customerId , warehouseId : fixture . warehouseId }
const raw = await readInventory ( scope )
check ( 'Inventory reader proves complete customer/warehouse scope' , canonical ( raw ? . scope ) === canonical ({... scope , coverage : 'CUSTOMER_WAREHOUSE_COMPLETE' }))
for ( const collection of [ 'balances' , 'positions' , 'ledger' ]) check ( `Complete ${ collection } rows have unique identities and customer ownership` , Array . isArray ( raw [ collection ])
&& new Set ( raw [ collection ]. map ( row => id ( row . id ))). size === raw [ collection ]. length
&& raw [ collection ]. every ( row => id ( row . id ) && id ( row . customerId ) === id ( member . customerId ) && id ( row . overseasWarehouseId ) === id ( fixture . warehouseId )))
check ( 'Original receipt balance and physical position are retained even at zero' , raw . balances . some ( row => id ( row . id ) === id ( member . balanceId ))
&& raw . positions . some ( row => id ( row . id ) === id ( member . positionId ) && id ( row . balanceId ) === id ( member . balanceId ) && id ( row . palletId ) === id ( member . palletId ) && row . palletNo === member . palletNo ))
for ( const balance of raw . balances ) {
for ( const field of balanceBuckets ) integer ( balance [ field ])
const positions = raw . positions . filter ( row => id ( row . balanceId ) === id ( balance . id ))
for ( const field of buckets ) check ( `Raw balance and every position conserve ${ field } ` , integer ( balance [ field ]) === positions . reduce (( sum , row )=> sum + integer ( row [ field ]), 0 ))
}
check ( 'No orphan stock positions' , raw . positions . every ( row => raw . balances . some ( balance => id ( balance . id ) === id ( row . balanceId ))))
return raw
}
const snapshot = async label => {
2026-10-20 10:35:52 +08:00
const trip = await request ( 'GET' , tripPath , undefined , 'Read automatic unique Fleet resource record' )
check ( 'One trip binds exactly this one native cross-customer dispatch' , trip . trip ? . tripNo === fixture . tripNo
&& id ( trip . trip . warehouseId ) === id ( fixture . warehouseId ) && trip . dispatches ? . length === 1 && trip . dispatches [ 0 ]. dispatchNo === fixture . dispatchNo )
const dispatch = await request ( 'GET' , path , undefined , 'Read native whole dispatch' )
const items = await request ( 'GET' , ` ${ path } /items` , undefined , 'Read actual per-customer cargo' )
const task = await request ( 'GET' , pdaPath , undefined , 'Read bound warehouse native PDA task' , true )
check ( 'Native main/items/PDA retain both true customers and physical pallets' , dispatch . dispatchNo === fixture . dispatchNo
&& items . dispatchNo === fixture . dispatchNo && task . dispatchNo === fixture . dispatchNo && id ( task . warehouseId ) === id ( fixture . warehouseId )
&& id ( dispatch . recordVersion ) === id ( items . recordVersion ) && id ( task . recordVersion ) === id ( dispatch . recordVersion )
&& items . items ? . length === 2 && task . items ? . length === 2 && fixture . members . every ( member =>
items . items . some ( i => id ( i . dispatchItemId ) === member . dispatchItemId && id ( i . customerId ) === member . customerId
&& id ( i . warehousePalletId ) === member . palletId && i . palletNo === member . palletNo && integer ( i . scheduledPackages ) === 1 )
&& task . items . some ( i => id ( i . dispatchItemId ) === member . dispatchItemId && id ( i . customerId ) === member . customerId && i . palletNo === member . palletNo )))
const members = []
for ( const member of proof . members ) {
let outbound = null , delivery = null
if ( member . outboundNo || member . deliveryNo ) {
check ( 'Customer execution documents are both explicit' , member . outboundNo && member . deliveryNo )
outbound = await request ( 'GET' , scoped ( ` ${ ROOT } /outbound-orders/ ${ encode ( member . outboundNo ) } ` , member . customerId ), undefined , 'Read customer outbound' )
delivery = await request ( 'GET' , scoped ( ` ${ ROOT } /delivery-orders/ ${ encode ( member . deliveryNo ) } ` , member . customerId ), undefined , 'Read customer delivery' )
check ( 'Execution documents keep customer, warehouse and shared main ownership' , outbound . outbound ? . outboundNo === member . outboundNo
&& outbound . outbound . dispatchNo === fixture . dispatchNo && id ( outbound . outbound . overseasWarehouseId ) === id ( fixture . warehouseId )
&& outbound . deliveries ? . length === 1 && outbound . deliveries [ 0 ]. deliveryNo === member . deliveryNo
&& id ( outbound . deliveries [ 0 ]. customerId ) === member . customerId && delivery . order ? . deliveryNo === member . deliveryNo
&& id ( delivery . order . customerId ) === member . customerId && delivery . order . dispatchNo === fixture . dispatchNo && delivery . order . outboundNo === member . outboundNo )
}
members . push ({ outbound , delivery , stock : await stock ( member ) })
2026-10-03 07:42:18 +08:00
}
2026-10-20 10:35:52 +08:00
const value = { trip , dispatch , items , task , members }; proof . snapshots [ label ] = value ; return value
2026-10-03 07:42:18 +08:00
}
2026-10-20 10:35:52 +08:00
const pick = async ( member , index ) => {
const before = await snapshot ( `BEFORE_PICK_ ${ index } ` ), item = before . task . items . find ( i => id ( i . dispatchItemId ) === member . dispatchItemId )
check ( 'PDA exposes exactly this customer real current-run pallet and position' , integer ( item . scheduledPackages ) === 1 && integer ( item . pickedPackages ) === 0
&& item . palletNo === member . palletNo && item . positions ? . length === 1 && id ( item . positions [ 0 ]. positionId ) === member . positionId
&& integer ( item . positions [ 0 ]. availablePackages ) === 1 )
const body = { recordVersion : before . task . recordVersion , positionId : member . positionId , packages : 1 , productQuantity : 1 ,
idempotencyKey : key ( `PICK- ${ index } ` ), remark : context . marker }
const pickPath = ` ${ pdaPath } /items/ ${ encode ( member . dispatchItemId ) } /pick`
await request ( 'POST' , pickPath , body , 'Pick this customer only' , true )
const after = await snapshot ( `AFTER_PICK_ ${ index } ` )
equal ( before . members [ 1 - index ]. stock , after . members [ 1 - index ]. stock , 'Other customer inventory unchanged by picking' )
const expected = structuredClone ( before . members [ index ]. stock )
for ( const collection of [ 'balances' , 'positions' ]) expected [ collection ]. find ( row => id ( row . id ) === ( collection === 'balances' ? member . balanceId : member . positionId )). availablePackages = 0
const counts = raw => Object . fromEntries ([ 'balances' , 'positions' ]. map ( collection => [ collection , raw [ collection ]. map ( row => ({ id : id ( row . id ),
... Object . fromEntries (( collection === 'balances' ? balanceBuckets : buckets ). map ( field => [ field , integer ( row [ field ])])) }))]))
equal ( counts ( expected ), counts ( after . members [ index ]. stock ), 'Only selected customer position and balance lose one box' )
const old = before . members [ index ]. stock . ledger , newRows = after . members [ index ]. stock . ledger . filter ( row => ! old . some ( prior => id ( prior . id ) === id ( row . id )))
equal ( old , after . members [ index ]. stock . ledger . filter ( row => old . some ( prior => id ( prior . id ) === id ( row . id ))), 'Immutable old movements preserved' )
check ( 'Single ALLOCATE/PICK/SHIP sequence has exact source and quantity' , newRows . length === 3 && [ 'ALLOCATE' , 'PICK' , 'SHIP' ]. every ( type => newRows . filter ( row =>
row . businessType === type && id ( row . positionId ) === member . positionId && row . businessOrderNo === fixture . dispatchNo && Number ( row . deltaPackages ) === ( type === 'SHIP' ? - 1 : 1 )). length === 1 ))
await request ( 'POST' , pickPath , body , 'Replay exact customer pick' , true )
equal ( after , await snapshot ( `PICK_REPLAY_ ${ index } ` ), 'Pick replay changes neither customer nor any execution record' )
2026-10-03 07:42:18 +08:00
}
try {
2026-10-20 10:35:52 +08:00
let cargoBasis , originalLoadingHash
if ( continuation ) {
const prior = priorProof . snapshots ? . AFTER_PICK_1 , command = fixture . tripProof . loadingCommand
const confirmed = command ? . result ? . result ? . confirmedLoad
check ( 'Continuation has the original failed owned proof and verified prerequisite gate' , priorProof . status === 'FAILED'
&& priorProof . marker === context . marker && priorProof . dispatchNo === fixture . dispatchNo && priorProof . tripNo === fixture . tripNo
&& id ( priorProof . warehouseId ) === id ( fixture . warehouseId ) && priorProof . gateProof === 'PREREQUISITE_REJECTION_VERIFIED'
&& priorProof . members ? . length === 2 && ! priorProof . arrangeRequest && ! priorProof . departure
&& ! priorProof . members . some ( member => member . outboundNo || member . deliveryNo )
&& Array . isArray ( priorProof . requests ) && priorProof . requests . every ( entry => [ 'GET' , 'HEAD' , 'OPTIONS' ]. includes ( entry . method ) || entry . status === 'RESPONDED' ))
const identityFields = [ 'marker' , 'customerId' , 'incomingNo' , 'dispatchNo' , 'dispatchItemId' , 'balanceId' , 'positionId' , 'palletId' , 'palletNo' ]
check ( 'Continuation preserves each original customer, source, item, balance, position and physical pallet' , fixture . members . every (( member , index ) =>
identityFields . every ( field => id ( member [ field ]) === id ( priorProof . members [ index ] ? .[ field ]))))
check ( 'Prior AFTER_PICK_1 is a complete reviewed picked but not shipped native snapshot' , prior ? . dispatch ? . dispatchNo === fixture . dispatchNo
&& prior . dispatch . status === 'ACTIVE' && prior . dispatch . stage === 'LOADING' && prior . dispatch . reviewState === 'APPROVED'
&& prior . dispatch . reviews ? . dispatchReview ? . status === 'APPROVED' && prior . dispatch . reviews ? . loadingReview ? . status === 'APPROVED'
&& integer ( prior . dispatch . counts ? . packageCount ) === 2 && integer ( prior . dispatch . counts ? . pickedPackageCount ) === 2
&& integer ( prior . dispatch . counts ? . shippedPackageCount ) === 0 && prior . task ? . pickingReconciled === true
&& prior . task . dispatchNo === fixture . dispatchNo && id ( prior . task . warehouseId ) === id ( fixture . warehouseId )
&& prior . task . stage === 'LOADING' && id ( prior . task . recordVersion ) === id ( prior . dispatch . recordVersion )
&& prior . items ? . dispatchNo === fixture . dispatchNo && id ( prior . items . recordVersion ) === id ( prior . dispatch . recordVersion )
&& prior . items . items ? . length === 2 && prior . task . items ? . length === 2
&& prior . members ? . length === 2 && prior . members . every ( row => row . stock && ! row . outbound && ! row . delivery )
&& prior . dispatch . documents ? . outbounds ? . length === 0 && prior . dispatch . documents ? . deliveries ? . length === 0 )
check ( 'Original loading command has a successful explicit receipt for this main and both exact physical pallets' , command ? . path === ` ${ pdaPath } /loading-complete`
&& command . body ? . idempotencyKey && command . body . manifestHash && command . result ? . dispatchNo === fixture . dispatchNo
&& command . result . action === 'LOADING_COMPLETE' && command . result . idempotencyKey === command . body . idempotencyKey
&& command . result . status === 'ACTIVE' && command . result . stage === 'AFTER_LOADING' && command . result . result ? . loadingCompletionHash
&& id ( command . body . recordVersion ) === id ( prior . dispatch . recordVersion )
&& /^(0|[1-9]\d*)$/ . test ( id ( command . result . recordVersion ))
&& /^(0|[1-9]\d*)$/ . test ( id ( command . body . recordVersion ))
&& BigInt ( id ( command . result . recordVersion )) > BigInt ( id ( command . body . recordVersion ))
&& integer ( command . result . counts ? . packageCount ) === 2 && integer ( command . result . counts ? . pickedPackageCount ) === 2
&& integer ( command . result . counts ? . shippedPackageCount ) === 0
&& confirmed ? . manifestHash === command . body . manifestHash && confirmed . operatorId && Number . isFinite ( Date . parse ( confirmed . confirmedAt ))
&& canonical ( confirmed ) === canonical ( fixture . tripProof . confirmedLoad )
&& Array . isArray ( command . body . measurements ) && command . body . measurements . length === 2
&& canonical ( command . body . measurements ) === canonical ( confirmed . pallets )
&& new Set ( confirmed . pallets . map ( row => id ( row . warehousePalletId ))). size === 2
&& fixture . members . every ( member => confirmed . pallets . some ( row => id ( row . warehousePalletId ) === member . palletId
&& Number . isSafeInteger ( row . palletSpaces ) && row . palletSpaces > 0
&& [ 'weightKg' , 'volumeCbm' ]. every ( field => [ 'number' , 'string' ]. includes ( typeof row [ field ])
&& /^(?:0|[1-9]\d*)(?:\.\d+)?$/ . test ( String ( row [ field ])) && Number . isFinite ( Number ( row [ field ])) && Number ( row [ field ]) > 0 )
&& Number . isSafeInteger ( row . deliveryIndex ) && row . deliveryIndex > 0 && fixture . tripProof . stops ? .[ row . deliveryIndex ] ? . destinationKey )))
proof . continued = true
proof . continuation = { mode : 'EXPLICIT_AFTER_LOADING' , priorProofSHA256 : createHash ( 'sha256' ). update ( canonical ( priorProof )). digest ( 'hex' ),
priorStatus : priorProof . status , gateProofSource : 'PRIOR_PROOF' , originalAfterPickSnapshot : structuredClone ( prior ),
originalLoadingCommand : structuredClone ( command ), originalConfirmedLoad : structuredClone ( confirmed ) }
proof . gateProof = priorProof . gateProof
await context . checkpoint ? .()
const initial = await snapshot ( 'CONTINUATION_INITIAL' )
check ( 'Current main is exactly the unarranged confirmed loading version with two picked and zero shipped packages' , initial . dispatch . status === 'ACTIVE'
&& initial . dispatch . stage === 'AFTER_LOADING' && initial . task . stage === 'AFTER_LOADING' && initial . trip . trip . status === 'PLANNED'
&& id ( initial . dispatch . recordVersion ) === id ( command . result . recordVersion ) && initial . task . pickingReconciled === true
&& initial . dispatch . reviewState === 'APPROVED' && initial . dispatch . reviews ? . dispatchReview ? . status === 'APPROVED'
&& initial . dispatch . reviews ? . loadingReview ? . status === 'APPROVED' && integer ( initial . dispatch . counts . packageCount ) === 2
&& integer ( initial . dispatch . counts . pickedPackageCount ) === 2 && integer ( initial . dispatch . counts . shippedPackageCount ) === 0
&& initial . dispatch . documents ? . outbounds ? . length === 0 && initial . dispatch . documents ? . deliveries ? . length === 0
&& id ( initial . trip . trip . vehicleId ) === id ( fixture . tripProof . vehicleId ) && id ( initial . trip . trip . driverId ) === id ( fixture . tripProof . driverId )
&& id ( prior . trip ? . trip ? . vehicleId ) === id ( fixture . tripProof . vehicleId ) && id ( prior . trip ? . trip ? . driverId ) === id ( fixture . tripProof . driverId )
&& canonical ( initial . trip . trip . stops ) === canonical ( fixture . tripProof . stops )
&& initial . items . items . every ( item => integer ( item . pickedPackages ) === 1 ) && initial . task . items . every ( item => integer ( item . pickedPackages ) === 1 ))
equal ( prior . members . map ( row => row . stock ), initial . members . map ( row => row . stock ), 'Continuation current complete inventory equals original AFTER_PICK_1 inventory' )
const sourceItems = items => items . map ( item => Object . fromEntries ([ 'dispatchItemId' , 'customerId' , 'sourceKey' , 'sourceVersion' , 'sourceType' ,
'planPalletId' , 'returnReceiptId' , 'relabelNo' , 'warehousePalletId' , 'palletNo' , 'orderNo' , 'inboundCode' , 'destination' , 'scheduledPackages' , 'pickedPackages' ]
. map ( field => [ field , item [ field ]]))). sort (( a , b ) => id ( a . dispatchItemId ). localeCompare ( id ( b . dispatchItemId )))
equal ( sourceItems ( prior . items . items ), sourceItems ( initial . items . items ), 'Continuation preserves both picked source items and destinations' )
const loading = await request ( 'GET' , ` ${ pdaPath } /loading` , undefined , 'Reconcile current native manifest against original successful loading receipt' , true )
check ( 'Current loading preview preserves the original manifest, confirmed receipt and two reconciled physical pallets' , loading . dispatchNo === fixture . dispatchNo
&& loading . status === 'ACTIVE' && loading . stage === 'AFTER_LOADING' && id ( loading . recordVersion ) === id ( command . result . recordVersion )
&& loading . pickingReconciled === true && loading . manifestHash === confirmed . manifestHash
&& canonical ( loading . confirmedLoad ) === canonical ( confirmed ) && loading . pallets ? . length === 2
&& new Set ( loading . pallets . map ( row => id ( row . warehousePalletId ))). size === 2
&& fixture . members . every ( member => loading . pallets . some ( row => id ( row . warehousePalletId ) === member . palletId
&& row . palletNo === member . palletNo && integer ( row . scheduledPackages ) === 1 && integer ( row . pickedPackages ) === 1 )))
proof . continuation . currentLoadingPreview = loading
cargoBasis = initial
originalLoadingHash = command . result . result . loadingCompletionHash
} else {
const initial = await snapshot ( 'INITIAL' )
check ( 'Fresh native fixture is reviewed LOADING with both customer receipts untouched' , initial . trip . trip . status === 'PLANNED'
&& initial . dispatch . status === 'ACTIVE' && initial . dispatch . stage === 'LOADING' && initial . dispatch . reviewState === 'APPROVED'
&& initial . dispatch . reviews ? . dispatchReview ? . status === 'APPROVED' && initial . dispatch . reviews ? . loadingReview ? . status === 'APPROVED'
&& integer ( initial . dispatch . counts . packageCount ) === 2 && integer ( initial . dispatch . counts . pickedPackageCount ) === 0
&& initial . dispatch . documents ? . deliveries ? . length === 0 && initial . members . every (( row , index ) =>
integer ( row . stock . positions . find ( p => id ( p . id ) === fixture . members [ index ]. positionId ). availablePackages ) === 1
&& row . stock . balances . every ( balance => balanceBuckets . filter ( field => field !== 'availablePackages' ). every ( field => integer ( balance [ field ]) === 0 ))
&& row . stock . balances . reduce (( sum , balance ) => sum + integer ( balance . availablePackages ), 0 ) === 1 ))
await pick ( proof . members [ 0 ], 0 )
const rejectedBefore = await snapshot ( 'GATE_BEFORE' )
check ( 'Precisely one customer picked while main remains LOADING' , integer ( rejectedBefore . dispatch . counts . pickedPackageCount ) === 1
&& rejectedBefore . dispatch . stage === 'LOADING' && rejectedBefore . task . pickingReconciled === false )
const preview = await request ( 'GET' , ` ${ pdaPath } /loading` , undefined , 'Read incomplete native loading manifest' , true )
await request ( 'POST' , ` ${ pdaPath } /loading-complete` , { recordVersion : rejectedBefore . task . recordVersion , idempotencyKey : key ( 'UNREADY-LOAD' ),
manifestHash : preview . manifestHash , measurements : [], remark : context . marker }, 'Unready second customer blocks explicit loading' , true ,
message => / 拣货 . * 核平 | 尚未核平 / . test ( message ))
await request ( 'POST' , ` ${ pdaPath } /depart` , { recordVersion : rejectedBefore . task . recordVersion , idempotencyKey : key ( 'UNREADY-DEPART' ), remark : context . marker },
'Unready second customer blocks whole trip before execution' , true , message => / 装车 | 派送 / . test ( message ))
equal ( rejectedBefore , await snapshot ( 'GATE_AFTER' ), 'Rejected departure leaves both complete inventories/outbounds/deliveries/trip unchanged' )
proof . gateProof = 'PREREQUISITE_REJECTION_VERIFIED'
await pick ( proof . members [ 1 ], 1 )
await confirmFleetLoading ( context , MODULE , fixture . tripProof , fixture . pdaToken , fixture . loadingMeasurements )
cargoBasis = proof . snapshots . AFTER_PICK_1
2026-10-04 10:32:26 +08:00
}
2026-10-20 10:35:52 +08:00
const arrangement = await request ( 'GET' , ` ${ path } /delivery-arrangement` , undefined , 'Read native loaded per-customer delivery arrangement' )
if ( continuation ) check ( 'Continuation has no prior arrangement and retains the original loading completion hash' , arrangement . arrangement == null
&& arrangement . loadingCompletionHash === originalLoadingHash && id ( arrangement . recordVersion ) === id ( fixture . tripProof . loadingCommand . result . recordVersion ))
check ( 'Loaded arrangement groups cover exactly both real customers' , arrangement . dispatchNo === fixture . dispatchNo && arrangement . status === 'ACTIVE'
&& arrangement . stage === 'AFTER_LOADING' && arrangement . arrange ? . allowed === true && arrangement . cargoHash && arrangement . loadingCompletionHash
&& arrangement . groups ? . length === 2 && proof . members . every ( m => arrangement . groups . some ( g => id ( g . customerId ) === m . customerId && g . cargo ? . length
&& g . cargo . every ( c => id ( c . customerId ) === m . customerId && id ( c . warehousePalletId ) === m . palletId ) && g . blockReasons ? . length === 0
&& g . destination ? . key === cargoBasis . items . items . find ( i => id ( i . customerId ) === m . customerId ) ? . destination ? . key )))
const arrangeBody = { recordVersion : arrangement . recordVersion , idempotencyKey : key ( 'ARRANGE' ), cargoHash : arrangement . cargoHash ,
loadingCompletionHash : arrangement . loadingCompletionHash , groups : arrangement . groups . map ( g => ({ groupKey : g . groupKey , groupCargoHash : g . groupCargoHash ,
plannedDeliveryAt : new Date ( Date . now () + 21600000 ). toISOString (), deliveryMethod : 'TRUCK_PALLET' , pickupMethod : 'WAREHOUSE_PICKUP' ,
loadingType : 'PALLET' , vehicleType : 'TRUCK' , vehicleSize : '本轮实际装载' , appointmentAccount : 'SELF' , remark : ` ${ context . marker } TEST合成资料` ,
externalFreightHash : g . externalFreightHash , feeCoverageCargoHash : g . feeCoverageCargoHash , feeCoverage : [],
fees : ( g . requiredServices || []). map ( feeType => ({ feeType , feeName : 'TEST本轮派送费' , direction : 'RECEIVABLE' , currency : 'CNY' , amount : 30 })) })) }
proof . arrangeRequest = arrangeBody
const arranged = await request ( 'POST' , ` ${ path } /transfer-delivery` , arrangeBody , 'Arrange both customers after real loading before departure' )
check ( 'Native arrangement creates customer-isolated outbounds and deliveries' , arranged . dispatchNo === fixture . dispatchNo && arranged . stage === 'AFTER_LOADING'
&& arranged . result ? . deliveries ? . length === 2 && arranged . result . outbounds ? . length === 2
&& new Set ( arranged . result . deliveries . map ( d => d . deliveryNo )). size === 2 && new Set ( arranged . result . outbounds . map ( o => o . outboundNo )). size === 2 )
for ( const [ index , member ] of proof . members . entries ()) {
const deliveries = arranged . result . deliveries . filter ( d => id ( d . customerId ) === member . customerId )
check ( 'Each customer has exactly its own source-specific delivery and outbound' , deliveries . length === 1 && integer ( deliveries [ 0 ]. packageCount ) === 1
&& arranged . result . outbounds . some ( o => id ( o . customerId ) === member . customerId && o . outboundNo === deliveries [ 0 ]. outboundNo && integer ( o . packageCount ) === 1 ))
Object . assign ( member , { outboundNo : deliveries [ 0 ]. outboundNo , deliveryNo : deliveries [ 0 ]. deliveryNo })
Object . assign ( fixture . members [ index ], { outboundNo : member . outboundNo , deliveryNo : member . deliveryNo })
2026-10-03 07:42:18 +08:00
}
2026-10-20 10:35:52 +08:00
const arrangedReplay = await request ( 'POST' , ` ${ path } /transfer-delivery` , arrangeBody , 'Replay exact native customer arrangement' )
check ( 'Native arrangement replay keeps original documents and main version' , arrangedReplay . replayed === true && id ( arrangedReplay . recordVersion ) === id ( arranged . recordVersion )
&& canonical ( arrangedReplay . result ) === canonical ( arranged . result ))
const ready = await snapshot ( 'READY' ), departBody = { recordVersion : ready . task . recordVersion , idempotencyKey : key ( 'DEPART' ), remark : context . marker }
const departPath = ` ${ pdaPath } /depart`
if ( verifyDepartureRollback !== undefined ) {
check ( 'Explicit rollback verifier is callable' , typeof verifyDepartureRollback === 'function' )
const rollback = await verifyDepartureRollback ({ context , fixture , ready , departPath , departBody , snapshot })
check ( 'Mid-transaction rollback has exact owned verification' , rollback ? . verified === true && rollback . scope === 'OWNED_TWO_CUSTOMER_DEPARTURE_ROLLBACK' )
equal ( ready , await snapshot ( 'ROLLBACK_RESTORED' ), 'Mid-transaction rollback restores both complete customer execution and inventory snapshots' )
proof . rollbackEvidence = rollback ; proof . midTransactionRollback = 'VERIFIED'
}
const departed = await request ( 'POST' , departPath , departBody , 'Depart one cross-customer native dispatch once' , true )
check ( 'Departure includes both customers in the one actual native main' , departed . dispatchNo === fixture . dispatchNo && departed . status === 'ACTIVE'
&& departed . stage === 'DELIVERING' && integer ( departed . result ? . shippedPackages ) === 2 && departed . result . deliveries ? . length === 2 )
proof . departure = departed
const after = await snapshot ( 'DEPARTED' )
check ( 'Both customer outbounds completed and main delivering' , after . trip . trip . status === 'IN_TRANSIT' && after . dispatch . stage === 'DELIVERING'
&& after . members . every ( row => row . outbound . outbound . status === 'OUTBOUNDED' && row . delivery . order . status === 'DELIVERING' ))
equal ( ready . members . map ( row => row . stock ), after . members . map ( row => row . stock ), 'Departure does not deduct either inventory again' )
const replay = await request ( 'POST' , departPath , departBody , 'Original PDA actor exact replay of native departure' , true )
check ( 'Shared departure replay is explicit and returns original result' , replay . replayed === true && id ( replay . recordVersion ) === id ( departed . recordVersion )
&& canonical ( replay . result ) === canonical ( departed . result ))
const replayed = await snapshot ( 'DEPART_REPLAY' )
equal ( after , replayed , 'Departure replay preserves both complete inventories and execution facts' )
await request ( 'POST' , ` ${ path } /depart` , departBody , 'Different platform actor cannot reuse the PDA departure command key' , false , 'ACTOR_FORBIDDEN' )
equal ( replayed , await snapshot ( 'FOREIGN_ACTOR_DEPART_REJECTED' ), 'Different actor rejection preserves both complete inventories and execution facts' )
for ( const [ index , member ] of proof . members . entries ()) {
const before = await snapshot ( `BEFORE_SIGN_ ${ index } ` ), documentPath = scoped ( ` ${ ROOT } /delivery-orders/ ${ encode ( member . deliveryNo ) } /documents` , member . customerId )
const docs = await request ( 'GET' , documentPath , undefined , 'Read this customer delivery document version' )
const uploadPath = scoped ( ` ${ ROOT } /delivery-orders/ ${ encode ( member . deliveryNo ) } /documents/RECEIPT/files` , member . customerId )
const uploadEntry = { method : 'POST' , path : uploadPath , label : 'Upload own synthetic receipt' , status : 'SENDING' }; proof . requests . push ( uploadEntry ); await context . checkpoint ? .()
let uploaded
try { uploaded = await context . requestMultipart ( 'POST' , uploadPath , { name : ` ${ context . marker } - ${ index } -TEST-receipt.txt` , type : 'text/plain' ,
content : new TextEncoder (). encode ( ` ${ context . marker } synthetic TEST receipt ${ member . deliveryNo } ` ) }) }
catch ( error ) { uploadEntry . status = 'UNKNOWN_RESULT' ; await context . checkpoint ? .(); throw error }
Object . assign ( uploadEntry , { status : 'RESPONDED' , http : uploaded ? . http , code : uploaded ? . body ? . code , requestId : uploaded ? . requestId , traceId : uploaded ? . traceId }); await context . checkpoint ? .()
check ( 'Receipt uploaded through correct customer endpoint' , ok ( uploaded ) && uploaded . requestId && uploaded . traceId && id ( uploaded . body ? . data ? . fileId ))
const documents = ( docs . categories || []). filter ( row => row . category !== 'RECEIPT' ). map ( row => ({ category : row . category , fileIds : ( row . files || []). map ( file => file . fileId ) }))
documents . push ({ category : 'RECEIPT' , fileIds : [ id ( uploaded . body . data . fileId )] })
await request ( 'PUT' , documentPath , { expectedVersion : docs . version , idempotencyKey : key ( `SIGN- ${ index } ` ), bolNo : docs . bolNo || null , documents }, 'Attach receipt to independently complete this delivery' )
const signed = await snapshot ( `SIGNED_ ${ index } ` )
check ( 'This customer independently signed' , signed . members [ index ]. delivery . order . status === 'DELIVERED' )
equal ( before . members [ 1 - index ]. delivery , signed . members [ 1 - index ]. delivery , 'Other customer delivery is not signed or changed implicitly' )
equal ( before . members . map ( row => row . stock ), signed . members . map ( row => row . stock ), 'Signing does not mutate either customer inventory' )
}
const started = Date . now ()
proof . completionPolling = { ... polling , status : 'WAITING' , attempts : [] }
for ( let attempt = 1 ; attempt <= polling . maxAttempts ; attempt ++ ) {
if ( Date . now () - started >= polling . deadlineMs ) break
const entry = { attempt , elapsedMs : Date . now () - started , status : 'READING' }
proof . completionPolling . attempts . push ( entry )
const current = await request ( 'GET' , path , undefined , 'Read bounded automatic delivery completion progress' )
check ( 'Completion progress retains the exact normal main, counts and both execution-document owners' , current . dispatchNo === fixture . dispatchNo
&& current . status === 'ACTIVE' && [ 'DELIVERING' , 'DELIVERED' ]. includes ( current . stage )
&& /^(0|[1-9]\d*)$/ . test ( id ( current . recordVersion )) && integer ( current . counts ? . packageCount ) === 2
&& integer ( current . counts ? . pickedPackageCount ) === 2 && integer ( current . counts ? . shippedPackageCount ) === 2
&& current . documents ? . outbounds ? . length === 2 && current . documents ? . deliveries ? . length === 2
&& proof . members . every ( member => current . documents . outbounds . some ( row => id ( row . customerId ) === member . customerId && row . outboundNo === member . outboundNo )
&& current . documents . deliveries . some ( row => id ( row . customerId ) === member . customerId && row . deliveryNo === member . deliveryNo && row . outboundNo === member . outboundNo )))
Object . assign ( entry , { status : 'RESPONDED' , stage : current . stage , recordVersion : current . recordVersion , elapsedMs : Date . now () - started })
if ( entry . elapsedMs >= polling . deadlineMs ) break
if ( current . stage === 'DELIVERED' ) { proof . completionPolling . status = 'COMPLETED' ; break }
await context . checkpoint ? .()
const remaining = polling . deadlineMs - ( Date . now () - started )
if ( attempt < polling . maxAttempts && remaining > 0 ) await new Promise ( resolve => setTimeout ( resolve , Math . min ( polling . intervalMs , remaining )))
}
proof . completionPolling . elapsedMs = Date . now () - started
if ( proof . completionPolling . status !== 'COMPLETED' ) {
proof . completionPolling . status = 'TIMED_OUT'
await context . checkpoint ? .()
throw new Error ( 'Automatic delivery completion did not reach DELIVERED within the explicit read-only polling bounds' )
}
const final = await snapshot ( 'FINAL' )
check ( 'All normal customer signatures aggregate native delivery completion' , final . dispatch . status === 'ACTIVE' && final . dispatch . stage === 'DELIVERED' )
proof . status = 'VERIFIED' ; return proof
} catch ( error ) {
proof . status = 'FAILED' ; proof . error = error . message
if ( proof . completionPolling ? . status === 'WAITING' ) {
proof . completionPolling . status = 'FAILED' ; proof . completionPolling . error = error . message
const attempt = proof . completionPolling . attempts . at ( - 1 )
if ( attempt ? . status === 'READING' ) attempt . status = 'FAILED'
}
throw error
}
2026-10-03 07:42:18 +08:00
}