fix(version): gate update banner on semver ordering, not string inequality (MAPPS-370) #430

Merged
nrupard merged 2 commits from fix/MAPPS-370-update-banner-semver-compare into main 2026-07-15 18:10:32 +02:00
Owner

Fixes MAPPS-370.

The admin update banner prompted a backwards downgrade ("Client: 0.7.1 -> 0.7.0") in staging and self-host stacks.

VersionPair::update_available() (src/modules/system.rs) returned true whenever latest != running - a plain string inequality with no direction and no numeric ordering. get_version() sets the client's latest to the server's running version, assuming mokosh-server and mokosh-www release in lockstep. The MAPPS-369 CSP hotfix broke that assumption: mokosh-www went to 0.7.1 while mokosh-server stayed 0.7.0, so client.running = 0.7.1 and client.latest = 0.7.0. 0.7.0 != 0.7.1 fired the banner and rendered the downgrade prompt. The string compare also mis-ordered multi-digit fields (0.7.10 sorts below 0.7.9).

Fix

  • New parse_semver() reduces a normalised MAJOR.MINOR.PATCH string to (u64, u64, u64); anything that is not exactly three integers returns None. No new crate dependency (plain X.Y.Z release strings do not need the full semver crate in a WASM bundle).
  • update_available() now returns true only when both sides parse and latest > running. Unparseable input on either side fails closed (no banner) rather than risking a wrong prompt.
  • The client.latest = server version model is unchanged: with a strict-greater compare a client ahead of the server stays quiet and clears once the server catches up, while a genuinely newer server still prompts.

Verification

just pre-commit green (fmt + clippy + wasm check + cargo test --lib, 215 tests). New tests cover: the reported 0.7.1 / 0.7.0 -> false downgrade case, a normal upgrade, multi-digit ordering (0.7.9 vs 0.7.10), equal, None, and malformed input; plus a parse_semver case table.

docs/versioning.md section "1. Cross-version update (the banner)" updated to describe the strict-greater semver compare and the server/client patch-divergence behavior.

Fixes MAPPS-370. The admin update banner prompted a backwards downgrade ("Client: 0.7.1 -> 0.7.0") in staging and self-host stacks. `VersionPair::update_available()` (`src/modules/system.rs`) returned true whenever `latest != running` - a plain string inequality with no direction and no numeric ordering. `get_version()` sets the client's `latest` to the server's running version, assuming mokosh-server and mokosh-www release in lockstep. The MAPPS-369 CSP hotfix broke that assumption: mokosh-www went to 0.7.1 while mokosh-server stayed 0.7.0, so `client.running` = 0.7.1 and `client.latest` = 0.7.0. `0.7.0 != 0.7.1` fired the banner and rendered the downgrade prompt. The string compare also mis-ordered multi-digit fields (`0.7.10` sorts below `0.7.9`). ## Fix - New `parse_semver()` reduces a normalised `MAJOR.MINOR.PATCH` string to `(u64, u64, u64)`; anything that is not exactly three integers returns `None`. No new crate dependency (plain X.Y.Z release strings do not need the full `semver` crate in a WASM bundle). - `update_available()` now returns true only when both sides parse and `latest > running`. Unparseable input on either side fails closed (no banner) rather than risking a wrong prompt. - The `client.latest = server version` model is unchanged: with a strict-greater compare a client ahead of the server stays quiet and clears once the server catches up, while a genuinely newer server still prompts. ## Verification `just pre-commit` green (fmt + clippy + wasm check + `cargo test --lib`, 215 tests). New tests cover: the reported `0.7.1 / 0.7.0 -> false` downgrade case, a normal upgrade, multi-digit ordering (`0.7.9` vs `0.7.10`), equal, `None`, and malformed input; plus a `parse_semver` case table. `docs/versioning.md` section "1. Cross-version update (the banner)" updated to describe the strict-greater semver compare and the server/client patch-divergence behavior.
fix(version): gate update banner on semver ordering, not string inequality
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 4m41s
7e83439bf7
`VersionPair::update_available()` returned true whenever `latest != running` (plain string inequality, no direction, no numeric ordering). `get_version()` sets the client's `latest` to the *server's* running version on the assumption the two images release in lockstep. The MAPPS-369 CSP hotfix broke that: mokosh-www went to 0.7.1 while mokosh-server stayed 0.7.0, so client.running=0.7.1 and client.latest=0.7.0. `0.7.0 != 0.7.1` fired the banner and rendered a backwards "Client: 0.7.1 -> 0.7.0" downgrade prompt in staging and self-host stacks. The string compare also mis-ordered multi-digit fields (`0.7.10` sorts below `0.7.9`).

Parse each side to `(major, minor, patch)` and show the banner only when `latest` is strictly greater than `running`. Unparseable input on either side fails closed (no banner) rather than risking a wrong prompt. Keeps the `client.latest = server version` model: with a strict-greater compare a client ahead of the server stays quiet and clears once the server catches up, while a genuinely newer server still prompts.

Tests cover the reported downgrade case, a normal upgrade, multi-digit ordering, equal, None, and malformed input. `docs/versioning.md` updated to describe the semver compare and the server/client patch-divergence behavior.

#MAPPS-370

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat(version): surface a "server behind client" banner for the reverse skew
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 2m54s
Create release / Create release from merged PR (pull_request) Has been skipped
25395883e9
The strict-greater `update_available()` fix correctly stopped the backwards downgrade prompt, but that left the genuine reverse mismatch (the loaded client bundle is newer than the server it talks to, e.g. a www-only patch hotfix, or a server image that was not upgraded alongside the client) with no banner at all.

Add `VersionPair::running_ahead()` - the inverse of `update_available` (`running` strictly greater than `latest`, same semver parse and fail-closed rules), so the two are mutually exclusive - and a distinct banner message. Both directions are now covered:

- Client behind server: "Update available. Client: X -> Y." -> bump the client tag and pull.
- Server behind client: "Server needs updating. The client bundle (X) is newer than the server (Y)." -> upgrade the server image.

Tests cover `running_ahead` (bundle newer, older, equal, multi-digit ordering, None, malformed, and mutual exclusivity with `update_available`). `docs/versioning.md` section 1 documents both skew directions.

#MAPPS-370

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard scheduled this pull request to auto merge when all checks succeed 2026-07-15 18:09:47 +02:00
nrupard deleted branch fix/MAPPS-370-update-banner-semver-compare 2026-07-15 18:10:32 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
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
psa-systems/mokosh-apps!430
No description provided.