Skip to content

fix(versions): rank only published rows in the version_updates view (audit M2) - #435

Merged
passcod merged 2 commits into
mainfrom
claude/pr-370-fix-m2-version-updates
Aug 1, 2026
Merged

fix(versions): rank only published rows in the version_updates view (audit M2)#435
passcod merged 2 commits into
mainfrom
claude/pr-370-fix-m2-version-updates

Conversation

@passcod

@passcod passcod commented Aug 1, 2026

Copy link
Copy Markdown
Member

Fixes M2 (medium) from the audit in #370.

The bug

version_updates reduces each (major, minor) line to its single highest-patch row (ROW_NUMBER() … WHERE rn = 1) with no status filter inside. get_updates_for_version then filters status = 'published' — too late. If the newest patch in a line is draft or yanked, that row is the only one the view exposes for the line, so the caller's filter drops the entire minor rather than falling back to the line's newest published patch.

MCP's get_version reads this, so available_updates silently omitted whole release lines. The public update_for endpoint does filter-then-reduce in Rust and offers the version fine, so the two disagree.

The fix

A migration redefining the view to rank published rows only — filter before the reduction, matching what update_for already does. A line with nothing published in it still contributes nothing, so an unpublished version can't leak out as an available update. The caller keeps its status filter as belt-and-braces.

Tests

New crates/database/tests/it/version_updates_view.rs:

  • a_line_offers_its_newest_published_patch_not_nothing — 2.46.{1,2} published + 2.46.3 draft, and 2.47.0 published + 2.47.1 yanked; updates from 2.45.0 are [2.46.2, 2.47.0].
  • a_wholly_unpublished_line_offers_nothing.

Confirmed against the unfixed view: updates from 2.45.0 come back empty — both lines vanish, not just the draft-topped one. Slightly worse than the audit described.


Generated by Claude Code

claude added 2 commits August 1, 2026 08:28
The view reduces each `(major, minor)` line to its single highest-patch row,
with no status filter inside; the caller then filters `status = 'published'`.
That is too late. If a line's newest patch is draft or yanked, that row is
the only one the view exposes for the line, so the caller's filter drops the
entire minor rather than falling back to the line's newest published patch.

With 2.46.2 published and 2.46.3 draft, nothing in the 2.46 line was offered
as an update at all — while the public `update_for` endpoint, which filters
before it reduces, happily offers 2.46.2. MCP's `get_version` reads this
view, so `available_updates` silently omitted whole release lines.

The view now ranks published rows only. A line with nothing published in it
still offers nothing, so an unpublished version can't leak out as an
available update.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SGfH1cdFKPnKpM7ytRThft
…version-updates

# Conflicts:
#	crates/database/tests/it/main.rs
@passcod
passcod marked this pull request as ready for review August 1, 2026 21:44
@passcod
passcod added this pull request to the merge queue Aug 1, 2026
Merged via the queue into main with commit 2165a02 Aug 1, 2026
7 checks passed
@passcod
passcod deleted the claude/pr-370-fix-m2-version-updates branch August 1, 2026 21:58
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.

2 participants