Files
minstrel/.gitea
bvandeusenandClaude Opus 5 9f3e0b8cd3
test-go / test (push) Successful in 1m25s
test-go / integration (push) Successful in 5m52s
feat(version): sidecar and /api/client/version carry name, code and channel
The client compares names while Android installs by versionCode, and the
wire had no way to close that gap: the sidecar was one positional line and
the endpoint returned a name only. This is the plumbing that makes the
ordering key decidable by the client at all.

The sidecar is now JSON rather than a grown positional string. That shape
was chosen against a specific failure: the obvious growth path was
"<name> <code>", which a first-space split silently mangles the moment a
third field appears — the code stops parsing as an integer and the reader
falls back to name comparison WITHOUT erroring. JSON cannot mistake a new
field for an old one.

code is a POINTER on both sides, and omitempty on the wire. Absent has to
stay distinguishable from zero: a build published before ordering keys were
recorded genuinely has no code, and zero would claim it is infinitely old
rather than unknown.

A malformed sidecar now fails loudly instead of serving a blank version.
If an unreadable file produced an empty name, every client would compare
against nothing, conclude it was current, and go quiet — "I cannot read
this" and "there is nothing newer" would return the same answer, which is
the failure mode nobody reports because nobody is offered anything to
report.

The non-tag :latest path no longer RECONSTRUCTS the bundled APK's version.
android-release now publishes the sidecar as a release asset beside the
APK, and the image build downloads it. The old reconstruction duplicated a
derivation formula across two files, and could only ever recover the name —
the ordering key is build-time minutes and exists nowhere once that build
ends. Releases predating the sidecar report their name with a null code,
which is the honest answer rather than a guessed one.

image-release also drops to a shallow checkout: it needed full history and
tags only to re-derive versions from the tagged commit, and now touches git
for nothing. MINSTREL_VERSION comes from GITHUB_REF.

Two things checked rather than assumed. The Android Json sets
ignoreUnknownKeys, so the added fields cannot break already-installed apps.
It also sets coerceInputValues, which will silently turn a null code into 0
if step 4 declares the field non-nullable — recorded on task #3811, because
reading the field declaration alone would never reveal it.

Also fixes a stale comment block describing "the Flutter client", deleted
in v2026.08.18.

Step 3 of 5 — Scribe task #3810, milestone #390.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SQ31KQpYbStyK5y58UmPLH
2026-09-09 21:51:41 -04:00
..