@intentius/chant 0.124.52 → 0.124.54
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/discover.d.ts.map +1 -1
- package/dist/audit/discover.js +3 -1
- package/dist/behaviour.d.ts +1 -1
- package/dist/behaviour.d.ts.map +1 -1
- package/dist/capabilities/templates.d.ts +65 -0
- package/dist/capabilities/templates.d.ts.map +1 -0
- package/dist/capabilities/templates.js +193 -0
- package/dist/capabilities/templates.json +145 -0
- package/dist/change-set-graph.d.ts +35 -3
- package/dist/change-set-graph.d.ts.map +1 -1
- package/dist/change-set-graph.js +60 -9
- package/dist/change-set.d.ts +65 -7
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +23 -12
- package/dist/ci-identity.d.ts +7 -2
- package/dist/ci-identity.d.ts.map +1 -1
- package/dist/ci-identity.js +4 -1
- package/dist/cli/commands/import-index.d.ts +52 -0
- package/dist/cli/commands/import-index.d.ts.map +1 -0
- package/dist/cli/commands/import-index.js +226 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +4 -2
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/components.js +11 -2
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +16 -3
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +22 -4
- package/dist/cli/handlers/index-cloud.d.ts +14 -0
- package/dist/cli/handlers/index-cloud.d.ts.map +1 -0
- package/dist/cli/handlers/index-cloud.js +22 -0
- package/dist/cli/handlers/index-diff.d.ts +18 -0
- package/dist/cli/handlers/index-diff.d.ts.map +1 -0
- package/dist/cli/handlers/index-diff.js +142 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts +25 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-drift.js +64 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.js +188 -28
- package/dist/cli/handlers/misc.d.ts +9 -0
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +77 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +15 -2
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +89 -15
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +28 -4
- package/dist/cli/handlers/scenario.d.ts.map +1 -1
- package/dist/cli/handlers/scenario.js +8 -7
- package/dist/cli/handlers/search.d.ts +34 -4
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +216 -36
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +55 -1
- package/dist/cli/mcp/lifecycle-tools.d.ts.map +1 -1
- package/dist/cli/mcp/lifecycle-tools.js +3 -2
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.js +4 -3
- package/dist/cli/mcp/workspace-tools.js +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +55 -2
- package/dist/cli/registry.d.ts +19 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cloud-lister/aws.d.ts +35 -0
- package/dist/cloud-lister/aws.d.ts.map +1 -0
- package/dist/cloud-lister/aws.js +203 -0
- package/dist/cloud-lister/azure.d.ts +34 -0
- package/dist/cloud-lister/azure.d.ts.map +1 -0
- package/dist/cloud-lister/azure.js +129 -0
- package/dist/cloud-lister/common.d.ts +40 -0
- package/dist/cloud-lister/common.d.ts.map +1 -0
- package/dist/cloud-lister/common.js +83 -0
- package/dist/cloud-lister/credentials.d.ts +50 -0
- package/dist/cloud-lister/credentials.d.ts.map +1 -0
- package/dist/cloud-lister/credentials.js +86 -0
- package/dist/cloud-lister/fakes.d.ts +27 -0
- package/dist/cloud-lister/fakes.d.ts.map +1 -0
- package/dist/cloud-lister/fakes.js +50 -0
- package/dist/cloud-lister/gcp.d.ts +42 -0
- package/dist/cloud-lister/gcp.d.ts.map +1 -0
- package/dist/cloud-lister/gcp.js +143 -0
- package/dist/cloud-lister/guard.d.ts +49 -0
- package/dist/cloud-lister/guard.d.ts.map +1 -0
- package/dist/cloud-lister/guard.js +103 -0
- package/dist/cloud-lister/ids.d.ts +23 -0
- package/dist/cloud-lister/ids.d.ts.map +1 -0
- package/dist/cloud-lister/ids.js +42 -0
- package/dist/cloud-lister/index.d.ts +67 -0
- package/dist/cloud-lister/index.d.ts.map +1 -0
- package/dist/cloud-lister/index.js +102 -0
- package/dist/cloud-lister/kubernetes.d.ts +64 -0
- package/dist/cloud-lister/kubernetes.d.ts.map +1 -0
- package/dist/cloud-lister/kubernetes.js +276 -0
- package/dist/cloud-lister/markers.d.ts +31 -0
- package/dist/cloud-lister/markers.d.ts.map +1 -0
- package/dist/cloud-lister/markers.js +73 -0
- package/dist/cloud-lister/mask.d.ts +31 -0
- package/dist/cloud-lister/mask.d.ts.map +1 -0
- package/dist/cloud-lister/mask.js +74 -0
- package/dist/cloud-lister/sigv4.d.ts +29 -0
- package/dist/cloud-lister/sigv4.d.ts.map +1 -0
- package/dist/cloud-lister/sigv4.js +54 -0
- package/dist/cloud-lister/transport.d.ts +55 -0
- package/dist/cloud-lister/transport.d.ts.map +1 -0
- package/dist/cloud-lister/transport.js +86 -0
- package/dist/cloud-lister/types.d.ts +121 -0
- package/dist/cloud-lister/types.d.ts.map +1 -0
- package/dist/cloud-lister/types.js +24 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +6 -0
- package/dist/components/capability-plugin.d.ts +9 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability.d.ts +215 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +21 -0
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/cli-support.js +58 -14
- package/dist/components/declared-reads.d.ts +38 -0
- package/dist/components/declared-reads.d.ts.map +1 -0
- package/dist/components/declared-reads.js +131 -0
- package/dist/components/deploy-units.d.ts.map +1 -1
- package/dist/components/deploy-units.js +4 -0
- package/dist/components/driver.d.ts +34 -1
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +66 -3
- package/dist/components/fan-out-run.d.ts +23 -1
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +82 -14
- package/dist/components/fan-out-support.d.ts +6 -0
- package/dist/components/fan-out-support.d.ts.map +1 -1
- package/dist/components/fan-out-support.js +4 -1
- package/dist/components/fan-out.d.ts +28 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/groups.d.ts +229 -0
- package/dist/components/groups.d.ts.map +1 -0
- package/dist/components/groups.js +760 -0
- package/dist/components/index.d.ts +6 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -0
- package/dist/components/plan-shape-conformance.d.ts +48 -0
- package/dist/components/plan-shape-conformance.d.ts.map +1 -0
- package/dist/components/plan-shape-conformance.js +122 -0
- package/dist/components/pr-run.d.ts +41 -4
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +209 -39
- package/dist/components/promote-rounds.d.ts +9 -0
- package/dist/components/promote-rounds.d.ts.map +1 -1
- package/dist/components/promote-rounds.js +23 -2
- package/dist/components/promote.d.ts +17 -0
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +36 -6
- package/dist/components/release-gate.d.ts +23 -1
- package/dist/components/release-gate.d.ts.map +1 -1
- package/dist/components/release-gate.js +97 -33
- package/dist/components/run-groups.d.ts +58 -0
- package/dist/components/run-groups.d.ts.map +1 -0
- package/dist/components/run-groups.js +78 -0
- package/dist/components/starter-plugin.d.ts +1 -0
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/starter-plugin.js +6 -1
- package/dist/components/verbs/index.d.ts +1 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +1 -0
- package/dist/components/verbs/member-outputs.d.ts +187 -0
- package/dist/components/verbs/member-outputs.d.ts.map +1 -0
- package/dist/components/verbs/member-outputs.js +218 -0
- package/dist/config.d.ts +60 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -0
- package/dist/deep-observation.d.ts +1 -13
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/deep-observation.js +5 -22
- package/dist/drift-record.d.ts +542 -0
- package/dist/drift-record.d.ts.map +1 -0
- package/dist/drift-record.js +886 -0
- package/dist/engine-facts.d.ts +144 -0
- package/dist/engine-facts.d.ts.map +1 -0
- package/dist/engine-facts.js +14 -0
- package/dist/graph-ir.d.ts +153 -2
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +224 -6
- package/dist/graph-refs.d.ts +145 -0
- package/dist/graph-refs.d.ts.map +1 -1
- package/dist/graph-refs.js +305 -0
- package/dist/graph-schema/fixtures/adopt.json +15 -0
- package/dist/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/dist/graph-schema/fixtures/index.json +68 -0
- package/dist/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/dist/graph-schema/fixtures.d.ts +23 -0
- package/dist/graph-schema/fixtures.d.ts.map +1 -0
- package/dist/graph-schema/fixtures.js +246 -0
- package/dist/graph-schema/generate.d.ts +15 -0
- package/dist/graph-schema/generate.d.ts.map +1 -0
- package/dist/graph-schema/generate.js +267 -0
- package/dist/graph-schema/graph.schema.json +1387 -0
- package/dist/health.schema.json +2 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/instance-nodes.d.ts +159 -0
- package/dist/instance-nodes.d.ts.map +1 -0
- package/dist/instance-nodes.js +231 -0
- package/dist/lexicon.d.ts +72 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/adoption-file.d.ts +56 -0
- package/dist/lifecycle/adoption-file.d.ts.map +1 -0
- package/dist/lifecycle/adoption-file.js +123 -0
- package/dist/lifecycle/cloud-index.d.ts +186 -0
- package/dist/lifecycle/cloud-index.d.ts.map +1 -0
- package/dist/lifecycle/cloud-index.js +618 -0
- package/dist/lifecycle/derive-edges.d.ts +59 -0
- package/dist/lifecycle/derive-edges.d.ts.map +1 -0
- package/dist/lifecycle/derive-edges.js +126 -0
- package/dist/lifecycle/git.d.ts +10 -9
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/git.js +7 -1
- package/dist/lifecycle/identity-match.d.ts +133 -0
- package/dist/lifecycle/identity-match.d.ts.map +1 -0
- package/dist/lifecycle/identity-match.js +147 -0
- package/dist/lifecycle/index-diff.d.ts +224 -0
- package/dist/lifecycle/index-diff.d.ts.map +1 -0
- package/dist/lifecycle/index-diff.js +327 -0
- package/dist/lifecycle/index-document.d.ts +130 -0
- package/dist/lifecycle/index-document.d.ts.map +1 -0
- package/dist/lifecycle/index-document.js +189 -0
- package/dist/lifecycle/index-drift.d.ts +121 -0
- package/dist/lifecycle/index-drift.d.ts.map +1 -0
- package/dist/lifecycle/index-drift.js +178 -0
- package/dist/lifecycle/index-import.d.ts +168 -0
- package/dist/lifecycle/index-import.d.ts.map +1 -0
- package/dist/lifecycle/index-import.js +515 -0
- package/dist/lifecycle/index-join.d.ts +129 -0
- package/dist/lifecycle/index-join.d.ts.map +1 -0
- package/dist/lifecycle/index-join.js +248 -0
- package/dist/lifecycle/index.d.ts +4 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +4 -0
- package/dist/lifecycle/observation-baseline.d.ts +61 -21
- package/dist/lifecycle/observation-baseline.d.ts.map +1 -1
- package/dist/lifecycle/observation-baseline.js +144 -19
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +6 -1
- package/dist/lifecycle/query.d.ts +45 -4
- package/dist/lifecycle/query.d.ts.map +1 -1
- package/dist/lifecycle/query.js +89 -7
- package/dist/lifecycle/replay.d.ts +10 -3
- package/dist/lifecycle/replay.d.ts.map +1 -1
- package/dist/lifecycle/replay.js +10 -6
- package/dist/lifecycle/scenario.d.ts +4 -3
- package/dist/lifecycle/scenario.d.ts.map +1 -1
- package/dist/lifecycle/snapshot-store-fake.d.ts +9 -0
- package/dist/lifecycle/snapshot-store-fake.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-fake.js +21 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts +102 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-s3.js +254 -0
- package/dist/lifecycle/snapshot-store.d.ts +170 -0
- package/dist/lifecycle/snapshot-store.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store.js +832 -0
- package/dist/lifecycle/snapshot.d.ts +11 -0
- package/dist/lifecycle/snapshot.d.ts.map +1 -1
- package/dist/lifecycle/snapshot.js +18 -5
- package/dist/lifecycle/type-listing.d.ts +148 -0
- package/dist/lifecycle/type-listing.d.ts.map +1 -0
- package/dist/lifecycle/type-listing.js +166 -0
- package/dist/lint/component-checks.d.ts +15 -1
- package/dist/lint/component-checks.d.ts.map +1 -1
- package/dist/lint/component-checks.js +1 -0
- package/dist/lint/presets/relaxed.json +2 -1
- package/dist/lint/presets/strict.json +2 -1
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.js +13 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.js +8 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts +33 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.js +123 -0
- package/dist/lint/rules/comp/index.d.ts +2 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/comp/index.js +4 -1
- package/dist/observation.d.ts +19 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +18 -1
- package/dist/op/activities/activity-contracts.d.ts +1 -1
- package/dist/op/activities/activity-contracts.js +1 -1
- package/dist/op/activities/change-set.d.ts +6 -4
- package/dist/op/activities/change-set.d.ts.map +1 -1
- package/dist/op/activities/change-set.js +4 -2
- package/dist/op/activity-failure.d.ts +27 -0
- package/dist/op/activity-failure.d.ts.map +1 -1
- package/dist/op/activity-failure.js +31 -0
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +5 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +22 -8
- package/dist/pr-loop.d.ts +56 -1
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +51 -1
- package/dist/pulumi-urn.d.ts +101 -0
- package/dist/pulumi-urn.d.ts.map +1 -0
- package/dist/pulumi-urn.js +131 -0
- package/dist/release-floors.d.ts +23 -0
- package/dist/release-floors.d.ts.map +1 -0
- package/dist/release-floors.js +22 -0
- package/dist/sensitive-key.d.ts +23 -0
- package/dist/sensitive-key.d.ts.map +1 -0
- package/dist/sensitive-key.js +31 -0
- package/dist/wave-runtime.mjs +234 -234
- package/dist/workspace/adoption-report.d.ts +53 -0
- package/dist/workspace/adoption-report.d.ts.map +1 -0
- package/dist/workspace/adoption-report.js +76 -0
- package/dist/workspace/capabilities-contract.d.ts +7 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -1
- package/dist/workspace/capabilities-contract.js +2 -1
- package/dist/workspace/capabilities.schema.json +98 -0
- package/dist/workspace/change-set.schema.json +42 -3
- package/dist/workspace/ci-cloud-identity.d.ts +13 -1
- package/dist/workspace/ci-cloud-identity.d.ts.map +1 -1
- package/dist/workspace/ci-cloud-identity.js +30 -1
- package/dist/workspace/compose-graph.d.ts +10 -1
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +6 -1
- package/dist/workspace/conformance/index.d.ts +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/index.js +6 -1
- package/dist/workspace/drift-cli.d.ts +81 -0
- package/dist/workspace/drift-cli.d.ts.map +1 -0
- package/dist/workspace/drift-cli.js +317 -0
- package/dist/workspace/drift.schema.json +672 -0
- package/dist/workspace/graph-cli.d.ts +2 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +3 -0
- package/dist/workspace/graph.schema.json +72 -0
- package/dist/workspace/init.d.ts +5 -1
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/init.js +55 -9
- package/dist/workspace/ledger.schema.json +1 -1
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +2 -0
- package/dist/workspace/pr-report.schema.json +51 -2
- package/dist/workspace/promote-waves.d.ts +112 -0
- package/dist/workspace/promote-waves.d.ts.map +1 -0
- package/dist/workspace/promote-waves.js +290 -0
- package/dist/workspace/promote.d.ts +84 -2
- package/dist/workspace/promote.d.ts.map +1 -1
- package/dist/workspace/promote.js +347 -61
- package/dist/workspace/reason-codes.d.ts +12 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +14 -0
- package/dist/workspace/search-contract.d.ts +3 -3
- package/dist/workspace/search-contract.d.ts.map +1 -1
- package/dist/workspace/search-contract.js +2 -0
- package/dist/workspace/search.schema.json +103 -5
- package/package.json +14 -1
- package/src/__fixtures__/drift-record/README.md +58 -0
- package/src/__fixtures__/drift-record/choudoufu-cone.ndjson +4 -0
- package/src/__fixtures__/drift-record/choudoufu-resource.ndjson +3 -0
- package/src/__fixtures__/drift-record/component-status-ledger.json +65 -0
- package/src/__fixtures__/drift-record/component-status.json +91 -0
- package/src/__fixtures__/drift-record/deep-diff.json +259 -0
- package/src/__fixtures__/drift-record/lifecycle-diff-live.json +825 -0
- package/src/__fixtures__/drift-record/live-diff.json +125 -0
- package/src/audit/discover.e2e.test.ts +14 -0
- package/src/audit/discover.ts +3 -1
- package/src/behaviour.ts +1 -1
- package/src/capabilities/templates.json +145 -0
- package/src/capabilities/templates.test.ts +212 -0
- package/src/capabilities/templates.ts +204 -0
- package/src/change-set-bundle.test.ts +83 -0
- package/src/change-set-graph.ts +80 -9
- package/src/change-set.test.ts +24 -0
- package/src/change-set.ts +77 -14
- package/src/ci-identity-targets.test.ts +23 -0
- package/src/ci-identity.ts +10 -4
- package/src/cli/commands/import-index.test.ts +117 -0
- package/src/cli/commands/import-index.ts +265 -0
- package/src/cli/commands/lint.ts +4 -2
- package/src/cli/handlers/components.test.ts +9 -0
- package/src/cli/handlers/components.ts +12 -2
- package/src/cli/handlers/fan-out.ts +17 -3
- package/src/cli/handlers/graph.test.ts +42 -0
- package/src/cli/handlers/graph.ts +26 -4
- package/src/cli/handlers/index-cloud.ts +32 -0
- package/src/cli/handlers/index-diff.test.ts +68 -0
- package/src/cli/handlers/index-diff.ts +146 -0
- package/src/cli/handlers/ledger-root-member.test.ts +161 -0
- package/src/cli/handlers/lifecycle-drift.ts +68 -0
- package/src/cli/handlers/lifecycle.test.ts +33 -11
- package/src/cli/handlers/lifecycle.ts +205 -30
- package/src/cli/handlers/misc.ts +73 -0
- package/src/cli/handlers/pr-waves-blocked.test.ts +37 -2
- package/src/cli/handlers/pr.ts +14 -2
- package/src/cli/handlers/promote.test.ts +64 -0
- package/src/cli/handlers/promote.ts +81 -6
- package/src/cli/handlers/query.ts +27 -4
- package/src/cli/handlers/run-declared-reads-cli.test.ts +187 -0
- package/src/cli/handlers/run-groups-cli.test.ts +229 -0
- package/src/cli/handlers/scenario.test.ts +13 -0
- package/src/cli/handlers/scenario.ts +8 -7
- package/src/cli/handlers/search-index.test.ts +255 -0
- package/src/cli/handlers/search-json.test.ts +1 -1
- package/src/cli/handlers/search-ownership.test.ts +194 -0
- package/src/cli/handlers/search.ts +271 -38
- package/src/cli/main.test.ts +7 -0
- package/src/cli/main.ts +56 -1
- package/src/cli/mcp/lifecycle-tools.ts +3 -2
- package/src/cli/mcp/resource-handlers.ts +4 -3
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/cli/parse-args.ts +40 -2
- package/src/cli/registry.ts +19 -1
- package/src/cloud-lister/aws.test.ts +202 -0
- package/src/cloud-lister/aws.ts +226 -0
- package/src/cloud-lister/azure.test.ts +132 -0
- package/src/cloud-lister/azure.ts +142 -0
- package/src/cloud-lister/common.ts +115 -0
- package/src/cloud-lister/credentials.ts +110 -0
- package/src/cloud-lister/fakes.ts +66 -0
- package/src/cloud-lister/gcp.test.ts +121 -0
- package/src/cloud-lister/gcp.ts +159 -0
- package/src/cloud-lister/guard.test.ts +198 -0
- package/src/cloud-lister/guard.ts +111 -0
- package/src/cloud-lister/ids.ts +54 -0
- package/src/cloud-lister/index.ts +134 -0
- package/src/cloud-lister/kubernetes.test.ts +160 -0
- package/src/cloud-lister/kubernetes.ts +284 -0
- package/src/cloud-lister/markers.ts +74 -0
- package/src/cloud-lister/mask.ts +77 -0
- package/src/cloud-lister/shape.test.ts +81 -0
- package/src/cloud-lister/sigv4.ts +70 -0
- package/src/cloud-lister/transport.ts +118 -0
- package/src/cloud-lister/types.ts +135 -0
- package/src/components/capability-plugin-loader.ts +4 -0
- package/src/components/capability-plugin.ts +10 -0
- package/src/components/capability.ts +229 -0
- package/src/components/cli-support.ts +70 -14
- package/src/components/declared-reads.test.ts +103 -0
- package/src/components/declared-reads.ts +134 -0
- package/src/components/deploy-units.ts +4 -0
- package/src/components/driver.ts +89 -4
- package/src/components/fan-out-run.ts +95 -15
- package/src/components/fan-out-support.ts +10 -1
- package/src/components/fan-out.ts +30 -0
- package/src/components/groups.test.ts +320 -0
- package/src/components/groups.ts +880 -0
- package/src/components/index.ts +42 -0
- package/src/components/plan-shape-conformance.ts +130 -0
- package/src/components/pr-env-run-bundle.test.ts +2 -0
- package/src/components/pr-run.test.ts +516 -3
- package/src/components/pr-run.ts +231 -41
- package/src/components/promote-rounds.ts +25 -2
- package/src/components/promote.ts +55 -5
- package/src/components/registry.test.ts +1 -1
- package/src/components/release-gate.ts +115 -30
- package/src/components/release-groups.test.ts +362 -0
- package/src/components/run-groups.ts +113 -0
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +1 -0
- package/src/components/verbs/member-outputs.test.ts +205 -0
- package/src/components/verbs/member-outputs.ts +308 -0
- package/src/config.ts +44 -0
- package/src/deep-observation.ts +5 -23
- package/src/drift-record.test.ts +596 -0
- package/src/drift-record.ts +1206 -0
- package/src/engine-facts.guard.test.ts +111 -0
- package/src/engine-facts.test.ts +178 -0
- package/src/engine-facts.ts +154 -0
- package/src/gated-waves-bundle.test.ts +2 -0
- package/src/graph-ir-live.test.ts +92 -0
- package/src/graph-ir.ts +317 -7
- package/src/graph-refs.ts +416 -0
- package/src/graph-schema/fixtures/adopt.json +15 -0
- package/src/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/src/graph-schema/fixtures/index.json +68 -0
- package/src/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/src/graph-schema/fixtures.ts +267 -0
- package/src/graph-schema/generate.ts +263 -0
- package/src/graph-schema/graph-schema.test.ts +153 -0
- package/src/graph-schema/graph.schema.json +1387 -0
- package/src/health.schema.json +2 -1
- package/src/identity.ts +2 -0
- package/src/index.ts +2 -0
- package/src/instance-nodes.ts +288 -0
- package/src/lexicon.ts +76 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T120000Z-aaaaaaaaaaaa.json +149 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T130000Z-bbbbbbbbbbbb.json +127 -0
- package/src/lifecycle/adoption-file.test.ts +100 -0
- package/src/lifecycle/adoption-file.ts +154 -0
- package/src/lifecycle/cloud-index.test.ts +517 -0
- package/src/lifecycle/cloud-index.ts +736 -0
- package/src/lifecycle/derive-edges.test.ts +193 -0
- package/src/lifecycle/derive-edges.ts +182 -0
- package/src/lifecycle/git.ts +10 -4
- package/src/lifecycle/identity-match.test.ts +308 -0
- package/src/lifecycle/identity-match.ts +257 -0
- package/src/lifecycle/index-diff.test.ts +198 -0
- package/src/lifecycle/index-diff.ts +476 -0
- package/src/lifecycle/index-document.test.ts +64 -0
- package/src/lifecycle/index-document.ts +299 -0
- package/src/lifecycle/index-drift.test.ts +191 -0
- package/src/lifecycle/index-drift.ts +304 -0
- package/src/lifecycle/index-import.test.ts +255 -0
- package/src/lifecycle/index-import.ts +634 -0
- package/src/lifecycle/index-join.test.ts +250 -0
- package/src/lifecycle/index-join.ts +304 -0
- package/src/lifecycle/index-store-load-bearing.test.ts +187 -0
- package/src/lifecycle/index.ts +4 -0
- package/src/lifecycle/member-ledger.test.ts +25 -7
- package/src/lifecycle/observation-baseline.test.ts +72 -1
- package/src/lifecycle/observation-baseline.ts +190 -27
- package/src/lifecycle/observe.ts +6 -1
- package/src/lifecycle/query.test.ts +69 -1
- package/src/lifecycle/query.ts +103 -10
- package/src/lifecycle/replay.test.ts +9 -5
- package/src/lifecycle/replay.ts +9 -5
- package/src/lifecycle/scenario.ts +4 -3
- package/src/lifecycle/snapshot-store-fake.ts +29 -0
- package/src/lifecycle/snapshot-store-s3.ts +316 -0
- package/src/lifecycle/snapshot-store.test.ts +385 -0
- package/src/lifecycle/snapshot-store.ts +981 -0
- package/src/lifecycle/snapshot.test.ts +13 -0
- package/src/lifecycle/snapshot.ts +23 -6
- package/src/lifecycle/type-listing.test.ts +166 -0
- package/src/lifecycle/type-listing.ts +309 -0
- package/src/lint/component-checks.ts +17 -1
- package/src/lint/config.test.ts +3 -0
- package/src/lint/presets/relaxed.json +2 -1
- package/src/lint/presets/strict.json +2 -1
- package/src/lint/rules/__fixtures__/comp/comp008/fail/dns.component.ts +15 -0
- package/src/lint/rules/__fixtures__/comp/comp008/pass/dns.component.ts +10 -0
- package/src/lint/rules/comp/comp.test.ts +2 -1
- package/src/lint/rules/comp/comp008-applies-signal-only-root.ts +121 -0
- package/src/lint/rules/comp/comp008.test.ts +77 -0
- package/src/lint/rules/comp/index.ts +4 -1
- package/src/observation-edges.test.ts +33 -0
- package/src/observation.ts +36 -1
- package/src/op/activities/activity-contracts.ts +1 -1
- package/src/op/activities/change-set.ts +8 -5
- package/src/op/activity-failure.ts +36 -0
- package/src/op/index.ts +2 -1
- package/src/op/local-executor.test.ts +80 -0
- package/src/op/local-executor.ts +27 -9
- package/src/pr-loop-bundle.test.ts +5 -2
- package/src/pr-loop.test.ts +43 -0
- package/src/pr-loop.ts +111 -2
- package/src/pulumi-urn.ts +151 -0
- package/src/release-floors.ts +22 -0
- package/src/sensitive-key.ts +34 -0
- package/src/workspace/adoption-report.test.ts +61 -0
- package/src/workspace/adoption-report.ts +103 -0
- package/src/workspace/capabilities-contract.test.ts +4 -0
- package/src/workspace/capabilities-contract.ts +9 -1
- package/src/workspace/capabilities.schema.json +98 -0
- package/src/workspace/change-set.schema.json +42 -3
- package/src/workspace/ci-cloud-identity.ts +31 -1
- package/src/workspace/compose-graph.test.ts +12 -0
- package/src/workspace/compose-graph.ts +12 -1
- package/src/workspace/conformance/conformance.e2e.test.ts +2 -1
- package/src/workspace/conformance/index.ts +6 -1
- package/src/workspace/drift-cli.test.ts +65 -0
- package/src/workspace/drift-cli.ts +365 -0
- package/src/workspace/drift.schema.json +672 -0
- package/src/workspace/graph-cli.ts +5 -0
- package/src/workspace/graph.schema.json +72 -0
- package/src/workspace/init.test.ts +38 -1
- package/src/workspace/init.ts +50 -8
- package/src/workspace/intent-gaps.test.ts +18 -2
- package/src/workspace/ledger.schema.json +1 -1
- package/src/workspace/nested-graph.ts +1 -0
- package/src/workspace/pr-report.schema.json +51 -2
- package/src/workspace/promote-waves.test.ts +296 -0
- package/src/workspace/promote-waves.ts +340 -0
- package/src/workspace/promote.test.ts +158 -4
- package/src/workspace/promote.ts +398 -57
- package/src/workspace/reason-codes.test.ts +4 -1
- package/src/workspace/reason-codes.ts +14 -0
- package/src/workspace/search-contract.ts +2 -0
- package/src/workspace/search.schema.json +103 -5
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant index <substrate>` and the library function behind it (chant#4532,
|
|
3
|
+
* tier 1 of INTENTIUS/behold#1025). It fills an index from a cloud with no
|
|
4
|
+
* project and keeps it in the index store.
|
|
5
|
+
*
|
|
6
|
+
* Built in behold as behold#1026 (the command) and behold#1029 (the lister),
|
|
7
|
+
* and moved here on the ruling that behold is a control plane and every
|
|
8
|
+
* model lives in chant
|
|
9
|
+
* (https://github.com/INTENTIUS/behold/issues/1024#issuecomment-6433236820).
|
|
10
|
+
* behold's `behold index` calls {@link runCloudIndex} with its own command
|
|
11
|
+
* name and default store directory.
|
|
12
|
+
*
|
|
13
|
+
* The pipeline, behold#1025's design as ruled (Q1-Q6, 2026-10-26):
|
|
14
|
+
*
|
|
15
|
+
* listCloud(scope, target) ../cloud-lister/
|
|
16
|
+
* -> ListingResult
|
|
17
|
+
* -> typeListing ./type-listing.ts (#4521)
|
|
18
|
+
* -> deriveEdges ./derive-edges.ts (#4522, with #4523's identity pass)
|
|
19
|
+
* -> IndexDocument
|
|
20
|
+
* -> store.writeIndex ./snapshot-store.ts (#4519)
|
|
21
|
+
*
|
|
22
|
+
* One run writes one version (Q6): one substrate and one account,
|
|
23
|
+
* subscription, project or cluster, with every location and type the flags
|
|
24
|
+
* name. The version is one immutable file (Q3),
|
|
25
|
+
* `index/cloud/<substrate>/<scopeId>/<scope digest>/<observedAt>-<digest12>.json`
|
|
26
|
+
* under the store's root, beside the `scope.json` that says what the digest
|
|
27
|
+
* means. A second run writes a second version; the first stays.
|
|
28
|
+
*
|
|
29
|
+
* Where it writes:
|
|
30
|
+
*
|
|
31
|
+
* - `--store <spec>`: a store from its spec ({@link planIndexStore});
|
|
32
|
+
* - else, inside a chant project (a `chant.config.ts` or `chant.config.json`
|
|
33
|
+
* in the working directory or above it): that project's configured store;
|
|
34
|
+
* - else (Q4): a `local` store in chant's per-user data directory,
|
|
35
|
+
* `$XDG_DATA_HOME/chant`, else `~/.local/share/chant`
|
|
36
|
+
* ({@link chantUserStoreDir}). `CHANT_INDEX_DIR`, when set, names that
|
|
37
|
+
* store's `index/` directory. A caller (behold) passes its own
|
|
38
|
+
* `defaultStoreDir` instead.
|
|
39
|
+
*
|
|
40
|
+
* Read-only:
|
|
41
|
+
*
|
|
42
|
+
* - the lister sends only its allowlisted reads (../cloud-lister/guard.ts),
|
|
43
|
+
* pins every call to an explicit endpoint, and with an endpoint takes
|
|
44
|
+
* static credentials only, never an SDK's default chain;
|
|
45
|
+
* - the command refuses to start with any action flag ({@link ACTION_FLAGS})
|
|
46
|
+
* before anything else is read, and starts no server;
|
|
47
|
+
* - nothing is written but the one index version (and its `scope.json`), and
|
|
48
|
+
* the store is never published to a remote by this command;
|
|
49
|
+
* - for GCP nothing is enabled: when the Cloud Asset API is off, the
|
|
50
|
+
* lister's note carries the `gcloud services enable` command for the
|
|
51
|
+
* person to run.
|
|
52
|
+
*
|
|
53
|
+
* The index is never consulted for a decision. Deleting it loses history and
|
|
54
|
+
* nothing else.
|
|
55
|
+
*
|
|
56
|
+
* Environment the command reads (and nothing else):
|
|
57
|
+
*
|
|
58
|
+
* - aws: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`
|
|
59
|
+
* (static credentials, when the first two are set), `AWS_ENDPOINT_URL`
|
|
60
|
+
* (the endpoint when `--endpoint` is absent), `AWS_REGION` then
|
|
61
|
+
* `AWS_DEFAULT_REGION` (the region when `--regions` is absent);
|
|
62
|
+
* - azure: `CHANT_AZURE_TOKEN` (an ARM bearer token);
|
|
63
|
+
* - gcp: `CHANT_GCP_TOKEN` (an OAuth access token);
|
|
64
|
+
* - kubernetes: `KUBECONFIG` (its first path) when `--kubeconfig` is absent;
|
|
65
|
+
* - the store: `CHANT_INDEX_DIR`, `XDG_DATA_HOME`, and for `--store` the
|
|
66
|
+
* `CHANT_SNAPSHOT_*` variables ./snapshot-store.ts reads.
|
|
67
|
+
*
|
|
68
|
+
* The maintainer's emulator run (never run by an agent), against the pinned
|
|
69
|
+
* floci on 4566 with a scratch data dir:
|
|
70
|
+
*
|
|
71
|
+
* env -u AWS_PROFILE -u AWS_SESSION_TOKEN \
|
|
72
|
+
* AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test \
|
|
73
|
+
* XDG_DATA_HOME=$(mktemp -d) \
|
|
74
|
+
* npx tsx packages/core/src/cli/main.ts index aws --endpoint http://localhost:4566 \
|
|
75
|
+
* --account 000000000000 --regions us-east-1 \
|
|
76
|
+
* --types AWS::S3::Bucket,AWS::IAM::Role,AWS::SQS::Queue
|
|
77
|
+
*
|
|
78
|
+
* Its last line is the verdict, `chant index: wrote <version> ...`.
|
|
79
|
+
*/
|
|
80
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
81
|
+
import { homedir } from "node:os";
|
|
82
|
+
import { basename, delimiter, dirname, isAbsolute, join, resolve } from "node:path";
|
|
83
|
+
import { CHANT_VERSION } from "../chant-version.js";
|
|
84
|
+
import { kubeTargetFromKubeconfig, listCloud, ListerConfigError, MutatingCallRefused, OriginRefused, } from "../cloud-lister/index.js";
|
|
85
|
+
import { NEXT_RELEASE } from "../release-floors.js";
|
|
86
|
+
import { deriveEdges } from "./derive-edges.js";
|
|
87
|
+
import { createSnapshotStore, resolveSnapshotStore, snapshotStoreConfig } from "./snapshot-store.js";
|
|
88
|
+
import { typeListing } from "./type-listing.js";
|
|
89
|
+
/** The first chant with `chant index` and {@link runCloudIndex} / {@link indexCloud}. */
|
|
90
|
+
export const CLOUD_INDEX_FLOOR = NEXT_RELEASE;
|
|
91
|
+
/**
|
|
92
|
+
* List one scope, type it, derive its edges and write one stamped version.
|
|
93
|
+
* Throws what the lister throws ({@link ListerConfigError},
|
|
94
|
+
* {@link OriginRefused}, {@link MutatingCallRefused}, a failed read) before
|
|
95
|
+
* anything is written, and {@link IndexWriteError} when the store's write
|
|
96
|
+
* throws.
|
|
97
|
+
*/
|
|
98
|
+
export async function indexCloud(req, deps = {}) {
|
|
99
|
+
if (!req.store.writable && req.store.kind !== "none") {
|
|
100
|
+
throw new IndexUsageError(`the store ${req.store.where} is read-only`);
|
|
101
|
+
}
|
|
102
|
+
const listing = await (deps.list ?? listCloud)(req.scope, req.target, { ...(deps.listOptions ?? {}), version: req.version ?? CHANT_VERSION });
|
|
103
|
+
const doc = deriveEdges(typeListing(listing, req.lexicons), req.lexicons);
|
|
104
|
+
let write;
|
|
105
|
+
try {
|
|
106
|
+
write = (await req.store.writeIndex(doc)) ?? { written: false, reason: `the ${req.store.kind} store keeps nothing` };
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
throw new IndexWriteError(e.message);
|
|
110
|
+
}
|
|
111
|
+
return { listing, doc, write };
|
|
112
|
+
}
|
|
113
|
+
// ── Arguments ───────────────────────────────────────────────────────────
|
|
114
|
+
/** Flags that would reach an action (deploy, apply, Ops, rollbacks). An index run refuses every one. */
|
|
115
|
+
export const ACTION_FLAGS = [
|
|
116
|
+
"--apply",
|
|
117
|
+
"--approve",
|
|
118
|
+
"--approver",
|
|
119
|
+
"--auto-approve",
|
|
120
|
+
"--adopt",
|
|
121
|
+
"--create",
|
|
122
|
+
"--delete",
|
|
123
|
+
"--deploy",
|
|
124
|
+
"--destroy",
|
|
125
|
+
"--enable",
|
|
126
|
+
"--enable-api",
|
|
127
|
+
"--fix",
|
|
128
|
+
"--import",
|
|
129
|
+
"--live",
|
|
130
|
+
"--op",
|
|
131
|
+
"--ops",
|
|
132
|
+
"--promote",
|
|
133
|
+
"--rollback",
|
|
134
|
+
"--run-op",
|
|
135
|
+
"--write",
|
|
136
|
+
"--yes",
|
|
137
|
+
];
|
|
138
|
+
const SUBSTRATES = { aws: "aws", azure: "azure", gcp: "gcp", kubernetes: "kubernetes", k8s: "kubernetes" };
|
|
139
|
+
/** The chant lexicon that types each substrate's listed types. */
|
|
140
|
+
export const SUBSTRATE_LEXICON = { aws: "aws", azure: "azure", gcp: "gcp", kubernetes: "k8s" };
|
|
141
|
+
export function indexUsage(command = "chant index", storeDefault = "a local store in chant's per-user data directory ($XDG_DATA_HOME/chant, else ~/.local/share/chant)") {
|
|
142
|
+
return `${command} <aws|azure|gcp|kubernetes> [scope] [target] [--store <spec>] [--json]
|
|
143
|
+
|
|
144
|
+
Read one account, subscription, project or cluster through its inventory
|
|
145
|
+
API, type it through chant's lexicons, add derived edges, and write one
|
|
146
|
+
stamped index version to the index store. Read-only: it lists, and writes
|
|
147
|
+
nothing but the index version. Every run writes a new version; the old ones
|
|
148
|
+
stay.
|
|
149
|
+
|
|
150
|
+
Scope:
|
|
151
|
+
--account <id> | --subscription <id> | --project <id> | --cluster <name> | --scope-id <id>
|
|
152
|
+
The AWS account, Azure subscription, GCP project or
|
|
153
|
+
cluster name the run reads (required, except for
|
|
154
|
+
kubernetes, which defaults to the kubeconfig's cluster).
|
|
155
|
+
--regions <r,...> Regions or locations (kubernetes: namespaces). AWS needs
|
|
156
|
+
them named (default AWS_REGION); others default to all.
|
|
157
|
+
--locations <l,...> Same as --regions.
|
|
158
|
+
--types <t,...> Types as the inventory API names them (default: all,
|
|
159
|
+
or a fixed default set for AWS).
|
|
160
|
+
--tag <k=v> Only objects with this tag or label. Repeatable.
|
|
161
|
+
|
|
162
|
+
Target:
|
|
163
|
+
--endpoint <url> An emulator's endpoint. With one, credentials must be
|
|
164
|
+
static: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY,
|
|
165
|
+
CHANT_AZURE_TOKEN, CHANT_GCP_TOKEN or --anonymous.
|
|
166
|
+
No SDK default credential chain is used. AWS also reads
|
|
167
|
+
AWS_ENDPOINT_URL.
|
|
168
|
+
--anonymous gcp with --endpoint: send no token (floci-gcp).
|
|
169
|
+
--ca <file> A CA bundle for the endpoint's TLS.
|
|
170
|
+
--insecure-skip-verify
|
|
171
|
+
Skip TLS verification; only for a loopback endpoint.
|
|
172
|
+
--kubeconfig <file> kubernetes: the kubeconfig (default KUBECONFIG, then
|
|
173
|
+
~/.kube/config). Token or client certificate only.
|
|
174
|
+
--context <name> kubernetes: the kubeconfig context.
|
|
175
|
+
|
|
176
|
+
Store:
|
|
177
|
+
--store <spec> local, local:<dir>, git-ref, git-ref:<ref>, s3,
|
|
178
|
+
s3://<bucket>[/<prefix>], or none.
|
|
179
|
+
Default: the chant project's store when run inside one,
|
|
180
|
+
else ${storeDefault}.
|
|
181
|
+
--json Print the result as one JSON object.
|
|
182
|
+
|
|
183
|
+
Refused: any action flag (${ACTION_FLAGS.slice(0, 5).join(", ")} and the rest of
|
|
184
|
+
ACTION_FLAGS in packages/core/src/lifecycle/cloud-index.ts). It starts no server.
|
|
185
|
+
`;
|
|
186
|
+
}
|
|
187
|
+
export class IndexUsageError extends Error {
|
|
188
|
+
constructor(message, actionFlag) {
|
|
189
|
+
super(message);
|
|
190
|
+
this.actionFlag = actionFlag;
|
|
191
|
+
this.name = "IndexUsageError";
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function list(value) {
|
|
195
|
+
return value
|
|
196
|
+
.split(",")
|
|
197
|
+
.map((s) => s.trim())
|
|
198
|
+
.filter(Boolean);
|
|
199
|
+
}
|
|
200
|
+
/** An index run's arguments. Throws {@link IndexUsageError}; an action flag is named in `actionFlag`. */
|
|
201
|
+
export function parseIndexArgs(argv, command = "chant index") {
|
|
202
|
+
// An action flag is refused before anything else is read, wherever it sits.
|
|
203
|
+
for (const a of argv) {
|
|
204
|
+
const flag = a.startsWith("--") ? a.split("=")[0] : undefined;
|
|
205
|
+
if (flag && ACTION_FLAGS.includes(flag)) {
|
|
206
|
+
throw new IndexUsageError(`${command} is read-only and refuses ${flag}: it lists and writes one index version, and no deploy, apply, Op or rollback is reachable from it. Nothing was listed and nothing was written.`, flag);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const [first, ...rest] = argv;
|
|
210
|
+
if (!first || first.startsWith("-"))
|
|
211
|
+
throw new IndexUsageError(`${command} needs a substrate: aws, azure, gcp or kubernetes`);
|
|
212
|
+
const substrate = SUBSTRATES[first];
|
|
213
|
+
if (!substrate)
|
|
214
|
+
throw new IndexUsageError(`${command}: unknown substrate '${first}' (aws, azure, gcp or kubernetes)`);
|
|
215
|
+
const out = { substrate, tags: {}, anonymous: false, insecureSkipVerify: false, json: false };
|
|
216
|
+
const scopeFlags = ["--account", "--subscription", "--project", "--cluster", "--scope-id"];
|
|
217
|
+
for (let i = 0; i < rest.length; i++) {
|
|
218
|
+
const raw = rest[i];
|
|
219
|
+
const eq = raw.startsWith("--") ? raw.indexOf("=") : -1;
|
|
220
|
+
const flag = eq > 0 ? raw.slice(0, eq) : raw;
|
|
221
|
+
const inline = eq > 0 ? raw.slice(eq + 1) : undefined;
|
|
222
|
+
const value = () => {
|
|
223
|
+
if (inline !== undefined)
|
|
224
|
+
return inline;
|
|
225
|
+
const v = rest[i + 1];
|
|
226
|
+
if (v === undefined || v.startsWith("--"))
|
|
227
|
+
throw new IndexUsageError(`${command}: ${flag} needs a value`);
|
|
228
|
+
i++;
|
|
229
|
+
return v;
|
|
230
|
+
};
|
|
231
|
+
if (scopeFlags.includes(flag)) {
|
|
232
|
+
const v = value();
|
|
233
|
+
if (out.scopeId !== undefined && out.scopeId !== v)
|
|
234
|
+
throw new IndexUsageError(`${command} reads one account, subscription, project or cluster per run; got ${out.scopeId} and ${v}`);
|
|
235
|
+
out.scopeId = v;
|
|
236
|
+
}
|
|
237
|
+
else if (flag === "--regions" || flag === "--locations" || flag === "--namespaces") {
|
|
238
|
+
out.locations = [...(out.locations ?? []), ...list(value())];
|
|
239
|
+
}
|
|
240
|
+
else if (flag === "--types") {
|
|
241
|
+
out.types = [...(out.types ?? []), ...list(value())];
|
|
242
|
+
}
|
|
243
|
+
else if (flag === "--tag") {
|
|
244
|
+
const v = value();
|
|
245
|
+
const at = v.indexOf("=");
|
|
246
|
+
if (at <= 0)
|
|
247
|
+
throw new IndexUsageError(`${command}: --tag takes key=value, got '${v}'`);
|
|
248
|
+
out.tags[v.slice(0, at)] = v.slice(at + 1);
|
|
249
|
+
}
|
|
250
|
+
else if (flag === "--endpoint") {
|
|
251
|
+
out.endpoint = value();
|
|
252
|
+
}
|
|
253
|
+
else if (flag === "--anonymous") {
|
|
254
|
+
out.anonymous = true;
|
|
255
|
+
}
|
|
256
|
+
else if (flag === "--ca") {
|
|
257
|
+
out.ca = value();
|
|
258
|
+
}
|
|
259
|
+
else if (flag === "--insecure-skip-verify") {
|
|
260
|
+
out.insecureSkipVerify = true;
|
|
261
|
+
}
|
|
262
|
+
else if (flag === "--kubeconfig") {
|
|
263
|
+
out.kubeconfig = value();
|
|
264
|
+
}
|
|
265
|
+
else if (flag === "--context") {
|
|
266
|
+
out.context = value();
|
|
267
|
+
}
|
|
268
|
+
else if (flag === "--store") {
|
|
269
|
+
out.store = value();
|
|
270
|
+
}
|
|
271
|
+
else if (flag === "--json") {
|
|
272
|
+
out.json = true;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
throw new IndexUsageError(`${command}: unknown argument '${raw}'`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (out.anonymous && out.substrate !== "gcp")
|
|
279
|
+
throw new IndexUsageError(`${command}: --anonymous is for gcp against an emulator`);
|
|
280
|
+
if (out.anonymous && out.endpoint === undefined)
|
|
281
|
+
throw new IndexUsageError(`${command}: --anonymous needs --endpoint (an emulator); a real project always takes a token`);
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
function isLoopback(endpoint) {
|
|
285
|
+
try {
|
|
286
|
+
const h = new URL(endpoint).hostname.replace(/^\[|\]$/g, "");
|
|
287
|
+
return h === "localhost" || h === "::1" || /^127\./.test(h);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/** The run's scope and target, from the flags and the variables the module comment lists. */
|
|
294
|
+
export function scopeAndTarget(args, deps) {
|
|
295
|
+
const { env } = deps;
|
|
296
|
+
const command = deps.command ?? "chant index";
|
|
297
|
+
const read = deps.readFile ?? ((p) => readFileSync(p, "utf8"));
|
|
298
|
+
const endpoint = args.endpoint ?? (args.substrate === "aws" ? env.AWS_ENDPOINT_URL || undefined : undefined);
|
|
299
|
+
if (args.insecureSkipVerify && (endpoint === undefined || !isLoopback(endpoint))) {
|
|
300
|
+
throw new ListerConfigError("--insecure-skip-verify is only for an emulator on a loopback endpoint");
|
|
301
|
+
}
|
|
302
|
+
const tls = args.ca || args.insecureSkipVerify ? { ...(args.ca ? { ca: read(resolve(deps.cwd, args.ca)) } : {}), ...(args.insecureSkipVerify ? { insecureSkipVerify: true } : {}) } : undefined;
|
|
303
|
+
const base = {
|
|
304
|
+
locations: args.locations && args.locations.length > 0 ? args.locations : "*",
|
|
305
|
+
types: args.types && args.types.length > 0 ? args.types : "*",
|
|
306
|
+
...(Object.keys(args.tags).length > 0 ? { tagFilter: args.tags } : {}),
|
|
307
|
+
};
|
|
308
|
+
const needScope = (what) => {
|
|
309
|
+
if (!args.scopeId)
|
|
310
|
+
throw new ListerConfigError(`${command} ${args.substrate} needs ${what}`);
|
|
311
|
+
return args.scopeId;
|
|
312
|
+
};
|
|
313
|
+
switch (args.substrate) {
|
|
314
|
+
case "aws": {
|
|
315
|
+
const region = env.AWS_REGION || env.AWS_DEFAULT_REGION;
|
|
316
|
+
const locations = base.locations === "*" && region ? [region] : base.locations;
|
|
317
|
+
const credentials = env.AWS_ACCESS_KEY_ID && env.AWS_SECRET_ACCESS_KEY
|
|
318
|
+
? { accessKeyId: env.AWS_ACCESS_KEY_ID, secretAccessKey: env.AWS_SECRET_ACCESS_KEY, ...(env.AWS_SESSION_TOKEN ? { sessionToken: env.AWS_SESSION_TOKEN } : {}) }
|
|
319
|
+
: undefined;
|
|
320
|
+
return {
|
|
321
|
+
scope: { substrate: "aws", scopeId: needScope("--account <id>"), ...base, locations },
|
|
322
|
+
target: { substrate: "aws", aws: { ...(endpoint !== undefined ? { endpoint } : {}), ...(credentials ? { credentials } : {}), ...(tls ? { tls } : {}) } },
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
case "azure": {
|
|
326
|
+
const token = env.CHANT_AZURE_TOKEN || undefined;
|
|
327
|
+
return {
|
|
328
|
+
scope: { substrate: "azure", scopeId: needScope("--subscription <id>"), ...base },
|
|
329
|
+
target: { substrate: "azure", azure: { ...(endpoint !== undefined ? { endpoint } : {}), ...(token !== undefined ? { token } : {}), ...(tls ? { tls } : {}) } },
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
case "gcp": {
|
|
333
|
+
const token = args.anonymous ? null : env.CHANT_GCP_TOKEN || undefined;
|
|
334
|
+
return {
|
|
335
|
+
scope: { substrate: "gcp", scopeId: needScope("--project <id>"), ...base },
|
|
336
|
+
target: { substrate: "gcp", gcp: { ...(endpoint !== undefined ? { endpoint } : {}), ...(token !== undefined ? { token } : {}), ...(tls ? { tls } : {}) } },
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
case "kubernetes": {
|
|
340
|
+
const path = args.kubeconfig
|
|
341
|
+
? resolve(deps.cwd, args.kubeconfig)
|
|
342
|
+
: env.KUBECONFIG
|
|
343
|
+
? env.KUBECONFIG.split(delimiter).filter(Boolean)[0]
|
|
344
|
+
: join(deps.home, ".kube", "config");
|
|
345
|
+
if (!path)
|
|
346
|
+
throw new ListerConfigError(`${command} kubernetes needs a kubeconfig (--kubeconfig or KUBECONFIG)`);
|
|
347
|
+
let text;
|
|
348
|
+
try {
|
|
349
|
+
text = read(path);
|
|
350
|
+
}
|
|
351
|
+
catch (e) {
|
|
352
|
+
throw new ListerConfigError(`${command} kubernetes could not read the kubeconfig ${path}: ${e.message}`);
|
|
353
|
+
}
|
|
354
|
+
const kube = kubeTargetFromKubeconfig(text, { ...(args.context ? { context: args.context } : {}), baseDir: dirname(path) });
|
|
355
|
+
const server = endpoint ?? kube.server;
|
|
356
|
+
const kubeTls = tls ? { ...kube.tls, ...tls } : kube.tls;
|
|
357
|
+
return {
|
|
358
|
+
scope: { substrate: "kubernetes", scopeId: args.scopeId ?? kube.clusterName, ...base },
|
|
359
|
+
target: { substrate: "kubernetes", kubernetes: { server, ...(kube.token ? { token: kube.token } : {}), ...(kubeTls ? { tls: kubeTls } : {}) } },
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* behold#1025 Q4: the per-user store's root, chant's per-user data directory.
|
|
366
|
+
* `CHANT_INDEX_DIR` names the store's `index/` directory; else
|
|
367
|
+
* `$XDG_DATA_HOME/chant`; else `~/.local/share/chant`.
|
|
368
|
+
*/
|
|
369
|
+
export function chantUserStoreDir(env = process.env, home = homedir()) {
|
|
370
|
+
const indexDir = env.CHANT_INDEX_DIR?.trim();
|
|
371
|
+
if (indexDir) {
|
|
372
|
+
if (basename(indexDir) !== "index") {
|
|
373
|
+
throw new IndexUsageError(`CHANT_INDEX_DIR (${indexDir}) must end in /index: the local store keeps index versions under <store>/index`);
|
|
374
|
+
}
|
|
375
|
+
return dirname(resolve(indexDir));
|
|
376
|
+
}
|
|
377
|
+
const xdg = env.XDG_DATA_HOME?.trim();
|
|
378
|
+
return join(xdg && isAbsolute(xdg) ? xdg : join(home, ".local", "share"), "chant");
|
|
379
|
+
}
|
|
380
|
+
const PROJECT_FILES = ["chant.config.ts", "chant.config.json"];
|
|
381
|
+
/** The chant project the working directory is in, if any: the nearest directory with a chant config. */
|
|
382
|
+
export function findChantProject(cwd, exists = existsSync) {
|
|
383
|
+
let dir = resolve(cwd);
|
|
384
|
+
for (;;) {
|
|
385
|
+
if (PROJECT_FILES.some((f) => exists(join(dir, f))))
|
|
386
|
+
return dir;
|
|
387
|
+
const up = dirname(dir);
|
|
388
|
+
if (up === dir)
|
|
389
|
+
return undefined;
|
|
390
|
+
dir = up;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* The store a run writes to. `--store` takes ./snapshot-store.ts's kinds as a
|
|
395
|
+
* spec: `local` (`.chant/store`, or `CHANT_SNAPSHOT_STORE_DIR`),
|
|
396
|
+
* `local:<dir>`, `git-ref`, `git-ref:<ref>`, `s3` (from `CHANT_SNAPSHOT_S3_*`),
|
|
397
|
+
* `s3://<bucket>[/<prefix>]`, `none`. The read-only `orphan-branch` store is
|
|
398
|
+
* refused. With no `--store`: the project's store, else `defaultStoreDir`.
|
|
399
|
+
*/
|
|
400
|
+
export function planIndexStore(o) {
|
|
401
|
+
const command = o.command ?? "chant index";
|
|
402
|
+
const env = { ...o.env };
|
|
403
|
+
if (o.store === undefined) {
|
|
404
|
+
const project = findChantProject(o.cwd, o.exists);
|
|
405
|
+
if (project)
|
|
406
|
+
return { kind: "project", projectDir: project };
|
|
407
|
+
return { kind: "user", dir: o.defaultStoreDir() };
|
|
408
|
+
}
|
|
409
|
+
const spec = o.store.trim();
|
|
410
|
+
const colon = spec.indexOf(":");
|
|
411
|
+
const head = spec.startsWith("s3://") ? "s3" : colon > 0 ? spec.slice(0, colon) : spec;
|
|
412
|
+
const tail = spec.startsWith("s3://") ? spec.slice("s3://".length) : colon > 0 ? spec.slice(colon + 1) : undefined;
|
|
413
|
+
env.CHANT_SNAPSHOT_STORE = head;
|
|
414
|
+
switch (head) {
|
|
415
|
+
case "local": {
|
|
416
|
+
if (tail !== undefined) {
|
|
417
|
+
if (!tail)
|
|
418
|
+
throw new IndexUsageError(`${command}: --store local:<dir> needs a directory`);
|
|
419
|
+
env.CHANT_SNAPSHOT_STORE_DIR = isAbsolute(tail) ? tail : resolve(o.cwd, tail);
|
|
420
|
+
}
|
|
421
|
+
return { kind: "spec", spec, configured: { store: "local" }, env };
|
|
422
|
+
}
|
|
423
|
+
case "git-ref":
|
|
424
|
+
return { kind: "spec", spec, configured: { store: "git-ref", readOrphanBranch: false, ...(tail ? { ref: tail } : {}) }, env };
|
|
425
|
+
case "s3": {
|
|
426
|
+
if (tail !== undefined) {
|
|
427
|
+
const [bucket, ...prefix] = tail.split("/");
|
|
428
|
+
if (!bucket)
|
|
429
|
+
throw new IndexUsageError(`${command}: --store s3://<bucket>[/<prefix>] needs a bucket`);
|
|
430
|
+
env.CHANT_SNAPSHOT_S3_BUCKET = bucket;
|
|
431
|
+
const p = prefix.join("/").replace(/\/+$/, "");
|
|
432
|
+
if (p)
|
|
433
|
+
env.CHANT_SNAPSHOT_S3_PREFIX = p;
|
|
434
|
+
else
|
|
435
|
+
delete env.CHANT_SNAPSHOT_S3_PREFIX;
|
|
436
|
+
}
|
|
437
|
+
return { kind: "spec", spec, configured: { store: "s3" }, env };
|
|
438
|
+
}
|
|
439
|
+
case "none":
|
|
440
|
+
return { kind: "spec", spec, configured: { store: "none" }, env };
|
|
441
|
+
case "orphan-branch":
|
|
442
|
+
throw new IndexUsageError(`${command}: the orphan-branch store is read-only; pass local, git-ref, s3 or none`);
|
|
443
|
+
default:
|
|
444
|
+
throw new IndexUsageError(`${command}: --store '${spec}' is not a store spec (local, local:<dir>, git-ref, git-ref:<ref>, s3, s3://<bucket>[/<prefix>], none)`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
/** Build the planned store. */
|
|
448
|
+
export async function openIndexStore(plan, cwd) {
|
|
449
|
+
switch (plan.kind) {
|
|
450
|
+
case "user":
|
|
451
|
+
return createSnapshotStore({ store: "local", dir: plan.dir }, { cwd });
|
|
452
|
+
case "project":
|
|
453
|
+
return resolveSnapshotStore({ cwd: plan.projectDir });
|
|
454
|
+
case "spec":
|
|
455
|
+
return createSnapshotStore(snapshotStoreConfig(plan.configured, plan.env), { cwd, env: plan.env });
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/** The substrate's lexicon plugin, or a note saying why there is none. */
|
|
459
|
+
export async function substrateLexicons(substrate) {
|
|
460
|
+
const name = SUBSTRATE_LEXICON[substrate];
|
|
461
|
+
const pkg = `@intentius/chant-lexicon-${name}`;
|
|
462
|
+
let plugin;
|
|
463
|
+
try {
|
|
464
|
+
const { loadPlugin } = await import("../cli/plugins.js");
|
|
465
|
+
plugin = (await loadPlugin(name));
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
plugin = undefined;
|
|
469
|
+
}
|
|
470
|
+
if (!plugin || typeof plugin.name !== "string") {
|
|
471
|
+
return {
|
|
472
|
+
lexicons: [],
|
|
473
|
+
note: `${pkg} is not installed, so ${substrate} objects are kept as nodes of unknown kind and get no derived edges; install it to type them`,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
if (!plugin.listedTypes) {
|
|
477
|
+
return { lexicons: [plugin], note: `${pkg} has no listedTypes (chant#4521), so ${substrate} objects are kept as nodes of unknown kind` };
|
|
478
|
+
}
|
|
479
|
+
return { lexicons: [plugin] };
|
|
480
|
+
}
|
|
481
|
+
function summarize(doc) {
|
|
482
|
+
const nodes = doc.graph.nodes;
|
|
483
|
+
const unmapped = nodes.filter((n) => n.unmappedKind === true).length;
|
|
484
|
+
const listed = doc.coverage.filter((c) => c.verdict === "listed").length;
|
|
485
|
+
return {
|
|
486
|
+
nodes: nodes.length,
|
|
487
|
+
typed: nodes.length - unmapped,
|
|
488
|
+
unmapped,
|
|
489
|
+
derivedEdges: doc.graph.edges.filter((e) => e.origin === "derived").length,
|
|
490
|
+
coverage: { listed, notObserved: doc.coverage.length - listed },
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* `chant index <substrate> …`, and `behold index` through it. Returns the
|
|
495
|
+
* exit code: 0 written (or a store that keeps nothing), 1 a read or write
|
|
496
|
+
* failed, 2 refused (usage, an action flag, a credential rule, a read-only
|
|
497
|
+
* store).
|
|
498
|
+
*/
|
|
499
|
+
export async function runCloudIndex(argv, opts = {}) {
|
|
500
|
+
const command = opts.command ?? "chant index";
|
|
501
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
502
|
+
const env = opts.env ?? process.env;
|
|
503
|
+
const home = opts.home ?? homedir();
|
|
504
|
+
const out = opts.stdout ?? ((s) => void process.stdout.write(s));
|
|
505
|
+
const err = opts.stderr ?? ((s) => void process.stderr.write(s));
|
|
506
|
+
const usage = indexUsage(command, opts.defaultStoreText);
|
|
507
|
+
if (argv.includes("-h") || argv.includes("--help")) {
|
|
508
|
+
out(usage);
|
|
509
|
+
return 0;
|
|
510
|
+
}
|
|
511
|
+
let args;
|
|
512
|
+
let plan;
|
|
513
|
+
try {
|
|
514
|
+
args = parseIndexArgs(argv, command);
|
|
515
|
+
plan = planIndexStore({
|
|
516
|
+
store: args.store,
|
|
517
|
+
cwd,
|
|
518
|
+
env,
|
|
519
|
+
defaultStoreDir: opts.defaultStoreDir ?? (() => chantUserStoreDir(env, home)),
|
|
520
|
+
command,
|
|
521
|
+
...(opts.exists ? { exists: opts.exists } : {}),
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
catch (e) {
|
|
525
|
+
if (e instanceof IndexUsageError) {
|
|
526
|
+
err(`${e.message}\n`);
|
|
527
|
+
if (!e.actionFlag)
|
|
528
|
+
err(`\n${usage}`);
|
|
529
|
+
return 2;
|
|
530
|
+
}
|
|
531
|
+
throw e;
|
|
532
|
+
}
|
|
533
|
+
let scope;
|
|
534
|
+
let target;
|
|
535
|
+
try {
|
|
536
|
+
({ scope, target } = scopeAndTarget(args, { env, cwd, home, command, ...(opts.readFile ? { readFile: opts.readFile } : {}) }));
|
|
537
|
+
}
|
|
538
|
+
catch (e) {
|
|
539
|
+
if (e instanceof ListerConfigError) {
|
|
540
|
+
err(`${e.message}. Nothing was listed and nothing was written.\n`);
|
|
541
|
+
return 2;
|
|
542
|
+
}
|
|
543
|
+
throw e;
|
|
544
|
+
}
|
|
545
|
+
let store;
|
|
546
|
+
try {
|
|
547
|
+
store = await (opts.openStore ?? openIndexStore)(plan, cwd);
|
|
548
|
+
}
|
|
549
|
+
catch (e) {
|
|
550
|
+
err(`${command}: the index store could not be opened: ${e.message}. Nothing was listed and nothing was written.\n`);
|
|
551
|
+
return 2;
|
|
552
|
+
}
|
|
553
|
+
if (!store.writable && store.kind !== "none") {
|
|
554
|
+
err(`${command}: the store ${store.where} is read-only. Nothing was listed and nothing was written.\n`);
|
|
555
|
+
return 2;
|
|
556
|
+
}
|
|
557
|
+
const lex = await (opts.lexicons ?? substrateLexicons)(args.substrate);
|
|
558
|
+
let result;
|
|
559
|
+
try {
|
|
560
|
+
result = await indexCloud({ scope, target, store, lexicons: lex.lexicons, ...(opts.version ? { version: opts.version } : {}) }, { ...(opts.list ? { list: opts.list } : {}), ...(opts.listOptions ? { listOptions: opts.listOptions } : {}) });
|
|
561
|
+
}
|
|
562
|
+
catch (e) {
|
|
563
|
+
if (e instanceof ListerConfigError || e instanceof OriginRefused || e instanceof MutatingCallRefused) {
|
|
564
|
+
err(`${e.message}. Nothing was written.\n`);
|
|
565
|
+
return 2;
|
|
566
|
+
}
|
|
567
|
+
if (e instanceof IndexWriteError) {
|
|
568
|
+
err(`${command}: the index version could not be written to ${store.where}: ${e.message}\n`);
|
|
569
|
+
return 1;
|
|
570
|
+
}
|
|
571
|
+
err(`${command}: ${e.message}. Nothing was written.\n`);
|
|
572
|
+
return 1;
|
|
573
|
+
}
|
|
574
|
+
const { doc, write } = result;
|
|
575
|
+
const notes = [];
|
|
576
|
+
if (lex.note)
|
|
577
|
+
notes.push(lex.note);
|
|
578
|
+
for (const n of doc.notes ?? [])
|
|
579
|
+
notes.push(n.message);
|
|
580
|
+
const version = write.path ? basename(write.path) : undefined;
|
|
581
|
+
const summary = {
|
|
582
|
+
substrate: args.substrate,
|
|
583
|
+
scopeId: scope.scopeId,
|
|
584
|
+
scopeKey: doc.stamp.scopeKey,
|
|
585
|
+
observedAt: doc.stamp.observedAt,
|
|
586
|
+
digest: doc.stamp.digest,
|
|
587
|
+
store: { kind: store.kind, where: store.where },
|
|
588
|
+
written: write.written,
|
|
589
|
+
...(version ? { version } : {}),
|
|
590
|
+
...(write.path ? { path: write.path } : {}),
|
|
591
|
+
...(write.reason ? { reason: write.reason } : {}),
|
|
592
|
+
...summarize(doc),
|
|
593
|
+
notes,
|
|
594
|
+
};
|
|
595
|
+
if (args.json) {
|
|
596
|
+
out(`${JSON.stringify(summary, null, 2)}\n`);
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
out(`${args.substrate} ${scope.scopeId}: ${summary.nodes} nodes (${summary.typed} typed, ${summary.unmapped} of unknown kind), ${summary.derivedEdges} derived edges\n`);
|
|
600
|
+
out(`coverage: ${summary.coverage.listed} (type, location) listed, ${summary.coverage.notObserved} not observed\n`);
|
|
601
|
+
for (const n of notes)
|
|
602
|
+
out(` note: ${n}\n`);
|
|
603
|
+
if (write.written)
|
|
604
|
+
out(`${command}: wrote ${version} under ${summary.scopeKey} in ${store.where}\n`);
|
|
605
|
+
else
|
|
606
|
+
out(`${command}: wrote nothing to ${store.where}: ${write.reason ?? "the store kept nothing"}\n`);
|
|
607
|
+
}
|
|
608
|
+
// An unchanged re-read at the same second, or a store that keeps nothing, is not a failure.
|
|
609
|
+
return 0;
|
|
610
|
+
}
|
|
611
|
+
/** A store write that threw, told apart from a failed listing. */
|
|
612
|
+
export class IndexWriteError extends Error {
|
|
613
|
+
constructor(message) {
|
|
614
|
+
super(message);
|
|
615
|
+
this.name = "IndexWriteError";
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
export { listCloud, ListerConfigError, MutatingCallRefused, OriginRefused, READ_OPERATIONS } from "../cloud-lister/index.js";
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derived edges for indexed resources (#4522, tier 1 of INTENTIUS/behold#1025,
|
|
3
|
+
* rules ruled on INTENTIUS/behold#1023 2026-10-26).
|
|
4
|
+
*
|
|
5
|
+
* An index typed by ./type-listing.ts has nodes and no edges: with no project
|
|
6
|
+
* there are no declared references. {@link deriveEdges} runs each lexicon's
|
|
7
|
+
* `referenceCatalog` (the one `chant graph --live` uses, #778) over the
|
|
8
|
+
* indexed nodes through `reconstructIndexedEdges` (../graph-refs.ts), and
|
|
9
|
+
* writes what it finds into the document:
|
|
10
|
+
*
|
|
11
|
+
* - every edge is `origin: "derived"` with the `rule` that drew it and
|
|
12
|
+
* `grain: "property"`; containment edges say `relation: "containment"` and
|
|
13
|
+
* fill `groups.byContainer`;
|
|
14
|
+
* - the join key is the scoped value: substrate and account, subscription,
|
|
15
|
+
* project or cluster, plus region for a regional type, account only for a
|
|
16
|
+
* global one (Q2);
|
|
17
|
+
* - a value matching several nodes draws no edge; an `ambiguous-reference`
|
|
18
|
+
* note records it with every candidate (Q3);
|
|
19
|
+
* - a reference to nothing in the index goes in `graph.dangling`;
|
|
20
|
+
* - tags make edges only through a catalog's typed tag rules (Q5);
|
|
21
|
+
* - a lexicon with no catalog is named in a `no-catalog` note, and its nodes
|
|
22
|
+
* get no derived edges: nothing guesses;
|
|
23
|
+
* - derivation runs over every document of one account from the same read
|
|
24
|
+
* (Q7, {@link deriveEdgesAcross}), and each edge is stored in its holder's
|
|
25
|
+
* document. Edges are per read and never carried to another read.
|
|
26
|
+
*
|
|
27
|
+
* After the catalog pass, the identity-match pass (#4523, behold#1023 Q1)
|
|
28
|
+
* runs over the same nodes: an attribute value equal to the native id or ARN
|
|
29
|
+
* of a node whose lexicon declares an `indexIdentity` draws an edge whose
|
|
30
|
+
* `rule` starts `identity-match:`, under the same scoped join key, and a
|
|
31
|
+
* value naming several nodes draws none and is recorded in an
|
|
32
|
+
* `ambiguous-identity` note with every candidate. A pair the catalog joined
|
|
33
|
+
* gets no second edge. Pure.
|
|
34
|
+
*/
|
|
35
|
+
import type { IRNode } from "../graph-ir.js";
|
|
36
|
+
import { type IndexedNodeScope, type ReferenceCatalog } from "../graph-refs.js";
|
|
37
|
+
import type { IndexIdentity } from "./identity-match.js";
|
|
38
|
+
import { type IndexDocument } from "./index-document.js";
|
|
39
|
+
/** What {@link deriveEdges} needs from a lexicon. A `LexiconPlugin` is one. */
|
|
40
|
+
export interface EdgeLexicon {
|
|
41
|
+
name: string;
|
|
42
|
+
referenceCatalog?: ReferenceCatalog;
|
|
43
|
+
/** Its identity rule (#4523): when present, the identity-match pass can name this lexicon's nodes. */
|
|
44
|
+
indexIdentity?: IndexIdentity;
|
|
45
|
+
}
|
|
46
|
+
/** The scope an indexed node's identifiers are unique in, from its document's stamp and its own location. */
|
|
47
|
+
export declare function indexedNodeScope(doc: IndexDocument, node: IRNode): IndexedNodeScope;
|
|
48
|
+
/** Derived edges over one index document. */
|
|
49
|
+
export declare function deriveEdges(doc: IndexDocument, lexicons: readonly EdgeLexicon[]): IndexDocument;
|
|
50
|
+
/**
|
|
51
|
+
* Derived edges over every document of one account from one read (behold#1023
|
|
52
|
+
* Q7): regional documents and an account-level one for global types, or the
|
|
53
|
+
* single document a `behold index` run writes (behold#1025 Q6). The documents
|
|
54
|
+
* must be cloud reads of one substrate and scope id with one `observedAt`;
|
|
55
|
+
* anything else is refused, because joining two reads would carry a name from
|
|
56
|
+
* one read to an object of another.
|
|
57
|
+
*/
|
|
58
|
+
export declare function deriveEdgesAcross(docs: readonly IndexDocument[], lexicons: readonly EdgeLexicon[]): IndexDocument[];
|
|
59
|
+
//# sourceMappingURL=derive-edges.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-edges.d.ts","sourceRoot":"","sources":["../../src/lifecycle/derive-edges.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAA0B,MAAM,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAKL,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAuB,KAAK,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AAE3F,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,sGAAsG;IACtG,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAKD,6GAA6G;AAC7G,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAKnF;AAQD,6CAA6C;AAC7C,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,aAAa,CAE/F;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,EAAE,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,aAAa,EAAE,CAgGnH"}
|