Maintenance release rolling up everything since 2026.06.1 (the 2026.06.2 bump was never cut as a release). Focus areas: arm64/Qt6 board support, Sentry error tracking, viewer/webview crash-recovery, and server/celery resilience. Cutting this triggers the balena OTA deploy to all screenly_ose/anthias-* fleets; unpinned devices pull it and restart.
New boards & fleets
- feat(viewer,build,balena): add arm64/Qt6 pi3-64 board and the Rock Pi 4 fleet; keep 32-bit pi3 as legacy (#2985).
Observability
- feat(sentry): add Sentry error tracking to the Django services (#3007).
- feat(sentry): tag events with device type, host kernel, and board model (#3021).
- feat(sentry): stamp the release with the build hash and tag balena deploys (#3025).
- fix(sentry): stop reporting transient redis blips and client disconnects (#3018), also drop transient redis TimeoutError events (#3028), and silence the celery redis-backend reconnect-retry log (#3036).
- fix(celery): don't report the by-design codec rejection to Sentry (#3041).
Performance
- perf(viewer): pace Qt6 video frame delivery to scene-render capacity (#3006).
- fix(viewer): aspect-fit, gapless looping, and 30fps cap for pi1/2/3 video (#3004).
Viewer & webview
- fix(viewer): run PulseAudio so Qt 6 video plays with audio (#3001).
- fix(viewer): default x86 audio fallback to ALSA 'default' (#3038).
- fix(viewer): wait for cage's Wayland socket before spawning the webview (#3030).
- fix(webview): add a page-load watchdog so a stalled fetch can't freeze the display (#3003).
- fix(viewer): respawn the webview when it dies mid-D-Bus call (#3012), before setup's
bus.get(#3020), and on a video-play D-Bus death rather than log+stop (#3031). - fix(viewer): silence sh's monitor-thread crash report on webview exit (#3011).
Server & celery resilience
- fix(server): open SQLite with WAL journaling and a busy timeout (#3015).
- fix(celery): gate worker startup on applied database migrations (#3016).
- fix(celery): catch the asset-probe timeout instead of hard-killing the worker (#3017).
- fix(celery): store
display_powerin redis as a string, not a bool (#3032). - fix(server): survive unreadable static files instead of crash-looping (#3026).
- fix(server): keep legacy host timezones from crash-looping Django (#3010).
- fix(server): stream the backup download so large libraries don't time out (#3005).
- fix(views): accept 12-hour AM/PM times in the asset edit form (#3002).
- fix(server): surface the exception detail in GitHub update-check warnings (#3023) and log release-check failures at warning, not error (#3019).
Uploads
- feat(server): offer HandBrake GUI steps for rejected video uploads (#3040).
Balena fleet automation
- feat(balena): hourly job to unpin pinned fleet devices (#2980).
- feat(balena): unpinner also rolls OS + supervisor updates (#2984).
Build & infra
- fix(build): ship libwebpdemux2 so pi3 Pillow can save WebP (#3042).
- fix(redis): persist data to the mounted volume so device identity survives recreation (#2983).
- fix(docker): pull the BuildKit frontend via mirror.gcr.io (#3008).
- Fixes SBOM (#2982).