@@ -66,6 +66,10 @@ const {
6666const {
6767 readTargetDataReconciliationEvidenceForPaths,
6868} = require ( '../dist/deployment/cutover/targetDataEvidence.js' ) ;
69+ const {
70+ adoptedTargetBaselinePath,
71+ createAdoptedTargetBaseline,
72+ } = require ( '../dist/deployment/cutover/targetBaseline.js' ) ;
6973const {
7074 targetRunJournalRecord,
7175 targetStopPhasePath,
@@ -121,6 +125,7 @@ function fixture(
121125 stoppedAuthority = 'docker' ,
122126 profile = 'edge' ,
123127 createDefaultSidecars = true ,
128+ useAdoptedTargetBaseline = false ,
124129 initializeDatabases,
125130 mutateTarget,
126131 } = { } ,
@@ -323,6 +328,32 @@ function fixture(
323328 } ;
324329 const applicationContents = `${ JSON . stringify ( application , null , 2 ) } \n` ;
325330 fs . writeFileSync ( applicationConfigPath , applicationContents , { mode : 0o600 } ) ;
331+ let adoptedTargetBaseline ;
332+ if ( useAdoptedTargetBaseline ) {
333+ adoptedTargetBaseline = createAdoptedTargetBaseline ( {
334+ preparedAtMs : 1_350 ,
335+ profile,
336+ instanceId : 'edge-router-1' ,
337+ cutoverId,
338+ activationDigest,
339+ commitmentDigest,
340+ applicationConfigDigest : crypto
341+ . createHash ( 'sha256' )
342+ . update ( applicationContents , 'utf8' )
343+ . digest ( 'hex' ) ,
344+ legacyDataApplicationCommitDigest : dataCommit . commitDigest ,
345+ legacyDataApplicationReceiptDigest : dataCommit . receiptDigest ,
346+ targetPathDigest : activationPayload . targetPathDigest ,
347+ targetDevice : activationPayload . targetDevice ,
348+ targetInode : activationPayload . targetInode ,
349+ targetSha256 : activationPayload . targetSha256 ,
350+ } ) ;
351+ fs . writeFileSync (
352+ adoptedTargetBaselinePath ( deploymentRoot ) ,
353+ `${ JSON . stringify ( adoptedTargetBaseline ) } \n` ,
354+ { mode : 0o600 } ,
355+ ) ;
356+ }
326357 const adoptedBundlePayload = {
327358 schemaVersion : 1 ,
328359 kind : 'qinglong3-local-adopted-deployment-bundle' ,
@@ -397,6 +428,16 @@ function fixture(
397428 legacySourcePath,
398429 targetDatabasePath,
399430 expectedActivationDigest : activationDigest ,
431+ ...( adoptedTargetBaseline === undefined
432+ ? { }
433+ : {
434+ adoptedTargetBaseline : {
435+ baselineDigest : adoptedTargetBaseline . baselineDigest ,
436+ targetDevice : adoptedTargetBaseline . targetDevice ,
437+ targetInode : adoptedTargetBaseline . targetInode ,
438+ targetSha256 : adoptedTargetBaseline . targetSha256 ,
439+ } ,
440+ } ) ,
400441 } ,
401442 uid ,
402443 ) ;
@@ -514,6 +555,8 @@ function fixture(
514555 legacySourcePath,
515556 targetDatabasePath,
516557 recoveryPath,
558+ adoptedTargetBaseline,
559+ reconciliation,
517560 } ;
518561}
519562
@@ -587,6 +630,42 @@ test('capture prepare rejects rollback-candidate stopped data', (t) => {
587630 ) ;
588631} ) ;
589632
633+ test ( 'capture prepare preserves exact adopted-target baseline evidence' , ( t ) => {
634+ const state = fixture ( t , {
635+ createDefaultSidecars : false ,
636+ useAdoptedTargetBaseline : true ,
637+ } ) ;
638+ assert . ok ( state . adoptedTargetBaseline ) ;
639+ assert . equal ( state . reconciliation . baselineKind , 'adopted_target' ) ;
640+ assert . equal (
641+ state . reconciliation . baselineDigest ,
642+ state . adoptedTargetBaseline . baselineDigest ,
643+ ) ;
644+ assert . equal ( state . reconciliation . targetMatchesBaseline , false ) ;
645+ const prepared = prepareLocalReconciliationCapture ( state . command ) ;
646+ assert . equal ( prepared . status , 'prepared' ) ;
647+ assert . equal ( prepared . state , 'reconciliation_capture_prepared' ) ;
648+ } ) ;
649+
650+ test ( 'capture prepare rejects a valid but detached adopted-target baseline' , ( t ) => {
651+ const state = fixture ( t , {
652+ createDefaultSidecars : false ,
653+ useAdoptedTargetBaseline : true ,
654+ } ) ;
655+ const baselinePath = adoptedTargetBaselinePath ( state . deploymentRoot ) ;
656+ const detachedBaseline = createAdoptedTargetBaseline ( {
657+ ...state . adoptedTargetBaseline ,
658+ targetSha256 : 'f' . repeat ( 64 ) ,
659+ } ) ;
660+ fs . writeFileSync ( baselinePath , `${ JSON . stringify ( detachedBaseline ) } \n` , {
661+ mode : 0o600 ,
662+ } ) ;
663+ assert . throws (
664+ ( ) => prepareLocalReconciliationCapture ( state . command ) ,
665+ / a d o p t e d t a r g e t b a s e l i n e i s d e t a c h e d f r o m s t o p p e d e v i d e n c e / ,
666+ ) ;
667+ } ) ;
668+
590669test ( 'service-manager stopped authority uses the same capture fence' , ( t ) => {
591670 const state = fixture ( t , { stoppedAuthority : 'service-manager' } ) ;
592671 const prepared = prepareLocalReconciliationCapture ( state . command ) ;
0 commit comments