@transcend-io/cli 12.0.0 → 12.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +162 -149
- package/dist/{app-CR3U95JW.mjs → app-BAx2hvcN.mjs} +20 -18
- package/dist/app-BAx2hvcN.mjs.map +1 -0
- package/dist/{approvePrivacyRequests-BDG82nlp.mjs → approvePrivacyRequests-B-4o7QMG.mjs} +2 -2
- package/dist/{approvePrivacyRequests-BDG82nlp.mjs.map → approvePrivacyRequests-B-4o7QMG.mjs.map} +1 -1
- package/dist/bin/bash-complete.mjs +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/bin/deprecated-command.mjs +1 -1
- package/dist/buildExamples-kR5_7dkU.mjs +2 -0
- package/dist/buildExamples-kR5_7dkU.mjs.map +1 -0
- package/dist/{buildXdiSyncEndpoint-FExEagKc.mjs → buildXdiSyncEndpoint-BSYwJ2vc.mjs} +2 -2
- package/dist/{buildXdiSyncEndpoint-FExEagKc.mjs.map → buildXdiSyncEndpoint-BSYwJ2vc.mjs.map} +1 -1
- package/dist/{bulkRestartRequests-OKwKXc52.mjs → bulkRestartRequests-DhOfMz0S.mjs} +2 -2
- package/dist/{bulkRestartRequests-OKwKXc52.mjs.map → bulkRestartRequests-DhOfMz0S.mjs.map} +1 -1
- package/dist/{bulkRetryEnrichers-Dl-n8AFF.mjs → bulkRetryEnrichers-Cj94ftnY.mjs} +2 -2
- package/dist/{bulkRetryEnrichers-Dl-n8AFF.mjs.map → bulkRetryEnrichers-Cj94ftnY.mjs.map} +1 -1
- package/dist/{cancelPrivacyRequests-BIgX5SDz.mjs → cancelPrivacyRequests-DgAhfcmg.mjs} +2 -2
- package/dist/{cancelPrivacyRequests-BIgX5SDz.mjs.map → cancelPrivacyRequests-DgAhfcmg.mjs.map} +1 -1
- package/dist/{command-X7lkPELf.mjs → command-gwG8sQwM.mjs} +2 -2
- package/dist/{command-X7lkPELf.mjs.map → command-gwG8sQwM.mjs.map} +1 -1
- package/dist/{constants-BRsj50Nb.mjs → constants-BCmVqlrM.mjs} +2 -2
- package/dist/{constants-BRsj50Nb.mjs.map → constants-BCmVqlrM.mjs.map} +1 -1
- package/dist/constants-DlH2vWm_.mjs +2 -0
- package/dist/constants-DlH2vWm_.mjs.map +1 -0
- package/dist/{createPoolingCommandUi-CyPZ3GqN.mjs → createPoolingCommandUi-ByyTeJx5.mjs} +2 -2
- package/dist/{createPoolingCommandUi-CyPZ3GqN.mjs.map → createPoolingCommandUi-ByyTeJx5.mjs.map} +1 -1
- package/dist/{downloadPrivacyRequestFiles-EBySRnvd.mjs → downloadPrivacyRequestFiles-yiE6NzXz.mjs} +2 -2
- package/dist/{downloadPrivacyRequestFiles-EBySRnvd.mjs.map → downloadPrivacyRequestFiles-yiE6NzXz.mjs.map} +1 -1
- package/dist/{extractClientError-DUJxHv07.mjs → extractClientError-BQgmnp3e.mjs} +2 -2
- package/dist/{extractClientError-DUJxHv07.mjs.map → extractClientError-BQgmnp3e.mjs.map} +1 -1
- package/dist/{fuzzyMatchColumns-2NmQqCZI.mjs → fuzzyMatchColumns-D18n9Beu.mjs} +2 -2
- package/dist/{fuzzyMatchColumns-2NmQqCZI.mjs.map → fuzzyMatchColumns-D18n9Beu.mjs.map} +1 -1
- package/dist/{generateCrossAccountApiKeys-pWTrIUE6.mjs → generateCrossAccountApiKeys-CoSsZwSz.mjs} +2 -2
- package/dist/{generateCrossAccountApiKeys-pWTrIUE6.mjs.map → generateCrossAccountApiKeys-CoSsZwSz.mjs.map} +1 -1
- package/dist/{impl-Dr_l_SLd.mjs → impl-4WoLxjdU.mjs} +2 -2
- package/dist/{impl-Dr_l_SLd.mjs.map → impl-4WoLxjdU.mjs.map} +1 -1
- package/dist/{impl-D1f9mJL_.mjs → impl-BCP4X_zk.mjs} +2 -2
- package/dist/{impl-D1f9mJL_.mjs.map → impl-BCP4X_zk.mjs.map} +1 -1
- package/dist/{impl-DXbxO2VJ.mjs → impl-BFSZEQ2s.mjs} +2 -2
- package/dist/{impl-DXbxO2VJ.mjs.map → impl-BFSZEQ2s.mjs.map} +1 -1
- package/dist/{impl-BdTxFv63.mjs → impl-BJnxahnW.mjs} +2 -2
- package/dist/{impl-BdTxFv63.mjs.map → impl-BJnxahnW.mjs.map} +1 -1
- package/dist/{impl-iD6Fknfe.mjs → impl-BKKBmXv4.mjs} +2 -2
- package/dist/{impl-iD6Fknfe.mjs.map → impl-BKKBmXv4.mjs.map} +1 -1
- package/dist/{impl-DtpgD_as.mjs → impl-BM2SWSKF.mjs} +2 -2
- package/dist/{impl-DtpgD_as.mjs.map → impl-BM2SWSKF.mjs.map} +1 -1
- package/dist/{impl-CrdqsTUy.mjs → impl-BMX6B40F.mjs} +2 -2
- package/dist/{impl-CrdqsTUy.mjs.map → impl-BMX6B40F.mjs.map} +1 -1
- package/dist/{impl-7rdGuHOC.mjs → impl-BRCAL4RM.mjs} +2 -2
- package/dist/{impl-7rdGuHOC.mjs.map → impl-BRCAL4RM.mjs.map} +1 -1
- package/dist/{impl-DxQ9yj3H.mjs → impl-BaGN4J-w.mjs} +2 -2
- package/dist/{impl-DxQ9yj3H.mjs.map → impl-BaGN4J-w.mjs.map} +1 -1
- package/dist/impl-Bf2Qli6c2.mjs +421 -0
- package/dist/{impl-DQcgEx7V2.mjs.map → impl-Bf2Qli6c2.mjs.map} +1 -1
- package/dist/{impl-DJcNhpbx.mjs → impl-BrdCuU0I.mjs} +2 -2
- package/dist/{impl-DJcNhpbx.mjs.map → impl-BrdCuU0I.mjs.map} +1 -1
- package/dist/{impl-Cxprr2hw.mjs → impl-C0R2azuF.mjs} +2 -2
- package/dist/{impl-Cxprr2hw.mjs.map → impl-C0R2azuF.mjs.map} +1 -1
- package/dist/{impl-B7l4bLG5.mjs → impl-C1hh_5On.mjs} +2 -2
- package/dist/{impl-B7l4bLG5.mjs.map → impl-C1hh_5On.mjs.map} +1 -1
- package/dist/{impl-Do2TNA3-.mjs → impl-C1vn0Y7f.mjs} +2 -2
- package/dist/{impl-Do2TNA3-.mjs.map → impl-C1vn0Y7f.mjs.map} +1 -1
- package/dist/impl-C36c5NfN.mjs +2 -0
- package/dist/impl-C36c5NfN.mjs.map +1 -0
- package/dist/{impl-DcL-8NEa2.mjs → impl-C54oUOeM2.mjs} +2 -2
- package/dist/{impl-DcL-8NEa2.mjs.map → impl-C54oUOeM2.mjs.map} +1 -1
- package/dist/{impl-HUfaARep.mjs → impl-CKg5Xu-r.mjs} +2 -2
- package/dist/{impl-HUfaARep.mjs.map → impl-CKg5Xu-r.mjs.map} +1 -1
- package/dist/{impl-B440iuvL.mjs → impl-ClhMRgQZ.mjs} +3 -3
- package/dist/{impl-B440iuvL.mjs.map → impl-ClhMRgQZ.mjs.map} +1 -1
- package/dist/{impl-BWPPVXG3.mjs → impl-CoqCyj7e.mjs} +3 -3
- package/dist/{impl-BWPPVXG3.mjs.map → impl-CoqCyj7e.mjs.map} +1 -1
- package/dist/impl-CuDZY6y7.mjs +2 -0
- package/dist/impl-CuDZY6y7.mjs.map +1 -0
- package/dist/{impl-DQG1pMzD2.mjs → impl-Cvyc-iTI2.mjs} +2 -2
- package/dist/{impl-DQG1pMzD2.mjs.map → impl-Cvyc-iTI2.mjs.map} +1 -1
- package/dist/impl-CwBa15M42.mjs +3 -0
- package/dist/impl-CwBa15M42.mjs.map +1 -0
- package/dist/{impl-BLQDgwxL.mjs → impl-CxpGBeJ0.mjs} +2 -2
- package/dist/{impl-BLQDgwxL.mjs.map → impl-CxpGBeJ0.mjs.map} +1 -1
- package/dist/{impl-CWP6AXSb.mjs → impl-CyDdvH5a.mjs} +2 -2
- package/dist/{impl-CWP6AXSb.mjs.map → impl-CyDdvH5a.mjs.map} +1 -1
- package/dist/{impl-vmLq6HCI.mjs → impl-D0cf-epj.mjs} +2 -2
- package/dist/{impl-vmLq6HCI.mjs.map → impl-D0cf-epj.mjs.map} +1 -1
- package/dist/{impl-CieztjdM.mjs → impl-D3gqip90.mjs} +2 -2
- package/dist/{impl-CieztjdM.mjs.map → impl-D3gqip90.mjs.map} +1 -1
- package/dist/{impl-wBcVYHlA.mjs → impl-D8YS5Bge.mjs} +2 -2
- package/dist/{impl-wBcVYHlA.mjs.map → impl-D8YS5Bge.mjs.map} +1 -1
- package/dist/{impl-1SsreZWo.mjs → impl-DCF3CF3O.mjs} +2 -2
- package/dist/{impl-1SsreZWo.mjs.map → impl-DCF3CF3O.mjs.map} +1 -1
- package/dist/impl-DE_cRfz52.mjs +2 -0
- package/dist/impl-DE_cRfz52.mjs.map +1 -0
- package/dist/impl-DG-041kN.mjs +3 -0
- package/dist/impl-DG-041kN.mjs.map +1 -0
- package/dist/{impl-B2ZXtnpX.mjs → impl-DNRA5i0w.mjs} +2 -2
- package/dist/{impl-B2ZXtnpX.mjs.map → impl-DNRA5i0w.mjs.map} +1 -1
- package/dist/{impl-Ds-gQfdc.mjs → impl-DSPxdc-T.mjs} +2 -2
- package/dist/{impl-Ds-gQfdc.mjs.map → impl-DSPxdc-T.mjs.map} +1 -1
- package/dist/{impl-FerHBNJx2.mjs → impl-DbddBTRj2.mjs} +2 -2
- package/dist/{impl-FerHBNJx2.mjs.map → impl-DbddBTRj2.mjs.map} +1 -1
- package/dist/{impl-eeS2lVi5.mjs → impl-DdUe8ClA.mjs} +2 -2
- package/dist/{impl-eeS2lVi5.mjs.map → impl-DdUe8ClA.mjs.map} +1 -1
- package/dist/{impl-CudSYx-g.mjs → impl-Dl8xSx8K.mjs} +2 -2
- package/dist/{impl-CudSYx-g.mjs.map → impl-Dl8xSx8K.mjs.map} +1 -1
- package/dist/{impl-DRKPx_I9.mjs → impl-DqnzZv43.mjs} +2 -2
- package/dist/{impl-DRKPx_I9.mjs.map → impl-DqnzZv43.mjs.map} +1 -1
- package/dist/{impl-D-a5xGld.mjs → impl-DrlfmH8g.mjs} +3 -3
- package/dist/{impl-D-a5xGld.mjs.map → impl-DrlfmH8g.mjs.map} +1 -1
- package/dist/{impl-DTadLabu.mjs → impl-F2lRJEqw.mjs} +2 -2
- package/dist/{impl-DTadLabu.mjs.map → impl-F2lRJEqw.mjs.map} +1 -1
- package/dist/{impl-CU38kdj8.mjs → impl-LDY2dgtc.mjs} +2 -2
- package/dist/{impl-CU38kdj8.mjs.map → impl-LDY2dgtc.mjs.map} +1 -1
- package/dist/{impl-C_Ifcb00.mjs → impl-OXGlZyUo.mjs} +2 -2
- package/dist/{impl-C_Ifcb00.mjs.map → impl-OXGlZyUo.mjs.map} +1 -1
- package/dist/{impl-Cb42aI60.mjs → impl-WJBuS_0m.mjs} +2 -2
- package/dist/{impl-Cb42aI60.mjs.map → impl-WJBuS_0m.mjs.map} +1 -1
- package/dist/{impl-DqHEIzpj.mjs → impl-agm4lpyq.mjs} +5 -5
- package/dist/{impl-DqHEIzpj.mjs.map → impl-agm4lpyq.mjs.map} +1 -1
- package/dist/impl-defjX-97.mjs +3 -0
- package/dist/impl-defjX-97.mjs.map +1 -0
- package/dist/{impl-DtnYcktN.mjs → impl-f59q7WnK.mjs} +2 -2
- package/dist/{impl-DtnYcktN.mjs.map → impl-f59q7WnK.mjs.map} +1 -1
- package/dist/{impl-DiwxYcux.mjs → impl-pA1b-G6B.mjs} +2 -2
- package/dist/{impl-DiwxYcux.mjs.map → impl-pA1b-G6B.mjs.map} +1 -1
- package/dist/{impl-D1UogVAq.mjs → impl-tYHONQMu.mjs} +2 -2
- package/dist/{impl-D1UogVAq.mjs.map → impl-tYHONQMu.mjs.map} +1 -1
- package/dist/{impl-CspH2ZWx.mjs → impl-u1nIo2-E.mjs} +2 -2
- package/dist/{impl-CspH2ZWx.mjs.map → impl-u1nIo2-E.mjs.map} +1 -1
- package/dist/index.d.mts +7 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{inquirer-BU5IpgA8.mjs → inquirer-jzIQWAvq.mjs} +2 -2
- package/dist/{inquirer-BU5IpgA8.mjs.map → inquirer-jzIQWAvq.mjs.map} +1 -1
- package/dist/{markRequestDataSiloIdsCompleted-BYNMCkhy.mjs → markRequestDataSiloIdsCompleted-B-Dgme2r.mjs} +2 -2
- package/dist/{markRequestDataSiloIdsCompleted-BYNMCkhy.mjs.map → markRequestDataSiloIdsCompleted-B-Dgme2r.mjs.map} +1 -1
- package/dist/{markSilentPrivacyRequests-gKYivzH1.mjs → markSilentPrivacyRequests-CPU4Q2lF.mjs} +2 -2
- package/dist/{markSilentPrivacyRequests-gKYivzH1.mjs.map → markSilentPrivacyRequests-CPU4Q2lF.mjs.map} +1 -1
- package/dist/{mergeTranscendInputs-D1CvxQu0.mjs → mergeTranscendInputs-B7WjxYMN.mjs} +3 -3
- package/dist/{mergeTranscendInputs-D1CvxQu0.mjs.map → mergeTranscendInputs-B7WjxYMN.mjs.map} +1 -1
- package/dist/{notifyPrivacyRequestsAdditionalTime-DbERhQ1Q.mjs → notifyPrivacyRequestsAdditionalTime-BWsm5Y5K.mjs} +2 -2
- package/dist/{notifyPrivacyRequestsAdditionalTime-DbERhQ1Q.mjs.map → notifyPrivacyRequestsAdditionalTime-BWsm5Y5K.mjs.map} +1 -1
- package/dist/{policy-bundle-manifest-BZnBMZQq.mjs → policy-bundle-manifest-BDey6EBs.mjs} +3 -3
- package/dist/{policy-bundle-manifest-BZnBMZQq.mjs.map → policy-bundle-manifest-BDey6EBs.mjs.map} +1 -1
- package/dist/{policy-project-discovery-C29UxWwt.mjs → policy-project-discovery-DV5PnFJq.mjs} +71 -68
- package/dist/policy-project-discovery-DV5PnFJq.mjs.map +1 -0
- package/dist/policy-scaffold-config-DtRELUZx.mjs +76 -0
- package/dist/policy-scaffold-config-DtRELUZx.mjs.map +1 -0
- package/dist/printResult-Dmwv78e7.mjs +33 -0
- package/dist/printResult-Dmwv78e7.mjs.map +1 -0
- package/dist/{pullAllDatapoints-Bm-Orhse.mjs → pullAllDatapoints-CNqQSSmF.mjs} +3 -3
- package/dist/{pullAllDatapoints-Bm-Orhse.mjs.map → pullAllDatapoints-CNqQSSmF.mjs.map} +1 -1
- package/dist/pullChunkedCustomSiloOutstandingIdentifiers-BaHp-jxs.mjs +2 -0
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DTGQOw--.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-BaHp-jxs.mjs.map} +1 -1
- package/dist/{pullManualEnrichmentIdentifiersToCsv-DMC5CQtE.mjs → pullManualEnrichmentIdentifiersToCsv-CiEFIvl_.mjs} +2 -2
- package/dist/{pullManualEnrichmentIdentifiersToCsv-DMC5CQtE.mjs.map → pullManualEnrichmentIdentifiersToCsv-CiEFIvl_.mjs.map} +1 -1
- package/dist/{pushCronIdentifiersFromCsv-DhS2z8IG.mjs → pushCronIdentifiersFromCsv-DeS78zyp.mjs} +2 -2
- package/dist/{pushCronIdentifiersFromCsv-DhS2z8IG.mjs.map → pushCronIdentifiersFromCsv-DeS78zyp.mjs.map} +1 -1
- package/dist/pushManualEnrichmentIdentifiersFromCsv-B3iVwuvs.mjs +2 -0
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-BTJGOmdU.mjs.map → pushManualEnrichmentIdentifiersFromCsv-B3iVwuvs.mjs.map} +1 -1
- package/dist/{removeUnverifiedRequestIdentifiers-BkAcUZZN.mjs → removeUnverifiedRequestIdentifiers-qS5A_eRZ.mjs} +2 -2
- package/dist/{removeUnverifiedRequestIdentifiers-BkAcUZZN.mjs.map → removeUnverifiedRequestIdentifiers-qS5A_eRZ.mjs.map} +1 -1
- package/dist/resolveBundleIdByName-BPrMkU0w.mjs +2 -0
- package/dist/resolveBundleIdByName-BPrMkU0w.mjs.map +1 -0
- package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs +2 -0
- package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs.map +1 -0
- package/dist/{retryRequestDataSilos-BoPmcB8-.mjs → retryRequestDataSilos-Cxaka-kA.mjs} +2 -2
- package/dist/{retryRequestDataSilos-BoPmcB8-.mjs.map → retryRequestDataSilos-Cxaka-kA.mjs.map} +1 -1
- package/dist/{skipPreflightJobs-DkBdYw-r.mjs → skipPreflightJobs-FdIm_Imj.mjs} +2 -2
- package/dist/{skipPreflightJobs-DkBdYw-r.mjs.map → skipPreflightJobs-FdIm_Imj.mjs.map} +1 -1
- package/dist/{skipRequestDataSilos-BRFiokix.mjs → skipRequestDataSilos-MTbj-OfW.mjs} +2 -2
- package/dist/{skipRequestDataSilos-BRFiokix.mjs.map → skipRequestDataSilos-MTbj-OfW.mjs.map} +1 -1
- package/dist/{streamPrivacyRequestsToCsv-Bt-H5J-y.mjs → streamPrivacyRequestsToCsv-BVzYSXNY.mjs} +2 -2
- package/dist/{streamPrivacyRequestsToCsv-Bt-H5J-y.mjs.map → streamPrivacyRequestsToCsv-BVzYSXNY.mjs.map} +1 -1
- package/dist/{syncCodePackages-CPkEukDm.mjs → syncCodePackages-DJnrcX5l.mjs} +2 -2
- package/dist/{syncCodePackages-CPkEukDm.mjs.map → syncCodePackages-DJnrcX5l.mjs.map} +1 -1
- package/dist/updateConsentManagerVersionToLatest-Udi7Iazb.mjs +2 -0
- package/dist/{updateConsentManagerVersionToLatest-DWblAwus.mjs.map → updateConsentManagerVersionToLatest-Udi7Iazb.mjs.map} +1 -1
- package/dist/{uploadConsents-D7Vg8ZRW.mjs → uploadConsents-w7FE65Zg.mjs} +2 -2
- package/dist/{uploadConsents-D7Vg8ZRW.mjs.map → uploadConsents-w7FE65Zg.mjs.map} +1 -1
- package/dist/uploadPrivacyRequestsFromCsv-B__QsguT.mjs +2 -0
- package/dist/uploadPrivacyRequestsFromCsv-B__QsguT.mjs.map +1 -0
- package/package.json +5 -5
- package/dist/app-CR3U95JW.mjs.map +0 -1
- package/dist/buildExamples-B6BdW0FD.mjs +0 -2
- package/dist/buildExamples-B6BdW0FD.mjs.map +0 -1
- package/dist/constants-qvGk0wlN.mjs +0 -2
- package/dist/constants-qvGk0wlN.mjs.map +0 -1
- package/dist/impl-BqTMPbwc2.mjs +0 -2
- package/dist/impl-BqTMPbwc2.mjs.map +0 -1
- package/dist/impl-CAoIp9Nl2.mjs +0 -3
- package/dist/impl-CAoIp9Nl2.mjs.map +0 -1
- package/dist/impl-Cee7Q1Ne.mjs +0 -2
- package/dist/impl-Cee7Q1Ne.mjs.map +0 -1
- package/dist/impl-DQcgEx7V2.mjs +0 -298
- package/dist/impl-DezV3QMo.mjs +0 -3
- package/dist/impl-DezV3QMo.mjs.map +0 -1
- package/dist/impl-btKJ1-VJ.mjs +0 -3
- package/dist/impl-btKJ1-VJ.mjs.map +0 -1
- package/dist/impl-ijoNwhGI.mjs +0 -2
- package/dist/impl-ijoNwhGI.mjs.map +0 -1
- package/dist/policy-project-discovery-C29UxWwt.mjs.map +0 -1
- package/dist/policy-scaffold-config-BUKAyPad.mjs +0 -76
- package/dist/policy-scaffold-config-BUKAyPad.mjs.map +0 -1
- package/dist/printResult-C2K9ODeE.mjs +0 -33
- package/dist/printResult-C2K9ODeE.mjs.map +0 -1
- package/dist/pullChunkedCustomSiloOutstandingIdentifiers-DTGQOw--.mjs +0 -2
- package/dist/pushManualEnrichmentIdentifiersFromCsv-BTJGOmdU.mjs +0 -2
- package/dist/resolveBundleIdByName-Dm_o5_bg.mjs +0 -2
- package/dist/resolveBundleIdByName-Dm_o5_bg.mjs.map +0 -1
- package/dist/resolvePolicyBundleVersion-DRUwe7fA.mjs +0 -2
- package/dist/resolvePolicyBundleVersion-DRUwe7fA.mjs.map +0 -1
- package/dist/updateConsentManagerVersionToLatest-DWblAwus.mjs +0 -2
- package/dist/uploadPrivacyRequestsFromCsv-B_hQwIn6.mjs +0 -2
- package/dist/uploadPrivacyRequestsFromCsv-B_hQwIn6.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"impl-BqTMPbwc2.mjs","names":["fg"],"sources":["../src/commands/policy/helpers/buildOpaBundleTarball.ts","../src/commands/policy/helpers/buildPolicyBundleFormData.ts","../src/commands/policy/helpers/defaultPolicyVersionLabel.ts","../src/lib/policy/policy-publish-hints.ts","../src/commands/policy/publish/impl.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { gunzipSync } from 'node:zlib';\n\nimport fg from 'fast-glob';\n\nimport { validatePolicyBundleContents } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { MAX_BUNDLE_COMPRESSED_BYTES, MAX_BUNDLE_DECOMPRESSED_BYTES } from '../constants.js';\nimport { assertOpaInstalled } from './assertOpaInstalled.js';\nimport { runOPACapture } from './runOpa.js';\n\n/** Result of collecting publishable entries from a policy bundle directory. */\ninterface PolicyBundleArchiveContents {\n /** Relative paths to include in the upload tarball (manifest first, then rego) */\n entries: string[];\n}\n\n/**\n * Collects `.manifest` and publishable `.rego` files from a policy directory.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns Validated archive entries\n */\nfunction collectPolicyBundleArchiveEntries(dir: string): PolicyBundleArchiveContents {\n const regoFiles = fg\n .sync('**/*.rego', {\n cwd: dir,\n onlyFiles: true,\n dot: false,\n })\n .sort();\n const onDiskManifestPath = path.join(dir, POLICY_MANIFEST_FILENAME);\n const { publishableRegoPaths } = validatePolicyBundleContents(\n fs.existsSync(onDiskManifestPath) ? fs.readFileSync(onDiskManifestPath, 'utf8') : undefined,\n regoFiles.map((relativePath) => ({\n path: relativePath,\n contents: fs.readFileSync(path.join(dir, relativePath), 'utf8'),\n })),\n );\n\n return {\n entries: [POLICY_MANIFEST_FILENAME, ...publishableRegoPaths],\n };\n}\n\n/**\n * Verifies that a policy directory compiles end-to-end with `opa build`.\n *\n * The compiled output is discarded — the server receives the `.manifest` +\n * `.rego` archive produced by {@link buildOpaBundleTarball}, not the OPA bundle\n * — but a successful build guarantees the policies compile and link, surfacing\n * errors (syntax, missing imports, undefined references, etc.) before upload.\n *\n * @param dir - Absolute path to the policy bundle directory\n */\nasync function assertBundleCompiles(dir: string): Promise<void> {\n const buildOutputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n try {\n // Run with `cwd` set to the bundle directory and pass `.` so `opa build`\n // resolves the bundle root correctly. Bundle mode (`-b`) keeps local\n // `input.json` / `input.example.json` fixtures from merging as data.\n // `*_test.rego` files are local-only.\n const { code, stderr } = await runOPACapture(\n ['build', '--ignore', '*_test.rego', '-b', '-o', buildOutputPath, '.'],\n { cwd: dir },\n );\n if (code !== 0) {\n throw new Error(stderr.trim() || `opa build failed with exit code ${code}`);\n }\n } finally {\n if (fs.existsSync(buildOutputPath)) {\n fs.unlinkSync(buildOutputPath);\n }\n }\n}\n\n/**\n * Formats a byte count as a human-readable size with binary units.\n *\n * @param bytes - Number of bytes\n * @returns Human-readable size, e.g. `14 MiB` or `4 KiB`\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const kib = bytes / 1024;\n if (kib < 1024) {\n return `${kib % 1 === 0 ? kib.toFixed(0) : kib.toFixed(1)} KiB`;\n }\n const mib = kib / 1024;\n return `${mib % 1 === 0 ? mib.toFixed(0) : mib.toFixed(1)} MiB`;\n}\n\n/**\n * Builds a gzip-compressed policy bundle tarball for upload to Transcend.\n *\n * The Policy Engine API expects a plain archive containing `.manifest` and\n * one or more `.rego` files. Local projects author an OPA `.manifest` and it\n * is uploaded directly — no rename at pack time. Before packaging, the\n * manifest is validated (shape + root coverage) and the bundle is validated\n * with `opa check` (strict Rego linting) and `opa build` (full compilation) so\n * failures surface client-side rather than after upload.\n *\n * @param dir - Directory containing `.manifest` and `.rego` policy files\n * @returns Absolute path to the generated `.tar.gz` bundle\n */\nexport async function buildOpaBundleTarball(dir: string): Promise<string> {\n assertOpaInstalled();\n\n const resolvedDir = path.resolve(dir);\n if (!fs.existsSync(resolvedDir) || !fs.statSync(resolvedDir).isDirectory()) {\n throw new Error(`Policy directory does not exist or is not a directory: ${resolvedDir}`);\n }\n\n // Validate the manifest shape and that roots cover every Rego package before\n // invoking OPA, so invalid manifests surface a clear error instead of an\n // opaque `opa build failed with exit code 1`.\n const { entries: archiveEntries } = collectPolicyBundleArchiveEntries(resolvedDir);\n\n // Match the Rego v1 validation the Policy Engine API runs on upload.\n const { code: checkCode, stderr: checkStderr } = await runOPACapture([\n 'check',\n '--strict',\n resolvedDir,\n ]);\n if (checkCode !== 0) {\n throw new Error(checkStderr.trim() || `opa check failed with exit code ${checkCode}`);\n }\n\n // Ensure the bundle compiles end-to-end before packaging for upload.\n await assertBundleCompiles(resolvedDir);\n\n const outputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n const tarResult = spawnSync('tar', ['-czf', outputPath, '-C', resolvedDir, ...archiveEntries], {\n env: { ...process.env, COPYFILE_DISABLE: '1' },\n encoding: 'utf8',\n });\n if (tarResult.status !== 0) {\n throw new Error(\n `Failed to create policy bundle archive: ${tarResult.stderr.trim() || 'tar failed'}`,\n );\n }\n\n const compressedBytes = fs.readFileSync(outputPath);\n if (compressedBytes.byteLength > MAX_BUNDLE_COMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_COMPRESSED_BYTES)} compressed upload limit ` +\n `(bundle is ${formatBytes(compressedBytes.byteLength)}). ` +\n `The server also rejects decompressed bundles larger than ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)}.`,\n );\n }\n\n const decompressedBytes = gunzipSync(compressedBytes);\n if (decompressedBytes.byteLength > MAX_BUNDLE_DECOMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)} decompressed upload limit ` +\n `(bundle is ${formatBytes(decompressedBytes.byteLength)} decompressed).`,\n );\n }\n\n return outputPath;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Fields for building a policy bundle upload form. */\nexport interface BuildPolicyBundleFormDataOptions {\n /** Absolute path to the bundle tarball */\n bundlePath: string;\n /** Version label */\n version: string;\n /** Optional description */\n description?: string;\n /** Bundle name (only for create) */\n bundleName?: string;\n}\n\n/**\n * Builds multipart form data for a policy bundle upload.\n *\n * @param options - Upload fields\n * @returns FormData ready for POST\n */\nexport function buildPolicyBundleFormData(options: BuildPolicyBundleFormDataOptions): FormData {\n const bundleBytes = fs.readFileSync(options.bundlePath);\n const form = new FormData();\n form.append(\n 'bundle',\n new Blob([bundleBytes], { type: 'application/gzip' }),\n path.basename(options.bundlePath),\n );\n form.append('version', options.version);\n if (options.description) {\n form.append('description', options.description);\n }\n if (options.bundleName) {\n form.append('bundleName', options.bundleName);\n }\n return form;\n}\n","/**\n * Formats a date as `yyyy-mm-dd-hh-mm-ss` in UTC.\n *\n * @param date - Date to format\n * @returns Timestamp label\n */\nfunction formatPolicyVersionTimestamp(date: Date): string {\n return date.toISOString().slice(0, 19).replace(/[T:]/g, '-');\n}\n\n/**\n * Returns a default version label from the bundle name and current UTC timestamp.\n *\n * @param bundleName - Tenant-unique policy bundle name\n * @param now - Current time (for testing)\n * @returns Version label in `{bundleName}-yyyy-mm-dd-hh-mm-ss` form\n */\nexport function defaultPolicyVersionLabel(bundleName: string, now: Date = new Date()): string {\n return `${bundleName}-${formatPolicyVersionTimestamp(now)}`;\n}\n","import {\n PERMISSIONS_POLICY_BUNDLE_NAME,\n type PolicyTemplateName,\n} from './policy-scaffold-templates.js';\n\n/** Inputs used to soft-warn about Permissions vs generic publish naming. */\nexport interface PolicyPublishBundleNameHintInput {\n /** Optional scaffold template from `.manifest` metadata. */\n template?: PolicyTemplateName;\n /** Declared OPA package roots. */\n roots: string[];\n}\n\n/**\n * Whether local authoring signals suggest a Permissions API bundle.\n *\n * Prefers explicit `metadata.transcend.io.template`. Without metadata, falls\n * back to a root that is exactly `permissions` or nested under it.\n *\n * @param input - Manifest template hint and roots\n * @returns Whether the local tree looks Permissions-oriented\n */\nfunction looksLikePermissionsBundle(input: PolicyPublishBundleNameHintInput): boolean {\n if (input.template === 'permissions') {\n return true;\n }\n if (input.template === 'generic') {\n return false;\n }\n return input.roots.some(\n (root) =>\n root === PERMISSIONS_POLICY_BUNDLE_NAME ||\n root.startsWith(`${PERMISSIONS_POLICY_BUNDLE_NAME}/`),\n );\n}\n\n/**\n * Soft-warning when `--bundle-name` disagrees with Permissions conventions.\n *\n * Upload does not enforce bundle kinds. Permissions API only loads the\n * remote bundle named {@link PERMISSIONS_POLICY_BUNDLE_NAME}.\n *\n * @param bundleName - Value of `--bundle-name`\n * @param input - Local manifest template/roots\n * @returns Warning text, or undefined when names align\n */\nexport function formatPolicyPublishBundleNameHint(\n bundleName: string,\n input: PolicyPublishBundleNameHintInput,\n): string | undefined {\n const permissionsLocal = looksLikePermissionsBundle(input);\n const permissionsRemote = bundleName === PERMISSIONS_POLICY_BUNDLE_NAME;\n\n if (permissionsLocal && !permissionsRemote) {\n return (\n `This directory looks like a Permissions API policy, but --bundle-name is ` +\n `\"${bundleName}\". Permissions API only loads the remote bundle named ` +\n `\"${PERMISSIONS_POLICY_BUNDLE_NAME}\". Upload still succeeds; pass ` +\n `--bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} if that is the intended path.`\n );\n }\n\n if (!permissionsLocal && permissionsRemote) {\n return (\n `--bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} reserves the Permissions API ` +\n `path. Upload treats all bundles the same; only that fixed name is queried by ` +\n `the Permissions API. Continue only if you intend this bundle for the Permissions API.`\n );\n }\n\n return undefined;\n}\n","import { join } from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { buildExampleCommand } from '../../../lib/docgen/buildExamples.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport { parsePolicyBundleManifest } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { resolvePolicyProjectDirectory } from '../../../lib/policy/policy-project-discovery.js';\nimport { formatPolicyPublishBundleNameHint } from '../../../lib/policy/policy-publish-hints.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.js';\nimport type { ActivateCommandFlags } from '../activate/impl.js';\nimport {\n buildPolicyBundleFormData,\n buildPolicyEngineClient,\n buildOpaBundleTarball,\n defaultPolicyVersionLabel,\n formatPolicyBundleVersionSummary,\n policyEngineRequest,\n printResult,\n resolveBundleIdByName,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { CreatePolicyBundleResponse, CreatePolicyBundleVersionResponse } from '../types.js';\n\n/** CLI flags for `transcend policy publish`. */\nexport interface PublishCommandFlags {\n /** Tenant-unique bundle name */\n 'bundle-name': string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Version label (defaults to `{bundleName}-yyyy-mm-dd-hh-mm-ss`) */\n version?: string;\n /** Optional version description */\n description?: string;\n /** Print raw JSON response */\n json: boolean;\n /** Skip the \"create new bundle\" confirmation */\n yes: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Build and upload a new immutable policy bundle version.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy bundle directory containing a `.manifest`\n */\nexport async function publish(\n this: LocalContext,\n {\n 'bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n version,\n description,\n json,\n yes,\n debug = false,\n }: PublishCommandFlags,\n directory: string,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const commandLogger = selectCommandLogger(this.logger, json);\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n const versionLabel = version ?? defaultPolicyVersionLabel(bundleName);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive: false },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n\n let bundlePath: string | undefined;\n try {\n commandLogger.info(colors.green(`Building policy bundle from ${resolvedDir}...`));\n bundlePath = await buildOpaBundleTarball(resolvedDir);\n\n try {\n const manifestPath = join(resolvedDir, POLICY_MANIFEST_FILENAME);\n const manifest = parsePolicyBundleManifest(this.fs.readFileSync(manifestPath, 'utf8'));\n const bundleNameHint = formatPolicyPublishBundleNameHint(bundleName, manifest);\n if (bundleNameHint) {\n commandLogger.warn(colors.yellow(bundleNameHint));\n }\n } catch {\n // Best-effort authoring hint; tarball build already validated the manifest.\n }\n\n const existingBundleId = await resolveBundleIdByName(client, bundleName);\n\n let responseBody: CreatePolicyBundleResponse | CreatePolicyBundleVersionResponse;\n\n if (existingBundleId) {\n commandLogger.info(colors.green(`Uploading new version for bundle \"${bundleName}\"...`));\n const form = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n });\n responseBody = await policyEngineRequest(\n client\n .post(`v1/policy-engine/policy-bundles/${existingBundleId}/versions`, { body: form })\n .json<CreatePolicyBundleVersionResponse>(),\n );\n } else {\n if (!interactive && !yes) {\n this.logger.error(\n colors.red(\n 'Cannot create a new bundle in non-interactive or JSON mode; pass --yes to confirm.',\n ),\n );\n this.process.exit(1);\n return;\n }\n\n if (!yes) {\n commandLogger.warn(\n colors.yellow(`No policy bundle named \"${bundleName}\" exists for this organization.`),\n );\n const shouldCreate = await inquirerConfirmBoolean({\n message: `No policy bundle named \"${bundleName}\" exists. Create a new bundle and upload its first version?`,\n });\n if (!shouldCreate) {\n commandLogger.info(colors.yellow('Publish cancelled.'));\n return;\n }\n }\n\n commandLogger.info(\n colors.green(`Creating bundle \"${bundleName}\" and uploading first version...`),\n );\n const createForm = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n bundleName,\n });\n responseBody = await policyEngineRequest(\n client\n .post('v1/policy-engine/policy-bundles', {\n body: createForm,\n })\n .json<CreatePolicyBundleResponse>(),\n );\n }\n\n printResult(this.process.stdout, {\n json,\n data: responseBody,\n renderTable: () => formatPolicyBundleVersionSummary(responseBody.version),\n });\n\n commandLogger.info(colors.green('Policy bundle version uploaded successfully.'));\n\n const activateCommand = buildExampleCommand<ActivateCommandFlags>(['policy', 'activate'], {\n version: responseBody.version.version,\n 'bundle-name': bundleName,\n });\n commandLogger.info(\n colors.yellow(\n `Publishing a policy does not activate it. To activate this version, run:\\n ${activateCommand}`,\n ),\n );\n } finally {\n if (bundlePath && this.fs.existsSync(bundlePath)) {\n this.fs.unlinkSync(bundlePath);\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/impl-CAoIp9Nl2.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./policyEngineCliError-CZrOHhLv.mjs";import{i as t,n,t as r}from"./printResult-C2K9ODeE.mjs";import{t as i}from"./resolveBundleIdByName-Dm_o5_bg.mjs";import{t as a}from"./resolvePolicyBundleVersion-DRUwe7fA.mjs";import{t as o}from"./done-input-validation-LiTaCEzF.mjs";import{t as s}from"./command-output-BJcDRXNr.mjs";import c from"node:path";import l from"colors";import u from"got";function d(e,t){return`${e}-${t}.tar.gz`}function f(e,t){return[`bundleName ${e.bundleName}`,`version ${e.version}`,`output ${t}`,`sha256 ${e.sha256}`,`sizeBytes ${e.sizeBytes}`,`uploadedAt ${e.uploadedAt}`,`activatedAt ${e.activatedAt??`-`}`].join(`
|
|
2
|
-
`)}async function p({"bundle-name":p,version:m,output:h,auth:g,"transcend-url":_,json:v,debug:y=!1}){o(this.process),e(y);let b=t(_,g),x=s(this.logger,v),S=await i(b,p);if(!S)throw Error(`Policy bundle "${p}" was not found for this organization.`);let C;if(m)C=(await a(b,S.id,{version:m})).id;else{if(!S.activeVersionId)throw Error(`Policy bundle "${p}" has no active version.`);C=S.activeVersionId}x.info(l.green(m?`Fetching download URL for bundle "${p}" version "${m}"...`:`Fetching download URL for active version of bundle "${p}"...`));let w=await n(b.get(`v1/policy-engine/policy-bundles/${S.id}/versions/${C}`).json());if(v){r(this.process.stdout,{json:!0,data:w});return}let T=c.resolve(h??d(p,w.version));x.info(l.green(`Downloading policy bundle to ${T}...`));let E;try{E=await u(w.downloadUrl).buffer()}catch(e){throw Error(`Failed to download policy bundle from the presigned URL: ${e instanceof Error?e.message:String(e)}`,{cause:e})}let D=c.dirname(T);this.fs.mkdirSync(D,{recursive:!0}),this.fs.writeFileSync(T,E),r(this.process.stdout,{json:!1,data:w,renderTable:()=>f(w,T)}),x.info(l.green(`Policy bundle downloaded successfully.`))}export{p as download};
|
|
3
|
-
//# sourceMappingURL=impl-CAoIp9Nl2.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"impl-CAoIp9Nl2.mjs","names":[],"sources":["../src/commands/policy/download/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport colors from 'colors';\nimport got from 'got';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { EMPTY_CELL } from '../constants.js';\nimport {\n buildPolicyEngineClient,\n policyEngineRequest,\n printResult,\n resolveBundleByName,\n resolvePolicyBundleVersion,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { GetPolicyBundleVersionResponse } from '../types.js';\n\n/** CLI flags for `transcend policy download`. */\nexport interface DownloadCommandFlags {\n /** Tenant-unique bundle name */\n 'bundle-name': string;\n /**\n * Caller-supplied version label to download.\n * When omitted, downloads the bundle's currently active version.\n */\n version?: string;\n /** Destination file path; defaults to `{bundleName}-{version}.tar.gz` */\n output?: string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Print metadata + presigned URL as JSON without writing a file */\n json: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Builds the default output path for a downloaded policy bundle.\n *\n * @param bundleName - Tenant-unique bundle name\n * @param version - Caller-supplied version label\n * @returns Relative path `{bundleName}-{version}.tar.gz`\n */\nexport function defaultPolicyDownloadOutputPath(bundleName: string, version: string): string {\n return `${bundleName}-${version}.tar.gz`;\n}\n\n/**\n * Formats download metadata for human-readable CLI output.\n *\n * @param body - Version metadata from the Policy Engine API\n * @param outputPath - Destination path written (or that would be written)\n * @returns Summary lines\n */\nfunction formatDownloadSummary(body: GetPolicyBundleVersionResponse, outputPath: string): string {\n return [\n `bundleName ${body.bundleName}`,\n `version ${body.version}`,\n `output ${outputPath}`,\n `sha256 ${body.sha256}`,\n `sizeBytes ${body.sizeBytes}`,\n `uploadedAt ${body.uploadedAt}`,\n `activatedAt ${body.activatedAt ?? EMPTY_CELL}`,\n ].join('\\n');\n}\n\n/**\n * Download a compiled policy bundle version to disk.\n *\n * Resolves `--bundle-name` and an optional `--version` to IDs, fetches a\n * short-lived presigned S3 URL from the monolith, then downloads the `.tar.gz`\n * bytes directly from S3 (the monolith does not proxy the artifact).\n *\n * When `--version` is omitted, downloads the bundle's currently active version.\n * If the bundle has no active version, exits with an error.\n *\n * @param this - CLI context\n * @param flags - Command flags\n */\nexport async function download(\n this: LocalContext,\n {\n 'bundle-name': bundleName,\n version,\n output,\n auth,\n 'transcend-url': transcendUrl,\n json,\n debug = false,\n }: DownloadCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const commandLogger = selectCommandLogger(this.logger, json);\n\n const bundle = await resolveBundleByName(client, bundleName);\n if (!bundle) {\n throw new Error(`Policy bundle \"${bundleName}\" was not found for this organization.`);\n }\n\n let versionId: string;\n if (version) {\n const resolvedVersion = await resolvePolicyBundleVersion(client, bundle.id, { version });\n versionId = resolvedVersion.id;\n } else {\n if (!bundle.activeVersionId) {\n throw new Error(`Policy bundle \"${bundleName}\" has no active version.`);\n }\n versionId = bundle.activeVersionId;\n }\n\n commandLogger.info(\n colors.green(\n version\n ? `Fetching download URL for bundle \"${bundleName}\" version \"${version}\"...`\n : `Fetching download URL for active version of bundle \"${bundleName}\"...`,\n ),\n );\n\n const body = await policyEngineRequest(\n client\n .get(`v1/policy-engine/policy-bundles/${bundle.id}/versions/${versionId}`)\n .json<GetPolicyBundleVersionResponse>(),\n );\n\n if (json) {\n printResult(this.process.stdout, {\n json: true,\n data: body,\n });\n return;\n }\n\n const outputPath = path.resolve(\n output ?? defaultPolicyDownloadOutputPath(bundleName, body.version),\n );\n\n commandLogger.info(colors.green(`Downloading policy bundle to ${outputPath}...`));\n\n let bundleBytes: Uint8Array;\n try {\n bundleBytes = await got(body.downloadUrl).buffer();\n } catch (err) {\n throw new Error(\n `Failed to download policy bundle from the presigned URL: ${\n err instanceof Error ? err.message : String(err)\n }`,\n { cause: err },\n );\n }\n\n const outputDir = path.dirname(outputPath);\n this.fs.mkdirSync(outputDir, { recursive: true });\n this.fs.writeFileSync(outputPath, bundleBytes);\n\n printResult(this.process.stdout, {\n json: false,\n data: body,\n renderTable: () => formatDownloadSummary(body, outputPath),\n });\n\n commandLogger.info(colors.green('Policy bundle downloaded successfully.'));\n}\n"],"mappings":"oZA+CA,SAAgB,EAAgC,EAAoB,EAAyB,CAC3F,MAAO,GAAG,EAAW,GAAG,EAAQ,SAUlC,SAAS,EAAsB,EAAsC,EAA4B,CAC/F,MAAO,CACL,eAAe,EAAK,aACpB,eAAe,EAAK,UACpB,eAAe,IACf,eAAe,EAAK,SACpB,eAAe,EAAK,YACpB,eAAe,EAAK,aACpB,eAAe,EAAK,aAAA,MACrB,CAAC,KAAK;EAAK,CAgBd,eAAsB,EAEpB,CACE,cAAe,EACf,UACA,SACA,OACA,gBAAiB,EACjB,OACA,QAAQ,IAEK,CACf,EAAoB,KAAK,QAAQ,CACjC,EAAwB,EAAM,CAE9B,IAAM,EAAS,EAAwB,EAAc,EAAK,CACpD,EAAgB,EAAoB,KAAK,OAAQ,EAAK,CAEtD,EAAS,MAAM,EAAoB,EAAQ,EAAW,CAC5D,GAAI,CAAC,EACH,MAAU,MAAM,kBAAkB,EAAW,wCAAwC,CAGvF,IAAI,EACJ,GAAI,EAEF,GAAY,MADkB,EAA2B,EAAQ,EAAO,GAAI,CAAE,UAAS,CAAC,EAC5D,OACvB,CACL,GAAI,CAAC,EAAO,gBACV,MAAU,MAAM,kBAAkB,EAAW,0BAA0B,CAEzE,EAAY,EAAO,gBAGrB,EAAc,KACZ,EAAO,MACL,EACI,qCAAqC,EAAW,aAAa,EAAQ,MACrE,uDAAuD,EAAW,MACvE,CACF,CAED,IAAM,EAAO,MAAM,EACjB,EACG,IAAI,mCAAmC,EAAO,GAAG,YAAY,IAAY,CACzE,MAAsC,CAC1C,CAED,GAAI,EAAM,CACR,EAAY,KAAK,QAAQ,OAAQ,CAC/B,KAAM,GACN,KAAM,EACP,CAAC,CACF,OAGF,IAAM,EAAa,EAAK,QACtB,GAAU,EAAgC,EAAY,EAAK,QAAQ,CACpE,CAED,EAAc,KAAK,EAAO,MAAM,gCAAgC,EAAW,KAAK,CAAC,CAEjF,IAAI,EACJ,GAAI,CACF,EAAc,MAAM,EAAI,EAAK,YAAY,CAAC,QAAQ,OAC3C,EAAK,CACZ,MAAU,MACR,4DACE,aAAe,MAAQ,EAAI,QAAU,OAAO,EAAI,GAElD,CAAE,MAAO,EAAK,CACf,CAGH,IAAM,EAAY,EAAK,QAAQ,EAAW,CAC1C,KAAK,GAAG,UAAU,EAAW,CAAE,UAAW,GAAM,CAAC,CACjD,KAAK,GAAG,cAAc,EAAY,EAAY,CAE9C,EAAY,KAAK,QAAQ,OAAQ,CAC/B,KAAM,GACN,KAAM,EACN,gBAAmB,EAAsB,EAAM,EAAW,CAC3D,CAAC,CAEF,EAAc,KAAK,EAAO,MAAM,yCAAyC,CAAC"}
|
package/dist/impl-Cee7Q1Ne.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./policyEngineCliError-CZrOHhLv.mjs";import{i as t,n,t as r}from"./printResult-C2K9ODeE.mjs";import{t as i}from"./renderTable-CZP2roD1.mjs";import{n as a}from"./resolveBundleIdByName-Dm_o5_bg.mjs";import{t as o}from"./done-input-validation-LiTaCEzF.mjs";import{t as s}from"./command-output-BJcDRXNr.mjs";import c from"colors";async function l({"bundle-name":l,auth:u,"transcend-url":d,limit:f,after:p,json:m,debug:h=!1}){o(this.process),e(h);let g=t(d,u),_=s(this.logger,m),v=await a(g,l);if(!v)throw Error(`Policy bundle "${l}" was not found for this organization.`);_.info(c.green(`Listing versions for bundle "${l}"...`));let y={limit:f};p&&(y.after=p);let b=await n(g.get(`v1/policy-engine/policy-bundles/${v}/versions`,{searchParams:y}).json());r(this.process.stdout,{json:m,data:b,renderTable:()=>{if(b.nodes.length===0)return p?`No more versions for bundle "${l}" (end of results).`:`No versions found for bundle "${l}".`;let e=i([`id`,`version`,`createdAt`,`activatedAt`,`deactivatedAt`],b.nodes.map(e=>[e.id,e.version,e.createdAt,e.activatedAt??`-`,e.deactivatedAt??`-`]));return b.pageInfo.endCursor&&(e+=`\n\nafter: ${b.pageInfo.endCursor}`),e}})}export{l as versions};
|
|
2
|
-
//# sourceMappingURL=impl-Cee7Q1Ne.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"impl-Cee7Q1Ne.mjs","names":[],"sources":["../src/commands/policy/versions/impl.ts"],"sourcesContent":["import colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { EMPTY_CELL } from '../constants.js';\nimport {\n buildPolicyEngineClient,\n policyEngineRequest,\n printResult,\n renderTable,\n resolveBundleIdByName,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { PolicyBundleVersionListResponse } from '../types.js';\n\n/** CLI flags for `transcend policy versions`. */\nexport interface VersionsCommandFlags {\n /** Tenant-unique bundle name */\n 'bundle-name': string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Page size */\n limit: number;\n /** Cursor from a previous page's pageInfo.endCursor */\n after?: string;\n /** Print raw JSON response */\n json: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * List versions for a policy bundle.\n *\n * @param this - CLI context\n * @param flags - Command flags\n */\nexport async function versions(\n this: LocalContext,\n {\n 'bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n limit,\n after,\n json,\n debug = false,\n }: VersionsCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const commandLogger = selectCommandLogger(this.logger, json);\n const bundleId = await resolveBundleIdByName(client, bundleName);\n\n if (!bundleId) {\n throw new Error(`Policy bundle \"${bundleName}\" was not found for this organization.`);\n }\n\n commandLogger.info(colors.green(`Listing versions for bundle \"${bundleName}\"...`));\n\n const searchParams: Record<string, string | number> = { limit };\n if (after) {\n searchParams.after = after;\n }\n\n const body = await policyEngineRequest(\n client\n .get(`v1/policy-engine/policy-bundles/${bundleId}/versions`, {\n searchParams,\n })\n .json<PolicyBundleVersionListResponse>(),\n );\n\n printResult(this.process.stdout, {\n json,\n data: body,\n renderTable: () => {\n if (body.nodes.length === 0) {\n // Distinguish \"this page is empty because you paginated past the end\"\n // from \"the bundle genuinely has no versions\" — the latter is already\n // surfaced during version resolution upstream.\n return after\n ? `No more versions for bundle \"${bundleName}\" (end of results).`\n : `No versions found for bundle \"${bundleName}\".`;\n }\n\n const rows = body.nodes.map((version) => [\n version.id,\n version.version,\n version.createdAt,\n version.activatedAt ?? EMPTY_CELL,\n version.deactivatedAt ?? EMPTY_CELL,\n ]);\n\n let table = renderTable(['id', 'version', 'createdAt', 'activatedAt', 'deactivatedAt'], rows);\n if (body.pageInfo.endCursor) {\n table += `\\n\\nafter: ${body.pageInfo.endCursor}`;\n }\n return table;\n },\n });\n}\n"],"mappings":"yVAwCA,eAAsB,EAEpB,CACE,cAAe,EACf,OACA,gBAAiB,EACjB,QACA,QACA,OACA,QAAQ,IAEK,CACf,EAAoB,KAAK,QAAQ,CACjC,EAAwB,EAAM,CAE9B,IAAM,EAAS,EAAwB,EAAc,EAAK,CACpD,EAAgB,EAAoB,KAAK,OAAQ,EAAK,CACtD,EAAW,MAAM,EAAsB,EAAQ,EAAW,CAEhE,GAAI,CAAC,EACH,MAAU,MAAM,kBAAkB,EAAW,wCAAwC,CAGvF,EAAc,KAAK,EAAO,MAAM,gCAAgC,EAAW,MAAM,CAAC,CAElF,IAAM,EAAgD,CAAE,QAAO,CAC3D,IACF,EAAa,MAAQ,GAGvB,IAAM,EAAO,MAAM,EACjB,EACG,IAAI,mCAAmC,EAAS,WAAY,CAC3D,eACD,CAAC,CACD,MAAuC,CAC3C,CAED,EAAY,KAAK,QAAQ,OAAQ,CAC/B,OACA,KAAM,EACN,gBAAmB,CACjB,GAAI,EAAK,MAAM,SAAW,EAIxB,OAAO,EACH,gCAAgC,EAAW,qBAC3C,iCAAiC,EAAW,IAWlD,IAAI,EAAQ,EAAY,CAAC,KAAM,UAAW,YAAa,cAAe,gBAAgB,CARzE,EAAK,MAAM,IAAK,GAAY,CACvC,EAAQ,GACR,EAAQ,QACR,EAAQ,UACR,EAAQ,aAAA,IACR,EAAQ,eAAA,IACT,CAE2F,CAAC,CAI7F,OAHI,EAAK,SAAS,YAChB,GAAS,cAAc,EAAK,SAAS,aAEhC,GAEV,CAAC"}
|
package/dist/impl-DQcgEx7V2.mjs
DELETED
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import{g as e}from"./constants-BRsj50Nb.mjs";import{i as t,n,r,t as i}from"./project-plan-output-BHHlkLxe.mjs";import{c as a,d as o,f as s,l as c,t as l,u}from"./project-discovery-CWRjlFnC.mjs";import{c as d,g as f,l as p,r as m,t as h}from"./policy-project-discovery-C29UxWwt.mjs";import{a as g,c as _,i as v,l as y,o as b,r as ee,s as x,t as S}from"./policy-runtime-6jmkXlBk.mjs";import{t as C}from"./done-input-validation-LiTaCEzF.mjs";import{i as w,n as T,r as E,t as D}from"./prompts-BhXfYD6g.mjs";import{t as O}from"./run-captured-process-BjaSDWXG.mjs";import{t as k}from"./project-plan-apply-Bg_1eMX9.mjs";import{a as A,i as j,n as te,r as ne,t as M}from"./policy-scaffold-config-BUKAyPad.mjs";import{isAbsolute as N,join as P,posix as F,relative as I,sep as L}from"node:path";import R from"colors";const z={Editor:`editor`,Skill:`skill`,Ci:`ci`};var B=`# Idiomatic Rego and document-tree authoring
|
|
2
|
-
|
|
3
|
-
## Start from the document tree
|
|
4
|
-
|
|
5
|
-
OPA evaluates queries against one document tree:
|
|
6
|
-
|
|
7
|
-
- \`input\` is the request-specific document supplied by the caller.
|
|
8
|
-
- \`data\` contains loaded policy packages and static data.
|
|
9
|
-
- A Rego \`package\` determines where a module contributes documents below \`data\`.
|
|
10
|
-
|
|
11
|
-
Choose package paths from the application's required query and ownership
|
|
12
|
-
boundaries. Keep directory and package names aligned
|
|
13
|
-
(\`directory-package-mismatch\`), and cover every publishable package with a
|
|
14
|
-
\`.manifest\` root.
|
|
15
|
-
|
|
16
|
-
### Multi-bundle template layout
|
|
17
|
-
|
|
18
|
-
Prefer a publish directory named \`{root}-bundle/\` so the package-root folder can
|
|
19
|
-
be \`{root}/\` without doubling names:
|
|
20
|
-
|
|
21
|
-
\`\`\`
|
|
22
|
-
example-bundle/ # transcend policy publish … <dir>
|
|
23
|
-
.manifest # roots + optional metadata.transcend.io.template
|
|
24
|
-
example/
|
|
25
|
-
result/… # package example.result
|
|
26
|
-
input.example.json
|
|
27
|
-
input.json # gitignored; VS Code / Regal Evaluate
|
|
28
|
-
\`\`\`
|
|
29
|
-
|
|
30
|
-
Permissions starters use the same layout. Upload does not branch on template
|
|
31
|
-
metadata; Permissions API still loads only the remote bundle named
|
|
32
|
-
\`permissions\` (publish with \`--bundle-name=permissions\`).
|
|
33
|
-
|
|
34
|
-
OPA \`.rego\` placement follows the \`package\` line; \`data.json\` paths follow the
|
|
35
|
-
filesystem and must sit under the manifest root prefix on disk.
|
|
36
|
-
|
|
37
|
-
Use Rego v1 explicitly:
|
|
38
|
-
|
|
39
|
-
\`\`\`rego
|
|
40
|
-
package example.result
|
|
41
|
-
|
|
42
|
-
import rego.v1
|
|
43
|
-
\`\`\`
|
|
44
|
-
|
|
45
|
-
When one publishable package reads another package under the same manifest root,
|
|
46
|
-
import it and use the local name:
|
|
47
|
-
|
|
48
|
-
\`\`\`rego
|
|
49
|
-
import data.example.facts
|
|
50
|
-
|
|
51
|
-
allow if facts.subject_is_trusted
|
|
52
|
-
\`\`\`
|
|
53
|
-
|
|
54
|
-
Do not use a fully qualified \`data.<root>…\` reference directly in a rule body.
|
|
55
|
-
Policy Engine re-namespaces package declarations and imports during activation,
|
|
56
|
-
and \`transcend policy lint\` rejects direct self-root references that would
|
|
57
|
-
change meaning.
|
|
58
|
-
|
|
59
|
-
## Define the contract before implementation
|
|
60
|
-
|
|
61
|
-
Find the actual caller and document:
|
|
62
|
-
|
|
63
|
-
1. the query path below \`data\`;
|
|
64
|
-
2. required and optional \`input\` fields;
|
|
65
|
-
3. the result document consumed by the caller;
|
|
66
|
-
4. fail-closed behavior for absent, malformed, or unknown input;
|
|
67
|
-
5. stable reason codes and any fields reserved for later extension.
|
|
68
|
-
|
|
69
|
-
Do not infer a product contract from the generated example. Replace its package
|
|
70
|
-
names and fields when the repository's contract is known.
|
|
71
|
-
|
|
72
|
-
Wire input JSON Schemas with \`# METADATA\` \`schemas:\` annotations and a schemas
|
|
73
|
-
directory passed to \`opa check -s\` / VS Code \`opa.schema\`.
|
|
74
|
-
|
|
75
|
-
## Prefer declarative result construction
|
|
76
|
-
|
|
77
|
-
String decisions inside an object remain readable and extensible. Keep one
|
|
78
|
-
result document shape and derive its fields from named rules:
|
|
79
|
-
|
|
80
|
-
\`\`\`rego
|
|
81
|
-
default decision := "deny"
|
|
82
|
-
|
|
83
|
-
decision := "allow" if {
|
|
84
|
-
input.subject.trusted == true
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
default reason_code := "untrusted_or_invalid_input"
|
|
88
|
-
|
|
89
|
-
reason_code := "trusted_subject" if {
|
|
90
|
-
decision == "allow"
|
|
91
|
-
}
|
|
92
|
-
\`\`\`
|
|
93
|
-
|
|
94
|
-
Rego rules define documents; they are not an imperative sequence of variable
|
|
95
|
-
assignments. Prefer small named predicates and one result constructor over
|
|
96
|
-
repeated branch-specific copies of the full output object.
|
|
97
|
-
|
|
98
|
-
## Fail closed
|
|
99
|
-
|
|
100
|
-
- Give the externally queried decision or result a deny/error default.
|
|
101
|
-
- Treat missing fields and unknown enum values as non-authorizing.
|
|
102
|
-
- Avoid broad truthiness checks when exact values are required.
|
|
103
|
-
- Add tests for malformed and incomplete inputs, not only expected allow cases.
|
|
104
|
-
- Add result fields compatibly so existing consumers can continue reading the
|
|
105
|
-
stable core.
|
|
106
|
-
`,V=`# Publishing
|
|
107
|
-
|
|
108
|
-
## Validate the upload contract
|
|
109
|
-
|
|
110
|
-
\`.manifest\` declares the document-tree roots included in the Policy Engine
|
|
111
|
-
bundle. Each non-test Rego package must equal a root or be nested below one.
|
|
112
|
-
Test modules remain local and are excluded from the upload archive.
|
|
113
|
-
|
|
114
|
-
In this template, the publish directory is \`{root}-bundle/\` (the folder that
|
|
115
|
-
contains \`.manifest\`), not the inner \`{root}/\` package tree alone.
|
|
116
|
-
|
|
117
|
-
Scaffolded manifests may include optional OPA \`metadata\`:
|
|
118
|
-
|
|
119
|
-
\`\`\`json
|
|
120
|
-
"metadata": {
|
|
121
|
-
"transcend.io": {
|
|
122
|
-
"template": "generic"
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
\`\`\`
|
|
126
|
-
|
|
127
|
-
\`template\` is an **authoring hint** (\`generic\` or \`permissions\`). Upload does
|
|
128
|
-
not branch on it.
|
|
129
|
-
|
|
130
|
-
Before publishing:
|
|
131
|
-
|
|
132
|
-
1. confirm the intended package and query paths with the consuming application;
|
|
133
|
-
2. run \`transcend policy lint <bundle-directory> --noInteractive\` and tests;
|
|
134
|
-
3. review the generated bundle name, version, description, and target Transcend environment;
|
|
135
|
-
4. keep API keys in the environment or the repository's approved secret store.
|
|
136
|
-
|
|
137
|
-
The publish path validates strict Rego compatibility and bundle compilation
|
|
138
|
-
before creating the upload tarball.
|
|
139
|
-
|
|
140
|
-
## Bundle names: generic vs Permissions
|
|
141
|
-
|
|
142
|
-
Upload uses one create/version path for every bundle. What makes a bundle
|
|
143
|
-
“Permissions” is convention plus where Sombra queries it:
|
|
144
|
-
|
|
145
|
-
- **Permissions API** always loads the fixed remote bundle name
|
|
146
|
-
\`permissions\`. Publish that starter with \`--bundle-name=permissions\`.
|
|
147
|
-
- **Generic / decide** bundles use any other \`--bundle-name\` and the decide
|
|
148
|
-
path.
|
|
149
|
-
|
|
150
|
-
\`policy publish\` may warn when \`.manifest\` metadata/roots look Permissions-
|
|
151
|
-
oriented but \`--bundle-name\` is not \`permissions\` (or the reverse). The warning
|
|
152
|
-
does not block upload.
|
|
153
|
-
|
|
154
|
-
## Publish deliberately
|
|
155
|
-
|
|
156
|
-
\`\`\`sh
|
|
157
|
-
# Generic / decide path
|
|
158
|
-
transcend policy publish --bundle-name example --auth "$TRANSCEND_API_KEY" \\
|
|
159
|
-
transcend/policy/example-bundle
|
|
160
|
-
|
|
161
|
-
# Permissions API path (fixed remote name)
|
|
162
|
-
transcend policy publish --bundle-name permissions --auth "$TRANSCEND_API_KEY" \\
|
|
163
|
-
transcend/policy/permissions-bundle
|
|
164
|
-
\`\`\`
|
|
165
|
-
|
|
166
|
-
Run \`transcend policy publish --help\` for current flags and scopes. Publishing
|
|
167
|
-
creates or updates remote Policy Engine bundle resources, so keep it out of
|
|
168
|
-
pull-request validation and require the repository's normal deployment approval.
|
|
169
|
-
|
|
170
|
-
Publish each \`{root}-bundle/\` separately with its own \`--bundle-name\`. Do not
|
|
171
|
-
add publishing, Transcend API credentials, or environment activation to the
|
|
172
|
-
validation-only workflow generated by \`policy init\`.
|
|
173
|
-
`,H="# Setup and tooling\n\n## Install the CLI\n\nInstall the Transcend CLI **≥ 11**:\n\n```sh\nnpm install --global @transcend-io/cli@^11\ntranscend policy --help # should list init, new, lint [<directory>], …\n```\n\n## Initialize safely\n\nRun `transcend policy init --help` before choosing flags. The default target is\n`transcend/policy`.\n\n`policy init` creates an empty multi-bundle workspace — shared Regal config\n(`project.roots: []`) and a README. No bundles or Rego are created.\n\nInteractive initialization offers VS Code setup, this Agent Skill, and\nvalidation-only GitHub Actions. Non-interactive automation enables only\nexplicitly supplied `--editor`, `--skill`, and `--ci` flags:\n\n```sh\ntranscend policy init ./transcend/policy --editor --skill --ci --noInteractive --yes\n```\n\nUse `--dryRun` to inspect the complete transactional plan. Existing policy\nfiles, manifests, Regal configuration, workflows, and customized managed\nartifacts are preserved.\n\n## Add bundles\n\nAfter initializing the workspace, add bundles with `transcend policy new`:\n\n```sh\ntranscend policy new --template generic --name example --yes\ntranscend policy new --template permissions --name permissions --yes\n```\n\nTemplates available:\n\n- `generic` — A fail-closed teaching entrypoint (default root: `example`)\n- `permissions` — A Permission API starter with purpose preferences (default root: `permissions`)\n\n`policy new` creates the `{name}-bundle/` directory, its `.manifest`, Rego tree,\ninput fixtures, and input schema. It also merges the root into Regal config and\nupdates VS Code settings/tasks when `.vscode` is present.\n\n## Required tools\n\n- Use OPA 1.x for Rego v1 parsing, formatting, checks, tests, and bundle compilation.\n- Use Regal for idiomatic Rego linting and editor language-server features.\n- Run `opa version` and `regal version` to confirm the active executables.\n\nThe generated Regal configuration targets OPA 1.18.2 capabilities. Generated CI\ninstalls OPA 1.18.2 and Regal 0.42.0; local tools only need to satisfy the\ncompatible versions reported by `policy init` and `policy lint`. Follow their\nofficial installation links when a compatible tool is missing.\n\n## Editor and CI\n\nRepository-level VS Code settings should include:\n\n- `opa.roots` — one entry per `{root}-bundle/` publish directory\n- `opa.bundleMode: true` — avoid loading fixture JSON as data\n- `opa.schema` — directory of input JSON Schemas (shared when multiple bundles\n need different envelopes)\n- `json.schemas` — optional validation of `input.json` / `input.example.json`\n\nPreserve custom settings and tasks when adapting generated editor files.\n\nGenerated GitHub Actions CI is read-only and credential-free: it installs pinned\ntools and the pinned Transcend CLI, then runs `transcend policy lint` per\npublish directory (matrix when multiple bundles exist). Locally, bare\n`transcend policy lint` verifies every child under the workspace that contains\na `.manifest`:\n\n```sh\ntranscend policy lint --noInteractive --json\ntranscend policy lint transcend/policy/example-bundle --noInteractive --json\n```\n\nAdapt triggers, runner labels, dependency installation, and caching to\nestablished repository conventions without adding publish steps or secrets.\n",U=`# Testing and debugging
|
|
174
|
-
|
|
175
|
-
## Write executable tests
|
|
176
|
-
|
|
177
|
-
Place tests next to the package they exercise and suffix test modules with
|
|
178
|
-
\`_test.rego\`. A separate \`_test\` package makes the production API and test
|
|
179
|
-
helpers easy to distinguish. Keep the \`_test\` package under the same manifest
|
|
180
|
-
root (for example \`example.result_test\`, not a sibling root), so bundle-mode
|
|
181
|
-
loads accept it.
|
|
182
|
-
|
|
183
|
-
\`\`\`rego
|
|
184
|
-
package example.result_test
|
|
185
|
-
|
|
186
|
-
import data.example.result
|
|
187
|
-
import rego.v1
|
|
188
|
-
|
|
189
|
-
test_denies_missing_input if {
|
|
190
|
-
result.decision == "deny" with input as {}
|
|
191
|
-
result.reason_code == "untrusted_or_invalid_input" with input as {}
|
|
192
|
-
}
|
|
193
|
-
\`\`\`
|
|
194
|
-
|
|
195
|
-
Cover at least:
|
|
196
|
-
|
|
197
|
-
- the ordinary allow case;
|
|
198
|
-
- explicit deny cases;
|
|
199
|
-
- absent, malformed, and unknown input;
|
|
200
|
-
- important result fields and reason codes;
|
|
201
|
-
- interactions between packages when one policy reads another document.
|
|
202
|
-
|
|
203
|
-
\`transcend policy lint\` requires a non-empty test suite.
|
|
204
|
-
|
|
205
|
-
## Use local inputs safely
|
|
206
|
-
|
|
207
|
-
Keep a sanitized \`input.example.json\` in each publish directory. \`policy new\`
|
|
208
|
-
also writes a gitignored \`input.json\` beside it (same contents) so VS Code /
|
|
209
|
-
Regal Evaluate work immediately. Customize \`input.json\` locally; keep
|
|
210
|
-
\`input.example.json\` committed and free of credentials or personal data.
|
|
211
|
-
|
|
212
|
-
## Run the complete gate
|
|
213
|
-
|
|
214
|
-
With no directory argument, \`policy lint\` and \`policy test\` verify every
|
|
215
|
-
immediate child under the workspace (\`transcend/policy\`) that contains a
|
|
216
|
-
\`.manifest\`. Pass one bundle path to target a single unit:
|
|
217
|
-
|
|
218
|
-
\`\`\`sh
|
|
219
|
-
transcend policy lint --noInteractive
|
|
220
|
-
transcend policy test
|
|
221
|
-
transcend policy lint transcend/policy/example-bundle --noInteractive
|
|
222
|
-
transcend policy test transcend/policy/example-bundle
|
|
223
|
-
opa check --strict -b transcend/policy/example-bundle -s transcend/policy/schemas
|
|
224
|
-
\`\`\`
|
|
225
|
-
|
|
226
|
-
\`policy lint\` and \`policy test\` run \`opa test -b\` (bundle mode) so a local
|
|
227
|
-
gitignored \`input.json\` beside \`input.example.json\` does not cause a merge
|
|
228
|
-
error. Prefer the CLI over raw directory-mode \`opa test\`. Strict OPA checks use
|
|
229
|
-
Rego v1 (no \`--v0-compatible\`).
|
|
230
|
-
|
|
231
|
-
Use \`transcend policy lint --help\` for formatter flags. Review Regal findings
|
|
232
|
-
deliberately instead of applying broad rewrites.
|
|
233
|
-
|
|
234
|
-
## Evaluate a query
|
|
235
|
-
|
|
236
|
-
\`policy eval\` requires an explicit bundle directory:
|
|
237
|
-
|
|
238
|
-
\`\`\`sh
|
|
239
|
-
transcend policy eval transcend/policy/example-bundle \\
|
|
240
|
-
--package data.example.result \\
|
|
241
|
-
--input transcend/policy/example-bundle/input.json
|
|
242
|
-
\`\`\`
|
|
243
|
-
|
|
244
|
-
Or pipe the envelope with \`--stdin-input\`. Use \`transcend policy eval --help\` for
|
|
245
|
-
curated \`opa eval\` pass-through flags (format, explain, metrics, and similar).
|
|
246
|
-
Exit-on-result flags like OPA \`--fail\` are not exposed — production Evaluate uses
|
|
247
|
-
the Data API (policy deny is a successful evaluation).
|
|
248
|
-
|
|
249
|
-
Or \`opa eval -b … -i …\` with the caller's query path. If the result differs from
|
|
250
|
-
expectations, inspect package paths, imports, defaults, input field presence,
|
|
251
|
-
and the selected bundle directory before changing policy logic.
|
|
252
|
-
`,W=`---
|
|
253
|
-
name: transcend-policy-engine
|
|
254
|
-
description: Sets up, authors, validates, tests, and publishes Transcend Policy Engine projects backed by OPA and Rego. Use for .manifest roots, Rego v1 policy trees, Regal configuration, local policy inputs, Policy Engine CI, or transcend policy CLI commands.
|
|
255
|
-
compatibility: Requires OPA 1.x, Regal, and Transcend CLI ≥ 11 for local validation.
|
|
256
|
-
---
|
|
257
|
-
|
|
258
|
-
# Transcend Policy Engine
|
|
259
|
-
|
|
260
|
-
Use the CLI for deterministic scaffolding and validation. Treat generated
|
|
261
|
-
examples as disposable teaching material and derive the real policy contract
|
|
262
|
-
from repository code and product requirements.
|
|
263
|
-
|
|
264
|
-
Requires **Transcend CLI ≥ 11** (\`transcend policy lint [<directory>]\`, with
|
|
265
|
-
\`init\` available).
|
|
266
|
-
|
|
267
|
-
## Workflow
|
|
268
|
-
|
|
269
|
-
1. Locate each publishable bundle directory (a directory with a \`.manifest\`;
|
|
270
|
-
\`policy new\` scaffolds these as \`{root}-bundle/\` with a \`{root}/\` package
|
|
271
|
-
tree inside).
|
|
272
|
-
2. For initialization, editor support, tools, or CI, read [references/setup-tooling.md](references/setup-tooling.md).
|
|
273
|
-
3. For package layout, document-tree design, decisions, and inputs, read [references/authoring.md](references/authoring.md).
|
|
274
|
-
4. For tests, local inputs, linting, and evaluation, read [references/testing-debugging.md](references/testing-debugging.md).
|
|
275
|
-
5. For bundle validation and publishing, read [references/publishing.md](references/publishing.md).
|
|
276
|
-
6. Preserve repository conventions and finish with:
|
|
277
|
-
|
|
278
|
-
\`\`\`sh
|
|
279
|
-
transcend policy lint --noInteractive
|
|
280
|
-
\`\`\`
|
|
281
|
-
|
|
282
|
-
## Documentation
|
|
283
|
-
|
|
284
|
-
- Every Transcend CLI command and subcommand provides contextual help with \`transcend <command> --help\`.
|
|
285
|
-
- Use the [Transcend CLI README](https://github.com/transcend-io/tools/tree/main/packages/cli#readme) for command documentation and examples.
|
|
286
|
-
- Use the [Transcend documentation index](https://docs.transcend.io/llms.txt) to find current product documentation.
|
|
287
|
-
|
|
288
|
-
## Guardrails
|
|
289
|
-
|
|
290
|
-
- Do not invent an input shape, output contract, package tree, or deployment convention.
|
|
291
|
-
- Keep decisions fail-closed and make result documents extensible.
|
|
292
|
-
- Never commit credentials or a real local \`input.json\`.
|
|
293
|
-
- Keep every publishable Rego package covered by a \`.manifest\` root.
|
|
294
|
-
- One publish directory = one Policy Engine bundle; do not merge unrelated
|
|
295
|
-
products into a single \`.manifest\` unless they share activation and callers.
|
|
296
|
-
`;const G=`transcend-policy-engine`,K=[{path:`SKILL.md`,contents:W},{path:`references/setup-tooling.md`,contents:H},{path:`references/authoring.md`,contents:B},{path:`references/testing-debugging.md`,contents:U},{path:`references/publishing.md`,contents:V}];function q(e){return`${e.hasSkill?`Use the \`${G}\` skill and run`:`Run`} ${e.newCommand} to add a bundle from a template, then adapt the policy document tree and input/output contract to the intended application.`}function J(e,n){return{version:e.version,command:e.command,applied:n.applied,dryRun:n.dryRun,targetDirectory:e.targetDirectory,manifestPath:e.manifestPath,changes:e.changes.map(e=>t(n.cwd,e)),warnings:e.warnings,nextSteps:e.nextSteps,features:[...e.features],aiHandoff:n.aiHandoff,tools:n.tools}}const Y={name:G,displayName:`Policy Engine`,owner:`@transcend-io/cli`,files:K};function X(e,t){let n=new Set(f().map(({path:t})=>P(e.targetDirectory,t))),r=new Set(t.features);return r.has(z.Editor)&&(n.add(P(e.projectRoot,`.vscode`,`settings.json`)),n.add(P(e.projectRoot,`.vscode`,`extensions.json`)),n.add(P(e.projectRoot,`.vscode`,`tasks.json`))),r.has(z.Skill)&&a(e.projectRoot,e.existingSkillDirectories,Y).forEach(e=>n.add(e)),r.has(z.Ci)&&e.repositoryRoot&&e.usesGithub&&n.add(P(e.repositoryRoot,j)),[...n].sort((e,t)=>e.localeCompare(t))}function Z(e,t){let n=I(e,t);if(n===`..`||n.startsWith(`..${L}`)||N(n))throw Error(`Refusing to modify path outside project root: ${t}`)}function re(e){let t=new Set([`${d}/input.json`]);return e.forEach(({path:e})=>{t.add(e);let n=F.dirname(e);for(;n!==`.`;)t.add(n),n=F.dirname(n)}),t}function Q(e,t,n){let r=s({snapshot:u(t.snapshots,n.path),after:n.contents,description:n.description,...n.createOnly===void 0?{}:{createOnly:n.createOnly}});r?e.changes.push(r):e.unchanged.push(n.path)}function ie(e,t,n,r,a,o){Q(e,t,{path:n,contents:r.contents,description:a}),e.warnings.push(...r.warnings.map(e=>`${e} (${i(o,n)})`))}function ae(e,t){let{state:n}=e,r=f(),a=`transcend policy new`,s={version:3,command:`init`,rootDirectory:n.projectRoot,targetDirectory:n.targetDirectory,manifestPath:n.targetDirectory,changes:[],unchanged:[],warnings:[],nextSteps:[a],features:[...t.features]},l=X(n,t);if(Z(n.projectRoot,n.targetDirectory),l.forEach(e=>Z(n.projectRoot,e)),n.relativeFilePaths.length===0)s.directoryPreconditions=[{path:n.targetDirectory,relativePaths:[...n.relativePaths]}],r.forEach(t=>{let r=P(n.targetDirectory,t.path);if(o(e.snapshots,r).kind!==`absent`)throw Error(`Expected an empty policy target, but found an entry at: ${r}`);Q(s,e,{path:r,contents:t.contents,description:t.description,createOnly:!0})});else{let t=!0;r.forEach(r=>{let a=P(n.targetDirectory,r.path),c=o(e.snapshots,a);if(c.kind===`file`&&c.contents===r.contents){s.unchanged.push(a);return}t=!1,c.kind!==`absent`&&(s.unchanged.push(a),s.warnings.push(`Existing policy scaffold path was left unchanged: ${i(n.invocationDirectory,a)}`))});let c=re(r),l=n.relativeFilePaths.some(e=>!c.has(e));(!t||l)&&s.warnings.push(`Existing policy target contains custom or partial content, so no workspace files were added or overwritten. Review ${i(n.invocationDirectory,n.targetDirectory)} manually, then run \`${a}\`.`)}let u=new Set(t.features),d=n.projectRoot;if(u.has(z.Editor)){let t=P(d,`.vscode`,`settings.json`),r=P(d,`.vscode`,`extensions.json`),a=P(d,`.vscode`,`tasks.json`);[{path:t,description:`Merge strict target-scoped OPA and Rego editor settings`,merge:(e,t,n)=>te(e,t,n)},{path:r,description:`Recommend the OPA extension and discourage its syntax-only conflict`,merge:e=>M(e)},{path:a,description:`Create the VS Code task configuration`,merge:(e,t,n)=>ne(e,t,n)}].forEach(({path:t,description:r,merge:a})=>{let c=o(e.snapshots,t);if(c.kind!==`absent`&&c.kind!==`file`){s.unchanged.push(t),s.warnings.push(`Existing VS Code artifact is not a regular file and was left unchanged: ${i(n.invocationDirectory,t)}`);return}ie(s,e,t,a(c.kind===`file`?c.contents:null,d,n.targetDirectory),r,n.invocationDirectory)})}if(u.has(z.Skill)){let t=c({rootDirectory:d,existingDirectories:n.existingSkillDirectories,snapshots:e.snapshots,skill:Y,preserveModified:!0});s.changes.push(...t.changes),s.unchanged.push(...t.unchanged),s.warnings.push(...t.warnings.map(e=>t.unchanged.reduce((e,t)=>e.replace(t,i(n.invocationDirectory,t)),e)))}if(u.has(z.Ci))if(!n.repositoryRoot||!n.usesGithub)s.warnings.push(`GitHub Actions setup was selected, but this target is not inside a detected GitHub repository.`);else{let r=P(n.repositoryRoot,j),a=I(n.repositoryRoot,n.targetDirectory).split(L).join(`/`)||`.`,c=A({cliVersion:t.cliVersion,workspaceDirectory:a,bundleDirectories:[]}),l=o(e.snapshots,r);l.kind===`absent`?Q(s,e,{path:r,contents:c,description:`Add credential-free Policy Engine validation`,createOnly:!0}):l.kind===`file`&&l.contents===c?s.unchanged.push(r):(s.unchanged.push(r),s.warnings.push(`Existing GitHub Actions workflow was left unchanged: ${i(n.invocationDirectory,r)}. Adapt it manually to validate each policy bundle.`))}return s.changes.forEach(({path:e})=>Z(n.projectRoot,e)),s}const oe={[z.Editor]:`VS Code settings and lint task`,[z.Skill]:`Policy Engine Agent Skill`,[z.Ci]:`Validation-only GitHub Actions`},se=Object.values(z);function $(e,t){let n=[t.stdout.trim(),t.stderr.trim()].filter(Boolean).join(`
|
|
297
|
-
`),r=e===`OPA`?ee:g;return`${e===`OPA`?`OPA 1.x`:`Regal ${S} or newer`} is required, but \`${e.toLowerCase()} version\` exited with code ${t.code}${n?`: ${n}`:`.`} Install or upgrade it using the official instructions: ${r}`}async function ce(e,t,n){let r={opa:null,regal:null},i=[],a=await n(`opa`,[`version`],{cwd:t},e);if(a.error?.code===`ENOENT`)i.push(v);else{let e=`${a.stdout}\n${a.stderr}`,t=_(e);a.code===0?t?i.push(t):r.opa=x(e).version:i.push(t??$(`OPA`,a))}let o=await n(`regal`,[`version`],{cwd:t},e);if(o.error?.code===`ENOENT`)i.push(b);else{let e=`${o.stdout}\n${o.stderr}`,t=y(e,S,`the generated OPA ${p} capabilities configuration`);o.code===0?t?i.push(t):r.regal=x(e).version:i.push(t??$(`Regal`,o))}return{tools:r,warnings:i}}async function le(t,a=h,o=O){C(this.process);try{let s=await ce(this,this.process.cwd(),o),c=m(this,a),u=new T(this),d=E(t,this.process.stdin.isTTY,this.process.stderr.isTTY),f=await w(u,{features:se,labels:oe,enabled:{[z.Editor]:t.editor,[z.Skill]:t.skill,[z.Ci]:t.ci},interactive:d}),p=X(c,{features:f}),h=ae({state:c,snapshots:l(this,c.projectRoot,p)},{features:f,cliVersion:e});h.warnings.push(...s.warnings),t.json||this.logger.info(r(h,{cwd:this.process.cwd(),title:`Policy initialization plan`,details:[{label:`Target`,path:h.targetDirectory}]}));let g=h.changes.length===0||t.dryRun;if(h.changes.length>0&&!t.dryRun)if(t.yes)g=!0;else if(d)g=await u.confirm(`Apply this complete plan?`,!0);else throw Error(`The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.`);g&&!t.dryRun&&h.changes.length>0&&await k(this,h);let _=g&&!t.dryRun&&h.changes.length>0,v=g&&!t.dryRun,y=q({projectPath:n(i(this.process.cwd(),c.targetDirectory)),hasSkill:v&&f.includes(z.Skill),newCommand:h.nextSteps[0]}),b=J(h,{applied:_,dryRun:t.dryRun,cwd:this.process.cwd(),aiHandoff:y,tools:s.tools});if(t.json){this.process.stdout.write(`${JSON.stringify(b)}\n`);return}if(t.dryRun){this.logger.info(R.yellow(`Dry run complete. No changes were written.`));return}if(!g){this.logger.info(R.yellow(`No changes applied.`));return}if(h.changes.length===0){let e=h.warnings.length===s.warnings.length?`Policy project is already initialized.`:`Existing policy project was left unchanged.`;this.logger.info(R.green(e))}else this.logger.info(R.green(`Policy project initialized.`));h.nextSteps.length>0&&(this.logger.info(`\n${R.bold(`Next steps`)}`),h.nextSteps.forEach(e=>this.logger.info(e))),this.logger.info(`\n${R.bold(`AI handoff — paste into your coding agent`)}`),this.logger.info(y)}catch(e){if(e instanceof D)return this.process.exit(130);throw e}}export{le as init};
|
|
298
|
-
//# sourceMappingURL=impl-DQcgEx7V2.mjs.map
|
package/dist/impl-DezV3QMo.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{r as e,t}from"./policyEngineCliError-CZrOHhLv.mjs";import{i as n,r,t as i}from"./printResult-C2K9ODeE.mjs";import{t as a}from"./formatPolicyBundleVersionSummary-DCHl1Vhy.mjs";import{n as o}from"./resolveBundleIdByName-Dm_o5_bg.mjs";import{t as s}from"./done-input-validation-LiTaCEzF.mjs";import{t as c}from"./command-output-BJcDRXNr.mjs";import l from"colors";async function u({"bundle-name":u,auth:d,"transcend-url":f,json:p,debug:m=!1}){s(this.process),e(m);let h=c(this.logger,p),g=n(f,d),_=await o(g,u);if(!_)throw Error(`Policy bundle "${u}" was not found for this organization.`);h.info(l.green(`Deactivating active version for bundle "${u}"...`));let v;try{v=await g.post(`v1/policy-engine/policy-bundles/${_}/deactivate`).json()}catch(e){if(e?.response?.statusCode===409)throw new t(`Policy bundle "${u}" has no active version.`,{cause:e});r(e)}i(this.process.stdout,{json:p,data:v,renderTable:()=>[`bundleId ${v.bundle.id}`,`bundleName ${v.bundle.bundleName}`,a(v.version)].join(`
|
|
2
|
-
`)}),h.info(l.green(`Policy bundle version deactivated.`))}export{u as deactivate};
|
|
3
|
-
//# sourceMappingURL=impl-DezV3QMo.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"impl-DezV3QMo.mjs","names":[],"sources":["../src/commands/policy/deactivate/impl.ts"],"sourcesContent":["import colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n buildPolicyEngineClient,\n formatPolicyBundleVersionSummary,\n printResult,\n resolveBundleIdByName,\n setPolicyEngineCliDebug,\n throwPolicyEngineRequestError,\n PolicyEngineCliError,\n} from '../helpers/index.js';\nimport type { DeactivatePolicyBundleResponse } from '../types.js';\n\n/** CLI flags for `transcend policy deactivate`. */\nexport interface DeactivateCommandFlags {\n /** Logical bundle name to deactivate */\n 'bundle-name': string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Print raw JSON response */\n json: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Deactivate the currently active version of a policy bundle.\n *\n * Resolves `--bundle-name` to the parent bundle UUID internally, then calls the\n * Policy Engine deactivate endpoint. The bundle is addressed by name only -- the\n * UUID is never exposed to the operator.\n *\n * @param this - CLI context\n * @param flags - Command flags\n */\nexport async function deactivate(\n this: LocalContext,\n {\n 'bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n json,\n debug = false,\n }: DeactivateCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const commandLogger = selectCommandLogger(this.logger, json);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n\n const resolvedBundleId = await resolveBundleIdByName(client, bundleName);\n if (!resolvedBundleId) {\n throw new Error(`Policy bundle \"${bundleName}\" was not found for this organization.`);\n }\n\n commandLogger.info(colors.green(`Deactivating active version for bundle \"${bundleName}\"...`));\n\n let body: DeactivatePolicyBundleResponse;\n try {\n body = await client\n .post(`v1/policy-engine/policy-bundles/${resolvedBundleId}/deactivate`)\n .json<DeactivatePolicyBundleResponse>();\n } catch (err) {\n // The monolith 409 references the internal bundle UUID; rewrite it to the\n // user-supplied bundle name so the error is actionable.\n const statusCode = (err as { response?: { statusCode?: number } })?.response?.statusCode;\n if (statusCode === 409) {\n throw new PolicyEngineCliError(`Policy bundle \"${bundleName}\" has no active version.`, {\n cause: err,\n });\n }\n throwPolicyEngineRequestError(err);\n }\n\n printResult(this.process.stdout, {\n json,\n data: body,\n renderTable: () =>\n [\n `bundleId ${body.bundle.id}`,\n `bundleName ${body.bundle.bundleName}`,\n formatPolicyBundleVersionSummary(body.version),\n ].join('\\n'),\n });\n\n commandLogger.info(colors.green('Policy bundle version deactivated.'));\n}\n"],"mappings":"gXAwCA,eAAsB,EAEpB,CACE,cAAe,EACf,OACA,gBAAiB,EACjB,OACA,QAAQ,IAEK,CACf,EAAoB,KAAK,QAAQ,CACjC,EAAwB,EAAM,CAE9B,IAAM,EAAgB,EAAoB,KAAK,OAAQ,EAAK,CACtD,EAAS,EAAwB,EAAc,EAAK,CAEpD,EAAmB,MAAM,EAAsB,EAAQ,EAAW,CACxE,GAAI,CAAC,EACH,MAAU,MAAM,kBAAkB,EAAW,wCAAwC,CAGvF,EAAc,KAAK,EAAO,MAAM,2CAA2C,EAAW,MAAM,CAAC,CAE7F,IAAI,EACJ,GAAI,CACF,EAAO,MAAM,EACV,KAAK,mCAAmC,EAAiB,aAAa,CACtE,MAAsC,OAClC,EAAK,CAIZ,GADoB,GAAgD,UAAU,aAC3D,IACjB,MAAM,IAAI,EAAqB,kBAAkB,EAAW,0BAA2B,CACrF,MAAO,EACR,CAAC,CAEJ,EAA8B,EAAI,CAGpC,EAAY,KAAK,QAAQ,OAAQ,CAC/B,OACA,KAAM,EACN,gBACE,CACE,eAAe,EAAK,OAAO,KAC3B,eAAe,EAAK,OAAO,aAC3B,EAAiC,EAAK,QAAQ,CAC/C,CAAC,KAAK;EAAK,CACf,CAAC,CAEF,EAAc,KAAK,EAAO,MAAM,qCAAqC,CAAC"}
|
package/dist/impl-btKJ1-VJ.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{r as e,t}from"./policyEngineCliError-CZrOHhLv.mjs";import{i as n,n as r,t as i}from"./printResult-C2K9ODeE.mjs";import{t as a}from"./formatPolicyBundleVersionSummary-DCHl1Vhy.mjs";import{n as o}from"./resolveBundleIdByName-Dm_o5_bg.mjs";import{t as s}from"./resolvePolicyBundleVersion-DRUwe7fA.mjs";import{t as c}from"./done-input-validation-LiTaCEzF.mjs";import{t as l}from"./command-output-BJcDRXNr.mjs";import u from"colors";async function d({"bundle-name":d,version:f,auth:p,"transcend-url":m,"dry-run":h,json:g,debug:_=!1}){c(this.process),e(_);let v=l(this.logger,g),y=n(m,p),b=await o(y,d);if(!b)throw Error(`Policy bundle "${d}" was not found for this organization.`);let x=await s(y,b,{version:f});v.info(u.green(h?`Validating activation for version "${x.version}"...`:`Activating version "${x.version}"...`));let S;try{S=await r(y.post(`v1/policy-engine/policy-bundles/${b}/versions/${x.id}/activate`,{json:h?{dryRun:!0}:{}}).json())}catch(e){throw(e instanceof t?e.cause:void 0)?.response?.statusCode===409?new t(`Version "${x.version}" of policy bundle "${d}" is already the active version.`,{cause:e}):e}i(this.process.stdout,{json:g,data:S,renderTable:()=>[`bundleId ${S.bundle.id}`,`bundleName ${S.bundle.bundleName}`,a(S.version)].join(`
|
|
2
|
-
`)}),v.info(u.green(h?`Activation validation succeeded.`:`Policy bundle version activated.`))}export{d as activate};
|
|
3
|
-
//# sourceMappingURL=impl-btKJ1-VJ.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"impl-btKJ1-VJ.mjs","names":[],"sources":["../src/commands/policy/activate/impl.ts"],"sourcesContent":["import colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n buildPolicyEngineClient,\n formatPolicyBundleVersionSummary,\n policyEngineRequest,\n PolicyEngineCliError,\n printResult,\n resolveBundleIdByName,\n resolvePolicyBundleVersion,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { ActivatePolicyBundleVersionResponse } from '../types.js';\n\n/** CLI flags for `transcend policy activate`. */\nexport interface ActivateCommandFlags {\n /** Logical bundle name to activate */\n 'bundle-name': string;\n /** Caller-supplied version label to activate */\n version?: string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Validate activation without flipping */\n 'dry-run': boolean;\n /** Print raw JSON response */\n json: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Activate an uploaded policy bundle version.\n *\n * Resolves `--bundle-name` to the parent bundle UUID internally, then calls the\n * Policy Engine activate endpoint. The bundle is addressed by name only -- the\n * UUID is never exposed to the operator.\n *\n * @param this - CLI context\n * @param flags - Command flags\n */\nexport async function activate(\n this: LocalContext,\n {\n 'bundle-name': bundleName,\n version,\n auth,\n 'transcend-url': transcendUrl,\n 'dry-run': dryRun,\n json,\n debug = false,\n }: ActivateCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const commandLogger = selectCommandLogger(this.logger, json);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const resolvedBundleId = await resolveBundleIdByName(client, bundleName);\n if (!resolvedBundleId) {\n throw new Error(`Policy bundle \"${bundleName}\" was not found for this organization.`);\n }\n const resolvedVersion = await resolvePolicyBundleVersion(client, resolvedBundleId, { version });\n\n commandLogger.info(\n colors.green(\n dryRun\n ? `Validating activation for version \"${resolvedVersion.version}\"...`\n : `Activating version \"${resolvedVersion.version}\"...`,\n ),\n );\n\n let body: ActivatePolicyBundleVersionResponse;\n try {\n body = await policyEngineRequest(\n client\n .post(\n `v1/policy-engine/policy-bundles/${resolvedBundleId}/versions/${resolvedVersion.id}/activate`,\n {\n json: dryRun ? { dryRun: true } : {},\n },\n )\n .json<ActivatePolicyBundleVersionResponse>(),\n );\n } catch (err) {\n // A 409 here means the requested version is already the active version --\n // surface that specifically (referencing the operator-facing bundle name\n // and version label) rather than the generic conflict fallback.\n const statusCode = (\n err instanceof PolicyEngineCliError\n ? (err.cause as { response?: { statusCode?: number } } | undefined)\n : undefined\n )?.response?.statusCode;\n if (statusCode === 409) {\n throw new PolicyEngineCliError(\n `Version \"${resolvedVersion.version}\" of policy bundle \"${bundleName}\" is already the active version.`,\n { cause: err },\n );\n }\n throw err;\n }\n\n printResult(this.process.stdout, {\n json,\n data: body,\n renderTable: () =>\n [\n `bundleId ${body.bundle.id}`,\n `bundleName ${body.bundle.bundleName}`,\n formatPolicyBundleVersionSummary(body.version),\n ].join('\\n'),\n });\n\n commandLogger.info(\n colors.green(dryRun ? 'Activation validation succeeded.' : 'Policy bundle version activated.'),\n );\n}\n"],"mappings":"mbA6CA,eAAsB,EAEpB,CACE,cAAe,EACf,UACA,OACA,gBAAiB,EACjB,UAAW,EACX,OACA,QAAQ,IAEK,CACf,EAAoB,KAAK,QAAQ,CACjC,EAAwB,EAAM,CAE9B,IAAM,EAAgB,EAAoB,KAAK,OAAQ,EAAK,CACtD,EAAS,EAAwB,EAAc,EAAK,CACpD,EAAmB,MAAM,EAAsB,EAAQ,EAAW,CACxE,GAAI,CAAC,EACH,MAAU,MAAM,kBAAkB,EAAW,wCAAwC,CAEvF,IAAM,EAAkB,MAAM,EAA2B,EAAQ,EAAkB,CAAE,UAAS,CAAC,CAE/F,EAAc,KACZ,EAAO,MACL,EACI,sCAAsC,EAAgB,QAAQ,MAC9D,uBAAuB,EAAgB,QAAQ,MACpD,CACF,CAED,IAAI,EACJ,GAAI,CACF,EAAO,MAAM,EACX,EACG,KACC,mCAAmC,EAAiB,YAAY,EAAgB,GAAG,WACnF,CACE,KAAM,EAAS,CAAE,OAAQ,GAAM,CAAG,EAAE,CACrC,CACF,CACA,MAA2C,CAC/C,OACM,EAAK,CAeZ,MAVE,aAAe,EACV,EAAI,MACL,IAAA,KACH,UAAU,aACM,IACX,IAAI,EACR,YAAY,EAAgB,QAAQ,sBAAsB,EAAW,kCACrE,CAAE,MAAO,EAAK,CACf,CAEG,EAGR,EAAY,KAAK,QAAQ,OAAQ,CAC/B,OACA,KAAM,EACN,gBACE,CACE,eAAe,EAAK,OAAO,KAC3B,eAAe,EAAK,OAAO,aAC3B,EAAiC,EAAK,QAAQ,CAC/C,CAAC,KAAK;EAAK,CACf,CAAC,CAEF,EAAc,KACZ,EAAO,MAAM,EAAS,mCAAqC,mCAAmC,CAC/F"}
|
package/dist/impl-ijoNwhGI.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{g as e}from"./constants-BRsj50Nb.mjs";import{n as t,r as n,t as r}from"./project-plan-output-BHHlkLxe.mjs";import{d as i,f as a,t as o,u as s}from"./project-discovery-CWRjlFnC.mjs";import{_ as c,d as l,f as u,h as ee,m as d,o as f,p,r as m,t as h}from"./policy-project-discovery-C29UxWwt.mjs";import{t as g}from"./done-input-validation-LiTaCEzF.mjs";import{n as te,r as _,t as v}from"./prompts-BhXfYD6g.mjs";import{t as y}from"./project-plan-apply-Bg_1eMX9.mjs";import{a as b,i as x,n as S,r as C}from"./policy-scaffold-config-BUKAyPad.mjs";import{join as w,relative as T,sep as E}from"node:path";import D from"colors";const O=/^[a-z][a-z0-9_]*$/u;function k(e){return e?O.test(e)?e.length>64?`Root name cannot exceed 64 characters.`:!0:`Root name must be lowercase alphanumeric with underscores (e.g. "example", "permissions").`:`Enter a bundle root name.`}async function A(O,A=h){g(this.process);try{let h=m(this,A),g=w(h.targetDirectory,`.regal`,`config.yaml`);if(!this.fs.existsSync(g))throw Error(`No policy workspace found at ${r(h.invocationDirectory,h.targetDirectory)}. Run \`transcend policy init\` first.`);let v=new te(this),j=_(O,this.process.stdin.isTTY,this.process.stderr.isTTY),M=O.template??(j?await v.select(`Template:`,u.map(e=>({name:p[e],value:e})),u[0]):void 0);if(!M||!u.includes(M))throw Error(`Missing policy template. Pass --template=${u.join(` or --template=`)}.`);let N=l[M],P=O.name??(j?await v.text(`Bundle root name:`,N,e=>{let t=k(e);return t===!0?!0:t}):void 0);if(!P)throw Error(`Missing bundle root name. Pass --name in a non-interactive invocation.`);let F=k(P);if(F!==!0)throw Error(F);let I=d(P),L=w(h.targetDirectory,I);if(this.fs.existsSync(L))throw Error(`Bundle directory already exists: ${r(h.invocationDirectory,L)}. Choose a different --name.`);let R=ee(M,P),{contents:z,roots:B}=c(this.fs.readFileSync(g,`utf8`),P),V=[g,...R.map(({path:e})=>w(h.targetDirectory,e))],H=w(h.projectRoot,`.vscode`,`settings.json`),U=w(h.projectRoot,`.vscode`,`tasks.json`),W=this.fs.existsSync(w(h.projectRoot,`.vscode`));W&&V.push(H,U);let G=h.repositoryRoot&&h.usesGithub?w(h.repositoryRoot,x):void 0;G&&this.fs.existsSync(G)&&V.push(G);let K=o(this,h.projectRoot,V.sort((e,t)=>e.localeCompare(t))),q=[],J=[],Y=[],X=a({snapshot:s(K,g),after:z,description:`Merge ${P} root into Regal config`});if(X?q.push(X):Y.push(g),R.forEach(e=>{let t=w(h.targetDirectory,e.path);if(i(K,t).kind!==`absent`)throw Error(`Expected an empty path but found an entry at: ${t}`);let n=a({snapshot:s(K,t),after:e.contents,description:e.description});n?q.push(n):Y.push(t)}),W){let e=i(K,H);if(e.kind===`file`||e.kind===`absent`){let t=S(e.kind===`file`?e.contents:null,h.projectRoot,h.targetDirectory,B),n=a({snapshot:e.kind===`file`?{path:H,contents:e.contents,mode:e.mode}:{path:H,contents:null},after:t.contents,description:`Merge bundle root into VS Code OPA settings`});n?q.push(n):Y.push(H),J.push(...t.warnings.map(e=>`${e} (${r(h.invocationDirectory,H)})`))}let t=i(K,U);if(t.kind===`file`||t.kind===`absent`){let e=C(t.kind===`file`?t.contents:null,h.projectRoot,h.targetDirectory,B),n=a({snapshot:t.kind===`file`?{path:U,contents:t.contents,mode:t.mode}:{path:U,contents:null},after:e.contents,description:`Add per-bundle and aggregate lint tasks`});n?q.push(n):Y.push(U),J.push(...e.warnings.map(e=>`${e} (${r(h.invocationDirectory,U)})`))}}if(G&&h.repositoryRoot){let t=i(K,G);if(t.kind===`file`){let n=T(h.repositoryRoot,h.targetDirectory).split(E).join(`/`)||`.`,i=b({cliVersion:e,workspaceDirectory:n,bundleDirectories:B.map(e=>{let t=d(e);return n===`.`?t:`${n}/${t}`})});if(t.contents.startsWith(`# Generated by transcend policy init`)){let e=a({snapshot:{path:G,contents:t.contents,mode:t.mode},after:i,description:`Update Policy Engine CI matrix for all publish directories`});e?q.push(e):Y.push(G)}else J.push(`Existing GitHub Actions workflow was left unchanged: ${r(h.invocationDirectory,G)}. Adapt it manually to lint each \`*-bundle/\` publish directory.`),Y.push(G)}}let Z=`transcend policy lint ${t(r(h.invocationDirectory,L))} --noInteractive`,Q={rootDirectory:h.projectRoot,targetDirectory:h.targetDirectory,manifestPath:w(L,f),changes:q,unchanged:Y,warnings:J,nextSteps:[Z]};O.json||this.logger.info(n(Q,{cwd:this.process.cwd(),title:`Policy bundle plan`,details:[{label:`Workspace`,path:Q.targetDirectory},{label:`Bundle`,path:L}]}));let $=Q.changes.length===0||O.dryRun;if(Q.changes.length>0&&!O.dryRun)if(O.yes)$=!0;else if(j)$=await v.confirm(`Apply this complete plan?`,!0);else throw Error(`The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.`);$&&!O.dryRun&&Q.changes.length>0&&await y(this,Q);let ne=$&&!O.dryRun&&Q.changes.length>0;if(O.json){this.process.stdout.write(`${JSON.stringify({applied:ne,dryRun:O.dryRun,template:M,root:P,bundleDirectory:L,targetDirectory:Q.targetDirectory,manifestPath:Q.manifestPath,changes:Q.changes.map(e=>({kind:e.kind,target:r(this.process.cwd(),e.path),description:e.description})),warnings:Q.warnings,nextSteps:Q.nextSteps})}\n`);return}if(O.dryRun){this.logger.info(D.yellow(`Dry run complete. No changes were written.`));return}if(!$){this.logger.info(D.yellow(`No changes applied.`));return}this.logger.info(D.green(`Policy bundle ${P} added.`)),Q.nextSteps.length>0&&(this.logger.info(`\n${D.bold(`Next steps`)}`),Q.nextSteps.forEach(e=>this.logger.info(e)))}catch(e){throw e instanceof v&&this.process.exit(130),e}}export{A as _new};
|
|
2
|
-
//# sourceMappingURL=impl-ijoNwhGI.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"impl-ijoNwhGI.mjs","names":["CLI_VERSION"],"sources":["../src/commands/policy/new/impl.ts"],"sourcesContent":["import { join, relative, sep } from 'node:path';\n\nimport colors from 'colors';\n\nimport { version as CLI_VERSION } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyProject,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n generatePolicyGithubActionsWorkflow,\n POLICY_CI_WORKFLOW_PATH,\n} from '../../../lib/policy/policy-scaffold-artifacts.js';\nimport {\n mergePolicyEditorSettings,\n mergePolicyEditorTasks,\n} from '../../../lib/policy/policy-scaffold-config.js';\nimport {\n buildBundleDirectoryName,\n generatePolicyBundleFiles,\n mergePolicyRegalConfigRoots,\n POLICY_MANIFEST_FILENAME,\n POLICY_TEMPLATE_DEFAULT_ROOTS,\n POLICY_TEMPLATE_NAMES,\n POLICY_TEMPLATE_PROMPT_LABELS,\n type PolicyTemplateName,\n} from '../../../lib/policy/policy-scaffold-templates.js';\nimport { collectPlanningSnapshots } from '../../../lib/scaffolding/project-discovery.js';\nimport { applyProjectPlan } from '../../../lib/scaffolding/project-plan-apply.js';\nimport {\n displayProjectPath,\n quoteShellArgument,\n renderProjectPlan,\n} from '../../../lib/scaffolding/project-plan-output.js';\nimport {\n planFileChange,\n getPlanningFileSnapshot,\n getPlanningPathSnapshot,\n type PlannedChange,\n type ProjectPlan,\n} from '../../../lib/scaffolding/project-plan.js';\nimport {\n isInteractivePromptInvocation,\n PromptCancelledError,\n ScaffoldPrompts,\n} from '../../../lib/scaffolding/prompts.js';\n\n/** Flags for `transcend policy new`. */\nexport interface PolicyNewFlags {\n /** Package root name. */\n name?: string;\n /** Starter template. */\n template?: PolicyTemplateName;\n /** Disable prompts. */\n noInteractive: boolean;\n /** Render but do not apply. */\n dryRun: boolean;\n /** Approve the final displayed plan. */\n yes: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/** Validate a bundle root name. */\nconst VALID_ROOT_PATTERN = /^[a-z][a-z0-9_]*$/u;\n\n/**\n * Validate a policy bundle root name.\n *\n * @param value - Proposed root name\n * @returns True or error message\n */\nfunction validateRootName(value: string): true | string {\n if (!value) {\n return 'Enter a bundle root name.';\n }\n if (!VALID_ROOT_PATTERN.test(value)) {\n return 'Root name must be lowercase alphanumeric with underscores (e.g. \"example\", \"permissions\").';\n }\n if (value.length > 64) {\n return 'Root name cannot exceed 64 characters.';\n }\n return true;\n}\n\n/**\n * Scaffold one policy bundle from a template.\n *\n * @param this - CLI context\n * @param flags - Template and interaction flags\n * @param directory - Target policy workspace directory\n */\nexport async function _new(\n this: LocalContext,\n flags: PolicyNewFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n): Promise<void> {\n doneInputValidation(this.process);\n try {\n const state = discoverPolicyProject(this, directory);\n const regalConfigPath = join(state.targetDirectory, '.regal', 'config.yaml');\n\n if (!this.fs.existsSync(regalConfigPath)) {\n throw new Error(\n `No policy workspace found at ${displayProjectPath(\n state.invocationDirectory,\n state.targetDirectory,\n )}. Run \\`transcend policy init\\` first.`,\n );\n }\n\n const prompts = new ScaffoldPrompts(this);\n const interactive = isInteractivePromptInvocation(\n flags,\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n\n const template =\n flags.template ??\n (interactive\n ? await prompts.select<PolicyTemplateName>(\n 'Template:',\n POLICY_TEMPLATE_NAMES.map((value) => ({\n name: POLICY_TEMPLATE_PROMPT_LABELS[value],\n value,\n })),\n POLICY_TEMPLATE_NAMES[0],\n )\n : undefined);\n if (!template || !POLICY_TEMPLATE_NAMES.includes(template)) {\n throw new Error(\n `Missing policy template. Pass --template=${POLICY_TEMPLATE_NAMES.join(' or --template=')}.`,\n );\n }\n\n const defaultRoot = POLICY_TEMPLATE_DEFAULT_ROOTS[template];\n const name =\n flags.name ??\n (interactive\n ? await prompts.text('Bundle root name:', defaultRoot, (value) => {\n const result = validateRootName(value);\n return result === true ? true : result;\n })\n : undefined);\n if (!name) {\n throw new Error('Missing bundle root name. Pass --name in a non-interactive invocation.');\n }\n const rootValidation = validateRootName(name);\n if (rootValidation !== true) {\n throw new Error(rootValidation);\n }\n\n const bundleDir = buildBundleDirectoryName(name);\n const bundlePath = join(state.targetDirectory, bundleDir);\n if (this.fs.existsSync(bundlePath)) {\n throw new Error(\n `Bundle directory already exists: ${displayProjectPath(\n state.invocationDirectory,\n bundlePath,\n )}. Choose a different --name.`,\n );\n }\n\n const files = generatePolicyBundleFiles(template, name);\n const existingRegalContents = this.fs.readFileSync(regalConfigPath, 'utf8');\n const { contents: updatedRegalConfig, roots: allRoots } = mergePolicyRegalConfigRoots(\n existingRegalContents,\n name,\n );\n\n const candidatePaths = [\n regalConfigPath,\n ...files.map(({ path }) => join(state.targetDirectory, path)),\n ];\n\n const vscodeSettingsPath = join(state.projectRoot, '.vscode', 'settings.json');\n const vscodeTasksPath = join(state.projectRoot, '.vscode', 'tasks.json');\n const hasVscode = this.fs.existsSync(join(state.projectRoot, '.vscode'));\n if (hasVscode) {\n candidatePaths.push(vscodeSettingsPath, vscodeTasksPath);\n }\n\n const workflowPath =\n state.repositoryRoot && state.usesGithub\n ? join(state.repositoryRoot, POLICY_CI_WORKFLOW_PATH)\n : undefined;\n if (workflowPath && this.fs.existsSync(workflowPath)) {\n candidatePaths.push(workflowPath);\n }\n\n const snapshots = collectPlanningSnapshots(\n this,\n state.projectRoot,\n candidatePaths.sort((a, b) => a.localeCompare(b)),\n );\n\n const changes: PlannedChange[] = [];\n const warnings: string[] = [];\n const unchanged: string[] = [];\n\n const regalChange = planFileChange({\n snapshot: getPlanningFileSnapshot(snapshots, regalConfigPath),\n after: updatedRegalConfig,\n description: `Merge ${name} root into Regal config`,\n });\n if (regalChange) {\n changes.push(regalChange);\n } else {\n unchanged.push(regalConfigPath);\n }\n\n files.forEach((file) => {\n const path = join(state.targetDirectory, file.path);\n const snapshot = getPlanningPathSnapshot(snapshots, path);\n if (snapshot.kind !== 'absent') {\n throw new Error(`Expected an empty path but found an entry at: ${path}`);\n }\n const change = planFileChange({\n snapshot: getPlanningFileSnapshot(snapshots, path),\n after: file.contents,\n description: file.description,\n });\n if (change) {\n changes.push(change);\n } else {\n unchanged.push(path);\n }\n });\n\n if (hasVscode) {\n const settingsSnapshot = getPlanningPathSnapshot(snapshots, vscodeSettingsPath);\n if (settingsSnapshot.kind === 'file' || settingsSnapshot.kind === 'absent') {\n const settingsResult = mergePolicyEditorSettings(\n settingsSnapshot.kind === 'file' ? settingsSnapshot.contents : null,\n state.projectRoot,\n state.targetDirectory,\n allRoots,\n );\n const settingsChange = planFileChange({\n snapshot:\n settingsSnapshot.kind === 'file'\n ? {\n path: vscodeSettingsPath,\n contents: settingsSnapshot.contents,\n mode: settingsSnapshot.mode,\n }\n : { path: vscodeSettingsPath, contents: null },\n after: settingsResult.contents,\n description: 'Merge bundle root into VS Code OPA settings',\n });\n if (settingsChange) {\n changes.push(settingsChange);\n } else {\n unchanged.push(vscodeSettingsPath);\n }\n warnings.push(\n ...settingsResult.warnings.map(\n (w) => `${w} (${displayProjectPath(state.invocationDirectory, vscodeSettingsPath)})`,\n ),\n );\n }\n\n const tasksSnapshot = getPlanningPathSnapshot(snapshots, vscodeTasksPath);\n if (tasksSnapshot.kind === 'file' || tasksSnapshot.kind === 'absent') {\n const tasksResult = mergePolicyEditorTasks(\n tasksSnapshot.kind === 'file' ? tasksSnapshot.contents : null,\n state.projectRoot,\n state.targetDirectory,\n allRoots,\n );\n const tasksChange = planFileChange({\n snapshot:\n tasksSnapshot.kind === 'file'\n ? {\n path: vscodeTasksPath,\n contents: tasksSnapshot.contents,\n mode: tasksSnapshot.mode,\n }\n : { path: vscodeTasksPath, contents: null },\n after: tasksResult.contents,\n description: 'Add per-bundle and aggregate lint tasks',\n });\n if (tasksChange) {\n changes.push(tasksChange);\n } else {\n unchanged.push(vscodeTasksPath);\n }\n warnings.push(\n ...tasksResult.warnings.map(\n (w) => `${w} (${displayProjectPath(state.invocationDirectory, vscodeTasksPath)})`,\n ),\n );\n }\n }\n\n if (workflowPath && state.repositoryRoot) {\n const workflowSnapshot = getPlanningPathSnapshot(snapshots, workflowPath);\n if (workflowSnapshot.kind === 'file') {\n const workspaceDirectory =\n relative(state.repositoryRoot, state.targetDirectory).split(sep).join('/') || '.';\n const bundleDirectories = allRoots.map((root) => {\n const bundle = buildBundleDirectoryName(root);\n return workspaceDirectory === '.' ? bundle : `${workspaceDirectory}/${bundle}`;\n });\n const desiredWorkflow = generatePolicyGithubActionsWorkflow({\n cliVersion: CLI_VERSION,\n workspaceDirectory,\n bundleDirectories,\n });\n if (workflowSnapshot.contents.startsWith('# Generated by transcend policy init')) {\n const workflowChange = planFileChange({\n snapshot: {\n path: workflowPath,\n contents: workflowSnapshot.contents,\n mode: workflowSnapshot.mode,\n },\n after: desiredWorkflow,\n description: 'Update Policy Engine CI matrix for all publish directories',\n });\n if (workflowChange) {\n changes.push(workflowChange);\n } else {\n unchanged.push(workflowPath);\n }\n } else {\n warnings.push(\n `Existing GitHub Actions workflow was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n workflowPath,\n )}. Adapt it manually to lint each \\`*-bundle/\\` publish directory.`,\n );\n unchanged.push(workflowPath);\n }\n }\n }\n\n const lintCommand = `transcend policy lint ${quoteShellArgument(\n displayProjectPath(state.invocationDirectory, bundlePath),\n )} --noInteractive`;\n\n const plan: ProjectPlan & {\n /** Absolute workspace directory. */\n targetDirectory: string;\n /** Absolute manifest path. */\n manifestPath: string;\n /** Unchanged paths. */\n unchanged: string[];\n /** Non-fatal warnings. */\n warnings: string[];\n /** Follow-up commands. */\n nextSteps: string[];\n } = {\n rootDirectory: state.projectRoot,\n targetDirectory: state.targetDirectory,\n manifestPath: join(bundlePath, POLICY_MANIFEST_FILENAME),\n changes,\n unchanged,\n warnings,\n nextSteps: [lintCommand],\n };\n\n if (!flags.json) {\n this.logger.info(\n renderProjectPlan(plan, {\n cwd: this.process.cwd(),\n title: 'Policy bundle plan',\n details: [\n { label: 'Workspace', path: plan.targetDirectory },\n { label: 'Bundle', path: bundlePath },\n ],\n }),\n );\n }\n\n let approved = plan.changes.length === 0 || flags.dryRun;\n if (plan.changes.length > 0 && !flags.dryRun) {\n if (flags.yes) {\n approved = true;\n } else if (interactive) {\n approved = await prompts.confirm('Apply this complete plan?', true);\n } else {\n throw new Error(\n 'The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.',\n );\n }\n }\n\n if (approved && !flags.dryRun && plan.changes.length > 0) {\n await applyProjectPlan(this, plan);\n }\n const applied = approved && !flags.dryRun && plan.changes.length > 0;\n\n if (flags.json) {\n this.process.stdout.write(\n `${JSON.stringify({\n applied,\n dryRun: flags.dryRun,\n template,\n root: name,\n bundleDirectory: bundlePath,\n targetDirectory: plan.targetDirectory,\n manifestPath: plan.manifestPath,\n changes: plan.changes.map((change) => ({\n kind: change.kind,\n target: displayProjectPath(this.process.cwd(), change.path),\n description: change.description,\n })),\n warnings: plan.warnings,\n nextSteps: plan.nextSteps,\n })}\\n`,\n );\n return;\n }\n if (flags.dryRun) {\n this.logger.info(colors.yellow('Dry run complete. No changes were written.'));\n return;\n }\n if (!approved) {\n this.logger.info(colors.yellow('No changes applied.'));\n return;\n }\n this.logger.info(colors.green(`Policy bundle ${name} added.`));\n if (plan.nextSteps.length > 0) {\n this.logger.info(`\\n${colors.bold('Next steps')}`);\n plan.nextSteps.forEach((step) => this.logger.info(step));\n }\n } catch (error) {\n if (error instanceof PromptCancelledError) {\n this.process.exit(130);\n }\n throw error;\n }\n}\n"],"mappings":"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"}
|