@mannyc1/ts-release 0.0.6 → 0.2.2
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/ARCHITECTURE.md +124 -87
- package/CHANGELOG.md +115 -0
- package/LICENSE +21 -0
- package/README.md +272 -540
- package/SPEC.md +206 -305
- package/apps/release-ts/README.md +32 -0
- package/apps/release-ts/src/cli/command.ts +164 -0
- package/apps/release-ts/src/cli/commands.ts +351 -0
- package/apps/release-ts/src/cli/main.ts +43 -0
- package/apps/release-ts/src/cli/node-main.ts +49 -0
- package/apps/ts-release-agents/LICENSE +21 -0
- package/apps/ts-release-agents/README.md +21 -0
- package/apps/ts-release-agents/evals/cases.json +11 -0
- package/apps/ts-release-agents/manifests/claude.json +5 -0
- package/apps/ts-release-agents/manifests/codex.json +5 -0
- package/apps/ts-release-agents/package.json +11 -0
- package/apps/ts-release-agents/skills/release/SKILL.md +48 -0
- package/apps/ts-release-agents/skills/release/references/configuration.md +18 -0
- package/apps/ts-release-agents/skills/release/references/recovery.md +10 -0
- package/apps/ts-release-agents/skills/release/references/staged-workflow.md +12 -0
- package/apps/ts-release-agents/skills/release/references/target-selection.md +13 -0
- package/apps/ts-release-agents/skills/release/references/verification.md +14 -0
- package/apps/ts-release-agents/src/build.ts +105 -0
- package/apps/ts-release-agents/src/check.ts +117 -0
- package/apps/ts-release-agents/src/install.ts +121 -0
- package/apps/ts-release-agents/test/contract.test.ts +56 -0
- package/apps/ts-release-agents/tsconfig.json +5 -0
- package/dist/api/api.d.ts +15 -0
- package/dist/api/api.d.ts.map +1 -0
- package/dist/api/api.js +244 -0
- package/dist/api/api.js.map +1 -0
- package/dist/api/errors.d.ts +39 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +32 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/input.d.ts +10 -0
- package/dist/api/input.d.ts.map +1 -0
- package/dist/api/input.js +73 -0
- package/dist/api/input.js.map +1 -0
- package/dist/api/runtime.d.ts +18 -0
- package/dist/api/runtime.d.ts.map +1 -0
- package/dist/api/runtime.js +7 -0
- package/dist/api/runtime.js.map +1 -0
- package/dist/api/types.d.ts +76 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +17 -0
- package/dist/api/types.js.map +1 -0
- package/dist/bin/ts-release.js +39239 -0
- package/dist/capabilities/bun-targets.d.ts +3 -0
- package/dist/capabilities/bun-targets.d.ts.map +1 -0
- package/dist/capabilities/bun-targets.js +3 -0
- package/dist/capabilities/bun-targets.js.map +1 -0
- package/dist/capabilities/field-ownership.d.ts +17 -0
- package/dist/capabilities/field-ownership.d.ts.map +1 -0
- package/dist/capabilities/field-ownership.js +40 -0
- package/dist/capabilities/field-ownership.js.map +1 -0
- package/dist/capabilities/module.d.ts +91 -0
- package/dist/capabilities/module.d.ts.map +1 -0
- package/dist/capabilities/module.js +2 -0
- package/dist/capabilities/module.js.map +1 -0
- package/dist/capabilities/registry.d.ts +829 -0
- package/dist/capabilities/registry.d.ts.map +1 -0
- package/dist/capabilities/registry.js +291 -0
- package/dist/capabilities/registry.js.map +1 -0
- package/dist/config/config.d.ts +6 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +42 -0
- package/dist/config/config.js.map +1 -0
- package/dist/correction/coordinator.d.ts +248 -0
- package/dist/correction/coordinator.d.ts.map +1 -0
- package/dist/correction/coordinator.js +274 -0
- package/dist/correction/coordinator.js.map +1 -0
- package/dist/correction/index.d.ts +3 -0
- package/dist/correction/index.d.ts.map +1 -0
- package/dist/correction/index.js +3 -0
- package/dist/correction/index.js.map +1 -0
- package/dist/correction/intent.d.ts +111 -0
- package/dist/correction/intent.d.ts.map +1 -0
- package/dist/correction/intent.js +146 -0
- package/dist/correction/intent.js.map +1 -0
- package/dist/drivers/archive.d.ts +8 -0
- package/dist/drivers/archive.d.ts.map +1 -0
- package/dist/drivers/archive.js +101 -0
- package/dist/drivers/archive.js.map +1 -0
- package/dist/drivers/contain.d.ts +6 -0
- package/dist/drivers/contain.d.ts.map +1 -0
- package/dist/drivers/contain.js +17 -0
- package/dist/drivers/contain.js.map +1 -0
- package/dist/drivers/environment.d.ts +4 -0
- package/dist/drivers/environment.d.ts.map +1 -0
- package/dist/drivers/environment.js +18 -0
- package/dist/drivers/environment.js.map +1 -0
- package/dist/drivers/errors.d.ts +9 -0
- package/dist/drivers/errors.d.ts.map +1 -0
- package/dist/drivers/errors.js +6 -0
- package/dist/drivers/errors.js.map +1 -0
- package/dist/drivers/glob.d.ts +2 -0
- package/dist/drivers/glob.d.ts.map +1 -0
- package/dist/drivers/glob.js +162 -0
- package/dist/drivers/glob.js.map +1 -0
- package/dist/drivers/process.d.ts +48 -0
- package/dist/drivers/process.d.ts.map +1 -0
- package/dist/drivers/process.js +257 -0
- package/dist/drivers/process.js.map +1 -0
- package/dist/drivers/redact.d.ts +4 -0
- package/dist/drivers/redact.d.ts.map +1 -0
- package/dist/drivers/redact.js +24 -0
- package/dist/drivers/redact.js.map +1 -0
- package/dist/drivers/seccomp-helper-source.d.ts +7 -0
- package/dist/drivers/seccomp-helper-source.d.ts.map +1 -0
- package/dist/drivers/seccomp-helper-source.js +121 -0
- package/dist/drivers/seccomp-helper-source.js.map +1 -0
- package/dist/drivers/utils.d.ts +4 -0
- package/dist/drivers/utils.d.ts.map +1 -0
- package/dist/drivers/utils.js +5 -0
- package/dist/drivers/utils.js.map +1 -0
- package/dist/drivers/workspace.d.ts +6 -0
- package/dist/drivers/workspace.d.ts.map +1 -0
- package/dist/drivers/workspace.js +49 -0
- package/dist/drivers/workspace.js.map +1 -0
- package/dist/extensions/provider-adapter.d.ts +48 -0
- package/dist/extensions/provider-adapter.d.ts.map +1 -0
- package/dist/extensions/provider-adapter.js +64 -0
- package/dist/extensions/provider-adapter.js.map +1 -0
- package/dist/host.d.ts +33 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +20 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/model/artifact-collection.d.ts +84 -0
- package/dist/model/artifact-collection.d.ts.map +1 -0
- package/dist/model/artifact-collection.js +185 -0
- package/dist/model/artifact-collection.js.map +1 -0
- package/dist/model/authority.d.ts +89 -0
- package/dist/model/authority.d.ts.map +1 -0
- package/dist/model/authority.js +80 -0
- package/dist/model/authority.js.map +1 -0
- package/dist/model/bun-targets.d.ts +34 -0
- package/dist/model/bun-targets.d.ts.map +1 -0
- package/dist/model/bun-targets.js +17 -0
- package/dist/model/bun-targets.js.map +1 -0
- package/dist/model/canonical.d.ts +8 -0
- package/dist/model/canonical.d.ts.map +1 -0
- package/dist/model/canonical.js +205 -0
- package/dist/model/canonical.js.map +1 -0
- package/dist/model/catalog.d.ts +76 -0
- package/dist/model/catalog.d.ts.map +1 -0
- package/dist/model/catalog.js +174 -0
- package/dist/model/catalog.js.map +1 -0
- package/dist/model/digest.d.ts +53 -0
- package/dist/model/digest.d.ts.map +1 -0
- package/dist/model/digest.js +127 -0
- package/dist/model/digest.js.map +1 -0
- package/dist/model/errors.d.ts +14 -0
- package/dist/model/errors.d.ts.map +1 -0
- package/dist/model/errors.js +8 -0
- package/dist/model/errors.js.map +1 -0
- package/dist/model/primitives.d.ts +19 -0
- package/dist/model/primitives.d.ts.map +1 -0
- package/dist/model/primitives.js +18 -0
- package/dist/model/primitives.js.map +1 -0
- package/dist/model/pypi.d.ts +12 -0
- package/dist/model/pypi.d.ts.map +1 -0
- package/dist/model/pypi.js +20 -0
- package/dist/model/pypi.js.map +1 -0
- package/dist/model/python-distribution.d.ts +33 -0
- package/dist/model/python-distribution.d.ts.map +1 -0
- package/dist/model/python-distribution.js +367 -0
- package/dist/model/python-distribution.js.map +1 -0
- package/dist/model/secret-patterns.d.ts +2 -0
- package/dist/model/secret-patterns.d.ts.map +1 -0
- package/dist/model/secret-patterns.js +12 -0
- package/dist/model/secret-patterns.js.map +1 -0
- package/dist/platform/bun.d.ts +7 -0
- package/dist/platform/bun.d.ts.map +1 -0
- package/dist/platform/bun.js +15 -0
- package/dist/platform/bun.js.map +1 -0
- package/dist/platform/credentials.d.ts +32 -0
- package/dist/platform/credentials.d.ts.map +1 -0
- package/dist/platform/credentials.js +772 -0
- package/dist/platform/credentials.js.map +1 -0
- package/dist/platform/host-support.d.ts +2 -0
- package/dist/platform/host-support.d.ts.map +1 -0
- package/dist/platform/host-support.js +4 -0
- package/dist/platform/host-support.js.map +1 -0
- package/dist/platform/node.d.ts +7 -0
- package/dist/platform/node.d.ts.map +1 -0
- package/dist/platform/node.js +15 -0
- package/dist/platform/node.js.map +1 -0
- package/dist/platform/release-runtime.d.ts +11 -0
- package/dist/platform/release-runtime.d.ts.map +1 -0
- package/dist/platform/release-runtime.js +34 -0
- package/dist/platform/release-runtime.js.map +1 -0
- package/dist/platform/services.d.ts +15 -0
- package/dist/platform/services.d.ts.map +1 -0
- package/dist/platform/services.js +30 -0
- package/dist/platform/services.js.map +1 -0
- package/dist/platform/source-observer.d.ts +5 -0
- package/dist/platform/source-observer.d.ts.map +1 -0
- package/dist/platform/source-observer.js +159 -0
- package/dist/platform/source-observer.js.map +1 -0
- package/dist/provider-sdk.d.ts +14 -0
- package/dist/provider-sdk.d.ts.map +1 -0
- package/dist/provider-sdk.js +10 -0
- package/dist/provider-sdk.js.map +1 -0
- package/dist/publication/adapter.d.ts +212 -0
- package/dist/publication/adapter.d.ts.map +1 -0
- package/dist/publication/adapter.js +83 -0
- package/dist/publication/adapter.js.map +1 -0
- package/dist/publication/authority.d.ts +137 -0
- package/dist/publication/authority.d.ts.map +1 -0
- package/dist/publication/authority.js +233 -0
- package/dist/publication/authority.js.map +1 -0
- package/dist/publication/catalog-git.d.ts +37 -0
- package/dist/publication/catalog-git.d.ts.map +1 -0
- package/dist/publication/catalog-git.js +451 -0
- package/dist/publication/catalog-git.js.map +1 -0
- package/dist/publication/claim.d.ts +39 -0
- package/dist/publication/claim.d.ts.map +1 -0
- package/dist/publication/claim.js +31 -0
- package/dist/publication/claim.js.map +1 -0
- package/dist/publication/coordinator.d.ts +246 -0
- package/dist/publication/coordinator.d.ts.map +1 -0
- package/dist/publication/coordinator.js +370 -0
- package/dist/publication/coordinator.js.map +1 -0
- package/dist/publication/github.d.ts +36 -0
- package/dist/publication/github.d.ts.map +1 -0
- package/dist/publication/github.js +644 -0
- package/dist/publication/github.js.map +1 -0
- package/dist/publication/http.d.ts +69 -0
- package/dist/publication/http.d.ts.map +1 -0
- package/dist/publication/http.js +29 -0
- package/dist/publication/http.js.map +1 -0
- package/dist/publication/index.d.ts +5 -0
- package/dist/publication/index.d.ts.map +1 -0
- package/dist/publication/index.js +5 -0
- package/dist/publication/index.js.map +1 -0
- package/dist/publication/npm.d.ts +40 -0
- package/dist/publication/npm.d.ts.map +1 -0
- package/dist/publication/npm.js +359 -0
- package/dist/publication/npm.js.map +1 -0
- package/dist/publication/profiles.d.ts +136 -0
- package/dist/publication/profiles.d.ts.map +1 -0
- package/dist/publication/profiles.js +90 -0
- package/dist/publication/profiles.js.map +1 -0
- package/dist/publication/publisher.d.ts +82 -0
- package/dist/publication/publisher.d.ts.map +1 -0
- package/dist/publication/publisher.js +53 -0
- package/dist/publication/publisher.js.map +1 -0
- package/dist/publication/pypi.d.ts +45 -0
- package/dist/publication/pypi.d.ts.map +1 -0
- package/dist/publication/pypi.js +369 -0
- package/dist/publication/pypi.js.map +1 -0
- package/dist/publication/recovery.d.ts +663 -0
- package/dist/publication/recovery.d.ts.map +1 -0
- package/dist/publication/recovery.js +252 -0
- package/dist/publication/recovery.js.map +1 -0
- package/dist/publication/report.d.ts +1061 -0
- package/dist/publication/report.d.ts.map +1 -0
- package/dist/publication/report.js +441 -0
- package/dist/publication/report.js.map +1 -0
- package/dist/recipes/config.d.ts +296 -0
- package/dist/recipes/config.d.ts.map +1 -0
- package/dist/recipes/config.js +325 -0
- package/dist/recipes/config.js.map +1 -0
- package/dist/release/capabilities.d.ts +12 -0
- package/dist/release/capabilities.d.ts.map +1 -0
- package/dist/release/capabilities.js +395 -0
- package/dist/release/capabilities.js.map +1 -0
- package/dist/release/compiler.d.ts +5 -0
- package/dist/release/compiler.d.ts.map +1 -0
- package/dist/release/compiler.js +19 -0
- package/dist/release/compiler.js.map +1 -0
- package/dist/release/config.d.ts +5 -0
- package/dist/release/config.d.ts.map +1 -0
- package/dist/release/config.js +10 -0
- package/dist/release/config.js.map +1 -0
- package/dist/release/context.d.ts +96 -0
- package/dist/release/context.d.ts.map +1 -0
- package/dist/release/context.js +168 -0
- package/dist/release/context.js.map +1 -0
- package/dist/release/graph.d.ts +271 -0
- package/dist/release/graph.d.ts.map +1 -0
- package/dist/release/graph.js +766 -0
- package/dist/release/graph.js.map +1 -0
- package/dist/release/inspect.d.ts +88 -0
- package/dist/release/inspect.d.ts.map +1 -0
- package/dist/release/inspect.js +75 -0
- package/dist/release/inspect.js.map +1 -0
- package/dist/release/prepare.d.ts +24 -0
- package/dist/release/prepare.d.ts.map +1 -0
- package/dist/release/prepare.js +1116 -0
- package/dist/release/prepare.js.map +1 -0
- package/dist/release/prepared-ref.d.ts +60 -0
- package/dist/release/prepared-ref.d.ts.map +1 -0
- package/dist/release/prepared-ref.js +131 -0
- package/dist/release/prepared-ref.js.map +1 -0
- package/dist/release/prepared-store.d.ts +90 -0
- package/dist/release/prepared-store.d.ts.map +1 -0
- package/dist/release/prepared-store.js +337 -0
- package/dist/release/prepared-store.js.map +1 -0
- package/dist/release/prepared.d.ts +172 -0
- package/dist/release/prepared.d.ts.map +1 -0
- package/dist/release/prepared.js +268 -0
- package/dist/release/prepared.js.map +1 -0
- package/dist/release/staging.d.ts +31 -0
- package/dist/release/staging.d.ts.map +1 -0
- package/dist/release/staging.js +218 -0
- package/dist/release/staging.js.map +1 -0
- package/dist/resolve/authored.d.ts +53 -0
- package/dist/resolve/authored.d.ts.map +1 -0
- package/dist/resolve/authored.js +55 -0
- package/dist/resolve/authored.js.map +1 -0
- package/dist/resolve/encode.d.ts +3 -0
- package/dist/resolve/encode.d.ts.map +1 -0
- package/dist/resolve/encode.js +21 -0
- package/dist/resolve/encode.js.map +1 -0
- package/dist/resolve/errors.d.ts +7 -0
- package/dist/resolve/errors.d.ts.map +1 -0
- package/dist/resolve/errors.js +17 -0
- package/dist/resolve/errors.js.map +1 -0
- package/dist/resolve/facts.d.ts +12 -0
- package/dist/resolve/facts.d.ts.map +1 -0
- package/dist/resolve/facts.js +18 -0
- package/dist/resolve/facts.js.map +1 -0
- package/dist/resolve/resolve.d.ts +10 -0
- package/dist/resolve/resolve.d.ts.map +1 -0
- package/dist/resolve/resolve.js +242 -0
- package/dist/resolve/resolve.js.map +1 -0
- package/dist/store.d.ts +11 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +9 -0
- package/dist/store.js.map +1 -0
- package/examples/README.md +20 -30
- package/examples/github-release/release.config.json +11 -18
- package/examples/homebrew-tap/README.md +11 -0
- package/examples/homebrew-tap/release.config.json +40 -28
- package/examples/multi-target/release.config.json +28 -53
- package/examples/npm-first-publish/release.config.json +23 -25
- package/examples/npm-only/release.config.json +22 -30
- package/examples/portable-cli/README.md +17 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-arm64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-x64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-arm64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-x64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-windows-x64.exe +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_10_15_x86_64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_11_0_arm64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_aarch64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_x86_64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-win_amd64.whl +1 -0
- package/examples/portable-cli/package.json +9 -0
- package/examples/portable-cli/release.config.json +53 -0
- package/examples/portable-cli/src/cli.ts +3 -0
- package/examples/pypi-registry/README.md +8 -0
- package/examples/scoop-bucket/README.md +10 -0
- package/examples/scoop-bucket/release.config.json +40 -30
- package/package.json +61 -154
- package/src/api/api.ts +365 -0
- package/src/api/errors.ts +36 -0
- package/src/api/input.ts +92 -0
- package/src/api/runtime.ts +14 -0
- package/src/api/types.ts +103 -0
- package/src/capabilities/bun-targets.ts +2 -0
- package/src/capabilities/field-ownership.ts +60 -0
- package/src/capabilities/module.ts +158 -0
- package/src/capabilities/registry.ts +333 -0
- package/src/config/config.ts +48 -0
- package/src/correction/coordinator.ts +336 -0
- package/src/correction/index.ts +2 -0
- package/src/correction/intent.ts +172 -0
- package/src/drivers/archive.ts +102 -0
- package/src/drivers/contain.ts +20 -0
- package/src/drivers/environment.ts +28 -0
- package/src/drivers/errors.ts +6 -0
- package/src/drivers/glob.ts +137 -0
- package/src/drivers/process.ts +340 -0
- package/src/drivers/redact.ts +31 -0
- package/src/drivers/seccomp-helper-source.ts +121 -0
- package/src/drivers/utils.ts +10 -0
- package/src/drivers/workspace.ts +40 -0
- package/src/extensions/provider-adapter.ts +99 -0
- package/src/host.ts +140 -0
- package/src/index.ts +64 -0
- package/src/model/artifact-collection.ts +237 -0
- package/src/model/authority.ts +116 -0
- package/src/model/bun-targets.ts +34 -0
- package/src/model/canonical.ts +205 -0
- package/src/model/catalog.ts +220 -0
- package/src/model/digest.ts +172 -0
- package/src/model/errors.ts +6 -0
- package/src/model/primitives.ts +37 -0
- package/src/model/pypi.ts +30 -0
- package/src/model/python-distribution.ts +360 -0
- package/src/model/secret-patterns.ts +11 -0
- package/src/platform/bun.ts +38 -0
- package/src/platform/credentials.ts +1083 -0
- package/src/platform/host-support.ts +4 -0
- package/src/platform/node.ts +38 -0
- package/src/platform/release-runtime.ts +47 -0
- package/src/platform/services.ts +57 -0
- package/src/platform/source-observer.ts +193 -0
- package/src/provider-sdk.ts +48 -0
- package/src/publication/adapter.ts +132 -0
- package/src/publication/authority.ts +397 -0
- package/src/publication/catalog-git.ts +603 -0
- package/src/publication/claim.ts +51 -0
- package/src/publication/coordinator.ts +578 -0
- package/src/publication/github.ts +954 -0
- package/src/publication/http.ts +101 -0
- package/src/publication/index.ts +4 -0
- package/src/publication/npm.ts +525 -0
- package/src/publication/profiles.ts +94 -0
- package/src/publication/publisher.ts +130 -0
- package/src/publication/pypi.ts +463 -0
- package/src/publication/recovery.ts +349 -0
- package/src/publication/report.ts +628 -0
- package/src/recipes/config.ts +395 -0
- package/src/release/capabilities.ts +459 -0
- package/src/release/compiler.ts +28 -0
- package/src/release/config.ts +12 -0
- package/src/release/context.ts +223 -0
- package/src/release/graph.ts +866 -0
- package/src/release/inspect.ts +83 -0
- package/src/release/prepare.ts +1331 -0
- package/src/release/prepared-ref.ts +193 -0
- package/src/release/prepared-store.ts +377 -0
- package/src/release/prepared.ts +299 -0
- package/src/release/staging.ts +257 -0
- package/src/resolve/authored.ts +64 -0
- package/src/resolve/encode.ts +22 -0
- package/src/resolve/errors.ts +15 -0
- package/src/resolve/facts.ts +18 -0
- package/src/resolve/resolve.ts +328 -0
- package/src/store.ts +28 -0
- package/templates/README.md +55 -59
- package/templates/bun-cli-github/README.md +12 -0
- package/templates/bun-cli-github/release.config.json +51 -0
- package/templates/github-actions/release.yml +57 -0
- package/templates/github-actions/reviewed-release.yml +80 -0
- package/templates/multi-target-homebrew/README.md +10 -0
- package/templates/multi-target-homebrew/release.config.json +43 -60
- package/templates/multi-target-scoop/README.md +10 -0
- package/templates/multi-target-scoop/release.config.json +43 -62
- package/templates/npm-github/release.config.json +25 -38
- package/templates/npm-github/reviewed-release.config.json +37 -0
- package/templates/npm-only/README.md +10 -0
- package/templates/npm-only/release.config.json +15 -30
- package/templates/portable-cli/README.md +13 -0
- package/templates/portable-cli/release.config.json +53 -0
- package/dist/config/errors.d.ts +0 -24
- package/dist/config/errors.d.ts.map +0 -1
- package/dist/config/errors.js +0 -19
- package/dist/config/errors.js.map +0 -1
- package/dist/config/load.d.ts +0 -9
- package/dist/config/load.d.ts.map +0 -1
- package/dist/config/load.js +0 -29
- package/dist/config/load.js.map +0 -1
- package/dist/config/schema.d.ts +0 -12
- package/dist/config/schema.d.ts.map +0 -1
- package/dist/config/schema.js +0 -19
- package/dist/config/schema.js.map +0 -1
- package/dist/domain/artifact.d.ts +0 -36
- package/dist/domain/artifact.d.ts.map +0 -1
- package/dist/domain/artifact.js +0 -29
- package/dist/domain/artifact.js.map +0 -1
- package/dist/domain/evidence.d.ts +0 -108
- package/dist/domain/evidence.d.ts.map +0 -1
- package/dist/domain/evidence.js +0 -96
- package/dist/domain/evidence.js.map +0 -1
- package/dist/domain/operation.d.ts +0 -153
- package/dist/domain/operation.d.ts.map +0 -1
- package/dist/domain/operation.js +0 -320
- package/dist/domain/operation.js.map +0 -1
- package/dist/domain/release.d.ts +0 -141
- package/dist/domain/release.d.ts.map +0 -1
- package/dist/domain/release.js +0 -127
- package/dist/domain/release.js.map +0 -1
- package/dist/domain/remote-state.d.ts +0 -85
- package/dist/domain/remote-state.d.ts.map +0 -1
- package/dist/domain/remote-state.js +0 -77
- package/dist/domain/remote-state.js.map +0 -1
- package/dist/domain/status.d.ts +0 -43
- package/dist/domain/status.d.ts.map +0 -1
- package/dist/domain/status.js +0 -51
- package/dist/domain/status.js.map +0 -1
- package/dist/domain/target.d.ts +0 -135
- package/dist/domain/target.d.ts.map +0 -1
- package/dist/domain/target.js +0 -137
- package/dist/domain/target.js.map +0 -1
- package/dist/host/host.d.ts +0 -32
- package/dist/host/host.d.ts.map +0 -1
- package/dist/host/host.js +0 -24
- package/dist/host/host.js.map +0 -1
- package/dist/host/http-live.d.ts +0 -6
- package/dist/host/http-live.d.ts.map +0 -1
- package/dist/host/http-live.js +0 -86
- package/dist/host/http-live.js.map +0 -1
- package/dist/host/http.d.ts +0 -43
- package/dist/host/http.d.ts.map +0 -1
- package/dist/host/http.js +0 -59
- package/dist/host/http.js.map +0 -1
- package/dist/host/platform.d.ts +0 -10
- package/dist/host/platform.d.ts.map +0 -1
- package/dist/host/platform.js +0 -114
- package/dist/host/platform.js.map +0 -1
- package/dist/host/test.d.ts +0 -23
- package/dist/host/test.d.ts.map +0 -1
- package/dist/host/test.js +0 -222
- package/dist/host/test.js.map +0 -1
- package/dist/internal/workflow-phases.d.ts +0 -3
- package/dist/internal/workflow-phases.d.ts.map +0 -1
- package/dist/internal/workflow-phases.js +0 -2
- package/dist/internal/workflow-phases.js.map +0 -1
- package/dist/internal/workspace-path.d.ts +0 -15
- package/dist/internal/workspace-path.d.ts.map +0 -1
- package/dist/internal/workspace-path.js +0 -36
- package/dist/internal/workspace-path.js.map +0 -1
- package/dist/planner/artifact-inventory.d.ts +0 -9
- package/dist/planner/artifact-inventory.d.ts.map +0 -1
- package/dist/planner/artifact-inventory.js +0 -84
- package/dist/planner/artifact-inventory.js.map +0 -1
- package/dist/planner/create-release-plan.d.ts +0 -5
- package/dist/planner/create-release-plan.d.ts.map +0 -1
- package/dist/planner/create-release-plan.js +0 -25
- package/dist/planner/create-release-plan.js.map +0 -1
- package/dist/planner/errors.d.ts +0 -81
- package/dist/planner/errors.d.ts.map +0 -1
- package/dist/planner/errors.js +0 -70
- package/dist/planner/errors.js.map +0 -1
- package/dist/planner/evidence-recorder.d.ts +0 -26
- package/dist/planner/evidence-recorder.d.ts.map +0 -1
- package/dist/planner/evidence-recorder.js +0 -330
- package/dist/planner/evidence-recorder.js.map +0 -1
- package/dist/planner/executor.d.ts +0 -58
- package/dist/planner/executor.d.ts.map +0 -1
- package/dist/planner/executor.js +0 -159
- package/dist/planner/executor.js.map +0 -1
- package/dist/planner/normalize-release.d.ts +0 -16
- package/dist/planner/normalize-release.d.ts.map +0 -1
- package/dist/planner/normalize-release.js +0 -218
- package/dist/planner/normalize-release.js.map +0 -1
- package/dist/planner/reconcile.d.ts +0 -17
- package/dist/planner/reconcile.d.ts.map +0 -1
- package/dist/planner/reconcile.js +0 -261
- package/dist/planner/reconcile.js.map +0 -1
- package/dist/planner/release-eligibility.d.ts +0 -39
- package/dist/planner/release-eligibility.d.ts.map +0 -1
- package/dist/planner/release-eligibility.js +0 -578
- package/dist/planner/release-eligibility.js.map +0 -1
- package/dist/planner/render-plan.d.ts +0 -15
- package/dist/planner/render-plan.d.ts.map +0 -1
- package/dist/planner/render-plan.js +0 -238
- package/dist/planner/render-plan.js.map +0 -1
- package/dist/planner/status.d.ts +0 -40
- package/dist/planner/status.d.ts.map +0 -1
- package/dist/planner/status.js +0 -313
- package/dist/planner/status.js.map +0 -1
- package/dist/targets/adapter-helpers.d.ts +0 -64
- package/dist/targets/adapter-helpers.d.ts.map +0 -1
- package/dist/targets/adapter-helpers.js +0 -124
- package/dist/targets/adapter-helpers.js.map +0 -1
- package/dist/targets/adapter.d.ts +0 -17
- package/dist/targets/adapter.d.ts.map +0 -1
- package/dist/targets/adapter.js +0 -2
- package/dist/targets/adapter.js.map +0 -1
- package/dist/targets/github-release.d.ts +0 -25
- package/dist/targets/github-release.d.ts.map +0 -1
- package/dist/targets/github-release.js +0 -82
- package/dist/targets/github-release.js.map +0 -1
- package/dist/targets/github.d.ts +0 -11
- package/dist/targets/github.d.ts.map +0 -1
- package/dist/targets/github.js +0 -125
- package/dist/targets/github.js.map +0 -1
- package/dist/targets/homebrew.d.ts +0 -11
- package/dist/targets/homebrew.d.ts.map +0 -1
- package/dist/targets/homebrew.js +0 -97
- package/dist/targets/homebrew.js.map +0 -1
- package/dist/targets/live.d.ts +0 -5
- package/dist/targets/live.d.ts.map +0 -1
- package/dist/targets/live.js +0 -50
- package/dist/targets/live.js.map +0 -1
- package/dist/targets/npm.d.ts +0 -10
- package/dist/targets/npm.d.ts.map +0 -1
- package/dist/targets/npm.js +0 -118
- package/dist/targets/npm.js.map +0 -1
- package/dist/targets/pypi.d.ts +0 -11
- package/dist/targets/pypi.d.ts.map +0 -1
- package/dist/targets/pypi.js +0 -103
- package/dist/targets/pypi.js.map +0 -1
- package/dist/targets/registry.d.ts +0 -25
- package/dist/targets/registry.d.ts.map +0 -1
- package/dist/targets/registry.js +0 -34
- package/dist/targets/registry.js.map +0 -1
- package/dist/targets/scoop.d.ts +0 -11
- package/dist/targets/scoop.d.ts.map +0 -1
- package/dist/targets/scoop.js +0 -78
- package/dist/targets/scoop.js.map +0 -1
- package/dist/types/effect-internal.d.ts +0 -5
- package/dist/types/effect-internal.d.ts.map +0 -1
- package/dist/types/effect-internal.js +0 -2
- package/dist/types/effect-internal.js.map +0 -1
- package/dist/workflows/config.d.ts +0 -252
- package/dist/workflows/config.d.ts.map +0 -1
- package/dist/workflows/config.js +0 -465
- package/dist/workflows/config.js.map +0 -1
- package/dist/workflows/diagnostics.d.ts +0 -62
- package/dist/workflows/diagnostics.d.ts.map +0 -1
- package/dist/workflows/diagnostics.js +0 -527
- package/dist/workflows/diagnostics.js.map +0 -1
- package/dist/workflows/evidence.d.ts +0 -26
- package/dist/workflows/evidence.d.ts.map +0 -1
- package/dist/workflows/evidence.js +0 -44
- package/dist/workflows/evidence.js.map +0 -1
- package/dist/workflows/index.d.ts +0 -7
- package/dist/workflows/index.d.ts.map +0 -1
- package/dist/workflows/index.js +0 -6
- package/dist/workflows/index.js.map +0 -1
- package/dist/workflows/init.d.ts +0 -84
- package/dist/workflows/init.d.ts.map +0 -1
- package/dist/workflows/init.js +0 -441
- package/dist/workflows/init.js.map +0 -1
- package/dist/workflows/live.d.ts +0 -9
- package/dist/workflows/live.d.ts.map +0 -1
- package/dist/workflows/live.js +0 -7
- package/dist/workflows/live.js.map +0 -1
- package/dist/workflows/options.d.ts +0 -30
- package/dist/workflows/options.d.ts.map +0 -1
- package/dist/workflows/options.js +0 -16
- package/dist/workflows/options.js.map +0 -1
- package/examples/non-strict-skips/artifacts/release-example-skips-0.1.0.tgz +0 -1
- package/examples/non-strict-skips/release.config.json +0 -31
- package/examples/pypi-registry/release.config.json +0 -31
- package/templates/github-actions/plan-and-approved-execute.yml +0 -58
- package/templates/github-actions/plan-only.yml +0 -33
- package/templates/github-actions/trusted-publishing.yml +0 -61
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import * as Context from "effect/Context"
|
|
3
|
+
import * as Schema from "effect/Schema"
|
|
4
|
+
import type { SubjectId } from "../model/authority.js"
|
|
5
|
+
import type {
|
|
6
|
+
AnonymousAccess,
|
|
7
|
+
CredentialAuthorityError,
|
|
8
|
+
PublisherOperation,
|
|
9
|
+
ScopedSecret
|
|
10
|
+
} from "./authority.js"
|
|
11
|
+
|
|
12
|
+
/** Raw host transport failure. Provider meaning is assigned only by the
|
|
13
|
+
* authority-checking sink/adapter that knows whether dispatch started. */
|
|
14
|
+
export class PublicationHttpError
|
|
15
|
+
extends Schema.TaggedErrorClass<PublicationHttpError>()("PublicationHttpError", {
|
|
16
|
+
commitment: Schema.Literals(["before-dispatch", "unknown"]),
|
|
17
|
+
reason: Schema.String
|
|
18
|
+
}) {}
|
|
19
|
+
|
|
20
|
+
export type HttpRequest = {
|
|
21
|
+
readonly method: "GET" | "POST" | "PATCH"
|
|
22
|
+
readonly url: string
|
|
23
|
+
readonly headers?: Readonly<Record<string, string>>
|
|
24
|
+
readonly body?: Uint8Array | string
|
|
25
|
+
}
|
|
26
|
+
export type HttpResponse = {
|
|
27
|
+
readonly status: number
|
|
28
|
+
readonly headers: Readonly<Record<string, string>>
|
|
29
|
+
readonly body: Uint8Array | string
|
|
30
|
+
}
|
|
31
|
+
export type PublicationHttp = {
|
|
32
|
+
readonly request: (request: HttpRequest) => Effect.Effect<HttpResponse, PublicationHttpError>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Read-only HTTP intent; authorization is injected and consumed by the host. */
|
|
36
|
+
export interface HttpObservationRequest {
|
|
37
|
+
readonly subject: SubjectId
|
|
38
|
+
readonly method: "GET"
|
|
39
|
+
readonly url: string
|
|
40
|
+
readonly headers?: Readonly<Record<string, string>>
|
|
41
|
+
readonly body?: Uint8Array | string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Host failure shared by authorization implementations without exposing secrets. */
|
|
45
|
+
export interface HttpAuthorizationError {
|
|
46
|
+
readonly _tag: "CredentialPlatformError"
|
|
47
|
+
readonly phase: "observe" | "mutate" | "resource" | "spawn"
|
|
48
|
+
readonly commitment: "before-dispatch" | "unknown"
|
|
49
|
+
readonly reason: string
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface MutationHttpRequest {
|
|
53
|
+
readonly method: "POST" | "PATCH"
|
|
54
|
+
readonly url: string
|
|
55
|
+
readonly headers?: Readonly<Record<string, string>>
|
|
56
|
+
readonly body?: Uint8Array | string
|
|
57
|
+
/** Host-owned credential projection; callers still never receive the secret. */
|
|
58
|
+
readonly credentialScheme?: "bearer" | "pypi-token-basic"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface AuthorizedMutationHttpShape {
|
|
62
|
+
readonly execute: (
|
|
63
|
+
operation: PublisherOperation,
|
|
64
|
+
request: MutationHttpRequest,
|
|
65
|
+
grant: ScopedSecret
|
|
66
|
+
) => Effect.Effect<HttpResponse, CredentialAuthorityError | HttpAuthorizationError>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Host-owned mutation HTTP sink; callers never receive or inject credentials. */
|
|
70
|
+
export class AuthorizedMutationHttp
|
|
71
|
+
extends Context.Service<AuthorizedMutationHttp, AuthorizedMutationHttpShape>()(
|
|
72
|
+
"ts-release/AuthorizedMutationHttp"
|
|
73
|
+
) {}
|
|
74
|
+
|
|
75
|
+
export interface HttpAuthorizerShape {
|
|
76
|
+
readonly execute: (
|
|
77
|
+
input: HttpObservationRequest,
|
|
78
|
+
grant: AnonymousAccess | ScopedSecret
|
|
79
|
+
) => Effect.Effect<HttpResponse, CredentialAuthorityError | HttpAuthorizationError>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Opaque observation sink implemented by a host platform layer. */
|
|
83
|
+
export class HttpAuthorizer
|
|
84
|
+
extends Context.Service<HttpAuthorizer, HttpAuthorizerShape>()(
|
|
85
|
+
"ts-release/HttpAuthorizer"
|
|
86
|
+
) {}
|
|
87
|
+
|
|
88
|
+
export const bodyText = (response: HttpResponse): string => typeof response.body === "string"
|
|
89
|
+
? response.body : new TextDecoder("utf-8", { fatal: true }).decode(response.body)
|
|
90
|
+
|
|
91
|
+
export const bodyJson = (response: HttpResponse): unknown => {
|
|
92
|
+
try {
|
|
93
|
+
return JSON.parse(bodyText(response)) as unknown
|
|
94
|
+
} catch (cause) {
|
|
95
|
+
throw PublicationHttpError.make({ commitment: "before-dispatch", reason: cause instanceof Error ? cause.message : String(cause) })
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const authHeaders = (credential: string): Readonly<Record<string, string>> => ({
|
|
100
|
+
authorization: `Bearer ${credential}`, accept: "application/json"
|
|
101
|
+
})
|
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
import { join } from "node:path"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import type { CredentialRequest, ResolvedAuthStrategy } from "../model/authority.js"
|
|
4
|
+
import { CredentialRequest as CredentialRequestSchema } from "../model/authority.js"
|
|
5
|
+
import {
|
|
6
|
+
digestEquals,
|
|
7
|
+
formatNpmSha1Shasum,
|
|
8
|
+
formatNpmSha512Sri,
|
|
9
|
+
formatSha256Hex,
|
|
10
|
+
parseNpmSha1Shasum,
|
|
11
|
+
parseNpmSha512Sri,
|
|
12
|
+
sha1Digest,
|
|
13
|
+
sha256Digest,
|
|
14
|
+
sha512Digest,
|
|
15
|
+
type Sha1Digest,
|
|
16
|
+
type Sha512Digest
|
|
17
|
+
} from "../model/digest.js"
|
|
18
|
+
import { NonEmptyName } from "../model/primitives.js"
|
|
19
|
+
import type { PreparedNpmPublication } from "../release/prepared.js"
|
|
20
|
+
import type { PreparedBundle } from "../release/prepared-store.js"
|
|
21
|
+
import type { CredentialGrant, MutationCredentialGrant } from "./authority.js"
|
|
22
|
+
import type {
|
|
23
|
+
CertifiedPublisherResult,
|
|
24
|
+
CertifiedPublisherSpawnShape,
|
|
25
|
+
NpmPublishOperation,
|
|
26
|
+
NpmUserConfigResourceShape
|
|
27
|
+
} from "./publisher.js"
|
|
28
|
+
import type { HttpAuthorizerShape } from "./http.js"
|
|
29
|
+
import {
|
|
30
|
+
ReleaseSubjectError,
|
|
31
|
+
type ReleaseObservationContext,
|
|
32
|
+
type ReleaseSubject
|
|
33
|
+
} from "./coordinator.js"
|
|
34
|
+
import {
|
|
35
|
+
Conflict,
|
|
36
|
+
AbsenceBasis,
|
|
37
|
+
AuthoritativelyAbsent,
|
|
38
|
+
CreateAuthorizationProof,
|
|
39
|
+
Difference,
|
|
40
|
+
InconclusiveObservation,
|
|
41
|
+
MutationPrecondition,
|
|
42
|
+
NeedsMutation,
|
|
43
|
+
OutcomeUnknown,
|
|
44
|
+
PresentEquivalent,
|
|
45
|
+
PresentDifferent,
|
|
46
|
+
ProviderAlreadyEquivalent,
|
|
47
|
+
ProviderAuthorizedCreate,
|
|
48
|
+
ProviderBlocked,
|
|
49
|
+
RejectedBeforeDispatch,
|
|
50
|
+
SafeReason,
|
|
51
|
+
VisibilityBasis,
|
|
52
|
+
VisibilityPending,
|
|
53
|
+
type MutationDecision,
|
|
54
|
+
type Observation,
|
|
55
|
+
type ProviderDecision
|
|
56
|
+
} from "./report.js"
|
|
57
|
+
import { makeRecoveryCapabilityProfile } from "./recovery.js"
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Timing values are policy bounds, not measured provider facts. They remain
|
|
61
|
+
* ASSUMED/UNVERIFIED until an explicitly authorized live run records evidence.
|
|
62
|
+
*/
|
|
63
|
+
export const npmRecoveryCapabilityProfile = makeRecoveryCapabilityProfile({
|
|
64
|
+
observation: "conditional",
|
|
65
|
+
authoritativeAbsence: "provider-specific",
|
|
66
|
+
createAuthorization: "authenticated-namespace-and-unique-coordinate",
|
|
67
|
+
replay: "coordinate-unique",
|
|
68
|
+
identifierReuse: "consumed-after-delete",
|
|
69
|
+
// The authored correction surface currently produces an operator proposal;
|
|
70
|
+
// no conditional npm correction adapter is installed.
|
|
71
|
+
correction: [],
|
|
72
|
+
exposure: "persistent-to-consumers",
|
|
73
|
+
historyRequirement: "optional-evidence",
|
|
74
|
+
readConvergence: {
|
|
75
|
+
contract: {
|
|
76
|
+
_tag: "assumed",
|
|
77
|
+
basis: "ASSUMED/UNVERIFIED: no authorized live mutation evidence establishes npm read-convergence timing."
|
|
78
|
+
},
|
|
79
|
+
observationRetry: {
|
|
80
|
+
maxAttempts: 6,
|
|
81
|
+
backoff: { baseMs: 2_000, factor: 2, capMs: 30_000 },
|
|
82
|
+
totalBudgetMs: 120_000
|
|
83
|
+
},
|
|
84
|
+
retryEligible: "VisibilityPending | Inconclusive",
|
|
85
|
+
exhaustion: "UncertainSubject with full trace"
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
/** Primary provider documentation reviewed for this protocol implementation. */
|
|
90
|
+
export const npmProviderProtocolDocumentation = Object.freeze({
|
|
91
|
+
reviewedAt: "2026-08-12",
|
|
92
|
+
packageMetadata: "https://github.com/npm/registry/blob/main/docs/responses/package-metadata.md",
|
|
93
|
+
publish: "https://docs.npmjs.com/cli/v11/commands/npm-publish/",
|
|
94
|
+
distTags: "https://docs.npmjs.com/adding-dist-tags-to-packages/",
|
|
95
|
+
trustedPublishing: "https://docs.npmjs.com/trusted-publishers/"
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
type NpmPublicationContract = PreparedNpmPublication & {
|
|
99
|
+
readonly distTag: { readonly toString: () => string }
|
|
100
|
+
readonly access: "public" | "restricted"
|
|
101
|
+
readonly authentication:
|
|
102
|
+
| { readonly strategy: "token" }
|
|
103
|
+
| {
|
|
104
|
+
readonly strategy: "trusted-publishing"
|
|
105
|
+
readonly attestation: {
|
|
106
|
+
readonly provider: "github-actions"
|
|
107
|
+
readonly runner: "github-hosted"
|
|
108
|
+
readonly repository: string
|
|
109
|
+
readonly workflow: string
|
|
110
|
+
readonly workflowRef: string
|
|
111
|
+
readonly allowedAction: "npm-publish-direct"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
readonly provenance: "automatic" | "required" | "disabled"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const contractOf = (publication: PreparedNpmPublication): NpmPublicationContract =>
|
|
118
|
+
publication as NpmPublicationContract
|
|
119
|
+
|
|
120
|
+
const fingerprint = (value: string): SafeReason => SafeReason.make(
|
|
121
|
+
`provider value sha256-${formatSha256Hex(sha256Digest(new TextEncoder().encode(value)))}`
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
const registryEndpoint = (publication: NpmPublicationContract): string => {
|
|
125
|
+
const value = publication.registryUrl.toString()
|
|
126
|
+
return value.endsWith("/") ? value : `${value}/`
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const registryPackageUrl = (publication: NpmPublicationContract): string =>
|
|
130
|
+
`${registryEndpoint(publication)}${encodeURIComponent(publication.packageName).replace(/^%40/u, "@")}`
|
|
131
|
+
|
|
132
|
+
const asObject = (value: unknown): Readonly<Record<string, unknown>> | undefined =>
|
|
133
|
+
typeof value === "object" && value !== null && !Array.isArray(value)
|
|
134
|
+
? value as Readonly<Record<string, unknown>>
|
|
135
|
+
: undefined
|
|
136
|
+
|
|
137
|
+
const parseJson = (body: Uint8Array | string): unknown | undefined => {
|
|
138
|
+
try {
|
|
139
|
+
const text = typeof body === "string"
|
|
140
|
+
? body
|
|
141
|
+
: new TextDecoder("utf-8", { fatal: true }).decode(body)
|
|
142
|
+
return JSON.parse(text) as unknown
|
|
143
|
+
} catch {
|
|
144
|
+
return undefined
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
type RegistryPackageFacts = {
|
|
149
|
+
readonly name: string
|
|
150
|
+
readonly versions: Readonly<Record<string, unknown>>
|
|
151
|
+
readonly distTags: Readonly<Record<string, unknown>>
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const registryPackageFacts = (value: unknown): RegistryPackageFacts | undefined => {
|
|
155
|
+
const metadata = asObject(value)
|
|
156
|
+
if (metadata === undefined || typeof metadata.name !== "string") return undefined
|
|
157
|
+
const versions = asObject(metadata.versions)
|
|
158
|
+
const distTags = asObject(metadata["dist-tags"])
|
|
159
|
+
return versions === undefined || distTags === undefined
|
|
160
|
+
? undefined
|
|
161
|
+
: { name: metadata.name, versions, distTags }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
type RegistryVersionFacts = {
|
|
165
|
+
readonly name: string
|
|
166
|
+
readonly version: string
|
|
167
|
+
readonly integrity: Sha512Digest
|
|
168
|
+
readonly shasum: Sha1Digest
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const registryVersionFacts = (value: unknown): RegistryVersionFacts | undefined => {
|
|
172
|
+
const metadata = asObject(value)
|
|
173
|
+
const dist = metadata === undefined ? undefined : asObject(metadata.dist)
|
|
174
|
+
if (metadata === undefined || dist === undefined || typeof metadata.name !== "string" ||
|
|
175
|
+
typeof metadata.version !== "string") return undefined
|
|
176
|
+
try {
|
|
177
|
+
return {
|
|
178
|
+
name: metadata.name,
|
|
179
|
+
version: metadata.version,
|
|
180
|
+
integrity: parseNpmSha512Sri(dist.integrity),
|
|
181
|
+
shasum: parseNpmSha1Shasum(dist.shasum)
|
|
182
|
+
}
|
|
183
|
+
} catch {
|
|
184
|
+
return undefined
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const observationRequests = (
|
|
189
|
+
publication: PreparedNpmPublication
|
|
190
|
+
): readonly [CredentialRequest, ...Array<CredentialRequest>] => {
|
|
191
|
+
const make = (strategy: ResolvedAuthStrategy): CredentialRequest => CredentialRequestSchema.make({
|
|
192
|
+
subject: publication.authority.subject,
|
|
193
|
+
provider: publication.authority.provider,
|
|
194
|
+
audience: publication.authority.audience,
|
|
195
|
+
purpose: "observe",
|
|
196
|
+
strategy
|
|
197
|
+
})
|
|
198
|
+
const first = publication.authority.observationStrategies[0]!
|
|
199
|
+
return [make(first), ...publication.authority.observationStrategies.slice(1).map(make)]
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const mutationRequest = (publication: PreparedNpmPublication): CredentialRequest =>
|
|
203
|
+
CredentialRequestSchema.make({
|
|
204
|
+
subject: publication.authority.subject,
|
|
205
|
+
provider: publication.authority.provider,
|
|
206
|
+
audience: publication.authority.audience,
|
|
207
|
+
purpose: "publish",
|
|
208
|
+
strategy: publication.authority.publishStrategy
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
const inconclusive = (
|
|
212
|
+
publication: PreparedNpmPublication,
|
|
213
|
+
reason: string
|
|
214
|
+
): InconclusiveObservation => InconclusiveObservation.make({
|
|
215
|
+
subject: publication.authority.subject,
|
|
216
|
+
reason: SafeReason.make(reason)
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
const difference = (
|
|
220
|
+
field: "name" | "version" | "integrity" | "shasum" | "dist-tag",
|
|
221
|
+
expected: string,
|
|
222
|
+
observed: string
|
|
223
|
+
): Difference =>
|
|
224
|
+
Difference.make({
|
|
225
|
+
field: NonEmptyName.make(field),
|
|
226
|
+
expected: SafeReason.make(expected),
|
|
227
|
+
observed: fingerprint(observed)
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
const visibleVersionAbsent = (publication: NpmPublicationContract): AuthoritativelyAbsent =>
|
|
231
|
+
AuthoritativelyAbsent.make({
|
|
232
|
+
subject: publication.authority.subject,
|
|
233
|
+
basis: AbsenceBasis.make({
|
|
234
|
+
kind: NonEmptyName.make("npm-visible-package-version-absent"),
|
|
235
|
+
detail: SafeReason.make("Authoritative package metadata omitted the exact prepared version coordinate.")
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
const trustedDirectCreate = (publication: NpmPublicationContract): boolean =>
|
|
240
|
+
publication.authentication.strategy === "trusted-publishing" &&
|
|
241
|
+
publication.authentication.attestation.provider === "github-actions" &&
|
|
242
|
+
publication.authentication.attestation.runner === "github-hosted" &&
|
|
243
|
+
publication.authentication.attestation.allowedAction === "npm-publish-direct" &&
|
|
244
|
+
publication.authority.publishStrategy.kind === "trusted-publishing" &&
|
|
245
|
+
publication.authority.publishStrategy.repository === publication.authentication.attestation.repository &&
|
|
246
|
+
publication.authority.publishStrategy.workflow ===
|
|
247
|
+
`.github/workflows/${publication.authentication.attestation.workflow}` &&
|
|
248
|
+
publication.authority.publishStrategy.workflowRef === publication.authentication.attestation.workflowRef &&
|
|
249
|
+
publication.authority.publishStrategy.allowedAction === "npm-publish-direct" &&
|
|
250
|
+
publication.authority.publishStrategy.publisherSink === "certified-npm-cli"
|
|
251
|
+
|
|
252
|
+
const authorizedCreateAbsence = (publication: NpmPublicationContract): AuthoritativelyAbsent =>
|
|
253
|
+
AuthoritativelyAbsent.make({
|
|
254
|
+
subject: publication.authority.subject,
|
|
255
|
+
basis: AbsenceBasis.make({
|
|
256
|
+
kind: NonEmptyName.make("npm-trusted-direct-create"),
|
|
257
|
+
detail: SafeReason.make("The prepared trusted-publishing attestation authorizes this exact direct-create coordinate.")
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
const visibilityPending = (publication: NpmPublicationContract): VisibilityPending =>
|
|
262
|
+
VisibilityPending.make({
|
|
263
|
+
subject: publication.authority.subject,
|
|
264
|
+
expectation: SafeReason.make("The exact published npm version and dist-tag become visible."),
|
|
265
|
+
basis: VisibilityBasis.make({
|
|
266
|
+
kind: NonEmptyName.make("npm-post-publish-read"),
|
|
267
|
+
detail: SafeReason.make("The same invocation dispatched one publish and is rereading provider metadata only.")
|
|
268
|
+
})
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
const decide = (
|
|
272
|
+
publication: NpmPublicationContract,
|
|
273
|
+
observation: Observation
|
|
274
|
+
): ProviderDecision => {
|
|
275
|
+
switch (observation._tag) {
|
|
276
|
+
case "PresentEquivalent":
|
|
277
|
+
return ProviderAlreadyEquivalent.make({ subject: publication.authority.subject })
|
|
278
|
+
case "PresentDifferent":
|
|
279
|
+
return Conflict.make({ subject: publication.authority.subject, differences: observation.differences })
|
|
280
|
+
case "AuthoritativelyAbsent":
|
|
281
|
+
return observation.basis.kind === "npm-visible-package-version-absent"
|
|
282
|
+
? NeedsMutation.make({
|
|
283
|
+
subject: publication.authority.subject,
|
|
284
|
+
precondition: MutationPrecondition.make({ kind: NonEmptyName.make("npm-visible-package-version-absent") })
|
|
285
|
+
})
|
|
286
|
+
: trustedDirectCreate(publication) && observation.basis.kind === "npm-trusted-direct-create"
|
|
287
|
+
? ProviderAuthorizedCreate.make({
|
|
288
|
+
subject: publication.authority.subject,
|
|
289
|
+
proof: CreateAuthorizationProof.make({ kind: NonEmptyName.make("npm-trusted-direct-create") })
|
|
290
|
+
})
|
|
291
|
+
: ProviderBlocked.make({
|
|
292
|
+
subject: publication.authority.subject,
|
|
293
|
+
reason: SafeReason.make("The npm namespace has no exact prepared create authorization.")
|
|
294
|
+
})
|
|
295
|
+
case "VisibilityPending":
|
|
296
|
+
case "Inconclusive":
|
|
297
|
+
return ProviderBlocked.make({
|
|
298
|
+
subject: publication.authority.subject,
|
|
299
|
+
reason: SafeReason.make("npm observation did not prove exact equivalence or an authorized absent coordinate.")
|
|
300
|
+
})
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const publishOperation = (
|
|
305
|
+
publication: NpmPublicationContract,
|
|
306
|
+
decision: MutationDecision
|
|
307
|
+
): NpmPublishOperation => ({
|
|
308
|
+
_tag: "PublishOperation",
|
|
309
|
+
subject: publication.authority.subject,
|
|
310
|
+
provider: publication.authority.provider,
|
|
311
|
+
audience: publication.authority.audience,
|
|
312
|
+
purpose: "publish",
|
|
313
|
+
decision
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
const sinkFailure = (publication: NpmPublicationContract, cause: unknown): ReleaseSubjectError =>
|
|
317
|
+
new ReleaseSubjectError({
|
|
318
|
+
subject: publication.authority.subject,
|
|
319
|
+
phase: "mutate",
|
|
320
|
+
commitment: typeof cause === "object" && cause !== null && "commitment" in cause && cause.commitment === "unknown"
|
|
321
|
+
? "unknown"
|
|
322
|
+
: "before-dispatch",
|
|
323
|
+
reason: SafeReason.make("The certified npm publisher boundary rejected or lost the prepared operation.")
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
const publisherAttempt = (
|
|
327
|
+
publication: NpmPublicationContract,
|
|
328
|
+
result: CertifiedPublisherResult
|
|
329
|
+
): RejectedBeforeDispatch | OutcomeUnknown => result._tag === "RejectedBeforeStart"
|
|
330
|
+
? RejectedBeforeDispatch.make({
|
|
331
|
+
subject: publication.authority.subject,
|
|
332
|
+
reason: SafeReason.make("The certified npm publisher process did not start.")
|
|
333
|
+
})
|
|
334
|
+
: OutcomeUnknown.make({
|
|
335
|
+
subject: publication.authority.subject,
|
|
336
|
+
reason: SafeReason.make(result._tag === "PublisherExited"
|
|
337
|
+
? "The npm publisher started and exited; exact registry reobservation must establish its effect."
|
|
338
|
+
: "The npm publisher started, but its terminal process result was unavailable.")
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
const validMutationDecision = (
|
|
342
|
+
publication: NpmPublicationContract,
|
|
343
|
+
decision: MutationDecision
|
|
344
|
+
): boolean => decision._tag === "NeedsMutation"
|
|
345
|
+
? decision.precondition.kind === "npm-visible-package-version-absent"
|
|
346
|
+
: decision.proof.kind === "npm-trusted-direct-create" && trustedDirectCreate(publication)
|
|
347
|
+
|
|
348
|
+
/** Exact Plan-225 npm subject over host-owned observation, credential, and process sinks. */
|
|
349
|
+
export const makeNpmSubject = (
|
|
350
|
+
bundle: PreparedBundle,
|
|
351
|
+
publication: PreparedNpmPublication,
|
|
352
|
+
http: HttpAuthorizerShape,
|
|
353
|
+
userConfigs: NpmUserConfigResourceShape,
|
|
354
|
+
publisher: CertifiedPublisherSpawnShape
|
|
355
|
+
): ReleaseSubject => {
|
|
356
|
+
const intent = contractOf(publication)
|
|
357
|
+
const packageArtifact = bundle.manifest.artifacts.find((artifact) =>
|
|
358
|
+
artifact.id.toString() === intent.artifactId.toString())
|
|
359
|
+
const bytes = bundle.blobs.get(intent.artifactId.toString())
|
|
360
|
+
const expectedIntegrity = bytes === undefined ? undefined : sha512Digest(bytes)
|
|
361
|
+
const expectedShasum = bytes === undefined ? undefined : sha1Digest(bytes)
|
|
362
|
+
const tarballPath = packageArtifact === undefined
|
|
363
|
+
? undefined
|
|
364
|
+
: join(bundle.directory, "blobs", packageArtifact.blob.hex)
|
|
365
|
+
|
|
366
|
+
const observe = Effect.fn("NpmReleaseSubject.observe")(function*(
|
|
367
|
+
grant: CredentialGrant,
|
|
368
|
+
context: ReleaseObservationContext
|
|
369
|
+
) {
|
|
370
|
+
if (bytes === undefined || packageArtifact === undefined || tarballPath === undefined ||
|
|
371
|
+
expectedIntegrity === undefined || expectedShasum === undefined) {
|
|
372
|
+
return inconclusive(intent, "The exact prepared npm artifact bytes are unavailable.")
|
|
373
|
+
}
|
|
374
|
+
if (grant._tag === "WorkloadIdentity") {
|
|
375
|
+
return yield* new ReleaseSubjectError({
|
|
376
|
+
subject: publication.authority.subject,
|
|
377
|
+
phase: "observe",
|
|
378
|
+
commitment: "before-dispatch",
|
|
379
|
+
reason: SafeReason.make("Workload identity cannot authorize npm metadata observation.")
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
const response = yield* http.execute({
|
|
383
|
+
subject: intent.authority.subject,
|
|
384
|
+
method: "GET",
|
|
385
|
+
url: registryPackageUrl(intent),
|
|
386
|
+
headers: { accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8" }
|
|
387
|
+
}, grant).pipe(Effect.mapError((cause) => new ReleaseSubjectError({
|
|
388
|
+
subject: intent.authority.subject,
|
|
389
|
+
phase: "observe",
|
|
390
|
+
commitment: cause._tag === "CredentialPlatformError" ? cause.commitment : "before-dispatch",
|
|
391
|
+
reason: SafeReason.make("npm metadata observation could not be completed by the host HTTP boundary.")
|
|
392
|
+
})))
|
|
393
|
+
|
|
394
|
+
if (response.status === 404) {
|
|
395
|
+
if (context.phase === "post-mutation" && context.attempt._tag !== "RejectedBeforeDispatch") {
|
|
396
|
+
return visibilityPending(intent)
|
|
397
|
+
}
|
|
398
|
+
return trustedDirectCreate(intent)
|
|
399
|
+
? authorizedCreateAbsence(intent)
|
|
400
|
+
: inconclusive(intent, "npm package visibility is unavailable and no trusted direct-create proof exists.")
|
|
401
|
+
}
|
|
402
|
+
if (response.status < 200 || response.status >= 300) {
|
|
403
|
+
return inconclusive(intent, `npm metadata observation returned HTTP ${response.status}.`)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const packument = registryPackageFacts(parseJson(response.body))
|
|
407
|
+
if (packument === undefined) {
|
|
408
|
+
return inconclusive(intent, "npm package metadata was malformed or omitted versions or dist-tags.")
|
|
409
|
+
}
|
|
410
|
+
if (packument.name !== intent.packageName) {
|
|
411
|
+
return PresentDifferent.make({
|
|
412
|
+
subject: intent.authority.subject,
|
|
413
|
+
differences: [difference("name", intent.packageName.toString(), packument.name)]
|
|
414
|
+
})
|
|
415
|
+
}
|
|
416
|
+
const rawVersion = packument.versions[intent.version.toString()]
|
|
417
|
+
if (rawVersion === undefined) {
|
|
418
|
+
return context.phase === "post-mutation" && context.attempt._tag !== "RejectedBeforeDispatch"
|
|
419
|
+
? visibilityPending(intent)
|
|
420
|
+
: visibleVersionAbsent(intent)
|
|
421
|
+
}
|
|
422
|
+
const observed = registryVersionFacts(rawVersion)
|
|
423
|
+
if (observed === undefined) return inconclusive(intent, "The exact npm version metadata was malformed.")
|
|
424
|
+
|
|
425
|
+
const differences: Array<Difference> = []
|
|
426
|
+
if (observed.name !== intent.packageName) {
|
|
427
|
+
differences.push(difference("name", intent.packageName.toString(), observed.name))
|
|
428
|
+
}
|
|
429
|
+
if (observed.version !== intent.version) {
|
|
430
|
+
differences.push(difference("version", intent.version.toString(), observed.version))
|
|
431
|
+
}
|
|
432
|
+
if (!digestEquals(observed.integrity, expectedIntegrity)) {
|
|
433
|
+
differences.push(difference(
|
|
434
|
+
"integrity",
|
|
435
|
+
formatNpmSha512Sri(expectedIntegrity),
|
|
436
|
+
formatNpmSha512Sri(observed.integrity)
|
|
437
|
+
))
|
|
438
|
+
}
|
|
439
|
+
if (!digestEquals(observed.shasum, expectedShasum)) {
|
|
440
|
+
differences.push(difference(
|
|
441
|
+
"shasum",
|
|
442
|
+
formatNpmSha1Shasum(expectedShasum),
|
|
443
|
+
formatNpmSha1Shasum(observed.shasum)
|
|
444
|
+
))
|
|
445
|
+
}
|
|
446
|
+
if (differences.length > 0) {
|
|
447
|
+
return PresentDifferent.make({
|
|
448
|
+
subject: intent.authority.subject,
|
|
449
|
+
differences: differences as [Difference, ...Array<Difference>]
|
|
450
|
+
})
|
|
451
|
+
}
|
|
452
|
+
const tag = packument.distTags[intent.distTag.toString()]
|
|
453
|
+
if (tag !== intent.version) {
|
|
454
|
+
if (context.phase === "post-mutation" && context.attempt._tag !== "RejectedBeforeDispatch") {
|
|
455
|
+
return visibilityPending(intent)
|
|
456
|
+
}
|
|
457
|
+
return PresentDifferent.make({
|
|
458
|
+
subject: intent.authority.subject,
|
|
459
|
+
differences: [difference(
|
|
460
|
+
"dist-tag",
|
|
461
|
+
intent.version.toString(),
|
|
462
|
+
typeof tag === "string" ? tag : "<missing>"
|
|
463
|
+
)]
|
|
464
|
+
})
|
|
465
|
+
}
|
|
466
|
+
return PresentEquivalent.make({ subject: intent.authority.subject })
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
const mutate = (
|
|
470
|
+
decision: MutationDecision,
|
|
471
|
+
grant: MutationCredentialGrant
|
|
472
|
+
) => {
|
|
473
|
+
if (!validMutationDecision(intent, decision) || tarballPath === undefined) {
|
|
474
|
+
return Effect.fail(new ReleaseSubjectError({
|
|
475
|
+
subject: intent.authority.subject,
|
|
476
|
+
phase: "mutate",
|
|
477
|
+
commitment: "before-dispatch",
|
|
478
|
+
reason: SafeReason.make("The npm mutation lacks its exact prepared absence proof or tarball path.")
|
|
479
|
+
}))
|
|
480
|
+
}
|
|
481
|
+
const operation = publishOperation(intent, decision)
|
|
482
|
+
const publisherSpec = {
|
|
483
|
+
operation,
|
|
484
|
+
cwd: bundle.directory,
|
|
485
|
+
tarballPath,
|
|
486
|
+
packageName: intent.packageName,
|
|
487
|
+
version: intent.version,
|
|
488
|
+
registryUrl: intent.registryUrl,
|
|
489
|
+
distTag: intent.distTag,
|
|
490
|
+
access: intent.access,
|
|
491
|
+
provenance: intent.provenance
|
|
492
|
+
} as const
|
|
493
|
+
return Effect.scoped(Effect.gen(function*() {
|
|
494
|
+
if (grant._tag === "WorkloadIdentity") {
|
|
495
|
+
yield* publisher.preflightTrustedNpm(operation, grant)
|
|
496
|
+
return yield* publisher.spawn({
|
|
497
|
+
_tag: "WorkloadPublisherSpec",
|
|
498
|
+
...publisherSpec
|
|
499
|
+
}, grant)
|
|
500
|
+
}
|
|
501
|
+
const userConfig = yield* userConfigs.acquire({
|
|
502
|
+
operation,
|
|
503
|
+
registryUrl: registryEndpoint(intent)
|
|
504
|
+
}, grant)
|
|
505
|
+
return yield* publisher.spawn({
|
|
506
|
+
_tag: "NpmPublisherSpec",
|
|
507
|
+
...publisherSpec,
|
|
508
|
+
userConfig
|
|
509
|
+
}, grant)
|
|
510
|
+
})).pipe(
|
|
511
|
+
Effect.map((result) => publisherAttempt(intent, result)),
|
|
512
|
+
Effect.mapError((cause) => sinkFailure(intent, cause))
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return {
|
|
517
|
+
id: intent.authority.subject,
|
|
518
|
+
recovery: npmRecoveryCapabilityProfile,
|
|
519
|
+
observationRequests: observationRequests(intent),
|
|
520
|
+
mutationRequest: mutationRequest(intent),
|
|
521
|
+
observe,
|
|
522
|
+
decide: (observation) => decide(intent, observation),
|
|
523
|
+
mutate
|
|
524
|
+
}
|
|
525
|
+
}
|