You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature]: Add a one-shot updater for already-provisioned Android radios #12
Android changes currently require connecting each supported radio and having a developer/Codex drive the update and verification interactively. Repeating the same ADB discovery, APK installation, model selection, provisioning, reboot, and validation steps consumes time and tokens and makes operator results less consistent.
Issue #6 covers first-time one-shot provisioning and release packaging. This issue is specifically for a reusable one-shot updater for already-provisioned devices.
An operator should be able to download a reviewed update bundle, connect each existing radio in turn, double-click one launcher, and receive a clear result without needing Codex, a source checkout, Gradle, Android Studio, or knowledge of model-specific commands.
Proposed artifacts
Add a distinct update entrypoint rather than overloading first-time provisioning:
Include both in the standalone GitHub Release bundle alongside the signed APK, checksum, existing guarded model helpers, and operator documentation.
The existing Provision Minimum Device.cmd remains the workflow for a new/reset device. The new updater is for devices that already have Minimum identity and managed configuration.
Supported update targets
Only explicitly supported and verified profiles:
T56 — UNIPRO / ZX
T99 — Youdotech / QM011
RYKS — ELINK / ym_258
Generic or unknown Android hardware may be inventory-reported but must not receive model-specific mutations. Unknown, unauthorized, offline, recovery-mode, or ambiguous targets must be rejected before installation.
Operator workflow
Recommended zero-argument flow:
Extract a signed Minimum update bundle.
Connect one already-provisioned radio and authorize ADB.
Double-click Update Minimum Device.cmd.
The script detects and verifies the exact hardware profile.
It inventories the current app/device state using sanitized output.
It verifies the bundled APK identity, version, checksum, and signer compatibility.
It installs the APK as an in-place upgrade without clearing app data.
It applies only required, versioned, model-gated migrations or setting checks.
It starts Minimum and waits for Ready.
It reboots only when the release/migration requires it, then verifies Ready again.
It confirms that Device ID and managed configuration were preserved.
It reports PASS, WARN, or FAIL and saves a sanitized local report.
It prompts the operator to disconnect the completed radio and connect the next one, or exit.
The script may process one physical device at a time for safe reboot correlation while allowing a single operator session to update several devices sequentially.
Core requirements
Safe device selection
Auto-detect the active ADB server on supported ports 5037/5041.
Require exactly one selected/authorized device for the recommended flow.
Support explicit -Serial or -TransportId for advanced use.
Verify manufacturer and model before any mutation.
Reject duplicate/ambiguous serial situations safely.
Re-identify the same physical/profile candidate after reboot without assuming the ADB transport ID is stable.
Never install or run model-specific logic on unknown hardware.
APK and release verification
Use the signed APK shipped in the reviewed GitHub Release bundle by default.
Verify SHA-256 before installation.
Verify application ID is exactly se.lublin.mumla.
Verify version name/code against bundle metadata.
Verify signer compatibility with the installed app before attempting an upgrade.
Refuse an unintended downgrade by default.
Require an explicit, prominently warned recovery option for any permitted downgrade.
Never download and execute an unverified “latest” artifact automatically.
If optional release download is added, pin the selected version and verify release metadata, checksum, package identity, and signer before use.
Preserve existing device state
Use an in-place APK update; never call uninstall or clear app data.
Capture the existing six-character Device ID before update and verify the same ID afterward.
2026-08-14 implementation and T56 updater acceptance
Merged via #14 at d4bbaf4be9432433994e7526d2efc0b040a767f6. PR CI and post-merge main CI (31726824727) passed Android and portal jobs. PowerShell 5.1 updater/state-machine coverage passed 31 tests.
T56 same-debug-signer physical evidence:
exact 16-member debug acceptance bundle; versionCode 3070301; actual build version 3.7.3-minimum.1-19-g1a5ed6aa-debug
ReportOnly returned expected legacy-baseline WARN, proof mode LEGACY_READY_UI, ID E7ROW7, config 16, Ready, no mutation
in-place update preserved the same Device ID/config/channel and produced expanded LKG/safe-settings evidence
cellular migration was idempotent (ALREADY_OK) with truthful route/APN readiness WARN
the first reboot exposed that this firmware can return on the alternate ADB server (5037 -> 5041); cross-port scanning was fixed while retaining exact same-ID correlation
exact rerun passed: APK_VERSION=ALREADY_OK, PRESERVED_EXTENDED, config 16 before/after and READY_SAME_ID after reboot
no uninstall, clear-data, reset or PTT transmission occurred
The issue remains open. T99 and RYKS physical updater acceptance is not yet recorded, and the official release-signer dry-run cannot be completed until a protected signed prerelease exists. Android's debug-to-release signing-key boundary remains nonwaivable: an official Release APK must be refused before installation on E7ROW7.
Sanitized reports intentionally contain the Minimum fleet Device ID but exclude USB serials, subscriber IDs, certificate fingerprints, raw UI XML and logs.
PR #17 is merged as 192ee37a146ad245cf5482656c410115ec1f82ce, and signed prerelease 3.7.3-minimum.2 was built successfully by https://github.com/awatchar/minimum/actions/runs/31734123092. Fresh current-workstation validation passed all bundle/APK hashes, exact raw/extracted allowlists, application ID, versionCode 3070301, versionName/tag, and exactly-one-reviewed-signer binding.
The published ZIP checksum has the correct hash but an absolute runner filename. The published prerelease was left immutable. PR #18 fixes future output to bind the portable asset basename and merged as 655d89234051c795176341808db19d93b1388d54; post-merge CI https://github.com/awatchar/minimum/actions/runs/32347826798 passed.
The known E7ROW7 installation remains on the debug signing channel and must never receive this release APK in place. At audit time no device was attached on either configured ADB server, so ReportOnly could not produce the required official-signer SIGNER_MISMATCH evidence or a same-session no-mutation comparison. No receiver/install/migration, reset, uninstall, clear-data or Portal action was attempted. This issue remains open until that non-destructive hardware gate can be recorded; no T99/RYKS result is claimed under the operator's T56-primary scope.
Problem to solve
Android changes currently require connecting each supported radio and having a developer/Codex drive the update and verification interactively. Repeating the same ADB discovery, APK installation, model selection, provisioning, reboot, and validation steps consumes time and tokens and makes operator results less consistent.
Issue #6 covers first-time one-shot provisioning and release packaging. This issue is specifically for a reusable one-shot updater for already-provisioned devices.
An operator should be able to download a reviewed update bundle, connect each existing radio in turn, double-click one launcher, and receive a clear result without needing Codex, a source checkout, Gradle, Android Studio, or knowledge of model-specific commands.
Proposed artifacts
Add a distinct update entrypoint rather than overloading first-time provisioning:
Include both in the standalone GitHub Release bundle alongside the signed APK, checksum, existing guarded model helpers, and operator documentation.
The existing
Provision Minimum Device.cmdremains the workflow for a new/reset device. The new updater is for devices that already have Minimum identity and managed configuration.Supported update targets
Only explicitly supported and verified profiles:
UNIPRO / ZXYoudotech / QM011ELINK / ym_258Generic or unknown Android hardware may be inventory-reported but must not receive model-specific mutations. Unknown, unauthorized, offline, recovery-mode, or ambiguous targets must be rejected before installation.
Operator workflow
Recommended zero-argument flow:
Update Minimum Device.cmd.Ready.Readyagain.PASS,WARN, orFAILand saves a sanitized local report.The script may process one physical device at a time for safe reboot correlation while allowing a single operator session to update several devices sequentially.
Core requirements
Safe device selection
-Serialor-TransportIdfor advanced use.APK and release verification
se.lublin.mumla.Preserve existing device state
Versioned migrations instead of full reprovisioning
APPLIED,ALREADY_OK,SKIPPED, orFAILED.Health and acceptance checks
Before mutation:
After installation:
Readystate within a bounded timeout.Readywhen reboot acceptance is run.WARNorFAIL.Do not treat APK installation success alone as update success.
Multi-device sequential session
Provide an optional loop mode, for example
-UpdateSession, that lets an operator update the fleet one radio at a time:Example summary:
Dry-run and recovery
-WhatIf/dry-run inventory that performs no mutation.Ready.Reporting and privacy
Save a timestamped sanitized JSON and human-readable text report locally. Include:
PASS,WARN, orFAILExclude:
Console output must also avoid printing secrets.
Maintainability and token reduction
Release integration
Acceptance criteria
Readyafter update; post-rebootReadyis verified when required.Safety constraints