Skip to content

feat(components): version currency — 'behind latest patch' signal (BomLens parity #18)#503

Merged
haksungjang merged 2 commits into
mainfrom
feat/currency-staleness-offline
Jul 18, 2026
Merged

feat(components): version currency — 'behind latest patch' signal (BomLens parity #18)#503
haksungjang merged 2 commits into
mainfrom
feat/currency-staleness-offline

Conversation

@haksungjang

Copy link
Copy Markdown
Contributor

Summary

Adds a component-level version currency signal — a sibling of the EOL flag that answers a different question: not "is this release line dead?" but "is this version behind the newest patch of its (still-supported) release line?".

Fully offline. It reuses the already-vendored endoflife.date snapshot, whose every cycle carries its newest patch (latest + latestReleaseDate). The same purl→product→cycle matcher the EOL evaluator uses now also compares the installed version to the cycle's latest via the tolerant cross-ecosystem comparator (upgrade_recommendation.compare_versions): installed < latest → outdated, >=current, no cycle/latest/unparseable → unknown. No new network at scan time — the deps.dev "absolute-newest / N releases behind" enrichment is a separate opt-in egress path, deliberately not in this MVP.

Backend

  • Migration 0040 adds component_versions.currency_* catalog columns (mirrors the 0038 EOL columns + a partial index on outdated).
  • evaluate() carries currency alongside EOL in one pass; stamp_component_version writes it — so BOTH the scan-persist hook and the weekly refresh beat stamp it for free (no new task, no new gate; rides EOL_ENABLED/the same snapshot).
  • Exposed on the components list/detail and a project-Overview outdated_count, with an ?outdated=true filter mirroring ?eol=true.

Frontend

  • CurrencyBadge (mirrors EolBadge, one tone below — medium, a maintenance signal, never Critical/High), a Components column, a drawer row, an Overview "N outdated" chip deep-linking to the filter, and the toolbar toggle. EN/KO, a FE↔BE CURRENCY_STATES parity contract, and a seed fixture on a component separate from the EOL one so both badges/chips assert independently.

Test plan

  • Currency evaluation matrix (outdated / current / unknown / no-latest / no-cycle-match) + stamp idempotency (6 new catalog cases; 63 EOL-suite tests green incl. the scan-stamp + refresh-beat paths)
  • List/detail exposure + ?outdated=true filter + permission-before-state (IDOR) ordering
  • CurrencyBadge render + a11y (renders only for outdated), Overview chip render + deep-link, FE↔BE mirror contract
  • mypy + ruff clean; FE typecheck/lint/i18n clean; OpenAPI snapshot regenerated
  • Note: the e2e seed now stamps one component outdated (parallel to the EOL fixture), so the badge/chip are demonstrable; the e2e otherwise auto-skips without the dev stack.

Closes BomLens parity #18 (offline MVP).

…mLens parity #18)

Adds a component-level 'version currency' signal, a sibling of the EOL flag
that answers a different question: not 'is this release line dead?' but 'is
this version behind the newest patch of its (still-supported) release line?'.

Fully OFFLINE — reuses the already-vendored endoflife.date snapshot, whose
every cycle carries its newest patch (latest + latestReleaseDate). The same
purl->product->cycle matcher the EOL evaluator uses now also compares the
installed version to the cycle's latest via the tolerant cross-ecosystem
comparator (upgrade_recommendation.compare_versions): installed < latest =>
outdated, >= => current, no cycle/latest/unparseable => unknown. No new
network at scan time.

Backend: migration 0040 adds component_versions.currency_* catalog columns
(mirrors the 0038 EOL columns + a partial index on 'outdated'); evaluate()
carries currency alongside EOL in one pass; stamp_component_version writes it,
so BOTH the scan-persist hook and the weekly refresh beat stamp it for free.
Exposed on the components list/detail and a project-Overview outdated_count,
with an outdated=true filter mirroring the eol=true one.

Frontend: CurrencyBadge (mirrors EolBadge, one tone below at medium — a
maintenance signal, never Critical/High), a Components column, a drawer row,
an Overview 'N outdated' chip deep-linking to the filter, and the toolbar
toggle. EN/KO, a FE<->BE CURRENCY_STATES parity contract, seed fixture on a
component separate from the EOL one so both assert independently.

The deps.dev 'absolute-newest across the ecosystem / N releases behind'
enrichment is a separate opt-in egress path (air-gap gated), not in this MVP.

Tests: currency evaluation matrix (outdated/current/unknown/no-latest/no-match)
+ stamp idempotency, list/detail exposure + outdated filter + IDOR ordering,
CurrencyBadge render + a11y, Overview chip render + deep-link, mirror contract.
OpenAPI snapshot regenerated. Updates parity #18 (closed, offline MVP).

from alembic import op

revision: str = "0040"
from alembic import op

revision: str = "0040"
down_revision: str | None = "0039"

revision: str = "0040"
down_revision: str | None = "0039"
branch_labels: str | Sequence[str] | None = None
revision: str = "0040"
down_revision: str | None = "0039"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
…nd-built completeness)

The AST hand-built-response completeness contract requires every
ProjectOverviewResponse field to be passed explicitly at the endpoint
construction site; outdated_count (0040) was in the service payload but not
threaded through, so it would silently default on the wire.
@haksungjang
haksungjang merged commit 9a71d6d into main Jul 18, 2026
20 checks passed
@haksungjang
haksungjang deleted the feat/currency-staleness-offline branch July 18, 2026 08:45
haksungjang added a commit that referenced this pull request Jul 18, 2026
…den path, screenshots (#505)

Close the doc-code drift and onboarding gaps found by the 2026-07 docs
quality review:

- Document the two shipped-but-undocumented user-facing features, EN+KO,
  with docs-uat assertions and freshly captured screenshots:
  * Vulnerabilities "Group by upgrade" view (W9-#53, #500)
  * Version currency "behind latest patch" signal (#503)
- Onboarding golden path: intro now leads with a recommended single
  route (5-min demo -> first real scan -> production); quickstart gains
  step 5 "Scan your first real project"; the docker-compose evaluation
  section delegates its duplicated boot steps to the quickstart (also
  removing its stale seed command that lacked --demo-only).
- ci-integration/github-actions: add a "Before you begin" block covering
  the three unmet prerequisites a new user hits (network-reachable
  portal vs localhost demo, API key, project id).
- reference/faq: fix the reachability contradiction ("planned" vs
  shipped for Go via govulncheck).
- contributor-guide/releasing: add a pre-tag documentation sweep to the
  release checklist (release notes from CHANGELOG [Unreleased], guide
  coverage for every user-facing entry, screenshot capture) so features
  can no longer ship without guide coverage.
- Screenshots: new capture spec (capture_feature_additions.spec.ts, split
  from the bulk matrix for isolated re-capture) and a deterministic
  fixed_version fixture in seed_e2e_user.py so the By-upgrade view
  renders real upgrade clusters; delete eight orphaned 68-byte
  placeholder PNGs under docs/user-guide/img/.

Verified: Docusaurus EN+KO build green (0 broken links/anchors),
docs-uat extract 201 steps, ko-style S1/S2 0, seed unit tests 10 passed,
both capture specs green against the live dev stack.
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.

1 participant