Repository navigation
feat(npmprofile): Pin the publish npm CLI and Node.js toolchain with digest-verified provisioning - #131
Conversation
Implement the ADR 0082/0083/0084 specification surface for the npm M1 dogfood retry: - Add the publish-stage npm CLI allowlist with the initial entry npm 11.21.0 (tarball URL + SHA-512 SRI pin data), the 12026-10-13 internals-checklist and registry cross-check review note, and the recorded deviation that npm/cli published no git tag or GitHub Release for v11.21.0 so the gitHead cross-check resolves at the release-commit level. - Specify digest-verified registry-tarball provisioning before any npm invocation in the publish job, including diagnostics. - Redefine the publish-side version contract as allowlist pin validation, replacing the build/publish npm equality check, and record the publish npm version in outcome evidence as publish_npm_version. - Finalize the authentication path per ADR 0083: npm-native trusted publishing with the ADR 0076 exchange preflight retained as a non-mutating observation whose minted token is discarded. - Register the five new publish-side diagnostics (npm-provision-download, npm-provision-digest-mismatch, npm-provision-archive-unsafe, npm-provision-version-mismatch, publish-npm-pin-mismatch) in the closed registry and the shared taxonomy. Signed-off-by: Yunseo Kim <[email protected]>
- Add the pinned runtime table (Node.js 24.21.0, bundled npm 11.19.0) to the build and pack specification with internal/toolchainpins/node-runtime.json as the single shared machine-readable definition and a CI drift check. - Specify the pre-install pair assertion: exact node/npm version equality with the recorded pair before the first npm invocation in each job that uses the bundled npm, failing closed with toolchain-pair-mismatch; the publish job runs the assertion in node-only mode under ADR 0082/0084. - Replace floating Node.js 24 descriptions in the build-pack and package-profile specifications with the exact pinned patch; retain the npm >= 11.5.1 floor and runtime.npm_version recording semantics as defense in depth. - Complete the PURL-derivation compatibility fixture keying with the build-side half and register toolchain-pair-mismatch and toolchain-pin-drift in the closed registry and shared taxonomy. Signed-off-by: Yunseo Kim <[email protected]>
Create internal/toolchainpins holding the two builder-owned machine-readable records as embedded files with strictly decoded, concurrency-safe typed loaders: - publish-npm.json: the ADR 0082/0084 publish-stage npm pin (npm 11.21.0, exact registry tarball URL, SHA-512 SRI byte-identical to the packument dist.integrity). - node-runtime.json: the ADR 0085 build toolchain pair (Node.js 24.21.0, bundled npm 11.19.0). Decoding reuses canonicaljson duplicate-member rejection, rejects unknown fields, and validates exact three-part SemVer versions, uncredentialed HTTPS tarball URLs, and sha512 SRI form with a 64-byte digest. go:embed makes the single-shared-definition property structural: the provisioning step, publish-side pin validation, and the pair assertion all read these records by import. Signed-off-by: Yunseo Kim <[email protected]>
…rball Implement ADR 0084 provisioning and the npm-profile-provision-npm subcommand: - Download only the embedded pin URL through the hardened fetcher, verify the compressed SHA-512 against the pinned SRI before creating any directory, extract into a private per-job directory with the existing no-links archive policy (duplicate-entry rejection, bounded decompressed bytes and entry count, gzip drain against truncation), and validate the extracted package.json version and CLI entry against the pin. - Emit a private launcher named npm that execs the resolved absolute node path against package/bin/npm-cli.js; provisioning executes neither node nor npm, keeping every failure pre-execution and pre-mutation. Partial extractions are removed on failure. - Map failures to the registered diagnostics npm-provision-download, npm-provision-digest-mismatch, npm-provision-archive-unsafe, and npm-provision-version-mismatch (check npm.publish.provision). - Register FuzzExtractNPMDistribution in both fuzz CI matrices per the testing guide. Verified live (SLSA_BUILDER_LIVE_TOOLCHAIN=1): the recorded URL serves bytes whose SHA-512 equals the pinned SRI and the provisioned launcher reports npm 11.21.0. Signed-off-by: Yunseo Kim <[email protected]>
Implement ADR 0085 pre-install pair assertion and the npm-profile-toolchain-assert subcommand: - Observe node --version and npm --version through the exec boundary and require exact equality with the embedded pair record (Node.js 24.21.0, bundled npm 11.19.0) before any install, build, or pack step; mismatch fails closed with toolchain-pair-mismatch (check npm.build.toolchain). - --node-only mode asserts the Node.js runtime without looking up or executing npm, for the publish job where the bundled npm is never invoked (ADR 0082/0084). - The npm >= 11.5.1 floor and Node-major-24 gate in toolchain.go are unchanged as defense in depth. Real-surface evidence: npm-profile-toolchain-assert --node-only passes on the pinned development runtime (node v24.21.0). Signed-off-by: Yunseo Kim <[email protected]>
Extend the closed diagnostic_metadata report shape with the optional publish_npm_version string member (exact three-part SemVer, non-trust observational metadata, never merged into the build-time externalParameters.runtime.npm_version record), following the package_manifest extension precedent, and name the exact placement in the publish pin-validation section: the outcome report's diagnostic_metadata on success and on observed failures, plus the failing diagnostic's evidence on pin mismatch. Signed-off-by: Yunseo Kim <[email protected]>
Replace the publish-side build/publish npm-version equality check with ADR 0082 pin validation: - validateNPMVersion now compares the observed publish npm version against the embedded allowlist pin (npm 11.21.0); a mismatch fails closed with publish-npm-pin-mismatch (check npm.publish.toolchain) before any registry mutation, carrying the observed version in the failing diagnostic's evidence. - The observed publish npm version is recorded as diagnostic_metadata.publish_npm_version on success and on failures after observation, per the extended closed report contract (diagnostic.go + strict metadata decoding in metadata_json.go). - The build-stage externalParameters.runtime.npm_version recording and the --npm-executable path validation are unchanged; failed or malformed version observation keeps the existing builder-version-mismatch fallback without fabricated metadata. RED-first semantic proof: publish 11.21.0 with build-observed 11.19.0 now passes, and publish 11.20.0 equal to the build record now fails against the pin with no mutation attempted. Signed-off-by: Yunseo Kim <[email protected]>
Teach the static workflow checker the ADR 0082/0084/0085 contract: - All three jobs of the npm reusable workflow must set up Node.js at the exact patch from the embedded pair record (24.21.0), replacing the floating "24" literal in the build job and adding the check to the provenance-sign and publish jobs. - Build and sign jobs must run npm-profile-toolchain-assert before any step whose run block invokes npm. - The publish job must run npm-profile-toolchain-assert --node-only, then an identified npm-profile-provision-npm step ordered before the diagnostics and publish steps; every npm reference in the job must bind to the provisioning step's output expression, and ambient npm resolution (including command -v npm) is rejected. Command-layer writer tests now use an inline conforming fixture instead of the (currently nonconforming) production workflow; the production workflow check itself is the expected-RED gate until the workflow is updated. Signed-off-by: Yunseo Kim <[email protected]>
Implement the ADR 0084/0085 drift gate: - pin-check compares the disk records against the human-readable spec tables: the publish allowlist row (version, tarball URL, SHA-512 SRI) in the provenance-publish spec and the runtime pair row in the build-pack spec, requiring exact equality and failing with toolchain-pin-drift (check toolchain.pins.drift) on any drift, missing table, or unparsable row. Markdown table parsing tolerates Prettier padding and inline-code delimiters but is exact on data values. - Wire pin-check into the existing Go job in lint.yml with no permission or hardening changes. Real-surface artifacts: repo-state run prints "Toolchain pin records match specification tables." (exit 0); a spec copy with one flipped SRI character fails exit 1 with a canonical toolchain-pin-drift report. Signed-off-by: Yunseo Kim <[email protected]>
Land the ADR 0082/0084/0085 toolchain contract on the npm reusable workflow: - All three jobs set up Node.js at the exact pinned patch 24.21.0. - The build and provenance-sign jobs assert the pinned toolchain pair (Node.js 24.21.0, bundled npm 11.19.0) immediately after setup, before any npm invocation. - The publish job asserts the pinned Node.js runtime in node-only mode, then provisions the digest-verified npm 11.21.0 CLI before any npm invocation including diagnostics; the diagnostics and publish steps invoke npm only through the provisioning step's npm-executable output, and ambient npm resolution is gone from the job. Verified: actionlint clean, prettier clean, and workflow-check --profile npm-only passes with the pinned-toolchain contract checks. Signed-off-by: Yunseo Kim <[email protected]>
Add the spec-required PURL-derivation compatibility fixture family,
one key per supported npm CLI version with scoped and unscoped
coverage:
- npm-purl-publish-11-21-0-{scoped,unscoped}-valid, keyed to the
publish allowlist pin npm 11.21.0 (ADR 0082).
- npm-purl-build-11-19-0-{scoped,unscoped}-valid, keyed to the
build-stage pair npm 11.19.0 bundled with Node.js 24.21.0
(ADR 0085).
Each fixture records the npm CLI version its expectation was verified
against and the expected Package URL, asserted against the producer's
NPMPackagePURL derivation; the live CLI cross-check rides with the
gated Live tests. Registered in internal/fixture/registry.go,
testdata/fixtures/index.json, and the expected-case map. Pre-existing
fixtures are byte-untouched.
Signed-off-by: Yunseo Kim <[email protected]>
- Retarget the verification procedure to the pending v0.1.3 retry: v0.1.3 dispatch and evidence expectations, tag identity recorded at dispatch time rather than pinned to attempt-4 values, the caller pin bump to a slsa-builder main SHA carrying the ADR 0082/0084/0085 pinned-toolchain implementation, and the note that the provisioned pinned npm 11.21.0 carries the upstream npm/cli#9882 fix so the Windlass-signed bundle attaches as-is under trusted publishing. The existing 0.1.2 publication from run 31840088262 remains the Phase 6.4 foreign-conflict target. - Record the attempt-4 evidence file and retarget its forward-looking metadata (tag refs/tags/v0.1.3, peeled commit pending) for the retry. - README (English and Korean): the npm support-window paragraph now states the build stage uses the npm bundled with the exactly pinned Node.js 24.21.0 patch (npm 11.19.0, asserted before first use per ADR 0085) and the publish stage provisions a separately pinned, digest-verified npm CLI (npm 11.21.0) per ADR 0082/0084. - AGENTS.md standing item: pin selected as npm 11.21.0 per ADR 0083's 11-line preference; provisioning and pair pin landed on the feature branch; remaining steps are the vers-js caller pin bump and the v0.1.3 dispatch with runbook phases 1-6. - CHANGELOG [Unreleased]: Added entries for the publish npm pin and provisioning, the toolchain pair pin and assertion, the publish pin validation with publish_npm_version outcome evidence, and the pin-check drift CI gate. Signed-off-by: Yunseo Kim <[email protected]>
Clarify in both the provenance-publish and build-pack specifications that every npm-invocation requirement (the ADR 0084 before-any- invocation provisioning clause and the ADR 0085 first-invocation pair assertion) governs invocations of the npm CLI by a step of the job's workflow, and that the pinned setup mechanism's internal, read-only environment logging, such as the version reporting actions/setup-node performs after installing Node.js, is part of the authenticated toolchain setup and is not an npm invocation. ADR 0085 authenticates the bundled npm through the pinned setup mechanism's own checksum verification, so the setup action's version logging is inherent to the authenticated setup; it touches no package operation, and the npm it reports is the pair-pinned bundled npm the assertion validates. Signed-off-by: Yunseo Kim <[email protected]>
The same-run already-committed convergence path returned success before version validation, so the converged run's outcome report omitted diagnostic_metadata.publish_npm_version even though the job observed the provisioned npm. Validate the provisioned npm against the allowlist pin on every path that reaches Publish, including convergence: the read-only --version observation runs after provisioning per the ADR 0084 ordering, the observed version is recorded in the report metadata, a pin mismatch fails with publish-npm-pin-mismatch instead of converging silently, and validation failures preserve the classified registry state. Registry classification order is unchanged. Signed-off-by: Yunseo Kim <[email protected]>
Close the compatibility-evidence gap for the npm PURL fixtures with the Live-gated TestNPMPURLCLICompatibilityLive: for each supported npm CLI version and each fixture package it exercises the CLI's own provenance subject derivation (npm-package-arg toPurl, the exact code path libnpmpublish uses to build and exact-match the provenance subject) and asserts equality with both the fixture-recorded PURL and NPMPackagePURL. npm 11.21.0 is provisioned through the digest-verified ProvisionNPM path; npm 11.19.0 is the pair-pinned bundled CLI. Verified 12026-10-13: 4/4 fixture cases pass, and the four fixture READMEs now record the completed cross-check evidence. The comparison publishes nothing and contacts no registry. Signed-off-by: Yunseo Kim <[email protected]>
|
Running ultrareview automatically — this PR appears to change infrastructure or deployment configuration, where a missed bug can break builds, releases, or production environments, so a deeper multi-pass review is worth running. I'll post findings when complete. |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Ultrareview ran automatically — this PR appears to change infrastructure or deployment configuration, where a missed bug can break builds, releases, or production environments, so a deeper multi-pass review is worth running.
All reported issues were addressed across 71 files
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
…und archive copies explicitly Address PR #131 review findings against the provisioning implementation. - The publish execution boundary rejected the provisioned launcher with trusted-core-boundary-violation because $RUNNER_TEMP/windlass-npm-cli was not a trusted root. runPublishCommand now derives a publish-only shim root that accepts exactly the workflow-owned private layout (absolute clean path under the resolved RUNNER_TEMP anchor, npm-provision-* parent, npm basename, no symlink components, 0700 directory and regular launcher); every sibling layout stays rejected. Caught by cubic review before the v0.1.3 dogfood. - Both archive io.Copy sites now use io.CopyN with explicit bounds (entry size for entries, remaining budget for the drain), making the pre-existing size policy explicit for static analysis (semgrep zip-bomb findings) without changing behavior or diagnostics. - Add deterministic coverage for the duplicate-entry, empty-archive, and budget-exhaustion rejection branches and for clean provisioning failure paths; reuse requireLiveToolchain in the PURL live test. Signed-off-by: Yunseo Kim <[email protected]>
…s at prose Address PR #131 review findings against the pin records and drift gate. - decodePublishPin checked URL.Host, which is non-empty for a port-only authority such as https://:443/npm.tgz. Require a nonempty Hostname so malformed pins are rejected before provisioning. - The specification table scan treated a prose line directly after the last row as an unparsable row. The scan now stops at the first non-pipe line while pipe-prefixed malformed rows are still rejected, so harmless formatting changes do not fail pin-check. Signed-off-by: Yunseo Kim <[email protected]>
Address a PR #131 review finding against the closed metadata contract. The top-level null check did not cover members nested inside package_manifest, so inputs such as {"package_manifest":{"description":null}} and {"package_manifest":{"keywords":[null]}} were accepted after decoding erased the null values. The specification requires explicit nulls to fail with diagnostics-contract-invalid at any depth ("Absent source fields are omitted; null ... fail"). UnmarshalJSON now scans each raw member value for null at any depth after duplicate-member rejection, with the whole-member check keeping its existing message. Signed-off-by: Yunseo Kim <[email protected]>
…table bindings, and structural argument validation Address three P1 PR #131 review findings against the static toolchain contract. - Step conditions: contract-relevant steps in a job must all carry the exact same whitespace-normalized if: expression (or none), and constant-false conditions are rejected, so an assertion can never be skipped while an npm operation runs. The production publish segment's uniform upstream-success gate remains compatible. - Executable binding: the publish diagnostics and publish steps must resolve NPM_EXECUTABLE to exactly the provisioning step output expression, at step or job env scope, rejecting ambient or hardcoded rebinding. - Argument validation: shell comments are stripped before matching and the --npm-executable argument token must be exactly the pinned expression; comment-supplied evidence, duplicate flags, concatenated tokens, unknown variables, and single-quoted literal variable names are rejected. - Preflight report contract: the node-only assertion and provisioning steps must now pass --report-path "$REPORT_PATH" with REPORT_PATH bound to the outcome report path, so the persistence wiring added for the outcome-report finding cannot be dropped silently. Fixtures model the production shape. Signed-off-by: Yunseo Kim <[email protected]>
…ror branches Address PR #131 review findings against the command adapters and outcome reporting. - npm-profile-provision-npm and npm-profile-toolchain-assert accept an optional --report-path and persist their typed failure report there atomically (0600) in addition to the stdout report; a successful run writes no file. The publish job wires REPORT_PATH and the flag into both preflight steps, so a provisioning or assertion failure uploads the specific diagnostic instead of the finalizer's generic input-unavailable. - Add deterministic coverage for adapter flag-validation failures and downstream failure propagation across the provision, assert, and pin-check adapters, plus dispatch and flags edge cases. - TestWorkflowCheckAcceptsProductionWorkflow runs the workflowcheck contract against the real js-ts-npm-package-slsa3.yml, so unit tests catch production conformance regressions alongside the lint.yml CLI gate. Signed-off-by: Yunseo Kim <[email protected]>
…ifications Address PR #131 review findings against the specification documents. - The build specification claimed the bundled npm is authenticated through the pinned setup mechanism's checksum verification. The pinned actions/setup-node performs no Node.js artifact checksum verification, so the contract now states the honest guarantee: version identity is pinned observationally by the pair assertion, and artifact integrity rests on the runner image and the setup mechanism's TLS download. - The pair-assertion sentence now defines the Node.js version canonicalization (strip the single leading v; npm compared verbatim), matching toolchain_assert.go, and names the pair assertion as the exempt preflight so the wording is not circular under the npm-invocation definition. - The provenance/publish source ADR inventory gains ADR 0085, and the runtime.node_version rule is clarified as a defense-in-depth floor with the exact pinned pair asserted before first use; stale examples move to the pinned pair (24.21.0 / 11.19.0). - The diagnostics taxonomy now documents the complete archive-safety rejection set (link and special-file entries) and both pin-record/spec comparisons covered by toolchain-pin-drift. - The npmprofile live-test inventory includes npm_purl_live_test.go. Signed-off-by: Yunseo Kim <[email protected]>
Address a PR #131 review finding against the Phase 0 runbook. Phase 0 recorded the caller file blob SHA but never verified that publish.yml actually references the selected builder commit, so a stale caller could dispatch the old reusable workflow and bypass the pinned npm. The runbook now requires updating the caller's uses: reference to the full 40-hex merged builder SHA, fetching and decoding the file, failing closed unless the SHAs match, and recording both the caller blob SHA and the builder SHA before dispatch. Signed-off-by: Yunseo Kim <[email protected]>
…k fixture Align the command-level workflow fixture with the production publish job: the node-only assertion and provisioning steps bind REPORT_PATH and pass --report-path, matching the workflowcheck contract added in 049796e. Signed-off-by: Yunseo Kim <[email protected]>
There was a problem hiding this comment.
1 existing issue remains and no new issues found across 35 files (changes from recent commits).
Confidence score: 4/5
- The valid fragment in
docs/architecture/verification-policy-and-fixtures.mdhas mismatched Node.js versions, so it violates the observed-version equality rule. Setbuilder.version.nodejstov24.21.0.
Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
View guided diff | Turn on auto-fix | Re-trigger cubic
Address the three remaining findings from the cubic re-review at 2031ea6. - Add a wrong-value REPORT_PATH mutation for the node-only assertion step, locking the checker's rejection of any binding other than the uploaded outcome report path (the suite previously covered only a missing binding). - Pin the dogfood runbook's caller-workflow fetch with ?ref=main so the verified publish.yml content matches the dispatched ref. - Update the capture example's builder.version nodejs to v24.21.0, matching the example's own runner-image node_version under the observed-version equality rule; shape-only builder.version examples stay aligned with the governed fixtures. Signed-off-by: Yunseo Kim <[email protected]>
Summary
Implements ADR 0082/0083/0084 (publish-stage npm CLI pin) and ADR 0085 (build-stage Node.js toolchain pair pin), and completes the in-repo preparation for the M1 dogfood retry as vers-js v0.1.3.
What changed:
internal/toolchainpins/publish-npm.jsonpins the publish npm CLI to 11.21.0 (tarball URL + SHA-512 SRI, byte-identical to the packumentdist.integrity);internal/toolchainpins/node-runtime.jsonpins the build toolchain pair to Node.js 24.21.0 / npm 11.19.0. Both change only through the bump pull-request procedures those ADRs define (pin and digest or pair updated together in one commit, internals/changelog review, fixtures, full CI gate); a version bump does not require an ADR amendment.npm-profile-provision-npmsubcommand downloads only the recorded URL through the hardened fetcher, verifies the compressed SHA-512 before creating any directory, extracts with the no-links archive policy, validates the extractedpackage.jsonversion, and emits a private launcher namednpm. Provisioning executes neither node nor npm; every failure is pre-mutation with registered diagnostics.npm-profile-toolchain-assertsubcommand requires exactnode --version/npm --versionequality with the recorded pair before the first npm invocation (build/sign jobs; node-only mode in the publish job).diagnostic_metadata.publish_npm_versionon every path reaching Publish, including same-run convergence.workflow-checkenforces the exact Node patch, assertion steps, provisioning ordering, and zero ambient npm in the publish job; newpin-checksubcommand (wired intolint.yml) fails on drift between the records and the spec tables.npm-package-arg.toPurlprovenance-subject code path.npm invocationdefinition), dogfood runbook retargeted to v0.1.3, README (English/Korean) publish-stage nuance, CHANGELOG[Unreleased]entries, and the attempt-4 dogfood evidence record with forward metadata retargeted.Why: the fourth M1 dogfood published
@windlass/[email protected]with npm-generated provenance because npm silently discarded the supplied--provenance-filebundle (#97). The upstream fix (npm/cli#9882) shipped in npm 12.1.0 and 11.20.0; ADR 0083 selects the fixed release as the initial publish pin, and the operator selected npm 11.21.0, the latest 11-line release carrying the fix. Pinning both toolchains converts toolchain drift into reviewed bump events. The pinned 11.21.0 passed the ADR 0082 internals checklist and ADR 0084 registry cross-checks (recorded in the spec's allowlist review note, including the documented deviation that npm/cli published no git tag or GitHub Release for v11.21.0, so thegitHeadcross-check resolves at the release-commit level).How to test:
go test ./...,go test -race ./...,golangci-lint run ./...,actionlint .github/workflows/*.yml,pnpm exec prettier --check .,pnpm exec markdownlint-cli2 "**/*.md",fixture-check,workflow-check,pin-check, and the gated live evidenceSLSA_BUILDER_LIVE_TOOLCHAIN=1 go test -run 'TestProvisionNpmLive|TestNPMPURLCLICompatibilityLive' ./internal/npmprofile/ -v.Related Issues
Change Type
Changelog
--provenance-filefix) provisioned from a digest-verified registry tarball, and pins the build-stage Node.js/npm toolchain pair (currently Node.js 24.21.0 / npm 11.19.0) asserted before first use; publish-side npm validation compares against the allowlist pin and recordspublish_npm_versionoutcome evidence; apin-checkCI gate fails on drift between the machine-readable pin records and the specification tables.Changelog update:
CHANGELOG.md[Unreleased]updatedChecklist
General
type(scope): SummaryCI/Workflow Changes (if applicable)
If this PR modifies GitHub Actions workflows or CI/CD configuration, it must comply with our Supply Chain Integrity requirements:
uses:references are pinned to full 40-character commit SHAs (with# vX.Y.Zcomment)step-security/harden-runneris included as the first step in every jobpermissionsare used instead of top-levelpermissionsProtocol / Compatibility Impact
If impacted, describe compatibility impact:
The publish-side npm version contract changes from exact equality with the build-time npm record to allowlist pin validation (ADR 0082); the diagnostics report schema gains the optional closed
diagnostic_metadata.publish_npm_versionmember following thepackage_manifestextension precedent; new conformance fixtures cover the PURL compatibility family for both pinned npm versions. The project is pre-release and the profile workflow is referenced by SHA, so no caller observes any change until it re-pins to a SHA carrying this merge; no versioned migration is required.Testing
Describe test evidence:
go test ./...andgo test -race ./...green (all 16 packages);golangci-lint run ./...0 issues;actionlintclean; Prettier and markdownlint clean.fixture-check,workflow-check --profile npm-only, and the newpin-check(repo-state GREEN; a spec copy with one flipped SRI character fails exit 1 withtoolchain-pin-drift).TestProvisionNpmLivedownloads the recorded npm 11.21.0 tarball, verifies its SHA-512 against the pinned SRI, and reports npm 11.21.0 from the provisioned launcher;TestNPMPURLCLICompatibilityLiveexercises both pinned CLIs' ownnpm-package-arg.toPurlprovenance-subject code path for all four fixtures (4/4 pass).Documentation
Rollout / Risk
docs/dogfood/npm-m1-verification-procedure.mdphases 1-6.Reviewer Checklist
Summary by cubic
Pins the publish-stage npm CLI and the build-stage Node.js/npm toolchain pair with digest-verified provisioning. Previously the publish job used the npm bundled with Node.js 24 and required the publish npm version to equal the build-time npm version; the latest dogfood attempt published npm-generated provenance because npm discarded the supplied
--provenance-filebundle. The publish stage now provisions npm 11.21.0, the latest 11-line release carrying the upstream fix, from a digest-verified registry tarball before any npm invocation.Provisioning and assertion
npm-profile-provision-npmdownloads only the recorded tarball, verifies the SHA-512 SRI, extracts with the no-links archive policy and explicitly bounded copies, and emits a private launcher; it never executes node or npm, and every failure stays pre-mutation.npm-profile-toolchain-assertrequires exactnode --version/npm --versionequality with the pinned pair (Node.js 24.21.0 / npm 11.19.0) before first npm use; the publish job asserts node only.publish_npm_versionon every path that reaches publish, including same-run convergence.pin-checkCI gate fails on drift between the machine-readable pin records and the spec tables.Workflow, fixtures, and rollout
--npm-executablearguments, and any preflight-report path binding other than the uploaded outcome report; preflight failures persist typed reports to the outcome path.uses:reference via a?ref=mainfetch) and the v0.1.3 dogfood dispatch.Written for commit f69846e. Summary will update on new commits.