2026-10-05 00:37:18 +08:00
// 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 )
}
2026-10-08 17:07:57 +08:00
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.' }
}
2026-10-05 00:37:18 +08:00
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.' })
2026-10-08 17:07:57 +08:00
result . nodes . push ({ ... discardCoverageBoundary (), evidenceFiles : [ files [ 5 ]] })
2026-10-05 00:37:18 +08:00
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
}