ae26d66987
* HealthzApi — GET /healthz unauthenticated endpoint returning
{status, version, min_client_version}.
* VersionCheckController — Hilt singleton; 5-minute poll loop on
appScope, soft-fails on network errors (keeps last-known
VersionResult: OK / TOO_OLD / SKIPPED). Reuses isVersionNewer()
from the About card's UpdateRepository. Exposes recheck() for
the banner's "Check now" button.
* VersionTooOldBanner — shell-level Compose banner with
AnimatedVisibility shrink/expand, triangle-alert icon, copy
matching Flutter, "Check now" trailing button. Tiny
VersionTooOldViewModel lifts the StateFlow through Hilt.
* ShellScaffold adds VersionTooOldBanner() above ConnectionErrorBanner()
in the existing banner slot.
* MinstrelApplication uses the construct-the-singleton trick to
start the poll loop at app launch.
Closes audit v2 #23. Locally cached content keeps working when
the banner is shown — the message nudges the user toward an
update without blocking the rest of the UI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>