// Internal evidence helper; invoked explicitly by the assigned audit, never runs on import. import fs from 'node:fs' import path from 'node:path' import crypto from 'node:crypto' export const digest = value => crypto.createHash('sha256').update(typeof value === 'string' ? value : JSON.stringify(value)).digest('hex') export function selectSteps(report, predicate) { return (report.steps || []).flatMap((step, index) => predicate(step) ? [{ pointer: `/steps/${index}`, ...step }] : []) } export function requirePassed(steps) { return steps.length > 0 && steps.every(s => s.passed === true) } export function discardCoverageBoundary() { return { node: 'F33-discard', conclusion: 'Historical rejection-release evidence is retained. Current approval keeps reservations; actual PDA confirmation deducts the confirmed quantity. Approval alone does not prove completion.', category: '需真实操作', next: 'Prepare a fresh owned approved application and bound PDA actor; freeze carton/SKU/ledger evidence. Verify actual confirmation, final-pallet response recovery, identical replay with zero new writes, changed quantity rejection, and warehouse confirmation separately. Do not deduct stock at approval or borrow unrelated completed samples.' } } export function transferConclusion(detail) { const shipped = Boolean(detail.actualShipAt) const terminal = detail.status === 'RECEIVED' const received = (detail.allocations || []).length > 0 && detail.allocations.every(a => a.status === 'RECEIVED' && a.destinationInventoryPositionId) return { status: detail.status, orderStatus: detail.orderStatus, transferNo: detail.transferNo, allocationCount: detail.allocations?.length || 0, packageCount: detail.packageCount, sourceCount: detail.sourceOrders?.length || 0, actualShipAt: detail.actualShipAt || null, completed: terminal && shipped && received, requiresRealOperation: !(terminal && shipped && received) } } export async function auditRemainingNodes({ root, output, env, live = false }) { if (fs.existsSync(output)) throw Error('REPORT_EXISTS_NO_OVERWRITE') const read = relative => JSON.parse(fs.readFileSync(path.join(root, relative), 'utf8')) const files = ['reports/node-completion-audit-root-20261004-r1.json', 'reports/admin-full-current-20261002-r4.json', 'reports/overseas-receiving-current-20261002-r1.json', 'reports/fba-core-f40-tax-fleet-20261003-r1/root_first.json', 'reports/f26-loaded-transit-verification-20261004-r2.json', 'reports/discard-review-entry-root-20261004-r1/final-evidence.json'] const reports = Object.fromEntries(files.map(f => [f, read(f)])) const full = reports[files[1]] const evidence = (file, predicate) => ({ file, sha256: digest(fs.readFileSync(path.join(root, file), 'utf8')), steps: selectSteps(reports[file], predicate) }) const result = { checkedAt: new Date().toISOString(), goalComplete: false, scope: 'Existing TEST evidence only; no business commands, SQL, fault injection, deployment or UI operation', sourceFiles: files.map(file => ({ file, sha256: digest(fs.readFileSync(path.join(root, file), 'utf8')) })), integrationRequired: { file: 'scripts/README.md', owner: '总控', reason: 'Current write boundary excludes shared script index; documentation contract identifies this new helper as undocumented.', text: '`scripts/fba-remaining-nodes-acceptance.mjs`:本轮FBA剩余节点内部证据助手,仅显式调用auditRemainingNodes;读取指定原报告并按JSON pointer/SHA-256保留证据。live=true仅使用明确TEST环境文件的独立Auth会话与串行GET,正常退出;不执行业务写命令、SQL、故障注入、部署或页面操作。报告reports/fba-remaining-nodes-20261004/,既有报告拒绝覆盖,失败保留且不自动重试。对应离线测试fba-remaining-nodes-acceptance.test.mjs。' }, nodes: [], requests: [], sessionClosed: !live } result.nodes.push({ node: 'F23.2', conclusion: 'HTTP actual AT_ORIGIN_PORT supported; Admin save and two-end projection remain unverified', category: '需真实操作', evidence: [evidence(files[3], s => /AT_ORIGIN_PORT/.test(s.name))], next: 'Use a current not-yet-at-origin-port sample; freeze query version/history and customer projection, record actual node once through Admin, capture POST and both readbacks; preserve customs/container identity and do not rewrite a later actual node.' }) result.nodes.push({ node: 'F25', conclusion: 'Clearance/DO upload and replay, fleet/appointment/empty-return supported; PU, distinct actual pickup and mail lifecycle unverified', category: '需真实操作', evidence: [evidence(files[1], s => s.module === 'phase5-terminal-drayage'), evidence(files[1], s => s.module === 'phase3-container-documents' && /DELIVERY_ORDER|DESTINATION_CLEARANCE/.test(s.name))], boundaries: { mailRequestsInOriginalReport: full.steps.filter(s => /terminal-drayages.*\/emails?|terminal-drayages.*pickup-email/.test(s.request?.path || '')).length, pickupAssertion: 'Original drayage assertion compares actualPickupAt to unloadingCompletedAt; this does not establish a distinct pickup command/time.' }, next: 'Freeze pre-pickup container and actual node history; inspect current DO/PU contract, confirm distinct PICKED_UP before unloading; capture explicit email queue/recipient snapshot, SMTP acceptance separately, fleet-change ordered cancellation/request and failed-mail retry without assuming delivery.' }) result.nodes.push({ node: 'F27', conclusion: 'Normal conversion/resources/replay supported; resource-failure retry UI unverified', category: '需真实操作', evidence: [evidence(files[1], s => s.module === 'phase4-tail-order-controls')], explicitRetryEvidence: selectSteps(full, s => /资源.*重试|计划.*重试|重试.*资源/.test(s.name)), next: 'First locate a real resourcePendingPlanCount>0 container; freeze plans, reservations, resource identities and original command key. Use original container conversion UI retry once, verify only failed resources finish and no new plans/reservations; healthy completed samples cannot prove recovery. Failure injection requires controller window.' }) result.nodes.push({ node: 'F33-transfer', conclusion: 'Original stock transfer approved; outbound/target receipt terminal not established', category: '需真实操作', originalTransferNo: 'WT-WH-20261002-430594', evidence: [evidence(files[1], s => (s.request?.path || '').includes('WT-WH-20261002-430594'))], originalFixture: full.createdResources.phase4OverseasClientServices, next: 'Continue this exact original transfer only after current source stock, holds, destination and allocations are frozen. Verify allocation, actual outbound and target receipt with per-position balances/unique movements and same-command replay. Incoming transfer fixtures are separate sources and cannot replace this ticket.' }) result.nodes.push({ ...discardCoverageBoundary(), evidenceFiles: [files[5]] }) result.nodes.push({ node: 'F26', conclusion: 'Existing 68-check source/transit scope is already evidenced; no repeat run', category: '可立即关闭指定分支', evidenceFiles: [files[4]], boundary: 'Only 11 FBA sources/13 actual cartons and pre-receipt mapping; not all event faults or UI.' }) result.nodes.push({ node: 'F24-external', conclusion: 'External carrier lifecycle lacks valid input', category: '缺用户输入', next: 'Provide valid carrier TEST input; synthetic fixture or manual nodes cannot close supplier lifecycle.' }) const save = () => { fs.mkdirSync(path.dirname(output), { recursive: true }); fs.writeFileSync(output, JSON.stringify(result, null, 2)) } save() if (!live) return result let session const call = async (method, route, body, token = session?.accessToken) => { if (method !== 'GET' && !['/auth/login', '/auth/logout'].includes(route)) throw Error('BUSINESS_WRITE_FORBIDDEN') const entry = { method, path: route, phase: 'INTENT' }; result.requests.push(entry); save() const response = await fetch(env.CHONGCHONG_ADMIN_API_BASE_URL.replace(/\/$/, '') + route, { method, redirect: 'error', signal: AbortSignal.timeout(20000), headers: { Accept: 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), ...(body === undefined ? {} : { 'Content-Type': 'application/json' }) }, ...(body === undefined ? {} : { body: JSON.stringify(body) }) }) const json = JSON.parse(await response.text()) Object.assign(entry, { phase: 'ACKNOWLEDGED', http: response.status, code: String(json.code), requestId: response.headers.get('x-request-id'), traceId: response.headers.get('x-trace-id') }); save() if (response.status !== 200 || String(json.code) !== '200') throw Error(`READ_FAILED_${response.status}_${json.code}`) return json.data } try { if (String(env.CHONGCHONG_ENV).toUpperCase() !== 'TEST' || !env.CHONGCHONG_ADMIN_API_BASE_URL || !env.CHONGCHONG_ADMIN_USERNAME || !env.CHONGCHONG_ADMIN_PASSWORD) throw Error('EXPLICIT_TEST_ENV_REQUIRED') session = await call('POST', '/auth/login', { loginId: env.CHONGCHONG_ADMIN_USERNAME, password: env.CHONGCHONG_ADMIN_PASSWORD }, '') const transferRoute = '/platform/v1/last-leg/warehouse-transfers/WT-WH-20261002-430594?customerId=2105875471489142785' const before = await call('GET', transferRoute) if (before.transferNo !== 'WT-WH-20261002-430594') throw Error('TRANSFER_SCOPE_MISMATCH') result.nodes.find(n => n.node === 'F33-transfer').current = transferConclusion(before) const container = full.createdResources.phase5TerminalDrayage.containerBookingId const drayage = await call('GET', `/platform/v1/terminal-drayages/${container}`) const history = await call('GET', `/platform/v1/terminal-drayages/${container}/history`) const mailbox = await call('GET', `/platform/v1/terminal-drayages/${container}/emails`) result.nodes.find(n => n.node === 'F25').current = { containerNo: drayage.containerNo, status: drayage.status, actualPickupAt: drayage.actualPickupAt, unloadingCompletedAt: drayage.unloadingCompletedAt, actualEmptyReturnAt: drayage.actualEmptyReturnAt, pickupEqualsUnloading: drayage.actualPickupAt === drayage.unloadingCompletedAt, historyActions: history.map(h => h.action), mailboxCount: mailbox.records?.length || 0, mailStatuses: (mailbox.records || []).map(m => ({ status: m.status, kind: m.kind })) } const overview = await call('GET', `/platform/v1/containers/overseas/${container}/overview`) Object.assign(result.nodes.find(n => n.node === 'F25').current, { pickupCodePresent: Boolean(overview.container?.pickupCode), documents: (overview.documents || []).map(d => ({ documentType: d.documentType, version: d.version, filePresent: Boolean(d.fileId), completed: d.completed === true })) }) const preview = await call('GET', `/platform/v1/last-leg/inbound-plans/container-preview?sourceContainerBookingId=${container}`) result.nodes.find(n => n.node === 'F27').current = { containerNo: preview.containerNo, totalOrderCount: preview.totalOrderCount, pendingOrderCount: preview.pendingOrderCount, blockedOrderCount: preview.blockedOrderCount, totalPlannedPalletCount: preview.totalPlannedPalletCount, plans: (preview.groups || []).flatMap(g => (g.orders || []).map(o => ({ planNo: o.existingPlanNo, planStatus: o.planStatus }))), recoveryProven: false } const after = await call('GET', transferRoute) result.transferReadStable = digest(before) === digest(after) result.liveReadSuccess = result.transferReadStable } catch (error) { result.liveReadSuccess = false; result.failure = String(error.message).replace(/https?:\/\/\S+/g, '[redacted]') } finally { if (!session) result.sessionClosed = true if (session) { try { await call('POST', '/auth/logout', { refreshToken: session.refreshToken }); result.sessionClosed = true } catch { result.sessionClosed = false; result.liveReadSuccess = false } } save() } return result }