test(npm): add real-npm-CLI end-to-end harness and CI job

Summary

Adds an npm end-to-end CI job that drives the real npm CLI against a freshly booted Artifact Registry. This is the interim stand-in for the npm conformance suite (S11 plan Step 23) until external tooling mirroring the OCI setup lands.

  • scripts/conformance/npm-e2e.sh: builds and boots AR (LabKit config paths relocated at link time, so the harness runs unprivileged locally and in CI), seeds a namespace and a hosted npm repository via psql, and walks the full lifecycle: publish (unscoped and scoped), duplicate-publish refusal, view, install (exact version, by dist-tag, and scoped), dist-tag add/ls/rm, deprecate and undeprecate, single-version unpublish, whole-package unpublish, and republish after unpublish. After each mutation it asserts the S11-prescribed database state via psql: soft-delete cascades, tag and packument-cache hard-deletes, and blob rows retained for GC.
  • conformance:npm:s3-garage job: extends the new .conformance-ar-env template (the backend-independent AR boot layout, now shared with .conformance-oci) plus .garage-backend. npm comes from the nodejs.org tarball pinned to GL_ASDF_NODEJS_VERSION, checksum-verified against SHASUMS256.txt and cached keyed on the version.
  • conformance:npm mise task for local runs.

Coverage notes

  • AC 60: both unpublish wire calls are asserted from the access log (packument -rev PUT and tarball DELETE).
  • AC 64: npm install proceeds past the audit stub, and both audit endpoints are asserted to return 404 directly.
  • AC 65: install verifies the exact published payload in node_modules.
  • Scoped packages assert the stored scope column, the scope-stripped npm_files.file_name, and isolation from the unscoped package's whole-package unpublish.
  • Anonymous read and write are asserted 401: the S08 bootstrap validator authenticates every request; public-read semantics arrive with the real auth stack.
  • Duplicate publish is refused client-side by npm ("cannot publish over"), so the server-side 409 stays integration-test territory.

Found by this harness

Three real-client gaps, all spec defects faithfully implemented: the packument _rev omission (fixed by !861 (merged)/!863 (merged)) and the two scoped-package contracts (fixed by !868 (merged)/!869 (merged), which this MR is stacked on): the _attachments key form and the raw-slash dist.tarball URL.

Stacking

Stacked on !869 (merged) (which is stacked on !868 (merged)): the scoped legs need both fixes. Retarget to main as they merge.

Related to #143 (closed)

Edited by João Pereira

Merge request reports

Loading
Loading