Documentation

Yank and deprecate

Two lifecycle operations, and how each ecosystem represents them.

Source: api.packr.blueforge.studio/-/docs/yank-and-deprecate

Yank and deprecate

Two operations that sound similar and are not.

Effect on resolutionReversibleDeletes anything
Yankstops being chosenyesno
Deprecatenoneyesno
Unpublishversion is gonenoyes

Yank a version nobody should get by accident: a bad build, a wrong commit, a release with a secret in it. Deprecate a version you would still rather people did not pick, but which works.

Neither deletes anything. unpublish, with its 72-hour window, remains the only destructive operation.

Yank

A yanked version:

  • is not deleted, and unyanking restores it;
  • stays downloadable by exact version, so lockfiles that already pin it keep resolving and existing builds do not break;
  • is flagged wherever the protocol has a place for the flag, and excluded where it does not;
  • never answers as latest.
packr-cli yank   cargo/serde@1.0.0 --reason "built from the wrong commit"
packr-cli unyank cargo/serde@1.0.0

Ecosystem-agnostic API:

POST /api/v1/admin/packages/yank
{"ecosystem":"cargo","name":"serde","version":"1.0.0","yanked":true,"reason":"…"}

Cargo also has native verbs, which the registry implements: DELETE /cargo/api/v1/crates/{crate}/{version}/yank and PUT .../unyank.

How each ecosystem shows it

EcosystemRepresentation
cargoyanked: true in the sparse index
PyPIPEP 592 data-yanked / "yanked" in the simple index
JVMyanked on the index line
NuGetlisted: false — the protocol's own word for it
Goabsent from @v/list; .info, .mod and .zip keep serving so go.sum still verifies
Mavenabsent from <versions> in maven-metadata.xml; the jar and pom keep serving
npmexcluded from latest resolution

Go and Maven have no in-protocol yank concept, so absence from the listing is the representation. That is why the exact-pin routes deliberately keep working.

Deprecate

A deprecated version still resolves, still answers as latest if it is newest, and still installs. The only effect is that clients whose protocol has somewhere to put the message show it.

packr-cli deprecate   pypi/widget@1.0.0 --message "use widget2"
packr-cli undeprecate pypi/widget@1.0.0
POST /api/v1/admin/packages/deprecate
{"ecosystem":"pypi","name":"widget","version":"1.0.0","message":"use widget2"}

An empty message clears the notice, matching npm deprecate "". A missing message field is a 400 rather than a clear, so a malformed request cannot silently undo a publisher's warning.

npm's own PUT /-/v1/deprecate still works, but only reaches npm packages.

Where it is rendered

EcosystemRepresentation
npmdeprecated on the version, in the packument and the version manifest
NuGetcatalogEntry.deprecation, the protocol's own model
JVMdeprecated on the index line
cargo, PyPI, Maven, Gonot rendered

The last row is deliberate. The cargo sparse index, PEP 503/691 and maven-metadata.xml define no deprecation field, and Go expresses deprecation as a // Deprecated: comment inside go.mod — which the registry must not rewrite, because that changes the file's hash and breaks every go.sum that already records it. Inventing a non-standard field those clients ignore would look like support without being it. The notice is still stored and still readable through the API for all seven.