@intentius/chant 0.13.1 → 0.15.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 +45 -5
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/proof.d.ts +3 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +4 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts +3 -0
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +8 -2
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts +37 -0
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts.map +1 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts +48 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts.map +1 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/pinned-upgrade.d.ts +41 -0
- package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts +39 -0
- package/dist/cli/handlers/components.d.ts.map +1 -0
- package/dist/cli/handlers/dev.d.ts +3 -0
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/graph.d.ts +4 -2
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -0
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +35 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/fetch.d.ts +22 -0
- package/dist/codegen/fetch.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.d.ts +110 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -0
- package/dist/codegen/pinned-upgrade.d.ts +153 -0
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -0
- package/dist/codegen/rolling-upgrade.d.ts +138 -0
- package/dist/codegen/rolling-upgrade.d.ts.map +1 -0
- package/dist/codegen/surface-snapshot.d.ts +173 -0
- package/dist/codegen/surface-snapshot.d.ts.map +1 -0
- package/dist/codegen/version-bump.d.ts +21 -0
- package/dist/codegen/version-bump.d.ts.map +1 -0
- package/dist/components/auto-release.d.ts +93 -0
- package/dist/components/auto-release.d.ts.map +1 -0
- package/dist/components/builders.d.ts +37 -0
- package/dist/components/builders.d.ts.map +1 -0
- package/dist/components/capability-plugin-loader.d.ts +111 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -0
- package/dist/components/capability-plugin-schema.d.ts +24 -0
- package/dist/components/capability-plugin-schema.d.ts.map +1 -0
- package/dist/components/capability-plugin.d.ts +85 -0
- package/dist/components/capability-plugin.d.ts.map +1 -0
- package/dist/components/capability.d.ts +89 -0
- package/dist/components/capability.d.ts.map +1 -0
- package/dist/components/cli-support.d.ts +204 -0
- package/dist/components/cli-support.d.ts.map +1 -0
- package/dist/components/component.d.ts +179 -0
- package/dist/components/component.d.ts.map +1 -0
- package/dist/components/config-defaults.d.ts +41 -0
- package/dist/components/config-defaults.d.ts.map +1 -0
- package/dist/components/discover.d.ts +60 -0
- package/dist/components/discover.d.ts.map +1 -0
- package/dist/components/driver-output.d.ts +20 -0
- package/dist/components/driver-output.d.ts.map +1 -0
- package/dist/components/driver.d.ts +209 -0
- package/dist/components/driver.d.ts.map +1 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/manifest-persistence.d.ts +79 -0
- package/dist/components/manifest-persistence.d.ts.map +1 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts +27 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts.map +1 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts +22 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts.map +1 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts +37 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts.map +1 -0
- package/dist/components/pilots/lambda.pilot.d.ts +35 -0
- package/dist/components/pilots/lambda.pilot.d.ts.map +1 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts +17 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts.map +1 -0
- package/dist/components/pilots/project.d.ts +13 -0
- package/dist/components/pilots/project.d.ts.map +1 -0
- package/dist/components/presets/ecs-fargate.d.ts +59 -0
- package/dist/components/presets/ecs-fargate.d.ts.map +1 -0
- package/dist/components/presets/index.d.ts +29 -0
- package/dist/components/presets/index.d.ts.map +1 -0
- package/dist/components/presets/lambda.d.ts +35 -0
- package/dist/components/presets/lambda.d.ts.map +1 -0
- package/dist/components/presets/single-host-compose.d.ts +43 -0
- package/dist/components/presets/single-host-compose.d.ts.map +1 -0
- package/dist/components/registry.d.ts +29 -0
- package/dist/components/registry.d.ts.map +1 -0
- package/dist/components/starter-plugin.d.ts +51 -0
- package/dist/components/starter-plugin.d.ts.map +1 -0
- package/dist/components/temporal-codegen-loader.d.ts +27 -0
- package/dist/components/temporal-codegen-loader.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts +35 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts +45 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts +33 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/bom-writer.d.ts +155 -0
- package/dist/components/verbs/bom-writer.d.ts.map +1 -0
- package/dist/components/verbs/build-archive.d.ts +205 -0
- package/dist/components/verbs/build-archive.d.ts.map +1 -0
- package/dist/components/verbs/build.d.ts +150 -0
- package/dist/components/verbs/build.d.ts.map +1 -0
- package/dist/components/verbs/cloud-executor.d.ts +88 -0
- package/dist/components/verbs/cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/component-bom.d.ts +103 -0
- package/dist/components/verbs/component-bom.d.ts.map +1 -0
- package/dist/components/verbs/index.d.ts +49 -0
- package/dist/components/verbs/index.d.ts.map +1 -0
- package/dist/components/verbs/license-policy.d.ts +56 -0
- package/dist/components/verbs/license-policy.d.ts.map +1 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts +81 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/process-runner.d.ts +64 -0
- package/dist/components/verbs/process-runner.d.ts.map +1 -0
- package/dist/components/verbs/reproducibility.d.ts +80 -0
- package/dist/components/verbs/reproducibility.d.ts.map +1 -0
- package/dist/components/verbs/sbom-generator.d.ts +157 -0
- package/dist/components/verbs/sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/sbom.d.ts +79 -0
- package/dist/components/verbs/sbom.d.ts.map +1 -0
- package/dist/components/verbs/shell.d.ts +35 -0
- package/dist/components/verbs/shell.d.ts.map +1 -0
- package/dist/components/verbs/sign.d.ts +222 -0
- package/dist/components/verbs/sign.d.ts.map +1 -0
- package/dist/components/verbs/stub.d.ts +18 -0
- package/dist/components/verbs/stub.d.ts.map +1 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts +51 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/verify.d.ts +106 -0
- package/dist/components/verbs/verify.d.ts.map +1 -0
- package/dist/components/verbs/vex.d.ts +65 -0
- package/dist/components/verbs/vex.d.ts.map +1 -0
- package/dist/components/verbs/vuln-gate.d.ts +91 -0
- package/dist/components/verbs/vuln-gate.d.ts.map +1 -0
- package/dist/components/verbs/vuln-scan.d.ts +116 -0
- package/dist/components/verbs/vuln-scan.d.ts.map +1 -0
- package/dist/components/verbs/wait-verify.d.ts +85 -0
- package/dist/components/verbs/wait-verify.d.ts.map +1 -0
- package/dist/config.d.ts +205 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon.d.ts +78 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/build-ledger-store.d.ts +121 -0
- package/dist/lifecycle/build-ledger-store.d.ts.map +1 -0
- package/dist/lifecycle/build-ledger.d.ts +225 -0
- package/dist/lifecycle/build-ledger.d.ts.map +1 -0
- package/dist/lifecycle/git.d.ts +84 -0
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +5 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/oras-referrer-lookup.d.ts +41 -0
- package/dist/lifecycle/oras-referrer-lookup.d.ts.map +1 -0
- package/dist/lifecycle/release-ledger.d.ts +122 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -0
- package/dist/lifecycle/status.d.ts +150 -0
- package/dist/lifecycle/status.d.ts.map +1 -0
- package/dist/lint/component-checks.d.ts +95 -0
- package/dist/lint/component-checks.d.ts.map +1 -0
- package/dist/lint/engine.d.ts +23 -0
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lint/presets/strict.json +8 -1
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts +10 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts +20 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts +28 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts +39 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +37 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts +43 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts +22 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts +33 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +18 -0
- package/dist/lint/rules/comp/index.d.ts.map +1 -0
- package/dist/lint/rules/comp/support.d.ts +71 -0
- package/dist/lint/rules/comp/support.d.ts.map +1 -0
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activity-registry.d.ts +11 -6
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +24 -0
- package/dist/op/activity-runtime.d.ts.map +1 -0
- package/dist/op/builders.d.ts +56 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/ownership.d.ts +20 -14
- package/dist/ownership.d.ts.map +1 -1
- package/package.json +14 -1
- package/src/audit/catalog.test.ts +74 -22
- package/src/audit/catalog.ts +74 -471
- package/src/audit/proof.ts +4 -2
- package/src/audit/report-html.test.ts +14 -7
- package/src/audit/report-model.ts +20 -9
- package/src/audit/report.test.ts +36 -13
- package/src/audit/report.ts +2 -0
- package/src/audit/rules-doc.test.ts +8 -6
- package/src/audit/rules-doc.ts +13 -5
- package/src/cli/commands/audit.ts +23 -18
- package/src/cli/commands/component-lint.test.ts +158 -0
- package/src/cli/commands/doctor.test.ts +116 -2
- package/src/cli/commands/doctor.ts +46 -0
- package/src/cli/commands/lexicon-rolling-upgrade.ts +198 -0
- package/src/cli/commands/lexicon-surface-diff.test.ts +104 -0
- package/src/cli/commands/lexicon-surface-diff.ts +185 -0
- package/src/cli/commands/lint.ts +142 -1
- package/src/cli/commands/pinned-upgrade.ts +204 -0
- package/src/cli/handlers/build.ts +58 -1
- package/src/cli/handlers/components.test.ts +504 -0
- package/src/cli/handlers/components.ts +404 -0
- package/src/cli/handlers/dev.ts +60 -1
- package/src/cli/handlers/graph.ts +47 -2
- package/src/cli/handlers/misc.ts +45 -1
- package/src/cli/handlers/run.test.ts +967 -3
- package/src/cli/handlers/run.ts +618 -11
- package/src/cli/main.test.ts +66 -0
- package/src/cli/main.ts +105 -2
- package/src/cli/registry.ts +35 -0
- package/src/codegen/fetch.test.ts +84 -3
- package/src/codegen/fetch.ts +76 -2
- package/src/codegen/lexicon-regen.test.ts +298 -0
- package/src/codegen/lexicon-regen.ts +545 -0
- package/src/codegen/pinned-upgrade.test.ts +399 -0
- package/src/codegen/pinned-upgrade.ts +423 -0
- package/src/codegen/rolling-upgrade.test.ts +333 -0
- package/src/codegen/rolling-upgrade.ts +320 -0
- package/src/codegen/surface-snapshot.test.ts +461 -0
- package/src/codegen/surface-snapshot.ts +546 -0
- package/src/codegen/version-bump.test.ts +47 -0
- package/src/codegen/version-bump.ts +39 -0
- package/src/components/README.md +130 -0
- package/src/components/SPRAWL-VALIDATION.md +181 -0
- package/src/components/__fixtures__/alb-ecs-service.json +51 -0
- package/src/components/__fixtures__/dynamodb-infra.json +32 -0
- package/src/components/__fixtures__/emr-job-consumer.json +26 -0
- package/src/components/__fixtures__/jar-lib-producer.json +16 -0
- package/src/components/__fixtures__/lambda-image-processor.json +28 -0
- package/src/components/__fixtures__/neo4j-fanout.json +34 -0
- package/src/components/__fixtures__/single-host-compose.json +29 -0
- package/src/components/auto-release.test.ts +217 -0
- package/src/components/auto-release.ts +216 -0
- package/src/components/builders.test.ts +45 -0
- package/src/components/builders.ts +71 -0
- package/src/components/capability-plugin-loader.ts +218 -0
- package/src/components/capability-plugin-schema.ts +56 -0
- package/src/components/capability-plugin.test.ts +235 -0
- package/src/components/capability-plugin.ts +108 -0
- package/src/components/capability.ts +117 -0
- package/src/components/cli-support.test.ts +579 -0
- package/src/components/cli-support.ts +481 -0
- package/src/components/component-schema.test.ts +265 -0
- package/src/components/component.schema.json +235 -0
- package/src/components/component.test.ts +251 -0
- package/src/components/component.ts +255 -0
- package/src/components/config-defaults.test.ts +263 -0
- package/src/components/config-defaults.ts +145 -0
- package/src/components/discover.test.ts +352 -0
- package/src/components/discover.ts +167 -0
- package/src/components/driver-output.ts +71 -0
- package/src/components/driver.test.ts +638 -0
- package/src/components/driver.ts +690 -0
- package/src/components/index.ts +113 -0
- package/src/components/manifest-persistence.test.ts +152 -0
- package/src/components/manifest-persistence.ts +164 -0
- package/src/components/pilots/README.md +33 -0
- package/src/components/pilots/alb-ecs.pilot.ts +63 -0
- package/src/components/pilots/dynamodb.pilot.ts +59 -0
- package/src/components/pilots/jar-emr.pilot.ts +69 -0
- package/src/components/pilots/lambda.pilot.ts +55 -0
- package/src/components/pilots/neo4j-fanout.pilot.ts +92 -0
- package/src/components/pilots/pilots-lint-clean.test.ts +78 -0
- package/src/components/pilots/pilots.test.ts +126 -0
- package/src/components/pilots/project.ts +13 -0
- package/src/components/presets/comp007-reduction.test.ts +122 -0
- package/src/components/presets/ecs-fargate.test.ts +84 -0
- package/src/components/presets/ecs-fargate.ts +103 -0
- package/src/components/presets/index.ts +32 -0
- package/src/components/presets/lambda.test.ts +35 -0
- package/src/components/presets/lambda.ts +53 -0
- package/src/components/presets/single-host-compose.test.ts +65 -0
- package/src/components/presets/single-host-compose.ts +64 -0
- package/src/components/registry.test.ts +112 -0
- package/src/components/registry.ts +37 -0
- package/src/components/starter-plugin.ts +105 -0
- package/src/components/temporal-codegen-loader.ts +41 -0
- package/src/components/verbs/__fixtures__/package-lock.json +45 -0
- package/src/components/verbs/__fixtures__/pom.xml +37 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-1.5.schema.json +3800 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-spdx-license.schema.json +621 -0
- package/src/components/verbs/__fixtures__/schemas/jsf-0.82.schema.json +240 -0
- package/src/components/verbs/__fixtures__/schemas/spdx-2.3.schema.json +740 -0
- package/src/components/verbs/__tests__/mock-cloud-executor.ts +102 -0
- package/src/components/verbs/__tests__/mock-process-runner.ts +79 -0
- package/src/components/verbs/__tests__/mock-sbom-generator.ts +85 -0
- package/src/components/verbs/bom-writer.test.ts +331 -0
- package/src/components/verbs/bom-writer.ts +386 -0
- package/src/components/verbs/build-archive.test.ts +251 -0
- package/src/components/verbs/build-archive.ts +296 -0
- package/src/components/verbs/build.test.ts +222 -0
- package/src/components/verbs/build.ts +252 -0
- package/src/components/verbs/cloud-executor.ts +181 -0
- package/src/components/verbs/component-bom.test.ts +219 -0
- package/src/components/verbs/component-bom.ts +189 -0
- package/src/components/verbs/index.ts +49 -0
- package/src/components/verbs/license-policy.ts +115 -0
- package/src/components/verbs/lockfile-sbom-generator.test.ts +195 -0
- package/src/components/verbs/lockfile-sbom-generator.ts +236 -0
- package/src/components/verbs/process-runner.test.ts +79 -0
- package/src/components/verbs/process-runner.ts +113 -0
- package/src/components/verbs/reproducibility.test.ts +24 -0
- package/src/components/verbs/reproducibility.ts +100 -0
- package/src/components/verbs/sbom-generator.test.ts +96 -0
- package/src/components/verbs/sbom-generator.ts +209 -0
- package/src/components/verbs/sbom.test.ts +184 -0
- package/src/components/verbs/sbom.ts +152 -0
- package/src/components/verbs/shell.test.ts +36 -0
- package/src/components/verbs/shell.ts +51 -0
- package/src/components/verbs/sign.test.ts +210 -0
- package/src/components/verbs/sign.ts +350 -0
- package/src/components/verbs/stub.ts +34 -0
- package/src/components/verbs/tool-sbom-generator.test.ts +194 -0
- package/src/components/verbs/tool-sbom-generator.ts +192 -0
- package/src/components/verbs/verify.test.ts +159 -0
- package/src/components/verbs/verify.ts +179 -0
- package/src/components/verbs/vex.ts +182 -0
- package/src/components/verbs/vuln-gate.test.ts +201 -0
- package/src/components/verbs/vuln-gate.ts +170 -0
- package/src/components/verbs/vuln-scan.test.ts +145 -0
- package/src/components/verbs/vuln-scan.ts +266 -0
- package/src/components/verbs/wait-verify.test.ts +111 -0
- package/src/components/verbs/wait-verify.ts +171 -0
- package/src/config.test.ts +74 -1
- package/src/config.ts +219 -0
- package/src/index.ts +32 -0
- package/src/lexicon.ts +88 -0
- package/src/lifecycle/build-ledger-store.test.ts +217 -0
- package/src/lifecycle/build-ledger-store.ts +165 -0
- package/src/lifecycle/build-ledger.test.ts +349 -0
- package/src/lifecycle/build-ledger.ts +305 -0
- package/src/lifecycle/git.test.ts +118 -0
- package/src/lifecycle/git.ts +149 -14
- package/src/lifecycle/index.ts +5 -0
- package/src/lifecycle/oras-referrer-lookup.test.ts +116 -0
- package/src/lifecycle/oras-referrer-lookup.ts +110 -0
- package/src/lifecycle/release-ledger.test.ts +209 -0
- package/src/lifecycle/release-ledger.ts +185 -0
- package/src/lifecycle/status.test.ts +330 -0
- package/src/lifecycle/status.ts +278 -0
- package/src/lint/component-checks.ts +148 -0
- package/src/lint/config.test.ts +21 -0
- package/src/lint/engine.ts +11 -2
- package/src/lint/presets/relaxed.json +8 -1
- package/src/lint/presets/strict.json +8 -1
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.ts +27 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.ts +19 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.ts +20 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.ts +18 -0
- package/src/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.ts +12 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.ts +18 -0
- package/src/lint/rules/comp/comp.test.ts +378 -0
- package/src/lint/rules/comp/comp001-publishes-never-applies.ts +78 -0
- package/src/lint/rules/comp/comp002-dangling-wiring-ref.ts +94 -0
- package/src/lint/rules/comp/comp003-mutating-no-rollback.ts +115 -0
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +66 -0
- package/src/lint/rules/comp/comp005-capability-kind-is-noun.ts +113 -0
- package/src/lint/rules/comp/comp006-shell-needs-reason.ts +55 -0
- package/src/lint/rules/comp/comp007-composition-sprawl.ts +71 -0
- package/src/lint/rules/comp/index.ts +37 -0
- package/src/lint/rules/comp/support.ts +173 -0
- package/src/lsp/lexicon-providers.test.ts +55 -0
- package/src/lsp/lexicon-providers.ts +13 -3
- package/src/op/activity-registry.test.ts +38 -0
- package/src/op/activity-registry.ts +31 -12
- package/src/op/activity-runtime.ts +73 -0
- package/src/op/builders.ts +92 -0
- package/src/op/index.ts +3 -1
- package/src/ownership.test.ts +24 -26
- package/src/ownership.ts +26 -38
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant components` handlers — release ledger + status surface (#568, epic
|
|
3
|
+
* #551 "Build & deploy observability").
|
|
4
|
+
*
|
|
5
|
+
* Two subcommands:
|
|
6
|
+
* - `chant components release record` — append one immutable release record
|
|
7
|
+
* to the `chant/lifecycle` orphan branch (../../lifecycle/release-ledger.ts).
|
|
8
|
+
* A deploy composition calls this (typically from a `Verify` phase, or the
|
|
9
|
+
* CI job that ran `chant build --components --generate <lexicon>`) once
|
|
10
|
+
* the artifact digest, git sha, and run id are known.
|
|
11
|
+
* - `chant components status [env]` — the status surface: joins the release
|
|
12
|
+
* ledger against live evidence (`lifecycle diff --live` + ownership,
|
|
13
|
+
* reused via `buildChangeSet`) by digest, and reports what's built vs
|
|
14
|
+
* what's deployed where, flagging unrecorded deploys and drift.
|
|
15
|
+
*
|
|
16
|
+
* `componentBom`/`build.reproducibility` (#614) resolve to real data as of
|
|
17
|
+
* #609: for every recorded digest in an environment's ledger, this handler
|
|
18
|
+
* looks up the persisted `BuildArchiveManifest` that produced it
|
|
19
|
+
* (`findBuildManifestByArtifactDigest`, ../../lifecycle/build-ledger-
|
|
20
|
+
* store.ts) and derives `buildsByDigest`/`componentBomByDigest` from it via
|
|
21
|
+
* `buildLedgerEntries`/`componentBomSummary` — the same derivation
|
|
22
|
+
* `build-ledger.test.ts` already exercises directly, now fed by a real
|
|
23
|
+
* manifest instead of a hand-built one. A digest with no persisted manifest
|
|
24
|
+
* (predates #609, or was recorded via `chant components release` alone with
|
|
25
|
+
* no corresponding build) simply has no entry in either map, so `build`/
|
|
26
|
+
* `componentBom` fall back to `null` exactly as before — no regression for
|
|
27
|
+
* ledgers with no persisted manifests at all.
|
|
28
|
+
*/
|
|
29
|
+
import { resolve } from "node:path";
|
|
30
|
+
import { getHeadCommit, fetchLifecycle, pushLifecycle, StaleLifecycleBranchError } from "../../lifecycle/git";
|
|
31
|
+
import {
|
|
32
|
+
appendReleaseRecord,
|
|
33
|
+
readReleaseLedger,
|
|
34
|
+
listReleaseEnvironments,
|
|
35
|
+
InvalidReleaseRecordError,
|
|
36
|
+
} from "../../lifecycle/release-ledger";
|
|
37
|
+
import { reconcileStatus, liveEvidenceFromChangeSet, compareAcrossEnvironments } from "../../lifecycle/status";
|
|
38
|
+
import { buildChangeSet } from "../../lifecycle/change-set";
|
|
39
|
+
import { buildLedgerEntries, componentBomSummary, type BuildLedgerEntry } from "../../lifecycle/build-ledger";
|
|
40
|
+
import { findBuildManifestByArtifactDigest } from "../../lifecycle/build-ledger-store";
|
|
41
|
+
import type { ComponentBomSummary } from "../../lifecycle/build-ledger";
|
|
42
|
+
import { loadChantConfig } from "../../config";
|
|
43
|
+
import { build } from "../../build";
|
|
44
|
+
import { discoverComponents } from "../../components/discover";
|
|
45
|
+
import { formatError, formatWarning, formatSuccess, formatBold } from "../format";
|
|
46
|
+
import type { CommandContext } from "../registry";
|
|
47
|
+
import type { ResourceMetadata } from "../../lexicon";
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* chant components release <env> --component <name> --digest <sha256:...>
|
|
51
|
+
* [--git-sha <sha>] [--run-id <id>] [--actor <name>]
|
|
52
|
+
*
|
|
53
|
+
* `--git-sha` defaults to the current HEAD commit (`git rev-parse HEAD`);
|
|
54
|
+
* `--run-id` defaults to common CI run-id env vars
|
|
55
|
+
* (`GITHUB_RUN_ID`/`CI_PIPELINE_ID`) or a locally generated id; `--actor`
|
|
56
|
+
* defaults to common CI actor env vars
|
|
57
|
+
* (`GITHUB_ACTOR`/`GITLAB_USER_LOGIN`/`USER`) but must resolve to *something*
|
|
58
|
+
* — an unattributed release record defeats the point of a release ledger, so
|
|
59
|
+
* this is the one field with no silent fallback to a placeholder.
|
|
60
|
+
*
|
|
61
|
+
* The timestamp is always a real `new Date()` taken here, at record time —
|
|
62
|
+
* never threaded in from elsewhere and never mocked in production code, per
|
|
63
|
+
* #568: "the session cannot call Date.now() in some contexts; take the
|
|
64
|
+
* timestamp from the environment/CLI at record time."
|
|
65
|
+
*/
|
|
66
|
+
export async function runComponentsReleaseRecord(ctx: CommandContext): Promise<number> {
|
|
67
|
+
const { args } = ctx;
|
|
68
|
+
const environment = args.extraPositional;
|
|
69
|
+
if (!environment) {
|
|
70
|
+
console.error(formatError({
|
|
71
|
+
message: "Environment is required: chant components release <env> --component <name> --digest <sha256:...>",
|
|
72
|
+
}));
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const component = args.component;
|
|
77
|
+
const digest = args.digest;
|
|
78
|
+
if (!component || !digest) {
|
|
79
|
+
console.error(formatError({
|
|
80
|
+
message: "--component and --digest are required",
|
|
81
|
+
hint: "chant components release <env> --component <name> --digest <sha256:...> [--git-sha <sha>] [--run-id <id>] [--actor <name>]",
|
|
82
|
+
}));
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const gitSha = args.gitSha ?? (await getHeadCommit().catch(() => undefined));
|
|
87
|
+
const runId = args.runId ?? process.env.GITHUB_RUN_ID ?? process.env.CI_PIPELINE_ID ?? `local-${Date.now()}`;
|
|
88
|
+
const actor = args.actor ?? process.env.GITHUB_ACTOR ?? process.env.GITLAB_USER_LOGIN ?? process.env.USER;
|
|
89
|
+
|
|
90
|
+
if (!gitSha) {
|
|
91
|
+
console.error(formatError({ message: "Could not resolve --git-sha (not in a git repo?) — pass it explicitly." }));
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
if (!actor) {
|
|
95
|
+
console.error(formatError({
|
|
96
|
+
message: "Could not resolve --actor from the environment",
|
|
97
|
+
hint: "Pass --actor explicitly, or set GITHUB_ACTOR / GITLAB_USER_LOGIN / USER.",
|
|
98
|
+
}));
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const timestamp = new Date().toISOString();
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const { commit, record } = await appendReleaseRecord({
|
|
106
|
+
component,
|
|
107
|
+
env: environment,
|
|
108
|
+
digest,
|
|
109
|
+
gitSha,
|
|
110
|
+
runId,
|
|
111
|
+
timestamp,
|
|
112
|
+
actor,
|
|
113
|
+
});
|
|
114
|
+
await pushLifecycle();
|
|
115
|
+
if (args.json) {
|
|
116
|
+
console.log(JSON.stringify(record, null, 2));
|
|
117
|
+
} else {
|
|
118
|
+
console.error(formatSuccess(
|
|
119
|
+
`Recorded release: ${formatBold(component)}@${environment} -> ${digest} (commit ${commit.slice(0, 7)})`,
|
|
120
|
+
));
|
|
121
|
+
}
|
|
122
|
+
return 0;
|
|
123
|
+
} catch (err) {
|
|
124
|
+
if (err instanceof InvalidReleaseRecordError) {
|
|
125
|
+
console.error(formatError({ message: err.message }));
|
|
126
|
+
return 1;
|
|
127
|
+
}
|
|
128
|
+
if (err instanceof StaleLifecycleBranchError) {
|
|
129
|
+
console.error(formatError({
|
|
130
|
+
message: err.message,
|
|
131
|
+
hint: `Pull and retry: \`git fetch origin chant/lifecycle:chant/lifecycle\` && \`chant components release ${environment} --component ${component} --digest ${digest}\`.`,
|
|
132
|
+
}));
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** One row of `chant components status` JSON output. */
|
|
140
|
+
interface StatusJsonRow {
|
|
141
|
+
component: string;
|
|
142
|
+
env: string;
|
|
143
|
+
recorded: {
|
|
144
|
+
digest: string;
|
|
145
|
+
gitSha: string;
|
|
146
|
+
runId: string;
|
|
147
|
+
timestamp: string;
|
|
148
|
+
actor: string;
|
|
149
|
+
} | null;
|
|
150
|
+
build: {
|
|
151
|
+
manifestDigest: string;
|
|
152
|
+
referrers: string[];
|
|
153
|
+
/** SBOM summary for this digest (#606), when one was generated and is discoverable — archive-carried or referrer-projected. `null` when neither source has one (e.g. the component opted out, or has no built artifact). */
|
|
154
|
+
sbom: { mediaType: string; packageCount?: number; generator?: string; source: string } | null;
|
|
155
|
+
/** This artifact's own honest, per-artifact reproducibility record (#614) — `null` when none is recorded. */
|
|
156
|
+
reproducibility: { basis: string; verifyBy?: string } | null;
|
|
157
|
+
} | null;
|
|
158
|
+
/**
|
|
159
|
+
* Component-level BOM aggregation summary (#614), when the recorded
|
|
160
|
+
* digest's build archive manifest is available — resolved from the
|
|
161
|
+
* persisted manifest store (#609, ../../lifecycle/build-ledger-store.ts)
|
|
162
|
+
* by digest. `null` when unavailable (no manifest was ever persisted for
|
|
163
|
+
* this digest — it predates #609, or was recorded via `chant components
|
|
164
|
+
* release` alone with no corresponding `chant build`/`run`) or when the
|
|
165
|
+
* manifest carries no BOM at all.
|
|
166
|
+
*/
|
|
167
|
+
componentBom: {
|
|
168
|
+
leaves: Array<{ path: string; bomKind: string; subjectDigest?: string; mediaType: string; packageCount?: number; generator?: string }>;
|
|
169
|
+
totalPackageCount: number;
|
|
170
|
+
isAssembly: boolean;
|
|
171
|
+
} | null;
|
|
172
|
+
reconciliation: string;
|
|
173
|
+
detail: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* chant components status [env] [--live] [--json] [--compare-to <env>]
|
|
178
|
+
*
|
|
179
|
+
* Answers "what's built" and "what's deployed where," joined by digest.
|
|
180
|
+
* Without `--live`, reports the release ledger alone (recorded vs unrecorded
|
|
181
|
+
* is meaningless without live evidence, so every recorded row reports
|
|
182
|
+
* `unknown` reconciliation — still useful as a pure ledger read). With
|
|
183
|
+
* `--live`, joins against `lifecycle diff --live` + ownership (reusing
|
|
184
|
+
* `buildChangeSet`, the same classification `lifecycle plan` already
|
|
185
|
+
* trusts) to flag unrecorded deploys and drift.
|
|
186
|
+
*
|
|
187
|
+
* Omitting `<env>` reports every environment that has release records.
|
|
188
|
+
* `--compare-to <env>` answers the single-query cross-environment question
|
|
189
|
+
* the epic names explicitly: "which build is in `<env>`, and is it the one
|
|
190
|
+
* tested in `<compare-to>`."
|
|
191
|
+
*/
|
|
192
|
+
export async function runComponentsStatus(ctx: CommandContext): Promise<number> {
|
|
193
|
+
const { args, plugins, serializers } = ctx;
|
|
194
|
+
const requestedEnv = args.extraPositional;
|
|
195
|
+
|
|
196
|
+
await fetchLifecycle();
|
|
197
|
+
|
|
198
|
+
const environments = requestedEnv ? [requestedEnv] : await listReleaseEnvironments();
|
|
199
|
+
if (environments.length === 0) {
|
|
200
|
+
console.error(formatWarning({
|
|
201
|
+
message: requestedEnv
|
|
202
|
+
? `No release records found for environment "${requestedEnv}"`
|
|
203
|
+
: "No release records found in any environment",
|
|
204
|
+
}));
|
|
205
|
+
return args.json ? (console.log(JSON.stringify([])), 0) : 0;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Discover components (best-effort) so a live/owned-but-never-recorded
|
|
209
|
+
// component still gets a row, not just those that appear in the ledger.
|
|
210
|
+
const { config } = await loadChantConfig(resolve("."));
|
|
211
|
+
const discovery = await discoverComponents(resolve(args.src ?? config.sourceDir ?? "."));
|
|
212
|
+
const allComponents = [...discovery.components.keys()];
|
|
213
|
+
|
|
214
|
+
// Component -> live entity/resource name(s) it owns (#598), when declared
|
|
215
|
+
// explicitly via `Component.liveNames`. Components with no `liveNames`
|
|
216
|
+
// simply have no entry here, so `liveEvidenceFromChangeSet` falls back to
|
|
217
|
+
// the name == entity join — no regression for the pilot components.
|
|
218
|
+
const liveNameMapping = new Map<string, string[] | undefined>();
|
|
219
|
+
for (const [name, discovered] of discovery.components) {
|
|
220
|
+
if (discovered.component.liveNames?.length) {
|
|
221
|
+
liveNameMapping.set(name, discovered.component.liveNames);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const allRows: StatusJsonRow[] = [];
|
|
226
|
+
const ledgerByEnv = new Map<string, Awaited<ReturnType<typeof readReleaseLedger>>>();
|
|
227
|
+
|
|
228
|
+
for (const environment of environments) {
|
|
229
|
+
const ledger = await readReleaseLedger(environment);
|
|
230
|
+
ledgerByEnv.set(environment, ledger);
|
|
231
|
+
if (ledger.malformed > 0) {
|
|
232
|
+
console.error(formatWarning({ message: `${environment}: skipped ${ledger.malformed} malformed ledger line(s)` }));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let liveEvidence;
|
|
236
|
+
if (args.live) {
|
|
237
|
+
const targetSerializers = serializers;
|
|
238
|
+
const buildResult = await build(resolve(args.src ?? config.sourceDir ?? "."), targetSerializers);
|
|
239
|
+
const merged: { env: string; entries: import("../../lifecycle/change-set").ChangeSetEntry[] } = { env: environment, entries: [] };
|
|
240
|
+
for (const plugin of plugins) {
|
|
241
|
+
if (!plugin.describeResources) continue;
|
|
242
|
+
const declared = new Set<string>();
|
|
243
|
+
const entities = new Map<string, { entityType: string; props: Record<string, unknown> }>();
|
|
244
|
+
for (const [name, entity] of buildResult.entities) {
|
|
245
|
+
if (entity.lexicon === plugin.name) {
|
|
246
|
+
declared.add(name);
|
|
247
|
+
entities.set(name, {
|
|
248
|
+
entityType: entity.entityType,
|
|
249
|
+
props: ("props" in entity && entity.props != null ? entity.props : {}) as Record<string, unknown>,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
let observedNow: Record<string, ResourceMetadata>;
|
|
254
|
+
try {
|
|
255
|
+
observedNow = await plugin.describeResources({ environment, buildOutput: "", entityNames: Array.from(declared), entities });
|
|
256
|
+
} catch (err) {
|
|
257
|
+
console.error(formatWarning({ message: `${plugin.name}: describeResources failed — ${err instanceof Error ? err.message : String(err)}` }));
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const cs = buildChangeSet(environment, { declared, observedNow, observedThen: undefined });
|
|
261
|
+
merged.entries.push(...cs.entries);
|
|
262
|
+
}
|
|
263
|
+
liveEvidence = liveEvidenceFromChangeSet(merged, liveNameMapping);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// #609: resolve the persisted build manifest behind each recorded digest
|
|
267
|
+
// (if any) so `build`/`componentBom` are real queries, not always null.
|
|
268
|
+
const buildsByDigest = new Map<string, BuildLedgerEntry>();
|
|
269
|
+
const componentBomByDigest = new Map<string, ComponentBomSummary>();
|
|
270
|
+
const recordedDigests = new Set(ledger.records.map((r) => r.digest));
|
|
271
|
+
for (const digest of recordedDigests) {
|
|
272
|
+
const manifest = await findBuildManifestByArtifactDigest(digest);
|
|
273
|
+
if (!manifest) continue;
|
|
274
|
+
|
|
275
|
+
const bom = componentBomSummary(manifest);
|
|
276
|
+
if (bom) componentBomByDigest.set(digest, bom);
|
|
277
|
+
|
|
278
|
+
const ledgerEntries = await buildLedgerEntries(manifest);
|
|
279
|
+
const entry = ledgerEntries.find((e) => e.digest === digest);
|
|
280
|
+
if (entry) buildsByDigest.set(digest, entry);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const rows = reconcileStatus(environment, ledger.records, {
|
|
284
|
+
liveEvidence,
|
|
285
|
+
allComponents,
|
|
286
|
+
buildsByDigest,
|
|
287
|
+
componentBomByDigest,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
for (const row of rows) {
|
|
291
|
+
allRows.push({
|
|
292
|
+
component: row.component,
|
|
293
|
+
env: row.env,
|
|
294
|
+
recorded: row.recorded
|
|
295
|
+
? {
|
|
296
|
+
digest: row.recorded.digest,
|
|
297
|
+
gitSha: row.recorded.gitSha,
|
|
298
|
+
runId: row.recorded.runId,
|
|
299
|
+
timestamp: row.recorded.timestamp,
|
|
300
|
+
actor: row.recorded.actor,
|
|
301
|
+
}
|
|
302
|
+
: null,
|
|
303
|
+
build: row.build
|
|
304
|
+
? {
|
|
305
|
+
manifestDigest: row.build.manifestDigest,
|
|
306
|
+
referrers: row.build.referrers.map((r) => r.kind),
|
|
307
|
+
sbom: row.build.sbom
|
|
308
|
+
? {
|
|
309
|
+
mediaType: row.build.sbom.mediaType,
|
|
310
|
+
packageCount: row.build.sbom.packageCount,
|
|
311
|
+
generator: row.build.sbom.generator,
|
|
312
|
+
source: row.build.sbom.source,
|
|
313
|
+
}
|
|
314
|
+
: null,
|
|
315
|
+
reproducibility: row.build.reproducibility
|
|
316
|
+
? { basis: row.build.reproducibility.basis, verifyBy: row.build.reproducibility.verifyBy }
|
|
317
|
+
: null,
|
|
318
|
+
}
|
|
319
|
+
: null,
|
|
320
|
+
componentBom: row.componentBom
|
|
321
|
+
? {
|
|
322
|
+
leaves: row.componentBom.leaves.map((l) => ({
|
|
323
|
+
path: l.path,
|
|
324
|
+
bomKind: l.bomKind,
|
|
325
|
+
subjectDigest: l.subjectDigest,
|
|
326
|
+
mediaType: l.mediaType,
|
|
327
|
+
packageCount: l.packageCount,
|
|
328
|
+
generator: l.generator,
|
|
329
|
+
})),
|
|
330
|
+
totalPackageCount: row.componentBom.totalPackageCount,
|
|
331
|
+
isAssembly: row.componentBom.isAssembly,
|
|
332
|
+
}
|
|
333
|
+
: null,
|
|
334
|
+
reconciliation: row.reconciliation,
|
|
335
|
+
detail: row.detail,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// `--compare-to` — single-query cross-env digest comparison, per component.
|
|
341
|
+
let comparisons: ReturnType<typeof compareAcrossEnvironments>[] | undefined;
|
|
342
|
+
if (args.compareTo && requestedEnv) {
|
|
343
|
+
const otherLedger = ledgerByEnv.get(args.compareTo) ?? (await readReleaseLedger(args.compareTo));
|
|
344
|
+
const componentsToCompare = new Set([...allRows.map((r) => r.component)]);
|
|
345
|
+
comparisons = [...componentsToCompare].sort().map((component) =>
|
|
346
|
+
compareAcrossEnvironments(
|
|
347
|
+
component,
|
|
348
|
+
{ name: requestedEnv, records: ledgerByEnv.get(requestedEnv)?.records ?? [] },
|
|
349
|
+
{ name: args.compareTo!, records: otherLedger.records },
|
|
350
|
+
),
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (args.json) {
|
|
355
|
+
console.log(JSON.stringify(comparisons ? { rows: allRows, comparisons } : allRows, null, 2));
|
|
356
|
+
return 0;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
console.log(
|
|
360
|
+
formatBold("COMPONENT".padEnd(24)) +
|
|
361
|
+
formatBold("ENV".padEnd(12)) +
|
|
362
|
+
formatBold("DIGEST".padEnd(20)) +
|
|
363
|
+
formatBold("STATUS".padEnd(14)) +
|
|
364
|
+
formatBold("DETAIL"),
|
|
365
|
+
);
|
|
366
|
+
console.log("-".repeat(110));
|
|
367
|
+
for (const row of allRows) {
|
|
368
|
+
const digestShort = row.recorded ? row.recorded.digest.slice(0, 19) : "-";
|
|
369
|
+
console.log(
|
|
370
|
+
row.component.padEnd(24) +
|
|
371
|
+
row.env.padEnd(12) +
|
|
372
|
+
digestShort.padEnd(20) +
|
|
373
|
+
row.reconciliation.padEnd(14) +
|
|
374
|
+
row.detail,
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (comparisons) {
|
|
379
|
+
console.log(`\n${formatBold(`Cross-check: ${requestedEnv} vs ${args.compareTo}`)}`);
|
|
380
|
+
for (const c of comparisons) {
|
|
381
|
+
const verdict = c.same ? "same build" : "DIFFERENT builds";
|
|
382
|
+
console.log(` ${c.component}: ${c.digestA ?? "(none)"} vs ${c.digestB ?? "(none)"} — ${verdict}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const unrecordedCount = allRows.filter((r) => r.reconciliation === "unrecorded").length;
|
|
387
|
+
const driftedCount = allRows.filter((r) => r.reconciliation === "drifted").length;
|
|
388
|
+
if (unrecordedCount === 0 && driftedCount === 0) {
|
|
389
|
+
console.error(formatSuccess(`No unrecorded deploys or drift across ${allRows.length} row(s)`));
|
|
390
|
+
} else {
|
|
391
|
+
console.error(formatWarning({ message: `${unrecordedCount} unrecorded, ${driftedCount} drifted` }));
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return 0;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** Fallback for `chant components` with no/unknown subcommand. */
|
|
398
|
+
export async function runComponentsUnknown(ctx: CommandContext): Promise<number> {
|
|
399
|
+
console.error(formatError({
|
|
400
|
+
message: `Unknown components subcommand: ${ctx.args.path}`,
|
|
401
|
+
hint: "Available: chant components status [env], chant components release <env>",
|
|
402
|
+
}));
|
|
403
|
+
return 1;
|
|
404
|
+
}
|
package/src/cli/handlers/dev.ts
CHANGED
|
@@ -46,10 +46,69 @@ export async function runDevCheckLexicon(ctx: CommandContext): Promise<number> {
|
|
|
46
46
|
return result.tier1Pass ? 0 : 1;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
export async function runDevSurfaceDiff(ctx: CommandContext): Promise<number> {
|
|
50
|
+
const dir = ctx.args.extraPositional ?? ".";
|
|
51
|
+
const { runSurfaceDiff, printSurfaceDiffResult } = await import("../commands/lexicon-surface-diff");
|
|
52
|
+
const result = await runSurfaceDiff({
|
|
53
|
+
lexiconDir: resolve(dir),
|
|
54
|
+
force: ctx.args.force,
|
|
55
|
+
verbose: ctx.args.verbose,
|
|
56
|
+
runExamples: ctx.args.runExamples,
|
|
57
|
+
pinnedDigestPath: ctx.args.pinnedDigest,
|
|
58
|
+
// --check never writes; it verifies the committed baseline is in sync.
|
|
59
|
+
updateSnapshot: ctx.args.check ? false : ctx.args.updateSnapshot,
|
|
60
|
+
bump: ctx.args.bump,
|
|
61
|
+
});
|
|
62
|
+
printSurfaceDiffResult(result, ctx.args.format === "json");
|
|
63
|
+
// --check: fail if regen failed OR the fresh surface drifted from the
|
|
64
|
+
// committed baseline (stale/hand-edited baseline, or pin bumped without
|
|
65
|
+
// updating it). Meaningful for pinned lexicons — a fresh regen at the pinned
|
|
66
|
+
// version must equal the baseline. #545.
|
|
67
|
+
if (ctx.args.check) {
|
|
68
|
+
if (!result.ok) return 1;
|
|
69
|
+
if (result.changed) {
|
|
70
|
+
console.error(
|
|
71
|
+
`Baseline out of sync: ${dir}/surface.snapshot.json differs from a fresh regen. ` +
|
|
72
|
+
`Re-baseline with: chant dev surface-diff ${dir} --update-snapshot --bump`,
|
|
73
|
+
);
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
return result.ok ? 0 : 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function runDevPinnedUpgrade(ctx: CommandContext): Promise<number> {
|
|
82
|
+
const dir = ctx.args.extraPositional ?? ".";
|
|
83
|
+
const { runPinnedUpgrade, printPinnedUpgradeResult } = await import("../commands/pinned-upgrade");
|
|
84
|
+
const result = await runPinnedUpgrade({
|
|
85
|
+
lexiconDir: resolve(dir),
|
|
86
|
+
force: ctx.args.force,
|
|
87
|
+
verbose: ctx.args.verbose,
|
|
88
|
+
});
|
|
89
|
+
printPinnedUpgradeResult(result, ctx.args.format === "json");
|
|
90
|
+
// Exit non-zero when the upstream query failed or the regen validation broke.
|
|
91
|
+
if (result.fetchError) return 1;
|
|
92
|
+
if (result.validation && !result.validation.ok) return 1;
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function runDevRollingUpgrade(ctx: CommandContext): Promise<number> {
|
|
97
|
+
const dir = ctx.args.extraPositional ?? ".";
|
|
98
|
+
const { runRollingUpgrade, printRollingUpgradeResult } = await import("../commands/lexicon-rolling-upgrade");
|
|
99
|
+
const result = await runRollingUpgrade({
|
|
100
|
+
lexiconDir: resolve(dir),
|
|
101
|
+
force: ctx.args.force,
|
|
102
|
+
verbose: ctx.args.verbose,
|
|
103
|
+
});
|
|
104
|
+
printRollingUpgradeResult(result, ctx.args.format === "json");
|
|
105
|
+
return result.validationOk ? 0 : 1;
|
|
106
|
+
}
|
|
107
|
+
|
|
49
108
|
export async function runDevUnknown(ctx: CommandContext): Promise<number> {
|
|
50
109
|
console.error(formatError({
|
|
51
110
|
message: `Unknown dev subcommand: ${ctx.args.path}`,
|
|
52
|
-
hint: "Available: chant dev generate, chant dev publish, chant dev onboard, chant dev check-lexicon",
|
|
111
|
+
hint: "Available: chant dev generate, chant dev publish, chant dev onboard, chant dev check-lexicon, chant dev surface-diff, chant dev pinned-upgrade, chant dev rolling-upgrade",
|
|
53
112
|
}));
|
|
54
113
|
return 1;
|
|
55
114
|
}
|
|
@@ -12,22 +12,67 @@ import { lintCommand } from "../commands/lint";
|
|
|
12
12
|
import { readFileSync } from "node:fs";
|
|
13
13
|
import { formatError, formatWarning, formatBold } from "../format";
|
|
14
14
|
import type { CommandContext } from "../registry";
|
|
15
|
+
import { computeComponentGraph } from "../../components/cli-support";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* `chant graph` — the Op dependency graph by default; `--stacks` renders the
|
|
18
19
|
* cross-stack apply-ordering graph (edges, order, waves) chant computes from
|
|
19
|
-
* cross-lexicon references; `--
|
|
20
|
-
*
|
|
20
|
+
* cross-lexicon references; `--components` (#560) renders the same
|
|
21
|
+
* order/waves shape for discovered `Component` declarations, from their
|
|
22
|
+
* `dependsOn`; `--format ir|mermaid` emits the lint-gated entity-graph IR (or
|
|
23
|
+
* a Mermaid flowchart of it) for diagrams (#493/#496).
|
|
21
24
|
*/
|
|
22
25
|
export async function runGraph(ctx: CommandContext): Promise<number> {
|
|
23
26
|
const viewFormats = ["ir", "mermaid", "dot", "layout"] as const;
|
|
24
27
|
if ((viewFormats as readonly string[]).includes(ctx.args.format)) {
|
|
25
28
|
return runGraphView(ctx, ctx.args.format as (typeof viewFormats)[number]);
|
|
26
29
|
}
|
|
30
|
+
if (ctx.args.components) return runComponentGraph(ctx);
|
|
27
31
|
if (ctx.args.stacks) return runStackGraph(ctx);
|
|
28
32
|
return runOpGraph();
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
/**
|
|
36
|
+
* `chant graph --components` (#560) — dependency order/waves for discovered
|
|
37
|
+
* `Component` declarations, mirroring `runStackGraph`'s presentation
|
|
38
|
+
* (waves top-to-bottom, consumer → producer edges) but sourced from
|
|
39
|
+
* `computeComponentGraph` (../../components/cli-support.ts), which resolves
|
|
40
|
+
* order purely from each component's flat `dependsOn` list — no AttrRef-style
|
|
41
|
+
* cross-lexicon inference needed, since a component's dependency is always
|
|
42
|
+
* an explicit name.
|
|
43
|
+
*/
|
|
44
|
+
async function runComponentGraph(ctx: CommandContext): Promise<number> {
|
|
45
|
+
const projectPath = resolve(ctx.args.path === "." ? "." : ctx.args.path);
|
|
46
|
+
const graph = await computeComponentGraph(projectPath);
|
|
47
|
+
|
|
48
|
+
if (!graph.success) {
|
|
49
|
+
console.error(formatError({ message: graph.error ?? "Failed to compute component graph" }));
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (ctx.args.json) {
|
|
54
|
+
console.log(JSON.stringify(graph, null, 2));
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (graph.order.length === 0) {
|
|
59
|
+
console.log("No components found");
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log(formatBold("Deploy order (waves apply top-to-bottom; a wave's components are parallel-safe):"));
|
|
64
|
+
graph.waves.forEach((wave, i) => console.log(` ${i + 1}. ${wave.join(", ")}`));
|
|
65
|
+
|
|
66
|
+
if (graph.edges.length > 0) {
|
|
67
|
+
console.log(formatBold("\nDependencies (consumer → producer):"));
|
|
68
|
+
for (const { from, to } of graph.edges) console.log(` ${from} → ${to}`);
|
|
69
|
+
} else {
|
|
70
|
+
console.log("\nNo cross-component dependencies — all components are independent.");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
31
76
|
/**
|
|
32
77
|
* `chant graph --format ir|mermaid|dot|layout` — build the graph IR (honouring
|
|
33
78
|
* `--detail`) and emit it as JSON, a Mermaid flowchart, Graphviz DOT, or node
|
package/src/cli/handlers/misc.ts
CHANGED
|
@@ -4,9 +4,10 @@ import { importCommand, importFromLive, printImportResult } from "../commands/im
|
|
|
4
4
|
import { auditCommand, printAuditResult, type AuditFormat, type AuditTier, type AuditFailOn } from "../commands/audit";
|
|
5
5
|
import type { ReportTheme } from "../../audit/report-html";
|
|
6
6
|
import type { ResourceSelector } from "../../lexicon";
|
|
7
|
-
import { formatError, formatSuccess, formatWarning } from "../format";
|
|
7
|
+
import { formatError, formatSuccess, formatWarning, formatBold } from "../format";
|
|
8
8
|
import type { CommandContext } from "../registry";
|
|
9
9
|
import { createRequire } from "module";
|
|
10
|
+
import { listComponents, describeComponent } from "../../components/cli-support";
|
|
10
11
|
|
|
11
12
|
const CHANT_VERSION: string = (() => {
|
|
12
13
|
try {
|
|
@@ -84,6 +85,30 @@ export async function runList(ctx: CommandContext): Promise<number> {
|
|
|
84
85
|
return 1;
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
// `chant list --components` (#560) surfaces discovered `Component`
|
|
89
|
+
// declarations instead of lexicon resources — a distinct entity kind (no
|
|
90
|
+
// `lexicon`/`entityType`), so it is a separate branch rather than folded
|
|
91
|
+
// into `listCommand`'s Declarable-shaped `ListEntity` rows.
|
|
92
|
+
if (args.components) {
|
|
93
|
+
const result = await listComponents(args.path);
|
|
94
|
+
if (!result.success) {
|
|
95
|
+
for (const e of result.errors) console.error(formatError({ message: e }));
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
if (listFormat === "json") {
|
|
99
|
+
console.log(JSON.stringify(result.components, null, 2));
|
|
100
|
+
} else if (result.components.length === 0) {
|
|
101
|
+
console.log("No components found.");
|
|
102
|
+
} else {
|
|
103
|
+
console.log(formatBold("NAME") + " " + formatBold("ARCHETYPE") + " " + formatBold("DEPENDS ON") + " " + formatBold("PHASES"));
|
|
104
|
+
for (const c of result.components) {
|
|
105
|
+
console.log(`${c.name} ${c.archetype} ${c.dependsOn.join(", ") || "-"} ${c.phases.join(", ")}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
console.error(formatSuccess(`Found ${formatBold(String(result.components.length))} component(s)`));
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
87
112
|
const result = await listCommand({
|
|
88
113
|
path: args.path,
|
|
89
114
|
format: listFormat,
|
|
@@ -112,6 +137,25 @@ export async function runDescribe(ctx: CommandContext): Promise<number> {
|
|
|
112
137
|
return 1;
|
|
113
138
|
}
|
|
114
139
|
|
|
140
|
+
// `chant describe <name> --components` (#560): describe a discovered
|
|
141
|
+
// `Component` (its full JSON contract projection) rather than a lexicon
|
|
142
|
+
// resource's resolved props bag.
|
|
143
|
+
if (args.components) {
|
|
144
|
+
const result = await describeComponent(args.extraPositional ?? ".", component);
|
|
145
|
+
if (!result.success || !result.described) {
|
|
146
|
+
console.log(result.output);
|
|
147
|
+
return 1;
|
|
148
|
+
}
|
|
149
|
+
if (describeFormat === "json") {
|
|
150
|
+
console.log(JSON.stringify(result.described.json, null, 2));
|
|
151
|
+
} else {
|
|
152
|
+
console.log(`${formatBold(result.described.name)} (${result.described.filePath})`);
|
|
153
|
+
console.log(JSON.stringify(result.described.json, null, 2));
|
|
154
|
+
}
|
|
155
|
+
console.error(formatSuccess(`Described ${formatBold(component)}`));
|
|
156
|
+
return 0;
|
|
157
|
+
}
|
|
158
|
+
|
|
115
159
|
const result = await describeCommand({
|
|
116
160
|
component,
|
|
117
161
|
path: args.extraPositional ?? ".",
|