@transcend-io/cli 12.1.3 → 12.1.4
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/dist/{app-DjiX1gVH.mjs → app-CsryyVyP.mjs} +16 -16
- package/dist/{app-DjiX1gVH.mjs.map → app-CsryyVyP.mjs.map} +1 -1
- package/dist/{approvePrivacyRequests-lxkQc3j9.mjs → approvePrivacyRequests-C0muFWCU.mjs} +2 -2
- package/dist/{approvePrivacyRequests-lxkQc3j9.mjs.map → approvePrivacyRequests-C0muFWCU.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-BPpsiPem.mjs → buildExamples-CiNg3tTN.mjs} +2 -2
- package/dist/{buildExamples-BPpsiPem.mjs.map → buildExamples-CiNg3tTN.mjs.map} +1 -1
- package/dist/{buildXdiSyncEndpoint-HKlaBsCz.mjs → buildXdiSyncEndpoint-DZtSxC6c.mjs} +2 -2
- package/dist/{buildXdiSyncEndpoint-HKlaBsCz.mjs.map → buildXdiSyncEndpoint-DZtSxC6c.mjs.map} +1 -1
- package/dist/{bulkRestartRequests-BI1lqrPC.mjs → bulkRestartRequests-Y9CfKTw_.mjs} +2 -2
- package/dist/{bulkRestartRequests-BI1lqrPC.mjs.map → bulkRestartRequests-Y9CfKTw_.mjs.map} +1 -1
- package/dist/{bulkRetryEnrichers-i64LOhXy.mjs → bulkRetryEnrichers-ciLaGX2W.mjs} +2 -2
- package/dist/{bulkRetryEnrichers-i64LOhXy.mjs.map → bulkRetryEnrichers-ciLaGX2W.mjs.map} +1 -1
- package/dist/{cancelPrivacyRequests-BzRQOYrf.mjs → cancelPrivacyRequests-BjltZFLz.mjs} +2 -2
- package/dist/{cancelPrivacyRequests-BzRQOYrf.mjs.map → cancelPrivacyRequests-BjltZFLz.mjs.map} +1 -1
- package/dist/{command-D9Sydip3.mjs → command-C52pNmp5.mjs} +2 -2
- package/dist/{command-D9Sydip3.mjs.map → command-C52pNmp5.mjs.map} +1 -1
- package/dist/{constants-rXUIz6Uy.mjs → constants-CXMjsQ0a.mjs} +2 -2
- package/dist/{constants-rXUIz6Uy.mjs.map → constants-CXMjsQ0a.mjs.map} +1 -1
- package/dist/{createPoolingCommandUi-BsU6e0Ov.mjs → createPoolingCommandUi-DOOGd85C.mjs} +2 -2
- package/dist/{createPoolingCommandUi-BsU6e0Ov.mjs.map → createPoolingCommandUi-DOOGd85C.mjs.map} +1 -1
- package/dist/{downloadPrivacyRequestFiles-B3Yv7zHE.mjs → downloadPrivacyRequestFiles-DgcvbEMQ.mjs} +2 -2
- package/dist/{downloadPrivacyRequestFiles-B3Yv7zHE.mjs.map → downloadPrivacyRequestFiles-DgcvbEMQ.mjs.map} +1 -1
- package/dist/{generateCrossAccountApiKeys-DWDNh4dG.mjs → generateCrossAccountApiKeys-Baa_kNwU.mjs} +2 -2
- package/dist/{generateCrossAccountApiKeys-DWDNh4dG.mjs.map → generateCrossAccountApiKeys-Baa_kNwU.mjs.map} +1 -1
- package/dist/{impl-uWnEYxoC.mjs → impl-1jDZ_mKw.mjs} +2 -2
- package/dist/{impl-uWnEYxoC.mjs.map → impl-1jDZ_mKw.mjs.map} +1 -1
- package/dist/{impl-CdFl00EX.mjs → impl-2j5-mUmH.mjs} +2 -2
- package/dist/{impl-CdFl00EX.mjs.map → impl-2j5-mUmH.mjs.map} +1 -1
- package/dist/{impl-DbqbZmAc.mjs → impl-2zSnVzmN.mjs} +2 -2
- package/dist/{impl-DbqbZmAc.mjs.map → impl-2zSnVzmN.mjs.map} +1 -1
- package/dist/{impl-Y4CI9YNK.mjs → impl-8QdaTZ72.mjs} +2 -2
- package/dist/{impl-Y4CI9YNK.mjs.map → impl-8QdaTZ72.mjs.map} +1 -1
- package/dist/{impl-CYJgNSKH.mjs → impl-B0Qyv21X.mjs} +2 -2
- package/dist/{impl-CYJgNSKH.mjs.map → impl-B0Qyv21X.mjs.map} +1 -1
- package/dist/{impl-Boj3WWax.mjs → impl-B5m1qcQh.mjs} +2 -2
- package/dist/{impl-Boj3WWax.mjs.map → impl-B5m1qcQh.mjs.map} +1 -1
- package/dist/{impl-CwBa15M42.mjs → impl-BEiCEzl_2.mjs} +2 -2
- package/dist/{impl-CwBa15M42.mjs.map → impl-BEiCEzl_2.mjs.map} +1 -1
- package/dist/{impl-C1UEaEKN.mjs → impl-BOYIfXzg.mjs} +2 -2
- package/dist/{impl-C1UEaEKN.mjs.map → impl-BOYIfXzg.mjs.map} +1 -1
- package/dist/{impl-CbZIfTUK.mjs → impl-Bo0QQ6wm.mjs} +2 -2
- package/dist/{impl-CbZIfTUK.mjs.map → impl-Bo0QQ6wm.mjs.map} +1 -1
- package/dist/{impl-BxJ3LBq5.mjs → impl-BoLR69pK.mjs} +2 -2
- package/dist/{impl-BxJ3LBq5.mjs.map → impl-BoLR69pK.mjs.map} +1 -1
- package/dist/{impl-DlrJX5Gl2.mjs → impl-C4sn-3gC2.mjs} +2 -2
- package/dist/{impl-DlrJX5Gl2.mjs.map → impl-C4sn-3gC2.mjs.map} +1 -1
- package/dist/{impl-CIHHFnIw.mjs → impl-C8Ft1xEP.mjs} +2 -2
- package/dist/{impl-CIHHFnIw.mjs.map → impl-C8Ft1xEP.mjs.map} +1 -1
- package/dist/{impl-B1za3AEd.mjs → impl-CEX3vttu.mjs} +2 -2
- package/dist/{impl-B1za3AEd.mjs.map → impl-CEX3vttu.mjs.map} +1 -1
- package/dist/{impl-hDN-9GZo.mjs → impl-CQI_neVJ.mjs} +2 -2
- package/dist/{impl-hDN-9GZo.mjs.map → impl-CQI_neVJ.mjs.map} +1 -1
- package/dist/{impl-CAukIeJv.mjs → impl-CdvjzYeu.mjs} +2 -2
- package/dist/{impl-CAukIeJv.mjs.map → impl-CdvjzYeu.mjs.map} +1 -1
- package/dist/{impl-KukgjmYS.mjs → impl-CiGah6mv.mjs} +2 -2
- package/dist/{impl-KukgjmYS.mjs.map → impl-CiGah6mv.mjs.map} +1 -1
- package/dist/{impl-BlsxbyrR.mjs → impl-CnE2Ph2T.mjs} +2 -2
- package/dist/{impl-BlsxbyrR.mjs.map → impl-CnE2Ph2T.mjs.map} +1 -1
- package/dist/{impl-CYpcKBww.mjs → impl-CszgclpX.mjs} +2 -2
- package/dist/{impl-CYpcKBww.mjs.map → impl-CszgclpX.mjs.map} +1 -1
- package/dist/{impl-DD-ICQ8E.mjs → impl-DBp-O291.mjs} +2 -2
- package/dist/{impl-DD-ICQ8E.mjs.map → impl-DBp-O291.mjs.map} +1 -1
- package/dist/{impl-CNURWgF12.mjs → impl-DD_MeWsL2.mjs} +2 -2
- package/dist/{impl-CNURWgF12.mjs.map → impl-DD_MeWsL2.mjs.map} +1 -1
- package/dist/{impl-BTXUJwyb.mjs → impl-DJ3dRBFE.mjs} +2 -2
- package/dist/{impl-BTXUJwyb.mjs.map → impl-DJ3dRBFE.mjs.map} +1 -1
- package/dist/{impl-DHhm_-pe.mjs → impl-DNHK5CZt.mjs} +2 -2
- package/dist/{impl-DHhm_-pe.mjs.map → impl-DNHK5CZt.mjs.map} +1 -1
- package/dist/{impl-C36c5NfN.mjs → impl-DUYRVzMo.mjs} +2 -2
- package/dist/{impl-C36c5NfN.mjs.map → impl-DUYRVzMo.mjs.map} +1 -1
- package/dist/{impl-Crkz6EBl.mjs → impl-DXF2BvZk.mjs} +2 -2
- package/dist/{impl-Crkz6EBl.mjs.map → impl-DXF2BvZk.mjs.map} +1 -1
- package/dist/{impl-Cr_GtYDt.mjs → impl-DdzqhQ1G.mjs} +2 -2
- package/dist/{impl-Cr_GtYDt.mjs.map → impl-DdzqhQ1G.mjs.map} +1 -1
- package/dist/{impl-BtHRf6Jp.mjs → impl-DhRoKdr5.mjs} +2 -2
- package/dist/{impl-BtHRf6Jp.mjs.map → impl-DhRoKdr5.mjs.map} +1 -1
- package/dist/{impl-fsBuXKVJ.mjs → impl-Dw4dUDc_.mjs} +2 -2
- package/dist/{impl-fsBuXKVJ.mjs.map → impl-Dw4dUDc_.mjs.map} +1 -1
- package/dist/{impl-Sx15m6eC2.mjs → impl-DxrqGYjm2.mjs} +2 -2
- package/dist/{impl-Sx15m6eC2.mjs.map → impl-DxrqGYjm2.mjs.map} +1 -1
- package/dist/{impl-DP9iMlRn.mjs → impl-Dxzy0Ksg.mjs} +2 -2
- package/dist/{impl-DP9iMlRn.mjs.map → impl-Dxzy0Ksg.mjs.map} +1 -1
- package/dist/{impl-CcYyiqaB.mjs → impl-DzwqivKg.mjs} +2 -2
- package/dist/{impl-CcYyiqaB.mjs.map → impl-DzwqivKg.mjs.map} +1 -1
- package/dist/{impl-DKhqM6hZ2.mjs → impl-GGs8OmpV2.mjs} +2 -2
- package/dist/{impl-DKhqM6hZ2.mjs.map → impl-GGs8OmpV2.mjs.map} +1 -1
- package/dist/{impl-mM7BgfxL.mjs → impl-GWNrdIf0.mjs} +2 -2
- package/dist/{impl-mM7BgfxL.mjs.map → impl-GWNrdIf0.mjs.map} +1 -1
- package/dist/{impl-DlPwOUAc.mjs → impl-KwUoQ4Mi.mjs} +2 -2
- package/dist/{impl-DlPwOUAc.mjs.map → impl-KwUoQ4Mi.mjs.map} +1 -1
- package/dist/{impl-Bnc9QUjN.mjs → impl-QVaJa-ut.mjs} +2 -2
- package/dist/{impl-Bnc9QUjN.mjs.map → impl-QVaJa-ut.mjs.map} +1 -1
- package/dist/{impl-CHY55Vge.mjs → impl-TeuLYZCx.mjs} +2 -2
- package/dist/{impl-CHY55Vge.mjs.map → impl-TeuLYZCx.mjs.map} +1 -1
- package/dist/{impl-DG-041kN.mjs → impl-VgI7mr67.mjs} +2 -2
- package/dist/{impl-DG-041kN.mjs.map → impl-VgI7mr67.mjs.map} +1 -1
- package/dist/{impl-CNU3pgwh.mjs → impl-Y5rjrfgs.mjs} +2 -2
- package/dist/{impl-CNU3pgwh.mjs.map → impl-Y5rjrfgs.mjs.map} +1 -1
- package/dist/{impl-DH_tLaGZ.mjs → impl-ZtYIzB9o.mjs} +2 -2
- package/dist/{impl-DH_tLaGZ.mjs.map → impl-ZtYIzB9o.mjs.map} +1 -1
- package/dist/{impl-defjX-97.mjs → impl-qNF5eqX-.mjs} +2 -2
- package/dist/{impl-defjX-97.mjs.map → impl-qNF5eqX-.mjs.map} +1 -1
- package/dist/{impl-BGgaogQG.mjs → impl-sEJHkjPw.mjs} +2 -2
- package/dist/{impl-BGgaogQG.mjs.map → impl-sEJHkjPw.mjs.map} +1 -1
- package/dist/{impl-C8RwWS6i.mjs → impl-tNT_EfWf.mjs} +2 -2
- package/dist/{impl-C8RwWS6i.mjs.map → impl-tNT_EfWf.mjs.map} +1 -1
- package/dist/{impl-BU_vn9I6.mjs → impl-w6TtbzCB.mjs} +2 -2
- package/dist/{impl-BU_vn9I6.mjs.map → impl-w6TtbzCB.mjs.map} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{markRequestDataSiloIdsCompleted-Bm61UHII.mjs → markRequestDataSiloIdsCompleted-63FCcKgi.mjs} +2 -2
- package/dist/{markRequestDataSiloIdsCompleted-Bm61UHII.mjs.map → markRequestDataSiloIdsCompleted-63FCcKgi.mjs.map} +1 -1
- package/dist/{markSilentPrivacyRequests-BtZHHUVJ.mjs → markSilentPrivacyRequests--bQ3UAKC.mjs} +2 -2
- package/dist/{markSilentPrivacyRequests-BtZHHUVJ.mjs.map → markSilentPrivacyRequests--bQ3UAKC.mjs.map} +1 -1
- package/dist/{notifyPrivacyRequestsAdditionalTime-DLW694xo.mjs → notifyPrivacyRequestsAdditionalTime-DQ9_6DaJ.mjs} +2 -2
- package/dist/{notifyPrivacyRequestsAdditionalTime-DLW694xo.mjs.map → notifyPrivacyRequestsAdditionalTime-DQ9_6DaJ.mjs.map} +1 -1
- package/dist/{policy-bundle-manifest-CDbVx8E6.mjs → policy-bundle-manifest-C8Oqz895.mjs} +2 -2
- package/dist/{policy-bundle-manifest-CDbVx8E6.mjs.map → policy-bundle-manifest-C8Oqz895.mjs.map} +1 -1
- package/dist/{policy-project-discovery-_6QosI9J.mjs → policy-project-discovery-BR9EiTHd.mjs} +2 -2
- package/dist/{policy-project-discovery-_6QosI9J.mjs.map → policy-project-discovery-BR9EiTHd.mjs.map} +1 -1
- package/dist/{policy-scaffold-config-DwZFigj7.mjs → policy-scaffold-config-CLIwzEFs.mjs} +2 -2
- package/dist/{policy-scaffold-config-DwZFigj7.mjs.map → policy-scaffold-config-CLIwzEFs.mjs.map} +1 -1
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DtDLjhzX.mjs → pullChunkedCustomSiloOutstandingIdentifiers-B0TFbcgJ.mjs} +2 -2
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DtDLjhzX.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-B0TFbcgJ.mjs.map} +1 -1
- package/dist/{pullManualEnrichmentIdentifiersToCsv-CWVaEx3x.mjs → pullManualEnrichmentIdentifiersToCsv-Bbg5FOIJ.mjs} +2 -2
- package/dist/{pullManualEnrichmentIdentifiersToCsv-CWVaEx3x.mjs.map → pullManualEnrichmentIdentifiersToCsv-Bbg5FOIJ.mjs.map} +1 -1
- package/dist/{pushCronIdentifiersFromCsv-J4ByJG4I.mjs → pushCronIdentifiersFromCsv-DLmgvrjn.mjs} +2 -2
- package/dist/{pushCronIdentifiersFromCsv-J4ByJG4I.mjs.map → pushCronIdentifiersFromCsv-DLmgvrjn.mjs.map} +1 -1
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-Dyh7-KVs.mjs → pushManualEnrichmentIdentifiersFromCsv-Cih6wgBt.mjs} +2 -2
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-Dyh7-KVs.mjs.map → pushManualEnrichmentIdentifiersFromCsv-Cih6wgBt.mjs.map} +1 -1
- package/dist/{removeUnverifiedRequestIdentifiers-DOXo1yCT.mjs → removeUnverifiedRequestIdentifiers-DkbeJa9c.mjs} +2 -2
- package/dist/{removeUnverifiedRequestIdentifiers-DOXo1yCT.mjs.map → removeUnverifiedRequestIdentifiers-DkbeJa9c.mjs.map} +1 -1
- package/dist/resolveBundleIdByName-D7NUOpLc.mjs +2 -0
- package/dist/resolveBundleIdByName-D7NUOpLc.mjs.map +1 -0
- package/dist/resolvePolicyBundleVersion-CKbF9vqc.mjs +2 -0
- package/dist/resolvePolicyBundleVersion-CKbF9vqc.mjs.map +1 -0
- package/dist/{retryRequestDataSilos-Dehz_PEx.mjs → retryRequestDataSilos-MxpSNKuV.mjs} +2 -2
- package/dist/{retryRequestDataSilos-Dehz_PEx.mjs.map → retryRequestDataSilos-MxpSNKuV.mjs.map} +1 -1
- package/dist/{skipPreflightJobs-BjFQxEwf.mjs → skipPreflightJobs-enp_ioAV.mjs} +2 -2
- package/dist/{skipPreflightJobs-BjFQxEwf.mjs.map → skipPreflightJobs-enp_ioAV.mjs.map} +1 -1
- package/dist/{skipRequestDataSilos-DB1_3m-p.mjs → skipRequestDataSilos-B23W9ZJe.mjs} +2 -2
- package/dist/{skipRequestDataSilos-DB1_3m-p.mjs.map → skipRequestDataSilos-B23W9ZJe.mjs.map} +1 -1
- package/dist/{streamPrivacyRequestsToCsv-BWmN5fl6.mjs → streamPrivacyRequestsToCsv-Cx5QIQT6.mjs} +2 -2
- package/dist/{streamPrivacyRequestsToCsv-BWmN5fl6.mjs.map → streamPrivacyRequestsToCsv-Cx5QIQT6.mjs.map} +1 -1
- package/dist/{updateConsentManagerVersionToLatest-C6jRvQPt.mjs → updateConsentManagerVersionToLatest-B2Ke4QhR.mjs} +2 -2
- package/dist/{updateConsentManagerVersionToLatest-C6jRvQPt.mjs.map → updateConsentManagerVersionToLatest-B2Ke4QhR.mjs.map} +1 -1
- package/dist/{uploadConsents-08KJPYm_.mjs → uploadConsents-BkvhwPJ6.mjs} +2 -2
- package/dist/{uploadConsents-08KJPYm_.mjs.map → uploadConsents-BkvhwPJ6.mjs.map} +1 -1
- package/dist/{uploadPrivacyRequestsFromCsv-M3iY9cjb.mjs → uploadPrivacyRequestsFromCsv-BGv8UH5q.mjs} +2 -2
- package/dist/{uploadPrivacyRequestsFromCsv-M3iY9cjb.mjs.map → uploadPrivacyRequestsFromCsv-BGv8UH5q.mjs.map} +1 -1
- package/package.json +1 -1
- package/dist/resolveBundleIdByName-BPrMkU0w.mjs +0 -2
- package/dist/resolveBundleIdByName-BPrMkU0w.mjs.map +0 -1
- package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs +0 -2
- package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-CNU3pgwh.mjs","names":[],"sources":["../src/lib/policy/policy-lint-model.ts","../src/lib/policy/policy-lint-output.ts","../src/commands/policy/lint/impl.ts"],"sourcesContent":["/** Stable policy lint result schema version. */\nexport const POLICY_LINT_RESULT_VERSION = 1;\n\n/** Stable multi-bundle lint result schema version. */\nexport const POLICY_LINT_MULTI_RESULT_VERSION = 2;\n\n/** Status of the full gate or an individual verification. */\nexport type PolicyLintStatus = 'passed' | 'failed' | 'skipped';\n\n/** One named policy verification. */\nexport interface PolicyLintCheck {\n /** Stable verification name. */\n name:\n | 'manifest'\n | 'opa-version'\n | 'regal-version'\n | 'format'\n | 'opa-check'\n | 'regal-lint'\n | 'opa-test';\n /** Verification outcome. */\n status: PolicyLintStatus;\n}\n\n/** Stable verification execution order. */\nexport const POLICY_LINT_CHECK_NAMES: PolicyLintCheck['name'][] = [\n 'manifest',\n 'opa-version',\n 'regal-version',\n 'format',\n 'opa-check',\n 'regal-lint',\n 'opa-test',\n];\n\n/** User-facing verification labels. */\nexport const POLICY_LINT_CHECK_LABELS: Readonly<Record<PolicyLintCheck['name'], string>> = {\n manifest: 'Manifest and package roots',\n 'opa-version': 'OPA 1.x',\n 'regal-version': 'Regal',\n format: 'OPA formatting',\n 'opa-check': 'OPA strict check',\n 'regal-lint': 'Regal lint',\n 'opa-test': 'OPA tests',\n};\n\n/** One machine-readable policy lint diagnostic. */\nexport interface PolicyLintDiagnostic {\n /** Stable diagnostic identifier. */\n code: string;\n /** Diagnostic severity. */\n severity: 'error';\n /** Human-readable detail, including captured tool output when available. */\n message: string;\n /** Optional path relative to the invocation directory. */\n path?: string;\n}\n\n/** Detected local policy tool versions. */\nexport interface PolicyLintTools {\n /** Detected OPA version, or null when missing or unsupported. */\n opa: string | null;\n /** Detected Regal version, or null when missing or unsupported. */\n regal: string | null;\n}\n\n/** Stable result emitted by `transcend policy lint --json` for one bundle. */\nexport interface PolicyLintResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_RESULT_VERSION;\n /** Overall verification outcome. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy bundle directory. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Detected supported tool versions. */\n tools: PolicyLintTools;\n /** Verification outcomes in stable execution order. */\n checks: PolicyLintCheck[];\n /** Files found to need OPA formatting, relative to the policy directory. */\n unformattedFiles: string[];\n /** Files repaired with OPA formatting, relative to the policy directory. */\n fixedFiles: string[];\n /** Ordered verification diagnostics. */\n diagnostics: PolicyLintDiagnostic[];\n}\n\n/**\n * Stable result when `transcend policy lint --json` verifies multiple bundles.\n *\n * Emitted only when the selected path is a workspace with more than one\n * publishable `*-bundle/` directory.\n */\nexport interface PolicyLintMultiResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_MULTI_RESULT_VERSION;\n /** Overall verification outcome across all bundles. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy workspace directory that was searched. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Per-bundle results in discovery order. */\n results: PolicyLintResult[];\n}\n","import path from 'node:path';\n\nimport type { CapturedProcessResult } from '../cli/run-captured-process.js';\n\n/**\n * Use captured tool output as a concise diagnostic.\n *\n * @param result - Captured process result\n * @param fallback - Message used when the tool emitted no output\n * @returns Diagnostic message\n */\nexport function getPolicyProcessFailureMessage(\n result: CapturedProcessResult,\n fallback: string,\n): string {\n const output = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join('\\n');\n return output || fallback;\n}\n\n/**\n * Convert absolute OPA formatter paths to stable project-relative paths.\n *\n * @param stdout - `opa fmt --list` output\n * @param projectDirectory - Absolute policy directory\n * @returns Sorted unique paths\n */\nexport function parseUnformattedPolicyFiles(stdout: string, projectDirectory: string): string[] {\n return [\n ...new Set(\n stdout\n .split(/\\r?\\n/gu)\n .map((file) => file.trim())\n .filter(Boolean)\n .map((file) =>\n path.isAbsolute(file)\n ? path.relative(projectDirectory, file).split(path.sep).join('/')\n : file.split(path.sep).join('/'),\n ),\n ),\n ].sort();\n}\n","import path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n runCapturedProcess,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport {\n type PolicyBundleRegoFile,\n validatePolicyBundleContents,\n} from '../../../lib/policy/policy-bundle-manifest.js';\nimport {\n type PolicyLintCheck,\n type PolicyLintDiagnostic,\n type PolicyLintMultiResult,\n type PolicyLintResult,\n POLICY_LINT_CHECK_LABELS,\n POLICY_LINT_CHECK_NAMES,\n POLICY_LINT_MULTI_RESULT_VERSION,\n POLICY_LINT_RESULT_VERSION,\n} from '../../../lib/policy/policy-lint-model.js';\nimport {\n getPolicyProcessFailureMessage,\n parseUnformattedPolicyFiles,\n} from '../../../lib/policy/policy-lint-output.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n OPA_MISSING_MESSAGE,\n parsePolicyToolVersion,\n REGAL_MISSING_MESSAGE,\n unsupportedOpaVersionMessage,\n unsupportedRegalVersionMessage,\n} from '../../../lib/policy/policy-runtime.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.js';\n\n/** CLI flags for `transcend policy lint`. */\nexport interface LintCommandFlags {\n /** Apply OPA formatting. */\n fix: boolean;\n /** Disable the optional formatting confirmation. */\n noInteractive: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/**\n * Collect Rego source snapshots without following symlinks.\n *\n * @param context - CLI context\n * @param projectDirectory - Absolute policy directory\n * @param currentDirectory - Current recursive directory\n * @returns Deterministically ordered Rego snapshots\n */\nfunction collectRegoFiles(\n context: LocalContext,\n projectDirectory: string,\n currentDirectory: string = projectDirectory,\n): PolicyBundleRegoFile[] {\n return context.fs\n .readdirSync(currentDirectory, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))\n .flatMap((entry) => {\n const absolutePath = path.join(currentDirectory, entry.name);\n if (entry.isDirectory()) {\n return collectRegoFiles(context, projectDirectory, absolutePath);\n }\n if (!entry.isFile() || !entry.name.endsWith('.rego')) {\n return [];\n }\n return [\n {\n path: path.relative(projectDirectory, absolutePath).split(path.sep).join('/'),\n contents: context.fs.readFileSync(absolutePath, 'utf8'),\n },\n ];\n });\n}\n\n/**\n * Resolve a Regal config file for a bundle, walking up to the workspace.\n *\n * @param context - CLI context\n * @param bundleDirectory - Absolute bundle directory\n * @returns Absolute config path, or undefined when none is found\n */\nfunction resolveRegalConfigFile(\n context: LocalContext,\n bundleDirectory: string,\n): string | undefined {\n let current = bundleDirectory;\n for (;;) {\n const nestedRegalConfig = path.join(current, '.regal', 'config.yaml');\n if (context.fs.existsSync(nestedRegalConfig)) {\n return nestedRegalConfig;\n }\n const rootRegalConfig = path.join(current, '.regal.yaml');\n if (context.fs.existsSync(rootRegalConfig)) {\n return rootRegalConfig;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n}\n\n/**\n * Render the terminal summary for a policy verification result.\n *\n * @param context - CLI context\n * @param result - Completed verification result\n * @param heading - Optional section heading when linting multiple bundles\n */\nfunction renderResult(context: LocalContext, result: PolicyLintResult, heading?: string): void {\n if (heading) {\n context.logger.info(`${colors.bold(heading)}\\n`);\n } else {\n context.logger.info(`${colors.bold('Policy verification')}\\n`);\n }\n result.checks.forEach(({ name, status }) => {\n const label = status === 'passed' ? 'PASS' : status === 'failed' ? 'FAIL' : 'SKIP';\n const styledLabel =\n status === 'passed'\n ? colors.green(label)\n : status === 'failed'\n ? colors.red(label)\n : colors.yellow(label);\n const version =\n name === 'opa-version' && result.tools.opa\n ? ` (${result.tools.opa})`\n : name === 'regal-version' && result.tools.regal\n ? ` (${result.tools.regal})`\n : '';\n context.logger.info(`${styledLabel} ${POLICY_LINT_CHECK_LABELS[name]}${version}`);\n });\n if (result.diagnostics.length > 0) {\n context.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n context.logger.error(\n colors.red(`error [${diagnostic.code}]: ${location}${diagnostic.message}`),\n );\n });\n if (result.status === 'passed') {\n context.logger.info('');\n context.logger.info(colors.green('Policy verification passed.'));\n } else {\n context.logger.error('');\n context.logger.error(colors.red('Policy verification failed.'));\n }\n}\n\n/**\n * Verify one publishable policy bundle directory.\n *\n * @param context - CLI context\n * @param flags - Command flags\n * @param resolvedDir - Absolute bundle directory\n * @param runner - Captured subprocess runner\n * @returns Completed verification result\n */\nasync function lintBundle(\n this: LocalContext,\n { fix, noInteractive, json }: LintCommandFlags,\n resolvedDir: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyLintResult> {\n const checks: PolicyLintCheck[] = POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: 'skipped',\n }));\n const diagnostics: PolicyLintDiagnostic[] = [];\n const result: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'passed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks,\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics,\n };\n const setStatus = (name: PolicyLintCheck['name'], status: PolicyLintCheck['status']): void => {\n checks.find((check) => check.name === name)!.status = status;\n };\n const addError = (code: string, message: string, diagnosticPath?: string): void => {\n diagnostics.push({\n code,\n severity: 'error',\n message,\n ...(diagnosticPath ? { path: diagnosticPath } : {}),\n });\n };\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n setStatus('manifest', 'failed');\n addError(\n 'project.directory',\n `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path.relative(this.process.cwd(), resolvedDir),\n );\n result.status = 'failed';\n return result;\n }\n\n const manifestPath = path.join(resolvedDir, POLICY_MANIFEST_FILENAME);\n try {\n validatePolicyBundleContents(\n this.fs.existsSync(manifestPath) ? this.fs.readFileSync(manifestPath, 'utf8') : undefined,\n collectRegoFiles(this, resolvedDir),\n );\n setStatus('manifest', 'passed');\n } catch (error) {\n setStatus('manifest', 'failed');\n addError(\n 'manifest.invalid',\n error instanceof Error ? error.message : String(error),\n path.relative(this.process.cwd(), manifestPath),\n );\n }\n\n const opaVersionResult = await runner('opa', ['version'], { cwd: resolvedDir }, this);\n if (opaVersionResult.error?.code === 'ENOENT') {\n setStatus('opa-version', 'failed');\n addError('opa.missing', OPA_MISSING_MESSAGE);\n } else {\n const opaVersionOutput = `${opaVersionResult.stdout}\\n${opaVersionResult.stderr}`;\n const unsupportedOpa = unsupportedOpaVersionMessage(opaVersionOutput);\n if (opaVersionResult.code !== 0 || unsupportedOpa) {\n setStatus('opa-version', 'failed');\n addError(\n 'opa.version',\n unsupportedOpa ??\n getPolicyProcessFailureMessage(\n opaVersionResult,\n 'Unable to determine the installed OPA version.',\n ),\n );\n } else {\n result.tools.opa = parsePolicyToolVersion(opaVersionOutput)!.version;\n setStatus('opa-version', 'passed');\n }\n }\n\n const regalVersionResult = await runner('regal', ['version'], { cwd: resolvedDir }, this);\n if (regalVersionResult.error?.code === 'ENOENT') {\n setStatus('regal-version', 'failed');\n addError('regal.missing', REGAL_MISSING_MESSAGE);\n } else {\n const regalVersionOutput = `${regalVersionResult.stdout}\\n${regalVersionResult.stderr}`;\n const unsupportedRegal = unsupportedRegalVersionMessage(regalVersionOutput);\n if (regalVersionResult.code !== 0 || unsupportedRegal) {\n setStatus('regal-version', 'failed');\n addError(\n 'regal.version',\n unsupportedRegal ??\n getPolicyProcessFailureMessage(\n regalVersionResult,\n 'Unable to determine the installed Regal version.',\n ),\n );\n } else {\n result.tools.regal = parsePolicyToolVersion(regalVersionOutput)!.version;\n setStatus('regal-version', 'passed');\n }\n }\n\n if (result.tools.opa) {\n const formatResult = await runner(\n 'opa',\n ['fmt', '--list', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (formatResult.code !== 0) {\n setStatus('format', 'failed');\n addError(\n 'opa.format',\n getPolicyProcessFailureMessage(\n formatResult,\n `opa fmt --list failed with exit code ${formatResult.code}`,\n ),\n );\n } else {\n result.unformattedFiles = parseUnformattedPolicyFiles(formatResult.stdout, resolvedDir);\n if (result.unformattedFiles.length === 0) {\n setStatus('format', 'passed');\n } else {\n let shouldFormat = fix;\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n if (!json && !fix) {\n this.logger.error(colors.red('Policy files are not formatted:'));\n result.unformattedFiles.forEach((file) => {\n this.logger.error(colors.red(` - ${file}`));\n });\n const diffResult = await runner(\n 'opa',\n ['fmt', '--diff', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n const diff = diffResult.stdout.trim() || diffResult.stderr.trim();\n if (diff) {\n this.logger.error('');\n this.logger.error(diff);\n }\n }\n if (!fix && interactive) {\n try {\n shouldFormat = await inquirerConfirmBoolean({\n message: 'Format the unformatted policy files listed above?',\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/force closed|prompt.*cancel|user.*close|SIGINT/iu.test(message)) {\n this.process.exit(130);\n }\n throw error;\n }\n }\n if (shouldFormat) {\n const writeResult = await runner(\n 'opa',\n ['fmt', '--write', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (writeResult.code === 0) {\n result.fixedFiles = [...result.unformattedFiles];\n setStatus('format', 'passed');\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-fix',\n getPolicyProcessFailureMessage(\n writeResult,\n `opa fmt --write failed with exit code ${writeResult.code}`,\n ),\n );\n }\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-required',\n 'Policy files are not formatted. Re-run `transcend policy lint --fix` to repair them.',\n );\n }\n }\n }\n\n const checkResult = await runner(\n 'opa',\n ['check', '--strict', '--ignore', '*_test.rego', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (checkResult.code === 0) {\n setStatus('opa-check', 'passed');\n } else {\n setStatus('opa-check', 'failed');\n addError(\n 'opa.check',\n getPolicyProcessFailureMessage(\n checkResult,\n `opa check failed with exit code ${checkResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.regal) {\n const regalConfig = resolveRegalConfigFile(this, resolvedDir);\n const regalResult = await runner(\n 'regal',\n [\n 'lint',\n '--fail-level',\n 'warning',\n ...(regalConfig ? ['--config-file', regalConfig] : []),\n resolvedDir,\n ],\n { cwd: resolvedDir },\n this,\n );\n if (regalResult.code === 0) {\n setStatus('regal-lint', 'passed');\n } else {\n setStatus('regal-lint', 'failed');\n addError(\n 'regal.lint',\n getPolicyProcessFailureMessage(\n regalResult,\n `regal lint failed with exit code ${regalResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.opa) {\n const testResult = await runner(\n 'opa',\n ['test', '--fail-on-empty', '-b', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (testResult.code === 0) {\n setStatus('opa-test', 'passed');\n } else {\n setStatus('opa-test', 'failed');\n addError(\n 'opa.test',\n getPolicyProcessFailureMessage(\n testResult,\n `opa test --fail-on-empty -b failed with exit code ${testResult.code}`,\n ),\n );\n }\n }\n\n result.status = checks.some(({ status }) => status === 'failed') ? 'failed' : 'passed';\n return result;\n}\n\n/**\n * Verify local policy bundles with the shared upload contract, OPA, and Regal.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and verifies each. Pass one bundle path to\n * verify a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n * @param runner - Captured subprocess runner\n */\nexport async function lint(\n this: LocalContext,\n flags: LintCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { fix = false, noInteractive = false, json = false } = flags;\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n const missing: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.directory',\n severity: 'error',\n message: `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path: path.relative(this.process.cwd(), resolvedDir),\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(missing)}\\n`);\n } else {\n renderResult(this, missing);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n const empty: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.bundles',\n severity: 'error',\n message:\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n path: path.relative(this.process.cwd(), resolvedDir) || '.',\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(empty)}\\n`);\n } else {\n renderResult(this, empty);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const results: PolicyLintResult[] = [];\n for (const bundleDirectory of bundleDirectories) {\n results.push(\n await lintBundle.call(this, { fix, noInteractive, json }, bundleDirectory, runner),\n );\n }\n\n const failed = results.some((result) => result.status === 'failed');\n if (json) {\n if (results.length === 1) {\n this.process.stdout.write(`${JSON.stringify(results[0])}\\n`);\n } else {\n const multi: PolicyLintMultiResult = {\n version: POLICY_LINT_MULTI_RESULT_VERSION,\n status: failed ? 'failed' : 'passed',\n directory: resolvedDir,\n fix,\n results,\n };\n this.process.stdout.write(`${JSON.stringify(multi)}\\n`);\n }\n } else if (results.length === 1) {\n renderResult(this, results[0]!);\n } else {\n results.forEach((result, index) => {\n if (index > 0) {\n this.logger.info('');\n }\n const relative = path.relative(this.process.cwd(), result.directory) || result.directory;\n renderResult(this, result, `Policy verification — ${relative}`);\n });\n }\n\n if (failed) {\n this.process.exitCode = 1;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"impl-Y5rjrfgs.mjs","names":[],"sources":["../src/lib/policy/policy-lint-model.ts","../src/lib/policy/policy-lint-output.ts","../src/commands/policy/lint/impl.ts"],"sourcesContent":["/** Stable policy lint result schema version. */\nexport const POLICY_LINT_RESULT_VERSION = 1;\n\n/** Stable multi-bundle lint result schema version. */\nexport const POLICY_LINT_MULTI_RESULT_VERSION = 2;\n\n/** Status of the full gate or an individual verification. */\nexport type PolicyLintStatus = 'passed' | 'failed' | 'skipped';\n\n/** One named policy verification. */\nexport interface PolicyLintCheck {\n /** Stable verification name. */\n name:\n | 'manifest'\n | 'opa-version'\n | 'regal-version'\n | 'format'\n | 'opa-check'\n | 'regal-lint'\n | 'opa-test';\n /** Verification outcome. */\n status: PolicyLintStatus;\n}\n\n/** Stable verification execution order. */\nexport const POLICY_LINT_CHECK_NAMES: PolicyLintCheck['name'][] = [\n 'manifest',\n 'opa-version',\n 'regal-version',\n 'format',\n 'opa-check',\n 'regal-lint',\n 'opa-test',\n];\n\n/** User-facing verification labels. */\nexport const POLICY_LINT_CHECK_LABELS: Readonly<Record<PolicyLintCheck['name'], string>> = {\n manifest: 'Manifest and package roots',\n 'opa-version': 'OPA 1.x',\n 'regal-version': 'Regal',\n format: 'OPA formatting',\n 'opa-check': 'OPA strict check',\n 'regal-lint': 'Regal lint',\n 'opa-test': 'OPA tests',\n};\n\n/** One machine-readable policy lint diagnostic. */\nexport interface PolicyLintDiagnostic {\n /** Stable diagnostic identifier. */\n code: string;\n /** Diagnostic severity. */\n severity: 'error';\n /** Human-readable detail, including captured tool output when available. */\n message: string;\n /** Optional path relative to the invocation directory. */\n path?: string;\n}\n\n/** Detected local policy tool versions. */\nexport interface PolicyLintTools {\n /** Detected OPA version, or null when missing or unsupported. */\n opa: string | null;\n /** Detected Regal version, or null when missing or unsupported. */\n regal: string | null;\n}\n\n/** Stable result emitted by `transcend policy lint --json` for one bundle. */\nexport interface PolicyLintResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_RESULT_VERSION;\n /** Overall verification outcome. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy bundle directory. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Detected supported tool versions. */\n tools: PolicyLintTools;\n /** Verification outcomes in stable execution order. */\n checks: PolicyLintCheck[];\n /** Files found to need OPA formatting, relative to the policy directory. */\n unformattedFiles: string[];\n /** Files repaired with OPA formatting, relative to the policy directory. */\n fixedFiles: string[];\n /** Ordered verification diagnostics. */\n diagnostics: PolicyLintDiagnostic[];\n}\n\n/**\n * Stable result when `transcend policy lint --json` verifies multiple bundles.\n *\n * Emitted only when the selected path is a workspace with more than one\n * publishable `*-bundle/` directory.\n */\nexport interface PolicyLintMultiResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_MULTI_RESULT_VERSION;\n /** Overall verification outcome across all bundles. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy workspace directory that was searched. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Per-bundle results in discovery order. */\n results: PolicyLintResult[];\n}\n","import path from 'node:path';\n\nimport type { CapturedProcessResult } from '../cli/run-captured-process.js';\n\n/**\n * Use captured tool output as a concise diagnostic.\n *\n * @param result - Captured process result\n * @param fallback - Message used when the tool emitted no output\n * @returns Diagnostic message\n */\nexport function getPolicyProcessFailureMessage(\n result: CapturedProcessResult,\n fallback: string,\n): string {\n const output = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join('\\n');\n return output || fallback;\n}\n\n/**\n * Convert absolute OPA formatter paths to stable project-relative paths.\n *\n * @param stdout - `opa fmt --list` output\n * @param projectDirectory - Absolute policy directory\n * @returns Sorted unique paths\n */\nexport function parseUnformattedPolicyFiles(stdout: string, projectDirectory: string): string[] {\n return [\n ...new Set(\n stdout\n .split(/\\r?\\n/gu)\n .map((file) => file.trim())\n .filter(Boolean)\n .map((file) =>\n path.isAbsolute(file)\n ? path.relative(projectDirectory, file).split(path.sep).join('/')\n : file.split(path.sep).join('/'),\n ),\n ),\n ].sort();\n}\n","import path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n runCapturedProcess,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport {\n type PolicyBundleRegoFile,\n validatePolicyBundleContents,\n} from '../../../lib/policy/policy-bundle-manifest.js';\nimport {\n type PolicyLintCheck,\n type PolicyLintDiagnostic,\n type PolicyLintMultiResult,\n type PolicyLintResult,\n POLICY_LINT_CHECK_LABELS,\n POLICY_LINT_CHECK_NAMES,\n POLICY_LINT_MULTI_RESULT_VERSION,\n POLICY_LINT_RESULT_VERSION,\n} from '../../../lib/policy/policy-lint-model.js';\nimport {\n getPolicyProcessFailureMessage,\n parseUnformattedPolicyFiles,\n} from '../../../lib/policy/policy-lint-output.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n OPA_MISSING_MESSAGE,\n parsePolicyToolVersion,\n REGAL_MISSING_MESSAGE,\n unsupportedOpaVersionMessage,\n unsupportedRegalVersionMessage,\n} from '../../../lib/policy/policy-runtime.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.js';\n\n/** CLI flags for `transcend policy lint`. */\nexport interface LintCommandFlags {\n /** Apply OPA formatting. */\n fix: boolean;\n /** Disable the optional formatting confirmation. */\n noInteractive: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/**\n * Collect Rego source snapshots without following symlinks.\n *\n * @param context - CLI context\n * @param projectDirectory - Absolute policy directory\n * @param currentDirectory - Current recursive directory\n * @returns Deterministically ordered Rego snapshots\n */\nfunction collectRegoFiles(\n context: LocalContext,\n projectDirectory: string,\n currentDirectory: string = projectDirectory,\n): PolicyBundleRegoFile[] {\n return context.fs\n .readdirSync(currentDirectory, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))\n .flatMap((entry) => {\n const absolutePath = path.join(currentDirectory, entry.name);\n if (entry.isDirectory()) {\n return collectRegoFiles(context, projectDirectory, absolutePath);\n }\n if (!entry.isFile() || !entry.name.endsWith('.rego')) {\n return [];\n }\n return [\n {\n path: path.relative(projectDirectory, absolutePath).split(path.sep).join('/'),\n contents: context.fs.readFileSync(absolutePath, 'utf8'),\n },\n ];\n });\n}\n\n/**\n * Resolve a Regal config file for a bundle, walking up to the workspace.\n *\n * @param context - CLI context\n * @param bundleDirectory - Absolute bundle directory\n * @returns Absolute config path, or undefined when none is found\n */\nfunction resolveRegalConfigFile(\n context: LocalContext,\n bundleDirectory: string,\n): string | undefined {\n let current = bundleDirectory;\n for (;;) {\n const nestedRegalConfig = path.join(current, '.regal', 'config.yaml');\n if (context.fs.existsSync(nestedRegalConfig)) {\n return nestedRegalConfig;\n }\n const rootRegalConfig = path.join(current, '.regal.yaml');\n if (context.fs.existsSync(rootRegalConfig)) {\n return rootRegalConfig;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n}\n\n/**\n * Render the terminal summary for a policy verification result.\n *\n * @param context - CLI context\n * @param result - Completed verification result\n * @param heading - Optional section heading when linting multiple bundles\n */\nfunction renderResult(context: LocalContext, result: PolicyLintResult, heading?: string): void {\n if (heading) {\n context.logger.info(`${colors.bold(heading)}\\n`);\n } else {\n context.logger.info(`${colors.bold('Policy verification')}\\n`);\n }\n result.checks.forEach(({ name, status }) => {\n const label = status === 'passed' ? 'PASS' : status === 'failed' ? 'FAIL' : 'SKIP';\n const styledLabel =\n status === 'passed'\n ? colors.green(label)\n : status === 'failed'\n ? colors.red(label)\n : colors.yellow(label);\n const version =\n name === 'opa-version' && result.tools.opa\n ? ` (${result.tools.opa})`\n : name === 'regal-version' && result.tools.regal\n ? ` (${result.tools.regal})`\n : '';\n context.logger.info(`${styledLabel} ${POLICY_LINT_CHECK_LABELS[name]}${version}`);\n });\n if (result.diagnostics.length > 0) {\n context.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n context.logger.error(\n colors.red(`error [${diagnostic.code}]: ${location}${diagnostic.message}`),\n );\n });\n if (result.status === 'passed') {\n context.logger.info('');\n context.logger.info(colors.green('Policy verification passed.'));\n } else {\n context.logger.error('');\n context.logger.error(colors.red('Policy verification failed.'));\n }\n}\n\n/**\n * Verify one publishable policy bundle directory.\n *\n * @param context - CLI context\n * @param flags - Command flags\n * @param resolvedDir - Absolute bundle directory\n * @param runner - Captured subprocess runner\n * @returns Completed verification result\n */\nasync function lintBundle(\n this: LocalContext,\n { fix, noInteractive, json }: LintCommandFlags,\n resolvedDir: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyLintResult> {\n const checks: PolicyLintCheck[] = POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: 'skipped',\n }));\n const diagnostics: PolicyLintDiagnostic[] = [];\n const result: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'passed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks,\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics,\n };\n const setStatus = (name: PolicyLintCheck['name'], status: PolicyLintCheck['status']): void => {\n checks.find((check) => check.name === name)!.status = status;\n };\n const addError = (code: string, message: string, diagnosticPath?: string): void => {\n diagnostics.push({\n code,\n severity: 'error',\n message,\n ...(diagnosticPath ? { path: diagnosticPath } : {}),\n });\n };\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n setStatus('manifest', 'failed');\n addError(\n 'project.directory',\n `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path.relative(this.process.cwd(), resolvedDir),\n );\n result.status = 'failed';\n return result;\n }\n\n const manifestPath = path.join(resolvedDir, POLICY_MANIFEST_FILENAME);\n try {\n validatePolicyBundleContents(\n this.fs.existsSync(manifestPath) ? this.fs.readFileSync(manifestPath, 'utf8') : undefined,\n collectRegoFiles(this, resolvedDir),\n );\n setStatus('manifest', 'passed');\n } catch (error) {\n setStatus('manifest', 'failed');\n addError(\n 'manifest.invalid',\n error instanceof Error ? error.message : String(error),\n path.relative(this.process.cwd(), manifestPath),\n );\n }\n\n const opaVersionResult = await runner('opa', ['version'], { cwd: resolvedDir }, this);\n if (opaVersionResult.error?.code === 'ENOENT') {\n setStatus('opa-version', 'failed');\n addError('opa.missing', OPA_MISSING_MESSAGE);\n } else {\n const opaVersionOutput = `${opaVersionResult.stdout}\\n${opaVersionResult.stderr}`;\n const unsupportedOpa = unsupportedOpaVersionMessage(opaVersionOutput);\n if (opaVersionResult.code !== 0 || unsupportedOpa) {\n setStatus('opa-version', 'failed');\n addError(\n 'opa.version',\n unsupportedOpa ??\n getPolicyProcessFailureMessage(\n opaVersionResult,\n 'Unable to determine the installed OPA version.',\n ),\n );\n } else {\n result.tools.opa = parsePolicyToolVersion(opaVersionOutput)!.version;\n setStatus('opa-version', 'passed');\n }\n }\n\n const regalVersionResult = await runner('regal', ['version'], { cwd: resolvedDir }, this);\n if (regalVersionResult.error?.code === 'ENOENT') {\n setStatus('regal-version', 'failed');\n addError('regal.missing', REGAL_MISSING_MESSAGE);\n } else {\n const regalVersionOutput = `${regalVersionResult.stdout}\\n${regalVersionResult.stderr}`;\n const unsupportedRegal = unsupportedRegalVersionMessage(regalVersionOutput);\n if (regalVersionResult.code !== 0 || unsupportedRegal) {\n setStatus('regal-version', 'failed');\n addError(\n 'regal.version',\n unsupportedRegal ??\n getPolicyProcessFailureMessage(\n regalVersionResult,\n 'Unable to determine the installed Regal version.',\n ),\n );\n } else {\n result.tools.regal = parsePolicyToolVersion(regalVersionOutput)!.version;\n setStatus('regal-version', 'passed');\n }\n }\n\n if (result.tools.opa) {\n const formatResult = await runner(\n 'opa',\n ['fmt', '--list', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (formatResult.code !== 0) {\n setStatus('format', 'failed');\n addError(\n 'opa.format',\n getPolicyProcessFailureMessage(\n formatResult,\n `opa fmt --list failed with exit code ${formatResult.code}`,\n ),\n );\n } else {\n result.unformattedFiles = parseUnformattedPolicyFiles(formatResult.stdout, resolvedDir);\n if (result.unformattedFiles.length === 0) {\n setStatus('format', 'passed');\n } else {\n let shouldFormat = fix;\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n if (!json && !fix) {\n this.logger.error(colors.red('Policy files are not formatted:'));\n result.unformattedFiles.forEach((file) => {\n this.logger.error(colors.red(` - ${file}`));\n });\n const diffResult = await runner(\n 'opa',\n ['fmt', '--diff', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n const diff = diffResult.stdout.trim() || diffResult.stderr.trim();\n if (diff) {\n this.logger.error('');\n this.logger.error(diff);\n }\n }\n if (!fix && interactive) {\n try {\n shouldFormat = await inquirerConfirmBoolean({\n message: 'Format the unformatted policy files listed above?',\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/force closed|prompt.*cancel|user.*close|SIGINT/iu.test(message)) {\n this.process.exit(130);\n }\n throw error;\n }\n }\n if (shouldFormat) {\n const writeResult = await runner(\n 'opa',\n ['fmt', '--write', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (writeResult.code === 0) {\n result.fixedFiles = [...result.unformattedFiles];\n setStatus('format', 'passed');\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-fix',\n getPolicyProcessFailureMessage(\n writeResult,\n `opa fmt --write failed with exit code ${writeResult.code}`,\n ),\n );\n }\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-required',\n 'Policy files are not formatted. Re-run `transcend policy lint --fix` to repair them.',\n );\n }\n }\n }\n\n const checkResult = await runner(\n 'opa',\n ['check', '--strict', '--ignore', '*_test.rego', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (checkResult.code === 0) {\n setStatus('opa-check', 'passed');\n } else {\n setStatus('opa-check', 'failed');\n addError(\n 'opa.check',\n getPolicyProcessFailureMessage(\n checkResult,\n `opa check failed with exit code ${checkResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.regal) {\n const regalConfig = resolveRegalConfigFile(this, resolvedDir);\n const regalResult = await runner(\n 'regal',\n [\n 'lint',\n '--fail-level',\n 'warning',\n ...(regalConfig ? ['--config-file', regalConfig] : []),\n resolvedDir,\n ],\n { cwd: resolvedDir },\n this,\n );\n if (regalResult.code === 0) {\n setStatus('regal-lint', 'passed');\n } else {\n setStatus('regal-lint', 'failed');\n addError(\n 'regal.lint',\n getPolicyProcessFailureMessage(\n regalResult,\n `regal lint failed with exit code ${regalResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.opa) {\n const testResult = await runner(\n 'opa',\n ['test', '--fail-on-empty', '-b', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (testResult.code === 0) {\n setStatus('opa-test', 'passed');\n } else {\n setStatus('opa-test', 'failed');\n addError(\n 'opa.test',\n getPolicyProcessFailureMessage(\n testResult,\n `opa test --fail-on-empty -b failed with exit code ${testResult.code}`,\n ),\n );\n }\n }\n\n result.status = checks.some(({ status }) => status === 'failed') ? 'failed' : 'passed';\n return result;\n}\n\n/**\n * Verify local policy bundles with the shared upload contract, OPA, and Regal.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and verifies each. Pass one bundle path to\n * verify a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n * @param runner - Captured subprocess runner\n */\nexport async function lint(\n this: LocalContext,\n flags: LintCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { fix = false, noInteractive = false, json = false } = flags;\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n const missing: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.directory',\n severity: 'error',\n message: `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path: path.relative(this.process.cwd(), resolvedDir),\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(missing)}\\n`);\n } else {\n renderResult(this, missing);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n const empty: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.bundles',\n severity: 'error',\n message:\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n path: path.relative(this.process.cwd(), resolvedDir) || '.',\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(empty)}\\n`);\n } else {\n renderResult(this, empty);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const results: PolicyLintResult[] = [];\n for (const bundleDirectory of bundleDirectories) {\n results.push(\n await lintBundle.call(this, { fix, noInteractive, json }, bundleDirectory, runner),\n );\n }\n\n const failed = results.some((result) => result.status === 'failed');\n if (json) {\n if (results.length === 1) {\n this.process.stdout.write(`${JSON.stringify(results[0])}\\n`);\n } else {\n const multi: PolicyLintMultiResult = {\n version: POLICY_LINT_MULTI_RESULT_VERSION,\n status: failed ? 'failed' : 'passed',\n directory: resolvedDir,\n fix,\n results,\n };\n this.process.stdout.write(`${JSON.stringify(multi)}\\n`);\n }\n } else if (results.length === 1) {\n renderResult(this, results[0]!);\n } else {\n results.forEach((result, index) => {\n if (index > 0) {\n this.logger.info('');\n }\n const relative = path.relative(this.process.cwd(), result.directory) || result.directory;\n renderResult(this, result, `Policy verification — ${relative}`);\n });\n }\n\n if (failed) {\n this.process.exitCode = 1;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./pullChunkedCustomSiloOutstandingIdentifiers-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./pullChunkedCustomSiloOutstandingIdentifiers-B0TFbcgJ.mjs";import{i as t,s as n}from"./writeCsv-CNZrq3zU.mjs";import{t as r}from"./done-input-validation-LiTaCEzF.mjs";import{chunk as i,uniq as a}from"lodash-es";import o from"colors";import{map as s}from"@transcend-io/utils";import{buildTranscendGraphQLClient as c,fetchRequestFilesForRequest as l}from"@transcend-io/sdk";async function u({file:u,fileTarget:d,transcendUrl:f,auth:p,sombraAuth:m,cronDataSiloId:h,targetDataSiloId:g,actions:_,skipRequestCount:v,pageLimit:y,chunkSize:b}){v&&this.logger.info(o.yellow(`Skipping request count as requested. This may help speed up the call.`)),(Number.isNaN(b)||b<=0||b%y!==0)&&(this.logger.error(o.red(`Invalid chunk size: "${b}". Must be a positive integer that is a multiple of ${y}.`)),this.process.exit(1)),r(this.process);let x=c(f,p),{baseName:S,extension:C}=t(u),{baseName:w,extension:T}=t(d),E=0,D=0,O=0;await e({dataSiloId:h,auth:p,sombraAuth:m,actions:_,apiPageSize:y,savePageSize:b,onSave:async e=>{E+=e.length;let t=await s(i(a(e.map(e=>e.requestId)),y),async e=>(this.logger.info(o.magenta(`Fetching target identifiers for ${e.length} requests`)),(await l(x,{logger:this.logger,pageSize:y*2,filterBy:{requestIds:e,dataSiloIds:[g]}})).map(({fileName:e,remoteId:t})=>{if(!t)throw Error(`Failed to find remoteId for ${e}`);return{RecordId:t,Object:e.replace(`.json`,``).split(`/`).pop()?.replace(` Information`,``),Comment:`Customer data deletion request submitted via transcend.io`}})),{concurrency:1});D+=t.flat().length;let r=a(e.map(e=>Object.keys(e)).flat()),c=`${S}-${O}${C}`,f=`${w}-${O}${T}`;await n(c,e,r),this.logger.info(o.green(`Successfully wrote ${e.length} identifiers to file "${u}"`));let p=t.flat();await n(f,p,a(p.map(e=>Object.keys(e)).flat())),this.logger.info(o.green(`Successfully wrote ${p.length} identifiers to file "${d}"`)),this.logger.info(o.blue(`Processed chunk of ${i.length} identifiers, found ${p.length} target identifiers`)),O+=1},transcendUrl:f,skipRequestCount:v}),this.logger.info(o.green(`Successfully wrote ${E} identifiers to file "${u}"`)),this.logger.info(o.green(`Successfully wrote ${D} identifiers to file "${d}"`))}export{u as pullProfiles};
|
|
2
|
+
//# sourceMappingURL=impl-ZtYIzB9o.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-ZtYIzB9o.mjs","names":[],"sources":["../src/commands/request/cron/pull-profiles/impl.ts"],"sourcesContent":["import type { RequestAction } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, fetchRequestFilesForRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { uniq, chunk } from 'lodash-es';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport {\n pullChunkedCustomSiloOutstandingIdentifiers,\n type CsvFormattedIdentifier,\n} from '../../../../lib/cron/index.js';\nimport { parseFilePath, writeLargeCsv } from '../../../../lib/helpers/index.js';\n\nexport interface PullProfilesCommandFlags {\n file: string;\n fileTarget: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n cronDataSiloId: string;\n targetDataSiloId: string;\n actions: RequestAction[];\n skipRequestCount: boolean;\n pageLimit: number;\n chunkSize: number;\n}\n\nexport async function pullProfiles(\n this: LocalContext,\n {\n file,\n fileTarget,\n transcendUrl,\n auth,\n sombraAuth,\n cronDataSiloId,\n targetDataSiloId,\n actions,\n skipRequestCount,\n pageLimit,\n chunkSize,\n }: PullProfilesCommandFlags,\n): Promise<void> {\n if (skipRequestCount) {\n this.logger.info(\n colors.yellow('Skipping request count as requested. This may help speed up the call.'),\n );\n }\n\n if (Number.isNaN(chunkSize) || chunkSize <= 0 || chunkSize % pageLimit !== 0) {\n this.logger.error(\n colors.red(\n `Invalid chunk size: \"${chunkSize}\". Must be a positive integer that is a multiple of ${pageLimit}.`,\n ),\n );\n this.process.exit(1);\n }\n\n doneInputValidation(this.process);\n\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const { baseName, extension } = parseFilePath(file);\n const { baseName: baseNameTarget, extension: extensionTarget } = parseFilePath(fileTarget);\n\n let allIdentifiersCount = 0;\n let allTargetIdentifiersCount = 0;\n let fileCount = 0;\n // Create onSave callback to handle chunked processing\n const onSave = async (chunkToSave: CsvFormattedIdentifier[]): Promise<void> => {\n // Add to all identifiers\n allIdentifiersCount += chunkToSave.length;\n\n // Get unique request IDs from this chunk\n const requestIds = chunkToSave.map((d) => d.requestId as string);\n const uniqueRequestIds = uniq(requestIds);\n\n // Pull down target identifiers for this chunk\n const chunkedRequestIds = chunk(uniqueRequestIds, pageLimit);\n const results = await map(\n chunkedRequestIds,\n async (requestIds) => {\n this.logger.info(\n colors.magenta(`Fetching target identifiers for ${requestIds.length} requests`),\n );\n const results = await fetchRequestFilesForRequest(client, {\n logger: this.logger,\n pageSize: pageLimit * 2,\n filterBy: {\n requestIds,\n dataSiloIds: [targetDataSiloId],\n },\n });\n return results.map(({ fileName, remoteId }) => {\n if (!remoteId) {\n throw new Error(`Failed to find remoteId for ${fileName}`);\n }\n return {\n RecordId: remoteId,\n Object: fileName.replace('.json', '').split('/').pop()?.replace(' Information', ''),\n Comment: 'Customer data deletion request submitted via transcend.io',\n };\n });\n },\n // We are grabbing all the request files for the 'pageLimit' # of requests at a time\n {\n concurrency: 1,\n },\n );\n\n allTargetIdentifiersCount += results.flat().length;\n\n // Write the identifiers and target identifiers to CSV\n const headers = uniq(chunkToSave.map((d) => Object.keys(d)).flat());\n const numberedFileName = `${baseName}-${fileCount}${extension}`;\n const numberedFileNameTarget = `${baseNameTarget}-${fileCount}${extensionTarget}`;\n await writeLargeCsv(numberedFileName, chunkToSave, headers);\n this.logger.info(\n colors.green(`Successfully wrote ${chunkToSave.length} identifiers to file \"${file}\"`),\n );\n\n const targetIdentifiers = results.flat();\n const headers2 = uniq(targetIdentifiers.map((d) => Object.keys(d)).flat());\n await writeLargeCsv(numberedFileNameTarget, targetIdentifiers, headers2);\n this.logger.info(\n colors.green(\n `Successfully wrote ${targetIdentifiers.length} identifiers to file \"${fileTarget}\"`,\n ),\n );\n\n this.logger.info(\n colors.blue(\n `Processed chunk of ${chunk.length} identifiers, found ${targetIdentifiers.length} target identifiers`,\n ),\n );\n fileCount += 1;\n };\n\n // Pull down outstanding identifiers using the new chunked function\n await pullChunkedCustomSiloOutstandingIdentifiers({\n dataSiloId: cronDataSiloId,\n auth,\n sombraAuth,\n actions,\n apiPageSize: pageLimit,\n savePageSize: chunkSize,\n onSave,\n transcendUrl,\n skipRequestCount,\n });\n\n this.logger.info(\n colors.green(`Successfully wrote ${allIdentifiersCount} identifiers to file \"${file}\"`),\n );\n this.logger.info(\n colors.green(\n `Successfully wrote ${allTargetIdentifiersCount} identifiers to file \"${fileTarget}\"`,\n ),\n );\n}\n"],"mappings":"wYA4BA,eAAsB,EAEpB,CACE,OACA,aACA,eACA,OACA,aACA,iBACA,mBACA,UACA,mBACA,YACA,aAEa,CACX,GACF,KAAK,OAAO,KACV,EAAO,OAAO,wEAAwE,CACvF,EAGC,OAAO,MAAM,EAAU,EAAI,GAAa,GAAK,EAAY,IAAc,KACzE,KAAK,OAAO,MACV,EAAO,IACL,wBAAwB,EAAU,sDAAsD,EAAU,GACnG,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAS,EAA4B,EAAc,EAAK,CACxD,CAAE,WAAU,aAAc,EAAc,EAAK,CAC7C,CAAE,SAAU,EAAgB,UAAW,GAAoB,EAAc,EAAW,CAEtF,EAAsB,EACtB,EAA4B,EAC5B,EAAY,EAwEhB,MAAM,EAA4C,CAChD,WAAY,EACZ,OACA,aACA,UACA,YAAa,EACb,aAAc,EACd,YA7EoB,IAAyD,CAE7E,GAAuB,EAAY,OAQnC,IAAM,EAAU,MAAM,EADI,EAHD,EADN,EAAY,IAAK,GAAM,EAAE,UACJ,CAGQ,CAAE,EAE/B,CACjB,KAAO,KACL,KAAK,OAAO,KACV,EAAO,QAAQ,mCAAmC,EAAW,OAAO,WAAW,CAChF,EASM,MARe,EAA4B,EAAQ,CACxD,OAAQ,KAAK,OACb,SAAU,EAAY,EACtB,SAAU,CACR,aACA,YAAa,CAAC,EAAiB,CAChC,CACF,CAAC,EACa,KAAK,CAAE,WAAU,cAAe,CAC7C,GAAI,CAAC,EACH,MAAU,MAAM,+BAA+B,IAAW,CAE5D,MAAO,CACL,SAAU,EACV,OAAQ,EAAS,QAAQ,QAAS,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,QAAQ,eAAgB,GAAG,CACnF,QAAS,4DACV,EACD,EAGJ,CACE,YAAa,EACd,CACF,CAED,GAA6B,EAAQ,MAAM,CAAC,OAG5C,IAAM,EAAU,EAAK,EAAY,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAC7D,EAAmB,GAAG,EAAS,GAAG,IAAY,IAC9C,EAAyB,GAAG,EAAe,GAAG,IAAY,IAChE,MAAM,EAAc,EAAkB,EAAa,EAAQ,CAC3D,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAY,OAAO,wBAAwB,EAAK,GAAG,CACvF,CAED,IAAM,EAAoB,EAAQ,MAAM,CAExC,MAAM,EAAc,EAAwB,EAD3B,EAAK,EAAkB,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CACF,CAAC,CACxE,KAAK,OAAO,KACV,EAAO,MACL,sBAAsB,EAAkB,OAAO,wBAAwB,EAAW,GACnF,CACF,CAED,KAAK,OAAO,KACV,EAAO,KACL,sBAAsB,EAAM,OAAO,sBAAsB,EAAkB,OAAO,qBACnF,CACF,CACD,GAAa,GAYb,eACA,mBACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAoB,wBAAwB,EAAK,GAAG,CACxF,CACD,KAAK,OAAO,KACV,EAAO,MACL,sBAAsB,EAA0B,wBAAwB,EAAW,GACpF,CACF"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as e,t}from"./policyEngineCliError-CZrOHhLv.mjs";import{i as n,r,t as i}from"./printResult-Dmwv78e7.mjs";import{t as a}from"./formatPolicyBundleVersionSummary-DCHl1Vhy.mjs";import{n as o}from"./resolveBundleIdByName-
|
|
1
|
+
import{r as e,t}from"./policyEngineCliError-CZrOHhLv.mjs";import{i as n,r,t as i}from"./printResult-Dmwv78e7.mjs";import{t as a}from"./formatPolicyBundleVersionSummary-DCHl1Vhy.mjs";import{n as o}from"./resolveBundleIdByName-D7NUOpLc.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({"remote-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
2
|
`)}),h.info(l.green(`Policy bundle version deactivated.`))}export{u as deactivate};
|
|
3
|
-
//# sourceMappingURL=impl-
|
|
3
|
+
//# sourceMappingURL=impl-qNF5eqX-.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-qNF5eqX-.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 'remote-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 `--remote-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 'remote-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,qBAAsB,EACtB,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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./updateConsentManagerVersionToLatest-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./updateConsentManagerVersionToLatest-B2Ke4QhR.mjs";import{t}from"./validateTranscendAuth-D-dDINof.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import{ConsentBundleType as r}from"@transcend-io/privacy-types";import i from"colors";import{mapSeries as a}from"@transcend-io/utils";async function o({auth:o,bundleTypes:s=[r.Production,r.Test],deploy:c,transcendUrl:l}){n(this.process);let u=await t(o,this);typeof u==`string`?(await e({deploy:c,transcendUrl:l,auth:u,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager!`))):(await a(u,async t=>{this.logger.info(i.magenta(`Updating Consent Manager for organization "${t.organizationName}"...`)),await e({deploy:c,transcendUrl:l,auth:t.apiKey,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager for organization "${t.organizationName}"!`))}),this.logger.info(i.green(`Successfully updated Consent Managers!`)))}export{o as updateConsentManager};
|
|
2
|
+
//# sourceMappingURL=impl-sEJHkjPw.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-sEJHkjPw.mjs","names":[],"sources":["../src/commands/consent/update-consent-manager/impl.ts"],"sourcesContent":["import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { updateConsentManagerVersionToLatest } from '../../../lib/consent-manager/index.js';\n\nexport interface UpdateConsentManagerCommandFlags {\n auth: string;\n bundleTypes: ConsentBundleType[];\n deploy: boolean;\n transcendUrl: string;\n}\n\nexport async function updateConsentManager(\n this: LocalContext,\n {\n auth,\n bundleTypes = [ConsentBundleType.Production, ConsentBundleType.Test],\n deploy,\n transcendUrl,\n }: UpdateConsentManagerCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n // Handle single update\n if (typeof apiKeyOrList === 'string') {\n // Update consent manager\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKeyOrList,\n bundleTypes,\n });\n this.logger.info(colors.green('Successfully updated Consent Manager!'));\n } else {\n await mapSeries(apiKeyOrList, async (apiKey) => {\n this.logger.info(\n colors.magenta(`Updating Consent Manager for organization \"${apiKey.organizationName}\"...`),\n );\n\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKey.apiKey,\n bundleTypes,\n });\n\n this.logger.info(\n colors.green(\n `Successfully updated Consent Manager for organization \"${apiKey.organizationName}\"!`,\n ),\n );\n });\n this.logger.info(colors.green('Successfully updated Consent Managers!'));\n }\n}\n"],"mappings":"0TAgBA,eAAsB,EAEpB,CACE,OACA,cAAc,CAAC,EAAkB,WAAY,EAAkB,KAAK,CACpE,SACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAe,MAAM,EAAsB,EAAM,KAAK,CAGxD,OAAO,GAAiB,UAE1B,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EACN,cACD,CAAC,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,wCAAwC,CAAC,GAEvE,MAAM,EAAU,EAAc,KAAO,IAAW,CAC9C,KAAK,OAAO,KACV,EAAO,QAAQ,8CAA8C,EAAO,iBAAiB,MAAM,CAC5F,CAED,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EAAO,OACb,cACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MACL,0DAA0D,EAAO,iBAAiB,IACnF,CACF,EACD,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,yCAAyC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{l as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{l as e}from"./constants-CXMjsQ0a.mjs";import{t}from"./generateCrossAccountApiKeys-Baa_kNwU.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";async function r({email:r,password:i,apiKeyTitle:a,file:o,scopes:s,deleteExistingApiKey:c,createNewApiKey:l,parentOrganizationId:u,transcendUrl:d}){n(this.process);let{errors:f,apiKeys:p}=await t({transcendUrl:d,password:i,email:r,parentOrganizationId:u,deleteExistingApiKey:c,createNewApiKey:l,apiKeyTitle:a,scopes:s.map(t=>e[t].name)});this.fs.writeFileSync(o,`${JSON.stringify(p,null,2)}\n`),f.length>0&&this.process.exit(1)}export{r as generateApiKeys};
|
|
2
|
+
//# sourceMappingURL=impl-tNT_EfWf.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-tNT_EfWf.mjs","names":[],"sources":["../src/commands/admin/generate-api-keys/impl.ts"],"sourcesContent":["import { ScopeName } from '@transcend-io/privacy-types';\n\nimport { SCOPES_BY_TITLE } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { generateCrossAccountApiKeys } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\n\n// Command flag interface\nexport interface GenerateApiKeysCommandFlags {\n email: string;\n password: string;\n apiKeyTitle: string;\n file: string;\n scopes: string[];\n deleteExistingApiKey: boolean;\n createNewApiKey: boolean;\n parentOrganizationId?: string;\n transcendUrl: string;\n}\n\n// Command implementation\nexport async function generateApiKeys(\n this: LocalContext,\n {\n email,\n password,\n apiKeyTitle,\n file,\n scopes,\n deleteExistingApiKey,\n createNewApiKey,\n parentOrganizationId,\n transcendUrl,\n }: GenerateApiKeysCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const scopeNames = scopes.map((scopeTitle) => SCOPES_BY_TITLE[scopeTitle].name as ScopeName);\n\n // Upload privacy requests\n const { errors, apiKeys } = await generateCrossAccountApiKeys({\n transcendUrl,\n password,\n email,\n parentOrganizationId,\n deleteExistingApiKey,\n createNewApiKey,\n apiKeyTitle,\n scopes: scopeNames,\n });\n\n // Write to disk\n this.fs.writeFileSync(file, `${JSON.stringify(apiKeys, null, 2)}\\n`);\n if (errors.length > 0) {\n this.process.exit(1);\n }\n}\n"],"mappings":"gKAqBA,eAAsB,EAEpB,CACE,QACA,WACA,cACA,OACA,SACA,uBACA,kBACA,uBACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAKjC,GAAM,CAAE,SAAQ,WAAY,MAAM,EAA4B,CAC5D,eACA,WACA,QACA,uBACA,uBACA,kBACA,cACA,OAXiB,EAAO,IAAK,GAAe,EAAgB,GAAY,KAWtD,CACnB,CAAC,CAGF,KAAK,GAAG,cAAc,EAAM,GAAG,KAAK,UAAU,EAAS,KAAM,EAAE,CAAC,IAAI,CAChE,EAAO,OAAS,GAClB,KAAK,QAAQ,KAAK,EAAE"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{i as e}from"./policy-project-discovery-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{i as e}from"./policy-project-discovery-BR9EiTHd.mjs";import{n as t,r as n}from"./runOpa-ojIqU1tO.mjs";import{t as r}from"./done-input-validation-LiTaCEzF.mjs";import i from"node:path";import a from"colors";async function o({package:o,input:s,"stdin-input":c,format:l,schema:u,explain:d,metrics:f,instrument:p,profile:m,timeout:h,"var-values":g,"show-builtin-errors":_},v){if(r(this.process),n(),c&&s)throw Error(`Pass either --input or --stdin-input, not both.`);if(!c&&!s)throw Error(`Provide an input document with --input <path> or --stdin-input.`);let y,b;if(c)y=[`--stdin-input`],b=`stdin`;else{let e=i.resolve(this.process.cwd(),s);if(!this.fs.existsSync(e))throw Error(`Input file not found: ${e}`);y=[`--input`,e],b=e}let x=e(this.process.cwd(),v),S=u?i.resolve(this.process.cwd(),u):void 0;if(S&&!this.fs.existsSync(S))throw Error(`Schema path not found: ${S}`);let C=[`eval`,`--format`,l,...y,`-b`,x,`--ignore`,`*_test.rego`,...S?[`--schema`,S]:[],...d&&d!==`off`?[`--explain`,d]:[],...f?[`--metrics`]:[],...p?[`--instrument`]:[],...m?[`--profile`]:[],...h?[`--timeout`,h]:[],...g?[`--var-values`]:[],..._?[`--show-builtin-errors`]:[],o];this.logger.info(a.green(`Evaluating ${o} with input ${b}...`));let w=await t(C);w!==0&&this.process.exit(w)}export{o as _eval};
|
|
2
|
+
//# sourceMappingURL=impl-w6TtbzCB.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-w6TtbzCB.mjs","names":[],"sources":["../src/commands/policy/eval/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { resolvePolicyProjectDirectory } from '../../../lib/policy/policy-project-discovery.js';\nimport { assertOpaInstalled, runOpa } from '../helpers/index.js';\nimport type { PolicyEvalExplainMode, PolicyEvalFormat } from './command.js';\n\n/** CLI flags for `transcend policy eval`. */\nexport interface EvalCommandFlags {\n /** OPA query to evaluate (e.g. `data.example.result`). */\n package: string;\n /** Path to a JSON envelope input file. */\n input?: string;\n /** Read the input document from stdin (`opa eval --stdin-input`). */\n 'stdin-input': boolean;\n /** `opa eval --format` value. */\n format: PolicyEvalFormat;\n /** Optional `opa eval --schema` path. */\n schema?: string;\n /** Optional `opa eval --explain` mode. */\n explain?: PolicyEvalExplainMode;\n /** `opa eval --metrics`. */\n metrics: boolean;\n /** `opa eval --instrument`. */\n instrument: boolean;\n /** `opa eval --profile`. */\n profile: boolean;\n /** Optional `opa eval --timeout` duration. */\n timeout?: string;\n /** `opa eval --var-values`. */\n 'var-values': boolean;\n /** `opa eval --show-builtin-errors`. */\n 'show-builtin-errors': boolean;\n}\n\n/**\n * Evaluate one envelope against a local policy bundle via `opa eval`.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy bundle directory containing a `.manifest`\n */\nexport async function _eval(\n this: LocalContext,\n {\n package: query,\n input,\n 'stdin-input': stdinInput,\n format,\n schema,\n explain,\n metrics,\n instrument,\n profile,\n timeout,\n 'var-values': varValues,\n 'show-builtin-errors': showBuiltinErrors,\n }: EvalCommandFlags,\n directory: string,\n): Promise<void> {\n doneInputValidation(this.process);\n\n assertOpaInstalled();\n\n if (stdinInput && input) {\n throw new Error('Pass either --input or --stdin-input, not both.');\n }\n if (!stdinInput && !input) {\n throw new Error('Provide an input document with --input <path> or --stdin-input.');\n }\n\n let inputArgs: string[];\n let inputLabel: string;\n if (stdinInput) {\n inputArgs = ['--stdin-input'];\n inputLabel = 'stdin';\n } else {\n const inputPath = path.resolve(this.process.cwd(), input!);\n if (!this.fs.existsSync(inputPath)) {\n throw new Error(`Input file not found: ${inputPath}`);\n }\n inputArgs = ['--input', inputPath];\n inputLabel = inputPath;\n }\n\n const bundlePath = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n const schemaPath = schema ? path.resolve(this.process.cwd(), schema) : undefined;\n if (schemaPath && !this.fs.existsSync(schemaPath)) {\n throw new Error(`Schema path not found: ${schemaPath}`);\n }\n\n // Match lint/publish and production Evaluate: `*_test.rego` is local-only and\n // never shipped. Keep `-b` / `--ignore` owned by the CLI (not pass-through).\n const args = [\n 'eval',\n '--format',\n format,\n ...inputArgs,\n '-b',\n bundlePath,\n '--ignore',\n '*_test.rego',\n ...(schemaPath ? ['--schema', schemaPath] : []),\n ...(explain && explain !== 'off' ? ['--explain', explain] : []),\n ...(metrics ? ['--metrics'] : []),\n ...(instrument ? ['--instrument'] : []),\n ...(profile ? ['--profile'] : []),\n ...(timeout ? ['--timeout', timeout] : []),\n ...(varValues ? ['--var-values'] : []),\n ...(showBuiltinErrors ? ['--show-builtin-errors'] : []),\n query,\n ];\n\n this.logger.info(colors.green(`Evaluating ${query} with input ${inputLabel}...`));\n\n const exitCode = await runOpa(args);\n if (exitCode !== 0) {\n this.process.exit(exitCode);\n }\n}\n"],"mappings":"qNA6CA,eAAsB,EAEpB,CACE,QAAS,EACT,QACA,cAAe,EACf,SACA,SACA,UACA,UACA,aACA,UACA,UACA,aAAc,EACd,sBAAuB,GAEzB,EACe,CAKf,GAJA,EAAoB,KAAK,QAAQ,CAEjC,GAAoB,CAEhB,GAAc,EAChB,MAAU,MAAM,kDAAkD,CAEpE,GAAI,CAAC,GAAc,CAAC,EAClB,MAAU,MAAM,kEAAkE,CAGpF,IAAI,EACA,EACJ,GAAI,EACF,EAAY,CAAC,gBAAgB,CAC7B,EAAa,YACR,CACL,IAAM,EAAY,EAAK,QAAQ,KAAK,QAAQ,KAAK,CAAE,EAAO,CAC1D,GAAI,CAAC,KAAK,GAAG,WAAW,EAAU,CAChC,MAAU,MAAM,yBAAyB,IAAY,CAEvD,EAAY,CAAC,UAAW,EAAU,CAClC,EAAa,EAGf,IAAM,EAAa,EAA8B,KAAK,QAAQ,KAAK,CAAE,EAAU,CACzE,EAAa,EAAS,EAAK,QAAQ,KAAK,QAAQ,KAAK,CAAE,EAAO,CAAG,IAAA,GACvE,GAAI,GAAc,CAAC,KAAK,GAAG,WAAW,EAAW,CAC/C,MAAU,MAAM,0BAA0B,IAAa,CAKzD,IAAM,EAAO,CACX,OACA,WACA,EACA,GAAG,EACH,KACA,EACA,WACA,cACA,GAAI,EAAa,CAAC,WAAY,EAAW,CAAG,EAAE,CAC9C,GAAI,GAAW,IAAY,MAAQ,CAAC,YAAa,EAAQ,CAAG,EAAE,CAC9D,GAAI,EAAU,CAAC,YAAY,CAAG,EAAE,CAChC,GAAI,EAAa,CAAC,eAAe,CAAG,EAAE,CACtC,GAAI,EAAU,CAAC,YAAY,CAAG,EAAE,CAChC,GAAI,EAAU,CAAC,YAAa,EAAQ,CAAG,EAAE,CACzC,GAAI,EAAY,CAAC,eAAe,CAAG,EAAE,CACrC,GAAI,EAAoB,CAAC,wBAAwB,CAAG,EAAE,CACtD,EACD,CAED,KAAK,OAAO,KAAK,EAAO,MAAM,cAAc,EAAM,cAAc,EAAW,KAAK,CAAC,CAEjF,IAAM,EAAW,MAAM,EAAO,EAAK,CAC/B,IAAa,GACf,KAAK,QAAQ,KAAK,EAAS"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e,n as t,r as n,t as r}from"./enums-OiLcZ26O.mjs";import{a as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./constants-
|
|
1
|
+
import{i as e,n as t,r as n,t as r}from"./enums-OiLcZ26O.mjs";import{a as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./constants-CXMjsQ0a.mjs";import{t as b}from"./logger-CPu6zbyQ.mjs";import{$ as x,A as S,B as ee,C as te,D as C,E as ne,F as re,G as ie,H as ae,I as oe,J as se,K as ce,L as le,M as ue,N as w,O as de,P as fe,Q as T,R as E,S as D,T as O,U as k,V as A,W as j,X as M,Y as N,Z as P,_ as F,a as I,at as L,b as R,c as z,ct as B,d as V,dt as pe,et as me,f as he,ft as ge,g as _e,gt as ve,h as ye,ht as be,i as xe,it as Se,j as Ce,k as we,l as Te,lt as Ee,m as De,mt as Oe,n as ke,nt as Ae,o as je,ot as Me,p as Ne,pt as Pe,q as Fe,r as Ie,rt as Le,s as Re,st as ze,t as Be,tt as Ve,u as He,ut as Ue,v as We,w as Ge,x as Ke,y as qe,z as Je}from"./codecs-CfcaFoZR.mjs";import{a as Ye,i as Xe,n as Ze,o as Qe,r as $e,s as et,t as tt}from"./readTranscendYaml-BfqQbPiT.mjs";import{i as nt,n as rt,r as it,t as at}from"./mergeTranscendInputs-B7WjxYMN.mjs";import{a as ot,c as st,i as ct,l as lt,n as ut,o as dt,r as ft,s as pt,t as mt,u as ht}from"./constants-DlH2vWm_.mjs";import{n as gt,t as _t}from"./fuzzyMatchColumns-D18n9Beu.mjs";import{a as vt,c as yt,d as bt,f as xt,i as St,l as Ct,n as wt,o as Tt,r as Et,s as Dt,t as Ot,u as kt}from"./uploadPrivacyRequestsFromCsv-BGv8UH5q.mjs";import{n as At,t as jt}from"./parseAttributesFromString-C5hJMRvt.mjs";import{n as H,t as Mt}from"./readCsv-DNcJ_UfU.mjs";import{n as Nt,t as Pt}from"./pullUnstructuredSubDataPointRecommendations-Ci4AOxyH.mjs";import{a as Ft,i as It,n as Lt,o as Rt,r as zt,t as Bt}from"./request-BpKyN9Xm.mjs";import{i as Vt,n as Ht,r as Ut,t as Wt}from"./pullTranscendConfiguration-CDUDqxpm.mjs";import{i as Gt,n as Kt,r as U,t as qt}from"./fetchAllRequests-BI0tFl_a.mjs";import{a as Jt,i as Yt,n as Xt,r as Zt,t as Qt}from"./pullChunkedCustomSiloOutstandingIdentifiers-B0TFbcgJ.mjs";import{n as $t,r as en,t as tn}from"./syncCodePackages-DJnrcX5l.mjs";import{t as nn}from"./markSilentPrivacyRequests--bQ3UAKC.mjs";import{a as rn,i as an,n as on,o as sn,r as cn,t as ln}from"./downloadPrivacyRequestFiles-DgcvbEMQ.mjs";import{n as un,r as dn,t as fn}from"./extractClientError-BQgmnp3e.mjs";import{t as pn}from"./approvePrivacyRequests-C0muFWCU.mjs";import{t as mn}from"./notifyPrivacyRequestsAdditionalTime-DQ9_6DaJ.mjs";import{t as hn}from"./cancelPrivacyRequests-BjltZFLz.mjs";import{n as gn,t as _n}from"./bulkRestartRequests-Y9CfKTw_.mjs";import{t as vn}from"./skipPreflightJobs-enp_ioAV.mjs";import{t as yn}from"./bulkRetryEnrichers-ciLaGX2W.mjs";import{t as bn}from"./retryRequestDataSilos-MxpSNKuV.mjs";import{n as W,r as G,t as xn}from"./streamPrivacyRequestsToCsv-Cx5QIQT6.mjs";import{n as Sn,r as Cn,t as wn}from"./inquirer-jzIQWAvq.mjs";import{t as Tn}from"./parseVariablesFromString-6TYW65LF.mjs";import{t as En}from"./collectParquetFilesOrExit-CbNQ9CJc.mjs";import{t as Dn}from"./collectCsvFilesOrExit-BindZ0dF.mjs";import{t as On}from"./parquetToCsvOneFile-DtbCFm08.mjs";import{a as kn,i as An,n as jn,o as Mn,r as Nn,s as Pn,t as Fn}from"./writeCsv-CNZrq3zU.mjs";import{t as In}from"./skipRequestDataSilos-B23W9ZJe.mjs";import{t as Ln}from"./removeUnverifiedRequestIdentifiers-DkbeJa9c.mjs";import{t as Rn}from"./updateConsentManagerVersionToLatest-B2Ke4QhR.mjs";import{n as K,t as q}from"./mapConsentCsvRowsToInputs-CkLfxaIf.mjs";import{t as zn}from"./pullConsentManagerMetrics-DKCkfbCB.mjs";import{n as Bn,r as Vn,t as Hn}from"./buildXdiSyncEndpoint-DZtSxC6c.mjs";import{t as Un}from"./consentManagersToBusinessEntities-DG0_eby5.mjs";import{i as Wn,n as Gn,r as Kn,t as qn}from"./uploadConsents-BkvhwPJ6.mjs";import{n as Jn,r as Yn,t as Xn}from"./pushCronIdentifiersFromCsv-DLmgvrjn.mjs";import{t as Zn}from"./markRequestDataSiloIdsCompleted-63FCcKgi.mjs";import{t as Qn}from"./generateCrossAccountApiKeys-Baa_kNwU.mjs";import{t as $n}from"./validateTranscendAuth-D-dDINof.mjs";import{n as er,t as tr}from"./listFiles-DDGCBdtx.mjs";import{t as nr}from"./pullAllDatapoints-CNqQSSmF.mjs";import{t as rr}from"./pullManualEnrichmentIdentifiersToCsv-Bbg5FOIJ.mjs";import{n as ir,r as ar,t as or}from"./pushManualEnrichmentIdentifiersFromCsv-Cih6wgBt.mjs";import{chunk as sr,difference as cr}from"lodash-es";import{join as lr}from"node:path";import J from"colors";import{readFileSync as ur,readdirSync as dr,statSync as Y}from"node:fs";import{map as X,mapSeries as fr}from"@transcend-io/utils";import pr from"fast-glob";import{UPDATE_OR_CREATE_COOKIES as mr,buildTranscendGraphQLClient as Z,createSombraGotInstance as hr,fetchAllRequestIdentifiers as gr,fetchConsentManagerId as _r,makeGraphQLRequest as vr,syncCookies as yr,syncDataFlows as br,validateSombraVersion as xr}from"@transcend-io/sdk";import{execSync as Q}from"child_process";async function $(e,t){let n=await _r(e,{logger:b});await fr(sr(t,100),async t=>{await vr(e,mr,{variables:{airgapBundleId:n,cookies:t.map(e=>({name:e.name,trackingPurposes:e.trackingPurposes&&e.trackingPurposes.length>0?e.trackingPurposes:void 0,description:e.description,service:e.service,status:e.status,attributes:e.attributes,isRegex:e.isRegex}))},logger:b})})}async function Sr(e,t){let n=!1;b.info(J.magenta(`Syncing "${t.length}" cookies...`));let r=t.filter(e=>t.filter(t=>e.name===t.name&&e.isRegex===t.isRegex).length>1);if(r.length>0)throw Error(`Failed to upload cookies as there were non-unique entries found: ${r.map(({name:e})=>e).join(`,`)}`);try{b.info(J.magenta(`Upserting "${t.length}" new cookies...`)),await $(e,t),b.info(J.green(`Successfully synced ${t.length} cookies!`))}catch(e){n=!0,b.error(J.red(`Failed to create cookies! - ${e.message}`))}return!n}async function Cr({auth:e,sombraAuth:t,actions:n=[],statuses:r=[],identifierSearch:a,pageLimit:o=100,concurrency:s=1,transcendUrl:c=i,createdAtBefore:l,skipRequestIdentifiers:u=!1,createdAtAfter:d,updatedAtBefore:f,updatedAtAfter:p,isTest:m}){let h=Z(c,e),g=await hr(c,e,{logger:b,sombraApiKey:t,sombraUrl:process.env.SOMBRA_URL}),_=``;l&&(_+=` before ${l.toISOString()}`),d&&(_+=`${_?`, and`:``} after ${d.toISOString()}`),b.info(J.magenta(`${n.length>0?`Pulling requests of type "${n.join(`" , "`)}"`:`Pulling all requests`}${_}`));let v=s>1&&d&&l,y=v?W(d,l,s):[{createdAtAfter:d,createdAtBefore:l}];v&&b.info(J.magenta(`Splitting date range into ${s} parallel chunks`));let x=(await X(y,e=>U(h,{actions:n,text:a,statuses:r,createdAtBefore:e.createdAtBefore,createdAtAfter:e.createdAtAfter,updatedAtBefore:f,updatedAtAfter:p,isTest:m}),{concurrency:v?s:1})).flat();u||await xr(h,{logger:b});let S=u?x.map(e=>({...e,requestIdentifiers:[]})):await X(x,async e=>{let t=await gr(h,g,{filterBy:{requestId:e.id},skipSombraCheck:!0,logger:b});return{...e,requestIdentifiers:t}},{concurrency:o});return b.info(J.magenta(`Pulled ${S.length} requests`)),{requestsWithRequestIdentifiers:S,requestsFormattedForCsv:S.map(G)}}function wr(e,t=ur){try{return e?t(e,`utf8`):``}catch{return``}}async function Tr({auth:e,trackerStatus:t,file:n,classifyService:r=!1,transcendUrl:a=i}){let o=Z(a,e);b.info(J.magenta(`Reading "${n}" from disk`)),await br(o,K(H(n,w),t),{classifyService:r,logger:b})||(b.error(J.red(`Encountered error(s) syncing data flows from CSV, see logs above for more info. `)),process.exit(1))}async function Er({auth:e,trackerStatus:t,file:n,transcendUrl:r=i}){let a=Z(r,e);b.info(J.magenta(`Reading "${n}" from disk`)),await yr(a,q(H(n,C),t),{logger:b})||(b.error(J.red(`Encountered error(s) syncing cookies from CSV, see logs above for more info. `)),process.exit(1))}function Dr(e){return dr(e).filter(t=>Y(lr(e,t)).isDirectory())}function Or(e){return e.replace(/(https?:\/\/[^\s]+)/g,`<link-omitted>`)}function kr(e){return Object.entries(e).reduce((e,[t,n])=>n!=null&&n!==``&&!(Array.isArray(n)&&n.length===0)&&!(typeof n==`object`&&Object.keys(n).length===0)?Object.assign(e,{[t]:n}):e,{})}function Ar({baseBranch:e,rootDirectory:t,githubRepo:n,excludedGlob:r=[],fileBlockList:i=[]}){Q(`git fetch origin ${e}`);let a=Q(`git ls-remote ${n} "refs/heads/${e}" | cut -f 1`,{encoding:`utf-8`}).split(`
|
|
2
2
|
`)[0],o=Q(`git rev-parse HEAD`,{encoding:`utf-8`}).split(`
|
|
3
3
|
`)[0];if(!a||!o)throw Error(`FAILED TO FIND COMMIT RANGE`);let s=cr(Q(`git fetch && git diff --name-only "${e||a}...${o}" -- ${t}`,{encoding:`utf-8`}).split(`
|
|
4
4
|
`).filter(e=>e),i),c=r.length>0?pr.sync(s,{ignore:r}):s,l={};return c.forEach(e=>{l[e]=Q(`git show ${o}:${e}`,{encoding:`utf-8`})}),{changedFiles:s,fileDiffs:l,repoName:n.split(`/`).pop().split(`.`)[0],commit:o}}export{v as ADMIN_DASH,p as ADMIN_DASH_DATAPOINTS,g as ADMIN_DASH_INTEGRATIONS,Bt as APPROVE_PRIVACY_REQUEST,Vt as ASSESSMENT_TEMPLATES,Be as ActionInput,ke as ActionItemCollectionInput,Ie as ActionItemInput,xe as ApiKeyInput,I as AssessmentAnswerOptionInput,je as AssessmentDisplayLogicInput,Re as AssessmentInput,z as AssessmentNestedRuleInput,Te as AssessmentResourceInput,He as AssessmentRetentionScheduleInput,V as AssessmentRuleInput,he as AssessmentSectionInput,Ne as AssessmentSectionQuestionInput,De as AssessmentTemplateInput,St as AttestedExtraIdentifiers,ye as AttributeInput,_e as AttributePreview,F as AttributeValueInput,mt as BLANK,ut as BULK_APPLY,We as BusinessEntityInput,Lt as CANCEL_PRIVACY_REQUEST,ft as CAN_APPLY_IN_BULK,ct as CachedFileState,ot as CachedRequestState,qe as CodePackageInput,R as CodePackageSdk,dt as ColumnName,Ke as ConsentManageExperienceInput,D as ConsentManagerInput,te as ConsentManagerServiceMetadata,Ge as ConsentPreferenceTopic,O as ConsentPreferenceTopicOptionValue,ne as ConsentPurpose,C as CookieCsvInput,de as CookieInput,Xt as CronIdentifier,Jn as CronIdentifierPush,Zt as CronPartition,u as DEBUG,i as DEFAULT_TRANSCEND_API,m as DEFAULT_TRANSCEND_API_KEY,_ as DEFAULT_TRANSCEND_CONSENT_API,Wt as DEFAULT_TRANSCEND_PULL_RESOURCES,we as DataCategoryGuessInput,S as DataCategoryInput,Ce as DataCategoryPreviewInput,ue as DataCategoryRecommendationInput,w as DataFlowCsvInput,fe as DataFlowInput,re as DataSiloInput,oe as DataSubjectInput,le as DatapointInput,E as DeletionDependencies,Je as DeletionDependency,ee as DeletionDependencyInput,A as DeletionDependencyReset,Nt as ENTRY_COUNT,ir as EnrichPrivacyRequest,ae as EnricherInput,k as FieldInput,pt as IDENTIFIER_BLOCK_LIST,Hn as IP_ADDRESS_REGEX,st as IS_REQUIRED,j as IdentifierInput,ie as ImportOnetrustAssessmentsInput,cn as IntlMessage,ce as IntlMessageInput,lt as NONE,zt as NOTIFY_ADDITIONAL_TIME,r as OneTrustFileFormat,t as OneTrustPullResource,n as OneTrustPullSource,jt as ParsedAttributeInput,Fe as PartitionInput,se as PolicyInput,N as PreferenceWorkflowConfigInput,M as PreferenceWorkflowConfigPurposeInput,P as PreflightInput,T as PrivacyCenterInput,qt as PrivacyRequest,vt as PrivacyRequestInput,un as PrivacyRequestResponse,x as ProcessingActivityInput,me as ProcessingPurposeInput,Ve as ProcessingPurposePreviewInput,Ae as PromptAVendorEmailSettings,qn as PurposeMap,It as REQUESTS,Ft as REQUESTS_COUNT,a as RETRYABLE_BATCH_STATUSES,Le as RegionInput,Se as RepositoryInput,an as RequestFileMetadata,rn as RequestFileMetadataResponse,Kt as RequestPurposeTrigger,L as RiskAssignmentInput,Me as RiskLogicInput,d as SCOPES_BY_TITLE,y as SCOPE_TITLES,ze as SiloDiscoveryResultInput,B as SoftwareDevelopmentKitInput,Ee as StoredApiKey,ht as SuccessfulRequest,o as TR_PULL_RESOURCE_SCOPE_MAP,s as TR_PUSH_RESOURCE_SCOPE_MAP,h as TR_YML_RESOURCE_TO_FIELD_NAME,Ue as TeamInput,pe as TemplateInput,ge as TranscendInput,e as TranscendPullResource,Rt as UPDATE_PRIVACY_REQUEST,Gn as USP_STRING_REGEX,tt as VARIABLE_PARAMETERS_NAME,Ze as VARIABLE_PARAMETERS_REGEXP,Pe as VendorInput,Oe as WebhookHeader,be as WorkflowConfigInput,Fn as appendCsvRowsOrdered,jn as appendCsvSync,pn as approvePrivacyRequests,Bn as buildXdiSyncEndpoint,_n as bulkRestartRequests,yn as bulkRetryEnrichers,hn as cancelPrivacyRequests,Dn as collectCsvFilesOrExit,En as collectParquetFilesOrExit,Un as consentManagersToBusinessEntities,tn as createCodePackage,Wn as createConsentToken,l as description,Vn as domainToHost,ln as downloadPrivacyRequestFiles,ar as enrichPrivacyRequest,nt as ensureAllDataSubjectsExist,fn as extractClientError,Ut as fetchAllAssessmentTemplates,U as fetchAllRequests,Jt as fetchRequestDataSiloActiveCount,Gt as fetchRequestsTotalCount,tr as filterFileNames,kr as filterNullishValuesFromObject,kt as filterRows,G as formatRequestForCsv,_t as fuzzyMatchColumns,gt as fuzzySearch,Qn as generateCrossAccountApiKeys,sn as getFileMetadataForPrivacyRequests,Ar as getGitFilesThatChanged,bt as getUniqueValuesForColumn,Nn as initCsvFile,wn as inquirerAutoComplete,Sn as inquirerConfirmBoolean,Cn as inquirerConfirmText,Dr as listDirectories,er as listFiles,wt as mapColumnsToAttributes,Et as mapColumnsToIdentifiers,q as mapCookieCsvRowsToInputs,Ct as mapCsvColumnsToApi,Tt as mapCsvRowsToRequestInputs,K as mapDataFlowCsvRowsToInputs,xt as mapEnumValues,yt as mapRequestEnumValues,Yn as markCronIdentifierCompleted,Zn as markRequestDataSiloIdsCompleted,nn as markSilentPrivacyRequests,at as mergeTranscendInputs,f as name,Dt as normalizeIdentifierValue,ve as normalizeTranscendInput,mn as notifyPrivacyRequestsAdditionalTime,On as parquetToCsvOneFile,At as parseAttributesFromString,Mt as parseCsv,An as parseFilePath,$e as parseTranscendYaml,Tn as parseVariablesFromString,nr as pullAllDatapoints,Qt as pullChunkedCustomSiloOutstandingIdentifiers,zn as pullConsentManagerMetrics,Yt as pullCronPageOfIdentifiers,rr as pullManualEnrichmentIdentifiersToCsv,Cr as pullPrivacyRequests,Ht as pullTranscendConfiguration,Pt as pullUnstructuredSubDataPointRecommendations,Xn as pushCronIdentifiersFromCsv,or as pushManualEnrichmentIdentifiersFromCsv,H as readCsv,wr as readSafe,Xe as readTranscendYaml,Or as removeLinks,Ln as removeUnverifiedRequestIdentifiers,Ye as replaceVariablesInYaml,gn as restartPrivacyRequest,bn as retryRequestDataSilos,Qe as serializeTranscendYaml,vn as skipPreflightJobs,In as skipRequestDataSilos,W as splitDateRange,on as streamPrivacyRequestFiles,xn as streamPrivacyRequestsToCsv,dn as submitPrivacyRequest,$t as syncCodePackages,rt as syncConfigurationToTranscend,Sr as syncCookies,it as syncDataSilos,en as updateCodePackages,Rn as updateConsentManagerVersionToLatest,$ as updateOrCreateCookies,Kn as uploadConsents,Er as uploadCookiesFromCsv,Tr as uploadDataFlowsFromCsv,Ot as uploadPrivacyRequestsFromCsv,$n as validateTranscendAuth,c as version,kn as writeCsv,Mn as writeCsvSync,Pn as writeLargeCsv,et as writeTranscendYaml};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=markRequestDataSiloIdsCompleted-
|
|
1
|
+
import{a as e}from"./constants-CXMjsQ0a.mjs";import{t}from"./logger-CPu6zbyQ.mjs";import{RequestDataSiloStatus as n}from"@transcend-io/privacy-types";import r from"colors";import{map as i}from"@transcend-io/utils";import{CHANGE_REQUEST_DATA_SILO_STATUS as a,buildTranscendGraphQLClient as o,fetchRequestDataSilo as s,makeGraphQLRequest as c}from"@transcend-io/sdk";import l from"cli-progress";async function u({requestIds:u,dataSiloId:d,auth:f,concurrency:p=100,status:m=n.Resolved,transcendUrl:h=e}){let g=o(h,f),_=new Date().getTime(),v=new l.SingleBar({},l.Presets.shades_classic);t.info(r.magenta(`Notifying Transcend for data silo "${d}" marking "${u.length}" requests as completed.`));let y=0;v.start(u.length,0),await i(u,async e=>{let n=await s(g,{logger:t,filterBy:{requestId:e,dataSiloId:d}});try{await c(g,a,{variables:{requestDataSiloId:n.id,status:m},logger:t})}catch(e){if(!e.message.includes(`Client error: Request must be active:`)&&!e.message.includes(`Failed to find RequestDataSilo`))throw e}y+=1,v.update(y)},{concurrency:p}),v.stop();let b=new Date().getTime()-_;return t.info(r.green(`Successfully notified Transcend in "${b/1e3}" seconds!`)),u.length}export{u as t};
|
|
2
|
+
//# sourceMappingURL=markRequestDataSiloIdsCompleted-63FCcKgi.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markRequestDataSiloIdsCompleted-
|
|
1
|
+
{"version":3,"file":"markRequestDataSiloIdsCompleted-63FCcKgi.mjs","names":[],"sources":["../src/lib/cron/markRequestDataSiloIdsCompleted.ts"],"sourcesContent":["import { RequestDataSiloStatus } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n makeGraphQLRequest,\n CHANGE_REQUEST_DATA_SILO_STATUS,\n fetchRequestDataSilo,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Given a CSV of Request IDs, mark associated RequestDataSilos as completed\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function markRequestDataSiloIdsCompleted({\n requestIds,\n dataSiloId,\n auth,\n concurrency = 100,\n status = RequestDataSiloStatus.Resolved,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The list of request ids to mark as completed */\n requestIds: string[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to update requests to */\n status?: RequestDataSiloStatus;\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying Transcend for data silo \"${dataSiloId}\" marking \"${requestIds.length}\" requests as completed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(requestIds.length, 0);\n await map(\n requestIds,\n async (requestId) => {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n logger,\n filterBy: { requestId, dataSiloId },\n });\n\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, CHANGE_REQUEST_DATA_SILO_STATUS, {\n variables: {\n requestDataSiloId: requestDataSilo.id,\n status,\n },\n logger,\n });\n } catch (err) {\n if (\n !err.message.includes('Client error: Request must be active:') &&\n !err.message.includes('Failed to find RequestDataSilo')\n ) {\n throw err;\n }\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(colors.green(`Successfully notified Transcend in \"${totalTime / 1000}\" seconds!`));\n return requestIds.length;\n}\n"],"mappings":"yYAoBA,eAAsB,EAAgC,CACpD,aACA,aACA,OACA,cAAc,IACd,SAAS,EAAsB,SAC/B,eAAe,GAcG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAGrF,EAAO,KACL,EAAO,QACL,sCAAsC,EAAW,aAAa,EAAW,OAAO,0BACjF,CACF,CAED,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAW,OAAQ,EAAE,CACvC,MAAM,EACJ,EACA,KAAO,IAAc,CACnB,IAAM,EAAkB,MAAM,EAAqB,EAAQ,CACzD,SACA,SAAU,CAAE,YAAW,aAAY,CACpC,CAAC,CAEF,GAAI,CACF,MAAM,EAGH,EAAQ,EAAiC,CAC1C,UAAW,CACT,kBAAmB,EAAgB,GACnC,SACD,CACD,SACD,CAAC,OACK,EAAK,CACZ,GACE,CAAC,EAAI,QAAQ,SAAS,wCAAwC,EAC9D,CAAC,EAAI,QAAQ,SAAS,iCAAiC,CAEvD,MAAM,EAIV,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAGvB,OADA,EAAO,KAAK,EAAO,MAAM,uCAAuC,EAAY,IAAK,YAAY,CAAC,CACvF,EAAW"}
|
package/dist/{markSilentPrivacyRequests-BtZHHUVJ.mjs → markSilentPrivacyRequests--bQ3UAKC.mjs}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=markSilentPrivacyRequests
|
|
1
|
+
import{a as e}from"./constants-CXMjsQ0a.mjs";import{t}from"./logger-CPu6zbyQ.mjs";import{o as n}from"./request-BpKyN9Xm.mjs";import{r}from"./fetchAllRequests-BI0tFl_a.mjs";import{RequestStatus as i}from"@transcend-io/privacy-types";import a from"colors";import{map as o}from"@transcend-io/utils";import{buildTranscendGraphQLClient as s,makeGraphQLRequest as c}from"@transcend-io/sdk";import l from"cli-progress";async function u({requestActions:u,auth:d,requestIds:f,statuses:p=[i.Compiling,i.RequestMade,i.Delayed,i.Approving,i.Secondary,i.Enriching,i.Waiting,i.SecondaryApproving],createdAtAfter:m,createdAtBefore:h,updatedAtBefore:g,updatedAtAfter:_,concurrency:v=100,transcendUrl:y=e}){let b=s(y,d),x=new Date().getTime(),S=new l.SingleBar({},l.Presets.shades_classic),C=await r(b,{actions:u,statuses:p,createdAtBefore:h,createdAtAfter:m,updatedAtBefore:g,updatedAtAfter:_,isSilent:!1,requestIds:f});t.info(a.magenta(`Marking "${C.length}" as silent mode.`));let w=0;S.start(C.length,0),await o(C,async e=>{await c(b,n,{variables:{input:{id:e.id,isSilent:!0}},logger:t}),w+=1,S.update(w)},{concurrency:v}),S.stop();let T=new Date().getTime()-x;return t.info(a.green(`Successfully marked ${w} requests as silent mode in "${T/1e3}" seconds!`)),C.length}export{u as t};
|
|
2
|
+
//# sourceMappingURL=markSilentPrivacyRequests--bQ3UAKC.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markSilentPrivacyRequests
|
|
1
|
+
{"version":3,"file":"markSilentPrivacyRequests--bQ3UAKC.mjs","names":[],"sources":["../src/lib/requests/markSilentPrivacyRequests.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { UPDATE_PRIVACY_REQUEST, fetchAllRequests } from '../graphql/index.js';\n\n/**\n * Mark a set of privacy requests to be in silent mode\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function markSilentPrivacyRequests({\n requestActions,\n auth,\n requestIds,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n createdAtAfter,\n createdAtBefore,\n updatedAtBefore,\n updatedAtAfter,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to mark silent */\n statuses?: RequestStatus[];\n /** The set of privacy requests to mark silent */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isSilent: false,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(colors.magenta(`Marking \"${allRequests.length}\" as silent mode.`));\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToMarkSilent) => {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n variables: {\n input: {\n id: requestToMarkSilent.id,\n isSilent: true,\n },\n },\n logger,\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"4ZAgBA,eAAsB,EAA0B,CAC9C,iBACA,OACA,aACA,WAAW,CACT,EAAc,UACd,EAAc,YACd,EAAc,QACd,EAAc,UACd,EAAc,UACd,EAAc,UACd,EAAc,QACd,EAAc,mBACf,CACD,iBACA,kBACA,kBACA,iBACA,cAAc,IACd,eAAe,GAsBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAG/E,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,WACA,kBACA,iBACA,kBACA,iBACA,SAAU,GACV,aACD,CAAC,CAGF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAY,OAAO,mBAAmB,CAAC,CAE9E,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAwB,CAC7B,MAAM,EAAmB,EAAQ,EAAwB,CACvD,UAAW,CACT,MAAO,CACL,GAAI,EAAoB,GACxB,SAAU,GACX,CACF,CACD,SACD,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAOvB,OALA,EAAO,KACL,EAAO,MACL,uBAAuB,EAAM,+BAA+B,EAAY,IAAK,YAC9E,CACF,CACM,EAAY"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=notifyPrivacyRequestsAdditionalTime-
|
|
1
|
+
import{a as e}from"./constants-CXMjsQ0a.mjs";import{t}from"./logger-CPu6zbyQ.mjs";import{r as n}from"./request-BpKyN9Xm.mjs";import{r}from"./fetchAllRequests-BI0tFl_a.mjs";import{RequestAction as i}from"@transcend-io/privacy-types";import a from"colors";import{map as o}from"@transcend-io/utils";import{buildTranscendGraphQLClient as s,fetchAllTemplates as c,makeGraphQLRequest as l}from"@transcend-io/sdk";import u from"cli-progress";async function d({requestActions:d=Object.values(i),auth:f,requestIds:p,createdAtBefore:m,days:h=45,daysLeft:g=10,createdAtAfter:_,updatedAtBefore:v,updatedAtAfter:y,emailTemplate:b=`Additional Time Needed`,concurrency:x=100,transcendUrl:S=e}){let C=s(S,f),w=new Date().getTime(),T=new u.SingleBar({},u.Presets.shades_classic),E=(await c(C,{logger:t,filterBy:{title:b}})).find(e=>e.title===b);if(!E)throw Error(`Failed to find a template with title: "${b}"`);let D=await r(C,{actions:d,createdAtBefore:m,createdAtAfter:_,updatedAtBefore:v,updatedAtAfter:y,isSilent:!1,isClosed:!1,requestIds:p});D=D.filter(e=>typeof e.daysRemaining==`number`&&e.daysRemaining<g),t.info(a.magenta(`Notifying "${D.length}" that more time is needed.`));let O=0;T.start(D.length,0),await o(D,async e=>{await l(C,n,{variables:{input:{requestId:e.id,template:E.template.defaultMessage,subject:E.subject.defaultMessage,additionalTime:h}},logger:t}),O+=1,T.update(O)},{concurrency:x}),T.stop();let k=new Date().getTime()-w;return t.info(a.green(`Successfully marked ${O} requests as silent mode in "${k/1e3}" seconds!`)),D.length}export{d as t};
|
|
2
|
+
//# sourceMappingURL=notifyPrivacyRequestsAdditionalTime-DQ9_6DaJ.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifyPrivacyRequestsAdditionalTime-
|
|
1
|
+
{"version":3,"file":"notifyPrivacyRequestsAdditionalTime-DQ9_6DaJ.mjs","names":[],"sources":["../src/lib/requests/notifyPrivacyRequestsAdditionalTime.ts"],"sourcesContent":["import { RequestAction } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n fetchAllTemplates,\n makeGraphQLRequest,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { NOTIFY_ADDITIONAL_TIME, fetchAllRequests } from '../graphql/index.js';\n\n/**\n * Mark a set of privacy requests to be in silent mode.\n * Note requests in silent mode are ignored\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function notifyPrivacyRequestsAdditionalTime({\n requestActions = Object.values(RequestAction),\n auth,\n requestIds,\n createdAtBefore,\n days = 45,\n daysLeft = 10,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n emailTemplate = 'Additional Time Needed',\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions?: RequestAction[];\n /** Filter for requests created before this date */\n createdAtBefore: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** Email template */\n emailTemplate?: string;\n /** Transcend API key authentication */\n auth: string;\n /** Number of days to extend request by */\n days?: number;\n /**\n * Only notify requests that have less than this number of days until they are considered expired.\n * This allows for re-running the command without notifying the same users multiple times\n */\n daysLeft?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The set of privacy requests to notify */\n requestIds?: string[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Grab the template with that title\n const matchingTemplates = await fetchAllTemplates(client, {\n logger,\n filterBy: { title: emailTemplate },\n });\n const exactTemplateMatch = matchingTemplates.find((template) => template.title === emailTemplate);\n if (!exactTemplateMatch) {\n throw new Error(`Failed to find a template with title: \"${emailTemplate}\"`);\n }\n\n // Pull in the requests\n let allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isSilent: false,\n isClosed: false,\n requestIds,\n });\n\n // Filter requests by daysLeft\n allRequests = allRequests.filter(\n (request) => typeof request.daysRemaining === 'number' && request.daysRemaining < daysLeft,\n );\n\n // Notify Transcend\n logger.info(colors.magenta(`Notifying \"${allRequests.length}\" that more time is needed.`));\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToNotify) => {\n await makeGraphQLRequest(client, NOTIFY_ADDITIONAL_TIME, {\n variables: {\n input: {\n requestId: requestToNotify.id,\n template: exactTemplateMatch.template.defaultMessage,\n subject: exactTemplateMatch.subject.defaultMessage,\n additionalTime: days,\n },\n },\n logger,\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"mbAqBA,eAAsB,EAAoC,CACxD,iBAAiB,OAAO,OAAO,EAAc,CAC7C,OACA,aACA,kBACA,OAAO,GACP,WAAW,GACX,iBACA,kBACA,iBACA,gBAAgB,yBAChB,cAAc,IACd,eAAe,GA6BG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAO/E,GAAqB,MAJK,EAAkB,EAAQ,CACxD,SACA,SAAU,CAAE,MAAO,EAAe,CACnC,CAAC,EAC2C,KAAM,GAAa,EAAS,QAAU,EAAc,CACjG,GAAI,CAAC,EACH,MAAU,MAAM,0CAA0C,EAAc,GAAG,CAI7E,IAAI,EAAc,MAAM,EAAiB,EAAQ,CAC/C,QAAS,EACT,kBACA,iBACA,kBACA,iBACA,SAAU,GACV,SAAU,GACV,aACD,CAAC,CAGF,EAAc,EAAY,OACvB,GAAY,OAAO,EAAQ,eAAkB,UAAY,EAAQ,cAAgB,EACnF,CAGD,EAAO,KAAK,EAAO,QAAQ,cAAc,EAAY,OAAO,6BAA6B,CAAC,CAE1F,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAoB,CACzB,MAAM,EAAmB,EAAQ,EAAwB,CACvD,UAAW,CACT,MAAO,CACL,UAAW,EAAgB,GAC3B,SAAU,EAAmB,SAAS,eACtC,QAAS,EAAmB,QAAQ,eACpC,eAAgB,EACjB,CACF,CACD,SACD,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAOvB,OALA,EAAO,KACL,EAAO,MACL,uBAAuB,EAAM,+BAA+B,EAAY,IAAK,YAC9E,CACF,CACM,EAAY"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{c as e,l as t,m as n}from"./policy-project-discovery-
|
|
1
|
+
import{c as e,l as t,m as n}from"./policy-project-discovery-BR9EiTHd.mjs";const r=/^\s*package\s+/mu;function i(e,t){let n=/^[A-Za-z_][A-Za-z0-9_]*/u.exec(e.slice(t));return n?{identifier:n[0],end:t+n[0].length}:void 0}function a(e,t){let n=t;for(;n<e.length&&/\s/u.test(e[n]);)n+=1;return n}function o(e,t){if(e[t]==="`"){let n=e.indexOf("`",t+1);return n===-1?void 0:{value:e.slice(t+1,n),end:n+1}}if(e[t]!==`"`)return;let n=t+1;for(;n<e.length;){if(e[n]===`\\`){n+=2;continue}if(e[n]===`"`){let r=e.slice(t,n+1);try{return{value:JSON.parse(r),end:n+1}}catch{return}}n+=1}}function s(e,t){let n=i(e,t);if(!n)return;let r=[n.identifier],s=n.end;for(;s<e.length;){let t=a(e,s);if(e[t]===`.`){let n=i(e,a(e,t+1));if(!n)break;r.push(n.identifier),s=n.end;continue}if(e[t]===`[`){let n=o(e,a(e,t+1));if(!n)break;let i=a(e,n.end);if(e[i]!==`]`)break;r.push(n.value),s=i+1;continue}break}return{source:e.slice(t,s),segments:r,end:s}}function c(e){let t=r.exec(e);if(!t)return;let n=s(e,t.index+t[0].length);return n?{source:n.source,segments:n.segments}:void 0}function l(e,t){let n=e[t],r=t+1;for(;r<e.length;){if(n===`"`&&e[r]===`\\`){r+=2;continue}if(e[r]===n)return r+1;r+=1}return r}function u(e){let t=[],n=0;for(;n<e.length;){if(e[n]===`#`){let t=e.indexOf(`
|
|
2
2
|
`,n);n=t===-1?e.length:t+1;continue}if(e[n]===`"`||e[n]==="`"){n=l(e,n);continue}let r=i(e,n);if(!r){n+=1;continue}if(r.identifier!==`data`){n=r.end;continue}let a=s(e,n);if(!a||a.segments.length===1){n=r.end;continue}let o=e.lastIndexOf(`
|
|
3
3
|
`,n-1)+1;/^\s*import\s+$/u.test(e.slice(o,n))||t.push({reference:a,line:e.slice(0,n).split(`
|
|
4
4
|
`).length}),n=a.end}return t}function d(e){return e.endsWith(`.rego`)&&!e.endsWith(`_test.rego`)}function f(t){if(t===void 0)throw Error(`Policy bundle directory must contain a ${e} file.`);let n;try{n=JSON.parse(t)}catch(t){throw Error(`${e} is not valid JSON: ${t instanceof Error?t.message:String(t)}`,{cause:t})}if(!n||typeof n!=`object`||Array.isArray(n))throw Error(`${e} must contain a JSON object.`);let r=n.roots;if(!Array.isArray(r)||r.length===0)throw Error(`${e} must declare "roots" as a non-empty array of strings (e.g. {"roots":["policy_engine"]}).`);if(!r.every(e=>typeof e==`string`&&e.length>0))throw Error(`${e} "roots" must be an array of non-empty strings.`);if(!r.every(e=>e.split(`/`).every(e=>/^[A-Za-z_][A-Za-z0-9_]*$/u.test(e))))throw Error(`${e} "roots" must contain slash-separated Rego identifiers so Policy Engine can re-namespace them safely.`);let i=p(n);return i===void 0?{roots:r}:{roots:r,template:i}}function p(e){let r=e.metadata;if(!r||typeof r!=`object`||Array.isArray(r))return;let i=r[t];if(!i||typeof i!=`object`||Array.isArray(i))return;let a=i.template;if(typeof a==`string`)return n.includes(a)?a:void 0}function m(e,t){return e.length>=t.length&&t.every((t,n)=>t===e[n])}function h(e,t){let n=t.join(`.`),r=e.source.slice(n.length);return e.source.startsWith(n)&&(r===``||r.startsWith(`.`)||/^\s*\[/u.test(r))}function g(e,t){return m(e.slice(1),t)}function _(t,n){let r=f(t),i=r.roots.join(`, `),a=n.filter(({path:e})=>d(e)).slice().sort((e,t)=>e.path.localeCompare(t.path));if(a.length===0)throw Error(`Policy bundle directory must contain at least one .rego policy file.`);let o=r.roots.map(e=>e.split(`/`)),s=a.flatMap(({path:e,contents:t})=>{let n=c(t);return!n||o.some(e=>h(n,e))?[]:[` - ${e} (package ${n.source}) is not covered by roots [${i}]`]});if(s.length>0)throw Error([`${e} "roots" do not cover all Rego packages in the bundle; uncovered packages will fail-closed at decide time. Either broaden "roots" or move the policy under a covered package:`,...s].join(`
|
|
5
5
|
`));let l=a.flatMap(({path:e,contents:t})=>u(t).filter(({reference:e})=>o.some(t=>g(e.segments,t))).map(({reference:t,line:n})=>` - ${e}:${n} references ${t.source}; import that package and use its local name`));if(l.length>0)throw Error([`Publishable Rego must not reference its declared bundle roots directly because Policy Engine re-namespaces package imports during activation:`,...l].join(`
|
|
6
6
|
`));return{manifest:r,publishableRegoPaths:a.map(({path:e})=>e)}}export{_ as n,f as t};
|
|
7
|
-
//# sourceMappingURL=policy-bundle-manifest-
|
|
7
|
+
//# sourceMappingURL=policy-bundle-manifest-C8Oqz895.mjs.map
|