Skip to content

rfc(pnpr): integrity-addressed patch revisions - #19

Open
zkochan wants to merge 18 commits into
mainfrom
rfc/pnpr-integrity-addressed-patches
Open

rfc(pnpr): integrity-addressed patch revisions#19
zkochan wants to merge 18 commits into
mainfrom
rfc/pnpr-integrity-addressed-patches

Conversation

@zkochan

@zkochan zkochan commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

This design supersedes #14 (closed in its favor). It contains two companion
RFCs:

  • pnpr/text/0000-integrity-addressed-patch-revisions.md projects provider
    builds over the original name@version. Every artifact is served from an
    immutable, registry-scoped URL keyed by its complete sha512 digest; the
    canonical name/-/name-version.tgz URL stays pinned to the original bytes
    forever. dist.revisions retains an append-only history of every accepted
    artifact — integrity, provider, revision number, VEX/provenance,
    withdrawn/supersededBy status, and each artifact's own
    resolution-relevant manifest fields.
  • text/0000-integrity-addressed-registry-tarballs.md teaches pnpm the
    lockfile representation and the <version>+rN revision-addressed spec.

The revision field

The revision number is a plain integer field, present only for replacements:

// registry metadata for a patched version
"dist": {
  "tarball": "https://registry.example/-/tarballs/sha512/<digest>",
  "integrity": "sha512-<patch-digest>",   // standard SRI, no extensions
  "revision": 2
}
# lockfile
packages:
  ejs@2.7.4:            # original — byte-identical to today's format
    resolution:
      integrity: sha512-<original>
  lodash@4.17.21:       # replacement — the field is the signal
    resolution:
      integrity: sha512-<patch-digest>
      revision: 1

