import test from 'node:test' import assert from 'node:assert/strict' import { mkdtempSync, mkdirSync, readFileSync, writeFileSync, existsSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join, dirname, resolve } from 'node:path' import { AcceptanceRun } from './admin-test-env-acceptance.mjs' import { run as runInboundMeasurement } from './admin-test-env-modules/inbound-measurement.mjs' import { verifyPalletLabels } from './admin-test-env-modules/phase3-loading-finalize.mjs' function departedRecoveryFixture() { const snapshotTrip = { tripNo: 'TR-OWN', status: 'IN_TRANSIT', recordVersion: '27', vehicleId: 'V1', driverId: 'D1', warehouseId: 'W1', departedAt: '2026-10-03T11:00:00Z' } const cargo = [{ dispatchNo: 'OWN', dispatchItemId: 'I1', warehousePalletId: 'P1', packages: 2 }, { dispatchNo: 'EXT', dispatchItemId: 'I2', warehousePalletId: 'P2', packages: 1 }] const departure = { action: 'DEPART', recordVersion: '27', snapshot: { trip: snapshotTrip, confirmedLoad: { manifestHash: 'a'.repeat(64), cargo } } } const proof = { marker: 'RUN', tripNo: 'TR-OWN', warehouseId: 'W1', customerId: 'C1', status: 'CHECKING', stage: 'TRIP_OPERATING_COSTS', checkpoints: [], dispatchNos: ['OWN', 'EXT'], picker: { membershipId: 'OLD-PDA' }, departureRequest: { idempotencyKey: 'old-key' }, departure: { tripNo: 'TR-OWN', status: 'IN_TRANSIT', departedAt: snapshotTrip.departedAt, shippedPackages: 3 } } const trip = { marker: 'RUN', tripNo: 'TR-OWN', costAcceptance: { marker: 'RUN', status: 'FAILED', costs: [], departure, requests: [{ method: 'GET', status: 'RESPONDED', http: 200, code: '200', requestId: 'r', traceId: 't' }] }, externalReceipt: { status: 'VERIFIED', bookingNo: 'BK', warehousePalletId: 'P2' }, externalDispatch: { dispatchNo: 'EXT', deliveryNo: 'DL-EXT' } } const report = { success: false, steps: [{ name: '独立预期覆盖全部实物且没有重叠托盘', passed: false }, { name: '模块执行', passed: false }], createdResources: { fleetAcceptance: proof, fleetTrips: [trip], fleetCostActors: { status: 'DISABLED' }, fleetFeeCoverageCases: [{ mode: 'PARTIAL', proof: { deliveryNos: ['DL-OWN'] } }] } } const base = '/api/platform/v1/last-leg/fleet/trips/TR-OWN' const responses = new Map([[base, { trip: structuredClone(snapshotTrip), dispatches: [{ dispatchNo: 'OWN', customerId: 'C1' }, { dispatchNo: 'EXT', customerId: 'C1' }] }], [base + '/history?page=1&size=100', { total: 1, records: [structuredClone(departure)] }], [base + '/costs?page=1&size=100', { page: { records: [], total: 0 }, summary: { manifestHash: 'a'.repeat(64), departureVersion: '27', totals: [] } }], [base + '/handovers', { records: [], total: 0 }]]) for (const row of cargo) { responses.set('/api/platform/v1/last-leg/dispatches/' + row.dispatchNo, { dispatchNo: row.dispatchNo, status: 'DEPARTED', overseasWarehouseId: 'W1', packageCount: row.packages, pickedPackageCount: row.packages, shippedPackageCount: row.packages, items: [{ id: row.dispatchItemId, warehousePalletId: row.warehousePalletId, packageCount: row.packages }] }) responses.set('/api/platform/v1/last-leg/delivery-orders/DL-' + row.dispatchNo + '?customerId=C1', { order: { deliveryNo: 'DL-' + row.dispatchNo, customerId: 'C1', dispatchNo: row.dispatchNo, status: 'WAIT_DELIVERY', version: '1', packageCount: row.packages, documentSummary: { categories: [{ fileCount: 0 }] } } }) } const calls = [], ctx = { marker: 'RUN', token: 'writer', context: {}, createdResources: report.createdResources, async checkpoint() { calls.push('checkpoint') }, async request(method, path) { assert.equal(method, 'GET', 'recovery verification must never write'); calls.push(path); assert.ok(responses.has(path), path) return { http: 200, body: { code: '200', data: responses.get(path) }, requestId: 'r', traceId: 't' } } } return { report, ctx, calls, responses, base, trip } } function afterCostsRecoveryFixture() { const fixture = departedRecoveryFixture(), { report, trip, responses, base } = fixture report.createdResources.fleetAcceptance.stage = 'IN_TRANSIT_HANDOVER' report.steps[0].name = '每张排车已发车且货量与客户起运仓一致' trip.costAcceptance.status = 'VERIFIED' trip.costAcceptance.costs = [{ costNo: 'CNY-COST' }, { costNo: 'USD-COST' }] trip.costAcceptance.final = { page: { records: structuredClone(trip.costAcceptance.costs), total: 2 }, summary: { manifestHash: 'a'.repeat(64), departureVersion: '27', totals: [{ currency: 'CNY', directCost: '100.03' }, { currency: 'USD', directCost: '13.07' }], allocationBlockReason: 'MULTI_STOP' } } trip.handover = { status: 'FAILED', requests: [{ method: 'GET', status: 'RESPONDED', http: 200, code: '200' }] } responses.set(base + '/costs?page=1&size=100', structuredClone(trip.costAcceptance.final)) return fixture } test('after-cost recovery requires its exact known read-only handover failure and rejects any handover write', () => { const { report } = afterCostsRecoveryFixture() assert.equal(reviewedFullCheckpoint(report, 'DEPARTED_AFTER_COSTS_BEFORE_HANDOVER').costsAlreadyVerified, true) report.createdResources.fleetTrips[0].handover.requests.push({ method: 'POST', status: 'RESPONDED', http: 200, code: '200' }) assert.throws(() => reviewedFullCheckpoint(report, 'DEPARTED_AFTER_COSTS_BEFORE_HANDOVER'), /checkpoint/) }) test('after-cost recovery checks original cost contents and refuses a changed amount before any write', async () => { const { ctx, responses, base } = afterCostsRecoveryFixture() responses.get(base + '/costs?page=1&size=100').summary.totals[0].directCost = '100.04' await assert.rejects(continueReviewedDeparture(ctx, { costsAlreadyVerified: true, prepareActors: () => assert.fail('no new actors'), makePicker: () => assert.fail('no new PDA before verification') }), /costs already written or cargo basis changed/) }) test('after-cost recovery retains verified costs and only enters handover, signatures and resource closure', async () => { const { ctx, trip } = afterCostsRecoveryFixture(), costs = trip.costAcceptance, oldHandover = trip.handover, operations = [] await continueReviewedDeparture(ctx, { costsAlreadyVerified: true, prepareActors: () => assert.fail('verified costs need no new cost actors'), resolveAccess: async () => ({}), makePicker: async () => ({ token: 'new-pda', membershipId: 'NEW-PDA' }), closePicker: async () => operations.push('close-pda'), complete: (context, trip, picker, details, options) => completeDepartedFleetScenario(context, trip, picker, details, { ...options, verifyCosts: () => assert.fail('costs must never be recreated'), handover: async () => operations.push('handover'), completeDelivery: async (_ctx, order) => { operations.push('sign:' + order.deliveryNo); return { order: { status: 'DELIVERED', signedAt: 'signed' } } }, closeTrip: async () => { operations.push('release'); return { status: 'CARGO_COMPLETED_AND_RESOURCES_RELEASED' } }, cleanup: async () => operations.push('cleanup'), }) }) assert.equal(trip.costAcceptance, costs); assert.equal(trip.previousReadOnlyHandoverAttempts[0], oldHandover) assert.deepEqual(operations, ['handover', 'sign:DL-OWN', 'sign:DL-EXT', 'release', 'cleanup', 'close-pda']) }) test('departed recovery requires reviewed SHA and exactly the original read-only cost failure', () => { assert.throws(() => parseFleetArguments(['--resume-report', 'reports/r5/report.json', '--resume-stage', 'DEPARTED_BEFORE_COSTS']), /SHA256/) const args = ['--resume-report', 'reports/r5/report.json', '--resume-stage', 'DEPARTED_BEFORE_COSTS', '--resume-sha256', 'a'.repeat(64)] assert.equal(parseFleetArguments(args).resumeSha256, 'a'.repeat(64)) assert.throws(() => parseFleetArguments([...args, '--scenario', 'return-redispatch']), /fresh run/) assert.equal(reviewedFullCheckpoint(departedRecoveryFixture().report, 'DEPARTED_BEFORE_COSTS').departed, true) for (const change of [r => r.createdResources.fleetTrips[0].costAcceptance.requests.push({ method: 'POST' }), r => r.createdResources.fleetTrips[0].handover = {}, r => r.createdResources.fleetAcceptance.receipts = [], r => r.createdResources.fleetCostActors.status = 'READY', r => r.steps[0].name = 'unknown write']) { const { report } = departedRecoveryFixture(); change(report) assert.throws(() => reviewedFullCheckpoint(report, 'DEPARTED_BEFORE_COSTS'), /checkpoint/) } }) for (const mutation of ['none', 'version', 'history', 'cost', 'handover', 'cargo', 'signature', 'document']) test(`recovery rechecks actual state before any session/business write: ${mutation}`, async () => { const { ctx, responses, base } = departedRecoveryFixture() if (mutation === 'version') responses.get(base).trip.recordVersion = '28' if (mutation === 'history') responses.get(base + '/history?page=1&size=100').records[0].snapshot.confirmedLoad.manifestHash = 'changed' if (mutation === 'cost') responses.get(base + '/costs?page=1&size=100').page.records.push({ costNo: 'COST' }) if (mutation === 'handover') responses.get(base + '/handovers').records.push({ handoverNo: 'H' }) if (mutation === 'cargo') responses.get('/api/platform/v1/last-leg/dispatches/OWN').items[0].packageCount = 3 const delivery = responses.get('/api/platform/v1/last-leg/delivery-orders/DL-OWN?customerId=C1').order if (mutation === 'signature') delivery.signedAt = 'now' if (mutation === 'document') delivery.documentSummary.categories[0].fileCount = 1 if (mutation === 'none') { await verifyDepartedRecovery(ctx); assert.equal(ctx.createdResources.fleetDepartureRecoveryVerification.status, 'VERIFIED') } else await assert.rejects(continueReviewedDeparture(ctx, { prepareActors: () => assert.fail('no new actors before validation') }), /recovery refused/) }) test('reviewed recovery archives old evidence and creates fresh sessions before shared post-departure flow only', async () => { const { ctx, trip, calls } = departedRecoveryFixture(); const oldCost = trip.costAcceptance await continueReviewedDeparture(ctx, { prepareActors: async () => { assert.equal(ctx.createdResources.fleetDepartureRecoveryVerification.status, 'VERIFIED'); calls.push('new-actors'); return { marker: 'RUN', listOnlyToken: 'reader', deniedToken: 'denied', async close() { calls.push('close-actors') } } }, resolveAccess: async () => ({}), makePicker: async child => { assert.match(child.marker, /RECOVERY-PDA/); calls.push('new-picker'); return { membershipId: 'NEW', token: 'new-pda' } }, closePicker: async () => calls.push('close-picker'), complete: async (context, actualTrip, picker, dispatches) => { assert.equal(actualTrip, trip); assert.equal(trip.costAcceptance, undefined); assert.equal(picker.membershipId, 'NEW'); assert.equal(dispatches.length, 2) assert.equal(trip.previousReadOnlyCostAttempts[0], oldCost); assert.equal(context.createdResources.fleetAcceptance.previousPicker.membershipId, 'OLD-PDA') calls.push('continue-from-costs') }, }) assert.deepEqual(calls.filter(x => !x.startsWith('/') && x !== 'checkpoint'), ['new-actors', 'new-picker', 'continue-from-costs', 'close-picker', 'close-actors']) }) test('shared continuation starts at costs, retains unavailable allocation and never enters picking or DEPART', async () => { const { ctx, trip, calls } = departedRecoveryFixture() const verified = await verifyDepartedRecovery(ctx), operations = [] await completeDepartedFleetScenario(ctx, trip, { token: 'pda' }, verified.dispatchDetails, { costActors: { marker: 'RUN' }, verifyCosts: async () => { operations.push('costs'); trip.costAcceptance = { status: 'VERIFIED', expected: { allocationStatus: 'UNAVAILABLE' } } }, handover: async () => { assert.equal(trip.costAcceptance.expected.allocationStatus, 'UNAVAILABLE'); operations.push('handover') }, completeDelivery: async (context, order) => { operations.push('signature:' + order.deliveryNo); return { order: { status: 'DELIVERED', signedAt: 'signed' } } }, closeTrip: async () => { operations.push('close-trip'); return { status: 'CARGO_COMPLETED_AND_RESOURCES_RELEASED' } }, cleanup: async () => operations.push('cleanup'), }) assert.deepEqual(operations, ['costs', 'handover', 'signature:DL-OWN', 'signature:DL-EXT', 'close-trip', 'cleanup']) assert.equal(ctx.createdResources.fleetAcceptance.stage, 'FINISHED') assert.ok(!calls.some(x => /\/depart$|\/pick|\/loading/.test(x))) }) test('changed source report SHA blocks recovery before creating context or logging in', async () => { const temporary = mkdtempSync(join(tmpdir(), 'fleet-recovery-sha-')) const root = join(temporary, 'chongchong-global', 'baiyue-firstleg'); mkdirSync(join(root, 'reports', 'original'), { recursive: true }) writeFileSync(join(root, 'reports', 'original', 'report.json'), JSON.stringify(departedRecoveryFixture().report)) try { const result = await runFleetAcceptance({ execute: true, environment: 'TEST', runId: 'reviewed', resumeStage: 'DEPARTED_BEFORE_COSTS', resumeReport: 'reports/original/report.json', resumeSha256: 'b'.repeat(64) }, { root, env: { CHONGCHONG_ENV: 'test', CHONGCHONG_ADMIN_API_BASE_URL: 'https://test.invalid', CHONGCHONG_ADMIN_USERNAME: 'admin', CHONGCHONG_ADMIN_PASSWORD: 'secret', ADMIN_PDA_USERNAME: 'pda', ADMIN_PDA_PASSWORD: 'secret' }, createContext: () => assert.fail('SHA mismatch must precede context/network'), }) assert.equal(result.success, false); assert.match(result.fatal, /SHA256 mismatch/) } finally { assert.equal(dirname(resolve(temporary)), resolve(tmpdir())) assert.ok(resolve(temporary).startsWith(join(resolve(tmpdir()), 'fleet-recovery-sha-'))) rmSync(temporary, { recursive: true, force: true }) } }) import { parseFleetArguments, fleetExecutionPlan, runFleetAcceptance, reviewedFullCheckpoint, verifyFleetTerminalState, runFleetHandoverStage, fleetCostShares, prepareFleetCostActors, findFleetActorPhone, guardFleetWrites, redactFleetWrite, verifyDepartedRecovery, continueReviewedDeparture, completeDepartedFleetScenario } from './fleet-test-env-acceptance.mjs' for (const response of [ { http: 0 }, { http: 503, body: { code: 'A0500' }, requestId: 'r', traceId: 't' }, { http: 200, body: null }, { http: 200, body: { code: '200' } }, { http: 302, body: { code: '200' }, requestId: 'r', traceId: 't' }, ]) test(`unknown prerequisite write stops every subsequent request: ${JSON.stringify(response)}`, async () => { const saved = [], calls = [] const ctx = { async request(method, path, body) { assert.equal(saved.at(-1).status, 'SENDING') assert.deepEqual(saved.at(-1).body, body) calls.push(path); return response } } guardFleetWrites(ctx, entry => saved.push(structuredClone(entry))) const body = { expectedVersion: 6, idempotencyKey: 'original-key', internalNotes: ['test remark'] } await assert.rejects(ctx.request('PUT', '/orders/1/remarks?tenantId=2', body), /Unknown write outcome/) body.expectedVersion = 99 assert.equal(saved[0].body.expectedVersion, 6) assert.equal(saved[1].status, 'UNKNOWN_RESULT') for (const method of ['POST', 'GET', 'DELETE']) await assert.rejects(ctx.request(method, '/must-not-run'), /Unknown write outcome/) assert.deepEqual(calls, ['/orders/1/remarks?tenantId=2']) }) test('formal correlated rejection is recorded and remains available for expected negative assertions', async () => { const saved = [], response = { http: 200, body: { code: 'A0409' }, requestId: 'r', traceId: 't' } const ctx = { async request() { return response } } guardFleetWrites(ctx, entry => saved.push(structuredClone(entry))) assert.equal(await ctx.request('POST', '/negative', { recordVersion: 7 }), response) assert.equal(saved[1].status, 'RESPONDED') await ctx.request('GET', '/readback'); assert.equal(saved.length, 2) }) test('response evidence preserves business messages and returned resource IDs with explicit session provenance and no tokens', async () => { const saved = [], ctx = { token: 'admin-session', pdaToken: 'pda-session', options: { username: 'test-admin' }, async request() { return { http: 200, body: { code: '200', message: 'created', data: { id: '123', businessNo: 'FIXTURE-123', accessToken: 'new-secret', refreshToken: 'refresh-secret' } }, requestId: 'r', traceId: 't' } } } guardFleetWrites(ctx, entry => saved.push(redactFleetWrite(structuredClone(entry)))) await ctx.request('POST', '/create', { expectedVersion: 3 }) assert.deepEqual(saved[0].actor, { kind: 'PLATFORM', source: 'CONTEXT_ADMIN_SESSION' }) assert.equal(saved[1].responseBody.message, 'created'); assert.equal(saved[1].responseBody.data.id, '123') await ctx.request('POST', '/pda', {}, 'pda-session'); assert.equal(saved[2].actor.kind, 'PDA') await ctx.request('POST', '/other', {}, 'unresolved-session'); assert.equal(saved[4].actor.kind, 'UNKNOWN') await ctx.request('POST', '/login', {}, ''); assert.equal(saved[6].actor.source, 'NO_SESSION') for (const secret of ['admin-session', 'pda-session', 'new-secret', 'refresh-secret', 'unresolved-session']) assert.ok(!JSON.stringify(saved).includes(secret)) }) test('POST carton-label PDF is a definite binary response with durable hash and permits same-fixture readback', async () => { const saved = [], calls = [], response = { http: 200, body: null, bytes: Buffer.from('%PDF-1.7\nfixture'), contentType: 'application/pdf', requestId: 'r', traceId: 't' } const ctx = { async requestBinary(method, path) { assert.equal(saved.at(-1).status, 'SENDING'); calls.push(path); return response }, async request() { calls.push('readback') } } guardFleetWrites(ctx, entry => saved.push(structuredClone(entry))) const path = '/api/platform/inbounds/1/carton-label-pdf?tenantId=2&cartonIndex=1' assert.equal(await ctx.requestBinary('POST', path), response) assert.equal(saved[0].path, path); assert.equal(saved[1].status, 'RESPONDED') assert.equal(saved[1].binary.bytes, response.bytes.length); assert.match(saved[1].binary.sha256, /^[a-f0-9]{64}$/) assert.equal(saved[1].binary.validPdf, true) await ctx.request('GET', '/api/platform/inbounds/1'); assert.deepEqual(calls, [path, 'readback']) }) test('real inbound prerequisite and AcceptanceRun binary transport accept three PDF writes then stop raw multipart retries', async t => { const calls = [], saved = [], summary = { id: '1', tenantId: '2', processStatus: 'WAIT_MEASURE', inboundCode: 'FIXTURE-INBOUND', totalPackageCount: 2 } const native = t.mock.method(globalThis, 'fetch', async (input, init) => { const req = new Request(input, init), path = new URL(req.url).pathname calls.push({ method: req.method, path }) const headers = { 'x-request-id': 'r', 'x-trace-id': 't' } if (req.method === 'GET') return new Response(JSON.stringify({ code: '200', data: { summary } }), { headers: { ...headers, 'content-type': 'application/json' } }) assert.equal(saved.at(-1).status, 'SENDING') if (path.endsWith('/carton-label-pdf')) return new Response('%PDF-1.7\nfixture', { headers: { ...headers, 'content-type': 'application/pdf' } }) assert.ok(path.endsWith('/measurement/carton-scans')) throw Error('transport failure Bearer sensitive-session https://example.invalid/private') }) const context = new AcceptanceRun({ gateway: 'https://test.invalid' }) context.createdResources.orders = { marker: context.marker, inboundId: '1', tenantId: '2' } const restore = guardFleetWrites(context, entry => saved.push(redactFleetWrite(structuredClone(entry))), { guardFetch: true }) try { await runInboundMeasurement(context) assert.equal(calls.filter(row => row.path.endsWith('/carton-label-pdf')).length, 3) assert.equal(calls.filter(row => row.path.endsWith('/measurement/carton-scans')).length, 1, 'raw helper retries must not reach transport') const pdfs = saved.filter(row => row.binary?.validPdf) assert.equal(pdfs.length, 3); assert.ok(pdfs.every(row => row.status === 'RESPONDED')) assert.equal(context.steps.find(row => row.name === '生成箱唛 PDF 并冻结稳定箱码').passed, true) const last = saved.at(-1); assert.equal(last.status, 'UNKNOWN_RESULT') assert.ok(last.body.multipart.some(row => row.field === 'data' && row.base64)) assert.ok(last.raw.includes('transport failure')); assert.ok(!last.raw.includes('sensitive-session')); assert.ok(!last.raw.includes('example.invalid')) await assert.rejects(context.request('POST', '/subsequent'), /transport failure/) } finally { restore(); assert.equal(globalThis.fetch, native); t.mock.restoreAll() } }) test('raw JSON prerequisite writes retain headers, original version and bounded diagnostics without duplicate journaling', async t => { let calls = 0 t.mock.method(globalThis, 'fetch', async () => { calls++; return new Response('x'.repeat(600), { status: 502 }) }) const saved = [], context = new AcceptanceRun({ gateway: 'https://test.invalid' }) const restore = guardFleetWrites(context, entry => saved.push(redactFleetWrite(structuredClone(entry))), { guardFetch: true }) try { await assert.rejects(fetch('https://test.invalid/approve', { method: 'PUT', headers: { 'content-type': 'application/json', Authorization: 'Bearer secret', 'Idempotency-Key': 'same-key' }, body: JSON.stringify({ expectedVersion: 6 }) }), /Unknown write outcome/) assert.equal(saved.length, 2); assert.equal(saved[0].body.expectedVersion, 6) assert.equal(saved[0].headers['idempotency-key'], 'same-key'); assert.equal(saved[0].headers.authorization, '[REDACTED]') assert.equal(saved[1].raw.length, 500) await assert.rejects(fetch('https://test.invalid/retry', { method: 'POST' }), /Unknown write outcome/) assert.equal(calls, 1) } finally { restore(); t.mock.restoreAll() } }) for (const invalidPdf of [false, true, 'zip']) test(`real loading finalize prints both PDFs through guarded direct fetch; invalid=${invalidPdf}`, async t => { const saved = [], calls = [], fixture = { destinationType: 'FBA', warehouseId: '1', containerNo: 'CONTAINER', cabinetNo: 'CABINET' } const manifest = { containerNo: fixture.containerNo, totalCount: 1, groups: [{ destinationWarehouseCode: 'FBA', labels: [{ containerNo: fixture.containerNo, destinationWarehouseInternalCode: 'F01', palletIndex: 1, palletCode: 'CABINET-F01-001' }] }] } t.mock.method(globalThis, 'fetch', async (input, init) => { const req = new Request(input, init); calls.push(req.url) assert.equal(saved.at(-1).status, 'SENDING') const headers = { 'x-request-id': 'r', 'x-trace-id': 't' } return req.url.includes('/prepare?') ? new Response(JSON.stringify({ code: '200', data: manifest }), { headers: { ...headers, 'content-type': 'application/json' } }) : new Response(invalidPdf === true ? 'proxy failure' : '%PDF-1.6\nfixture', { headers: { ...headers, 'content-type': invalidPdf === 'zip' ? 'application/zip' : 'application/pdf' } }) }) const ctx = new AcceptanceRun({ gateway: 'https://test.invalid' }) const restore = guardFleetWrites(ctx, entry => saved.push(redactFleetWrite(structuredClone(entry))), { guardFetch: true }) try { await verifyPalletLabels(ctx, fixture, '2') const prints = saved.filter(row => row.path.includes('/print?')) assert.equal(calls.filter(url => url.includes('/print?')).length, invalidPdf ? 1 : 2) assert.equal(prints.at(-1).status, invalidPdf ? 'UNKNOWN_RESULT' : 'RESPONDED') assert.equal(prints.at(-1).binary.validPdf, !invalidPdf) assert.equal(prints.at(-1).raw, null, 'binary response bytes must not enter text evidence') assert.equal(prints[0].body.destinationWarehouseCode, null) if (!invalidPdf) { assert.equal(prints[2].body.destinationWarehouseCode, 'FBA'); assert.ok(ctx.steps.every(row => row.passed)) } else await assert.rejects(ctx.request('POST', '/no-retry'), /Unknown write outcome/) } finally { restore(); t.mock.restoreAll() } }) for (const override of [{ http: 0 }, { http: 503 }, { bytes: Buffer.from('proxy') }, { bytes: new Uint8Array() }, { contentType: 'text/html' }, { traceId: null }, { contentType: 'application/json', bytes: Buffer.from('{"code":"200"}'), body: { code: '200' } }]) test(`binary write still stops on unknown or invalid response: ${JSON.stringify(override)}`, async () => { const saved = [], ctx = { async requestBinary() { return { http: 200, body: null, bytes: Buffer.from('%PDF-1.7'), contentType: 'application/pdf', requestId: 'r', traceId: 't', ...override } }, async request() { assert.fail('must stop') } } guardFleetWrites(ctx, entry => saved.push(structuredClone(entry))) await assert.rejects(ctx.requestBinary('POST', '/carton-label-pdf'), /Unknown write outcome/) assert.equal(saved[1].status, 'UNKNOWN_RESULT') await assert.rejects(ctx.request('GET', '/readback'), /Unknown write outcome/) }) test('checkpoint failure stops before dispatch; transport throw stops even after caller catches', async () => { let calls = 0 const ctx = { async request() { calls++; throw Error('transport failure') } } guardFleetWrites(ctx, () => { throw Error('disk full') }) await assert.rejects(ctx.request('POST', '/write'), /disk full/) await assert.rejects(ctx.request('GET', '/later'), /disk full/); assert.equal(calls, 0) const saved = [], other = { async request() { calls++; throw Error('transport failure') } } guardFleetWrites(other, entry => saved.push(structuredClone(entry))) await assert.rejects(other.request('PUT', '/write'), /transport failure/) await assert.rejects(other.request('POST', '/cleanup'), /transport failure/) assert.equal(calls, 1); assert.equal(saved[1].status, 'UNKNOWN_RESULT') }) test('multipart delegates once and retains recoverable fixture bytes, business keys and versions without credentials', async () => { const saved = [], ctx = { async requestMultipart(method, path, form) { return this.requestWithBody(method, path, form) }, async requestWithBody() { return { http: 200, body: { code: '200' }, requestId: 'r', traceId: 't' } }, } guardFleetWrites(ctx, entry => saved.push(redactFleetWrite(structuredClone(entry)))) const form = new FormData(); form.append('file', new Blob(['fixture']), 'proof.txt'); form.append('password', 'hidden') await ctx.requestMultipart('POST', '/upload', form) assert.equal(saved.length, 2); assert.equal(Buffer.from(saved[0].body.multipart[0].base64, 'base64').toString(), 'fixture') assert.ok(!JSON.stringify(saved).includes('hidden')) const clean = redactFleetWrite({ draftToken: 'business-draft', idempotencyKey: 'command-key', expectedVersion: 6, headers: { Authorization: 'Bearer hidden', 'X-Access-Token': 'hidden' }, body: { password: 'hidden', accessToken: 'hidden' } }) assert.equal(clean.draftToken, 'business-draft'); assert.equal(clean.idempotencyKey, 'command-key') assert.equal(clean.expectedVersion, 6); assert.ok(!JSON.stringify(clean).includes('hidden')) }) test('fleet entry defaults to a no-side-effect plan and requires explicit TEST and unique run ID', () => { const p = parseFleetArguments([]) assert.equal(p.execute, false); assert.equal(fleetExecutionPlan(p).execution, 'PLAN') for (const args of [['--execute'], ['--execute', '--run-id', 'new'], ['--execute', '--environment', 'prod', '--run-id', 'new'], ['--execute', '--environment', 'TEST', '--run-id', '../old'], ['--plan', '--execute'], ['--force'], ['--run-id', 'a', '--run-id', 'b']]) { assert.throws(() => parseFleetArguments(args)) } assert.equal(parseFleetArguments(['--execute', '--environment', 'TEST', '--run-id', 'new']).execute, true) const handover = parseFleetArguments(['--plan', '--environment', 'TEST', '--run-id', 'fleet-handover-20261003', '--output', 'reports/fleet-handover-live-20261003']) assert.equal(fleetExecutionPlan(handover).outputDir, 'reports/fleet-handover-live-20261003') for (const output of ['reports/../outside', 'C:/temp/output', 'reports', 'reports/nested/path']) assert.throws(() => parseFleetArguments(['--output', output])) }) test('return redispatch is explicit, fresh-only and declares source-event proof separately', () => { const config = parseFleetArguments(['--plan', '--environment', 'TEST', '--run-id', 'return-new', '--scenario', 'return-redispatch']) const plan = fleetExecutionPlan(config) assert.equal(plan.scenario, 'return-redispatch'); assert.ok(plan.returnRedispatch.required.includes('Two current-run domestic sources')) assert.throws(() => parseFleetArguments(['--scenario', 'return-redispatch', '--resume-report', 'reports/old/report.json', '--resume-stage', 'FULL_COVERAGE']), /fresh run/) assert.throws(() => parseFleetArguments(['--scenario', 'unknown'])) }) test('handover stage exports only a verified same-run departure fixture before the optional UI checkpoint', async () => { const order = [], departure = { tripNo: 'TR-NEW', status: 'IN_TRANSIT' } const context = { marker: 'CURRENT', context: { saveFleetHandoverFixture(value) { order.push('save'); assert.equal(value.marker, 'CURRENT') } }, createdResources: { fleetAcceptance: { departure } } } const trip = { tripNo: 'TR-NEW', warehouseId: '92', costAcceptance: { status: 'VERIFIED', marker: 'CURRENT', expected: { finalCny: '100.03', usd: '13.07' } } }, details = [{ dispatchNo: 'PC-NEW' }] const verified = { status: 'VERIFIED', marker: 'CURRENT', originalDeparture: { snapshot: { confirmedLoad: { pallets: [] } } }, browser: { tripNo: 'TR-NEW' }, handoverNo: 'HO-NEW' } const result = await runFleetHandoverStage(context, trip, 'secret-picker-token', details, { verify: async (ctx, module, proof, token, dispatches) => { order.push('verify'); assert.equal(ctx, context); assert.equal(proof, trip); assert.equal(token, 'secret-picker-token'); assert.equal(dispatches, details); return verified }, onReady: async fixture => { order.push('ui'); assert.equal(fixture.status, 'DEPART_AND_HANDOVER_VERIFIED'); assert.equal(fixture.departure, departure) }, }) assert.deepEqual(order, ['verify', 'save', 'ui']); assert.ok(!JSON.stringify(result).includes('secret-picker-token')) assert.deepEqual(result.costs, trip.costAcceptance) for (const invalid of [{ ...verified, status: 'FAILED' }, { ...verified, marker: 'OLD' }, { ...verified, originalDeparture: null }]) { await assert.rejects(runFleetHandoverStage(context, trip, 'token', details, { verify: async () => invalid, onReady: async () => assert.fail('invalid evidence must not reach the browser checkpoint') }), /current verified/) } }) test('cost shares use controlled physical pallets and the original external booking, never statistical totals', () => { const trip = { externalReceipt: { status: 'VERIFIED', bookingNo: 'BK-ONE', warehousePalletId: '3' }, externalDispatch: { dispatchNo: 'EXT' } } const details = [{ dispatchNo: 'OWN', items: [{ warehousePalletId: '1' }, { warehousePalletId: '1' }, { warehousePalletId: '2' }] }, { dispatchNo: 'EXT', items: [{ warehousePalletId: '3' }] }] assert.deepEqual(fleetCostShares(trip, details), [ { businessNo: 'OWN', sourceType: 'OWN', dispatchNo: 'OWN', warehousePalletIds: ['1', '2'], palletSpaces: 2 }, { businessNo: 'BK-ONE', sourceType: 'EXTERNAL', dispatchNo: 'EXT', warehousePalletIds: ['3'], palletSpaces: 1 }, ]) assert.throws(() => fleetCostShares(trip, [{ ...details[0], items: [{ warehousePalletId: '3' }] }, details[1]]), /distinct/) assert.throws(() => fleetCostShares(trip, [details[0], { ...details[1], items: [{ warehousePalletId: '4' }] }]), /receipt/) }) test('missing isolated cost actor preparation rejects before readers or fixture creation', async () => { let touched = false await assert.rejects(runFleetAcceptance({ execute: true, environment: 'TEST' }, { env: { CHONGCHONG_ENV: 'test' }, prepareCostActors: null, readers: { preflight() { touched = true } }, }), /actor preparation/) assert.equal(touched, false) }) for (const failLogin of [false, true]) test(`cost actors create exact isolated roles and disable only owned accounts; login failure=${failLogin}`, async () => { const calls = [], saved = [], roles = [], users = [] const context = { marker: 'RUN', token: 'admin-secret', createdResources: {}, async findAvailablePhone() { return '19900000000' }, async checkpoint() { saved.push(structuredClone(context.createdResources)) }, async request(method, path, body, token) { if (method === 'GET' && (path.startsWith('/api/platform/v1/iam/users?') || path.includes('/administrator-phone-availability?'))) return { http: 200, body: { code: '200', data: path.includes('/administrator-phone-availability?') ? true : { records: [], total: 0 } }, requestId: 'r', traceId: 't' } const pending = saved.at(-1).fleetCostActors.requests.at(-1) assert.equal(pending.status, 'SENDING'); assert.equal(pending.path, path) calls.push({ method, path, body, token }) let data if (path.endsWith('/authorization/permissions')) data = token === 'session-1' ? ['platform:fleet:trip:list'] : [] else if (path.endsWith('/permissions') && method === 'GET') data = [{ id: '7', permissionCode: 'platform:fleet:trip:list', status: 'ACTIVE' }] else if (path.endsWith('/roles') && method === 'POST') { data = { ...body, id: String(roles.length + 1), roleType: 'CUSTOM' }; roles.push(data) } else if (path.endsWith('/roles/permissions')) data = body else if (path.endsWith('/users') && method === 'POST') { data = { ...body, membershipId: String(users.length + 10) }; users.push(data) } else if (path === '/api/auth/login') { if (failLogin) throw Error('login unavailable'); data = { accessToken: `session-${users.length}` } } else if (path.endsWith('/status')) data = body else assert.fail(path) return { http: 200, body: { code: '200', data }, requestId: 'request', traceId: 'trace' } } } if (failLogin) await assert.rejects(prepareFleetCostActors(context), /login unavailable/) else { const actors = await prepareFleetCostActors(context) assert.equal(actors.listOnlyToken, 'session-1'); assert.equal(actors.deniedToken, 'session-2') assert.equal(calls.filter(row => row.path.endsWith('/roles/permissions'))[1].body.permissionIds.length, 0) await actors.close() const count = calls.length; await actors.close(); assert.equal(calls.length, count) } assert.equal(context.createdResources.fleetCostActors.status, 'DISABLED') assert.equal(calls.filter(row => /\/users\/\d+\/status$/.test(row.path)).length, users.length) assert.equal(calls.filter(row => /\/roles\/\d+\/status$/.test(row.path)).length, roles.length) const evidence = JSON.stringify(saved) assert.ok(!evidence.includes('session-1')); assert.ok(!evidence.includes('admin-secret')) for (const user of users) assert.ok(!evidence.includes(user.password)) assert.ok(!calls.some(row => row.method === 'DELETE')) }) test('fresh cost actor phones avoid existing platform users and use an independent namespace under the same original marker', async () => { const phones = [], ctx = { marker: 'ORIGINAL-RUN', async request(method, path) { assert.equal(method, 'GET') let data if (path.includes('/users?')) { const phone = new URL('https://test.invalid' + path).searchParams.get('keyword'); phones.push(phone) data = { records: phones.length === 1 ? [{ phone }] : [], total: phones.length === 1 ? 1 : 0 } } else data = true return { http: 200, body: { code: '200', data }, requestId: 'r', traceId: 't' } } } const first = await findFleetActorPhone(ctx, 'a'.repeat(16)) assert.notEqual(first, phones[0]); assert.match(first, /^18\d{9}$/) const second = await findFleetActorPhone(ctx, 'b'.repeat(16)) assert.notEqual(first, second) }) test('phone lookup failure stops without any user creation or guessing', async () => { let calls = 0 await assert.rejects(findFleetActorPhone({ marker: 'RUN', async request(method) { assert.equal(method, 'GET'); calls++; return { http: 0 } } }, 'a'.repeat(16)), /Cannot verify/) assert.equal(calls, 1) }) test('main chain performs handover after actual DEPART and before receipts, and cleanup follows current-resource closure', async () => { const source = readFileSync(new URL('./fleet-test-env-acceptance.mjs', import.meta.url), 'utf8') const savedDeparture = source.indexOf('proof.departure = departed'), handover = source.indexOf("stage('IN_TRANSIT_HANDOVER')") const receipt = source.indexOf("stage('RECEIPTS_AND_RESOURCE_RELEASE')"), closure = source.indexOf('proof.closure = await closeTrip') const cleanup = source.indexOf('await cleanup(context, MODULE, trip)') assert.ok(savedDeparture > 0 && savedDeparture < handover && handover < receipt && receipt < closure && closure < cleanup) assert.match(source, /finally \{ await disablePicker\(context, picker, 71\) \}/) }) async function executeFixture(failProducer = false) { const temporary = mkdtempSync(join(tmpdir(), 'fleet-entry-contract-')) const root = join(temporary, 'chongchong-global', 'baiyue-firstleg'); mkdirSync(root, { recursive: true }) const calls = [], secrets = 'never-print-this-secret' const env = { CHONGCHONG_ENV: 'test', CHONGCHONG_ADMIN_API_BASE_URL: 'https://test.invalid', CHONGCHONG_ADMIN_USERNAME: 'fixture-admin', CHONGCHONG_ADMIN_PASSWORD: secrets, ADMIN_PDA_USERNAME: 'fixture-pda', ADMIN_PDA_PASSWORD: secrets } const config = parseFleetArguments(['--execute', '--environment', 'TEST', '--run-id', 'fixture']) const createContext = options => ({ options, context: {}, createdResources: {}, steps: [], modules: [], coverageGaps: [], token: secrets, async request(method, path, body) { const pending = JSON.parse(readFileSync(join(root, 'reports/fleet-fixture/evidence/write-000001.json'), 'utf8')) assert.equal(pending.request.status, 'SENDING'); assert.deepEqual(pending.request.body, body) assert.equal(pending.request.path, path); calls.push('unknown-write'); return { http: 0 } }, async executeModule(name, handler) { try { await handler(); this.modules.push({ name, success: true }) } catch { this.modules.push({ name, success: false }); this.steps.push({ name: 'producer failed', passed: false }) } }, async run() { await this.executeModule('producer', async () => { calls.push('producer') if (failProducer === 'unknown') { try { await this.request('PUT', '/orders/1/remarks?tenantId=2', { expectedVersion: 6, idempotencyKey: 'original-key', internalNotes: ['fixture'] }) } catch { /* Simulate a prerequisite swallowing an error. */ } await this.request('POST', '/loading/must-not-run', {}) } if (failProducer) throw Error('fixture failure') }) await this.executeModule('phase4-overseas-dispatch', async () => { calls.push('dispatch'); this.createdResources.current = { accessToken: secrets } }) return { success: true, steps: this.steps, modules: this.modules, createdResources: this.createdResources, summary: { failed: 0 } } }, }) try { const options = { root, env, createContext, readers: { async preflight() { calls.push('preflight') }, async readReceiving() { throw Error('not used') } }, scenario: async context => { calls.push('fleet'); context.createdResources.fleetAcceptance = { status: 'HTTP_CHAIN_VERIFIED_WITH_ACK_GAP' } const command = { requests: [{ method: 'POST', status: 'SENDING', body: { idempotencyKey: 'original-key' }, accessToken: secrets }] } await context.context.checkpointFleetHandover(command) const firstPath = join(root, 'reports/fleet-fixture/evidence/handover-000001.json') const before = readFileSync(firstPath, 'utf8'), saved = JSON.parse(before) assert.equal(saved.proof.requests[0].body.idempotencyKey, 'original-key') assert.equal(saved.proof.requests[0].status, 'SENDING'); assert.ok(!before.includes(secrets)) command.requests[0].status = 'RESPONDED' await context.context.checkpointFleetHandover(command) assert.equal(readFileSync(firstPath, 'utf8'), before) assert.equal(JSON.parse(readFileSync(join(root, 'reports/fleet-fixture/evidence/handover-000002.json'), 'utf8')).proof.requests[0].status, 'RESPONDED') } } const result = await runFleetAcceptance(config, options) const report = JSON.parse(readFileSync(result.report, 'utf8')) if (failProducer === 'unknown') { const unknown = JSON.parse(readFileSync(join(root, 'reports/fleet-fixture/evidence/write-000002.json'), 'utf8')) assert.equal(unknown.request.status, 'UNKNOWN_RESULT'); assert.equal(unknown.request.body.expectedVersion, 6) assert.equal(unknown.request.body.idempotencyKey, 'original-key') } assert.ok(!readFileSync(result.report, 'utf8').includes(secrets)) assert.equal(existsSync(join(root, 'reports/.fleet-acceptance.lock')), false) const oldReport = readFileSync(result.report, 'utf8') const repeated = await runFleetAcceptance(config, options) assert.equal(repeated.success, false) assert.equal(readFileSync(result.report, 'utf8'), oldReport, 'existing run is never overwritten or resumed') return { result, report, calls } } finally { assert.equal(dirname(resolve(temporary)), resolve(tmpdir())) assert.ok(resolve(temporary).startsWith(join(resolve(tmpdir()), 'fleet-entry-contract-'))) rmSync(temporary, { recursive: true, force: true }) } } test('fresh entry runs dedicated fleet scenario after prerequisites without altering the default F40 chain', async () => { const { result, report, calls } = await executeFixture() assert.equal(result.success, true) assert.deepEqual(calls, ['preflight', 'producer', 'dispatch', 'fleet']) assert.equal(report.fleetGoalComplete, false) assert.equal(report.createdResources.current.accessToken, '[REDACTED]') }) test('failed prerequisite stops before further fixture creation and retains the failed report', async () => { const { result, report, calls } = await executeFixture(true) assert.equal(result.success, false) assert.deepEqual(calls, ['preflight', 'producer']) assert.equal(report.fatal, 'Producer stopped: producer') }) test('real fleet entry journals prerequisite writes before sending and stops loading even if producer catches unknown outcome', async () => { const { result, report, calls } = await executeFixture('unknown') assert.equal(result.success, false) assert.deepEqual(calls, ['preflight', 'producer', 'unknown-write']) assert.equal(report.fatal, 'Producer stopped: producer') }) test('environment mismatch rejects before invoking any readers or contexts', async () => { let touched = false await assert.rejects(() => runFleetAcceptance({ execute: true, environment: 'TEST', runId: 'new' }, { env: { CHONGCHONG_ENV: 'production' }, readers: { preflight() { touched = true } }, }), /TEST/) assert.equal(touched, false) }) test('reviewed resume requires explicit paired checkpoint options', () => { assert.throws(() => parseFleetArguments(['--resume-report', 'reports/old/report.json'])) assert.throws(() => parseFleetArguments(['--resume-report', 'reports/old/report.json', '--resume-stage', 'PICK_EACH_DISPATCH'])) const c = parseFleetArguments(['--execute', '--environment', 'TEST', '--run-id', 'reviewed', '--resume-report', 'reports/old/report.json', '--resume-stage', 'FULL_COVERAGE']) assert.equal(c.resumeStage, 'FULL_COVERAGE') }) test('checkpoint guard forbids repeating commands whose write outcome may be unknown', () => { const report = { success: false, createdResources: { fleetAcceptance: { marker: 'M', stage: 'FULL_COVERAGE', status: 'CHECKING', tripNo: 'T', originalDispatch: { dispatchNo: 'D' } }, fleetTrips: [{ tripNo: 'T', dispatchNo: 'D' }], fleetFeeCoverageCases: [{ mode: 'FULL', marker: 'M', dispatchNo: 'D', proof: { status: 'CHECKING', requests: [{ method: 'GET' }] } }], } } assert.equal(reviewedFullCheckpoint(report).marker, 'M') const mutated = structuredClone(report) mutated.createdResources.fleetFeeCoverageCases[0].proof.requests.push({ method: 'POST' }) assert.throws(() => reviewedFullCheckpoint(mutated), /unknown outcomes/) mutated.createdResources.fleetFeeCoverageCases[0].proof.requests.pop() mutated.createdResources.fleetFeeCoverageCases[0].proof.outboundNo = 'OUT-1' assert.throws(() => reviewedFullCheckpoint(mutated), /unknown outcomes/) assert.throws(() => reviewedFullCheckpoint(mutated, 'FULL_COVERAGE_PERSISTED'), /exact successful command/) Object.assign(mutated.createdResources.fleetFeeCoverageCases[0].proof, { deliveryNos: ['DEL-1'], confirmationRequest: { idempotencyKey: 'original-key' } }) mutated.createdResources.fleetFeeCoverageCases[0].proof.requests.push({ label: '正式保存本次原费用服务覆盖并转派送', method: 'POST', http: 200, code: '200' }) assert.equal(reviewedFullCheckpoint(mutated, 'FULL_COVERAGE_PERSISTED').persisted, true) }) test('receipt-ready reconciliation cannot repeat a receipt that has already started', () => { const report = { success: false, steps: [{ name: '创建海外PDA仓库操作员71', code: 'A0409', message: '手机号已存在' }], createdResources: { fleetAcceptance: { marker: 'M', stage: 'RESERVATIONS', status: 'CHECKING', tripNo: 'T' }, fleetTrips: [{ tripNo: 'T', dispatchNo: 'D2', reservation: { status: 'VERIFIED' } }], fleetFeeCoverageCases: [{ mode: 'FULL', proof: { status: 'VERIFIED' } }, { mode: 'PARTIAL', dispatchNo: 'D2', proof: { status: 'VERIFIED' } }], } } assert.equal(reviewedFullCheckpoint(report, 'EXTERNAL_RECEIPT_READY').receiptReady, true) report.createdResources.fleetTrips[0].externalReceipt = { status: 'CHECKING' } assert.throws(() => reviewedFullCheckpoint(report, 'EXTERNAL_RECEIPT_READY'), /no receipt writes/) }) test('palletized checkpoint requires a saved successful command, owned operator, and no later confirmation', () => { const report = { success: false, createdResources: { fleetAcceptance: { marker: 'M', stage: 'EXTERNAL_RECEIPT', status: 'CHECKING', tripNo: 'T', picker: { membershipId: '71' }, pickerMarker: 'M-PDA' }, fleetTrips: [{ tripNo: 'T', dispatchNo: 'D2', reservation: { status: 'VERIFIED' }, externalReceipt: { status: 'CHECKING', warehousePalletId: 'P1', palletizeRequest: { idempotencyKey: 'original' }, requests: [ { label: 'PDA正式完成外接收货及库存入账', method: 'POST', http: 200, code: '200' }, ] } }], fleetFeeCoverageCases: [{ mode: 'FULL', proof: { status: 'VERIFIED' } }, { mode: 'PARTIAL', dispatchNo: 'D2', proof: { status: 'VERIFIED' } }], } } assert.equal(reviewedFullCheckpoint(report, 'EXTERNAL_PALLETIZED').palletized, true) assert.throws(() => reviewedFullCheckpoint(report, 'EXTERNAL_RECEIPT_CONFIRMED'), /exact successful PDA command/) const confirmed = structuredClone(report) confirmed.createdResources.fleetTrips[0].externalReceipt.receiptRequest = { idempotencyKey: 'confirm-original' } assert.throws(() => reviewedFullCheckpoint(confirmed, 'EXTERNAL_RECEIPT_CONFIRMED'), /exact successful PDA command/) confirmed.createdResources.fleetTrips[0].externalReceipt.requests.push({ label: '运营按实际1托位和新单价30确认实收', method: 'POST', http: 200, code: '200' }) assert.equal(reviewedFullCheckpoint(confirmed, 'EXTERNAL_RECEIPT_CONFIRMED').receiptConfirmed, true) assert.throws(() => reviewedFullCheckpoint(confirmed, 'EXTERNAL_PALLETIZED'), /exact successful PDA command/) for (const mutate of [ r => { r.fleetTrips[0].externalReceipt.requests[0].code = 'A0409' }, r => { delete r.fleetTrips[0].externalReceipt.palletizeRequest.idempotencyKey }, r => { delete r.fleetAcceptance.picker }, r => { r.fleetTrips[0].externalReceipt.receiptRequest = { idempotencyKey: 'later' } }, r => { r.fleetTrips[0].externalDispatch = { status: 'CHECKING' } }, ]) { const invalid = structuredClone(report); mutate(invalid.createdResources) assert.throws(() => reviewedFullCheckpoint(invalid, 'EXTERNAL_PALLETIZED'), /exact successful PDA command/) } }) function terminalFixture(fault = '') { const finalTrip = { status: 'COMPLETED', completedAt: '2026-10-02T22:01:00Z', recordVersion: '30', vehicleRelease: { endLocation: 'ONT8' }, driverRelease: { endLocation: 'ONT8' } } const closure = { status: 'CARGO_COMPLETED_AND_RESOURCES_RELEASED', finalTrip, probes: [{ tripNo: 'PROBE' }] } const trip = { tripNo: 'T', closure, externalReceipt: { status: 'VERIFIED' }, reassignment: { status: 'VERIFIED' }, externalDispatch: { status: 'VERIFIED', dispatchNo: 'EXT', deliveryNo: 'DEL-EXT' } } const proof = { marker: 'M', tripNo: 'T', customerId: '92', stage: 'RECEIPTS_AND_RESOURCE_RELEASE', closure, receipts: ['DEL-OWN', 'DEL-EXT'].map(deliveryNo => ({ deliveryNo, signedAt: '2026-10-02T22:00:00' })), departure: { shippedPackages: 6 }, finance: { status: 'CONSUMER_PERSISTED', source: { sourceFeeId: 'F1', sourceVersion: 1 } } } const resources = { fleetAcceptance: proof, fleetTrips: [trip], fleetFeeCoverageCases: [{ mode: 'PARTIAL', dispatchNo: 'OWN', proof: { deliveryNos: ['DEL-OWN'] } }] } const calls = [] const context = { createdResources: resources, assert() {}, async request(method, path) { calls.push({ method, path }); assert.equal(method, 'GET') let data if (path.endsWith('/trips/T')) data = { trip: finalTrip, dispatches: ['OWN', 'EXT'].map(dispatchNo => ({ dispatchNo })) } else if (path.endsWith('/trips/PROBE')) data = { trip: { status: 'CANCELLED' } } else if (path.includes('/dispatches/')) { const number = path.split('/').at(-1), count = number === 'OWN' ? 5 : 1 data = { dispatchNo: number, status: 'DEPARTED', packageCount: count, pickedPackageCount: count, shippedPackageCount: fault === 'quantity' ? 0 : count } } else if (path.includes('/delivery-orders/')) data = { order: { deliveryNo: path.split('/').at(-1).split('?')[0], status: fault === 'unsigned' ? 'WAIT_DELIVERY' : 'DELIVERED', signedAt: '2026-10-02T22:00:00' } } else if (path.includes('/fee-pool?')) data = [{ customerId: '92', sourceId: 'F1', sourceVersion: fault === 'wrong-fee-version' ? 2 : 1, amount: 30, currency: 'CNY', sourceType: 'OVERSEAS_DELIVERY_FEE' }] else throw Error('unexpected path') return { http: 200, body: { code: '200', data: structuredClone(data) }, requestId: 'r', traceId: 't' } } } return { context, calls, report: { success: false, createdResources: resources, steps: [{ name: '本次车次货物结案及车辆司机释放完成', passed: false }] } } } test('terminal reconciliation reads actual completion, every dispatch/delivery and exact fee without replaying writes', async () => { const f = terminalFixture() assert.equal(reviewedFullCheckpoint(f.report, 'TERMINAL_READONLY').terminal, true) const result = await verifyFleetTerminalState(f.context) assert.equal(result.terminalReadback.status, 'VERIFIED') assert.equal(f.calls.length, 7) assert.ok(f.calls.every(row => row.method === 'GET')) const invalid = terminalFixture().report invalid.steps.push({ name: '真实业务失败', passed: false }) assert.throws(() => reviewedFullCheckpoint(invalid, 'TERMINAL_READONLY'), /known aggregate assertion/) }) for (const fault of ['quantity', 'unsigned', 'wrong-fee-version']) test(`terminal readback rejects ${fault}`, async () => { const f = terminalFixture(fault) await assert.rejects(() => verifyFleetTerminalState(f.context)) assert.equal(f.context.createdResources.fleetAcceptance.terminalReadback.status, 'CHECKING') })