@@ -553,6 +553,7 @@ func prepareArtifacts(layout ports.ControllerLayout, admission protocol.Admissio
553553}
554554
555555var verifyWorkPackage = workpackage .Verify
556+ var prepareWorkspaceWorkPackageTransferFn = prepareWorkspaceWorkPackageTransfer
556557
557558func capturePinnedWorkPackage (root * os.Root , deliveryID , fingerprint string ) (string , func (), error ) {
558559 repository , err := os .MkdirTemp ("" , "boatstack-work-package-snapshot-" )
@@ -647,7 +648,7 @@ func prepareWorkspacePlanTransfer(repositoryRoot, workspacePath, deliveryID, exp
647648 mutations := []ports.ResourceMutation {planMutation , approvalMutation }
648649 var promotion planPromotionReceipt
649650 if decodeStrictArtifact (approvalRaw , & promotion ) == nil && promotion .SchemaVersion == 2 {
650- packageMutations , packageErr := prepareWorkspaceWorkPackageTransfer (repositoryRoot , workspacePath , deliveryID , promotion .WorkPackageFingerprint )
651+ packageMutations , packageErr := prepareWorkspaceWorkPackageTransferFn (repositoryRoot , workspacePath , deliveryID , promotion .WorkPackageFingerprint , promotion . WorkPackageApprovalFingerprint )
651652 if packageErr != nil {
652653 return nil , packageErr
653654 }
@@ -656,7 +657,7 @@ func prepareWorkspacePlanTransfer(repositoryRoot, workspacePath, deliveryID, exp
656657 return mutations , nil
657658}
658659
659- func prepareWorkspaceWorkPackageTransfer (repositoryRoot , workspacePath , deliveryID , packageFingerprint string ) ([]ports.ResourceMutation , error ) {
660+ func prepareWorkspaceWorkPackageTransfer (repositoryRoot , workspacePath , deliveryID , packageFingerprint , expectedApprovalFingerprint string ) ([]ports.ResourceMutation , error ) {
660661 sourcePath := filepath .Join (repositoryRoot , ".boatstack" , "work-packages" , deliveryID , packageFingerprint )
661662 root , err := os .OpenRoot (sourcePath )
662663 if err != nil {
@@ -680,6 +681,10 @@ func prepareWorkspaceWorkPackageTransfer(repositoryRoot, workspacePath, delivery
680681 if verified .Integrity != workpackage .Valid || verified .Contract != workpackage .Valid || verified .Approval != workpackage .Valid {
681682 return nil , fmt .Errorf ("workspace work package verification failed: %s" , strings .Join (verified .Diagnostics , "; " ))
682683 }
684+ verifiedApproval , err := workpackage .ReadVerifiedApproval (snapshotRepository , deliveryID , packageFingerprint )
685+ if err != nil || verifiedApproval .Approval .Fingerprint != expectedApprovalFingerprint {
686+ return nil , fmt .Errorf ("workspace work package approval does not bind promotion lineage" )
687+ }
683688 snapshotRoot := filepath .Join (snapshotRepository , ".boatstack" , "work-packages" , deliveryID , packageFingerprint )
684689 destinationRoot := filepath .Join (workspacePath , ".boatstack" , "work-packages" , deliveryID , packageFingerprint )
685690 destinationExists := false
@@ -707,6 +712,12 @@ func prepareWorkspaceWorkPackageTransfer(repositoryRoot, workspacePath, delivery
707712 if err != nil {
708713 return err
709714 }
715+ if filepath .ToSlash (relative ) == "approval.json" {
716+ if ! bytes .Equal (raw , verifiedApproval .Raw ) {
717+ return fmt .Errorf ("workspace work package approval changed after verification" )
718+ }
719+ raw = verifiedApproval .Raw
720+ }
710721 mutation , err := immutableWorkPackageMutation (filepath .Join (destinationRoot , relative ), raw )
711722 if err != nil {
712723 return err
@@ -754,18 +765,11 @@ func validateWorkspaceApproval(repositoryRoot, deliveryID, expectedPlanFingerpri
754765 if verified .Integrity != workpackage .Valid || verified .Contract != workpackage .Valid || verified .Approval != workpackage .Valid {
755766 return fmt .Errorf ("schema-2 promotion package is invalid" )
756767 }
757- packageRoot := filepath .Join (repositoryRoot , ".boatstack" , "work-packages" , deliveryID , promotion .WorkPackageFingerprint )
758- approvalRaw , err := os .ReadFile (filepath .Join (packageRoot , "approval.json" ))
759- var approval workpackage.Approval
760- if err != nil || workpackage .StrictDecode (approvalRaw , & approval ) != nil || approval .Fingerprint != promotion .WorkPackageApprovalFingerprint {
768+ verifiedApproval , err := workpackage .ReadVerifiedApproval (repositoryRoot , deliveryID , promotion .WorkPackageFingerprint )
769+ if err != nil || verifiedApproval .Approval .Fingerprint != promotion .WorkPackageApprovalFingerprint {
761770 return fmt .Errorf ("schema-2 promotion approval lineage is invalid" )
762771 }
763- manifestRaw , err := os .ReadFile (filepath .Join (packageRoot , "manifest.json" ))
764- var manifest workpackage.Manifest
765- if err != nil || workpackage .StrictDecode (manifestRaw , & manifest ) != nil {
766- return fmt .Errorf ("schema-2 promotion manifest is invalid" )
767- }
768- for _ , output := range manifest .Outputs {
772+ for _ , output := range verifiedApproval .Manifest .Outputs {
769773 if output .ID == promotion .PlanOutputID && output .Required && output .SHA256 == expectedPlanFingerprint {
770774 return nil
771775 }
0 commit comments