Coupled Cargo rehearsal cannot validate the library package manifest before macro publish #137

Closed
opened 2026-07-29 01:49:47 +00:00 by perishadmin · 1 comment
Contributor

Context

The first v0.14.0 beta attempt published plumb-macro and only then discovered that Cargo canonicalizes the library dependency from a named registry to registry-index in the packaged manifest. The current credential-free rehearsal runs cargo package --no-verify --list for plumb, which proves the file set but never inspects that generated manifest.

A full library package cannot simply replace the list operation: Cargo still resolves the exact registry dependency, so it refuses while the matching prerelease macro is not published. The irreversible macro publish therefore remains ahead of one coupled-manifest proof.

This is related to #135 but narrower: #135 concerns generic lane evidence; this issue is the concrete coupled-Cargo rehearsal seam.

Acceptance

  • A credential-free rehearsal detects an incorrect exact macro version or registry target in the packaged library manifest before any external publish.
  • The proof is hermetic: no Cargo upload, R2 write, metadata advance, or Git tag.
  • Use a local registry fixture or another proof equivalent to Cargo packaged-manifest normalization; do not duplicate Cargo normalization rules as an unchecked guess.
  • Add a regression specimen for named-registry to registry-index canonicalization.
  • Reconcile the coupled-Cargo lane reference if Cargo imposes a narrower achievable ordering.
Context The first v0.14.0 beta attempt published `plumb-macro` and only then discovered that Cargo canonicalizes the library dependency from a named registry to `registry-index` in the packaged manifest. The current credential-free rehearsal runs `cargo package --no-verify --list` for `plumb`, which proves the file set but never inspects that generated manifest. A full library package cannot simply replace the list operation: Cargo still resolves the exact registry dependency, so it refuses while the matching prerelease macro is not published. The irreversible macro publish therefore remains ahead of one coupled-manifest proof. This is related to #135 but narrower: #135 concerns generic lane evidence; this issue is the concrete coupled-Cargo rehearsal seam. Acceptance - A credential-free rehearsal detects an incorrect exact macro version or registry target in the packaged library manifest before any external publish. - The proof is hermetic: no Cargo upload, R2 write, metadata advance, or Git tag. - Use a local registry fixture or another proof equivalent to Cargo packaged-manifest normalization; do not duplicate Cargo normalization rules as an unchecked guess. - Add a regression specimen for named-registry to `registry-index` canonicalization. - Reconcile the coupled-Cargo lane reference if Cargo imposes a narrower achievable ordering.
Owner

Closed by main dd42b90, and worth recording how it surfaced.

Under the old model this was hidden. The Cargo attachment pinned each package to the version it last changed in, so the library's requirement on the macro named a version already on the registry, and cargo package could verify it. The coupling was real; the pins made it invisible.

v0.26.0 makes the attachment one object: every package it declares carries one version and ships together. The library then requires plumb-macro =0.26.0 before that version exists, and the stable release stopped exactly where you said it would:

error: failed to prepare local package for uploading
  failed to select a version for the requirement `plumb-macro = "=0.26.0"`
  required by package `plumb v0.26.0`

The answer is not to make the rehearsal cleverer. cargo package verifies by building, and the version it needs cannot exist before the ordered publish creates it — that is Cargo's shape, not Plumb's. So a rehearsal now says which packages it cannot rehearse and why:

plumb-core requires a sibling this release has not published yet

and the ordered publish is what proves them. Dev-dependencies do not count as coupling, because verification does not build them.

Closed by main `dd42b90`, and worth recording how it surfaced. Under the old model this was hidden. The Cargo attachment pinned each package to the version it last changed in, so the library's requirement on the macro named a version already on the registry, and `cargo package` could verify it. The coupling was real; the pins made it invisible. v0.26.0 makes the attachment one object: every package it declares carries one version and ships together. The library then requires `plumb-macro =0.26.0` before that version exists, and the stable release stopped exactly where you said it would: ``` error: failed to prepare local package for uploading failed to select a version for the requirement `plumb-macro = "=0.26.0"` required by package `plumb v0.26.0` ``` The answer is not to make the rehearsal cleverer. `cargo package` verifies by building, and the version it needs cannot exist before the ordered publish creates it — that is Cargo's shape, not Plumb's. So a rehearsal now says which packages it cannot rehearse and why: ``` plumb-core requires a sibling this release has not published yet ``` and the ordered publish is what proves them. Dev-dependencies do not count as coupling, because verification does not build them.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
PerishLab/plumb#137
No description provided.