@intentius/chant 0.124.13 → 0.124.15
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/bin/chant +11 -0
- package/dist/agents/checks.js +326 -0
- package/dist/agents/discover.js +885 -0
- package/dist/agents/importer.js +17 -0
- package/dist/agents/index.js +12 -0
- package/dist/agents/types.js +19 -0
- package/dist/apply.js +151 -0
- package/dist/attrref.js +70 -0
- package/dist/audit/catalog.js +350 -0
- package/dist/audit/core.js +252 -0
- package/dist/audit/discover.js +633 -0
- package/dist/audit/fetch.js +666 -0
- package/dist/audit/lineage.js +91 -0
- package/dist/audit/nginx.js +366 -0
- package/dist/audit/prior-art.js +132 -0
- package/dist/audit/proof.js +321 -0
- package/dist/audit/report-html.js +194 -0
- package/dist/audit/report-model.js +198 -0
- package/dist/audit/report.js +102 -0
- package/dist/audit/rules-doc.js +144 -0
- package/dist/audit/secrets.js +405 -0
- package/dist/audit/terraform-state.js +140 -0
- package/dist/audit/wrangler.js +262 -0
- package/dist/behaviour-delta.js +401 -0
- package/dist/behaviour-engine.js +357 -0
- package/dist/behaviour-graph.js +83 -0
- package/dist/behaviour-http.js +188 -0
- package/dist/behaviour-kinds.js +172 -0
- package/dist/behaviour-overlay.js +50 -0
- package/dist/behaviour-predict.js +188 -0
- package/dist/behaviour-request.js +194 -0
- package/dist/behaviour.js +1325 -0
- package/dist/build-params.js +108 -0
- package/dist/build.d.ts +6 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +669 -0
- package/dist/builder.js +44 -0
- package/dist/cdk/advise.js +30 -0
- package/dist/cdk/assembly.js +122 -0
- package/dist/cdk/graph.js +444 -0
- package/dist/cdk/tier-map.js +64 -0
- package/dist/cdk/types.js +24 -0
- package/dist/change-set.d.ts +24 -2
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +361 -0
- package/dist/child-project.js +21 -0
- package/dist/ci-jobs.d.ts +227 -0
- package/dist/ci-jobs.d.ts.map +1 -0
- package/dist/ci-jobs.js +448 -0
- package/dist/claimed-fields.js +135 -0
- package/dist/cli/build-options.js +70 -0
- package/dist/cli/build-params-cli.js +139 -0
- package/dist/cli/command-group.js +123 -0
- package/dist/cli/commands/audit-agents.js +326 -0
- package/dist/cli/commands/audit.js +571 -0
- package/dist/cli/commands/build.js +920 -0
- package/dist/cli/commands/carve-apply.js +153 -0
- package/dist/cli/commands/carve-bridge.js +201 -0
- package/dist/cli/commands/carve-emit.js +332 -0
- package/dist/cli/commands/carve-status.js +119 -0
- package/dist/cli/commands/carve.js +204 -0
- package/dist/cli/commands/check-lexicon-docs.js +79 -0
- package/dist/cli/commands/check-lexicon-examples.js +177 -0
- package/dist/cli/commands/check-lexicon-intrinsics.js +291 -0
- package/dist/cli/commands/check-lexicon-mcp.js +82 -0
- package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-plugin.js +104 -0
- package/dist/cli/commands/check-lexicon.js +766 -0
- package/dist/cli/commands/describe.js +85 -0
- package/dist/cli/commands/diff.js +175 -0
- package/dist/cli/commands/doctor.js +350 -0
- package/dist/cli/commands/import-agents.js +155 -0
- package/dist/cli/commands/import.js +670 -0
- package/dist/cli/commands/init-lexicon/templates/codegen.js +194 -0
- package/dist/cli/commands/init-lexicon/templates/docs.js +100 -0
- package/dist/cli/commands/init-lexicon/templates/examples.js +29 -0
- package/dist/cli/commands/init-lexicon/templates/lint.js +34 -0
- package/dist/cli/commands/init-lexicon/templates/lsp.js +37 -0
- package/dist/cli/commands/init-lexicon/templates/plugin.js +108 -0
- package/dist/cli/commands/init-lexicon/templates/project.js +240 -0
- package/dist/cli/commands/init-lexicon/templates/spec.js +56 -0
- package/dist/cli/commands/init-lexicon/templates/tests.js +66 -0
- package/dist/cli/commands/init-lexicon.js +172 -0
- package/dist/cli/commands/init.js +381 -0
- package/dist/cli/commands/lexicon-rolling-upgrade.js +145 -0
- package/dist/cli/commands/lexicon-surface-diff.js +145 -0
- package/dist/cli/commands/licenses.js +125 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +948 -0
- package/dist/cli/commands/list.js +63 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +423 -0
- package/dist/cli/commands/onboard.js +403 -0
- package/dist/cli/commands/pinned-upgrade.js +191 -0
- package/dist/cli/commands/update.js +194 -0
- package/dist/cli/commands/vendor.js +217 -0
- package/dist/cli/conflict-check.js +104 -0
- package/dist/cli/debug.js +8 -0
- package/dist/cli/format.js +104 -0
- package/dist/cli/handlers/build.js +267 -0
- package/dist/cli/handlers/carve-apply.js +30 -0
- package/dist/cli/handlers/carve-bridge.js +28 -0
- package/dist/cli/handlers/carve-emit.js +50 -0
- package/dist/cli/handlers/carve-status.js +26 -0
- package/dist/cli/handlers/carve.js +40 -0
- package/dist/cli/handlers/change-set.js +46 -0
- package/dist/cli/handlers/components.js +730 -0
- package/dist/cli/handlers/dev.js +113 -0
- package/dist/cli/handlers/emulator.js +233 -0
- package/dist/cli/handlers/explain.js +54 -0
- package/dist/cli/handlers/fan-out.js +422 -0
- package/dist/cli/handlers/gate-resume.js +275 -0
- package/dist/cli/handlers/generate.js +84 -0
- package/dist/cli/handlers/graph.js +969 -0
- package/dist/cli/handlers/init.js +102 -0
- package/dist/cli/handlers/lifecycle.js +1727 -0
- package/dist/cli/handlers/lint.js +62 -0
- package/dist/cli/handlers/migrate.js +48 -0
- package/dist/cli/handlers/misc.js +391 -0
- package/dist/cli/handlers/operator.js +1162 -0
- package/dist/cli/handlers/override-approve.js +102 -0
- package/dist/cli/handlers/pr.js +503 -0
- package/dist/cli/handlers/promote.js +342 -0
- package/dist/cli/handlers/run-generate.js +206 -0
- package/dist/cli/handlers/run-wave.js +66 -0
- package/dist/cli/handlers/run.js +1191 -0
- package/dist/cli/handlers/scenario.js +325 -0
- package/dist/cli/handlers/search.js +924 -0
- package/dist/cli/handlers/serve.js +32 -0
- package/dist/cli/handlers/vendor.js +154 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli/is-entry-point.js +23 -0
- package/dist/cli/lsp/capabilities.js +28 -0
- package/dist/cli/lsp/diagnostics.js +34 -0
- package/dist/cli/lsp/server.js +329 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +2540 -0
- package/dist/cli/mcp/lifecycle-tools.js +80 -0
- package/dist/cli/mcp/op-tools.js +306 -0
- package/dist/cli/mcp/resource-handlers.js +258 -0
- package/dist/cli/mcp/resources/context.js +85 -0
- package/dist/cli/mcp/server.js +353 -0
- package/dist/cli/mcp/tools/build.js +111 -0
- package/dist/cli/mcp/tools/composites.js +95 -0
- package/dist/cli/mcp/tools/explain.js +166 -0
- package/dist/cli/mcp/tools/import.js +49 -0
- package/dist/cli/mcp/tools/lint.js +41 -0
- package/dist/cli/mcp/tools/scaffold.js +111 -0
- package/dist/cli/mcp/tools/search.js +112 -0
- package/dist/cli/mcp/types.js +1 -0
- package/dist/cli/mcp/workspace-plugins.js +91 -0
- package/dist/cli/mcp/workspace-tools.d.ts +1 -1
- package/dist/cli/mcp/workspace-tools.js +564 -0
- package/dist/cli/mcp-config.js +70 -0
- package/dist/cli/plugins.js +313 -0
- package/dist/cli/registry.js +23 -0
- package/dist/cli/reporters/stylish.js +329 -0
- package/dist/cli/version.js +15 -0
- package/dist/cli/watch.js +79 -0
- package/dist/codegen/bound-property-types.js +82 -0
- package/dist/codegen/coverage.js +119 -0
- package/dist/codegen/docs-file-markers.js +60 -0
- package/dist/codegen/docs-pages.js +115 -0
- package/dist/codegen/docs-rule-scanning.js +164 -0
- package/dist/codegen/docs-rules.js +76 -0
- package/dist/codegen/docs-sections.js +117 -0
- package/dist/codegen/docs-sidebar.js +65 -0
- package/dist/codegen/docs-types.js +4 -0
- package/dist/codegen/docs.js +356 -0
- package/dist/codegen/fetch.js +340 -0
- package/dist/codegen/generate-post-synth-barrel.js +63 -0
- package/dist/codegen/generate-registry.js +71 -0
- package/dist/codegen/generate-runtime-index.js +56 -0
- package/dist/codegen/generate-typescript.js +119 -0
- package/dist/codegen/generate.js +115 -0
- package/dist/codegen/json-patch.js +141 -0
- package/dist/codegen/json-schema-to-ts.js +344 -0
- package/dist/codegen/json-schema.js +246 -0
- package/dist/codegen/lexicon-regen.js +412 -0
- package/dist/codegen/naming.js +217 -0
- package/dist/codegen/okf-lexicon.js +245 -0
- package/dist/codegen/package.js +150 -0
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
- package/dist/codegen/pinned-upgrade.js +494 -0
- package/dist/codegen/registry.js +60 -0
- package/dist/codegen/rehype-base-url.mjs +68 -0
- package/dist/codegen/rolling-upgrade.js +217 -0
- package/dist/codegen/surface-snapshot.js +537 -0
- package/dist/codegen/testdata/postgres-tags.json +242 -0
- package/dist/codegen/topo-sort.js +36 -0
- package/dist/codegen/typecheck.js +115 -0
- package/dist/codegen/validate.js +200 -0
- package/dist/codegen/version-bump.js +35 -0
- package/dist/components/auto-release.js +143 -0
- package/dist/components/builders.js +47 -0
- package/dist/components/capability-plugin-loader.js +175 -0
- package/dist/components/capability-plugin-schema.js +46 -0
- package/dist/components/capability-plugin.js +99 -0
- package/dist/components/capability.js +60 -0
- package/dist/components/changed-files.js +72 -0
- package/dist/components/cli-support.js +427 -0
- package/dist/components/component.js +120 -0
- package/dist/components/component.schema.json +271 -0
- package/dist/components/config-defaults.js +130 -0
- package/dist/components/deploy-units.js +60 -0
- package/dist/components/discover.d.ts.map +1 -1
- package/dist/components/discover.js +189 -0
- package/dist/components/driver-output.js +86 -0
- package/dist/components/driver.js +728 -0
- package/dist/components/fan-out-output.js +165 -0
- package/dist/components/fan-out-record.js +94 -0
- package/dist/components/fan-out-run.js +373 -0
- package/dist/components/fan-out-support.js +60 -0
- package/dist/components/fan-out.js +273 -0
- package/dist/components/gate-plan.js +41 -0
- package/dist/components/gated-wave-pipeline.js +46 -0
- package/dist/components/index.js +24 -0
- package/dist/components/layers.js +28 -0
- package/dist/components/manifest-persistence.js +108 -0
- package/dist/components/pilots/alb-ecs.pilot.js +59 -0
- package/dist/components/pilots/dynamodb.pilot.js +51 -0
- package/dist/components/pilots/jar-emr.pilot.js +65 -0
- package/dist/components/pilots/lambda.pilot.js +52 -0
- package/dist/components/pilots/neo4j-fanout.pilot.js +68 -0
- package/dist/components/pilots/project.js +12 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +135 -0
- package/dist/components/pr-run.js +363 -0
- package/dist/components/presets/ecs-fargate.js +72 -0
- package/dist/components/presets/index.js +28 -0
- package/dist/components/presets/lambda.js +34 -0
- package/dist/components/presets/single-host-compose.js +41 -0
- package/dist/components/promote.js +549 -0
- package/dist/components/registry.js +34 -0
- package/dist/components/run-progress.js +33 -0
- package/dist/components/sandbox/driver.d.ts.map +1 -1
- package/dist/components/sandbox/driver.js +93 -0
- package/dist/components/sandbox/run.js +115 -0
- package/dist/components/starter-plugin.js +104 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.js +68 -0
- package/dist/components/verbs/__tests__/mock-process-runner.js +45 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.js +56 -0
- package/dist/components/verbs/bom-writer.js +287 -0
- package/dist/components/verbs/build-archive.js +188 -0
- package/dist/components/verbs/build.js +142 -0
- package/dist/components/verbs/cloud-executor.js +110 -0
- package/dist/components/verbs/component-bom.js +125 -0
- package/dist/components/verbs/ensure-secret.js +50 -0
- package/dist/components/verbs/index.js +61 -0
- package/dist/components/verbs/license-policy.js +75 -0
- package/dist/components/verbs/lockfile-sbom-generator.js +191 -0
- package/dist/components/verbs/process-runner.js +78 -0
- package/dist/components/verbs/r2-sync.js +93 -0
- package/dist/components/verbs/reproducibility.js +62 -0
- package/dist/components/verbs/run-agent.js +577 -0
- package/dist/components/verbs/sbom-generator.js +119 -0
- package/dist/components/verbs/sbom.js +97 -0
- package/dist/components/verbs/shell.js +32 -0
- package/dist/components/verbs/sign.js +221 -0
- package/dist/components/verbs/stub.js +28 -0
- package/dist/components/verbs/tool-sbom-generator.js +154 -0
- package/dist/components/verbs/verify.js +112 -0
- package/dist/components/verbs/vex.js +131 -0
- package/dist/components/verbs/vuln-gate.js +152 -0
- package/dist/components/verbs/vuln-scan.js +288 -0
- package/dist/components/verbs/wait-verify.js +106 -0
- package/dist/components/verbs/wrangler.js +179 -0
- package/dist/components/wave-plan.js +102 -0
- package/dist/composite.d.ts +10 -2
- package/dist/composite.d.ts.map +1 -1
- package/dist/composite.js +313 -0
- package/dist/config-import.d.ts.map +1 -1
- package/dist/config-import.js +22 -0
- package/dist/config-sandbox.js +122 -0
- package/dist/config-static.js +206 -0
- package/dist/config.js +605 -0
- package/dist/content-digest.js +23 -0
- package/dist/declarable.js +114 -0
- package/dist/deep-observation.js +437 -0
- package/dist/detectLexicon.js +54 -0
- package/dist/discovery/cache.js +70 -0
- package/dist/discovery/collect.d.ts +2 -1
- package/dist/discovery/collect.d.ts.map +1 -1
- package/dist/discovery/collect.js +223 -0
- package/dist/discovery/cycles.js +95 -0
- package/dist/discovery/entity-wire-codec.js +391 -0
- package/dist/discovery/entity-wire.js +42 -0
- package/dist/discovery/files.js +121 -0
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/fold-import.js +4073 -0
- package/dist/discovery/fold-rank.js +292 -0
- package/dist/discovery/graph.js +115 -0
- package/dist/discovery/host-composite.d.ts +35 -0
- package/dist/discovery/host-composite.d.ts.map +1 -0
- package/dist/discovery/host-composite.js +93 -0
- package/dist/discovery/import.d.ts.map +1 -1
- package/dist/discovery/import.js +65 -0
- package/dist/discovery/index.d.ts +9 -0
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/index.js +333 -0
- package/dist/discovery/param-deps.js +487 -0
- package/dist/discovery/resolve.js +39 -0
- package/dist/discovery/sandbox/bundle.js +214 -0
- package/dist/discovery/sandbox/child-errors.js +26 -0
- package/dist/discovery/sandbox/config-run.js +100 -0
- package/dist/discovery/sandbox/config-wire.js +183 -0
- package/dist/discovery/sandbox/driver.d.ts.map +1 -1
- package/dist/discovery/sandbox/driver.js +333 -0
- package/dist/discovery/sandbox/fork.js +229 -0
- package/dist/discovery/sandbox/policy-run.js +142 -0
- package/dist/discovery/sandbox/policy-wire.js +152 -0
- package/dist/discovery/sandbox/run.js +77 -0
- package/dist/discovery/specifier-resolve.js +320 -0
- package/dist/discovery/walk.js +284 -0
- package/dist/effect-receipt.js +340 -0
- package/dist/env.js +55 -0
- package/dist/errors.js +62 -0
- package/dist/fold/fold.js +1434 -0
- package/dist/fold/foldable-helpers.js +229 -0
- package/dist/fold/subset.js +696 -0
- package/dist/fold-provenance.js +414 -0
- package/dist/gate-decision.d.ts +20 -9
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +313 -0
- package/dist/gate-resume-run.js +154 -0
- package/dist/gated-waves.js +165 -0
- package/dist/governance.js +43 -0
- package/dist/graph-declared.js +45 -0
- package/dist/graph-detail.js +207 -0
- package/dist/graph-dot.js +54 -0
- package/dist/graph-effective.js +107 -0
- package/dist/graph-ir.js +623 -0
- package/dist/graph-layout.js +184 -0
- package/dist/graph-lens.js +105 -0
- package/dist/graph-mermaid.js +83 -0
- package/dist/graph-ops.js +39 -0
- package/dist/graph-refs.js +156 -0
- package/dist/held-elsewhere.js +87 -0
- package/dist/identity.js +251 -0
- package/dist/import/base-parser.js +34 -0
- package/dist/import/embedded.js +255 -0
- package/dist/import/generator.js +1 -0
- package/dist/import/ir-utils.js +85 -0
- package/dist/import/parser-options.js +45 -0
- package/dist/import/parser.js +1 -0
- package/dist/index.js +118 -0
- package/dist/intrinsic-interpolation.js +73 -0
- package/dist/intrinsic.js +31 -0
- package/dist/join-key.js +35 -0
- package/dist/kubectl-context.js +150 -0
- package/dist/lexicon-config.js +58 -0
- package/dist/lexicon-integrity.js +47 -0
- package/dist/lexicon-manifest.js +70 -0
- package/dist/lexicon-module.d.ts.map +1 -1
- package/dist/lexicon-module.js +241 -0
- package/dist/lexicon-output.js +218 -0
- package/dist/lexicon-plugin-helpers.js +104 -0
- package/dist/lexicon-schema.js +136 -0
- package/dist/lexicon.js +130 -0
- package/dist/lifecycle/affected.js +224 -0
- package/dist/lifecycle/assert-live.js +110 -0
- package/dist/lifecycle/build-ledger-store.js +160 -0
- package/dist/lifecycle/build-ledger.js +155 -0
- package/dist/lifecycle/change-set.js +356 -0
- package/dist/lifecycle/converge-ledger.js +161 -0
- package/dist/lifecycle/deep-diff.js +233 -0
- package/dist/lifecycle/deep-observe.js +147 -0
- package/dist/lifecycle/digest.js +143 -0
- package/dist/lifecycle/disruption.js +135 -0
- package/dist/lifecycle/gate-applied.js +113 -0
- package/dist/lifecycle/gate-audit.d.ts +69 -2
- package/dist/lifecycle/gate-audit.d.ts.map +1 -1
- package/dist/lifecycle/gate-audit.js +415 -0
- package/dist/lifecycle/gate-ledger-select.js +89 -0
- package/dist/lifecycle/gate-ledger.d.ts +24 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.js +201 -0
- package/dist/lifecycle/gate-origin.js +117 -0
- package/dist/lifecycle/gate-pending.js +58 -0
- package/dist/lifecycle/git.js +1182 -0
- package/dist/lifecycle/identity.js +58 -0
- package/dist/lifecycle/index.js +26 -0
- package/dist/lifecycle/lease.js +283 -0
- package/dist/lifecycle/ledger-port.js +1 -0
- package/dist/lifecycle/legacy-digest.js +91 -0
- package/dist/lifecycle/live-diff.js +274 -0
- package/dist/lifecycle/local-note.js +15 -0
- package/dist/lifecycle/member-ledger.js +122 -0
- package/dist/lifecycle/observation-baseline.js +155 -0
- package/dist/lifecycle/observe.js +375 -0
- package/dist/lifecycle/oras-referrer-lookup.js +82 -0
- package/dist/lifecycle/override-ledger.js +54 -0
- package/dist/lifecycle/plan-digest.js +110 -0
- package/dist/lifecycle/plan-ledger.js +129 -0
- package/dist/lifecycle/receipt-plan.js +192 -0
- package/dist/lifecycle/release-ledger.js +155 -0
- package/dist/lifecycle/release-read.js +64 -0
- package/dist/lifecycle/replay.js +193 -0
- package/dist/lifecycle/rollback.js +102 -0
- package/dist/lifecycle/run-ledger.js +183 -0
- package/dist/lifecycle/scenario-eval.js +204 -0
- package/dist/lifecycle/scenario.js +214 -0
- package/dist/lifecycle/snapshot.js +239 -0
- package/dist/lifecycle/status.js +447 -0
- package/dist/lifecycle/symptoms.js +117 -0
- package/dist/lifecycle/teardown.js +255 -0
- package/dist/lifecycle/types.js +1 -0
- package/dist/lifecycle/unobserved-gate.js +33 -0
- package/dist/lifecycle/wave-plans.js +68 -0
- package/dist/lifecycle/work-item-id.js +36 -0
- package/dist/lifecycle/work-lease.js +393 -0
- package/dist/lint/component-checks.js +87 -0
- package/dist/lint/config.js +483 -0
- package/dist/lint/declarative.js +122 -0
- package/dist/lint/discover.d.ts.map +1 -1
- package/dist/lint/discover.js +138 -0
- package/dist/lint/engine.js +246 -0
- package/dist/lint/knowledge-checks.js +64 -0
- package/dist/lint/named-checks.js +22 -0
- package/dist/lint/output-checks.js +87 -0
- package/dist/lint/output-docs.js +163 -0
- package/dist/lint/parser.js +33 -0
- package/dist/lint/pipeline-change-gate.js +70 -0
- package/dist/lint/policy-import.d.ts +1 -1
- package/dist/lint/policy-import.d.ts.map +1 -1
- package/dist/lint/policy-import.js +62 -0
- package/dist/lint/policy-sandbox.js +86 -0
- package/dist/lint/policy.js +122 -0
- package/dist/lint/post-synth.js +87 -0
- package/dist/lint/presets/relaxed.json +26 -0
- package/dist/lint/presets/strict.json +24 -24
- package/dist/lint/receipt-checks.js +83 -0
- package/dist/lint/rule-loader.d.ts.map +1 -1
- package/dist/lint/rule-loader.js +89 -0
- package/dist/lint/rule-registry.js +86 -0
- package/dist/lint/rule.js +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.js +7 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.js +7 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.js +9 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.js +11 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.js +9 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.js +25 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.js +21 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.js +24 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.js +17 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.js +18 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.js +20 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.js +12 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.js +16 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.js +12 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.js +11 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.js +11 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.js +10 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.js +16 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.js +69 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.js +84 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.js +103 -0
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.js +70 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.js +109 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.js +49 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.js +64 -0
- package/dist/lint/rules/comp/index.js +33 -0
- package/dist/lint/rules/comp/support.js +129 -0
- package/dist/lint/rules/composite-scope.js +51 -0
- package/dist/lint/rules/cor017-composite-name-match.js +93 -0
- package/dist/lint/rules/cor018-composite-prefer-lexicon-type.js +136 -0
- package/dist/lint/rules/cor021-env-literal-name.js +100 -0
- package/dist/lint/rules/cor022-receipt-leaf.js +118 -0
- package/dist/lint/rules/cor024-receipt-secret-pointer.js +199 -0
- package/dist/lint/rules/declarable-naming-convention.js +62 -0
- package/dist/lint/rules/evl001-non-literal-expression.js +66 -0
- package/dist/lint/rules/evl002-control-flow-resource.js +69 -0
- package/dist/lint/rules/evl003-dynamic-property-access.js +44 -0
- package/dist/lint/rules/evl004-spread-non-const.js +94 -0
- package/dist/lint/rules/evl005-resource-block-body.js +41 -0
- package/dist/lint/rules/evl007-invalid-siblings.js +105 -0
- package/dist/lint/rules/evl009-composite-no-constant.js +158 -0
- package/dist/lint/rules/evl010-composite-no-transform.js +59 -0
- package/dist/lint/rules/evl011-symbolic-in-template.js +106 -0
- package/dist/lint/rules/export-required.js +115 -0
- package/dist/lint/rules/file-declarable-limit.js +88 -0
- package/dist/lint/rules/flat-declarations.js +62 -0
- package/dist/lint/rules/index.js +90 -0
- package/dist/lint/rules/no-cyclic-declarable-ref.js +138 -0
- package/dist/lint/rules/no-redundant-type-import.js +76 -0
- package/dist/lint/rules/no-redundant-value-cast.js +41 -0
- package/dist/lint/rules/no-string-ref.js +59 -0
- package/dist/lint/rules/no-unused-declarable-import.js +75 -0
- package/dist/lint/rules/no-unused-declarable.js +142 -0
- package/dist/lint/rules/op/index.js +28 -0
- package/dist/lint/rules/op/ops012-activity-contract.js +54 -0
- package/dist/lint/rules/op/ops013-step-output-ref.js +88 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.js +114 -0
- package/dist/lint/rules/op/ops015-gate-approval.js +45 -0
- package/dist/lint/rules/op/support.js +11 -0
- package/dist/lint/rules/op/sys010-key-over-plain-http.js +100 -0
- package/dist/lint/rules/property-kind.js +56 -0
- package/dist/lint/rules/single-concern-file.js +71 -0
- package/dist/lint/rules/sys001-no-literal-key.js +60 -0
- package/dist/lint/selectors.js +168 -0
- package/dist/lint/suppressions.js +129 -0
- package/dist/lint/typescript.js +17 -0
- package/dist/live-endpoint.js +113 -0
- package/dist/live-read-session.js +76 -0
- package/dist/lsp/lexicon-providers.js +163 -0
- package/dist/lsp/types.js +5 -0
- package/dist/managed-fields.js +293 -0
- package/dist/mcp/types.js +4 -0
- package/dist/notify-verify.js +0 -1
- package/dist/notify.js +0 -1
- package/dist/notify.schema.json +72 -0
- package/dist/observation.js +266 -0
- package/dist/okf-read.js +134 -0
- package/dist/okf.js +275 -0
- package/dist/op/__fixtures__/decide-stub-backend.js +125 -0
- package/dist/op/activities/activity-contracts.d.ts +1 -1
- package/dist/op/activities/activity-contracts.js +313 -0
- package/dist/op/activities/apply.js +582 -0
- package/dist/op/activities/build.js +18 -0
- package/dist/op/activities/change-coverage.js +40 -0
- package/dist/op/activities/change-set.d.ts +8 -3
- package/dist/op/activities/change-set.d.ts.map +1 -1
- package/dist/op/activities/change-set.js +67 -0
- package/dist/op/activities/converge.js +492 -0
- package/dist/op/activities/decide.js +211 -0
- package/dist/op/activities/env-teardown.js +110 -0
- package/dist/op/activities/factory.js +591 -0
- package/dist/op/activities/forge-pull-request.js +82 -0
- package/dist/op/activities/gh-host.js +78 -0
- package/dist/op/activities/guard-validate.js +165 -0
- package/dist/op/activities/http-check.js +40 -0
- package/dist/op/activities/index.js +59 -0
- package/dist/op/activities/lexicon-upgrade.js +629 -0
- package/dist/op/activities/lifecycle.js +109 -0
- package/dist/op/activities/pipeline-audit.js +147 -0
- package/dist/op/activities/policy.js +26 -0
- package/dist/op/activities/predict-behaviour.js +341 -0
- package/dist/op/activities/propose-upgrade.js +165 -0
- package/dist/op/activities/reconcile.d.ts +28 -16
- package/dist/op/activities/reconcile.d.ts.map +1 -1
- package/dist/op/activities/reconcile.js +1011 -0
- package/dist/op/activities/shell.js +118 -0
- package/dist/op/activities/source-release.js +97 -0
- package/dist/op/activities/source-rollback.js +165 -0
- package/dist/op/activities/teardown.js +17 -0
- package/dist/op/activities/util.js +6 -0
- package/dist/op/activities/wait.js +51 -0
- package/dist/op/activities/work-evidence.js +35 -0
- package/dist/op/activities/workflow-audit.js +133 -0
- package/dist/op/activity-contract-registry.js +106 -0
- package/dist/op/activity-contract.js +232 -0
- package/dist/op/activity-failure.js +31 -0
- package/dist/op/activity-profiles.js +129 -0
- package/dist/op/activity-registry.js +105 -0
- package/dist/op/activity-runtime.js +28 -0
- package/dist/op/builders.d.ts +1 -1
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +801 -0
- package/dist/op/change-signal.js +118 -0
- package/dist/op/composites/apply-op.js +151 -0
- package/dist/op/composites/behaviour-op.js +65 -0
- package/dist/op/composites/converge-op.js +141 -0
- package/dist/op/composites/index.js +19 -0
- package/dist/op/composites/lexicon-upgrade-op.js +107 -0
- package/dist/op/composites/pipeline-audit-op.js +50 -0
- package/dist/op/composites/reconcile-op.js +84 -0
- package/dist/op/composites/watch-op.js +69 -0
- package/dist/op/composites/workflow-audit-op.js +57 -0
- package/dist/op/converge-rule.js +205 -0
- package/dist/op/cron.js +146 -0
- package/dist/op/decide-backend.js +181 -0
- package/dist/op/decide-config.js +68 -0
- package/dist/op/decide-read-inputs.js +141 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/discover.js +213 -0
- package/dist/op/duration.js +21 -0
- package/dist/op/emulator-freshness.js +80 -0
- package/dist/op/emulator-lifecycle.js +269 -0
- package/dist/op/factory.js +83 -0
- package/dist/op/gate-approval.js +172 -0
- package/dist/op/gate-name.js +86 -0
- package/dist/op/gate-plan-context.js +167 -0
- package/dist/op/gate-point-run.js +67 -0
- package/dist/op/gate-point.js +111 -0
- package/dist/op/gate-resume-plan.js +155 -0
- package/dist/op/gate-resume.js +31 -0
- package/dist/op/gate-review.js +290 -0
- package/dist/op/gate-run-locator.js +85 -0
- package/dist/op/gate-summary.js +100 -0
- package/dist/op/gate-wait.js +56 -0
- package/dist/op/gate.js +449 -0
- package/dist/op/generate-pipeline.js +124 -0
- package/dist/op/index.js +51 -0
- package/dist/op/lifecycle-receipt-store.js +45 -0
- package/dist/op/local-executor.js +1164 -0
- package/dist/op/local-output.js +140 -0
- package/dist/op/op-ir.js +317 -0
- package/dist/op/op-verb-class.js +131 -0
- package/dist/op/op-waves-notify.js +136 -0
- package/dist/op/op-waves-run.d.ts +1 -1
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +1657 -0
- package/dist/op/op-waves.js +409 -0
- package/dist/op/operator.js +743 -0
- package/dist/op/receipt-store.js +94 -0
- package/dist/op/resource.js +23 -0
- package/dist/op/run-context.js +28 -0
- package/dist/op/run-live.js +256 -0
- package/dist/op/runtime.js +21 -0
- package/dist/op/runtimes/local.js +195 -0
- package/dist/op/source-archive.js +131 -0
- package/dist/op/step-output-ref.js +397 -0
- package/dist/op/steward-beside.js +169 -0
- package/dist/op/steward-points.js +138 -0
- package/dist/op/steward-turn.js +59 -0
- package/dist/op/steward.js +317 -0
- package/dist/op/types.js +25 -0
- package/dist/op/work-lease-decl.js +81 -0
- package/dist/op/work-lease-run.js +393 -0
- package/dist/override-gate.js +284 -0
- package/dist/owner-chain.js +74 -0
- package/dist/ownership.js +92 -0
- package/dist/params.js +61 -0
- package/dist/plan-summary.js +711 -0
- package/dist/point-decision.js +211 -0
- package/dist/pr-forge.js +810 -0
- package/dist/pr-loop.js +203 -0
- package/dist/project-codegen.js +191 -0
- package/dist/project-root.js +74 -0
- package/dist/project-validation.js +50 -0
- package/dist/provenance.js +157 -0
- package/dist/pseudo-parameter.js +40 -0
- package/dist/reconcile.js +450 -0
- package/dist/resource-attributes.js +33 -0
- package/dist/runtime-adapter.js +77 -0
- package/dist/runtime.js +66 -0
- package/dist/secret-materialization.js +153 -0
- package/dist/secret-provenance.js +250 -0
- package/dist/serializer-walker.js +112 -0
- package/dist/serializer.js +1 -0
- package/dist/sort.js +45 -0
- package/dist/stack-output.js +115 -0
- package/dist/telemetry-attribution.js +149 -0
- package/dist/terraform/__fixtures__/build-graph.js +63 -0
- package/dist/terraform/adopt-state.js +40 -0
- package/dist/terraform/aws-resources.js +384 -0
- package/dist/terraform/bridge.js +204 -0
- package/dist/terraform/carve-provider.js +155 -0
- package/dist/terraform/carve.js +138 -0
- package/dist/terraform/data-source-shape.js +57 -0
- package/dist/terraform/emit-source.js +36 -0
- package/dist/terraform/excise.js +123 -0
- package/dist/terraform/graduate.js +128 -0
- package/dist/terraform/graph.js +435 -0
- package/dist/terraform/hcl2json.js +60 -0
- package/dist/terraform/manifest.js +149 -0
- package/dist/terraform/parse.js +81 -0
- package/dist/terraform/providers/aws.js +146 -0
- package/dist/terraform/providers/gcp.js +294 -0
- package/dist/terraform/providers/index.js +17 -0
- package/dist/terraform/providers/kubernetes.js +253 -0
- package/dist/terraform/score.js +151 -0
- package/dist/terraform/state.js +67 -0
- package/dist/terraform/tier-map.js +74 -0
- package/dist/terraform/types.js +13 -0
- package/dist/terraform/unified-diff.js +132 -0
- package/dist/testing.js +295 -0
- package/dist/toml-emit.js +153 -0
- package/dist/toml-parse.js +355 -0
- package/dist/toml-utils.js +60 -0
- package/dist/toml.js +428 -0
- package/dist/ts-loader.d.ts +46 -0
- package/dist/ts-loader.d.ts.map +1 -0
- package/dist/ts-loader.js +103 -0
- package/dist/types.js +1 -0
- package/dist/utils.js +61 -0
- package/dist/validation.js +20 -0
- package/dist/vendor/js-yaml-load.js +1662 -0
- package/dist/workspace/__fixtures__/contract-repo.d.ts +7 -0
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.js +119 -0
- package/dist/workspace/__fixtures__/decide-workspace.js +112 -0
- package/dist/workspace/__fixtures__/sessions.d.ts +1 -1
- package/dist/workspace/__fixtures__/sessions.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/sessions.js +91 -0
- package/dist/workspace/__fixtures__/two-member-workspace.js +34 -0
- package/dist/workspace/agent-cli.js +99 -0
- package/dist/workspace/agent.schema.json +390 -0
- package/dist/workspace/answers-ledger.js +89 -0
- package/dist/workspace/box-cli.js +142 -0
- package/dist/workspace/box-factory-write.js +196 -0
- package/dist/workspace/box-factory-write.schema.json +342 -0
- package/dist/workspace/box-factory.js +88 -0
- package/dist/workspace/box-intent.js +126 -0
- package/dist/workspace/box-isolation.js +169 -0
- package/dist/workspace/box-listing-write.schema.json +204 -0
- package/dist/workspace/box-listing.js +298 -0
- package/dist/workspace/box-publish.js +352 -0
- package/dist/workspace/box-publish.schema.json +498 -0
- package/dist/workspace/box-services.js +39 -0
- package/dist/workspace/broker-protocol.js +359 -0
- package/dist/workspace/broker-protocol.schema.json +228 -0
- package/dist/workspace/change-set.schema.json +462 -0
- package/dist/workspace/changes-cli.js +56 -0
- package/dist/workspace/changes.js +446 -0
- package/dist/workspace/changes.schema.json +642 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.js +198 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.js +155 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.js +214 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.js +180 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.js +99 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit.js +847 -0
- package/dist/workspace/chant-migrations.js +113 -0
- package/dist/workspace/check.schema.json +433 -0
- package/dist/workspace/checks/box-isolation.js +62 -0
- package/dist/workspace/checks/boxes.js +491 -0
- package/dist/workspace/checks/diagrams.js +104 -0
- package/dist/workspace/checks/generated.js +419 -0
- package/dist/workspace/checks/ledgers.js +212 -0
- package/dist/workspace/checks/links.js +191 -0
- package/dist/workspace/checks/live.js +100 -0
- package/dist/workspace/checks/pipelines.js +188 -0
- package/dist/workspace/checks/records.js +169 -0
- package/dist/workspace/checks.js +426 -0
- package/dist/workspace/ci-green-cli.js +125 -0
- package/dist/workspace/ci-green-forge.js +83 -0
- package/dist/workspace/ci-green-workflow.d.ts +3 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +202 -0
- package/dist/workspace/ci-green.js +325 -0
- package/dist/workspace/ci-last-green.schema.json +158 -0
- package/dist/workspace/class-data.d.ts +84 -0
- package/dist/workspace/class-data.d.ts.map +1 -0
- package/dist/workspace/class-data.js +238 -0
- package/dist/workspace/compose-graph.js +235 -0
- package/dist/workspace/compose-reports.js +146 -0
- package/dist/workspace/composites.js +264 -0
- package/dist/workspace/composites.schema.json +617 -0
- package/dist/workspace/conformance/__fixture__/app/package.json +7 -0
- package/dist/workspace/conformance/__fixture__/app/src/server.mjs +29 -0
- package/dist/workspace/conformance/__fixture__/decisions/decision.kind.mjs +54 -0
- package/dist/workspace/conformance/__fixture__/decisions/decision.schema.json +512 -0
- package/dist/workspace/conformance/__fixture__/decisions/fix-001-how-the-app-is-deployed.md +40 -0
- package/dist/workspace/conformance/__fixture__/delivery/chant.config.ts +7 -0
- package/dist/workspace/conformance/__fixture__/delivery/lexicon/index.ts +26 -0
- package/dist/workspace/conformance/__fixture__/delivery/package.json +7 -0
- package/dist/workspace/conformance/__fixture__/delivery/src/app.component.ts +14 -0
- package/dist/workspace/conformance/__fixture__/delivery/src/app.ts +4 -0
- package/dist/workspace/conformance/__fixtures__/reference-broker.js +205 -0
- package/dist/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
- package/dist/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
- package/dist/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
- package/dist/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
- package/dist/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
- package/dist/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
- package/dist/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
- package/dist/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
- package/dist/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
- package/dist/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
- package/dist/workspace/conformance/broker.js +736 -0
- package/dist/workspace/conformance/index.js +673 -0
- package/dist/workspace/conformance/vitest.js +108 -0
- package/dist/workspace/conformance/writer.js +1080 -0
- package/dist/workspace/decide.js +879 -0
- package/dist/workspace/decision-points.schema.json +135 -135
- package/dist/workspace/declaration-write-cli.js +74 -0
- package/dist/workspace/declaration-write.js +238 -0
- package/dist/workspace/declaration.js +938 -0
- package/dist/workspace/declaration.schema.json +1413 -1413
- package/dist/workspace/declared-kinds.js +106 -0
- package/dist/workspace/environments.js +164 -0
- package/dist/workspace/evidence.schema.json +279 -0
- package/dist/workspace/export-cli.js +185 -0
- package/dist/workspace/export.js +499 -0
- package/dist/workspace/factory-rules.js +175 -0
- package/dist/workspace/generated-files.js +92 -0
- package/dist/workspace/glob.js +45 -0
- package/dist/workspace/graph-cache.js +352 -0
- package/dist/workspace/graph-cli.js +348 -0
- package/dist/workspace/graph.schema.json +1338 -0
- package/dist/workspace/identity-gate-rule.js +75 -0
- package/dist/workspace/identity.js +126 -0
- package/dist/workspace/import.js +283 -0
- package/dist/workspace/init.js +620 -0
- package/dist/workspace/intent-cli.js +263 -0
- package/dist/workspace/intent-joins.js +201 -0
- package/dist/workspace/intent-record.js +352 -0
- package/dist/workspace/intent-record.schema.json +864 -0
- package/dist/workspace/intent.js +1582 -0
- package/dist/workspace/intent.schema.json +2420 -0
- package/dist/workspace/json-edit.js +221 -0
- package/dist/workspace/jsonc.js +235 -0
- package/dist/workspace/kind-readers.js +103 -0
- package/dist/workspace/kinds.d.ts +3 -7
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +553 -0
- package/dist/workspace/lexicon-symbols.js +112 -0
- package/dist/workspace/lineage-adopt-cli.js +102 -0
- package/dist/workspace/lineage-adopt.js +360 -0
- package/dist/workspace/lineage-check.js +282 -0
- package/dist/workspace/lineage-cli.js +121 -0
- package/dist/workspace/lineage-hash-index.js +284 -0
- package/dist/workspace/lineage-init.js +507 -0
- package/dist/workspace/lineage-lock.js +387 -0
- package/dist/workspace/lineage-merge.js +45 -0
- package/dist/workspace/lineage-migrations.d.ts.map +1 -1
- package/dist/workspace/lineage-migrations.js +329 -0
- package/dist/workspace/lineage-provenance.js +36 -0
- package/dist/workspace/lineage-update.js +138 -0
- package/dist/workspace/lineage-upgrade-cli.js +131 -0
- package/dist/workspace/lineage-upgrade.js +889 -0
- package/dist/workspace/lineage-vendor.js +171 -0
- package/dist/workspace/lineage-version.js +128 -0
- package/dist/workspace/lineage-versions.js +275 -0
- package/dist/workspace/links.js +330 -0
- package/dist/workspace/ls-generated.js +95 -0
- package/dist/workspace/ls.js +277 -0
- package/dist/workspace/ls.schema.json +333 -0
- package/dist/workspace/member-commands.js +508 -0
- package/dist/workspace/member-handles.js +216 -0
- package/dist/workspace/member-pipeline.js +258 -0
- package/dist/workspace/member-run.js +117 -0
- package/dist/workspace/member-write.schema.json +193 -0
- package/dist/workspace/nested-graph.js +156 -0
- package/dist/workspace/nesting.js +38 -0
- package/dist/workspace/patch.js +301 -0
- package/dist/workspace/patch.schema.json +321 -0
- package/dist/workspace/pin-cli.js +55 -0
- package/dist/workspace/pin-integrity.js +100 -0
- package/dist/workspace/plan-summary.schema.json +155 -0
- package/dist/workspace/point-answer.schema.json +129 -129
- package/dist/workspace/points-cli.js +291 -0
- package/dist/workspace/points-write.schema.json +660 -0
- package/dist/workspace/points.js +521 -0
- package/dist/workspace/points.schema.json +916 -0
- package/dist/workspace/pr-report.schema.json +108 -0
- package/dist/workspace/principal-classes.d.ts +4 -11
- package/dist/workspace/principal-classes.d.ts.map +1 -1
- package/dist/workspace/principal-classes.js +162 -0
- package/dist/workspace/reason-codes.js +326 -0
- package/dist/workspace/record-assets.js +151 -0
- package/dist/workspace/record-decided.js +105 -0
- package/dist/workspace/record-sessions.js +96 -0
- package/dist/workspace/record-source.js +114 -0
- package/dist/workspace/records-amend.schema.json +284 -0
- package/dist/workspace/records-checkout.js +76 -0
- package/dist/workspace/records-cli.js +707 -0
- package/dist/workspace/records-close.js +116 -0
- package/dist/workspace/records-close.schema.json +278 -0
- package/dist/workspace/records-new.schema.json +202 -0
- package/dist/workspace/records-review.schema.json +367 -0
- package/dist/workspace/records-since.js +317 -0
- package/dist/workspace/records-since.schema.json +218 -0
- package/dist/workspace/records-write.js +1229 -0
- package/dist/workspace/records.js +1345 -0
- package/dist/workspace/records.schema.json +604 -0
- package/dist/workspace/reference-kinds/app/package.json +10 -0
- package/dist/workspace/reference-kinds/app/workspace-kinds.json +45 -0
- package/dist/workspace/returns.js +303 -0
- package/dist/workspace/root-refusal.js +75 -0
- package/dist/workspace/run-statement.schema.json +622 -0
- package/dist/workspace/runs-cli.js +584 -0
- package/dist/workspace/runs-write.schema.json +994 -0
- package/dist/workspace/runs.js +708 -0
- package/dist/workspace/runs.schema.json +1257 -0
- package/dist/workspace/runtimes.js +76 -0
- package/dist/workspace/session-kinds.js +83 -0
- package/dist/workspace/signers.schema.json +206 -0
- package/dist/workspace/source-block.js +125 -0
- package/dist/workspace/squash.js +177 -0
- package/dist/workspace/status-gates.js +162 -0
- package/dist/workspace/status-stewards.js +330 -0
- package/dist/workspace/status.js +514 -0
- package/dist/workspace/status.schema.json +998 -0
- package/dist/workspace/steward-index.js +191 -0
- package/dist/workspace/symbols.js +188 -0
- package/dist/workspace/template-manifest.js +227 -0
- package/dist/workspace/template-pins.js +115 -0
- package/dist/workspace/trailer-joins.js +65 -0
- package/dist/workspace/trailers.js +111 -0
- package/dist/workspace/tree.js +136 -0
- package/dist/workspace/trust/attestor.js +63 -0
- package/dist/workspace/trust/dsse.js +108 -0
- package/dist/workspace/trust/evidence-cli.js +175 -0
- package/dist/workspace/trust/evidence.js +161 -0
- package/dist/workspace/trust/gate-seal.js +226 -0
- package/dist/workspace/trust/policy.js +190 -0
- package/dist/workspace/trust/provenance.js +180 -0
- package/dist/workspace/trust/rotation.js +298 -0
- package/dist/workspace/trust/run-commits.js +101 -0
- package/dist/workspace/trust/run-statement.js +182 -0
- package/dist/workspace/trust/seal.js +272 -0
- package/dist/workspace/trust/signers-cli.js +152 -0
- package/dist/workspace/trust/ssh-commit.js +178 -0
- package/dist/workspace/trust/test-repo.js +118 -0
- package/dist/workspace/trust/trust-files.js +193 -0
- package/dist/workspace/trust/verify-cli.js +63 -0
- package/dist/workspace/trust/verify.js +192 -0
- package/dist/workspace/which-chant.js +141 -0
- package/dist/workspace/wip-cli.js +95 -0
- package/dist/workspace/wip-write.schema.json +504 -0
- package/dist/workspace/wip.js +631 -0
- package/dist/workspace/wip.schema.json +334 -0
- package/dist/workspace/work-cli.js +448 -0
- package/dist/workspace/work-evidence.js +122 -0
- package/dist/workspace/work-evidence.schema.json +222 -0
- package/dist/workspace/work-history.schema.json +421 -0
- package/dist/workspace/work-lease.schema.json +246 -0
- package/dist/workspace/work-size.js +77 -0
- package/dist/workspace/work.js +283 -0
- package/dist/workspace/workspace-kinds.schema.json +259 -259
- package/dist/workspace/workspace-principals.schema.json +53 -53
- package/dist/workspace/write-lock-cli.js +105 -0
- package/dist/workspace/write-lock.js +424 -0
- package/dist/workspace/write-lock.schema.json +172 -0
- package/dist/workspace/write-scope.js +484 -0
- package/dist/yaml.js +459 -0
- package/package.json +2 -2
- package/src/build.ts +8 -0
- package/src/change-set.test.ts +48 -0
- package/src/change-set.ts +52 -2
- package/src/ci-jobs.test.ts +49 -0
- package/src/ci-jobs.ts +515 -0
- package/src/cli/commands/check-lexicon-plugin.ts +2 -0
- package/src/cli/commands/lint.ts +3 -0
- package/src/cli/commands/migrate.ts +2 -0
- package/src/cli/compiled-cli.e2e.test.ts +165 -0
- package/src/cli/main.ts +121 -27
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/codegen/pinned-upgrade.ts +2 -0
- package/src/components/discover.ts +2 -0
- package/src/components/pr-pipeline.ts +3 -2
- package/src/components/sandbox/driver.ts +3 -1
- package/src/composite.ts +15 -3
- package/src/config-import.ts +3 -0
- package/src/discovery/collect.ts +15 -1
- package/src/discovery/fold-build-parity.test.ts +71 -0
- package/src/discovery/fold-import.ts +25 -127
- package/src/discovery/fold-project-provenance.test.ts +21 -4
- package/src/discovery/host-composite.ts +101 -0
- package/src/discovery/import.ts +2 -0
- package/src/discovery/index.ts +11 -1
- package/src/discovery/sandbox/driver.ts +3 -1
- package/src/gate-decision-bundle.test.ts +5 -4
- package/src/gate-decision-identity.test.ts +59 -6
- package/src/gate-decision.ts +81 -21
- package/src/lexicon-module.ts +3 -0
- package/src/lifecycle/gate-audit.test.ts +55 -1
- package/src/lifecycle/gate-audit.ts +116 -3
- package/src/lifecycle/gate-ledger.test.ts +20 -1
- package/src/lifecycle/gate-ledger.ts +33 -1
- package/src/lint/config.ts +1 -1
- package/src/lint/discover.ts +28 -8
- package/src/lint/policy-import.ts +4 -1
- package/src/lint/rule-loader.ts +2 -0
- package/src/op/activities/activity-contracts.ts +1 -1
- package/src/op/activities/change-set.ts +11 -3
- package/src/op/activities/lexicon-upgrade.test.ts +2 -0
- package/src/op/activities/reconcile.test.ts +62 -2
- package/src/op/activities/reconcile.ts +46 -22
- package/src/op/builders.ts +1 -1
- package/src/op/discover.ts +3 -0
- package/src/op/op-waves-run.ts +4 -3
- package/src/op/op-waves.test.ts +2 -0
- package/src/op/work-lease-run.test.ts +12 -4
- package/src/ts-loader.test.ts +23 -0
- package/src/ts-loader.ts +122 -0
- package/src/workspace/__fixtures__/contract-repo.ts +17 -1
- package/src/workspace/__fixtures__/sessions.ts +3 -3
- package/src/workspace/change-set.schema.json +5 -3
- package/src/workspace/chant-migrations/chud-lexicon-exit.ts +1 -1
- package/src/workspace/ci-green-workflow.test.ts +4 -4
- package/src/workspace/ci-green-workflow.ts +5 -2
- package/src/workspace/class-data.test.ts +64 -0
- package/src/workspace/class-data.ts +236 -0
- package/src/workspace/declaration.ts +1 -1
- package/src/workspace/kinds.ts +7 -36
- package/src/workspace/lineage-migrations.ts +2 -0
- package/src/workspace/points.ts +1 -1
- package/src/workspace/principal-classes.ts +12 -95
- package/src/workspace/records-formats.test.ts +7 -2
- package/src/workspace/records-sessions-write.test.ts +3 -3
- package/src/workspace/status-contract.e2e.test.ts +37 -0
- package/src/workspace/status-contract.test.ts +23 -21
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote fetch — pull a repo's candidate files (all lexicons) from a git host so
|
|
3
|
+
* the auditor can run on a URL, not just a local path. This is the ONLY audit
|
|
4
|
+
* module that touches the network; the core stays pure.
|
|
5
|
+
*
|
|
6
|
+
* SSRF posture: only an allowlisted set of hosts is accepted; request URLs are
|
|
7
|
+
* built from the parsed owner/repo (never a user-controlled host); redirects
|
|
8
|
+
* are refused; and file count / size / total bytes / time are all capped.
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULTS = {
|
|
11
|
+
maxFiles: 50,
|
|
12
|
+
maxBytesPerFile: 256 * 1024,
|
|
13
|
+
maxTotalBytes: 2 * 1024 * 1024,
|
|
14
|
+
timeoutMs: 10000,
|
|
15
|
+
};
|
|
16
|
+
const ALLOWED_HOSTS = {
|
|
17
|
+
"github.com": { kind: "github", api: "https://api.github.com", lexicon: "github" },
|
|
18
|
+
"codeberg.org": { kind: "forgejo", api: "https://codeberg.org/api/v1", lexicon: "forgejo" },
|
|
19
|
+
"gitlab.com": { kind: "gitlab", api: "https://gitlab.com/api/v4", lexicon: "gitlab" },
|
|
20
|
+
};
|
|
21
|
+
export class FetchError extends Error {
|
|
22
|
+
}
|
|
23
|
+
/** Parse and validate a repo URL against the host allowlist (SSRF guard). */
|
|
24
|
+
export function parseRepoUrl(url) {
|
|
25
|
+
let u;
|
|
26
|
+
try {
|
|
27
|
+
u = new URL(url);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new FetchError(`Invalid URL: ${url}`);
|
|
31
|
+
}
|
|
32
|
+
if (u.protocol !== "https:") {
|
|
33
|
+
throw new FetchError(`Only https:// URLs are allowed (got ${u.protocol}).`);
|
|
34
|
+
}
|
|
35
|
+
const host = ALLOWED_HOSTS[u.hostname];
|
|
36
|
+
if (!host) {
|
|
37
|
+
throw new FetchError(`Host not allowed: ${u.hostname}. Allowed: ${Object.keys(ALLOWED_HOSTS).join(", ")}.`);
|
|
38
|
+
}
|
|
39
|
+
const parts = u.pathname.replace(/^\/+/, "").split("/");
|
|
40
|
+
if (parts.length < 2 || !parts[0] || !parts[1]) {
|
|
41
|
+
throw new FetchError(`URL must be https://${u.hostname}/<owner>/<repo>.`);
|
|
42
|
+
}
|
|
43
|
+
return { host, owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
|
|
44
|
+
}
|
|
45
|
+
/** GitHub (and good manners) require a User-Agent — workerd's fetch sends none,
|
|
46
|
+
* so a missing UA 403s every request. Always set one, with or without a token. */
|
|
47
|
+
const USER_AGENT = "chant-audit (+https://github.com/intentius/chant)";
|
|
48
|
+
function authHeaders(kind, token) {
|
|
49
|
+
const base = { "User-Agent": USER_AGENT };
|
|
50
|
+
if (!token)
|
|
51
|
+
return base;
|
|
52
|
+
if (kind === "github")
|
|
53
|
+
return { ...base, Authorization: `Bearer ${token}` };
|
|
54
|
+
if (kind === "forgejo")
|
|
55
|
+
return { ...base, Authorization: `token ${token}` };
|
|
56
|
+
return { ...base, "PRIVATE-TOKEN": token };
|
|
57
|
+
}
|
|
58
|
+
function timeoutSignal(ms) {
|
|
59
|
+
return typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function"
|
|
60
|
+
? AbortSignal.timeout(ms)
|
|
61
|
+
: undefined;
|
|
62
|
+
}
|
|
63
|
+
// ── Whole-repo fetch (all lexicons, not just CI) ─────────────────────────────
|
|
64
|
+
// Mirrors the local walk: list the repo tree, keep candidate paths, fetch their
|
|
65
|
+
// contents (capped), and hand the raw {path, content} set to the shared
|
|
66
|
+
// classifier in discover.ts. SSRF posture is unchanged — allowlisted host,
|
|
67
|
+
// URLs built from parsed owner/repo, redirects refused, counts/bytes capped.
|
|
68
|
+
/** Module-level JSON GET that refuses redirects (reused by the tree-walk). */
|
|
69
|
+
async function getJsonAt(url, headers, doFetch, timeoutMs) {
|
|
70
|
+
let res;
|
|
71
|
+
try {
|
|
72
|
+
res = await doFetch(url, { headers, redirect: "manual", signal: timeoutSignal(timeoutMs) });
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
throw new FetchError(`Request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
}
|
|
77
|
+
if (res.status >= 300 && res.status < 400)
|
|
78
|
+
throw new FetchError(`Refusing to follow redirect from ${url}`);
|
|
79
|
+
if (res.status === 404)
|
|
80
|
+
return { status: 404, body: null };
|
|
81
|
+
if (!res.ok)
|
|
82
|
+
throw new FetchError(`${url} returned ${res.status}`);
|
|
83
|
+
return { status: res.status, body: await res.json() };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Like `getJsonAt`, but for search endpoints specifically: a 404 here means
|
|
87
|
+
* "this endpoint doesn't exist" (an unsupported/misconfigured search API — the
|
|
88
|
+
* real-world case for Forgejo, whose code-search availability is undocumented,
|
|
89
|
+
* #520), not "zero results" the way a missing *file* would be. Zero results are
|
|
90
|
+
* a 200 with an empty array/list, so treating 404 as an error (rather than
|
|
91
|
+
* `getJsonAt`'s "return null" leniency) lets a genuinely unsupported search API
|
|
92
|
+
* fall back to the walk instead of silently reporting no matches.
|
|
93
|
+
*/
|
|
94
|
+
async function getSearchJsonAt(url, headers, doFetch, timeoutMs) {
|
|
95
|
+
let res;
|
|
96
|
+
try {
|
|
97
|
+
res = await doFetch(url, { headers, redirect: "manual", signal: timeoutSignal(timeoutMs) });
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
throw new FetchError(`Request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
101
|
+
}
|
|
102
|
+
if (res.status >= 300 && res.status < 400)
|
|
103
|
+
throw new FetchError(`Refusing to follow redirect from ${url}`);
|
|
104
|
+
if (!res.ok)
|
|
105
|
+
throw new FetchError(`${url} returned ${res.status}`);
|
|
106
|
+
return res.json();
|
|
107
|
+
}
|
|
108
|
+
function projectId(owner, repo) {
|
|
109
|
+
return encodeURIComponent(`${owner}/${repo}`);
|
|
110
|
+
}
|
|
111
|
+
/** The repo's default branch, so the tree request has a concrete ref. */
|
|
112
|
+
async function defaultBranch(host, owner, repo, doFetch, headers, ms) {
|
|
113
|
+
const url = host.kind === "gitlab"
|
|
114
|
+
? `${host.api}/projects/${projectId(owner, repo)}`
|
|
115
|
+
: `${host.api}/repos/${owner}/${repo}`;
|
|
116
|
+
const { body } = await getJsonAt(url, headers, doFetch, ms);
|
|
117
|
+
const branch = body?.default_branch;
|
|
118
|
+
return branch && typeof branch === "string" ? branch : "HEAD";
|
|
119
|
+
}
|
|
120
|
+
// ── Search-first discovery for large repos (#520) ───────────────────────────
|
|
121
|
+
//
|
|
122
|
+
// A full tree walk + extension filter over-fetches badly on a large monorepo
|
|
123
|
+
// (thousands of `.yml`/`.json` candidates, almost all irrelevant) and still
|
|
124
|
+
// misses IaC/CI content living at non-canonical paths. Above a size threshold,
|
|
125
|
+
// switch from "walk everything `isCandidatePath` allows" to "search for each
|
|
126
|
+
// content-detected lexicon's characteristic signature, download only hits":
|
|
127
|
+
//
|
|
128
|
+
// - Known-path lexicons (github, forgejo, and gitlab's canonical file) never
|
|
129
|
+
// need a search query — their location is fixed, so a plain path/tree
|
|
130
|
+
// lookup already finds them for any repo size. GitHub/Forgejo Actions
|
|
131
|
+
// *must* live under `.github`/`.forgejo` workflows (the platform enforces
|
|
132
|
+
// it), so no search term is listed for them at all. GitLab's `include:`
|
|
133
|
+
// can pull in CI files from anywhere, so its canonical file is still
|
|
134
|
+
// backed by a `stages:` search term to catch those satellites (#518).
|
|
135
|
+
// - Content-detected lexicons (k8s, aws, azure, gcp, docker, helm) have no
|
|
136
|
+
// fixed path, so at scale the only cheap way to find them is a search for
|
|
137
|
+
// the grep-equivalent of their `detectTemplate` signature.
|
|
138
|
+
// - Search is additive, never load-bearing: any error, rate limit, or
|
|
139
|
+
// unsupported/unavailable API degrades to the walk rather than failing
|
|
140
|
+
// the audit.
|
|
141
|
+
/** Repos above this many tree entries switch from the walk to search-first
|
|
142
|
+
* discovery. Cheap to evaluate — it's the size of a call already being made
|
|
143
|
+
* (GitHub/Forgejo's one-shot recursive tree; GitLab's first root-tree page,
|
|
144
|
+
* see below) — and keeps small repos on the walk, which needs no search API
|
|
145
|
+
* at all and so works even where search is unavailable (e.g. a Forgejo
|
|
146
|
+
* instance with no code indexer). */
|
|
147
|
+
const LARGE_REPO_TREE_ENTRIES = 500;
|
|
148
|
+
/** How many result pages to pull per search term. GitLab's basic (non-
|
|
149
|
+
* Elasticsearch) blob search returns at most ~20 results per query regardless
|
|
150
|
+
* of `per_page` and doesn't paginate past them; GitHub code search is rate-
|
|
151
|
+
* limited (~10 req/min unauthenticated) and caps at 1000 results/query. Either
|
|
152
|
+
* way, a short page (`< per_page`) already stops the loop early — this is just
|
|
153
|
+
* a hard ceiling on round trips per term. */
|
|
154
|
+
const MAX_SEARCH_PAGES = 3;
|
|
155
|
+
/**
|
|
156
|
+
* Content-detected lexicons: no canonical path, so search-first discovery
|
|
157
|
+
* needs one characteristic content term per lexicon, taken from that lexicon's
|
|
158
|
+
* own `detectTemplate` signature. One row per lexicon — docker gets two
|
|
159
|
+
* (Dockerfile and Compose share nothing in content) — so adding a new
|
|
160
|
+
* content-detected lexicon here is the only step needed to search for it.
|
|
161
|
+
* Ordered most → least selective; the caller de-duplicates by path, so a
|
|
162
|
+
* broader later term (`apiVersion`) adds nothing for files the more specific
|
|
163
|
+
* earlier term (`apiVersion: v2`) already found.
|
|
164
|
+
*/
|
|
165
|
+
const CONTENT_SEARCH_TERMS = [
|
|
166
|
+
{ lexicon: "aws", term: "AWSTemplateFormatVersion" }, // CloudFormation
|
|
167
|
+
{ lexicon: "azure", term: "deploymentTemplate" }, // ARM $schema substring
|
|
168
|
+
{ lexicon: "gcp", term: "cnrm.cloud.google.com" }, // GCP Config Connector
|
|
169
|
+
{ lexicon: "helm", term: "apiVersion: v2" }, // Chart.yaml
|
|
170
|
+
{ lexicon: "docker", term: "FROM " }, // Dockerfiles (space avoids false hits)
|
|
171
|
+
{ lexicon: "docker", term: "services:" }, // Docker Compose
|
|
172
|
+
{ lexicon: "k8s", term: "apiVersion" }, // any k8s resource (broad; runs last)
|
|
173
|
+
];
|
|
174
|
+
/** GitLab-only: `include:` can pull a CI file in from anywhere, so the
|
|
175
|
+
* canonical-path lexicon still gets a search term (#518, #520). GitHub and
|
|
176
|
+
* Forgejo Actions have no such mechanism, so they need none. */
|
|
177
|
+
const GITLAB_CI_TERM = "stages:";
|
|
178
|
+
/** One page of GitLab's blob search (`scope=blobs`) for a single term. */
|
|
179
|
+
async function gitlabSearchPage(host, owner, repo, ref, term, page, doFetch, headers, ms) {
|
|
180
|
+
const url = `${host.api}/projects/${projectId(owner, repo)}/search?scope=blobs&search=${encodeURIComponent(term)}&per_page=100&page=${page}&ref=${encodeURIComponent(ref)}`;
|
|
181
|
+
const body = await getSearchJsonAt(url, headers, doFetch, ms);
|
|
182
|
+
if (!Array.isArray(body))
|
|
183
|
+
return [];
|
|
184
|
+
return body.map((e) => e.path).filter((p) => typeof p === "string");
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* GitLab content search across every term (CI + content-detected lexicons),
|
|
188
|
+
* de-duplicated by path. Throws on the first request error (a 401 with a bad
|
|
189
|
+
* or absent token, a rate limit, a transient failure) — the caller catches
|
|
190
|
+
* that and falls back to the BFS walk (#520).
|
|
191
|
+
*/
|
|
192
|
+
async function gitlabSearch(host, owner, repo, ref, doFetch, headers, ms) {
|
|
193
|
+
const out = [];
|
|
194
|
+
const seen = new Set();
|
|
195
|
+
const terms = [GITLAB_CI_TERM, ...CONTENT_SEARCH_TERMS.map((t) => t.term)];
|
|
196
|
+
for (const term of terms) {
|
|
197
|
+
for (let page = 1; page <= MAX_SEARCH_PAGES; page++) {
|
|
198
|
+
const hits = await gitlabSearchPage(host, owner, repo, ref, term, page, doFetch, headers, ms);
|
|
199
|
+
if (hits.length === 0)
|
|
200
|
+
break;
|
|
201
|
+
for (const p of hits)
|
|
202
|
+
if (!seen.has(p)) {
|
|
203
|
+
seen.add(p);
|
|
204
|
+
out.push({ path: p, type: "blob" });
|
|
205
|
+
}
|
|
206
|
+
if (hits.length < 100)
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Non-recursive BFS over a bounded directory frontier. GitLab's recursive tree
|
|
214
|
+
* API lists ALL directories before any blobs for large repos (#518), so this
|
|
215
|
+
* walks directories breadth-first to ensure root blobs appear on the first
|
|
216
|
+
* request regardless of how many subdirectories follow. `seedRootPage1`, when
|
|
217
|
+
* given, is the root's page-1 entries already fetched by the size probe below
|
|
218
|
+
* — reused here so the small-repo path never double-fetches it.
|
|
219
|
+
*/
|
|
220
|
+
async function gitlabBfsWalk(host, owner, repo, ref, doFetch, headers, ms, seedRootPage1) {
|
|
221
|
+
const out = [];
|
|
222
|
+
const queue = [""]; // "" = repo root
|
|
223
|
+
const MAX_DIRS = 30;
|
|
224
|
+
const MAX_BLOBS = 200;
|
|
225
|
+
let dirs = 0;
|
|
226
|
+
while (queue.length > 0 && dirs < MAX_DIRS && out.length < MAX_BLOBS) {
|
|
227
|
+
const dir = queue.shift();
|
|
228
|
+
dirs++;
|
|
229
|
+
const pathParam = dir ? `&path=${encodeURIComponent(dir)}` : "";
|
|
230
|
+
for (let page = 1; page <= 5; page++) {
|
|
231
|
+
let body;
|
|
232
|
+
if (dir === "" && page === 1 && seedRootPage1) {
|
|
233
|
+
body = seedRootPage1;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
const url = `${host.api}/projects/${projectId(owner, repo)}/repository/tree?per_page=100&page=${page}&ref=${encodeURIComponent(ref)}${pathParam}`;
|
|
237
|
+
({ body } = await getJsonAt(url, headers, doFetch, ms));
|
|
238
|
+
}
|
|
239
|
+
if (!Array.isArray(body) || body.length === 0)
|
|
240
|
+
break;
|
|
241
|
+
for (const e of body) {
|
|
242
|
+
if (e.type === "blob")
|
|
243
|
+
out.push({ path: e.path, type: "blob" });
|
|
244
|
+
else if (e.type === "tree")
|
|
245
|
+
queue.push(e.path);
|
|
246
|
+
}
|
|
247
|
+
if (body.length < 100)
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return out;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* GitLab tree discovery: a cheap size probe (the root's first tree page, which
|
|
255
|
+
* every path below needs anyway) decides walk vs. search. GitLab's own
|
|
256
|
+
* recursive-tree endpoint can't be used to size the repo up front — that's the
|
|
257
|
+
* exact pagination trap #518 fixed (directories dominate the page cap before
|
|
258
|
+
* any blob appears) — so "is the root itself large" (a full 100-entry page)
|
|
259
|
+
* stands in for "is the repo large".
|
|
260
|
+
*/
|
|
261
|
+
async function listTreeGitLab(host, owner, repo, ref, doFetch, headers, ms) {
|
|
262
|
+
const rootUrl = `${host.api}/projects/${projectId(owner, repo)}/repository/tree?per_page=100&page=1&ref=${encodeURIComponent(ref)}`;
|
|
263
|
+
const { body: rootBody } = await getJsonAt(rootUrl, headers, doFetch, ms);
|
|
264
|
+
const rootPage1 = Array.isArray(rootBody) ? rootBody : [];
|
|
265
|
+
const isLarge = rootPage1.length >= 100;
|
|
266
|
+
if (isLarge && "PRIVATE-TOKEN" in headers) {
|
|
267
|
+
// GitLab's search API requires authentication even for public projects, so
|
|
268
|
+
// this branch only ever runs with a token. Any failure — no search access,
|
|
269
|
+
// a rate limit, a transient error — falls back to the walk (#520) rather
|
|
270
|
+
// than failing the audit.
|
|
271
|
+
try {
|
|
272
|
+
return await gitlabSearch(host, owner, repo, ref, doFetch, headers, ms);
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// fall through to the walk below
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return gitlabBfsWalk(host, owner, repo, ref, doFetch, headers, ms, rootPage1);
|
|
279
|
+
}
|
|
280
|
+
/** One page of GitHub's code search (`GET /search/code`) for a single term. */
|
|
281
|
+
async function githubSearchPage(host, owner, repo, term, page, doFetch, headers, ms) {
|
|
282
|
+
const q = encodeURIComponent(`${term} repo:${owner}/${repo}`);
|
|
283
|
+
const url = `${host.api}/search/code?q=${q}&per_page=100&page=${page}`;
|
|
284
|
+
const body = await getSearchJsonAt(url, { ...headers, Accept: "application/vnd.github+json" }, doFetch, ms);
|
|
285
|
+
const items = body?.items;
|
|
286
|
+
if (!Array.isArray(items))
|
|
287
|
+
return [];
|
|
288
|
+
return items.map((e) => e.path).filter((p) => typeof p === "string");
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* GitHub code search across the content-detected lexicons. Rate-limited to
|
|
292
|
+
* ~10 req/min unauthenticated (#520) — a 403/422/429 throws (via `getSearchJsonAt`)
|
|
293
|
+
* and the caller falls back to the already-fetched full tree.
|
|
294
|
+
*/
|
|
295
|
+
async function githubCodeSearch(host, owner, repo, doFetch, headers, ms) {
|
|
296
|
+
const out = [];
|
|
297
|
+
const seen = new Set();
|
|
298
|
+
for (const { term } of CONTENT_SEARCH_TERMS) {
|
|
299
|
+
for (let page = 1; page <= MAX_SEARCH_PAGES; page++) {
|
|
300
|
+
const hits = await githubSearchPage(host, owner, repo, term, page, doFetch, headers, ms);
|
|
301
|
+
if (hits.length === 0)
|
|
302
|
+
break;
|
|
303
|
+
for (const p of hits)
|
|
304
|
+
if (!seen.has(p)) {
|
|
305
|
+
seen.add(p);
|
|
306
|
+
out.push({ path: p, type: "blob" });
|
|
307
|
+
}
|
|
308
|
+
if (hits.length < 100)
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* One page of a Forgejo/Gitea repo code search. The shape here mirrors Gitea's
|
|
316
|
+
* `{ok, data}` search envelope (also used by `GET /repos/search`), tolerating
|
|
317
|
+
* a bare array too — Forgejo's code-search REST surface (and whether an
|
|
318
|
+
* instance even runs a code indexer) isn't consistently documented across
|
|
319
|
+
* versions (#520), so this is best-effort: any unexpected shape/status throws
|
|
320
|
+
* and the caller falls back to the full tree, never breaking the audit.
|
|
321
|
+
*/
|
|
322
|
+
async function forgejoSearchPage(host, owner, repo, term, page, doFetch, headers, ms) {
|
|
323
|
+
const url = `${host.api}/repos/${owner}/${repo}/search?q=${encodeURIComponent(term)}&page=${page}&limit=100`;
|
|
324
|
+
const body = await getSearchJsonAt(url, headers, doFetch, ms);
|
|
325
|
+
const data = Array.isArray(body) ? body : body?.data;
|
|
326
|
+
if (!Array.isArray(data))
|
|
327
|
+
return [];
|
|
328
|
+
return data.map((e) => e.path).filter((p) => typeof p === "string");
|
|
329
|
+
}
|
|
330
|
+
/** Forgejo/Gitea code search across the content-detected lexicons. See `forgejoSearchPage`. */
|
|
331
|
+
async function forgejoCodeSearch(host, owner, repo, doFetch, headers, ms) {
|
|
332
|
+
const out = [];
|
|
333
|
+
const seen = new Set();
|
|
334
|
+
for (const { term } of CONTENT_SEARCH_TERMS) {
|
|
335
|
+
for (let page = 1; page <= MAX_SEARCH_PAGES; page++) {
|
|
336
|
+
const hits = await forgejoSearchPage(host, owner, repo, term, page, doFetch, headers, ms);
|
|
337
|
+
if (hits.length === 0)
|
|
338
|
+
break;
|
|
339
|
+
for (const p of hits)
|
|
340
|
+
if (!seen.has(p)) {
|
|
341
|
+
seen.add(p);
|
|
342
|
+
out.push({ path: p, type: "blob" });
|
|
343
|
+
}
|
|
344
|
+
if (hits.length < 100)
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return out;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* GitHub/Forgejo tree discovery: their `git/trees?recursive=1` API returns the
|
|
352
|
+
* whole tree in one call (no GitLab-style ordering trap), so the entry count
|
|
353
|
+
* from that single call is a free large-repo signal. Below the threshold,
|
|
354
|
+
* behavior is unchanged — the full blob list, later filtered by
|
|
355
|
+
* `isCandidatePath`. Above it, known-path lexicons (CI) are kept straight from
|
|
356
|
+
* the tree we already have — free, no search needed — and the content-detected
|
|
357
|
+
* lexicons are found by search instead of downloaded wholesale.
|
|
358
|
+
*/
|
|
359
|
+
async function listTreeGitHubLike(host, owner, repo, ref, doFetch, headers, ms) {
|
|
360
|
+
const url = `${host.api}/repos/${owner}/${repo}/git/trees/${encodeURIComponent(ref)}?recursive=1`;
|
|
361
|
+
const { body } = await getJsonAt(url, headers, doFetch, ms);
|
|
362
|
+
const treeBody = body;
|
|
363
|
+
const tree = treeBody?.tree;
|
|
364
|
+
if (!Array.isArray(tree))
|
|
365
|
+
return [];
|
|
366
|
+
const blobs = tree.filter((e) => e.type === "blob").map((e) => ({ path: e.path, type: "blob", size: e.size }));
|
|
367
|
+
const isLarge = blobs.length > LARGE_REPO_TREE_ENTRIES || treeBody?.truncated === true;
|
|
368
|
+
if (!isLarge)
|
|
369
|
+
return blobs;
|
|
370
|
+
const { ciLexiconForPath } = await import("./discover.js");
|
|
371
|
+
const known = blobs.filter((e) => ciLexiconForPath(e.path));
|
|
372
|
+
try {
|
|
373
|
+
const hits = host.kind === "github"
|
|
374
|
+
? await githubCodeSearch(host, owner, repo, doFetch, headers, ms)
|
|
375
|
+
: await forgejoCodeSearch(host, owner, repo, doFetch, headers, ms);
|
|
376
|
+
const knownPaths = new Set(known.map((e) => e.path));
|
|
377
|
+
return [...known, ...hits.filter((h) => !knownPaths.has(h.path))];
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
// Search unavailable/errored/rate-limited — degrade to the full tree we
|
|
381
|
+
// already have, filtered by isCandidatePath downstream, same as a small
|
|
382
|
+
// repo (#520: search is additive, never load-bearing).
|
|
383
|
+
return blobs;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/** List blob paths worth considering for download (all lexicons), choosing walk vs. search-first per host (#520). */
|
|
387
|
+
async function listTree(host, owner, repo, ref, doFetch, headers, ms) {
|
|
388
|
+
if (host.kind === "gitlab")
|
|
389
|
+
return listTreeGitLab(host, owner, repo, ref, doFetch, headers, ms);
|
|
390
|
+
return listTreeGitHubLike(host, owner, repo, ref, doFetch, headers, ms);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Resilient GET → text. Returns undefined on any error or non-ok status, so one
|
|
394
|
+
* file's failure (a bad path, a 403 secondary rate-limit, a timeout) never
|
|
395
|
+
* aborts the whole walk. `redirect: "manual"` keeps the SSRF posture — a 3xx is
|
|
396
|
+
* skipped, never followed.
|
|
397
|
+
*/
|
|
398
|
+
async function fetchText(url, headers, doFetch, ms) {
|
|
399
|
+
let res;
|
|
400
|
+
try {
|
|
401
|
+
res = await doFetch(url, { headers, redirect: "manual", signal: timeoutSignal(ms) });
|
|
402
|
+
}
|
|
403
|
+
catch {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
if (!res.ok)
|
|
407
|
+
return undefined;
|
|
408
|
+
try {
|
|
409
|
+
return await res.text();
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Fetch one file's content. GitHub reads from the raw CDN first — a burst of
|
|
417
|
+
* contents-API calls trips GitHub's *secondary* rate limit on large repos
|
|
418
|
+
* (dozens of files), whereas raw.githubusercontent.com isn't subject to it and
|
|
419
|
+
* needs no auth for public repos. The contents API is the fallback for private
|
|
420
|
+
* repos (raw 404s there without auth). GitLab uses its raw endpoint; Forgejo
|
|
421
|
+
* uses the contents API.
|
|
422
|
+
*/
|
|
423
|
+
async function fetchFileContent(host, owner, repo, path, ref, doFetch, headers, ms) {
|
|
424
|
+
// Encode each segment (keep the slashes) — paths can contain spaces and other
|
|
425
|
+
// characters that make an unencoded URL malformed and 403 (e.g. GitHub's
|
|
426
|
+
// changelog fragments like ".changes/v1.16/NEW FEATURES-….yaml").
|
|
427
|
+
const encodedPath = path.split("/").map(encodeURIComponent).join("/");
|
|
428
|
+
if (host.kind === "gitlab") {
|
|
429
|
+
const url = `${host.api}/projects/${projectId(owner, repo)}/repository/files/${encodeURIComponent(path)}/raw?ref=${encodeURIComponent(ref)}`;
|
|
430
|
+
return fetchText(url, headers, doFetch, ms);
|
|
431
|
+
}
|
|
432
|
+
if (host.kind === "github") {
|
|
433
|
+
// No token sent cross-host to the CDN; public repos need none.
|
|
434
|
+
const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${encodeURIComponent(ref)}/${encodedPath}`;
|
|
435
|
+
const raw = await fetchText(rawUrl, { "User-Agent": USER_AGENT }, doFetch, ms);
|
|
436
|
+
if (raw !== undefined)
|
|
437
|
+
return raw;
|
|
438
|
+
// Private repo (raw 404s without auth) — fall through to the contents API.
|
|
439
|
+
}
|
|
440
|
+
// Contents API: base64 JSON. Forgejo always; GitHub private-repo fallback.
|
|
441
|
+
const url = `${host.api}/repos/${owner}/${repo}/contents/${encodedPath}?ref=${encodeURIComponent(ref)}`;
|
|
442
|
+
let res;
|
|
443
|
+
try {
|
|
444
|
+
res = await doFetch(url, { headers, redirect: "manual", signal: timeoutSignal(ms) });
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
return undefined;
|
|
448
|
+
}
|
|
449
|
+
if (!res.ok)
|
|
450
|
+
return undefined;
|
|
451
|
+
let file;
|
|
452
|
+
try {
|
|
453
|
+
file = (await res.json());
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
return undefined;
|
|
457
|
+
}
|
|
458
|
+
if (!file?.content)
|
|
459
|
+
return undefined;
|
|
460
|
+
return Buffer.from(file.content, file.encoding ?? "base64").toString("utf-8");
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Fetch every candidate file in a repo (all lexicons), so a URL audit covers the
|
|
464
|
+
* same ground as a local one. Returns raw {path, content}; classification (which
|
|
465
|
+
* needs the lexicon plugins) is the caller's job via `classifyFiles`.
|
|
466
|
+
*/
|
|
467
|
+
export async function fetchRepoFiles(url, opts = {}) {
|
|
468
|
+
const { isCandidatePath } = await import("./discover.js");
|
|
469
|
+
const { host, owner, repo } = parseRepoUrl(url);
|
|
470
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
471
|
+
const cfg = {
|
|
472
|
+
maxFiles: opts.maxFiles ?? DEFAULTS.maxFiles,
|
|
473
|
+
maxBytesPerFile: opts.maxBytesPerFile ?? DEFAULTS.maxBytesPerFile,
|
|
474
|
+
maxTotalBytes: opts.maxTotalBytes ?? DEFAULTS.maxTotalBytes,
|
|
475
|
+
timeoutMs: opts.timeoutMs ?? DEFAULTS.timeoutMs,
|
|
476
|
+
};
|
|
477
|
+
const headers = authHeaders(host.kind, opts.token);
|
|
478
|
+
const ref = opts.ref ?? (await defaultBranch(host, owner, repo, doFetch, headers, cfg.timeoutMs));
|
|
479
|
+
const tree = await listTree(host, owner, repo, ref, doFetch, headers, cfg.timeoutMs);
|
|
480
|
+
const candidates = tree.filter((e) => isCandidatePath(e.path));
|
|
481
|
+
const files = [];
|
|
482
|
+
let total = 0;
|
|
483
|
+
for (const entry of candidates) {
|
|
484
|
+
if (files.length >= cfg.maxFiles)
|
|
485
|
+
break;
|
|
486
|
+
if ((entry.size ?? 0) > cfg.maxBytesPerFile)
|
|
487
|
+
continue; // skip oversize when the host reports size
|
|
488
|
+
const content = await fetchFileContent(host, owner, repo, entry.path, ref, doFetch, headers, cfg.timeoutMs);
|
|
489
|
+
if (content === undefined)
|
|
490
|
+
continue;
|
|
491
|
+
if (content.length > cfg.maxBytesPerFile)
|
|
492
|
+
continue;
|
|
493
|
+
total += content.length;
|
|
494
|
+
if (total > cfg.maxTotalBytes)
|
|
495
|
+
throw new FetchError("Repository files exceed the total size cap.");
|
|
496
|
+
files.push({ path: entry.path, content });
|
|
497
|
+
}
|
|
498
|
+
return files;
|
|
499
|
+
}
|
|
500
|
+
const SHA40 = /^[0-9a-f]{40}$/;
|
|
501
|
+
/**
|
|
502
|
+
* Resolve an action ref (e.g. action="actions/checkout", ref="v4") to its
|
|
503
|
+
* commit SHA via the GitHub API. Returns undefined on any failure — pinning
|
|
504
|
+
* degrades gracefully to guidance. Actions are GitHub-hosted slugs, so this
|
|
505
|
+
* queries api.github.com regardless of the audited repo's host.
|
|
506
|
+
*/
|
|
507
|
+
export async function resolveActionSha(action, ref, opts = {}) {
|
|
508
|
+
const parts = action.split("/");
|
|
509
|
+
if (parts.length < 2 || !parts[0] || !parts[1])
|
|
510
|
+
return undefined;
|
|
511
|
+
const [owner, repo] = parts;
|
|
512
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
513
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/commits/${encodeURIComponent(ref)}`;
|
|
514
|
+
try {
|
|
515
|
+
const res = await doFetch(url, {
|
|
516
|
+
headers: {
|
|
517
|
+
Accept: "application/vnd.github+json",
|
|
518
|
+
"User-Agent": USER_AGENT,
|
|
519
|
+
...(opts.token ? { Authorization: `Bearer ${opts.token}` } : {}),
|
|
520
|
+
},
|
|
521
|
+
redirect: "manual",
|
|
522
|
+
signal: timeoutSignal(opts.timeoutMs ?? DEFAULTS.timeoutMs),
|
|
523
|
+
});
|
|
524
|
+
if (!res.ok)
|
|
525
|
+
return undefined;
|
|
526
|
+
const body = (await res.json());
|
|
527
|
+
return body.sha && SHA40.test(body.sha) ? body.sha : undefined;
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
return undefined;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
const DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
|
|
534
|
+
/** Public registries we'll talk to. The image ref is untrusted (SSRF guard). */
|
|
535
|
+
const ALLOWED_REGISTRIES = new Set([
|
|
536
|
+
"registry-1.docker.io",
|
|
537
|
+
"ghcr.io",
|
|
538
|
+
"quay.io",
|
|
539
|
+
"gcr.io",
|
|
540
|
+
"public.ecr.aws",
|
|
541
|
+
"mcr.microsoft.com",
|
|
542
|
+
"registry.gitlab.com",
|
|
543
|
+
]);
|
|
544
|
+
/** Parse a Docker/OCI image reference. Returns undefined if already digested. */
|
|
545
|
+
export function parseImageRef(ref) {
|
|
546
|
+
if (ref.includes("@"))
|
|
547
|
+
return undefined; // already digest-pinned
|
|
548
|
+
let registry = "registry-1.docker.io";
|
|
549
|
+
let rest = ref;
|
|
550
|
+
let repoPrefix = "";
|
|
551
|
+
const firstSlash = ref.indexOf("/");
|
|
552
|
+
const firstPart = firstSlash === -1 ? "" : ref.slice(0, firstSlash);
|
|
553
|
+
if (firstPart && (firstPart.includes(".") || firstPart.includes(":") || firstPart === "localhost")) {
|
|
554
|
+
registry = firstPart;
|
|
555
|
+
rest = ref.slice(firstSlash + 1);
|
|
556
|
+
}
|
|
557
|
+
else if (firstSlash === -1) {
|
|
558
|
+
repoPrefix = "library/"; // bare Docker Hub official image
|
|
559
|
+
}
|
|
560
|
+
let tag = "latest";
|
|
561
|
+
const lastColon = rest.lastIndexOf(":");
|
|
562
|
+
const lastSlash = rest.lastIndexOf("/");
|
|
563
|
+
if (lastColon > lastSlash) {
|
|
564
|
+
tag = rest.slice(lastColon + 1);
|
|
565
|
+
rest = rest.slice(0, lastColon);
|
|
566
|
+
}
|
|
567
|
+
if (!rest)
|
|
568
|
+
return undefined;
|
|
569
|
+
return { registry, repository: repoPrefix + rest, tag };
|
|
570
|
+
}
|
|
571
|
+
/** Parse a `Bearer realm=...,service=...,scope=...` challenge into a token URL. */
|
|
572
|
+
function tokenUrlFromChallenge(header) {
|
|
573
|
+
const m = /Bearer\s+(.*)/i.exec(header);
|
|
574
|
+
if (!m)
|
|
575
|
+
return undefined;
|
|
576
|
+
const params = {};
|
|
577
|
+
for (const part of m[1].split(",")) {
|
|
578
|
+
const kv = /(\w+)="([^"]*)"/.exec(part.trim());
|
|
579
|
+
if (kv)
|
|
580
|
+
params[kv[1]] = kv[2];
|
|
581
|
+
}
|
|
582
|
+
if (!params.realm)
|
|
583
|
+
return undefined;
|
|
584
|
+
const url = new URL(params.realm);
|
|
585
|
+
if (params.service)
|
|
586
|
+
url.searchParams.set("service", params.service);
|
|
587
|
+
if (params.scope)
|
|
588
|
+
url.searchParams.set("scope", params.scope);
|
|
589
|
+
return url.toString();
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Resolve a container image `name:tag` to its `sha256:...` digest via the OCI
|
|
593
|
+
* registry v2 API (anonymous bearer-token challenge). Returns undefined on any
|
|
594
|
+
* failure or for a non-allowlisted registry. The image ref is untrusted, so we
|
|
595
|
+
* only ever contact allowlisted public registries (SSRF guard).
|
|
596
|
+
*/
|
|
597
|
+
export async function resolveImageDigest(image, opts = {}) {
|
|
598
|
+
const parsed = parseImageRef(image);
|
|
599
|
+
if (!parsed || !ALLOWED_REGISTRIES.has(parsed.registry))
|
|
600
|
+
return undefined;
|
|
601
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
602
|
+
const ms = opts.timeoutMs ?? DEFAULTS.timeoutMs;
|
|
603
|
+
const accept = [
|
|
604
|
+
"application/vnd.oci.image.index.v1+json",
|
|
605
|
+
"application/vnd.oci.image.manifest.v1+json",
|
|
606
|
+
"application/vnd.docker.distribution.manifest.list.v2+json",
|
|
607
|
+
"application/vnd.docker.distribution.manifest.v2+json",
|
|
608
|
+
].join(", ");
|
|
609
|
+
const manifestUrl = `https://${parsed.registry}/v2/${parsed.repository}/manifests/${encodeURIComponent(parsed.tag)}`;
|
|
610
|
+
try {
|
|
611
|
+
let res = await doFetch(manifestUrl, { headers: { Accept: accept, "User-Agent": USER_AGENT }, redirect: "manual", signal: timeoutSignal(ms) });
|
|
612
|
+
if (res.status === 401) {
|
|
613
|
+
const tokenUrl = tokenUrlFromChallenge(res.headers.get("www-authenticate") ?? "");
|
|
614
|
+
if (!tokenUrl)
|
|
615
|
+
return undefined;
|
|
616
|
+
const tokRes = await doFetch(tokenUrl, { headers: { "User-Agent": USER_AGENT }, redirect: "manual", signal: timeoutSignal(ms) });
|
|
617
|
+
if (!tokRes.ok)
|
|
618
|
+
return undefined;
|
|
619
|
+
const tok = (await tokRes.json());
|
|
620
|
+
const bearer = tok.token ?? tok.access_token;
|
|
621
|
+
if (!bearer)
|
|
622
|
+
return undefined;
|
|
623
|
+
res = await doFetch(manifestUrl, { headers: { Accept: accept, "User-Agent": USER_AGENT, Authorization: `Bearer ${bearer}` }, redirect: "manual", signal: timeoutSignal(ms) });
|
|
624
|
+
}
|
|
625
|
+
if (!res.ok)
|
|
626
|
+
return undefined;
|
|
627
|
+
const digest = res.headers.get("docker-content-digest");
|
|
628
|
+
return digest && DIGEST_RE.test(digest) ? digest : undefined;
|
|
629
|
+
}
|
|
630
|
+
catch {
|
|
631
|
+
return undefined;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Resolve the audited repo's current commit SHA (best-effort) for the report
|
|
636
|
+
* snapshot, so findings are anchored to an exact commit. Returns undefined on
|
|
637
|
+
* any failure.
|
|
638
|
+
*/
|
|
639
|
+
export async function resolveRepoCommit(url, opts = {}) {
|
|
640
|
+
let parsed;
|
|
641
|
+
try {
|
|
642
|
+
parsed = parseRepoUrl(url);
|
|
643
|
+
}
|
|
644
|
+
catch {
|
|
645
|
+
return undefined;
|
|
646
|
+
}
|
|
647
|
+
const { host, owner, repo } = parsed;
|
|
648
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
649
|
+
const headers = authHeaders(host.kind, opts.token);
|
|
650
|
+
const apiUrl = host.kind === "gitlab"
|
|
651
|
+
? `${host.api}/projects/${encodeURIComponent(`${owner}/${repo}`)}/repository/commits?per_page=1`
|
|
652
|
+
: `${host.api}/repos/${owner}/${repo}/commits?per_page=1&limit=1`;
|
|
653
|
+
try {
|
|
654
|
+
const res = await doFetch(apiUrl, { headers, redirect: "manual", signal: timeoutSignal(opts.timeoutMs ?? DEFAULTS.timeoutMs) });
|
|
655
|
+
if (!res.ok)
|
|
656
|
+
return undefined;
|
|
657
|
+
const body = (await res.json());
|
|
658
|
+
if (!Array.isArray(body) || body.length === 0)
|
|
659
|
+
return undefined;
|
|
660
|
+
const sha = body[0].sha ?? body[0].id;
|
|
661
|
+
return typeof sha === "string" ? sha : undefined;
|
|
662
|
+
}
|
|
663
|
+
catch {
|
|
664
|
+
return undefined;
|
|
665
|
+
}
|
|
666
|
+
}
|