test(lastleg): verify dispatch repair with current-run HTTP evidence

This commit is contained in:
2026-10-18 19:21:12 +08:00
parent db4354bda8
commit 4bef8577fa
3 changed files with 742 additions and 0 deletions
+4
View File
@@ -8,6 +8,10 @@
## 当前新增脚本的执行边界
`dispatch-repair-acceptance.mjs` 是本批排车修复的内部增量验收助手,不是独立 CLI。`verifyDispatchRepair` 默认只返回计划,显式执行要求 TEST、Lastleg/Admin 健康及 Schema 就绪、请求前后持久化检查点。`context.producerEvidence` 指定本轮生产回执 JSON 的路径及 SHA-256;文件须含 `environment=TEST`、`marker`、已部署 Lastleg 的 `sourceCommit` 和 `requests`。请求条目保留实际 `method/path/body/actor`、`status=RESPONDED`、`http/code/requestId/traceId/result`,不得保存登录凭据或 Token。助手从正式创建响应及父来源回执提取业务号、客户和仓库,形成资源白名单;所有 fixture 关联身份在首个请求前核对,不能仅声明“本轮新建”。缺样本标记 NOT_RUN,不借旧业务样本。
该助手核对取消出库/取消排车/释放重排、实际出库门禁、换标全托、混托两种展示来源、拆合托后重核、原箱回仓及只读权限。两种混托须使用独立排车/托盘/预订,普通与外接来源的箱数由生产实收回执确定,并回查实物仓位组成及报价数量/单价/金额。原箱限本轮单箱出库,按原始 SKU、客户、仓分页精确筛选库存及流水,以排车号匹配 OUTBOUND;先取完成前 S、首次完成后 R,再同键重放取 R′,核对本轮唯一 SKU 的完成前零库存基线及首次总量、可用展示数量、箱数恢复、receiptNo 的 EXCEPTION_RETURN_IN 精确集合、目标托盘库位及重放零增量。HTTP availableQuantity 是受实箱可用量限制的展示值,不冒称裸余额证明。只对已授权的新排车调用 DELETE 取消状态,不运行移托 DELETE 负向分支,不物理删除、SQL 造数或清理。未知结果保存原命令并停写;证据明确标为合成测试资料,不冒充真实外部预约/POD。保留 `sourceEventsVerified=false`,来源事件、人工页面及 PDA 真机仍单列。相邻 `dispatch-repair-acceptance-contract.test.mjs` 只做离线验证,未实际执行不得表述为环境通过。
- 人工状态矩阵的 `FEE_CONFIRMING` 使用独立新订单,在测量提交成功后暂停审核,经正式 `fees/calculate` 生成费用;回查同一费用版本、入库客户身份、测量仍待审核及入仓码精确筛选结果。该状态是必验项,不再列入不可造数缺口;不发送费用、不推进该样本、不借历史数据。入口仍为 `--modules manual-state-matrix`,对应 `order-inbound-status-fixtures-contract.test.mjs` 和 `manual-state-matrix-contract.test.mjs`。
- `WAIT_PRICING` 另建保留原始 `APPROVED` 的订单,先形成未发布的 `FEE_CONFIRMING`,再通过客户实时渠道目录与报价选择同仓、同目的仓、同税制的不同渠道,以正式申报更新触发费用失效;回查 `WAIT_PRICING/UNPRICED`、新渠道及精确筛选。缺少可计价替换渠道、客户漂移或状态未收敛均失败;不写业务SQL,退出专用目录查询会话。该状态同样为必验项,原先借历史 `WAIT_SPLIT` 样本的兜底已移除。
@@ -0,0 +1,304 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { after } from 'node:test'
import { writeFileSync, unlinkSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { randomUUID, createHash } from 'node:crypto'
import { verifyDispatchRepair } from './dispatch-repair-acceptance.mjs'
const commit = 'a'.repeat(40)
const ok = data => ({ http: 200, body: { code: '200', data: structuredClone(data) }, requestId: 'synthetic-request', traceId: 'synthetic-trace' })
const reject = (code = 'A0409', http = 409) => ({ http, body: { code }, requestId: 'synthetic-request', traceId: 'synthetic-trace' })
const fresh = more => ({ customerId: 'C', warehouseId: 'W', ...more })
const evidenceFiles = []
after(() => { for (const file of evidenceFiles) { assert.ok(file.startsWith(join(tmpdir(), 'dispatch-repair-proof-'))); unlinkSync(file) } })
function producerReport() {
const requests = []
const event = (method, path, body, result, actor = 'PLATFORM') => requests.push({ method, path, body, result, actor,
status: 'RESPONDED', http: 200, code: '200', requestId: `actual-producer-${requests.length}`, traceId: `actual-trace-${requests.length}` })
function stock(no, inboundCode, pallets, relabelNo) {
event('POST', '/api/platform/v1/last-leg/warehouse-transfers?customerId=C', { operatingWarehouseId: 'W', remark: 'CURRENT new stock' }, { transferNo: no, operatingWarehouseId: 'W' })
event('POST', `/api/pda/v1/last-leg/warehouse-transfers/${no}/palletize`, {}, { transferNo: no, operatingWarehouseId: 'W', inboundCode, relabelNo,
pallets: pallets.map(([warehousePalletId, cartonCount]) => ({ warehousePalletId, palletNo: `PAL-${warehousePalletId}`, cartonCount })) })
}
function candidate(planPalletId, warehousePalletId, inboundCode, extra = {}) {
const row = { planPalletId, warehousePalletId, inboundCode, orderRefs: inboundCode, customerId: 'C', overseasWarehouseId: 'W', sourceStage: 'RECEIVED', ...extra }
event('GET', '/api/platform/v1/last-leg/dispatches/candidates', undefined, [row]); return row
}
function dispatch(no, rows, relabelNo, packages = 1) {
event('POST', '/api/platform/v1/last-leg/dispatches/pre-arrange', { planPalletIds: rows.map(x => relabelNo ? x.warehousePalletId : x.planPalletId), relabelNo },
{ dispatchNo: no, overseasWarehouseId: 'W', packageCount: packages, items: rows })
}
function trip(no) { event('POST', '/api/platform/v1/last-leg/fleet/trips', { remark: 'CURRENT new trip' }, { trip: { tripNo: no, warehouseId: 'W' } }) }
function external(no, tripNo, transferNo, inboundCode, palletId, destinationPallet) {
trip(tripNo)
const booking = { bookingNo: no, tripNo, customerId: 'C', cargo: { priceBasis: 'PALLET', palletSpaces: 1, unitPrice: 2, currency: 'USD' }, agreedAmount: 2 }
event('POST', `/api/platform/v1/last-leg/fleet/trips/${tripNo}/bookings`, {}, { booking })
event('POST', `/api/platform/v1/last-leg/fleet/trips/${tripNo}/bookings/${no}/incoming`, {}, { booking: { ...booking, incomingNo: transferNo } })
event('POST', `/api/pda/v1/last-leg/warehouse-transfers/${transferNo}/palletize`, {}, { transferNo, inboundCode, operatingWarehouseId: 'W', pallets: [{ warehousePalletId: palletId, palletNo: `PAL-${palletId}`, cartonCount: 2 }] })
event('POST', `/api/platform/v1/last-leg/fleet/trips/${tripNo}/bookings/${no}/receipt-confirmation`, {}, { booking: { ...booking, status: 'RECEIVED', incomingNo: transferNo,
receipt: { source: { receiptHash: 'OLD', inboundCode, destinationKey: 'DST', pallets: [{ warehousePalletId: destinationPallet, packages: 2 }] } } } })
}
stock('TC', 'IN-C', [['101', 1]])
dispatch('DP', [candidate('11', '101', 'IN-C')])
stock('TR', 'IN-R', [['201', 2], ['202', 2]], 'RL')
for (const pallet of ['201', '202']) candidate(null, pallet, 'IN-R', { sourceStage: 'RELABEL', orderRefs: 'RL', orderNo: 'CUSTOMER-ORDER' })
for (const i of [1, 2]) {
stock(`TN${i}`, `IN-N${i}`, [[`30${i}`, 3]])
external(`BK${i}`, `T${i}`, `TE${i}`, `IN-E${i}`, `40${i}`, `30${i}`)
const row = candidate(`3${i}`, `30${i}`, i === 1 ? `IN-N${i}` : `IN-E${i}`)
dispatch(i === 1 ? 'DP-N' : 'DP-E', [row], undefined, 5)
}
external('BK', 'TR', 'TF', 'IN-F', '501', '31')
function pallet(palletId, palletCode, locationId) {
event('POST', '/api/platform/v1/overseas-warehouse-resources/W/pallets', { palletCode }, palletId)
event('GET', `/api/platform/v1/overseas-warehouse-resources/W/pallets/${palletId}`, undefined, { id: palletId, warehouseId: 'W', palletCode, locationId })
}
pallet('31', 'CURRENT-NEW-GEOMETRY', '113')
pallet('601', 'CURRENT-SOURCE', '114'); pallet('111', 'CURRENT-TARGET', '112')
event('GET', '/api/platform/v1/overseas-warehouse-resources/W/locations', undefined, { records: [{ id: '112', locationCode: 'LOCATION' }] })
event('GET', '/api/merchant/v1/iam/tenant/profile', undefined, { id: 'C' }, 'MERCHANT')
event('POST', '/api/merchant/v1/last-leg/return-orders', { remark: 'CURRENT new return' }, { order: { returnNo: 'RT', overseasWarehouseId: 'W' } }, 'MERCHANT')
event('GET', '/api/platform/v1/last-leg/return-inventory/cartons/BOX', undefined, { cartonMark: 'BOX', sourceReturnNo: 'RT', customerId: 'C', overseasWarehouseId: 'W', status: 'AVAILABLE', items: [{ skuCode: 'SKU-A', quantity: 3 }, { skuCode: 'SKU-B', quantity: 2 }] })
event('POST', '/api/merchant/v1/last-leg/relabel-applications', { operationWarehouseId: 'W' }, { application: { relabelNo: 'RL-N', customerId: 'C', overseasWarehouseId: 'W' } }, 'MERCHANT')
dispatch('NDP', [candidate(null, '601', null, { sourceStage: 'RELABEL', orderRefs: 'RL-N', returnCartonSource: true })], 'RL-N', 1)
event('POST', '/api/platform/v1/last-leg/dispatches/NDP/transfer-delivery', {}, { outboundNo: 'O', deliveries: [{ deliveryNo: 'D' }] })
event('GET', '/api/platform/v1/last-leg/delivery-orders/D/return-inbound-options?customerId=C', undefined, [{ customerId: 'C', lastMileOrderId: '91', deliveryNo: 'D', outboundNo: 'O', returnSources: [{ returnCartonId: '81', cartonMark: 'BOX', inventoryPositionId: null }] }])
return { environment: 'TEST', marker: 'CURRENT', sourceCommit: commit, requests }
}
function writeProducer(ctx, report = producerReport()) {
const bytes = Buffer.from(JSON.stringify(report)), path = join(tmpdir(), `dispatch-repair-proof-${randomUUID()}.json`)
writeFileSync(path, bytes); evidenceFiles.push(path); ctx.producerEvidence = { path, sha256: createHash('sha256').update(bytes).digest('hex') }
}
function context(handler = () => assert.fail('No request expected')) {
const ctx = { marker: 'CURRENT', environment: 'TEST', release: { lastlegHealthy: true, adminHealthy: true, schemaReady: true, lastlegCommit: commit },
createdResources: {}, calls: [], checkpoints: [],
async checkpoint() { this.checkpoints.push(structuredClone(this.createdResources.dispatchRepairAcceptance)) },
async request(method, path, body) { this.calls.push({ method, path, body: structuredClone(body) }); return handler(method, path, body) } }
writeProducer(ctx); return ctx
}
const execute = (ctx, fixtures) => verifyDispatchRepair(ctx, fixtures, { execute: true })
test('import/plan is zero-network and missing current fixtures never become a pass', async () => {
const ctx = context(); assert.equal((await verifyDispatchRepair(ctx, {})).status, 'PLAN_ONLY'); assert.equal(ctx.calls.length, 0)
const result = await execute(ctx, {})
assert.equal(result.status, 'PARTIAL_NOT_ALL_VERIFIED')
assert.equal(Object.values(result.cases).every(row => row.status === 'NOT_RUN'), true)
assert.equal(result.sourceEventsVerified, false)
})
for (const field of ['lastlegHealthy', 'adminHealthy', 'schemaReady']) test(`unready ${field} blocks before any HTTP`, async () => {
const ctx = context(); ctx.release[field] = false
await assert.rejects(execute(ctx, {}), /healthy TEST releases/); assert.equal(ctx.calls.length, 0)
})
test('production target and an old run fixture cannot borrow TEST authorization', async () => {
const ctx = context(); ctx.environment = 'PRODUCTION'; await assert.rejects(execute(ctx, {}), /TEST releases/)
const owned = context(); await assert.rejects(execute(owned, { departedGate: fresh({ outboundNo: 'OLD-O', deliveryNo: 'OLD-D' }) }), /Unowned outbound/)
assert.equal(owned.calls.length, 0)
})
test('self-declared current flags cannot authorize an old dispatch absent from producer receipts', async () => {
const ctx = context()
await assert.rejects(execute(ctx, { cancellation: fresh({ dispatchNo: 'OLD-DP', allowDispatchCancellation: true,
marker: 'CURRENT', createdInThisRun: true, producerRequestId: 'claimed-current-request', producerTraceId: 'claimed-current-trace',
transferBody: {}, rearrangeBody: { planPalletIds: ['11'] } }) }), /Unowned dispatch/)
assert.equal(ctx.calls.length, 0)
})
test('a later foreign shipment blocks all cases before the first HTTP request', async () => {
const ctx = context()
await assert.rejects(execute(ctx, { cancellation: fresh({ dispatchNo: 'DP', allowDispatchCancellation: true,
transferBody: {}, rearrangeBody: { planPalletIds: ['11'] } }), departedGate: fresh({ outboundNo: 'OLD-O', deliveryNo: 'D' }) }), /Unowned outbound/)
assert.equal(ctx.calls.length, 0)
})
test('changed producer hash or response warehouse binding is rejected with zero HTTP', async () => {
const ctx = context(); ctx.producerEvidence.sha256 = '0'.repeat(64)
await assert.rejects(execute(ctx, {}), /hash mismatch/); assert.equal(ctx.calls.length, 0)
const scoped = context(), report = producerReport()
report.requests.find(row => row.method === 'POST' && row.path.endsWith('/pre-arrange')).result.overseasWarehouseId = 'OTHER'
writeProducer(scoped, report)
await assert.rejects(execute(scoped, {}), /Dispatch birth response/); assert.equal(scoped.calls.length, 0)
})
test('failed pre-send checkpoint leaves the command unsent', async () => {
const ctx = context(); ctx.checkpoint = async () => { throw Error('disk full') }
await assert.rejects(execute(ctx, { departedGate: fresh({ outboundNo: 'O', deliveryNo: 'D' }) }), /disk full/)
assert.equal(ctx.calls.length, 0)
})
test('new unpicked dispatch cancels outbound, retains cancelled history, re-arranges released pallets and replays old transfer', async () => {
let cancelled = false, dispatchCancelled = false, transfers = 0
const ctx = context((method, path, body) => {
if (path.endsWith('/transfer-delivery')) return ok({ outboundNo: 'O', deliveries: [{ deliveryNo: 'D' }], replayed: transfers++ > 0 })
if (path.includes('/delivery-orders/') && path.includes('/status')) { assert.ok(['DELIVERING', 'REJECTED', 'CANCELLED'].includes(body.status)); assert.equal(body.expectedVersion, 0); return reject() }
if (path.includes('/delivery-orders/')) return ok({ order: { deliveryNo: 'D', outboundNo: 'O', status: cancelled ? 'CANCELLED' : 'WAIT_DELIVERY', version: 0, packageCount: 1 } })
if (path.endsWith('/outbound-orders/O/cancel')) { cancelled = true; return ok(null) }
if (path.endsWith('/outbound-orders/O')) return ok({ outbound: { status: cancelled ? 'CANCELLED' : 'WAIT_OUTBOUND' } })
if (method === 'DELETE') { assert.equal(path, '/api/platform/v1/last-leg/dispatches/DP'); assert.equal(cancelled, true); dispatchCancelled = true; return ok(null) }
if (path.endsWith('/dispatches/DP')) return ok({ status: dispatchCancelled ? 'CANCELLED' : 'PENDING_DEPARTURE', createdAt: '2026-10-18T16:00:00', actions: { canTransfer: true } })
if (path.includes('/dispatches/candidates?')) return ok([{ planPalletId: '11' }])
if (path.endsWith('/pre-arrange')) { assert.deepEqual(body.planPalletIds, ['11']); assert.equal(dispatchCancelled, true); return ok({ dispatchNo: 'DP-NEW', status: 'PENDING_DEPARTURE', items: [{ planPalletId: '11' }] }) }
assert.fail(path)
})
const result = await execute(ctx, { cancellation: fresh({ allowDispatchCancellation: true, dispatchNo: 'DP', transferBody: { fees: [] }, rearrangeBody: { planPalletIds: ['11'] }, candidateQuery: { sourceStage: 'RECEIVED' } }) })
assert.equal(result.cases.cancellation.status, 'PASS')
assert.equal(ctx.calls.filter(row => row.method === 'DELETE').length, 1)
assert.equal(ctx.calls.some(row => row.method === 'DELETE' && row.path.includes('/items/')), false)
})
test('domain rejection cannot be faked by a missing permission; actual shipment cancellation leaves facts unchanged', async () => {
for (const forbidden of [false, true]) {
const order = { status: 'WAIT_DELIVERY', version: 4, packageCount: 1, outboundNo: 'O' }
const ctx = context((method, path) => {
if (method === 'GET') return ok(path.includes('/outbound-orders/') ? { outbound: { status: 'OUTBOUNDED' } } : { order })
return forbidden ? reject('A0403', 403) : reject()
})
const run = execute(ctx, { departedGate: fresh({ outboundNo: 'O', deliveryNo: 'D' }) })
if (forbidden) await assert.rejects(run, /Unexpected result/)
else assert.equal((await run).cases.departedGate.status, 'PASS')
}
})
for (const broken of [false, true]) test(`two-pallet relabel rejects partial selection with unchanged candidates then accepts all; broken=${broken}`, async () => {
const ids = ['201', '202']
const ctx = context((method, path, body) => {
if (path.includes('/relabel-applications/')) return ok({ application: { relabelNo: 'RL', status: 'READY_FOR_OUTBOUND', fulfillmentStatus: 'WAIT_PRE_DISPATCH' } })
if (path.includes('/candidates?')) return ok(ids.map(warehousePalletId => ({ orderRefs: 'RL', orderNo: 'CUSTOMER-ORDER', warehousePalletId, planPalletId: null })))
assert.equal(method, 'POST'); assert.equal(body.relabelNo, 'RL')
if (body.planPalletIds.length === 1 && !broken) return reject()
return ok({ status: 'PENDING_DEPARTURE', dispatchNo: 'DP', items: body.planPalletIds.map(warehousePalletId => ({ warehousePalletId, planPalletId: null })) })
})
const run = execute(ctx, { wholeRelabel: fresh({ relabelNo: 'RL' }) })
if (broken) await assert.rejects(run, /Unexpected result/)
else assert.equal((await run).cases.wholeRelabel.status, 'PASS')
})
function mixedFixture(fault = '') {
const samples = [1, 2].map(i => ({ displayKind: i === 1 ? 'ORDINARY' : 'EXTERNAL', dispatchNo: i === 1 ? 'DP-N' : 'DP-E',
ordinaryInboundCode: `IN-N${i}`, externalInboundCode: `IN-E${i}`, bookingNo: `BK${i}`, palletId: `30${i}` }))
const ctx = context((method, path) => {
if (path.includes('/inventory/balances') && !path.includes('/positions')) return ok({ total: 4,
records: [1, 2].flatMap(i => ['N', 'E'].map(kind => ({ id: `${kind}${i}`, customerId: 'C', overseasWarehouseId: 'W', inboundCode: `IN-${kind}${i}` }))) })
if (path.includes('/positions')) {
const balance = path.match(/balances\/([NE][12])\//)[1], kind = balance[0], i = balance[1]
return ok([{ id: `POS-${balance}`, customerId: 'C', overseasWarehouseId: 'W', inboundCode: `IN-${balance}`,
palletId: `30${i}`, availablePackages: kind === 'N' ? fault === 'wrong-component' ? 4 : 3 : 2, pickedPackages: 0 }])
}
const sample = samples.find(row => path.includes(row.dispatchNo)), i = sample.dispatchNo === 'DP-N' ? 1 : 2
if (path.endsWith('/external-freight')) return ok({ requiresDeliveryFee: true, snapshotHash: `hash-${i}`, quotes: [{ bookingNo: `BK${i}`, inboundCode: `IN-E${i}`,
quantity: fault === 'wrong-quantity' ? 2 : 1, amount: fault === 'wrong-amount' ? 3 : 2, unitPrice: 2, currency: 'USD', destinationKey: 'DST' }] })
return ok({ overseasWarehouseId: 'W', items: [{ warehousePalletId: `30${i}`, palletNo: `PAL-30${i}`,
inboundCode: i === 1 && fault !== 'wrong-display' ? 'IN-N1' : `IN-E${i}` }] })
})
if (fault === 'duplicate-sample') samples[1] = { ...samples[0], displayKind: 'EXTERNAL' }
return { ctx, fixture: fresh({ samples }) }
}
test('independent mixed display permutations prove per-source packages and commercial quantity/amount', async () => {
const f = mixedFixture(), result = await execute(f.ctx, { mixedSources: f.fixture })
assert.equal(result.cases.mixedSources.status, 'PASS')
assert.deepEqual(result.cases.mixedSources.evidence.map(x => x.expectedSources.map(y => y.packages)), [[3, 2], [3, 2]])
})
for (const fault of ['duplicate-sample', 'wrong-display', 'wrong-component', 'wrong-quantity', 'wrong-amount']) test(`mixed source ${fault} cannot pass`, async () => {
const f = mixedFixture(fault)
await assert.rejects(execute(f.ctx, { mixedSources: f.fixture }), /independent|Displayed source|Physical pallet|external quote/)
assert.ok(f.ctx.calls.every(row => row.method === 'GET'))
if (fault === 'duplicate-sample') assert.equal(f.ctx.calls.length, 0)
})
test('changed receiving geometry requires fresh measurements and new key; exact confirmation replay remains identical', async () => {
const bodies = []
const receipt = { source: { receiptHash: 'NEW', pallets: [{ warehousePalletId: '31', packages: 2 }] }, pallets: [{ warehousePalletId: '31', palletSpaces: 1, weightKg: 7, volumeCbm: 0.5 }] }
const ctx = context((method, path, body) => {
if (method === 'GET' && path.endsWith('/bookings')) return ok({ records: [{ bookingNo: 'BK', customerId: 'C', status: 'RECEIVED', dispatchNo: null, receipt: { source: { receiptHash: 'OLD' } } }] })
if (method === 'GET') return ok({ tripRecordVersion: 5, recordVersion: 6, incoming: { receiptHash: 'NEW', pallets: [{ warehousePalletId: '31', weightKg: null, volumeCbm: null }] } })
bodies.push(structuredClone(body)); assert.equal(body.receiptHash, 'NEW'); assert.equal(body.tripRecordVersion, 5); assert.equal(body.recordVersion, 6)
if (bodies.length === 1) { assert.equal(body.pallets[0].weightKg, undefined); return reject() }
assert.deepEqual(body.pallets, receipt.pallets)
return ok({ booking: { receipt }, replayed: bodies.length === 3 })
})
const result = await execute(ctx, { receiptRefresh: fresh({ tripNo: 'TR', bookingNo: 'BK', oldReceiptHash: 'OLD', unitPrice: 2,
measurements: [{ warehousePalletId: '31', weightKg: 7, volumeCbm: 0.5 }] }) })
assert.equal(result.cases.receiptRefresh.status, 'PASS')
assert.notEqual(bodies[0].idempotencyKey, bodies[1].idempotencyKey); assert.deepEqual(bodies[1], bodies[2])
})
function nativeFixture(fault = '') {
let marked = false, completeCount = 0
const quantity = sku => sku === 'SKU-A' ? 3 : 2
const page = (u, rows) => ok({ total: rows.length, records: rows.slice(Number(u.searchParams.get('page') || 1) - 1, Number(u.searchParams.get('page') || 1)) })
const ctx = context((method, path, body) => {
const u = new URL(path, 'https://test.invalid'), sku = u.searchParams.get('skuCode'), Q = quantity(sku)
if (u.pathname === '/api/platform/v1/last-leg/return-inventory') {
let total = completeCount ? Q : 0
if (fault === 'missing-sku' && sku === 'SKU-B') total = 0
if (fault === 'replay-adds-stock' && completeCount >= 2) total = Q * 2
return page(u, [{ customerId: 'OTHER', overseasWarehouseId: 'W', skuCode: sku, totalQuantity: 999, availableQuantity: 999, cartonQuantity: 9 },
{ customerId: 'C', overseasWarehouseId: 'W', skuCode: `${sku}-FUZZY`, totalQuantity: 999, availableQuantity: 999, cartonQuantity: 9 },
{ customerId: 'C', overseasWarehouseId: 'W', skuCode: sku, totalQuantity: total,
availableQuantity: fault === 'availability-not-restored' ? 0 : total,
cartonQuantity: completeCount && fault !== 'cartons-not-restored' ? 1 : 0,
updatedAt: fault === 'replay-updates-time' && completeCount >= 2 ? '2026-10-18T16:02:00' : completeCount ? '2026-10-18T16:01:00' : '2026-10-18T16:00:00' }])
}
if (u.pathname.endsWith('/return-inventory/movements')) {
const base = { customerId: 'C', overseasWarehouseId: 'W', skuCode: sku, occurredAt: '2026-10-18T16:00:00' }
const incoming = { ...base, movementType: 'EXCEPTION_RETURN_IN', referenceNo: 'NATIVE-RECEIPT', totalDelta: Q, availableDelta: Q, occurredAt: '2026-10-18T16:01:00' }
const rows = [{ ...base, skuCode: `${sku}-FUZZY`, movementType: 'OUTBOUND', referenceNo: 'NDP', totalDelta: -999, availableDelta: -999 },
{ ...base, movementType: 'OUTBOUND', referenceNo: fault === 'wrong-outbound-reference' ? 'O' : 'NDP', totalDelta: -Q, availableDelta: -Q }]
if (completeCount && !(fault === 'missing-movement' && sku === 'SKU-B')) rows.push(incoming)
if (fault === 'duplicate-incoming' && completeCount) rows.push(incoming)
if (fault === 'replay-adds-movement' && completeCount >= 2) rows.push({ ...incoming, occurredAt: '2026-10-18T16:02:00' })
return page(u, rows)
}
if (path.includes('/return-inventory/cartons/')) return ok({ cartonMark: 'BOX', status: completeCount ? 'AVAILABLE' : 'OUTBOUNDED',
customerId: 'C', overseasWarehouseId: 'W', palletCode: fault === 'wrong-target' ? 'WRONG-TARGET' : 'CURRENT-TARGET', locationCode: 'LOCATION', putawayAt: completeCount ? '2026-10-18T16:01:00' : null,
items: [{ skuCode: 'SKU-A', quantity: 3, availableQuantity: completeCount ? 3 : 0 }, { skuCode: 'SKU-B', quantity: 2, availableQuantity: completeCount ? 2 : 0 }] })
if (path.includes('/return-inbound-options')) return ok([{ lastMileOrderId: fault === 'wrong-master' ? '92' : '91', customerId: 'C', inboundOrderId: null, inboundCode: null, deliveryNo: 'D', outboundNo: 'O',
returnSources: [{ returnCartonId: '81', inventoryPositionId: null, outboundPalletItemId: '71', cartonMark: 'BOX', maxReturnPackages: 1 }] }])
if (path.includes('/mark-return')) {
assert.equal(body.lastMileOrderId, '91'); assert.equal(Object.hasOwn(body, 'inboundOrderId'), false)
assert.deepEqual(body.items, [{ outboundPalletItemId: '71', returnCartonId: '81', packageCount: 1 }])
const replayed = marked; marked = true; return ok({ exceptionNo: 'EX', version: 0, replayed })
}
if (path.includes('/start-processing')) return ok({ version: 1 })
if (path.includes('/complete')) { assert.equal(body.receipts[0].inventoryPositionId, null); assert.equal(body.receipts[0].returnCartonId, '81'); return ok({ status: 'COMPLETED', restoredPackages: 1, replayed: completeCount++ > 0 }) }
if (method === 'GET' && path.includes('/exception-orders/')) return ok({ returnReceipts: [{ receiptNo: 'NATIVE-RECEIPT', receivedPackages: 1, receivedAt: '2026-10-18T16:01:00' }] })
if (method === 'GET' && path.includes('/delivery-orders/')) return ok({ order: { status: 'RETURNED', outboundNo: 'O', packageCount: 1, version: 2 } })
assert.fail(path)
})
ctx.requestMultipart = async (method, path, file) => { assert.match(new TextDecoder().decode(file.content), /SYNTHETIC TEST/); return ok({ fileId: '101' }) }
return { ctx, fixture: fresh({ cartonMark: 'BOX', returnCartonId: '81', lastMileOrderId: '91', deliveryNo: 'D', outboundNo: 'O',
target: { targetPalletId: '111', targetPalletNo: 'CURRENT-TARGET', targetLocationId: '112', targetLocationCode: 'LOCATION' } }) }
}
test('native recovery reads exact paged SKU stock between first completion and replay', async () => {
const f = nativeFixture(), result = await execute(f.ctx, { nativeCartonReturn: f.fixture })
const evidence = result.cases.nativeCartonReturn.evidence
assert.equal(result.cases.nativeCartonReturn.status, 'PASS')
assert.deepEqual(evidence.S.stock.map(x => x.total), [0, 0]); assert.deepEqual(evidence.R.stock.map(x => x.total), [3, 2]); assert.deepEqual(evidence.Rprime, evidence.R)
assert.deepEqual(evidence.R.stock.map(x => x.availableView), [3, 2]); assert.deepEqual(evidence.R.stock.map(x => x.cartons), [1, 1])
const completes = f.ctx.calls.map((row, i) => row.path.includes('/complete') ? i : -1).filter(i => i >= 0)
assert.equal(completes.length, 2)
assert.ok(f.ctx.calls.slice(completes[0] + 1, completes[1]).some(row => row.path.includes('/return-inventory?')))
assert.ok(f.ctx.calls.some(row => row.path.includes('page=3')))
})
for (const fault of ['wrong-master', 'missing-sku', 'availability-not-restored', 'cartons-not-restored', 'missing-movement', 'duplicate-incoming', 'replay-adds-stock', 'replay-adds-movement', 'replay-updates-time', 'wrong-target', 'wrong-outbound-reference']) test(`native recovery ${fault} cannot pass`, async () => {
const f = nativeFixture(fault)
await assert.rejects(execute(f.ctx, { nativeCartonReturn: f.fixture }), /Actual native|Every original|Native replay|exact validated|Original single-carton/)
if (fault === 'wrong-master') assert.ok(f.ctx.calls.every(row => row.method === 'GET'))
})
test('an old target pallet cannot be authorized by a valid native carton fixture', async () => {
const f = nativeFixture(); f.fixture.target.targetPalletId = 'OLD-PALLET'
await assert.rejects(execute(f.ctx, { nativeCartonReturn: f.fixture }), /Unowned pallet/)
assert.equal(f.ctx.calls.length, 0)
})
test('read-only list permission allows detail but rejects cancellation with unchanged outbound', async () => {
const outbound = { status: 'WAIT_OUTBOUND', version: 0, packageCount: 1 }
const ctx = context(() => ok({ outbound }))
ctx.requestReadonly = async (method) => method === 'GET' ? ok({ outbound }) : reject('A0403', 403)
assert.equal((await execute(ctx, { permissions: fresh({ outboundNo: 'O' }) })).cases.permissions.status, 'PASS')
})
test('unknown command response is checkpointed and never automatically retried', async () => {
const ctx = context((method) => method === 'GET' ? ok({ outbound: { status: 'OUTBOUNDED' } }) : { http: 0, body: null })
// The uncorrelated read itself stops before any command or automatic recovery.
ctx.request = async function (method, path) { this.calls.push({ method, path }); return { http: 0, body: null } }
await assert.rejects(execute(ctx, { departedGate: fresh({ outboundNo: 'O', deliveryNo: 'D' }) }), /Unknown transport/)
assert.equal(ctx.calls.length, 1); assert.equal(ctx.checkpoints.at(-1).requests.at(-1).status, 'UNKNOWN_RESULT')
})
@@ -0,0 +1,434 @@
import { randomUUID, createHash } from 'node:crypto'
import { readFile } from 'node:fs/promises'
const BASE = '/api/platform/v1/last-leg'
const id = value => value == null ? '' : String(value)
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b)
const must = (value, reason) => { if (!value) throw Error(reason) }
const success = r => r?.http === 200 && String(r?.body?.code) === '200'
const rejected = r => [400, 409, 422].includes(r?.http)
|| r?.http === 200 && ['A0400', 'A0409', 'A0422'].includes(String(r?.body?.code))
const key = () => `dispatch-repair-${randomUUID()}`
const scope = (path, customerId) => `${path}?${new URLSearchParams({ customerId })}`
const cases = ['cancellation', 'departedGate', 'wholeRelabel', 'mixedSources', 'receiptRefresh', 'nativeCartonReturn', 'permissions']
/** The allowlist is derived from successful producer API receipts, never from fixture ownership flags. */
async function loadProducerResources(context) {
must(context.producerEvidence?.path && /^[a-f0-9]{64}$/.test(context.producerEvidence?.sha256 || ''), 'Hashed current-run producer evidence required')
const bytes = await readFile(context.producerEvidence.path)
must(createHash('sha256').update(bytes).digest('hex') === context.producerEvidence.sha256, 'Producer evidence hash mismatch')
const report = JSON.parse(bytes.toString('utf8'))
must(report.environment === 'TEST' && report.marker === context.marker && report.sourceCommit === context.release.lastlegCommit
&& Array.isArray(report.requests), 'Producer report run/environment/release mismatch')
const own = Object.fromEntries(['transfer', 'inbound', 'candidate', 'dispatch', 'outbound', 'delivery', 'relabel', 'trip', 'booking', 'return', 'carton', 'pallet'].map(k => [k, new Map()]))
const actors = new Map()
function add(kind, key, customerId, warehouseId, event, extra = {}) {
must(key && warehouseId, `Producer ${kind} response lacks identity/warehouse`)
const previous = own[kind].get(id(key))
if (previous) must(id(previous.customerId) === id(customerId) && id(previous.warehouseId) === id(warehouseId), 'Producer resource scope drifted')
own[kind].set(id(key), { ...previous, ...extra, key: id(key), customerId: id(customerId), warehouseId: id(warehouseId),
requestId: event.requestId, traceId: event.traceId })
}
for (const e of report.requests) {
if (e.status !== 'RESPONDED' || e.http !== 200 || String(e.code) !== '200' || !e.requestId || !e.traceId || !e.result) continue
const u = new URL(e.path, 'https://producer.invalid'), path = u.pathname, data = e.result
if (e.method === 'GET' && path === '/api/merchant/v1/iam/tenant/profile' && data.id) actors.set(e.actor, id(data.id))
if (e.method === 'POST' && path === `${BASE}/warehouse-transfers` && String(e.body?.remark).includes(context.marker)) {
must(data.operatingWarehouseId === e.body.operatingWarehouseId && u.searchParams.get('customerId'), 'Transfer birth scope mismatch')
add('transfer', data.transferNo, u.searchParams.get('customerId'), data.operatingWarehouseId, e)
}
if (e.method === 'POST' && path === `${BASE}/fleet/trips` && String(e.body?.remark).includes(context.marker))
add('trip', data.trip?.tripNo, '', data.trip?.warehouseId, e)
let match = path.match(/\/fleet\/trips\/([^/]+)\/bookings(?:\/([^/]+)(?:\/incoming|\/confirm|\/receipt-confirmation|\/dispatch)?)?$/)
if (e.method === 'POST' && match && own.trip.has(decodeURIComponent(match[1])) && data.booking) {
const trip = own.trip.get(decodeURIComponent(match[1])), b = data.booking
if (!match[2] || own.booking.has(b.bookingNo)) {
add('booking', b.bookingNo, b.customerId, trip.warehouseId, e, { tripNo: b.tripNo, booking: data.booking })
if (b.incomingNo) add('transfer', b.incomingNo, b.customerId, trip.warehouseId, e, { externalBookingNo: b.bookingNo })
}
}
match = path.match(/\/warehouse-transfers\/([^/]+)(?:\/palletize|\/confirm-measurement|\/review)?$/)
const transfer = match && own.transfer.get(decodeURIComponent(match[1]))
if (transfer && data.transferNo === transfer.key && id(data.operatingWarehouseId) === transfer.warehouseId && data.inboundCode) {
const pallets = data.pallets || [], received = pallets.reduce((n, row) => n + Number(row.cartonCount || 0), 0)
add('inbound', data.inboundCode, transfer.customerId, transfer.warehouseId, e, { receivedPackages: received,
kind: transfer.externalBookingNo ? 'EXTERNAL' : 'ORDINARY', externalBookingNo: transfer.externalBookingNo })
for (const row of pallets) if (row.warehousePalletId) add('pallet', row.warehousePalletId, transfer.customerId, transfer.warehouseId, e, { palletCode: row.palletNo })
if (data.relabelNo) add('relabel', data.relabelNo, transfer.customerId, transfer.warehouseId, e)
}
if (e.method === 'POST' && path === '/api/merchant/v1/last-leg/relabel-applications' && actors.has(e.actor)) {
const a = data.application
must(a && id(a.customerId) === actors.get(e.actor) && id(a.overseasWarehouseId) === id(e.body?.operationWarehouseId), 'Relabel producer scope mismatch')
add('relabel', a.relabelNo, a.customerId, a.overseasWarehouseId, e)
}
if (e.method === 'POST' && path === '/api/merchant/v1/last-leg/return-orders' && actors.has(e.actor)
&& String(e.body?.remark).includes(context.marker)) add('return', data.order?.returnNo, actors.get(e.actor), data.order?.overseasWarehouseId, e)
match = path.match(/\/overseas-warehouse-resources\/([^/]+)\/pallets(?:\/([^/]+))?$/)
if (match && e.method === 'POST' && !match[2] && String(e.body?.palletCode).includes(context.marker))
add('pallet', typeof data === 'object' ? data.id : data, '', decodeURIComponent(match[1]), e, { palletCode: e.body.palletCode })
if (match && e.method === 'GET' && match[2] && own.pallet.has(decodeURIComponent(match[2]))) {
const old = own.pallet.get(decodeURIComponent(match[2]))
must(id(data.warehouseId) === old.warehouseId && data.palletCode === old.palletCode, 'New pallet readback drifted')
add('pallet', old.key, old.customerId, old.warehouseId, e, { locationId: id(data.locationId), palletCode: data.palletCode })
}
match = path.match(/\/overseas-warehouse-resources\/([^/]+)\/locations$/)
if (e.method === 'GET' && match) for (const pallet of own.pallet.values()) {
if (pallet.warehouseId !== decodeURIComponent(match[1]) || !pallet.locationId) continue
const location = (Array.isArray(data) ? data : data.records || []).find(row => id(row.id) === pallet.locationId)
if (location?.locationCode) pallet.locationCode = location.locationCode
}
match = path.match(/\/return-inventory\/cartons\/([^/]+)$/)
const returned = match && own.return.get(data.sourceReturnNo)
if (e.method === 'GET' && returned && data.cartonMark === decodeURIComponent(match[1])) {
must(id(data.customerId) === returned.customerId && id(data.overseasWarehouseId) === returned.warehouseId, 'New return carton scope mismatch')
add('carton', data.cartonMark, returned.customerId, returned.warehouseId, e, { sourceReturnNo: data.sourceReturnNo,
...(data.status !== 'OUTBOUNDED' ? { originalSkuItems: data.items } : {}) })
}
if (e.method === 'GET' && path === `${BASE}/dispatches/candidates` && Array.isArray(data)) {
for (const row of data) {
const parent = row.sourceStage === 'RELABEL' ? own.relabel.get(row.orderRefs) : own.inbound.get(row.inboundCode)
if (!parent || id(row.customerId) !== parent.customerId || id(row.overseasWarehouseId) !== parent.warehouseId) continue
add('candidate', row.sourceStage === 'RELABEL' ? `RL:${row.warehousePalletId}` : row.planPalletId, parent.customerId, parent.warehouseId, e, { candidate: row })
}
}
if (e.method === 'POST' && path === `${BASE}/dispatches/pre-arrange`) {
const sources = (e.body?.planPalletIds || []).map(value => own.candidate.get(e.body.relabelNo ? `RL:${value}` : id(value)))
must(sources.length && sources.every(Boolean) && sources.every(row => row.customerId === sources[0].customerId && row.warehouseId === sources[0].warehouseId), 'Dispatch creation lacks owned source receipts')
must(id(data.overseasWarehouseId) === sources[0].warehouseId && same((data.items || []).map(row => id(row.warehousePalletId)).sort(), sources.map(row => id(row.candidate.warehousePalletId)).sort()), 'Dispatch birth response differs from producer selection')
add('dispatch', data.dispatchNo, sources[0].customerId, sources[0].warehouseId, e, { dispatch: data, arrangeBody: e.body })
}
match = path.match(/\/dispatches\/([^/]+)\/transfer-delivery$/)
const dispatched = match && own.dispatch.get(decodeURIComponent(match[1]))
if (e.method === 'POST' && dispatched && data.outboundNo && !data.replayed) {
add('outbound', data.outboundNo, dispatched.customerId, dispatched.warehouseId, e, { dispatchNo: dispatched.key })
for (const row of data.deliveries || []) add('delivery', row.deliveryNo, dispatched.customerId, dispatched.warehouseId, e, { outboundNo: data.outboundNo, dispatchNo: dispatched.key })
}
match = path.match(/\/delivery-orders\/([^/]+)\/return-inbound-options$/)
if (e.method === 'GET' && match && own.delivery.has(decodeURIComponent(match[1])) && Array.isArray(data)) {
for (const relation of data) for (const source of relation.returnSources || []) {
const carton = own.carton.get(source.cartonMark)
if (carton && source.returnCartonId && source.inventoryPositionId == null
&& id(relation.customerId) === carton.customerId && relation.deliveryNo === decodeURIComponent(match[1])
&& relation.outboundNo === own.delivery.get(decodeURIComponent(match[1])).outboundNo)
add('carton', carton.key, carton.customerId, carton.warehouseId, e, { returnCartonId: id(source.returnCartonId), lastMileOrderId: id(relation.lastMileOrderId), deliveryNo: relation.deliveryNo })
}
}
}
return own
}
function requireOwned(own, kind, key, fixture) {
const row = own[kind].get(id(key))
must(row && row.warehouseId === id(fixture.warehouseId) && (!row.customerId || row.customerId === id(fixture.customerId)), `Unowned ${kind} ${id(key)}; producer receipt identity/customer/warehouse mismatch`)
return row
}
function validateAllResources(own, fixtures) {
for (const [name, f] of Object.entries(fixtures || {})) {
must(f.customerId && f.warehouseId, 'Fixture customer and warehouse required')
if (name === 'cancellation') {
const d = requireOwned(own, 'dispatch', f.dispatchNo, f)
must(same(d.arrangeBody.planPalletIds.map(id).sort(), f.rearrangeBody?.planPalletIds?.map(id).sort()), 'Re-arrangement must reuse only the exact producer sources')
}
if (['departedGate', 'permissions', 'nativeCartonReturn'].includes(name)) {
requireOwned(own, 'outbound', f.outboundNo, f)
if (f.deliveryNo) {
const d = requireOwned(own, 'delivery', f.deliveryNo, f)
must(d.outboundNo === f.outboundNo, 'Delivery/outbound producer relation mismatch')
}
}
if (name === 'wholeRelabel') requireOwned(own, 'relabel', f.relabelNo, f)
if (name === 'receiptRefresh') {
const b = requireOwned(own, 'booking', f.bookingNo, f)
must(b.tripNo === f.tripNo, 'Booking/trip producer relation mismatch')
for (const row of f.measurements || []) requireOwned(own, 'pallet', row.warehousePalletId, f)
}
if (name === 'mixedSources') {
must(f.samples?.length === 2 && new Set(f.samples.map(x => x.dispatchNo)).size === 2
&& new Set(f.samples.map(x => id(x.palletId))).size === 2 && new Set(f.samples.map(x => x.bookingNo)).size === 2, 'Mixed-source samples must be independent dispatches, pallets and bookings')
for (const sample of f.samples) {
requireOwned(own, 'dispatch', sample.dispatchNo, f); requireOwned(own, 'pallet', sample.palletId, f)
const normal = requireOwned(own, 'inbound', sample.ordinaryInboundCode, f), external = requireOwned(own, 'inbound', sample.externalInboundCode, f)
const booking = requireOwned(own, 'booking', sample.bookingNo, f)
must(normal.kind === 'ORDINARY' && external.kind === 'EXTERNAL' && external.externalBookingNo === booking.key
&& normal.receivedPackages > 0 && external.receivedPackages > 0, 'Independent ordinary/external receipt quantities required')
}
}
if (name === 'nativeCartonReturn') {
const carton = requireOwned(own, 'carton', f.cartonMark, f), pallet = requireOwned(own, 'pallet', f.target?.targetPalletId, f)
const delivery = own.delivery.get(f.deliveryNo), dispatch = own.dispatch.get(delivery.dispatchNo)
must(carton.returnCartonId === id(f.returnCartonId) && carton.lastMileOrderId === id(f.lastMileOrderId)
&& carton.deliveryNo === f.deliveryNo && carton.originalSkuItems?.length && dispatch.dispatch.packageCount === 1,
'Native carton/master must come from the owned single-carton shipment')
must(pallet.palletCode === f.target.targetPalletNo && pallet.locationId === id(f.target.targetLocationId) && pallet.locationCode === f.target.targetLocationCode, 'Return target must match the newly created physical pallet/location')
}
}
}
/** Internal, explicit TEST-only runner. Import and plan mode never send requests. */
export async function verifyDispatchRepair(context, fixtures, { execute = false } = {}) {
if (!execute) return { status: 'PLAN_ONLY', cases, excluded: ['item DELETE negative branch', 'UI/PDA hardware', 'external document authenticity'] }
must(context.environment === 'TEST' && context.release?.lastlegHealthy && context.release?.adminHealthy
&& context.release?.schemaReady && /^[a-f0-9]{40}$/.test(context.release?.lastlegCommit || ''), 'Matching healthy TEST releases and schema readback required')
must(context.marker && typeof context.checkpoint === 'function', 'Current run marker and durable checkpoint required')
const own = await loadProducerResources(context)
validateAllResources(own, fixtures)
const proof = { marker: context.marker, release: context.release, status: 'CHECKING', requests: [], cases: {},
externalEvidence: 'Synthetic test records only; not real appointment/POD proof', sourceEventsVerified: false }
context.createdResources ??= {}
must(!context.createdResources.dispatchRepairAcceptance, 'No automatic restart of an existing acceptance run')
context.createdResources.dispatchRepairAcceptance = proof
async function call(method, path, body, { failure = false, file = null, cancel = false, actor = 'PLATFORM' } = {}) {
must(method !== 'DELETE' || cancel && /^\/api\/platform\/v1\/last-leg\/dispatches\/[^/?]+$/.test(path), 'Item deletion and arbitrary DELETE are excluded')
const entry = { method, path, actor, body: body === undefined ? undefined : structuredClone(body), status: 'SENDING' }
if (file) entry.file = { name: file.name, type: file.type, size: file.content.byteLength, sha256: createHash('sha256').update(file.content).digest('hex') }
proof.requests.push(entry); await context.checkpoint()
let response
try {
if (actor === 'READ_ONLY') must(typeof context.requestReadonly === 'function', 'Own read-only session required')
response = file ? await context.requestMultipart(method, path, file)
: await (actor === 'READ_ONLY' ? context.requestReadonly : context.request).call(context, method, path, body)
must(Number.isInteger(response?.http) && response.http >= 200 && response.http < 500
&& response.requestId && response.traceId && response.body && typeof response.body === 'object'
&& (success(response) || /^[A-Z]\d{4}$/.test(String(response.body.code))), 'Unknown transport or uncorrelated response; preserve command, do not replay')
} 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()
must(failure === 'FORBIDDEN' ? response.http === 403 || response.http === 200 && String(response.body.code) === 'A0403'
: failure ? rejected(response) : success(response), `Unexpected result: ${method} ${path}`)
return response.body.data
}
const number = value => { const n = Number(value); must(value != null && Number.isSafeInteger(n), 'Exact safe integer quantity required'); return n }
const cents = value => { const v = String(value); must(/^\d+(?:\.\d{1,2})?$/.test(v), 'Exact nonnegative money value required'); const [a, b = ''] = v.split('.'); return BigInt(a) * 100n + BigInt(b.padEnd(2, '0')) }
async function pages(path) {
const rows = [], url = new URL(path, 'https://test.invalid')
for (let page = 1; page <= 100; page++) {
url.searchParams.set('page', String(page)); url.searchParams.set('size', '200')
const data = await call('GET', url.pathname + url.search)
must(Array.isArray(data?.records) && number(data.total) >= 0, 'Complete paged API evidence required')
rows.push(...data.records)
if (rows.length === number(data.total)) return rows
must(rows.length < number(data.total) && data.records.length > 0, 'Paged evidence has inconsistent total or missing page')
}
throw Error('Paged evidence exceeded bounded limit; not verified')
}
async function nativeSnapshot(f, skuCodes) {
const stock = [], movements = []
for (const skuCode of skuCodes) {
const query = new URLSearchParams({ customerId: f.customerId, overseasWarehouseId: f.warehouseId, skuCode })
const exact = row => id(row.customerId) === id(f.customerId) && id(row.overseasWarehouseId) === id(f.warehouseId) && row.skuCode === skuCode
const balances = (await pages(`${BASE}/return-inventory?${query}`)).filter(exact)
must(balances.length <= 1, 'Duplicate exact native SKU balance')
const row = balances[0]
stock.push({ skuCode, present: Boolean(row), total: row ? number(row.totalQuantity) : 0,
availableView: row ? number(row.availableQuantity) : 0, cartons: row ? number(row.cartonQuantity) : 0,
updatedAt: row?.updatedAt ?? null })
movements.push(...(await pages(`${BASE}/return-inventory/movements?${query}`)).filter(exact).map(row => ({
customerId: id(row.customerId), warehouseId: id(row.overseasWarehouseId), skuCode: row.skuCode,
type: row.movementType, referenceNo: row.referenceNo, totalDelta: number(row.totalDelta), availableDelta: number(row.availableDelta), occurredAt: row.occurredAt })))
}
return { stock: stock.sort((a, b) => a.skuCode.localeCompare(b.skuCode)), movements: movements.sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b))) }
}
const shipment = value => ({ status: value?.status, version: value?.version, outboundNo: value?.outboundNo,
packageCount: value?.packageCount, signedAt: value?.signedAt, signedPackages: value?.signedPackages })
const dispatch = value => ({ status: value?.status, packageCount: value?.packageCount, items: value?.items })
async function run(name, action) {
const fixture = fixtures?.[name]
if (!fixture) { proof.cases[name] = { status: 'NOT_RUN', reason: 'Current-run producer fixture missing' }; return }
proof.cases[name] = { status: 'CHECKING', producerEvidenceSha256: context.producerEvidence.sha256 }
try { proof.cases[name].evidence = await action(fixture); proof.cases[name].status = 'PASS' }
catch (error) { Object.assign(proof.cases[name], { status: 'FAILED', reason: error.message }); throw error }
finally { await context.checkpoint() }
}
try {
await run('cancellation', async f => {
must(f.allowDispatchCancellation === true && f.dispatchNo && f.transferBody && f.rearrangeBody, 'Owned cancellation fixture and explicit business cancel scope required')
const path = `${BASE}/dispatches/${encodeURIComponent(f.dispatchNo)}`
const original = await call('GET', path)
must(original.status === 'PENDING_DEPARTURE' && original.createdAt && original.actions?.canTransfer, 'New unpicked execution required')
const transferBody = { ...f.transferBody, idempotencyKey: key() }
const transfer = await call('POST', `${path}/transfer-delivery`, transferBody)
must(transfer.outboundNo && transfer.deliveries?.length, 'New outbound and delivery required')
const dpath = scope(`${BASE}/delivery-orders/${encodeURIComponent(transfer.deliveries[0].deliveryNo)}`, f.customerId)
const before = await call('GET', dpath)
must(before.order?.status === 'WAIT_DELIVERY' && before.order.outboundNo === transfer.outboundNo, 'Delivery must belong to new unexecuted outbound')
for (const status of ['DELIVERING', 'REJECTED', 'CANCELLED']) {
await call('PUT', scope(`${BASE}/delivery-orders/${encodeURIComponent(before.order.deliveryNo)}/status`, f.customerId),
{ status, expectedVersion: before.order.version, remark: context.marker }, { failure: true })
}
must(same(shipment((await call('GET', dpath)).order), shipment(before.order)), 'Rejected status commands changed delivery')
const opath = `${BASE}/outbound-orders/${encodeURIComponent(transfer.outboundNo)}`
await call('POST', `${opath}/cancel`, { reason: context.marker })
must((await call('GET', opath)).outbound?.status === 'CANCELLED', 'Outbound cancellation did not persist')
must((await call('GET', dpath)).order?.status === 'CANCELLED', 'Linked delivery cancellation did not persist')
await call('DELETE', path, undefined, { cancel: true })
must((await call('GET', path)).status === 'CANCELLED', 'Original dispatch was not retained as cancelled')
const candidateQuery = new URLSearchParams(f.candidateQuery)
const candidates = await call('GET', `${BASE}/dispatches/candidates?${candidateQuery}`)
const expected = f.rearrangeBody.planPalletIds.map(id)
must(expected.length && expected.every(value => candidates.some(row => id(row.planPalletId) === value)), 'Cancelled source pallets were not released')
const replacement = await call('POST', `${BASE}/dispatches/pre-arrange`, f.rearrangeBody)
must(replacement.dispatchNo && replacement.dispatchNo !== f.dispatchNo && replacement.status === 'PENDING_DEPARTURE'
&& same(replacement.items.map(row => id(row.planPalletId)).sort(), [...expected].sort()), 'Released source was not re-arranged exactly once')
const replay = await call('POST', `${path}/transfer-delivery`, transferBody)
must(replay.outboundNo === transfer.outboundNo && replay.replayed, 'Old transfer replay generated another outbound')
return { originalDispatchNo: f.dispatchNo, cancelledOutboundNo: transfer.outboundNo, replacementDispatchNo: replacement.dispatchNo }
})
await run('departedGate', async f => {
const opath = `${BASE}/outbound-orders/${encodeURIComponent(f.outboundNo)}`
const dpath = scope(`${BASE}/delivery-orders/${encodeURIComponent(f.deliveryNo)}`, f.customerId)
const outbound = await call('GET', opath), before = await call('GET', dpath)
must(outbound.outbound?.status === 'OUTBOUNDED' && before.order?.outboundNo === f.outboundNo, 'Actual current-run shipment required')
await call('POST', `${opath}/cancel`, { reason: context.marker }, { failure: true })
await call('PUT', scope(`${BASE}/delivery-orders/${encodeURIComponent(f.deliveryNo)}/status`, f.customerId),
{ status: 'CANCELLED', expectedVersion: before.order.version, remark: context.marker }, { failure: true })
must(same(shipment((await call('GET', dpath)).order), shipment(before.order)), 'Departure cancellation gate changed delivery')
return { outboundNo: f.outboundNo, deliveryNo: f.deliveryNo }
})
await run('wholeRelabel', async f => {
const apath = scope(`${BASE}/relabel-applications/${encodeURIComponent(f.relabelNo)}`, f.customerId)
const cpath = `${BASE}/dispatches/candidates?${new URLSearchParams({ sourceStage: 'RELABEL', orderNo: f.relabelNo })}`
const before = await call('GET', apath), candidates = await call('GET', cpath)
const ids = candidates.filter(row => row.orderRefs === f.relabelNo).map(row => id(row.warehousePalletId)).sort()
must(ids.length === 2 && new Set(ids).size === 2, 'Exactly two real pallets from the owned relabel application required')
await call('POST', `${BASE}/dispatches/pre-arrange`, { relabelNo: f.relabelNo, planPalletIds: ids.slice(0, 1) }, { failure: true })
must(same((await call('GET', apath)).application, before.application), 'Partial relabel rejection changed the application')
must(same((await call('GET', cpath)).filter(row => row.orderRefs === f.relabelNo).map(row => id(row.warehousePalletId)).sort(), ids), 'Partial relabel rejection retained a lock or lost cargo')
const full = await call('POST', `${BASE}/dispatches/pre-arrange`, { relabelNo: f.relabelNo, planPalletIds: ids })
must(full.status === 'PENDING_DEPARTURE' && full.items?.length === 2 && same(full.items.map(row => id(row.warehousePalletId)).sort(), ids), 'Full relabel selection did not preserve both pallets')
return { relabelNo: f.relabelNo, dispatchNo: full.dispatchNo, pallets: ids }
})
await run('mixedSources', async f => {
must(same(f.samples.map(row => row.displayKind).sort(), ['EXTERNAL', 'ORDINARY']), 'Both physical display permutations required')
const evidence = []
for (const sample of f.samples) {
const normal = own.inbound.get(sample.ordinaryInboundCode), external = own.inbound.get(sample.externalInboundCode)
const booking = own.booking.get(sample.bookingNo).booking
const current = await call('GET', `${BASE}/dispatches/${encodeURIComponent(sample.dispatchNo)}`)
const displayed = current.items?.find(row => id(row.warehousePalletId) === id(sample.palletId))
const expectedDisplay = sample.displayKind === 'ORDINARY' ? normal.key : external.key
must(displayed?.inboundCode === expectedDisplay && displayed.palletNo && id(current.overseasWarehouseId) === id(f.warehouseId), 'Displayed source does not match its independently produced ordinary/external origin')
const balances = (await pages(`${BASE}/inventory/balances?${new URLSearchParams({ customerId: f.customerId, overseasWarehouseId: f.warehouseId })}`))
.filter(row => id(row.customerId) === id(f.customerId) && id(row.overseasWarehouseId) === id(f.warehouseId))
const quantities = new Map(), positions = []
for (const balance of balances) {
const rows = await call('GET', `${BASE}/inventory/balances/${encodeURIComponent(id(balance.id))}/positions?${new URLSearchParams({ customerId: f.customerId, palletNo: displayed.palletNo })}`)
must(Array.isArray(rows), 'Actual inventory positions required')
for (const row of rows.filter(row => id(row.palletId) === id(sample.palletId))) {
must(id(row.customerId) === id(f.customerId) && id(row.overseasWarehouseId) === id(f.warehouseId), 'Physical pallet source scope mismatch')
const quantity = number(row.availablePackages) + number(row.pickedPackages)
if (quantity > 0) quantities.set(row.inboundCode, (quantities.get(row.inboundCode) || 0) + quantity)
positions.push({ positionId: id(row.id), inboundCode: row.inboundCode, quantity })
}
}
must(quantities.size === 2 && quantities.get(normal.key) === normal.receivedPackages && quantities.get(external.key) === external.receivedPackages,
'Physical pallet composition differs from independent receiving facts')
const freight = await call('GET', `${BASE}/dispatches/${encodeURIComponent(sample.dispatchNo)}/external-freight`)
const quote = freight.quotes?.[0], cargo = booking.cargo, receipt = booking.receipt?.source
const quantity = cargo?.priceBasis === 'PALLET' ? number(cargo.palletSpaces) : 1
must(freight.requiresDeliveryFee === true && freight.quotes?.length === 1 && quote.bookingNo === sample.bookingNo
&& quote.inboundCode === external.key && quote.currency === cargo.currency && quote.destinationKey === receipt?.destinationKey
&& number(quote.quantity) === quantity && cents(quote.unitPrice) === cents(cargo.unitPrice)
&& cents(quote.amount) === cents(booking.agreedAmount) && cents(quote.amount) === cents(cargo.unitPrice) * BigInt(quantity)
&& freight.snapshotHash, 'Actual external quote quantity/price/amount/currency differs from producer commercial facts')
evidence.push({ dispatchNo: sample.dispatchNo, palletId: sample.palletId, displayKind: sample.displayKind,
expectedSources: [{ inboundCode: normal.key, packages: normal.receivedPackages }, { inboundCode: external.key, packages: external.receivedPackages }],
positions, quote, snapshotHash: freight.snapshotHash })
}
return evidence
})
await run('receiptRefresh', async f => {
must(f.tripNo && f.bookingNo && f.oldReceiptHash && Number(f.unitPrice) >= 0, 'Owned booking and previous actual receipt required')
const bookingsPath = `${BASE}/fleet/trips/${encodeURIComponent(f.tripNo)}/bookings`
const listing = await call('GET', bookingsPath)
const booking = listing.records?.find(row => row.bookingNo === f.bookingNo)
must(booking && id(booking.customerId) === id(f.customerId) && booking.status === 'RECEIVED' && !booking.dispatchNo
&& booking.receipt?.source?.receiptHash === f.oldReceiptHash, 'Previously accepted, currently unbound own-customer booking required')
const path = `${bookingsPath}/${encodeURIComponent(f.bookingNo)}`
const before = await call('GET', `${path}/incoming`)
must(before.incoming?.receiptHash && before.incoming.receiptHash !== f.oldReceiptHash && before.incoming.pallets?.length
&& before.incoming.pallets.some(row => row.weightKg == null || row.volumeCbm == null), 'Fresh split/merge geometry requiring measurement must be proven')
must(f.measurements?.length === before.incoming.pallets.length, 'Independent new physical pallet measurements required')
const body = { tripRecordVersion: before.tripRecordVersion, recordVersion: before.recordVersion, receiptHash: before.incoming.receiptHash,
pallets: before.incoming.pallets.map(row => ({ warehousePalletId: id(row.warehousePalletId), palletSpaces: 1 })), unitPrice: f.unitPrice, idempotencyKey: key() }
await call('POST', `${path}/receipt-confirmation`, body, { failure: true })
body.idempotencyKey = key()
body.pallets = body.pallets.map(row => ({ ...row, ...f.measurements.find(value => id(value.warehousePalletId) === row.warehousePalletId) }))
must(body.pallets.every(row => Number(row.weightKg) > 0 && Number(row.volumeCbm) > 0), 'Positive new measurements required')
const confirmed = await call('POST', `${path}/receipt-confirmation`, body)
const replay = await call('POST', `${path}/receipt-confirmation`, body)
must(confirmed.booking?.receipt?.source?.receiptHash === body.receiptHash && replay.replayed === true
&& same(replay.booking.receipt, confirmed.booking.receipt), 'Re-confirmed receipt or exact replay drifted')
return { tripNo: f.tripNo, bookingNo: f.bookingNo, receipt: confirmed.booking.receipt }
})
await run('nativeCartonReturn', async f => {
must(f.cartonMark && f.returnCartonId && f.lastMileOrderId && f.target, 'Owned native carton, actual master and actual target resources required')
const cartonPath = `${BASE}/return-inventory/cartons/${encodeURIComponent(f.cartonMark)}`
const before = await call('GET', cartonPath)
must(before.status === 'OUTBOUNDED' && id(before.customerId) === id(f.customerId) && id(before.overseasWarehouseId) === id(f.warehouseId), 'Native carton must be actually shipped for this customer and warehouse')
const relations = await call('GET', scope(`${BASE}/delivery-orders/${encodeURIComponent(f.deliveryNo)}/return-inbound-options`, f.customerId))
const relation = relations.find(row => id(row.lastMileOrderId) === id(f.lastMileOrderId) && row.deliveryNo === f.deliveryNo && row.outboundNo === f.outboundNo)
const source = relation?.returnSources?.find(row => id(row.returnCartonId) === id(f.returnCartonId) && row.inventoryPositionId == null && row.cartonMark === f.cartonMark && Number(row.maxReturnPackages) === 1)
must(source, 'Actual native carton source is missing; do not invent an inventory position or inbound')
const body = { lastMileOrderId: id(f.lastMileOrderId), reason: `${context.marker} synthetic refusal`, returnDirection: 'OVERSEAS_WAREHOUSE',
items: [{ outboundPalletItemId: id(source.outboundPalletItemId), returnCartonId: id(source.returnCartonId), packageCount: 1 }], idempotencyKey: key() }
const markPath = scope(`${BASE}/delivery-orders/${encodeURIComponent(f.deliveryNo)}/mark-return`, f.customerId)
const marked = await call('POST', markPath, body), replayMark = await call('POST', markPath, body)
must(marked.exceptionNo && replayMark.exceptionNo === marked.exceptionNo && replayMark.replayed, 'Native mark-return replay drifted')
const path = `${BASE}/exception-orders/${encodeURIComponent(marked.exceptionNo)}`
const started = await call('POST', scope(`${path}/start-processing`, f.customerId), { expectedVersion: marked.version, idempotencyKey: key(), handlingAction: 'SYNTHETIC TEST CARTON RETURN' })
const file = { name: `${context.marker}-native-return.txt`, type: 'text/plain', content: new TextEncoder().encode('SYNTHETIC TEST EVIDENCE; not a real external POD') }
const uploaded = await call('POST', scope(`${path}/evidence`, f.customerId), undefined, { file })
const completeBody = { expectedVersion: started.version, idempotencyKey: key(), handlingResult: 'SYNTHETIC TEST ACTUAL RETURN', evidenceFileIds: [uploaded.fileId],
receipts: [{ outboundPalletItemId: id(source.outboundPalletItemId), inventoryPositionId: null, returnCartonId: id(source.returnCartonId), receivedPackages: 1, ...f.target }] }
const born = own.carton.get(f.cartonMark), expected = new Map(born.originalSkuItems.map(row => [row.skuCode, number(row.quantity)]))
must(expected.size === born.originalSkuItems.length && [...expected.values()].every(n => n > 0), 'Unique original native SKU quantities required')
const skus = [...expected.keys()].sort(), S = await nativeSnapshot(f, skus)
const dispatchNo = own.delivery.get(f.deliveryNo).dispatchNo
const outboundEvidence = S.movements.filter(row => row.type === 'OUTBOUND' && row.referenceNo === dispatchNo)
must(outboundEvidence.length === skus.length && skus.every(sku => outboundEvidence.filter(row => row.skuCode === sku).length === 1
&& outboundEvidence.find(row => row.skuCode === sku).totalDelta === -expected.get(sku)), 'Original single-carton per-SKU outbound movement does not match producer carton')
const completed = await call('POST', scope(`${path}/complete`, f.customerId), completeBody)
const R = await nativeSnapshot(f, skus), history = await call('GET', scope(path, f.customerId)), after = await call('GET', cartonPath)
must(completed.status === 'COMPLETED' && number(completed.restoredPackages) === 1 && history.returnReceipts?.length === 1
&& number(history.returnReceipts[0].receivedPackages) === 1 && history.returnReceipts[0].receiptNo && history.returnReceipts[0].receivedAt, 'Native receipt identity/box count is incomplete')
const receiptNo = history.returnReceipts[0].receiptNo
const incoming = R.movements.filter(row => row.type === 'EXCEPTION_RETURN_IN' && row.referenceNo === receiptNo)
must(!S.movements.some(row => row.referenceNo === receiptNo) && incoming.length === skus.length
&& same(incoming.map(row => row.skuCode).sort(), skus) && skus.every(sku => {
const previous = S.stock.find(row => row.skuCode === sku), restored = R.stock.find(row => row.skuCode === sku)
const movement = incoming.find(row => row.skuCode === sku)
return restored.present && restored.updatedAt && restored.total - previous.total === expected.get(sku)
&& previous.total === 0 && previous.availableView === 0 && previous.cartons === 0
&& restored.availableView === expected.get(sku) && restored.cartons === 1
&& movement.totalDelta === expected.get(sku) && movement.availableDelta === expected.get(sku) && movement.occurredAt
}), 'Every original SKU must restore its exact total, visible availability, carton count and one immutable receipt movement')
must(after.status === 'AVAILABLE' && id(after.customerId) === id(f.customerId) && id(after.overseasWarehouseId) === id(f.warehouseId)
&& after.cartonMark === f.cartonMark && after.palletCode === f.target.targetPalletNo && after.locationCode === f.target.targetLocationCode && after.putawayAt,
'Native carton did not return to the exact validated physical pallet/location')
const deliveryAfter = await call('GET', scope(`${BASE}/delivery-orders/${encodeURIComponent(f.deliveryNo)}`, f.customerId))
must(deliveryAfter.order?.status === 'RETURNED', 'Actual single-carton recovery did not close its delivery')
const replay = await call('POST', scope(`${path}/complete`, f.customerId), completeBody)
const Rprime = await nativeSnapshot(f, skus), historyAgain = await call('GET', scope(path, f.customerId)), cartonAgain = await call('GET', cartonPath)
const deliveryAgain = await call('GET', scope(`${BASE}/delivery-orders/${encodeURIComponent(f.deliveryNo)}`, f.customerId))
must(replay.replayed === true && same(Rprime, R) && same(historyAgain.returnReceipts, history.returnReceipts)
&& same({ pallet: cartonAgain.palletCode, location: cartonAgain.locationCode, at: cartonAgain.putawayAt, status: cartonAgain.status },
{ pallet: after.palletCode, location: after.locationCode, at: after.putawayAt, status: after.status })
&& same(shipment(deliveryAgain.order), shipment(deliveryAfter.order)), 'Native replay changed SKU stock, receipt rows/times, target or delivery')
return { exceptionNo: marked.exceptionNo, cartonMark: f.cartonMark, dispatchNo, receiptNo, S, R, Rprime,
expectedSkuQuantities: Object.fromEntries(expected), target: f.target,
availableQuantityMeaning: 'HTTP availableQuantity is a capped visible value; total and immutable availableDelta verified, no naked-ledger availability claim' }
})
await run('permissions', async f => {
must(typeof context.requestReadonly === 'function' && f.outboundNo, 'Dedicated read-only session and owned fresh outbound required')
const path = `${BASE}/outbound-orders/${encodeURIComponent(f.outboundNo)}`
const before = await call('GET', path, undefined, { actor: 'READ_ONLY' })
must(before.outbound?.status === 'WAIT_OUTBOUND', 'Current unexecuted outbound required for permission isolation')
await call('POST', `${path}/cancel`, { reason: context.marker }, { failure: 'FORBIDDEN', actor: 'READ_ONLY' })
const after = await call('GET', path)
must(same(shipment(after.outbound), shipment(before.outbound)), 'Forbidden read-only command changed outbound')
return { outboundNo: f.outboundNo, readAllowed: true, cancellationForbidden: true }
})
proof.status = cases.every(name => proof.cases[name]?.status === 'PASS') ? 'HTTP_CASES_PASSED_REVIEW_REQUIRED' : 'PARTIAL_NOT_ALL_VERIFIED'
return proof
} catch (error) { proof.status = 'FAILED'; proof.error = error.message; throw error }
finally { await context.checkpoint() }
}