v2.5.0
Production release: pipeline polish, mobile-responsive shell, multi-tool visibility.
Fixed
docker pull :latestreturned stale code.:latestwas pushed from BOTH the tag-build job AND the main-branch build job in.github/workflows/docker.yml. A docs-only push tomainafter a release tag would race the tag job and overwrite:latestwith main's older HEAD. Removed the main-branch line;:latestnow ONLY tracks the most recent semver tag.- GitHub Releases stuck at v1.0.1. Tags
v2.0.0..v2.4.2existed in git but no workflow ever created Release entries. Addedsoftprops/action-gh-release@v2step gated on tag push; release body extracted from the matching[X.Y.Z]CHANGELOG section via awk. Every future tag auto-publishes a Release with formatted notes. - No URL printed on container startup. Added
docker-entrypoint.shthat prints a banner with the open URL before handing off to nginx. Honest about host-port mapping (doesn't print a misleadinglocalhost:80when usersdocker run -p 8080:80).
Added
- In-app version display. Footer chip shows
v{APP_VERSION}linking to the changelog. About page shows "Running v{APP_VERSION}" with View changelog + All releases links. Version is injected at build time via Vitedefine:reading the rootpackage.json— no hand-sync. - Update-available banner.
/settings/release/update-check.tsfetchesapi.github.com/.../releases/latestonce per session (6h sessionStorage cache) and surfaces a dismissible accent banner above the HeaderBar when a newer version exists. Per-version dismiss state in localStorage so dismissing v2.5.1 doesn't suppress v2.6.0. Silent on every failure path (network, 4xx, malformed JSON, CORS). Default ON; opt-out via the new "Release notifications" section in Settings → Local Data. - Mobile-responsive shell.
- New hamburger button (
<smonly) in HeaderBar opens a full-screenMobileNavDrawercontaining the same 26-tool list the desktop TabRail renders. Each row shows the sameanimate-pulserunning-dot — the "blinking effect" works on mobile. - Drawer accessibility:
role="dialog",aria-modal, focus trap, Escape to close, backdrop click closes, focus restores to the hamburger button. - Desktop TabRail wrapped in
hidden sm:blockso it disappears below 640 px (where it was wrapping to 3-5 rows and pushing the running dots off-screen). - Touch targets in HeaderBar buttons + Settings sidebar bumped to
min-h-11/h-10 w-10on mobile (closer to the 44 px HIG floor) and back to the desktop sizing onsm:and up. pt-safe/pb-safe/pl-safe/pr-safeutilities inapp/src/app.cssusingenv(safe-area-inset-*)— applied to the sticky header (iPhone notch) and the footer (Android nav bar).
- New hamburger button (
- Global "{N} running" badge in HeaderBar.
ActiveRunsBadge.sveltesurfaces in-flight runs from every tool, not just the currently-open route. Click opens a popover listing each running tool with elapsed time + a deep-link back to its route. Closes the visibility gap where users couldn't tell whether a long-running tool was still working after they navigated away. - Tool registry refactor.
TabRail.svelte'sTABSarray now carries atoolIdfield per entry inside a<script module>export.MobileNavDrawerandActiveRunsBadgeboth consume the same source-of-truth array. The old 9-entryhrefToToolId()switch is gone — all 26 visible tool routes now resolve to a toolId, so the desktop TabRail running-dot and the mobile drawer running-dot fire for every tool with anactiveRuns.start()registration. - Reload-orphan notification.
activeRuns.svelte.tswrites a tinySet<toolId>snapshot to localStorage on everystart()and removes on everyfinish/fail/cancel/clear. If the previous session left entries (closed tab, hard reload, crash mid-flight), the layoutonMountemits a one-shotnotify.info"N runs were interrupted by your last page reload" and clears the snapshot. The in-flight Promise can't be resumed, but the user's form state IS persisted (existinguseToolState). - Dynamic README badge.
README.mdline 21 swapped its hardcodedv2.3.0badge for ashields.io/github/v/releasedynamic badge that polls GitHub's API and serves a cached SVG. The README never drifts from the actual release surface again.
Changed
app/vite.config.ts: build now reads rootpackage.jsonviafs.readFileSyncand exposes__APP_VERSION__+__APP_REPO__as compile-time globals. Also dropped the stale$legacy: '../js'alias that pointed at the deleted directory.
Tests
- 873 → 886 (+13): full coverage for the new
release/update-check.tsmodule — semver compare edge cases, sessionStorage cache hit/miss, silent failure on non-OK responses, thrown fetch, malformed JSON, manual cache clearing.
Image
ghcr.io/m4xx101/cryptex-oss:v2.5.0(multi-archlinux/amd64+linux/arm64).:latest,:v2.5,:2.5,:v2,:2all point at the same SHA. The new pipeline guarantees:latesttracks the v2.5.0 SHA going forward — the bug that caused users to pull stale code is fixed.