@intentius/chant 0.57.0 → 0.58.0
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/audit/catalog.d.ts +51 -1
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/core.d.ts +20 -1
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts +14 -8
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/lineage.d.ts +10 -0
- package/dist/audit/lineage.d.ts.map +1 -0
- package/dist/audit/prior-art.d.ts +385 -0
- package/dist/audit/prior-art.d.ts.map +1 -0
- package/dist/audit/proof.d.ts +16 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-html.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +8 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +3 -0
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/audit/secrets.d.ts +15 -0
- package/dist/audit/secrets.d.ts.map +1 -1
- package/dist/audit/terraform-state.d.ts +46 -0
- package/dist/audit/terraform-state.d.ts.map +1 -0
- package/dist/build.d.ts +17 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/claimed-fields.d.ts +161 -0
- package/dist/claimed-fields.d.ts.map +1 -0
- package/dist/cli/build-params-cli.d.ts +2 -2
- package/dist/cli/command-group.d.ts +14 -0
- package/dist/cli/command-group.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts +17 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
- package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
- package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
- package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/onboard.d.ts +2 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +82 -16
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -42
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts +28 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts +16 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resources/context.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +26 -9
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
- package/dist/components/auto-release.d.ts +10 -20
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/capability.d.ts +4 -4
- package/dist/components/cli-support.d.ts +20 -21
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +3 -3
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/driver-output.d.ts.map +1 -1
- package/dist/components/driver.d.ts +66 -36
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/manifest-persistence.d.ts +1 -9
- package/dist/components/manifest-persistence.d.ts.map +1 -1
- package/dist/components/run-progress.d.ts +6 -6
- package/dist/components/run-progress.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts +9 -15
- package/dist/components/verbs/run-agent.d.ts.map +1 -1
- package/dist/components/verbs/verify.d.ts +2 -2
- package/dist/deep-observation.d.ts +17 -0
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/discovery/files.d.ts +4 -4
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +33 -0
- package/dist/discovery/param-deps.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
- package/dist/discovery/sandbox/config-wire.d.ts +2 -2
- package/dist/fold/foldable-helpers.d.ts +5 -1
- package/dist/fold/foldable-helpers.d.ts.map +1 -1
- package/dist/fold-provenance.d.ts +236 -0
- package/dist/fold-provenance.d.ts.map +1 -0
- package/dist/graph-ops.d.ts +1 -1
- package/dist/held-elsewhere.d.ts +85 -0
- package/dist/held-elsewhere.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/kubectl-context.d.ts +3 -3
- package/dist/lexicon-config.d.ts +4 -4
- package/dist/lexicon-plugin-helpers.d.ts +1 -1
- package/dist/lexicon.d.ts +104 -14
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/change-set.d.ts +13 -0
- package/dist/lifecycle/change-set.d.ts.map +1 -1
- package/dist/lifecycle/deep-diff.d.ts +133 -6
- package/dist/lifecycle/deep-diff.d.ts.map +1 -1
- package/dist/lifecycle/deep-observe.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +71 -3
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts +2 -2
- package/dist/lifecycle/run-ledger.d.ts +53 -0
- package/dist/lifecycle/run-ledger.d.ts.map +1 -0
- package/dist/lifecycle/symptoms.d.ts +3 -3
- package/dist/lifecycle/symptoms.d.ts.map +1 -1
- package/dist/lint/config.d.ts +81 -2
- package/dist/lint/config.d.ts.map +1 -1
- package/dist/lint/post-synth.d.ts +55 -2
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +1 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.d.ts +16 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
- package/dist/lint/rules/op/support.d.ts +12 -0
- package/dist/lint/rules/op/support.d.ts.map +1 -0
- package/dist/lint/suppressions.d.ts +108 -0
- package/dist/lint/suppressions.d.ts.map +1 -0
- package/dist/live-endpoint.d.ts +1 -1
- package/dist/op/activities/activity-contracts.d.ts +54 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -0
- package/dist/op/activities/apply.d.ts +262 -0
- package/dist/op/activities/apply.d.ts.map +1 -0
- package/dist/op/activities/build.d.ts +13 -0
- package/dist/op/activities/build.d.ts.map +1 -0
- package/dist/op/activities/converge.d.ts +110 -0
- package/dist/op/activities/converge.d.ts.map +1 -0
- package/dist/op/activities/env-teardown.d.ts +76 -0
- package/dist/op/activities/env-teardown.d.ts.map +1 -0
- package/dist/op/activities/guard-validate.d.ts +64 -0
- package/dist/op/activities/guard-validate.d.ts.map +1 -0
- package/dist/op/activities/http-check.d.ts +34 -0
- package/dist/op/activities/http-check.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +31 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
- package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
- package/dist/op/activities/lifecycle.d.ts +42 -0
- package/dist/op/activities/lifecycle.d.ts.map +1 -0
- package/dist/op/activities/pipeline-audit.d.ts +84 -0
- package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
- package/dist/op/activities/policy.d.ts +17 -0
- package/dist/op/activities/policy.d.ts.map +1 -0
- package/dist/op/activities/reconcile.d.ts +89 -0
- package/dist/op/activities/reconcile.d.ts.map +1 -0
- package/dist/op/activities/shell.d.ts +13 -0
- package/dist/op/activities/shell.d.ts.map +1 -0
- package/dist/op/activities/teardown.d.ts +10 -0
- package/dist/op/activities/teardown.d.ts.map +1 -0
- package/dist/op/activities/util.d.ts +7 -0
- package/dist/op/activities/util.d.ts.map +1 -0
- package/dist/op/activities/wait.d.ts +28 -0
- package/dist/op/activities/wait.d.ts.map +1 -0
- package/dist/op/activities/workflow-audit.d.ts +92 -0
- package/dist/op/activities/workflow-audit.d.ts.map +1 -0
- package/dist/op/activity-contract-registry.d.ts +76 -0
- package/dist/op/activity-contract-registry.d.ts.map +1 -0
- package/dist/op/activity-contract.d.ts +25 -18
- package/dist/op/activity-contract.d.ts.map +1 -1
- package/dist/op/activity-failure.d.ts +28 -0
- package/dist/op/activity-failure.d.ts.map +1 -0
- package/dist/op/activity-profiles.d.ts +118 -0
- package/dist/op/activity-profiles.d.ts.map +1 -0
- package/dist/op/activity-registry.d.ts +22 -38
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +3 -14
- package/dist/op/activity-runtime.d.ts.map +1 -1
- package/dist/op/builders.d.ts +84 -29
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/composites/apply-op.d.ts +113 -0
- package/dist/op/composites/apply-op.d.ts.map +1 -0
- package/dist/op/composites/converge-op.d.ts +120 -0
- package/dist/op/composites/converge-op.d.ts.map +1 -0
- package/dist/op/composites/index.d.ts +26 -0
- package/dist/op/composites/index.d.ts.map +1 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
- package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
- package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
- package/dist/op/composites/reconcile-op.d.ts +57 -0
- package/dist/op/composites/reconcile-op.d.ts.map +1 -0
- package/dist/op/composites/watch-op.d.ts +60 -0
- package/dist/op/composites/watch-op.d.ts.map +1 -0
- package/dist/op/composites/workflow-audit-op.d.ts +57 -0
- package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
- package/dist/op/converge-rule.d.ts +12 -10
- package/dist/op/converge-rule.d.ts.map +1 -1
- package/dist/op/cron.d.ts +51 -0
- package/dist/op/cron.d.ts.map +1 -0
- package/dist/op/discover.d.ts +9 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/duration.d.ts +11 -0
- package/dist/op/duration.d.ts.map +1 -0
- package/dist/op/emulator-lifecycle.d.ts.map +1 -1
- package/dist/op/gate.d.ts +90 -0
- package/dist/op/gate.d.ts.map +1 -0
- package/dist/op/generate-pipeline.d.ts +9 -0
- package/dist/op/generate-pipeline.d.ts.map +1 -1
- package/dist/op/index.d.ts +23 -7
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +114 -28
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-output.d.ts +11 -1
- package/dist/op/local-output.d.ts.map +1 -1
- package/dist/op/op-ir.d.ts +184 -0
- package/dist/op/op-ir.d.ts.map +1 -0
- package/dist/op/op-verb-class.d.ts +10 -2
- package/dist/op/op-verb-class.d.ts.map +1 -1
- package/dist/op/operator.d.ts +30 -5
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/receipt-store.d.ts +1 -1
- package/dist/op/receipt-store.d.ts.map +1 -1
- package/dist/op/resource.d.ts +15 -1
- package/dist/op/resource.d.ts.map +1 -1
- package/dist/op/runtime.d.ts +200 -0
- package/dist/op/runtime.d.ts.map +1 -0
- package/dist/op/runtimes/local.d.ts +29 -0
- package/dist/op/runtimes/local.d.ts.map +1 -0
- package/dist/op/step-output-ref.d.ts +15 -13
- package/dist/op/step-output-ref.d.ts.map +1 -1
- package/dist/op/types.d.ts +79 -27
- package/dist/op/types.d.ts.map +1 -1
- package/dist/ownership.d.ts +1 -1
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/serializer-walker.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/audit/catalog.test.ts +79 -3
- package/src/audit/catalog.ts +111 -13
- package/src/audit/core.test.ts +26 -0
- package/src/audit/core.ts +61 -17
- package/src/audit/discover.test.ts +39 -0
- package/src/audit/discover.ts +91 -15
- package/src/audit/lineage.ts +100 -0
- package/src/audit/prior-art.ts +153 -0
- package/src/audit/proof.test.ts +67 -0
- package/src/audit/proof.ts +70 -0
- package/src/audit/report-html.ts +9 -4
- package/src/audit/report-model.ts +16 -2
- package/src/audit/report.test.ts +33 -0
- package/src/audit/report.ts +5 -3
- package/src/audit/rules-doc.test.ts +34 -2
- package/src/audit/rules-doc.ts +82 -9
- package/src/audit/secrets.ts +15 -3
- package/src/audit/terraform-state.test.ts +144 -0
- package/src/audit/terraform-state.ts +131 -0
- package/src/build.ts +31 -1
- package/src/claimed-fields.test.ts +145 -0
- package/src/claimed-fields.ts +208 -0
- package/src/cli/build-params-cli.ts +2 -2
- package/src/cli/command-group.ts +14 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
- package/src/cli/commands/audit.test.ts +189 -11
- package/src/cli/commands/audit.ts +73 -27
- package/src/cli/commands/build.test.ts +292 -9
- package/src/cli/commands/build.ts +156 -24
- package/src/cli/commands/check-lexicon-docs.ts +1 -1
- package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
- package/src/cli/commands/check-lexicon-examples.ts +42 -10
- package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
- package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
- package/src/cli/commands/init-lexicon.test.ts +97 -2
- package/src/cli/commands/init-lexicon.ts +4 -2
- package/src/cli/commands/init.test.ts +35 -1
- package/src/cli/commands/init.ts +14 -3
- package/src/cli/commands/lint.test.ts +48 -0
- package/src/cli/commands/lint.ts +123 -0
- package/src/cli/commands/onboard.test.ts +75 -0
- package/src/cli/commands/onboard.ts +54 -23
- package/src/cli/handlers/build.test.ts +81 -1
- package/src/cli/handlers/build.ts +15 -1
- package/src/cli/handlers/graph.test.ts +3 -3
- package/src/cli/handlers/lifecycle.test.ts +195 -12
- package/src/cli/handlers/lifecycle.ts +123 -6
- package/src/cli/handlers/misc.ts +1 -1
- package/src/cli/handlers/operator.test.ts +183 -11
- package/src/cli/handlers/operator.ts +260 -55
- package/src/cli/handlers/run.test.ts +431 -1287
- package/src/cli/handlers/run.ts +365 -915
- package/src/cli/main.test.ts +23 -15
- package/src/cli/main.ts +88 -33
- package/src/cli/mcp/op-tools.ts +147 -88
- package/src/cli/mcp/resource-handlers.ts +10 -37
- package/src/cli/mcp/resources/context.ts +11 -12
- package/src/cli/mcp/server.test.ts +25 -27
- package/src/cli/mcp/server.ts +2 -2
- package/src/cli/registry.ts +26 -9
- package/src/codegen/docs.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.ts +1 -1
- package/src/components/README.md +3 -2
- package/src/components/auto-release.test.ts +4 -20
- package/src/components/auto-release.ts +17 -42
- package/src/components/capability.ts +4 -4
- package/src/components/cli-support.test.ts +10 -5
- package/src/components/cli-support.ts +52 -44
- package/src/components/component.schema.json +2 -2
- package/src/components/component.ts +3 -3
- package/src/components/driver-output.ts +14 -2
- package/src/components/driver.test.ts +92 -22
- package/src/components/driver.ts +193 -83
- package/src/components/index.ts +1 -6
- package/src/components/manifest-persistence.test.ts +2 -20
- package/src/components/manifest-persistence.ts +4 -24
- package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
- package/src/components/run-progress.ts +6 -6
- package/src/components/verbs/run-agent.ts +11 -17
- package/src/components/verbs/verify.ts +2 -2
- package/src/deep-observation.test.ts +75 -0
- package/src/deep-observation.ts +48 -0
- package/src/discovery/collect.test.ts +3 -3
- package/src/discovery/files.ts +4 -4
- package/src/discovery/fold-import.ts +105 -2
- package/src/discovery/param-deps.test.ts +112 -1
- package/src/discovery/param-deps.ts +193 -0
- package/src/discovery/sandbox/bundle.ts +15 -1
- package/src/discovery/sandbox/config-wire.test.ts +2 -2
- package/src/discovery/sandbox/config-wire.ts +2 -2
- package/src/fold/fold.test.ts +56 -0
- package/src/fold/foldable-helpers.ts +81 -1
- package/src/fold-provenance-exclusion.test.ts +186 -0
- package/src/fold-provenance.test.ts +495 -0
- package/src/fold-provenance.ts +441 -0
- package/src/graph-ops.test.ts +2 -2
- package/src/graph-ops.ts +1 -1
- package/src/held-elsewhere.test.ts +102 -0
- package/src/held-elsewhere.ts +114 -0
- package/src/index.ts +3 -0
- package/src/kubectl-context.ts +3 -3
- package/src/lexicon-config.test.ts +5 -5
- package/src/lexicon-config.ts +4 -4
- package/src/lexicon-plugin-helpers.ts +1 -1
- package/src/lexicon.ts +120 -14
- package/src/lifecycle/change-set.test.ts +49 -0
- package/src/lifecycle/change-set.ts +67 -0
- package/src/lifecycle/converge-ledger.ts +1 -1
- package/src/lifecycle/deep-diff.test.ts +267 -14
- package/src/lifecycle/deep-diff.ts +217 -14
- package/src/lifecycle/deep-observe.test.ts +3 -1
- package/src/lifecycle/deep-observe.ts +16 -6
- package/src/lifecycle/gate-ledger.test.ts +74 -2
- package/src/lifecycle/gate-ledger.ts +143 -36
- package/src/lifecycle/index.ts +1 -0
- package/src/lifecycle/release-ledger.ts +2 -2
- package/src/lifecycle/run-ledger.test.ts +268 -0
- package/src/lifecycle/run-ledger.ts +201 -0
- package/src/lifecycle/symptoms.ts +3 -3
- package/src/lint/config.test.ts +82 -1
- package/src/lint/config.ts +112 -3
- package/src/lint/policy.test.ts +1 -1
- package/src/lint/post-synth.test.ts +31 -0
- package/src/lint/post-synth.ts +54 -1
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
- package/src/lint/rules/comp/comp.test.ts +1 -1
- package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
- package/src/lint/rules/comp/index.ts +3 -3
- package/src/lint/rules/op/index.ts +23 -0
- package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
- package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
- package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
- package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
- package/src/lint/rules/op/support.ts +11 -0
- package/src/lint/suppressions.test.ts +163 -0
- package/src/lint/suppressions.ts +204 -0
- package/src/live-endpoint.ts +1 -1
- package/src/op/activities/activity-contracts.ts +66 -0
- package/src/op/activities/apply.test.ts +567 -0
- package/src/op/activities/apply.ts +662 -0
- package/src/op/activities/build.ts +26 -0
- package/src/op/activities/converge.test.ts +330 -0
- package/src/op/activities/converge.ts +449 -0
- package/src/op/activities/env-teardown.test.ts +187 -0
- package/src/op/activities/env-teardown.ts +171 -0
- package/src/op/activities/guard-validate.test.ts +139 -0
- package/src/op/activities/guard-validate.ts +223 -0
- package/src/op/activities/http-check.test.ts +48 -0
- package/src/op/activities/http-check.ts +55 -0
- package/src/op/activities/index.ts +119 -0
- package/src/op/activities/lexicon-upgrade.test.ts +492 -0
- package/src/op/activities/lexicon-upgrade.ts +673 -0
- package/src/op/activities/lifecycle.ts +85 -0
- package/src/op/activities/pipeline-audit.test.ts +67 -0
- package/src/op/activities/pipeline-audit.ts +201 -0
- package/src/op/activities/policy.test.ts +19 -0
- package/src/op/activities/policy.ts +37 -0
- package/src/op/activities/reconcile.test.ts +81 -0
- package/src/op/activities/reconcile.ts +187 -0
- package/src/op/activities/shell.ts +26 -0
- package/src/op/activities/teardown.ts +22 -0
- package/src/op/activities/util.ts +6 -0
- package/src/op/activities/wait.ts +69 -0
- package/src/op/activities/workflow-audit.test.ts +90 -0
- package/src/op/activities/workflow-audit.ts +203 -0
- package/src/op/activity-contract-registry.test.ts +98 -0
- package/src/op/activity-contract-registry.ts +114 -0
- package/src/op/activity-contract.test.ts +1 -1
- package/src/op/activity-contract.ts +37 -33
- package/src/op/activity-failure.ts +34 -0
- package/src/op/activity-profiles.test.ts +56 -0
- package/src/op/activity-profiles.ts +116 -0
- package/src/op/activity-registry.test.ts +37 -28
- package/src/op/activity-registry.ts +27 -56
- package/src/op/activity-runtime.ts +3 -47
- package/src/op/builders-exports.test.ts +0 -49
- package/src/op/builders-typed.test.ts +164 -0
- package/src/op/builders.ts +123 -39
- package/src/op/composites/apply-op.ts +208 -0
- package/src/op/composites/composites.test.ts +366 -0
- package/src/op/composites/converge-op.test.ts +168 -0
- package/src/op/composites/converge-op.ts +214 -0
- package/src/op/composites/index.ts +26 -0
- package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
- package/src/op/composites/lexicon-upgrade-op.ts +134 -0
- package/src/op/composites/pipeline-audit-op.test.ts +25 -0
- package/src/op/composites/pipeline-audit-op.ts +78 -0
- package/src/op/composites/reconcile-op.test.ts +51 -0
- package/src/op/composites/reconcile-op.ts +107 -0
- package/src/op/composites/watch-op.ts +108 -0
- package/src/op/composites/workflow-audit-op.test.ts +25 -0
- package/src/op/composites/workflow-audit-op.ts +88 -0
- package/src/op/converge-rule.ts +12 -10
- package/src/op/cron.test.ts +128 -0
- package/src/op/cron.ts +149 -0
- package/src/op/discover-root.test.ts +105 -1
- package/src/op/discover.test.ts +6 -2
- package/src/op/discover.ts +84 -16
- package/src/op/duration.ts +21 -0
- package/src/op/effect-step.test.ts +26 -11
- package/src/op/emulator-lifecycle.ts +1 -2
- package/src/op/gate.ts +155 -0
- package/src/op/generate-pipeline.test.ts +65 -3
- package/src/op/generate-pipeline.ts +19 -2
- package/src/op/index.ts +39 -6
- package/src/op/local-executor.test.ts +163 -34
- package/src/op/local-executor.ts +370 -102
- package/src/op/local-output.test.ts +95 -11
- package/src/op/local-output.ts +33 -4
- package/src/op/op-ir.test.ts +281 -0
- package/src/op/op-ir.ts +417 -0
- package/src/op/op-verb-class.ts +19 -5
- package/src/op/op.test.ts +26 -5
- package/src/op/operator.test.ts +175 -6
- package/src/op/operator.ts +63 -16
- package/src/op/receipt-store.ts +1 -1
- package/src/op/resource.ts +20 -2
- package/src/op/runtime.ts +203 -0
- package/src/op/runtimes/local.test.ts +181 -0
- package/src/op/runtimes/local.ts +212 -0
- package/src/op/step-output-ref.ts +15 -13
- package/src/op/types.ts +84 -24
- package/src/ownership.ts +1 -1
- package/src/provenance.test.ts +6 -0
- package/src/provenance.ts +21 -1
- package/src/serializer-walker.test.ts +42 -0
- package/src/serializer-walker.ts +21 -2
- package/dist/cli/handlers/op-progress.d.ts +0 -90
- package/dist/cli/handlers/op-progress.d.ts.map +0 -1
- package/dist/cli/handlers/run-client.d.ts +0 -127
- package/dist/cli/handlers/run-client.d.ts.map +0 -1
- package/dist/cli/handlers/run-report.d.ts +0 -5
- package/dist/cli/handlers/run-report.d.ts.map +0 -1
- package/dist/components/temporal-codegen-loader.d.ts +0 -27
- package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
- package/src/cli/handlers/op-progress.test.ts +0 -268
- package/src/cli/handlers/op-progress.ts +0 -248
- package/src/cli/handlers/run-client.test.ts +0 -82
- package/src/cli/handlers/run-client.ts +0 -219
- package/src/cli/handlers/run-report.test.ts +0 -62
- package/src/cli/handlers/run-report.ts +0 -122
- package/src/components/temporal-codegen-loader.ts +0 -41
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
package/dist/op/types.d.ts
CHANGED
|
@@ -1,30 +1,62 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Op type definitions — the data model for a named, phased
|
|
2
|
+
* Op type definitions — the data model for a named, phased Op.
|
|
3
3
|
*
|
|
4
|
-
* These types are intentionally free of
|
|
5
|
-
* in core without
|
|
4
|
+
* These types are intentionally free of any runtime SDK's imports, so they can
|
|
5
|
+
* live in core without core depending on a runtime.
|
|
6
6
|
*/
|
|
7
7
|
import type { EffectReceiptRef } from "./receipt-store.js";
|
|
8
|
+
import type { ActivityProfileName } from "./activity-profiles.js";
|
|
8
9
|
export interface OpConfig {
|
|
9
|
-
/** Kebab-case identifier.
|
|
10
|
+
/** Kebab-case identifier. Names the Op's output directory (`dist/ops/<name>/`), and is the name `chant run <name>` and another Op's `depends` refer to. */
|
|
10
11
|
name: string;
|
|
11
12
|
/** Human-readable description shown in `chant run list` and deployment reports. */
|
|
12
13
|
overview: string;
|
|
13
|
-
/** Temporal task queue. Defaults to `name`. */
|
|
14
|
-
taskQueue?: string;
|
|
15
|
-
/** Temporal namespace. Defaults to chant.config.ts defaultProfile's namespace. */
|
|
16
|
-
namespace?: string;
|
|
17
14
|
/** Ordered list of execution phases. */
|
|
18
15
|
phases: PhaseDefinition[];
|
|
19
16
|
/** Other Op names that must be complete before this Op can run. */
|
|
20
17
|
depends?: string[];
|
|
21
18
|
/** Compensation phases executed on terminal failure (run in reverse order). */
|
|
22
19
|
onFailure?: PhaseDefinition[];
|
|
23
|
-
/**
|
|
24
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Discovery keys for this Op — free-form `name: value` pairs a reader
|
|
22
|
+
* filters on. `ConvergeOp` sets `Converge: "true"` and `Env`, `WatchOp`
|
|
23
|
+
* sets `Watch`, and `discoverConvergeOps` (`./operator.ts`) reads both;
|
|
24
|
+
* `chant run list` prints whatever is here.
|
|
25
|
+
*
|
|
26
|
+
* These are the discovery half of what `searchAttributes` used to carry
|
|
27
|
+
* (#2118). The other half — a run's own outcome (`Phase`, `Drift`,
|
|
28
|
+
* `Approver`, `RollbackFailed`) — is not a property of the declaration at
|
|
29
|
+
* all and now lands on the run ledger as a fact
|
|
30
|
+
* (`../lifecycle/run-ledger.ts`), written per run rather than declared once.
|
|
31
|
+
*/
|
|
32
|
+
labels?: Record<string, string>;
|
|
33
|
+
/**
|
|
34
|
+
* The cadence this Op runs on, when it has one (#2120). Runtime-neutral
|
|
35
|
+
* data, not a scheduler: the github/gitlab/forgejo lexicons render it as a
|
|
36
|
+
* CI cron ({@link ScheduledOpSpec}), `chant operator` reads it as this Op's
|
|
37
|
+
* tick cadence, a hosting lexicon hands it to its own scheduler, and the
|
|
38
|
+
* local one-shot executor ignores it.
|
|
39
|
+
*/
|
|
40
|
+
schedule?: OpSchedule;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* An Op's cadence (#2120). The cron is validated at `Op()` construction by
|
|
44
|
+
* the permissive 5-/6-field parser in `./cron.ts`, the same one a lexicon's
|
|
45
|
+
* own post-synth cron check imports.
|
|
46
|
+
*/
|
|
47
|
+
export interface OpSchedule {
|
|
48
|
+
/** 5- or 6-field cron expression, read in the running host's local time. */
|
|
49
|
+
cron: string;
|
|
50
|
+
/**
|
|
51
|
+
* What a fire does while the previous run is still going. `"skip"` is the
|
|
52
|
+
* only value — and the default — because that is what a level-triggered
|
|
53
|
+
* tick wants: the next fire re-observes everything anyway, so queueing a
|
|
54
|
+
* backlog buys nothing a single later tick does not.
|
|
55
|
+
*/
|
|
56
|
+
overlap?: "skip";
|
|
25
57
|
}
|
|
26
58
|
export interface PhaseDefinition {
|
|
27
|
-
/** Display name shown in progress output
|
|
59
|
+
/** Display name shown in progress output. */
|
|
28
60
|
name: string;
|
|
29
61
|
/** Ordered steps within the phase. */
|
|
30
62
|
steps: StepDefinition[];
|
|
@@ -56,27 +88,47 @@ export interface ActivityStep {
|
|
|
56
88
|
*/
|
|
57
89
|
args?: Record<string, unknown>;
|
|
58
90
|
/**
|
|
59
|
-
* Key from
|
|
91
|
+
* Key from {@link ACTIVITY_PROFILES} controlling timeout + retry.
|
|
60
92
|
* Default: "fastIdempotent"
|
|
61
93
|
*/
|
|
62
|
-
profile?:
|
|
94
|
+
profile?: ActivityProfileName;
|
|
63
95
|
/**
|
|
64
|
-
* Surface this activity's return value as a
|
|
96
|
+
* Surface this activity's return value as a named run outcome.
|
|
65
97
|
*
|
|
66
|
-
* The
|
|
67
|
-
* `
|
|
68
|
-
*
|
|
69
|
-
*
|
|
98
|
+
* The local executor captures it into the step's record and folds it into
|
|
99
|
+
* the run ledger's `outcomes` (`../lifecycle/run-ledger.ts`); a hosting
|
|
100
|
+
* lexicon's serializer may additionally publish it to whatever index that
|
|
101
|
+
* runtime queries by. Useful for reading back a run by outcome (e.g. `Drift:
|
|
102
|
+
* "true"/"false"` from a lifecycleDiff activity).
|
|
103
|
+
*
|
|
104
|
+
* An array publishes several attributes off the same result in one upsert
|
|
105
|
+
* (#2105): one activity can answer more than one question about a run, and
|
|
106
|
+
* `choudoufuLivePlan`'s drift boolean plus its unowned and adoptable counts
|
|
107
|
+
* are three attributes over a single live read that nothing would be gained
|
|
108
|
+
* by splitting into three steps. A single object is the same thing with one
|
|
109
|
+
* entry, and stays the authored form everywhere one attribute is enough.
|
|
70
110
|
*
|
|
71
111
|
* `from` is a dot-path into the return value (e.g. `"drifted"` for
|
|
72
112
|
* `{ drifted: boolean }`); when omitted, the whole return value is
|
|
73
|
-
*
|
|
113
|
+
* recorded.
|
|
74
114
|
*/
|
|
75
|
-
outcomeAttribute?:
|
|
76
|
-
name: string;
|
|
77
|
-
from?: string;
|
|
78
|
-
};
|
|
115
|
+
outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[];
|
|
79
116
|
}
|
|
117
|
+
/** One named run outcome published off a step's return value. */
|
|
118
|
+
export interface OutcomeAttribute {
|
|
119
|
+
/** The outcome's name, as it appears in the run ledger's `outcomes`. */
|
|
120
|
+
name: string;
|
|
121
|
+
/** Dot-path into the activity's return value; the whole value when omitted. */
|
|
122
|
+
from?: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* {@link ActivityStep.outcomeAttribute} as a list, whichever form it was
|
|
126
|
+
* authored in. `[]` when the step publishes none, so every consumer can
|
|
127
|
+
* iterate without first asking which of the two shapes it is holding.
|
|
128
|
+
*/
|
|
129
|
+
export declare function outcomeAttributesOf(step: {
|
|
130
|
+
outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[];
|
|
131
|
+
}): OutcomeAttribute[];
|
|
80
132
|
/**
|
|
81
133
|
* Read-compare-run-write over an effect receipt (#1834, epic #1703). The
|
|
82
134
|
* runtime reads the live receipt through the receipt store, compares it
|
|
@@ -99,18 +151,18 @@ export interface EffectStep {
|
|
|
99
151
|
expectation?: string;
|
|
100
152
|
/**
|
|
101
153
|
* Steps run when the live receipt does not match, in authored order. A gate
|
|
102
|
-
* authored here
|
|
154
|
+
* authored here is reached only when the effect will fire. Effect steps do not
|
|
103
155
|
* nest.
|
|
104
156
|
*/
|
|
105
157
|
steps: Array<ActivityStep | GateStep>;
|
|
106
|
-
/** Annotation carried into the
|
|
158
|
+
/** Annotation carried into the Op's build output as a comment. */
|
|
107
159
|
description?: string;
|
|
108
160
|
}
|
|
109
161
|
export interface GateStep {
|
|
110
162
|
kind: "gate";
|
|
111
|
-
/**
|
|
163
|
+
/** The gate's name — what `chant approve <op> <gate>` resolves. */
|
|
112
164
|
signalName: string;
|
|
113
|
-
/**
|
|
165
|
+
/** How long a recorded pending gate stays valid, as a duration string. Default: "48h". */
|
|
114
166
|
timeout?: string;
|
|
115
167
|
/** Human-readable description of the action required to unblock this gate. */
|
|
116
168
|
description?: string;
|
package/dist/op/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/op/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/op/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,2JAA2J;IAC3J,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;CAC1D;AAED,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAA;CAAE,GAAG,gBAAgB,EAAE,CAI1H;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,4EAA4E;IAC5E,OAAO,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,EAAE,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC,CAAC;IACtC,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
package/dist/ownership.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface ChannelKeys {
|
|
|
40
40
|
/**
|
|
41
41
|
* The label-based ownership convention (`app.kubernetes.io/managed-by` +
|
|
42
42
|
* `chant.intentius.io/{stack,env}`) — the default, shared by every label-based
|
|
43
|
-
* lexicon (k8s, gcp, helm, and the
|
|
43
|
+
* lexicon (k8s, gcp, helm, and the `k8sApply` activity's `kubectl --prune`
|
|
44
44
|
* selector). AWS and Azure tag keys are defined in their own lexicons.
|
|
45
45
|
*/
|
|
46
46
|
export declare const LABEL_OWNERSHIP_KEYS: ChannelKeys;
|
package/dist/provenance.d.ts
CHANGED
|
@@ -67,6 +67,20 @@ export interface EntityProvenance {
|
|
|
67
67
|
* is governed by `tier`, which is what an editor needs to know. Under-reports
|
|
68
68
|
* (a shape the collector does not follow drops a dependency) and never
|
|
69
69
|
* over-reports a parameter the expression does not mention.
|
|
70
|
+
* - `composite-parameter` — the fold interpreted the composite's factory body,
|
|
71
|
+
* and the expression for this path reads the named factory parameter paths
|
|
72
|
+
* (chant #2161). Same syntactic-dependency discipline as `build-param`, and
|
|
73
|
+
* for the same reason: a shape the collector does not follow drops a
|
|
74
|
+
* parameter, it never invents one.
|
|
75
|
+
* - `composite-literal` — the fold interpreted the factory body and the
|
|
76
|
+
* expression for this path reads no parameter at all. The composite fixes
|
|
77
|
+
* this field, and no argument at the call site moves it.
|
|
78
|
+
*
|
|
79
|
+
* The coarse `composite` and the two fine kinds are not alternatives. A build
|
|
80
|
+
* records `composite` when it expanded a composite without interpreting its
|
|
81
|
+
* body (the run path, an inadmissible factory), and that is why
|
|
82
|
+
* ./fold-provenance.ts answers `unknown` there rather than falling through to a
|
|
83
|
+
* direct declaration.
|
|
70
84
|
*/
|
|
71
85
|
export type PathOrigin = {
|
|
72
86
|
kind: "authored";
|
|
@@ -77,6 +91,13 @@ export type PathOrigin = {
|
|
|
77
91
|
} | {
|
|
78
92
|
kind: "build-param";
|
|
79
93
|
params: string[];
|
|
94
|
+
} | {
|
|
95
|
+
kind: "composite-parameter";
|
|
96
|
+
composite: string;
|
|
97
|
+
parameters: string[];
|
|
98
|
+
} | {
|
|
99
|
+
kind: "composite-literal";
|
|
100
|
+
composite: string;
|
|
80
101
|
};
|
|
81
102
|
/**
|
|
82
103
|
* Merge provenance onto an entity. Non-enumerable so it is invisible to
|
package/dist/provenance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAED
|
|
1
|
+
{"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAWrD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAqB1E;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAExF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,SAAS,CAQxF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,EACvD,IAAI,EAAE,MAAM,GACX,UAAU,GAAG,SAAS,CAQxB;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAa7D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,sCAAsC;IACtC,MAAM,EAAE,KAAK,GAAG,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC;CACnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer-walker.d.ts","sourceRoot":"","sources":["../src/serializer-walker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"serializer-walker.d.ts","sourceRoot":"","sources":["../src/serializer-walker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAO/C,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,mEAAmE;IACnE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1C,+DAA+D;IAC/D,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC;CAChF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAyFT"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "Declarative infrastructure-as-code toolkit — TypeScript on Node.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -59,6 +59,11 @@
|
|
|
59
59
|
"types": "./dist/op/index.d.ts",
|
|
60
60
|
"default": "./src/op/index.ts"
|
|
61
61
|
},
|
|
62
|
+
"./op/activities": {
|
|
63
|
+
"development": "./src/op/activities/index.ts",
|
|
64
|
+
"types": "./dist/op/activities/index.d.ts",
|
|
65
|
+
"default": "./src/op/activities/index.ts"
|
|
66
|
+
},
|
|
62
67
|
"./components": {
|
|
63
68
|
"development": "./src/components/index.ts",
|
|
64
69
|
"types": "./dist/components/index.d.ts",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
2
|
import { readdirSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
|
-
import { RULE_CATALOG, RULE_CATEGORY, auditRule, resolveAuditCatalog } from "./catalog";
|
|
4
|
+
import { PRIOR_ART, RULE_CATALOG, RULE_CATEGORY, auditRule, resolveAuditCatalog, canonicalRuleId } from "./catalog";
|
|
5
5
|
import { loadPlugins } from "../cli/plugins";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Every lexicon in the repo, enumerated rather than listed (#1346).
|
|
9
9
|
*
|
|
10
10
|
* This was nine hardcoded names. It missed fountain, which contributes a
|
|
11
|
-
* catalog, and could not notice fly
|
|
11
|
+
* catalog, and could not notice fly, which did not — so their six
|
|
12
12
|
* post-synth checks reached `chant audit` with no title, tier, fix kind, or
|
|
13
13
|
* category, and the guard meant to catch exactly that was blind to them. A
|
|
14
14
|
* thirteenth lexicon would have been invisible to it on arrival.
|
|
@@ -67,6 +67,11 @@ describe("RULE_CATALOG (aggregated: core static + lexicon-contributed, #687)", (
|
|
|
67
67
|
.filter((id) => !shipped.has(id))
|
|
68
68
|
// Core's own cross-cutting ids are not any one lexicon's to ship.
|
|
69
69
|
.filter((id) => !(id in RULE_CATALOG))
|
|
70
|
+
// A deprecated rule is deliberately kept in the catalog after its check
|
|
71
|
+
// stops shipping (chant #2113). That's the whole point of `deprecated`
|
|
72
|
+
// over deleting the entry, so it's not "stale" the way an orphaned
|
|
73
|
+
// entry with no explanation is.
|
|
74
|
+
.filter((id) => !catalog[id]?.deprecated)
|
|
70
75
|
.sort();
|
|
71
76
|
expect(stale).toEqual([]);
|
|
72
77
|
});
|
|
@@ -123,6 +128,33 @@ describe("RULE_CATALOG (aggregated: core static + lexicon-contributed, #687)", (
|
|
|
123
128
|
}
|
|
124
129
|
});
|
|
125
130
|
|
|
131
|
+
test("lineage entries key into PRIOR_ART, link over https, and use a known relation", async () => {
|
|
132
|
+
const relations = new Set(["equivalent", "overlaps", "extends"]);
|
|
133
|
+
for (const [id, m] of Object.entries(await aggregate())) {
|
|
134
|
+
for (const l of m.lineage ?? []) {
|
|
135
|
+
expect(l.tool in PRIOR_ART, `${id} credits unregistered tool "${l.tool}"`).toBe(true);
|
|
136
|
+
expect(l.url.startsWith("https://"), `${id} lineage url ${l.url}`).toBe(true);
|
|
137
|
+
expect(relations.has(l.relation), `${id} lineage relation ${l.relation}`).toBe(true);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("lineage is credit, not authority: it never forces a category or tier", () => {
|
|
143
|
+
const m = auditRule("ZZZ001", "report-only", "guidance", "t", "r", {
|
|
144
|
+
lineage: [{ tool: Object.keys(PRIOR_ART)[0] as never, url: "https://example.invalid/x", relation: "overlaps" }],
|
|
145
|
+
});
|
|
146
|
+
expect(m.category).toBe("best-practice");
|
|
147
|
+
expect(m.tier).toBe("report-only");
|
|
148
|
+
expect(m.lineage?.length).toBe(1);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("every registered prior-art tool is credited by at least one rule", async () => {
|
|
152
|
+
const used = new Set<string>();
|
|
153
|
+
for (const m of Object.values(await aggregate())) for (const l of m.lineage ?? []) used.add(l.tool);
|
|
154
|
+
const idle = Object.keys(PRIOR_ART).filter((k) => !used.has(k)).sort();
|
|
155
|
+
expect(idle, "PRIOR_ART entries no rule credits").toEqual([]);
|
|
156
|
+
});
|
|
157
|
+
|
|
126
158
|
test("flagship security rules carry an authority citation", async () => {
|
|
127
159
|
const catalog = await aggregate();
|
|
128
160
|
const flagship = ["GHA017", "GHA021", "GHA029", "GHA033", "GHA034", "GHA036", "GHA037", "WGL016", "WGL029"];
|
|
@@ -134,13 +166,34 @@ describe("RULE_CATALOG (aggregated: core static + lexicon-contributed, #687)", (
|
|
|
134
166
|
}
|
|
135
167
|
});
|
|
136
168
|
|
|
169
|
+
test("a deprecated id must still resolve (chant #2113): the inverse of the every-check-has-metadata test above", async () => {
|
|
170
|
+
// A retired check ships no runtime PostSynthCheck any more, so it is
|
|
171
|
+
// absent from `realCheckIds()`/`shippedRuleIds()` — that's what makes it
|
|
172
|
+
// "deprecated" rather than merely renamed. The catalog entry, and its
|
|
173
|
+
// resolution, must survive that removal.
|
|
174
|
+
const catalog = {
|
|
175
|
+
...RULE_CATALOG,
|
|
176
|
+
ZZZ900: auditRule("ZZZ900", "report-only", "guidance", "Retired check", "No longer applicable.", {
|
|
177
|
+
category: "best-practice",
|
|
178
|
+
}),
|
|
179
|
+
};
|
|
180
|
+
catalog.ZZZ900.deprecated = "superseded by ZZZ901";
|
|
181
|
+
expect(catalog.ZZZ900).toBeDefined();
|
|
182
|
+
expect(catalog.ZZZ900.deprecated).toBe("superseded by ZZZ901");
|
|
183
|
+
expect(canonicalRuleId("ZZZ900", catalog)).toBe("ZZZ900");
|
|
184
|
+
});
|
|
185
|
+
|
|
137
186
|
test("deterministic fixes are limited to the safe mechanical set", async () => {
|
|
138
187
|
const deterministic = Object.values(await aggregate())
|
|
139
188
|
.filter((m) => m.fixKind === "deterministic")
|
|
140
189
|
.map((m) => m.id)
|
|
141
190
|
.sort();
|
|
191
|
+
// TF016 and TF019 (#2110) are the first report-only rules in the set: both
|
|
192
|
+
// unquote or delete exactly the flagged line, which is as mechanical as
|
|
193
|
+
// pinning an action, and `report-model.ts` renders them as quick wins for
|
|
194
|
+
// that reason. Every entry here needs a case in `proof.ts`'s `proveFix`.
|
|
142
195
|
expect(deterministic).toEqual(
|
|
143
|
-
["GHA017", "GHA021", "GHA029", "GHA030", "GHA033", "WGL031"].sort(),
|
|
196
|
+
["GHA017", "GHA021", "GHA029", "GHA030", "GHA033", "TF016", "TF019", "WGL031"].sort(),
|
|
144
197
|
);
|
|
145
198
|
});
|
|
146
199
|
});
|
|
@@ -164,6 +217,29 @@ describe("auditRule (lexicon-facing catalog constructor, #687)", () => {
|
|
|
164
217
|
});
|
|
165
218
|
});
|
|
166
219
|
|
|
220
|
+
describe("canonicalRuleId (chant #2113, alias resolution)", () => {
|
|
221
|
+
const catalog: Record<string, ReturnType<typeof auditRule>> = {
|
|
222
|
+
NEW001: { ...auditRule("NEW001", "report-only", "guidance", "T", "r"), aliases: ["OLD001", "LEGACY_OLD"] },
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
test("a canonical id passes through unchanged", () => {
|
|
226
|
+
expect(canonicalRuleId("NEW001", catalog)).toBe("NEW001");
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("an alias resolves to the canonical id", () => {
|
|
230
|
+
expect(canonicalRuleId("OLD001", catalog)).toBe("NEW001");
|
|
231
|
+
expect(canonicalRuleId("LEGACY_OLD", catalog)).toBe("NEW001");
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("an id that is neither a key nor an alias passes through unchanged", () => {
|
|
235
|
+
expect(canonicalRuleId("NOBODY_KNOWS_THIS", catalog)).toBe("NOBODY_KNOWS_THIS");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test("defaults to the static core RULE_CATALOG when no catalog is given", () => {
|
|
239
|
+
expect(canonicalRuleId("SEC001")).toBe("SEC001");
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
167
243
|
describe("resolveAuditCatalog (#687 aggregation seam)", () => {
|
|
168
244
|
test("with no lexicons, returns a copy of the static core catalog", async () => {
|
|
169
245
|
const resolved = await resolveAuditCatalog([]);
|
package/src/audit/catalog.ts
CHANGED
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* test asserts the aggregate stays in sync with the lexicons' post-synth checks.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import type { Lineage } from "./prior-art";
|
|
21
|
+
import { applyLineage as attachLineage } from "./prior-art";
|
|
22
|
+
import { coreAuditLineage } from "./lineage";
|
|
23
|
+
export { PRIOR_ART, applyLineage, lineageLabel, type Lineage, type LineageRelation, type PriorArtEntry, type PriorArtTool } from "./prior-art";
|
|
24
|
+
|
|
20
25
|
export type Tier = "merge-worthy" | "report-only";
|
|
21
26
|
|
|
22
27
|
/** deterministic = safe auto-fix/diff; guidance = report text only (needs judgment). */
|
|
@@ -48,14 +53,42 @@ export interface RuleMeta {
|
|
|
48
53
|
title: string;
|
|
49
54
|
/** External backing so a finding isn't just chant's opinion. */
|
|
50
55
|
authority?: Authority[];
|
|
56
|
+
/**
|
|
57
|
+
* Prior art: the open-source tools whose rules check the same condition
|
|
58
|
+
* (./prior-art.ts). Credit, not authority — never affects tier or category.
|
|
59
|
+
*/
|
|
60
|
+
lineage?: Lineage[];
|
|
51
61
|
/** One-line fix guidance (always present). */
|
|
52
62
|
remediation: string;
|
|
53
63
|
/**
|
|
54
64
|
* False if the check reads the chant model (`ctx.entities`) rather than the
|
|
55
65
|
* emitted YAML (`ctx.outputs`) — such a check won't fire on audited YAML.
|
|
56
|
-
*
|
|
66
|
+
* Most post-synth checks are output-based, but cpln, fly, fountain, k3s
|
|
67
|
+
* and render all ship model-based checks with this false.
|
|
57
68
|
*/
|
|
58
69
|
yamlBased: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Retired ids this rule used to ship under (chant #2113). A rule id is
|
|
72
|
+
* public the day it ships. trivy's checks carry `id`, `long_id` and
|
|
73
|
+
* `aliases` for exactly this reason, so a rename or a scheme migration
|
|
74
|
+
* doesn't strand every existing reference to the old id. An alias resolves
|
|
75
|
+
* to this entry wherever a rule id is looked up by a human or a config.
|
|
76
|
+
* `canonicalRuleId()` (below) is the shared resolver; a `lint.rules` key
|
|
77
|
+
* and #2111's HCL suppression both go through it (or will, since #2111
|
|
78
|
+
* lands separately and is not touched by this change).
|
|
79
|
+
*/
|
|
80
|
+
aliases?: string[];
|
|
81
|
+
/**
|
|
82
|
+
* Set when this rule is retired: `true`, or a string explaining what
|
|
83
|
+
* replaced it / why it no longer fires. A deprecated rule stays in the
|
|
84
|
+
* catalog rather than being deleted. trivy's `deprecated: true` field lets
|
|
85
|
+
* a ruleset retire a check without breaking every existing suppression or
|
|
86
|
+
* dashboard that still names it, so its id keeps resolving (via `aliases`
|
|
87
|
+
* on whichever rule superseded it, when there is one) and the rules page
|
|
88
|
+
* still lists it, greyed out, instead of the id going dark with no
|
|
89
|
+
* explanation.
|
|
90
|
+
*/
|
|
91
|
+
deprecated?: boolean | string;
|
|
59
92
|
}
|
|
60
93
|
|
|
61
94
|
// ── Authority references ─────────────────────────────────────────────
|
|
@@ -147,6 +180,10 @@ export const CWE_HARDCODED_CREDS: Authority = {
|
|
|
147
180
|
name: "CWE-798 — Use of Hard-coded Credentials",
|
|
148
181
|
url: "https://cwe.mitre.org/data/definitions/798.html",
|
|
149
182
|
};
|
|
183
|
+
export const HASHICORP_STYLE_GITIGNORE: Authority = {
|
|
184
|
+
name: "HashiCorp Terraform style guide — .gitignore",
|
|
185
|
+
url: "https://developer.hashicorp.com/terraform/language/style#gitignore",
|
|
186
|
+
};
|
|
150
187
|
export const CWE_CLEARTEXT: Authority = {
|
|
151
188
|
name: "CWE-319 — Cleartext Transmission of Sensitive Information",
|
|
152
189
|
url: "https://cwe.mitre.org/data/definitions/319.html",
|
|
@@ -159,13 +196,14 @@ function meta(
|
|
|
159
196
|
title: string,
|
|
160
197
|
remediation: string,
|
|
161
198
|
authority?: Authority[],
|
|
199
|
+
lineage?: Lineage[],
|
|
162
200
|
): RuleMeta {
|
|
163
201
|
// An authority citation is the strongest security signal, so it wins. Otherwise
|
|
164
202
|
// the curated RULE_CATEGORY map (defined below, before RULE_CATALOG runs)
|
|
165
203
|
// decides correctness vs best-practice vs security-without-authority; the drift
|
|
166
204
|
// test guarantees every id is mapped, so the fallback is only a type belt.
|
|
167
205
|
const category: Category = authority && authority.length > 0 ? "security" : RULE_CATEGORY[id] ?? "best-practice";
|
|
168
|
-
return { id, tier, fixKind, category, title, remediation, authority, yamlBased: true };
|
|
206
|
+
return { id, tier, fixKind, category, title, remediation, authority, ...(lineage?.length ? { lineage } : {}), yamlBased: true };
|
|
169
207
|
}
|
|
170
208
|
|
|
171
209
|
const M = "merge-worthy" as const;
|
|
@@ -221,6 +259,10 @@ export const RULE_CATEGORY: Record<string, Category> = {
|
|
|
221
259
|
NGX005: "security",
|
|
222
260
|
NGX006: "best-practice",
|
|
223
261
|
NGX007: "best-practice",
|
|
262
|
+
// TF023 — Terraform state committed to the repository. Core-owned for the
|
|
263
|
+
// same reason SEC/WRG/NGX are: it reads the discovered file list, not a
|
|
264
|
+
// parsed root module. See ./terraform-state.ts.
|
|
265
|
+
TF023: "security",
|
|
224
266
|
// AGT — agent configuration (`chant audit --agents`). Core-owned like COR/EXT:
|
|
225
267
|
// these run against the machine's own agent config, not against any one
|
|
226
268
|
// lexicon's emitted output, so no lexicon ships them.
|
|
@@ -282,6 +324,21 @@ export const RULE_CATALOG: Record<string, RuleMeta> = {
|
|
|
282
324
|
NGX006: meta("NGX006", R, G, "Server version disclosure", "Add `server_tokens off;` in the http block so nginx stops advertising its exact version in the Server header and error pages."),
|
|
283
325
|
NGX007: meta("NGX007", R, G, "Access logging disabled at server scope", "Re-enable access_log at http/server scope (silencing a single noisy location is fine) so requests are recorded for incident investigation."),
|
|
284
326
|
|
|
327
|
+
// TF023 (#2110) — Terraform state, or the `.terraform/` working directory,
|
|
328
|
+
// committed to the repository. The one TF rule core owns: every other TF id
|
|
329
|
+
// is a post-synth check over a parsed root module (the terraform lexicon's
|
|
330
|
+
// `auditCatalog()`), while this one reads the discovered file list and never
|
|
331
|
+
// runs during `chant build`. Same shape as SEC/WRG/NGX above, and the same
|
|
332
|
+
// reason it lives here: `terraform-state.ts` needs no lexicon installed.
|
|
333
|
+
TF023: meta(
|
|
334
|
+
"TF023",
|
|
335
|
+
M,
|
|
336
|
+
G,
|
|
337
|
+
"Terraform state committed to the repository",
|
|
338
|
+
"Delete the state file (or `.terraform/`) from version control, add it to .gitignore, move the state to a remote backend, and rotate every credential the file held.",
|
|
339
|
+
[HASHICORP_STYLE_GITIGNORE],
|
|
340
|
+
),
|
|
341
|
+
|
|
285
342
|
// ── Agent configuration (`chant audit --agents`) ──────────────────
|
|
286
343
|
AGT001: agentMeta(
|
|
287
344
|
"AGT001",
|
|
@@ -337,6 +394,9 @@ export const RULE_CATALOG: Record<string, RuleMeta> = {
|
|
|
337
394
|
),
|
|
338
395
|
};
|
|
339
396
|
|
|
397
|
+
// Prior art credits for the core static rules (SEC/WRG/NGX/AGT/EXT) — ./lineage.ts.
|
|
398
|
+
attachLineage(RULE_CATALOG, coreAuditLineage);
|
|
399
|
+
|
|
340
400
|
/**
|
|
341
401
|
* Build one catalog entry — the lexicon-facing constructor for
|
|
342
402
|
* `LexiconPlugin.auditCatalog()` (#687), so a lexicon can declare its own rules'
|
|
@@ -351,10 +411,20 @@ export function auditRule(
|
|
|
351
411
|
fixKind: FixKind,
|
|
352
412
|
title: string,
|
|
353
413
|
remediation: string,
|
|
354
|
-
opts?: { authority?: Authority[]; category?: Category },
|
|
414
|
+
opts?: { authority?: Authority[]; category?: Category; lineage?: Lineage[] },
|
|
355
415
|
): RuleMeta {
|
|
356
416
|
const category: Category = opts?.authority && opts.authority.length > 0 ? "security" : (opts?.category ?? "best-practice");
|
|
357
|
-
return {
|
|
417
|
+
return {
|
|
418
|
+
id,
|
|
419
|
+
tier,
|
|
420
|
+
fixKind,
|
|
421
|
+
category,
|
|
422
|
+
title,
|
|
423
|
+
remediation,
|
|
424
|
+
authority: opts?.authority,
|
|
425
|
+
...(opts?.lineage?.length ? { lineage: opts.lineage } : {}),
|
|
426
|
+
yamlBased: true,
|
|
427
|
+
};
|
|
358
428
|
}
|
|
359
429
|
|
|
360
430
|
/**
|
|
@@ -374,15 +444,18 @@ export async function resolveAuditCatalog(lexicons: string[]): Promise<Record<st
|
|
|
374
444
|
lexicons.includes("forgejo") && !lexicons.includes("github") ? [...lexicons, "github"] : lexicons;
|
|
375
445
|
if (needed.length === 0) return catalog;
|
|
376
446
|
// Lazy import so importing this module doesn't pull in the plugin/config graph
|
|
377
|
-
// (matches ./core.ts's `load` — see #408).
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
447
|
+
// (matches ./core.ts's `load` — see #408). Loaded one at a time (rather than
|
|
448
|
+
// the bulk `loadPlugins`, which aborts on the first failure) so one
|
|
449
|
+
// not-yet-installed lexicon (e.g. terraform, #2085) doesn't drop every other
|
|
450
|
+
// lexicon's contributed catalog back to the static core map.
|
|
451
|
+
const { loadPlugin } = await import("../cli/plugins");
|
|
452
|
+
for (const name of needed) {
|
|
453
|
+
let plugin: { auditCatalog?(): Record<string, RuleMeta> };
|
|
454
|
+
try {
|
|
455
|
+
plugin = await loadPlugin(name);
|
|
456
|
+
} catch {
|
|
457
|
+
continue; // a lexicon package isn't installed, its catalog just doesn't contribute.
|
|
458
|
+
}
|
|
386
459
|
const contributed = plugin?.auditCatalog?.();
|
|
387
460
|
if (contributed) Object.assign(catalog, contributed);
|
|
388
461
|
}
|
|
@@ -394,6 +467,31 @@ export function ruleMeta(id: string): RuleMeta | undefined {
|
|
|
394
467
|
return RULE_CATALOG[id];
|
|
395
468
|
}
|
|
396
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Resolve a rule id to its canonical form against `catalog` (chant #2113). An
|
|
472
|
+
* id that is itself a key of `catalog` passes through unchanged (this covers
|
|
473
|
+
* the common case without scanning every entry's `aliases`); otherwise every
|
|
474
|
+
* entry's `aliases` is searched for a match, and the id it belongs to is
|
|
475
|
+
* returned. An id neither a key nor anyone's alias passes through unchanged
|
|
476
|
+
* too, since this is a best-effort resolver, not a validator, so an unknown
|
|
477
|
+
* id is a caller's problem, not this function's.
|
|
478
|
+
*
|
|
479
|
+
* Exported so a `lint.rules`/preset key that names an alias resolves to the
|
|
480
|
+
* rule that actually runs (see `resolveConfiguredSeverity`,
|
|
481
|
+
* `../lint/config.ts`), and so #2111's HCL suppression code can key an
|
|
482
|
+
* inline `# chant-ignore <id>` off the same resolution once it lands — that
|
|
483
|
+
* suppression mechanism does not exist yet in this worktree (#2111 is a
|
|
484
|
+
* separate, parallel issue), so this function is exported now for it to call
|
|
485
|
+
* later rather than being wired into it here.
|
|
486
|
+
*/
|
|
487
|
+
export function canonicalRuleId(id: string, catalog: Record<string, RuleMeta> = RULE_CATALOG): string {
|
|
488
|
+
if (id in catalog) return id;
|
|
489
|
+
for (const [canonicalId, meta] of Object.entries(catalog)) {
|
|
490
|
+
if (meta.aliases?.includes(id)) return canonicalId;
|
|
491
|
+
}
|
|
492
|
+
return id;
|
|
493
|
+
}
|
|
494
|
+
|
|
397
495
|
/** Docs path for the audit rules reference (one anchor per rule id). */
|
|
398
496
|
export const RULES_DOC_PATH = "/chant/lint-rules/audit-rules/";
|
|
399
497
|
|
package/src/audit/core.test.ts
CHANGED
|
@@ -208,6 +208,32 @@ describe("auditFiles", () => {
|
|
|
208
208
|
expect(findings.map((f) => `${f.file}:${f.entity}`).sort()).toEqual(["a.yaml:one", "b.yaml:two"]);
|
|
209
209
|
});
|
|
210
210
|
|
|
211
|
+
test("parse-to-graph with an async entities parser: auditFiles awaits it into ctx.entities (#2082)", async () => {
|
|
212
|
+
const entityCheck: PostSynthCheck = {
|
|
213
|
+
id: "ENT003",
|
|
214
|
+
description: "reads ctx.entities, not ctx.outputs",
|
|
215
|
+
check: (ctx) =>
|
|
216
|
+
[...ctx.entities.keys()].map((name) => ({ checkId: "ENT003", severity: "warning" as const, message: `saw ${name}`, entity: name })),
|
|
217
|
+
};
|
|
218
|
+
const findings = await auditFiles(
|
|
219
|
+
[
|
|
220
|
+
{ path: "a.tf", content: "one", lexicon: "terraform" },
|
|
221
|
+
{ path: "b.tf", content: "two", lexicon: "terraform" },
|
|
222
|
+
],
|
|
223
|
+
{
|
|
224
|
+
checksProvider: async () => [entityCheck],
|
|
225
|
+
// The lexicon's parser is inherently async (a lazy-loaded wasm HCL
|
|
226
|
+
// parser, per #1567's terraform follow-up). The returned Promise
|
|
227
|
+
// must be awaited before the check sees ctx.entities.
|
|
228
|
+
entitiesProvider: async () => async (content) => {
|
|
229
|
+
await Promise.resolve();
|
|
230
|
+
return new Map([[content, { entityType: "T::X" } as never]]);
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
);
|
|
234
|
+
expect(findings.map((f) => `${f.file}:${f.entity}`).sort()).toEqual(["a.tf:one", "b.tf:two"]);
|
|
235
|
+
});
|
|
236
|
+
|
|
211
237
|
test("parse-to-graph merge: the same entity name in two files keeps both — a duplicate check sees the collision cross-file", async () => {
|
|
212
238
|
const dupCheck: PostSynthCheck = {
|
|
213
239
|
id: "DUP001",
|