~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

A release can be yanked, leaving it to read but no one's latest

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:release/yank

What changes

knotless release yank <url> <package> <version> [--undo], and the release_yank tool, withdraw a version. It stays there to read and download by its version, so what pins it keeps working, but it is no longer the latest.

A new record, dev.knotless.releaseYank, in the owner's account under the release's own key, since a release's record never changes. Deleting it takes the yank back.

What skips a yanked version: release download and release read of the latest, /releases/latest, docker pull of latest, workflow pin, a step's version in the directory, and the release a repository's pages show under its name. The releases page marks it Yanked, and release list and release_list say so.

Why

The only way to withdraw a bad release was to delete its record, which breaks everyone who pinned it. It is also what a Cargo registry needs before anyone relies on one, and yanked in Cargo's index will read these records, but nothing here is particular to Cargo.

How it was checked

Tests added at each layer: the CLI against the PDS, the MCP tool, the index, and what the pages and steps pick as latest. A throwaway server earlier showed real cargo honouring a yank over a record of this shape. The rest is left to CI.

The page's state is not in the recording, so the shots check does not draw it: pictures of the tag follow on this pull.

Shortcomings

An existing OAuth login lacks the new collection's scope, so its yank fails until it logs in again. App passwords are not affected.

/releases/ and the image registry list a package's releases once a minute, so a yank takes up to a minute to reach them.

A shared step's page still lists its yanked versions unmarked, and a step with every version yanked has no page. The Atom feed still lists yanked versions. There is no reason field and no control on the pages: both can come later.

Review

The lexicon is the part that cannot be taken back: start at lexicons/dev/knotless/releaseYank.json.

🤖 Generated with Claude Code

Asked for changes

This adds dev.knotless.releaseYank, a second record under the release's own key. It adds release yank [--undo] and the release_yank tool, and makes the latest-version logic (CLI, step pins, pages, index) skip yanked versions. The design is sound, and the lexicon is minimal and fits the existing release record.

Must fix: the index backfill never reads yank records. indexed_collections() in crates/knotless-serve/src/lib.rs (about line 853) lists the collections a backfill and relay lookup read. It includes nsid::RELEASE but not nsid::RELEASE_YANK. You added the new nsid to jetstream::knotless, so live events are indexed. Anything that arrives through backfill is not. That covers a fresh index, a CACHE rebuild (this pull adds release_yank to that drop list), and any yank missed while the feed was down. After such a rebuild every yanked version would read as live again: it would become latest on the pages, /releases/latest and the step directory. Add knotless::records::nsid::RELEASE_YANK there, and add a test like the existing ones for the list. If a test already ties the backfill list to the jetstream one, it should have caught this, so check it.

Minor, no change needed: release::list checks yanks with yanks.iter().any(..) for each release. This is quadratic, but it is small per repository and package.

crates/knotless-serve/src/index.rsline 1307Outdated
.and_then(|n| self.share(&db, &uri, did, &release).map(|_| n)),
None => Ok(0),
}
} else if collection == nsid::RELEASE_YANK {
review.knotless.dev

The index stores yanks here, but indexed_collections() in crates/knotless-serve/src/lib.rs doesn't list RELEASE_YANK, so a backfill never feeds this branch. Add it there.

Approved

The earlier request is done. indexed_collections() in crates/knotless-serve/src/lib.rs now lists nsid::RELEASE_YANK, and the new test a_backfill_reads_yanks checks that. A rebuilt or backfilled index will therefore see yanks. I read only that fix and the PR metadata this round, not the rest of the diff again. I found nothing else to ask for.

Approved

My earlier request is still done: indexed_collections() lists RELEASE_YANK, and a_backfill_reads_yanks covers it. Since my last approval the head moved to a merge of main plus a commit that adjusts the yank test to the sandbox's trimmed command output. I did not re-read the full diff this round. A diff of the new head against the old one came back too large to read, because it includes the merged main changes. I read only the commit messages and PR metadata, and found nothing new to ask for.

Approved

My earlier request is still done: indexed_collections() lists RELEASE_YANK, and a_backfill_reads_yanks covers it. Since my last approval the head gained one commit, "Resolve the merge with main's reformatted pages", which only resolves a merge conflict. I did not re-read the full diff, because main's merged changes make it too large. I read the commit messages and the pull's metadata, and found nothing new to ask for. The merge queue's checks cover the conflict resolution.

Approved

My earlier request is still done: indexed_collections() lists RELEASE_YANK, and a_backfill_reads_yanks covers it. I did not re-read the full diff this round, because the merges from main make the diff against earlier heads too large to read. I found nothing new to ask for.

Merged as a59f04e
Part of a stack of 3
  1. A release can be yanked, leaving it to read but no one's latest Landed as a59f04e
  2. main