Originals are never marked. The canonical URL is pinned to revision zero
by invariant, so integrity-only entries stay correct on every registry —
revision-aware or not — and a lockfile with no adopted patches needs no new
format. Only revision: N entries are gated by lockfile version and fetched
from the digest route (one direct CDN request; falling back to the canonical
URL is impossible by construction, since original bytes cannot match a
replacement's integrity). Registry feature detection (the pnpr handshake) is
advisory only — better diagnostics, optional originals-by-digest optimization
— never load-bearing: the lockfile field alone determines the fetch
convention.

Explicit revision selection: <version>+rN

The revision number carried as semver build metadata makes a
revision-addressed spec,
usable as an override target or a directly declared dependency:

{ "pnpm": { "overrides": { "ejs@2.7.4": "2.7.4+r0" } } }  // keep the original

No new override semantics: exact-version selectors already match intersecting
declared ranges (pnpm/pnpm#13470, retained for npm parity). pnpm resolves the
version half normally, then selects revision N from dist.revisions
using that revision's own manifest fields, since revisions may legally
differ in dependencies. Unknown revision numbers fail hard; rewriting applies once;
conflicting revision demands for one name@version are an explicit error.
Registry policy wins: refused bytes fail the install, they are never
substituted.

Important properties

  • npm and Yarn receive registry-selected patches through dist.tarball on
    fresh resolutions; pnpm additionally gets revision management (host-free
    lockfile entries, +rN pinning, pnpm update --patches). Clients that
    reconstruct conventional URLs fail loudly, never silently wrong.
  • Existing lockfiles of every client keep installing exactly what they pin;
    canonical immutability makes that honest instead of breaking them.
  • Provider manifests carry a signed monotonic sequence, checkpointed
    together with the accepted manifest's digest: an exact redelivery is a
    no-op, the same sequence with different content is rejected as provider
    equivocation, and replayed older documents are rejected. The checkpoint
    advances atomically with durable acceptance, so rollback requires a fresh
    manifest or an explicitly authorized operator action.
  • Revision allocation serializes on (registry, name, version) with separate
    uniqueness constraints on revision number and digest; the registry owns the
    numbering — provider changes never renumber.
  • The digest endpoint is scoped beneath the addressed registry and authorizes
    against the principal's package-level access; knowledge of a digest is not
    authorization. Full sha512 values are required.
  • Immutability means stable bytes, not availability: policy refusal applies
    identically to canonical and digest routes and requires edge purge or
    non-shared caching.
  • Revision numbers are registry-scoped; portability across registry
    configuration guarantees integrity, never identical revision-number
    meaning.
  • deprecated and other registry-managed mutable metadata stay outside the
    immutable revision records, whose artifact-derived fields never change; the
    only registry-managed annotations on a history entry are its
    withdrawn/supersededBy status fields.

Compatibility

  • Lockfiles without revision entries are byte-identical to the current
    format — no gate, readable by older pnpm.
  • Pointing a lockfile at a registry without the digest endpoint keeps the
    whole unpatched graph installable; only replacement entries fail, as
    genuine unavailability.
  • dist.integrity is a standard SRI value; npm-compatible clients ignore the
    unknown dist.revision field and follow dist.tarball normally.
  • The existing named-registry package-key collision remains a separate
    lockfile-identity problem.

Summary by CodeRabbit

  • Documentation
    • Documented integrity-addressed registry tarballs for immutable artifact retrieval using verified digest URLs.
    • Defined revision metadata, revision-zero handling, and append-only histories for original and replacement artifacts.
    • Specified lockfile behavior for integrity and revision fields, including strict verification and version gating.
    • Added guidance for selecting, pinning, and refreshing revisions with workspace targets and pnpm update --patches.
    • Covered provider ingestion, authorization, auditing, restoration, testing, and open protocol considerations.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds two RFCs for immutable, registry-scoped digest tarballs and revision metadata. They define provider ingestion, projected revision history, pnpm lockfile and fetch behavior, revision selection, compatibility checks, refresh operations, and audit rules.

Changes

Integrity-addressed revisions

Layer / File(s) Summary
pnpr protocol and projected metadata
pnpr/text/0000-integrity-addressed-patch-revisions.md
Defines immutable artifact identity, signed provider manifests, digest URLs, projected metadata, revision history, and canonical tarball behavior.
Revision lifecycle and audit model
pnpr/text/0000-integrity-addressed-patch-revisions.md
Defines revision refresh, atomic projection, ordinal allocation, authorization, retention, caching, auditing, implementation tasks, and tests.
pnpm resolution and digest fetching
text/0000-integrity-addressed-registry-tarballs.md
Defines metadata validation, lockfile representation, digest URL hydration, registry identity handling, strict SRI verification, and offline installation.
Historical compatibility and revision refresh
text/0000-integrity-addressed-registry-tarballs.md
Defines historical verification, older-client gating, revision overrides, conflicts, atomic refresh, implementation requirements, tests, alternatives, prior art, and open questions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Provider
  participant pnprRegistry
  participant RegistryPackument
  participant pnpmResolver
  participant Lockfile
  Provider->>pnprRegistry: submit signed artifact revision
  pnprRegistry->>RegistryPackument: publish verified revision metadata
  pnpmResolver->>RegistryPackument: resolve name@version and revision
  pnpmResolver->>Lockfile: record integrity and revision
  pnpmResolver->>pnprRegistry: fetch registry-scoped digest URL
  pnprRegistry-->>pnpmResolver: return immutable tarball bytes
  pnpmResolver->>Lockfile: verify SRI and install selected revision
Loading

Poem

A rabbit checks each digest byte,
And marks the revisions right.
The lockfile keeps the chosen hay,
While immutable paths lead the way.
Patch refreshes hop in line.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the RFC for integrity-addressed patch revisions, which is the main change in the pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rfc/pnpr-integrity-addressed-patches

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@zkochan
zkochan marked this pull request as ready for review July 28, 2026 16:15
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

RFC: Integrity-addressed patch revisions and pnpm fetching

📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Proposes immutable, registry-scoped digest URLs for original and patched package artifacts.
• Encodes stable artifact revisions in SRI options while preserving package identity.
• Defines pnpm lockfile fetching, verification, compatibility, and revision-refresh behavior.
Diagram

graph TD
  Provider["Patch Provider"] -->|signed artifact| Registry["pnpr Registry"] -->|stores by digest| Store[("Digest Store")]
  Registry -->|projects revision| Metadata["Package Metadata"] -->|marked integrity| Resolver["pnpm Resolver"] -->|pins revision| Lockfile["pnpm Lockfile"] -->|digest request| Registry
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Provider package aliases
  • ➕ Uses established package substitution and immutable publication semantics.
  • ➕ Makes provider identity explicit in consumer dependency metadata.
  • ➖ Leaks registry policy into lockfiles, SBOMs, peer resolution, and runtime metadata.
  • ➖ Requires provider-specific registry configuration and pnpm overrides or annotations.
2. Store digest tarball paths
  • ➕ Makes the fetch convention explicit without extending SRI interpretation.
  • ➕ Can remain portable when represented as a registry-relative path.
  • ➖ Duplicates the algorithm and digest already contained in integrity.
  • ➖ Adds lockfile surface that must remain synchronized with the SRI value.
3. Header-selected revisions
  • ➕ Retains one recognizable canonical package URL.
  • ➕ Could select historical content without introducing a new URL route.
  • ➖ Requires custom CDN forwarding and high-cardinality cache variation or redirects.
  • ➖ Makes one URL represent multiple bodies and adds deployment complexity.

Recommendation: Prefer the proposed digest-addressed design if pnpm and pnpr can safely preserve raw empty SRI options and gate the lockfile format. It best preserves name/version semantics, immutable cache keys, registry-scoped authorization, and single-request installs; provider aliases remain the strongest fallback if extending SRI semantics proves incompatible with ecosystem tooling.

Files changed (2) +1227 / -0

Documentation (2) +1227 / -0
0000-integrity-addressed-patch-revisions.mdSpecify pnpr artifact revision projection and storage +724/-0

Specify pnpr artifact revision projection and storage

• Adds the registry-side RFC for ingesting provider artifacts, assigning stable revisions, and serving complete-digest URLs under the original package identity. It also defines append-only provenance history, authorization boundaries, compatibility guarantees, refresh atomicity, and audit behavior.

pnpr/text/0000-integrity-addressed-patch-revisions.md

0000-integrity-addressed-registry-tarballs.mdSpecify pnpm revision-aware integrity fetching +503/-0

Specify pnpm revision-aware integrity fetching

• Adds the companion pnpm RFC defining SRI revision markers, compact lockfile storage, digest URL construction, and response verification. It covers legacy lockfiles, lockfile format gating, registry path preservation, historical verification, and atomic patch-revision refreshes.

text/0000-integrity-addressed-registry-tarballs.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpr/text/0000-integrity-addressed-patch-revisions.md`:
- Around line 181-204: The “Provider input remains integrity-pinned”
specification must define anti-rollback enforcement for signed patch manifests.
Add a persisted, signed monotonic checkpoint for each provider identity and
require pnpr to reject manifests selecting revisions older than the checkpoint;
document an explicit, authorized rollback mechanism and its verification
requirements.
- Around line 491-505: Update the provider refresh sequence to make `(registry,
name@version, digest)` revision allocation unique and idempotent: claim or reuse
an existing digest mapping within a transaction/unique constraint before
assigning an ordinal, and append revision metadata plus select the mapping
atomically. Ensure concurrent refreshes and retries reuse the same stable
ordinal rather than allocating duplicates.
- Around line 282-292: Update the public CDN caching and policy sections
describing successful immutable responses, including the related sections on
revocation and cache behavior, to define authorization-aware edge enforcement
and purge/invalidation when a revision is blocked. If immediate revocation on
warm immutable hits cannot be guaranteed, weaken the policy wording to state the
actual propagation behavior instead of promising an immediate 403.
- Around line 157-171: Clarify the immutability and access-policy rules in the
RFC sections covering tarball URLs, historical artifact screening, and legacy
lockfiles: define immutability as successful responses returning unchanged
bytes, specify whether vulnerability screening applies to canonical URLs as well
as integrity URLs, and document the response legacy lockfiles receive when
access is denied.

In `@text/0000-integrity-addressed-registry-tarballs.md`:
- Around line 207-209: Restrict the registry-base portability guarantee and its
tests to hostname aliases or deployment moves of the same logical registry.
Update the digest URL resolution and hydration behavior described in the
registry portability section, including the identity gap noted around the
lockfile discussion, so changing to an unrelated configured registry is not
treated as equivalent; alternatively persist and validate registry identity
before hydration.
- Around line 312-316: Define the lockfile version gate for revision-aware
integrity and the `?vN` representation, including when pnpm emits it and how
hydrated lockfile parsing rejects it in older clients. Update the affected
proposal sections consistently and add a compatibility test verifying older
clients fail fast on the gated lockfile rather than reconstructing the canonical
`dist.tarball` URL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 39f74957-4168-4ccf-809c-ebc7cea26467

📥 Commits

Reviewing files that changed from the base of the PR and between 413a998 and 3af3d0f.

📒 Files selected for processing (2)
  • pnpr/text/0000-integrity-addressed-patch-revisions.md
  • text/0000-integrity-addressed-registry-tarballs.md
📜 Review details
🧰 Additional context used
🪛 LanguageTool
pnpr/text/0000-integrity-addressed-patch-revisions.md

[grammar] ~465-~465: Ensure spelling is correct
Context: ...is longer by one sha512 digest. Patched packuments contain a small revision list. Both cos...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~481-~481: This phrase is redundant. Consider writing “same”.
Context: ...ked registry package, pnpm resolves the same exact name@version. If dist.integrity cha...

(SAME_EXACT)


[grammar] ~506-~506: Ensure spelling is correct
Context: ...validate projected full and abbreviated packuments. No tarball cache object is invalidated o...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~518-~518: To elevate your writing, try using an alternative expression here.
Context: ... returns a policy-specific 403. This matters for a vulnerable original. A reproducib...

(MATTERS_RELEVANT)

text/0000-integrity-addressed-registry-tarballs.md

[grammar] ~145-~145: Use a hyphen to join words.
Context: ...egrity`; 4. the digest is complete, well formed, and unambiguous; 5. the selected...

(QB_NEW_EN_HYPHEN)


[style] ~349-~349: This phrase is redundant. Consider writing “same”.
Context: ... pnpm resolves current metadata for the same exact name@version. If dist.integrity cha...

(SAME_EXACT)

🔇 Additional comments (2)
pnpr/text/0000-integrity-addressed-patch-revisions.md (1)

1-156: LGTM!

Also applies to: 172-180, 205-281, 293-408, 428-449, 470-490, 523-690, 691-725

text/0000-integrity-addressed-registry-tarballs.md (1)

1-206: LGTM!

Also applies to: 210-266, 278-311, 318-475, 477-499

Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md
Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md
Comment thread text/0000-integrity-addressed-registry-tarballs.md
Comment thread text/0000-integrity-addressed-registry-tarballs.md Outdated
Replace the empty-option/`?vN` markers with explicit `?r0`/`?rN` ordinals:
`r` abbreviates *registry revision*, matches `dist.revisions` numbering,
and follows Alpine/Gentoo `-rN` precedent, while an always-non-empty
option removes the raw-SRI-parsing fragility.

Specify workspace revision selection through ordinary overrides whose
targets carry the ordinal as semver build metadata (`<version>+rN`):
`+r0` pins the original, positive ordinals adopt or freeze replacements,
unknown ordinals fail hard, and registry policy 403s still win.

Require each `dist.revisions` entry to carry a `manifest` object with the
abbreviated-packument field subset, derived from the verified tarball and
never provider-declared, so a pinned non-selected revision resolves with
its own dependency metadata.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pnpr/text/0000-integrity-addressed-patch-revisions.md (1)

328-332: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Define revision-reference equality separately from artifact equality.

Line 328 says the ?rN option is excluded from equality, while selection still depends on the digest plus ordinal and dist.revisions[] advertises each ordinal as a distinct artifact. Document that canonical digest equality ignores options, but resolving or checking ?rN must match the canonical dist.revisions[].revision for that integrity, and reject or canonicalize forged mismatched ordinals.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pnpr/text/0000-integrity-addressed-patch-revisions.md` around lines 328 -
332, Clarify the revision semantics in the document: canonical artifact digest
equality must ignore the ?rN option, while resolving or validating a revision
reference must match the canonical dist.revisions[].revision for the
corresponding integrity digest. Specify that forged or inconsistent ordinals are
rejected or canonicalized, and keep option-only changes from creating new stored
artifacts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpr/text/0000-integrity-addressed-patch-revisions.md`:
- Line 718: Resolve the ordinal contract before retaining the conformance
requirement: explicitly require stable monotonic rN ordinals across provider
changes, or define the migration behavior that applies when providers change.
Update the surrounding unresolved questions and the conformance statement for
the first replacement so they consistently reflect the chosen rule.
- Around line 509-514: Update the revision-override handling for +rN selections
to persist the addressed registry together with the package identity and pinned
ordinal. When resolving or applying an override, require the stored registry and
name@version to match the current package before using the revision; ensure pnpm
update --patches recognizes these workspace overrides as pinned and does not
refresh them.

In `@text/0000-integrity-addressed-registry-tarballs.md`:
- Around line 149-155: Update the integrity-validation wording to compare the
decoded URL digest with the decoded payload from dist.integrity after removing
its canonical rN option, while retaining the sha512- algorithm prefix handling.
Clarify that literal comparison against the full integrity string is invalid
because the URL contains only the digest.

---

Outside diff comments:
In `@pnpr/text/0000-integrity-addressed-patch-revisions.md`:
- Around line 328-332: Clarify the revision semantics in the document: canonical
artifact digest equality must ignore the ?rN option, while resolving or
validating a revision reference must match the canonical
dist.revisions[].revision for the corresponding integrity digest. Specify that
forged or inconsistent ordinals are rejected or canonicalized, and keep
option-only changes from creating new stored artifacts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d0504695-6831-4e86-b826-b5927fe1d04b

📥 Commits

Reviewing files that changed from the base of the PR and between 3af3d0f and e84a7c4.

📒 Files selected for processing (2)
  • pnpr/text/0000-integrity-addressed-patch-revisions.md
  • text/0000-integrity-addressed-registry-tarballs.md
📜 Review details
🧰 Additional context used
🪛 LanguageTool
pnpr/text/0000-integrity-addressed-patch-revisions.md

[style] ~648-~648: Consider an alternative for the overused word “exactly”.
Context: ...ements. Rejected: - an empty option is exactly the state a generic SRI library is most...

(EXACTLY_PRECISELY)

text/0000-integrity-addressed-registry-tarballs.md

[style] ~596-~596: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...n policy for pnpm update --patches? - What should the global posture setting that ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🔇 Additional comments (2)
pnpr/text/0000-integrity-addressed-patch-revisions.md (1)

19-21: LGTM!

Also applies to: 24-27, 31-33, 94-96, 118-123, 146-147, 164-166, 266-267, 308-327, 334-337, 357-388, 409-424, 458-462, 643-659, 705-706, 716-717, 719-724, 766-767

text/0000-integrity-addressed-registry-tarballs.md (1)

367-372: 🗄️ Data Integrity & Integration

Specify verification of revision manifests before using them for resolution.

dist.revisions[N].manifest becomes authoritative for dependencies, peers, engines, and install scripts, but the fetch steps only verify tarball bytes against the digest. Explicitly require the companion manifest-verification contract—including its binding to the selected name, version, revision, and digest—and fail before subtree resolution when that metadata is stale or mismatched.

Also applies to: 546-548

Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread text/0000-integrity-addressed-registry-tarballs.md Outdated
zkochan and others added 3 commits July 28, 2026 20:04
Exact-version override selectors already match intersecting declared
ranges in current pnpm (pnpm/pnpm#13470, retained for npm parity), so no
resolver semantics change is needed. <version>+rN becomes a plain
revision-addressed spec — usable as an override target or a directly
declared dependency — resolved by picking the version normally, then
selecting the revision from dist.revisions. State the version-pinning
trade-off and the npm degradation (pin without revision selection)
honestly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Provider manifests carry a signed monotonic sequence; pnpr rejects
  replayed lower-sequence documents, so selection rollback requires a
  fresh manifest or an explicitly authorized operator action.
- Revision allocation is transactional: (registry, name, version,
  digest) maps to exactly one ordinal, idempotent under retries.
- Immutability means stable bytes, not availability: policy refusal
  requires edge purge or non-shared caching, applies identically to
  canonical and digest routes, and the digest route authorizes against
  the principal's package-level access.
- Ordinals are documented as registry-scoped; portability guarantees
  integrity, not identical ordinal meaning across registries.
- Override rewriting applies once (no chains or cycles), and
  conflicting revision demands for one name@version fail explicitly.
- deprecated is registry-managed mutable metadata, excluded from the
  artifact-derived revision manifest subset.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Allocation serializes on (registry, name, version) with separate
  uniqueness constraints on the ordinal and the digest mapping, so
  concurrent refreshes with different digests cannot share an ordinal.
- The registry owns the ordinal history: provider renames, replacements,
  or removals never renumber existing revisions (previously an open
  question, now normative since rN pins are a public API).
- The provider sequence checkpoint advances atomically with durable
  manifest acceptance, keeping a crashed sequence retryable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ordinal moves out of the integrity value: dist.revision on the
registry side and resolution.revision in the lockfile, present only for
replacements (N >= 1). Originals are never marked — the canonical URL is
pinned to revision zero by invariant, so plain integrity-only entries
stay correct on every registry, a lockfile with no adopted patches is
byte-identical to today's format, and only revision entries need the
lockfile-version gate.

dist.integrity returns to a standard SRI value that strict consumers
parse. Registry feature detection (the pnpr handshake) is specified as
advisory only — diagnostics and an optional originals-by-digest
optimization — never load-bearing for the fetch convention, which the
lockfile field alone determines. Digest-route tarballs without
dist.revision are normalized to integrity-only entries so hostnames
never enter the lockfile.

Document that npm/yarn patch delivery rides dist.tarball (unchanged by
canonical immutability), that convention-reconstructing clients fail
loudly rather than silently, and add a client-matrix verification
question. The SRI-option and mark-everything designs move to rejected
alternatives; +rN spec syntax is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pnpr/text/0000-integrity-addressed-patch-revisions.md (1)

203-218: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Constrain provider artifact fetches before download.

entries.*.tarball is an arbitrary server-side URL, but the RFC does not restrict its origin, redirects, DNS rebinding, or private-network targets. A signed or compromised provider manifest could therefore turn refresh into SSRF. Require HTTPS provider-origin allowlists, private-IP/egress checks, redirect validation, and ensure provider credentials are never forwarded to artifact hosts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pnpr/text/0000-integrity-addressed-patch-revisions.md` around lines 203 -
218, The artifact download flow described for manifest entries.*.tarball must
enforce SSRF protections before fetching: require HTTPS URLs from an approved
provider-origin allowlist, reject private or otherwise disallowed resolved
addresses and egress targets, validate every redirect against the same rules,
and never forward provider credentials to artifact hosts. Apply these checks
before download and preserve complete integrity verification afterward.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpr/text/0000-integrity-addressed-patch-revisions.md`:
- Around line 438-443: Update the abbreviated historical metadata specification
to retain each history entry’s integer revision ordinal alongside its integrity,
digest URL, and manifest fields. Ensure +rN resolution can map N to the correct
historical record, and add a focused test covering revision ordinals in
abbreviated packuments.
- Around line 438-443: Define a transactional carry-forward/merge rule for
revision swaps so projected version entries preserve registry-managed mutable
fields, including deprecated, when refreshed. Update the revision
refresh/projection process described in the metadata rules, keeping immutable
historical provenance separate while merging existing mutable metadata into the
replacement entry.
- Around line 220-230: Update the per-provider sequence checkpoint logic to
persist both the highest accepted sequence and its canonical manifest digest.
Treat an exact replay of the same sequence and digest as an idempotent no-op,
but reject any manifest using the same sequence with a different digest as
equivocation; retain advancement only for higher sequences and keep checkpoint
updates atomic with durable manifest acceptance.
- Around line 334-346: Define and document a single validation policy for
dist.revision across registry and client validation, covering absent,
non-integer, out-of-range, and mismatched values. Ensure full and abbreviated
packuments apply the same policy, and explicitly reconcile malformed-value
rejection with structured revision metadata being authoritative; update the
relevant test matrix and rules accordingly.

In `@text/0000-integrity-addressed-registry-tarballs.md`:
- Around line 376-381: Make revision refresh graph-transactional: when updating
the resolved entry’s revision and manifest, re-resolve the entire affected
dependency graph using the refreshed revision metadata, including dependency and
peer edges, engines, binaries, and install-script state. Commit all graph,
snapshot, and peer-resolution changes atomically, and roll back the refresh if
re-resolution produces conflicts. Add coverage for a revision whose dependency
metadata changes, including the corresponding lines around the revision refresh
logic.
- Around line 207-225: Update the revisioned digest tarball fetch requirements
at this section and the corresponding sections around lines 612 and 642 to
reject every 3xx response as a hard failure, not only redirects crossing
origins. Preserve the single authenticated GET behavior and prohibit following
same-origin or cross-origin redirects.

---

Outside diff comments:
In `@pnpr/text/0000-integrity-addressed-patch-revisions.md`:
- Around line 203-218: The artifact download flow described for manifest
entries.*.tarball must enforce SSRF protections before fetching: require HTTPS
URLs from an approved provider-origin allowlist, reject private or otherwise
disallowed resolved addresses and egress targets, validate every redirect
against the same rules, and never forward provider credentials to artifact
hosts. Apply these checks before download and preserve complete integrity
verification afterward.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 92882297-ba60-41e2-9dfc-8fc8fe0a3e60

📥 Commits

Reviewing files that changed from the base of the PR and between e84a7c4 and 5613a6f.

📒 Files selected for processing (2)
  • pnpr/text/0000-integrity-addressed-patch-revisions.md
  • text/0000-integrity-addressed-registry-tarballs.md
📜 Review details
🧰 Additional context used
🪛 LanguageTool
text/0000-integrity-addressed-registry-tarballs.md

[grammar] ~137-~137: Use a hyphen to join words.
Context: ...egrity; 4. the digest is complete, well formed, and unambiguous; 5. dist.revisi...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (6)
pnpr/text/0000-integrity-addressed-patch-revisions.md (2)

1-14: LGTM!

Also applies to: 26-58, 62-138, 141-192, 232-263, 265-283, 290-333, 347-410, 424-437, 445-505, 507-552, 554-604, 606-735, 737-758, 775-796, 798-835


15-22: 🗄️ Data Integrity & Integration

Manual verification needed for revision selection rules.

The excerpt raises a plausible concern about inconsistent keying between dist.tarball encoding, multiple SRI hash expressions, missing dist.revision, and absent revision handling, but the draft context is needed before ruling this as actionable.

text/0000-integrity-addressed-registry-tarballs.md (4)

130-138: Compare the URL digest with the SRI payload, not the full SRI token.

dist.integrity contains sha512-<base64>, while the URL contains only digest bytes. Define validation as decoding the SRI payload after removing the algorithm prefix and comparing those bytes with the decoded base64url path digest.


315-319: Specify the concrete lockfile gate.

The RFC requires revision fields to be gated but still leaves the lockfile version and emission/rejection behavior unresolved. Define the exact version, writer behavior, hydrated-lockfile rejection, and mixed-version compatibility matrix.

Also applies to: 606-608, 676-678


151-161: 🗄️ Data Integrity & Integration | ⚡ Quick win

Define the ordinal’s numeric bounds and canonical encoding.

“Positive integer” is insufficient for a JSON/JavaScript protocol: without a safe upper bound or canonical decimal-string representation, large ordinals can round or compare inconsistently and break revision selection. Add overflow, leading-zero, and maximum-value tests.

Also applies to: 636-637


357-368: 🎯 Functional Correctness

State that +rN overrides need new override behavior.

The linked pnpm issue is not publicly available as a stable contract here, so this should not present pnpm’s existing override behavior as sufficient if the feature allows a version-pinning override to force a selected version regardless of the declared range.

Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread text/0000-integrity-addressed-registry-tarballs.md Outdated
Comment thread text/0000-integrity-addressed-registry-tarballs.md
@jordi-heller

Copy link
Copy Markdown

pnpm might start supporting vendors like echo, that upload multiple releases that resolve to the same npm version (but differ in tarball and integrity). a feature to consider is the ability to refresh a lockfile to get the newest release while keeping the same version. Since a query of the version would only return the release the registry exposes there is no decision logic to be made by pnpr/pnpm, it should probably only query each version in the lockfile directly and replace the entry if it's different. pnpm has a feature that does something similar (npm install --fix-lockfile --lockfile-only), but what could be added is restriction to only update the hash if it belongs to a pre configured vendor etc

Versions such as `2.7.4-echo.2` are prereleases under semver. Ordinary ranges
containing `2.7.4` do not necessarily select them, peer ranges may reject them,
and the package no longer reports the version the application was tested
against. Build metadata is unsuitable because semver ignores it for precedence

@jordi-heller jordi-heller Jul 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a possibility of using build metadata. npm clients will ignore it, thereby seeing it as just the regular version, but the registry itself can be organized to serve the newest revision whenever its published. This (mostly) will not break any old lockfile as long as the urls of different versions are different (you can encode them with pkg-version+vendor.N.tgz for example). If the old urls stay on the registry users can always get the latest version when they ask for it, and they will not break if they're lockfile is out of date.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, we do leverage the build metadata in this rfc for explicitly specifying which revision to install via overrides. For the tarball URL I have suggested to use the integrity checksum of the tarball. Alternatively we could consider adding the revision number to the url as you suggest.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to the alternatives as Encode the revision number in the tarball
URL
, since it deserved a written comparison rather than a passing mention.

The scheme shares the append-only intent, and the readability/proxy-log
argument is real. What decided it for the fetch convention is that such a URL
only names the bytes — it doesn't commit to them. Immutability becomes a
policy the registry has to honor rather than something the client can verify:
nothing in the request detects a wrong body until integrity verification of a
completed download. With the digest route the cache key is the content itself,
pnpm constructs the URL from registry plus the integrity it already stores,
and "never fall back to another URL" holds by construction.

A registry can still expose a per-revision readable route as an alias for
humans and non-pnpm tooling — that doesn't conflict with anything here. The
convention pnpm relies on stays the digest URL.

@zkochan

zkochan commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

a feature to consider is the ability to refresh a lockfile to get the newest release while keeping the same version.

sure, such feature would make sense. The current architecture would make it slow though. We'd have to read the whole package document for every package found in the lockfile. I wonder if there is a better way.

zkochan and others added 2 commits July 31, 2026 02:11
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The SRI-option rejection asserted that strict consumers may reject options.
The real failure is worse: pnpm's Rust ssri has no option grammar, so it
absorbs the option into the digest, round-trips it through Display, and fails
far from the parse. Integrity-string equality is also byte equality across
pnpm, so an ordinal inside the value would make a revision-only difference
read as a content change.

Record encoding the ordinal in the lockfile package key as an alternative,
since the registry-qualified keys of pnpm/pnpm#13528 invite it. It is rejected
on churn: a dep path repeats once per dependent, so one revision bump would
rewrite roughly fifty lines for a package as common as semver, and
patchedDependencies already demonstrates this with patch_hash. The key may
carry extra data; it may not carry data designed to change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jordi-heller

Copy link
Copy Markdown

a feature to consider is the ability to refresh a lockfile to get the newest release while keeping the same version.

sure, such feature would make sense. The current architecture would make it slow though. We'd have to read the whole package document for every package found in the lockfile. I wonder if there is a better way.

What if we use a Get package/version request that only fetches the manifest of that version? Probably impossible to do better but will more efficient than fetching entire package documents

@zkochan

zkochan commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

pnpr has server side resolution, so I think it can do it fast. The npm registry has an audit endpoint which detects vulnerabilities. Maybe something similar could be added for this in the future. I think it wouldn't conflict with the design described in this PR. I think for the initial install having this info in the package document is good.

@jdalton

jdalton commented Aug 6, 2026

Copy link
Copy Markdown

Really excited about this - it's slipstream patching: the patched build
slides in under the same name@version, the digest stays the real identity,
the revision number is just for humans, and unpatched lockfiles never change.
Glad ?rN inside the integrity string is gone, too.

Comment on lines +438 to +441
additionally carry all provenance fields. Abbreviated metadata should keep
current `dist` plus the integrity, digest URL, and `manifest` of historical
revisions, so revision pinning works from the metadata pnpm actually
fetches. An unpatched version does not need a `dist.revisions` array or a

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example has revision on each entry; the requirement sentence doesn't
ask for it, and +rN resolves against the abbreviated packument.

Suggested change
additionally carry all provenance fields. Abbreviated metadata should keep
current `dist` plus the integrity, digest URL, and `manifest` of historical
revisions, so revision pinning works from the metadata pnpm actually
fetches. An unpatched version does not need a `dist.revisions` array or a
additionally carry all provenance fields. Abbreviated metadata should keep
current `dist` plus the `revision` ordinal, integrity, digest URL, and
`manifest` of each historical revision, so revision pinning works from the
metadata pnpm actually fetches. An unpatched version does not need a
`dist.revisions` array or a

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied. The requirement now reads:

Abbreviated metadata should keep current dist plus the revision number,
integrity, digest URL, and manifest of each historical revision — +rN
resolution maps a number to its history record using the metadata pnpm
actually fetches, so the number must survive abbreviation.

Also added a test bullet for the number being present in the abbreviated form.

Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
those package-level rules; "the registry references this digest" alone is
not sufficient. pnpr may deduplicate physical storage globally, but it must
not expose an object merely because another organization or registry stored
the same digest. Knowledge of a digest is not a bearer credential.

@jdalton jdalton Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's a proxy in the middle supposed to do?

Today anything sitting between the client and the registry - a corporate
proxy, a mirror, a registry firewall - can tell which package a request is
for just by reading the URL: lodash/-/lodash-4.17.21.tgz. That's what those
layers use to enforce policy, cache, and keep audit logs.

/-/tarballs/sha512/<digest> tells them nothing, on purpose (dedup, provider
neutrality - fair). But the doc doesn't say what that layer should do
instead. Two things worth spelling out:

  • "effective registry" when a proxy is in front. Revision numbers are
    scoped per registry and credentials are scoped same-origin, and both get
    ambiguous when the origin the client sees is the proxy, not the registry.
  • How to map a digest back to a package. Presumably dist.revisions is
    the lookup - and the answer can be plural, since dedup means one digest can
    back several name@versions.

Without this, every proxy invents its own heuristic.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — the RFC took the package name out of the URL without saying what
the layers that relied on it should do instead. Added a section,
Intermediaries and the digest route, spelling out both points you raised:

  • Effective registry. When a proxy fronts pnpr, the proxy's base URL is
    the registry from the client's point of view: revision numbers are scoped to
    that base and credentials are scoped same-origin to it. A proxy projecting
    several upstream registries has to present them as distinct bases (distinct
    path prefixes, say), because one base implies one numbering and one
    credential scope.
  • Digest → package. dist.revisions is the mapping, and the answer may be
    plural, since dedup lets one digest back several name@versions. A pnpr
    deployment should expose that reverse lookup to authorized policy and audit
    tooling.

against the base version. An integrity-aware pnpm audit extension can identify
the installed revision and subtract only fixes declared for those exact bytes.
A later provider revision does not retroactively add fixes to an older locked
revision.

@jdalton jdalton Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does audit tell "r2 replaces r1" from "r2 sits alongside r1"?

Both are legal here (different fixes sets), and revision numbers only tell
you the order - not whether an old one is dead. The withdrawal state the doc
defers is cheapest to add now - a per-entry withdrawn/supersededBy fits
append-only fine.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and cheaper to add now than to retrofit. Revision entries may carry
optional withdrawn and supersededBy fields: supersededBy records which
revision replaced a retired one, and two live revisions with disjoint fixes
sets simply coexist with neither set.

This is consistent with append-only — the fields describe the record's
standing, never its artifact, so annotating one touches no artifact-derived
field, byte, or number, and nothing is removed or renumbered. The RFC now says
that explicitly, since "append-only" and "mutable status field" read as a
contradiction otherwise. The audit section notes that the number alone never
distinguishes the two cases; there's also a test for annotating status without
renumbering.

Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated
Comment thread text/0000-integrity-addressed-registry-tarballs.md Outdated
Comment thread text/0000-integrity-addressed-registry-tarballs.md Outdated
resolution and validate the pair (origin, algorithm, digest equality,
positive integer ordinal).
2. Record `revision: N` in the resolution object and gate the field with an
appropriate lockfile version; lockfiles without the field keep the current

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When resolution.revision ships, please land it in @pnpm/lockfile-types +
docs in the same release. Lots of tools parse pnpm-lock.yaml; a typed field
on day one beats everyone reverse-engineering it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — added to the implementation steps: ship the field's type in
@pnpm/lockfile-types and document it in the same release that first emits it,
for exactly the reason you give.

@jdalton

jdalton commented Aug 6, 2026

Copy link
Copy Markdown

The npm registry has an audit endpoint which detects vulnerabilities. Maybe something similar could be added for this in the future.

👍 - this can come later without conflicting with the design here. A shape
suggestion for when it does: batch - POST the locked
(name@version, revision?) pairs, get back the selected revision, integrity,
and fixes for each; advisory only, the lockfile still decides what gets
fetched.

Audit is the strongest reason to build it: advisories are keyed on
name@version, so after a patched revision is installed a plain audit still
reports the vulnerabilities the patch fixed. The doc's answer (subtract
dist.revisions[].fixes for the installed bytes) is exactly this lookup -
one request per lockfile instead of a packument per package.

Comment thread pnpr/text/0000-integrity-addressed-patch-revisions.md Outdated

Rules:

- `N` is a positive base-10 integer;

@divmain divmain Aug 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth specifying that 0 < N <= MAX_SAFE_INTEGER. I'd assume this is the case but, because registries might not be implemented in JavaScript, it'd be worth defining this precisely.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point — "positive integer" isn't a spec for a protocol that
non-JavaScript registries implement. The revision field now requires a
canonical base-10 integer, no leading zeros, sign, or exponent, bounded by
0 < N ≤ 2^53 − 1. Registries must not allocate outside the range, and
clients reject values outside it. The malformed-value test now covers leading
zeros and above-range values alongside zero, negative, and non-integer.

naming in resolution metadata. It couples lockfiles to a provider and
duplicates structured registry metadata, and a provider rename would look
like an artifact change. Neutral integers explain artifact changes without
making provider identity part of package resolution.

@divmain divmain Aug 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neutral integers make artifact change comprehensible but they carry less meaning at rest.

For projects that end up with multiple registries for a single project (e.g. different registries for different @scopes), it would be useful to pack more information into the revision than a single ordinal can carry. The integrity field doesn't help here, and the registry identify is not present in the lock-file entry.

Additionally, a registry might source revisions from multiple providers, and then interleave those revisions into a single sequence of ordinals. In this scenario, the ordinal still conveys "this revision is presumably newer/better than the previous revision you were using" but otherwise requires sleuthing if someone wants to understand the provenance of a new revision being adopted.

It might be worth considering something ike -[a-zA-Z0-9_]+ as an optional suffix to the ordinal: meaningless to and thrown away by the package manager, but present in the lock-file for human readers.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both scenarios you describe are real: interleaved providers behind one
numbering, and multiple registries in one project where the lockfile entry
doesn't record which registry it came from.

I've recorded the suffix idea as an open question rather than adopting it,
because it pulls against the Put provider identity in the revision record
rejection — once the suffix exists, provider naming is back in resolution
metadata for anyone reading a lockfile, and a provider rename shows up as a
diff on entries whose bytes never changed. The counter-argument is that the
package manager throws it away, so it can't affect resolution. That trade
seems worth deciding deliberately rather than in passing.

Worth separating from the registry-identity half of your comment: the lockfile
genuinely can't say which registry an entry resolved from today, and a suffix
would only paper over that for human readers. It's tracked as its own open
question — representing named-registry identity so two registries can serve
the same name@version without colliding. Fixing that properly would give
provenance to tooling as well as to readers.

zkochan and others added 7 commits August 8, 2026 12:07
Co-authored-by: John-David Dalton <jdalton@users.noreply.github.com>
Co-authored-by: John-David Dalton <jdalton@users.noreply.github.com>
Co-authored-by: John-David Dalton <jdalton@users.noreply.github.com>
Co-authored-by: John-David Dalton <jdalton@users.noreply.github.com>
Co-authored-by: John-David Dalton <jdalton@users.noreply.github.com>
Co-authored-by: John-David Dalton <jdalton@users.noreply.github.com>
Review feedback from #19:

- sequence checkpoint stores the manifest digest: exact replay is a
  no-op, same sequence with different content is provider equivocation
- one validation rule for dist.revision, identical for full and
  abbreviated packuments
- abbreviated packuments retain each history entry's revision number
- new section on intermediaries: effective registry behind a proxy,
  digest-to-package mapping via dist.revisions
- per-entry withdrawn/supersededBy status in revision history
- every 3xx fails the digest fetch, same-origin included
- revision numbers bounded to 2^53 - 1 in canonical decimal form
- ship resolution.revision in @pnpm/lockfile-types with docs
- new unresolved questions: batch revision endpoint, human-readable
  revision annotation suffix

Terminology: a registry revision is now defined as the history entry;
its integer is its revision number, matching the dist.revision field.
The word "ordinal" no longer appears.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants