import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' import { normalizeModuleOrder } from '../admin-test-env-acceptance.mjs' import { run } from './phase4-cross-region-events.mjs' const source = readFileSync(new URL('./phase4-cross-region-events.mjs', import.meta.url), 'utf8') const system = readFileSync(new URL('./system.mjs', import.meta.url), 'utf8') test('cross-region denial probes the current domestic container detail route', () => { assert.ok(source.includes('/api/platform/v1/containers/domestic/${encodeURIComponent(id(phase3.containerBookingId))}')) assert.ok(!source.includes('/api/platform/v1/containers/${encodeURIComponent(id(phase3.containerBookingId))}')) }) function response(path, data, http = 200, code = '200') { return { method: 'GET', path, http, body: { code, data }, requestId: 'request-1', traceId: 'trace-1' } } function context(resources = {}) { const steps = [] const gaps = [] const calls = [] return { marker: 'MARKER-1', token: 'platform-token', createdResources: resources, steps, gaps, calls, addCoverageGap(module, scenario, name, reason, category, metadata) { gaps.push({ module, scenario, name, reason, category, ...metadata }) }, addStep(module, name, value, passed, evidence, options) { steps.push({ module, name, passed: Boolean(passed), evidence, options }) return Boolean(passed) }, assert(module, name, value, passed, evidence, options) { return this.addStep(module, name, value, passed, evidence, options) }, async request(...args) { const route = /\/(?:last-leg|overseas-warehouse-resources)(?:\/|\?|$)/.test(String(args[1])); const handler = route ? async function(method,path,body,token,headers) { calls.push({ region: 'OVERSEAS', method, path, token: token || this.token }) if (token === '') return response(path, null, 401, 'A0401') if (path.includes('/last-leg/orders/9001')) { return response(path, { order: { id: '9001', containerNo: 'MSCU1234567' } }) } return response(path, { records: [{ id: '7001', containerNo: 'MSCU1234567' }] }) } : async function(method,path,body,token) { calls.push({ region: 'CN', method, path, token: token || this.token }) if (token === '') return response(path, null, 401, 'A0401') if (path.includes('/overview')) return response(path, { container: { id: '3001', containerNo: 'MSCU1234567', unloadingCompletedAt: '2026-08-24T10:00:00Z', unloadingPhotoUploadedAt: '2026-08-24T09:00:00Z', estimatedEmptyReportedAt: '2026-08-27T10:00:00Z', actualEmptyReportedAt: null, emptyReportSourceVersion: 7, } }) return response(path, { records: [{ container: { id: '3001', containerNo: 'MSCU1234567' } }] }) }; return handler.apply(this,args); }, } } test('entry orders marker-owned prerequisites before cross-region acceptance', () => { const modules = normalizeModuleOrder(['phase4-cross-region-events']) const cross = modules.indexOf('phase4-cross-region-events') for (const prerequisite of ['system', 'phase3-loading-finalize', 'phase4-overseas-pda']) { assert.ok(modules.indexOf(prerequisite) >= 0 && modules.indexOf(prerequisite) < cross, prerequisite) } }) test('cross-region normalization keeps existing producers ahead of every phase-three consumer', () => { const requested = [ 'merchant-qualification-fixture', 'orders', 'inbound-measurement', 'phase3-container-loading', 'phase3-loading-model-bridge', 'phase3-loading', 'ocean-bookings', 'phase3-loading-finalize', 'phase3-customs', 'phase3-outbound-dispatch', 'phase3-outbound-aggregate', 'phase4-overseas-pda', 'phase4-cross-region-events', ] const modules = normalizeModuleOrder(requested) for (const [producer, consumer] of [ ['merchant-qualification-fixture', 'orders'], ['orders', 'inbound-measurement'], ['inbound-measurement', 'phase3-container-loading'], ['phase3-container-loading', 'phase3-loading'], ['phase3-loading', 'phase3-loading-model-bridge'], ['phase3-loading', 'ocean-bookings'], ['phase3-loading-finalize', 'phase3-customs'], ['phase3-customs', 'phase3-outbound-dispatch'], ['phase3-outbound-dispatch', 'phase3-outbound-aggregate'], ['phase4-overseas-pda', 'phase4-cross-region-events'], ]) assert.ok(modules.indexOf(producer) < modules.indexOf(consumer), `${producer} -> ${consumer}`) assert.deepEqual(normalizeModuleOrder(modules), modules) }) test('phase-four producer variants restore the primary orchestration fixture after each matrix branch', async () => { const source = await import('node:fs/promises').then((fs) => fs.readFile( new URL('../admin-test-env-acceptance.mjs', import.meta.url), 'utf8')) const start = source.indexOf('const createdKeys = [', source.indexOf('async runPhase4ProducerVariant')) const end = source.indexOf(']', start) const createdKeys = source.slice(start, end) for (const key of [ 'phase3Loading', 'phase3LoadingCompletedProducer', 'orchestrationFixtures', 'oceanBooking', 'phase3CustomsSupplier', 'phase3Customs', 'serviceCenterFlow', 'portSchedule', 'phase3OutboundDispatch', 'phase3CarrierScheduleQuery', 'phase4CarrierPickupReady', ]) assert.match(createdKeys, new RegExp(`'${key}'`)) }) test('cross-region producers do not repeat the destructive A0 snapshot mutation', async () => { const source = await import('node:fs/promises').then((fs) => fs.readFile( new URL('../admin-test-env-acceptance.mjs', import.meta.url), 'utf8')) const variantStart = source.indexOf('async runPhase4ProducerVariant') const fixtureCall = source.slice(variantStart, source.indexOf('const loading =', variantStart)) assert.match(fixtureCall, /preparePhase3LoadingFixture\('', false\)/) }) test('tail controls receive their own completed producer matrix before they consume it', async () => { const entry = await import('node:fs/promises').then((fs) => fs.readFile( new URL('../admin-test-env-acceptance.mjs', import.meta.url), 'utf8')) assert.match(entry, /module === 'phase4-tail-order-controls' \|\| module === 'phase4-overseas-pda'/) assert.match(entry, /await this\.ensurePhase4PdaProducerMatrix\(\)/) }) test('contract covers unified session, canonical 403, both event directions and diagnostics', () => { for (const token of [ '无会话不得访问Lastleg', '同一平台会话可访问国内授权详情', 'cn-overseas-event-not-delivered', 'overseas-cn-event-not-delivered', 'requestId=', 'traceId=', 'pollRequests=', '非事件重放证据', 'missing-direct-delivery-replay-evidence', ]) assert.ok(source.includes(token), token) assert.match(system, /缺少canonical海外订单权限必须403/) assert.match(system, /restrictedOverseasToken/) }) test('full observable cross-region flow performs requests and passes', async () => { const ctx = context({ phase3Loading: { marker: 'MARKER-1', finalizeSucceeded: true, containerBookingId: '3001', containerNo: 'MSCU1234567', loadingPlanId: '4001' }, phase4OverseasPda: { marker: 'MARKER-1', finalStatus: 'COMPLETED', customerId: '100', orderId: '9001' }, }) await assert.rejects(() => run(ctx), /missing|真实投递重试与同事件幂等证据/) assert.ok(ctx.calls.length >= 8) assert.equal(ctx.steps.filter((step) => !step.name.includes('真实投递')).every((step) => step.passed), true) assert.equal(ctx.gaps.length, 1) assert.equal(ctx.gaps[0].category, 'missing-direct-delivery-replay-evidence') assert.ok(ctx.calls.some((call) => call.region === 'CN' && call.token === 'platform-token')) assert.ok(ctx.calls.some((call) => call.region === 'OVERSEAS' && call.token === 'platform-token')) }) test('missing marker fixture is a blocking coverage gap after real security request', async () => { const ctx = context() await assert.rejects(() => run(ctx), /blocking coverage gap/) assert.ok(ctx.calls.length > 0) assert.equal(ctx.gaps.length, 1) assert.equal(ctx.gaps[0].deploymentBlocker, true) assert.equal(ctx.steps.some((step) => !step.passed && step.options?.deploymentBlocker), true) })