feat(npm): rebuild a missing packument and serve the abbreviated form to installers - #958
Merged
Conversation
|
🐳 Test image pushed: docker pull ghcr.io/getnora-io/nora:pr-958
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-958 |
devitway
force-pushed
the
fix/npm-packument-rebuild
branch
from
September 5, 2026 08:30
d0d0129 to
9738ffb
Compare
A hosted package whose derived `metadata.json` was absent answered 404 even
though every published version was still in storage. The reassembly already
existed — `regenerate_packument()` lists `versions/`, `dist-tags/` and
`pkg.json` — but only the publish path ever called it, so a read fell through to
the upstream proxy and 404'd for a package that exists only in this registry.
The read path now rebuilds when `versions/` is non-empty, serves the result and
re-materializes `metadata.json` so the cost is paid once. It runs before the
namespace guard on purpose: serving locally-owned bytes is always allowed, and
that guard exists to stop the upstream fetch below it. The rebuild takes the
same `publish_lock` the publish path uses, so a fleet stampeding one package
rebuilds it once rather than once per request.
A name with nothing behind it still returns 404 — the rebuild must not invent a
package out of an empty prefix.
Measured on an S3 (MinIO) polygon, hosted package with 500 versions and no
materialized packument:
before 404, 0 B, 0.93 ms
after 200, 234186 B, 185 ms — then 2.8 ms once materialized
absent 404, 1.2 ms, unchanged
Storage layout is untouched: same keys and the same object count as before, and
a full publish/install/proxy pass over the polygon shows no change in behaviour.
Adds `nora_packument_rebuilt_total{registry}` — a non-zero rate points at
storage that was written or restored outside NORA.
Closes #956
Co-authored-by: ivaseeq <126263471+ivaseeq@users.noreply.github.com>
`npm install` asks for `application/vnd.npm.install-v1+json` — the abbreviated
packument — and NORA ignored it, serving the full document to every client. The
fields it carries are exactly the ones an installer never reads: readme,
maintainers, repository, per-version description, scripts, gitHead.
The packument serve path now branches on `Accept` and projects the document down
to npm's abbreviated shape. The per-version field list is an allowlist, in one
place: dropping a field an installer consults — `os`, `cpu`, `engines`,
`peerDependenciesMeta` — silently changes what gets resolved, so a field is
added there once rather than at a call site.
`Vary: Accept` goes with it, and it is not decoration. The body now depends on a
request header while NORA still marks metadata `Cache-Control: public`; without
`Vary` a shared cache can hand the abbreviated document to a client that asked
for the full one.
The abbreviation is derived locally rather than requested upstream, so the cache
keeps exactly one canonical object per package and the full document is never
displaced by a short one.
Measured against a live upstream through the proxy, all versions preserved:
lodash 247652 -> 71989 B -70.9% 117 versions
express 804975 -> 344703 B -57.2% 288 versions
An unparsable body is served unchanged rather than turned into an error: the
client asked for a projection of this document, not for a failure.
Closes #957
Co-authored-by: ivaseeq <126263471+ivaseeq@users.noreply.github.com>
feat(npm): serve the abbreviated packument for install-v1 clients
|
🐳 Test image pushed: docker pull ghcr.io/getnora-io/nora:pr-958
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-958 |
ertime037
previously approved these changes
Sep 5, 2026
devitway
force-pushed
the
fix/npm-packument-rebuild
branch
from
September 5, 2026 08:54
163c983 to
d400d70
Compare
|
🐳 Test image pushed: docker pull ghcr.io/getnora-io/nora:pr-958
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-958 |
2 similar comments
|
🐳 Test image pushed: docker pull ghcr.io/getnora-io/nora:pr-958
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-958 |
|
🐳 Test image pushed: docker pull ghcr.io/getnora-io/nora:pr-958
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-958 |
|
🐳 Test image pushed: docker pull ghcr.io/getnora-io/nora:pr-958
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-958 |
ertime037
enabled auto-merge
September 5, 2026 09:22
ertime037
disabled auto-merge
September 5, 2026 09:22
ertime037
enabled auto-merge
September 5, 2026 09:22
ertime037
approved these changes
Sep 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #956. Closes #957.
Two npm packument fixes. #959 was stacked on this branch and has already merged into it, so this PR now carries both.
1. A missing packument is rebuilt instead of 404'd (#956)
GET /npm/<pkg>answered 404 for a hosted package whose derivedmetadata.jsonwas missing, while every published version was still sitting in storage.The reassembly already existed —
regenerate_packument()listsversions/,dist-tags/andpkg.json— but only the publish path called it. A read fell through to the upstream proxy, which then 404'd for a package that exists only in this registry.The read path now rebuilds when
versions/is non-empty, serves the result, and re-materializesmetadata.jsonso the cost is paid once.publish_lockthe publish path takes, so a fleet stampeding one package rebuilds it once rather than once per request.Measured on a polygon: real S3 (MinIO), real
npm publish, 500 versions,metadata.jsondeleted from the bucket.mainAdds
nora_packument_rebuilt_total{registry}. A non-zero rate means storage was written or restored outside NORA — worth an alert rather than a silent repair.2. The abbreviated packument for install-v1 clients (#957)
npm installasks forapplication/vnd.npm.install-v1+jsonand NORA ignored it, serving the full document to everyone. The fields it carries are exactly the ones an installer never reads.os,cpu,engines,peerDependenciesMeta— silently changes what gets resolved.Vary: Acceptis load-bearing. The body now depends on a request header while metadata staysCache-Control: public; without it a shared cache can hand the short document to a client that wanted the full one.lodashexpressThe polygon caught a real bug mid-flight: the first pass abbreviated the body on the stale-serve path but left
Content-Type: application/jsonon it — a short document announced as the full one. Fixed by routing that branch through the same helper, and a test now asserts thex-nora-staleprecondition together with the content type, so the degraded path cannot drift from the normal one again.Validation
Seven tests across both changes, flip-verified — with the rebuild disabled two go red while the "absent package stays 404" guard stays green, which is what it is for.
End-to-end on the polygon with the same binary: publish 200 versions, read the packument,
npm installfrom the registry (hosted and proxied), Maven proxy fetch — all unchanged, and the storage layout is identical tomain: same keys, same object count.Full suite: 63 lib + 1788 bin + 6 doc, zero failures.
cargo fmt --checkandcargo clippy -p nora-registry --all-targets -- -D warningsclean.Credit
Both were surfaced while validating #889 on a polygon; the defects are ours. Both commits carry
Co-authored-by: ivaseeq.