fix(scanner): report osVersion and appVersion on every heartbeat #18

Merged
james.maes merged 1 commits from fix/refresh-device-versions into main 2026-11-06 23:23:24 +00:00
Owner

Summary

Scanner host now reports the installed osVersion and appVersion on every session heartbeat.

MC9400 finding. After the authorized in-place update 1.0.0 → 1.0.1 (versionCode 2 → 3) on the MC9400, scan receipts still reported appVersion 1.0.0. The host only sent osVersion/appVersion at enrollment, and the server never refreshed them on the device record.

Change.

  • MobileSessionApi carries osVersion (Build.VERSION.RELEASE) and appVersion (BuildConfig.VERSION_NAME) in each heartbeat body; blank values are omitted and values are capped at 200 characters. The map is injectable for tests.
  • Docs: docs/UI-API.md (heartbeat contract) and docs/SESSION-STATE.md (finding).

Validation

  • Shared-library and scanner JVM tests passed: core 52, mobileapp 62, scanner-host 125 (MobileSessionTest.networkPayloadUsesSemanticRoutesAndCarriesOnlyScreenMetadata now asserts both version keys are present and that no other device metadata such as manufacturer/model is sent)
  • Scanner lint clean
  • Native emulator tests: not run for this change
  • Hardware: not yet installed on the MC9400; ships in the planned 1.0.2 build. Remaining check: a scan receipt after the update shows the new appVersion.

Compatibility and rollout

Additive optional keys on the existing heartbeat. Effective with a mobile-scanners 1.6.0 server (same-named server branch refreshes the device record when the values change); older servers ignore the keys. The installed 1.0.1 APK does not include this change. No credentials, cookies, tokens or barcodes included.

🤖 Generated with Claude Code

## Summary Scanner host now reports the installed `osVersion` and `appVersion` on every session heartbeat. **MC9400 finding.** After the authorized in-place update 1.0.0 → 1.0.1 (versionCode 2 → 3) on the MC9400, scan receipts still reported `appVersion` 1.0.0. The host only sent `osVersion`/`appVersion` at enrollment, and the server never refreshed them on the device record. **Change.** - `MobileSessionApi` carries `osVersion` (`Build.VERSION.RELEASE`) and `appVersion` (`BuildConfig.VERSION_NAME`) in each heartbeat body; blank values are omitted and values are capped at 200 characters. The map is injectable for tests. - Docs: `docs/UI-API.md` (heartbeat contract) and `docs/SESSION-STATE.md` (finding). ## Validation - [x] Shared-library and scanner JVM tests passed: core 52, mobileapp 62, scanner-host 125 (`MobileSessionTest.networkPayloadUsesSemanticRoutesAndCarriesOnlyScreenMetadata` now asserts both version keys are present and that no other device metadata such as `manufacturer`/`model` is sent) - [x] Scanner lint clean - [ ] Native emulator tests: not run for this change - [ ] Hardware: not yet installed on the MC9400; ships in the planned 1.0.2 build. Remaining check: a scan receipt after the update shows the new `appVersion`. ## Compatibility and rollout Additive optional keys on the existing heartbeat. Effective with a mobile-scanners **1.6.0** server (same-named server branch refreshes the device record when the values change); older servers ignore the keys. The installed 1.0.1 APK does not include this change. No credentials, cookies, tokens or barcodes included. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
james.maes added 1 commit 2026-11-06 16:41:07 +00:00
fix(scanner): report osVersion and appVersion on every heartbeat
QRun-IO/ci-policy: ci / fork-guard (pull_request) Skipped
QRun-IO/ci-policy: native / fork-deny (pull_request) Skipped
QRun-IO/ci-policy: native / dotnet-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / Scoped workflow [workflow 539bec410f7926fec3ef7fabe51934a91e0248be] (pull_request) Successful in 13s
QRun-IO/ci-policy: ci / head-profile (pull_request) Skipped
QRun-IO/ci-policy: native / native-result (pull_request) Successful in 12s
QRun-IO/ci-policy: ci / repository-policy (pull_request) Skipped
QRun-IO/ci-policy: ci / application-template-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / gradle-1 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (pull_request) Skipped
QRun-IO/ci-policy: ci / node-8 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-9 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-10 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (pull_request) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-13 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-14 (pull_request) Skipped
QRun-IO/ci-policy: ci / original-business (pull_request) Skipped
QRun-IO/ci-policy: ci / original-mcp (pull_request) Skipped
QRun-IO/ci-policy: ci / original-voyage (pull_request) Skipped
QRun-IO/ci-policy: ci / original-cli (pull_request) Skipped
QRun-IO/ci-policy: ci / not-enrolled (pull_request) Skipped
QRun-IO/ci-policy: ci / shared-pipeline (pull_request) Skipped
QRun-IO/ci-policy: Shared Android CI / unit-test (pull_request) Successful in 4m35s
QRun-IO/ci-policy: Shared Android CI / android-test (pull_request) Successful in 10m21s
QRun-IO/ci-policy: Shared Android CI / secrets (pull_request) Successful in 22s
QRun-IO/ci-policy: Shared Android CI / package (pull_request) Successful in 20s
QRun-IO/ci-policy: Shared Android CI / gate (pull_request) Successful in 18s
QRun-IO/ci-policy: ci / android-0 (pull_request) Successful in 1h27m9s
QRun-IO/ci-policy: ci / ci-result (pull_request) Successful in 9s
f733a9906c
After the MC9400 in-place 1.0.0 to 1.0.1 update, scan receipts still showed
appVersion 1.0.0: the host sent osVersion/appVersion only at enrollment and
the server never refreshed them. MobileSessionApi now carries both values
(Build.VERSION.RELEASE and BuildConfig.VERSION_NAME, blank values omitted,
200-character cap) on each heartbeat so a mobile-scanners 1.6 server
refreshes the device record; older servers ignore the optional keys.

MobileSessionTest verifies the heartbeat payload carries only the two
version keys and no other device metadata. UI-API.md and SESSION-STATE.md
record the change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
james.maes merged commit eeb9f63322 into main 2026-11-06 23:23:24 +00:00
Sign in to join this conversation.