feat(dispatch): unify whole vehicle scheduling, source ownership and staged execution
This commit is contained in:
@@ -14,7 +14,7 @@ function harness(root, fail = false) {
|
||||
calls.push({ method, path })
|
||||
const data = path === '/api/auth/login' ? { accessToken: 'private-access', refreshToken: 'private-refresh' }
|
||||
: path.includes('warehouse-options') ? [{ id: '900' }] : {}
|
||||
return { http: 200, body: { code: '200', data } }
|
||||
return { http: 200, body: { code: '200', data }, requestId: 'offline-request', traceId: 'offline-trace' }
|
||||
}, async requestWithBody() { throw Error('Unexpected multipart') } }
|
||||
return { calls, cleanup, context, options: { env, outputRoot: root, contextFactory: () => context,
|
||||
readers: { preflight: async () => {}, readFleetInventory: async scope => ({ scope, balances: [], positions: [], ledger: [] }) },
|
||||
@@ -24,11 +24,13 @@ function harness(root, fail = false) {
|
||||
assert.equal(options.pdaToken, 'private-pda')
|
||||
await context.request('POST', '/api/test-owned-command', { idempotencyKey: 'stable-command', password: 'private-pda-password' })
|
||||
if (fail) throw Error('FIXTURE_FAILED')
|
||||
return { pdaToken: options.pdaToken, marker: context.marker, tripNo: 'TR-OFFLINE', members: [{ customerId: '42' }, { customerId: '43' }] }
|
||||
const tripProof = { marker: 'FT-OWNED', dispatchNo: 'DS-ONE', tripNo: 'TR-OFFLINE', warehouseId: '900' }
|
||||
context.createdResources.fleetTrips = [tripProof]
|
||||
return { pdaToken: options.pdaToken, marker: context.marker, dispatchNo: 'DS-ONE', tripNo: 'TR-OFFLINE', warehouseId: '900', tripProof,
|
||||
members: ['42', '43'].map(customerId => ({ customerId, marker: context.marker, dispatchNo: 'DS-ONE', receiptVerified: true })) }
|
||||
}, verify: async (_context, _fixture, options) => {
|
||||
await options.readInventory({ marker: context.marker, customerId: '42', warehouseId: '900' })
|
||||
context.createdResources.fleetCrossCustomer = { status: 'VERIFIED', tripNo: 'TR-OFFLINE' }
|
||||
context.createdResources.fleetTrips = [{ tripNo: 'TR-OFFLINE' }]
|
||||
context.createdResources.fleetCrossCustomer = { marker: context.marker, dispatchNo: 'DS-ONE', status: 'VERIFIED', tripNo: 'TR-OFFLINE' }
|
||||
return context.createdResources.fleetCrossCustomer
|
||||
},
|
||||
finish: async (_context, _module, trip) => { trip.closure = { status: 'CARGO_COMPLETED_AND_RESOURCES_RELEASED' } },
|
||||
@@ -82,7 +84,7 @@ test('operator creation followed by login failure still disables the newly creat
|
||||
try {
|
||||
const h = harness(root), original = h.context.request
|
||||
h.context.request = async function (...args) {
|
||||
if (args[1] === '/api/platform/v1/iam/users') return { http: 200, body: { code: '200', data: { membershipId: '82' } } }
|
||||
if (args[1] === '/api/platform/v1/iam/users') return { http: 200, body: { code: '200', data: { membershipId: '82' } }, requestId: 'offline-request', traceId: 'offline-trace' }
|
||||
return original.apply(this, args)
|
||||
}
|
||||
h.options.pickerCreate = async context => {
|
||||
@@ -99,3 +101,88 @@ test('operator creation followed by login failure still disables the newly creat
|
||||
rmSync(root, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
for (const [verificationScope, proofKey] of [['CROSS_CUSTOMER', 'fleetCrossCustomer'], ['CAPACITY_POOL', 'fleetCapacityPool'], ['SAME_ROUTE_COST', 'fleetSameRouteCost']]) {
|
||||
test(`explicit ${verificationScope} requires its own authoritative native proof`, async () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'fleet-cross-contract-'))
|
||||
try {
|
||||
const h = harness(root); h.options.verificationScope = verificationScope
|
||||
h.options.verify = async (context, fixture) => {
|
||||
const proof = { marker: context.marker, dispatchNo: fixture.dispatchNo, tripNo: fixture.tripNo, status: 'VERIFIED' }
|
||||
context.createdResources[proofKey] = proof; return proof
|
||||
}
|
||||
const report = await runCrossCustomer(config(), h.options)
|
||||
assert.equal(report.success, true); assert.equal(report.verificationScope, verificationScope)
|
||||
} finally { assert.equal(dirname(resolve(root)), resolve(tmpdir())); assert.ok(basename(root).startsWith('fleet-cross-contract-')); rmSync(root, { recursive: true, force: true }) }
|
||||
})
|
||||
}
|
||||
|
||||
for (const mismatch of ['wrong scope', 'wrong dispatch', 'wrong marker', 'unregistered proof', 'foreign trip proof']) {
|
||||
test(`native proof mismatch cannot close resources: ${mismatch}`, async () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'fleet-cross-contract-'))
|
||||
try {
|
||||
const h = harness(root); let closed = false
|
||||
if (mismatch === 'foreign trip proof') {
|
||||
const prepare = h.options.prepare
|
||||
h.options.prepare = async (...args) => { const fixture = await prepare(...args); fixture.tripProof = { ...fixture.tripProof }; return fixture }
|
||||
}
|
||||
h.options.verify = async (context, fixture) => {
|
||||
const proof = { marker: mismatch === 'wrong marker' ? 'OTHER' : context.marker,
|
||||
dispatchNo: mismatch === 'wrong dispatch' ? 'DS-OTHER' : fixture.dispatchNo, tripNo: fixture.tripNo, status: 'VERIFIED' }
|
||||
if (mismatch !== 'unregistered proof') context.createdResources[mismatch === 'wrong scope' ? 'fleetCapacityPool' : 'fleetCrossCustomer'] = proof
|
||||
return proof
|
||||
}
|
||||
h.options.finish = async () => { closed = true }
|
||||
const report = await runCrossCustomer(config(), h.options)
|
||||
assert.equal(report.success, false); assert.equal(closed, false); assert.deepEqual(h.cleanup, ['81'])
|
||||
} finally { assert.equal(dirname(resolve(root)), resolve(tmpdir())); assert.ok(basename(root).startsWith('fleet-cross-contract-')); rmSync(root, { recursive: true, force: true }) }
|
||||
})
|
||||
}
|
||||
|
||||
test('native helper checkpoint snapshots and original write intent are durable before HTTP', async () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'fleet-cross-contract-'))
|
||||
try {
|
||||
const h = harness(root), original = h.context.request
|
||||
h.context.request = async function (...args) {
|
||||
if (args[1] === '/api/test-owned-command') {
|
||||
const folder = join(root, 'reports/fleet-cross-offline-one')
|
||||
const progress = JSON.parse(readFileSync(join(folder, 'progress.json'), 'utf8'))
|
||||
assert.equal(progress.createdResources.nativeBeforeSend.dispatchNo, 'DS-ONE')
|
||||
const requests = readdirSync(join(folder, 'requests')).map(name => JSON.parse(readFileSync(join(folder, 'requests', name), 'utf8')))
|
||||
const intent = requests.find(row => row.path === args[1])
|
||||
assert.equal(intent.stage, 'INTENT'); assert.equal(intent.body.idempotencyKey, 'stable-command')
|
||||
}
|
||||
return original.apply(this, args)
|
||||
}
|
||||
const prepare = h.options.prepare
|
||||
h.options.prepare = async (context, options) => {
|
||||
context.createdResources.nativeBeforeSend = { dispatchNo: 'DS-ONE' }; await context.checkpoint()
|
||||
return prepare(context, options)
|
||||
}
|
||||
assert.equal((await runCrossCustomer(config(), h.options)).success, true)
|
||||
} finally { assert.equal(dirname(resolve(root)), resolve(tmpdir())); assert.ok(basename(root).startsWith('fleet-cross-contract-')); rmSync(root, { recursive: true, force: true }) }
|
||||
})
|
||||
|
||||
test('unknown write retains original intent, blocks later business requests and still attempts owned identity cleanup', async () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'fleet-cross-contract-'))
|
||||
try {
|
||||
const h = harness(root), original = h.context.request
|
||||
h.context.request = async function (...args) {
|
||||
if (args[1] === '/api/unknown-command') { h.calls.push({ method: args[0], path: args[1] }); return { http: 503, body: { code: 'S0503' }, requestId: 'offline-request', traceId: 'offline-trace' } }
|
||||
return original.apply(this, args)
|
||||
}
|
||||
h.options.prepare = async context => {
|
||||
await assert.rejects(context.request('POST', '/api/unknown-command', { idempotencyKey: 'original-unknown', recordVersion: '0' }), /Unknown write outcome/)
|
||||
await assert.rejects(context.request('POST', '/api/forbidden-followup', { idempotencyKey: 'must-not-send' }), /Unknown write outcome/)
|
||||
throw Error('UNKNOWN_STOPPED')
|
||||
}
|
||||
const report = await runCrossCustomer(config(), h.options)
|
||||
assert.equal(report.success, false); assert.deepEqual(h.cleanup, ['81']); assert.equal(report.sessionsClosed, true)
|
||||
assert.equal(h.calls.some(row => row.path === '/api/forbidden-followup'), false)
|
||||
const folder = join(root, 'reports/fleet-cross-offline-one/requests')
|
||||
const saved = readdirSync(folder).map(name => JSON.parse(readFileSync(join(folder, name), 'utf8'))).find(row => row.path === '/api/unknown-command')
|
||||
assert.equal(saved.stage, 'UNKNOWN_RESULT'); assert.equal(saved.body.idempotencyKey, 'original-unknown'); assert.equal(saved.body.recordVersion, '0')
|
||||
assert.equal(report.createdResources.fleetWriteBoundary.status, 'STOPPED')
|
||||
} finally { assert.equal(dirname(resolve(root)), resolve(tmpdir())); assert.ok(basename(root).startsWith('fleet-cross-contract-')); rmSync(root, { recursive: true, force: true }) }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user