Skip to content

[Feature]: Finalize one-shot provisioning bundle and publish the next GitHub Release #6

Description

@awatchar

Problem to solve

Minimum should provide an operator-friendly one-shot provisioning package, similar to the provisioning workflow previously completed and verified for the T56.

The package should allow an operator to prepare a supported radio from a Windows workstation without requiring a complete source checkout, Android Studio, Gradle, or manual execution of multiple PowerShell scripts.

The completed application and provisioning tools should also be published together as versioned assets on the GitHub Releases page.

Existing implementation

The repository already contains the main components of this workflow:

  • Provision Minimum Device.cmd
  • scripts/provision-minimum-device.ps1
  • scripts/prepare-t56.ps1
  • scripts/prepare-t99.ps1
  • scripts/prepare-ryks.ps1
  • docs/PROVISIONING_BUNDLE_README.txt
  • .github/workflows/release-apk.yml

An earlier prerelease, 3.7.3-minimum.1, already published a signed APK and provisioning ZIP.

This Issue is therefore intended to:

  1. Review and finalize the one-shot provisioning workflow.
  2. Include all completed and approved changes since the previous release.
  3. Verify the provisioning bundle on the supported hardware.
  4. Publish a new GitHub Release containing both the APK and the standalone provisioning package.

Desired outcome

An operator should be able to:

  1. Download one provisioning ZIP from GitHub Releases.
  2. Extract the ZIP on Windows.
  3. Connect one authorized radio through ADB.
  4. Double-click Provision Minimum Device.cmd.
  5. Allow the script to identify and verify the supported hardware model.
  6. Install the included Minimum APK without clearing existing app data.
  7. Apply the appropriate guarded model-specific provisioning procedure.
  8. Register or verify the displayed Minimum Device ID.
  9. Wait for Minimum to reach the Ready state.
  10. Reboot the radio.
  11. Confirm that Minimum automatically returns to Ready.
  12. Receive a clear PASS or actionable failure message.

The operator should not need a source checkout, Gradle, Android Studio, or manual knowledge of the individual provisioning scripts.

Supported device profiles

The one-shot launcher should support only explicitly approved hardware profiles:

  • T56: UNIPRO / ZX
  • T99: Youdotech / QM011
  • RYKS: ELINK / ym_258

Unknown or ambiguous hardware must be reported and rejected before APK installation or any provisioning change is performed.

Model-specific behavior must remain isolated. Hardware mappings, PTT rules, Location policy, and other settings must not be copied between device models without physical acceptance evidence.

Provisioning requirements

The one-shot provisioning workflow should:

  • Detect an authorized ADB device safely.
  • Support the standard ADB port 5037 and the existing Minimum lab port 5041.
  • Require explicit selection when more than one valid target is connected.
  • Verify the manufacturer and model before making changes.
  • Reject unknown, unsupported, unauthorized, or ambiguous targets.
  • Install the APK without clearing Minimum app data.
  • Preserve the existing Minimum Device ID and configuration when upgrading.
  • Stop with a clear explanation when an installed debug-signed APK cannot be upgraded by the release-signed APK.
  • Run the correct guarded model-specific preparation script.
  • Configure or verify required Android permissions.
  • Configure or verify managed Location according to the device profile.
  • Configure or verify the approved Wi-Fi profile when requested.
  • Remove Zello for Android user 0 only through the approved and recoverable procedure.
  • Launch Minimum and obtain the six-character Device ID.
  • Open the Minimum Portal for device registration when required.
  • Wait until managed configuration is active and the radio reaches Ready.
  • Reboot the device and verify unattended startup.
  • Confirm that the same Device ID remains active after reboot.
  • Finish with an explicit PASS only after post-reboot Ready verification succeeds.
  • Provide actionable error messages when any step fails.
  • Avoid displaying or logging passwords, access tokens, bearer tokens, signing credentials, or private configuration data.

Standalone provisioning bundle

The GitHub Release should include a ZIP archive named using the release tag, for example:

minimum-provisioning-<version>.zip

The extracted bundle should contain at least:

minimum-provisioning-<version>/
├── Provision Minimum Device.cmd
├── minimum-foss.apk
├── README.txt
├── VERSION.txt
├── scripts/
│   ├── provision-minimum-device.ps1
│   ├── prepare-t56.ps1
│   ├── prepare-t99.ps1
│   └── prepare-ryks.ps1
└── assets/
    └── t99-wifi-provisioner.apk

The bundle must be self-contained for normal provisioning use and must not depend on files outside the extracted directory, except for documented workstation requirements such as Android Platform Tools.

GitHub Release requirements

Publish a new versioned GitHub Release from an exact reviewed tag.

The Release should contain:

  • minimum-<version>-foss.apk
  • minimum-<version>-foss.apk.sha256
  • minimum-provisioning-<version>.zip
  • minimum-provisioning-<version>.zip.sha256

The Release workflow should:

  • Build from the exact Git tag.
  • Build and run the required automated tests.
  • Assemble the FOSS release APK.
  • Sign the APK using the protected GitHub release environment.
  • Verify the APK signature.
  • Verify the expected application ID.
  • Verify versionCode.
  • Verify that versionName matches the Git tag.
  • Build the temporary Wi-Fi provisioning helper.
  • Package the standalone Windows provisioning bundle.
  • Verify that all required bundle files are present.
  • Generate SHA-256 checksums.
  • Reject bundles containing secrets, signing files, credential stores, or private configuration.
  • Publish all approved artifacts to the same GitHub Release.
  • Generate release notes describing completed changes and known limitations.

Documentation requirements

Update the provisioning documentation so that an operator can complete the workflow without reading the source code.

The documentation should clearly explain:

  • Windows and ADB requirements.
  • How to extract and start the provisioning bundle.
  • How the device is selected and verified.
  • Which device models are supported.
  • How Device ID registration works.
  • Any operator interaction required by Android.
  • The meaning of PASS and common failure messages.
  • How to verify the SHA-256 checksums.
  • The APK signature-mismatch limitation when upgrading from a debug build.
  • How to recover safely after an interrupted or failed provisioning attempt.
  • Which actions are intentionally not automated for safety reasons.

Verification

Before publishing the Release:

  • Run the relevant Android unit tests.
  • Build the signed FOSS release APK successfully.
  • Verify the APK package, version, and signature.
  • Test extraction and execution of the standalone ZIP on a clean Windows workstation.
  • Confirm that the provisioning workflow does not require a source checkout or Gradle.
  • Confirm that no credentials or signing material are included.
  • Perform at least one real-device provisioning test for each device profile claimed as supported.
  • Verify Ready before and after reboot.
  • Record any unverified hardware behavior as a known limitation rather than treating it as passed.

Acceptance criteria

  • Provision Minimum Device.cmd starts the guided one-shot workflow by double-clicking.
  • The workflow requires no command-line parameters for the recommended setup.
  • The operator does not need the source repository, Gradle, or Android Studio.
  • The correct supported device profile is detected and verified.
  • Unknown or ambiguous hardware is rejected before changes are made.
  • The bundled APK is installed without automatically clearing existing app data.
  • Existing Device ID and configuration are preserved during a compatible upgrade.
  • The script stops safely and explains any APK signature mismatch.
  • Model-specific provisioning remains guarded and isolated.
  • Minimum reaches Ready before reboot.
  • Minimum reaches Ready again after reboot.
  • The Device ID remains unchanged after reboot.
  • The script reports PASS only after all required checks succeed.
  • A new reviewed Git tag is created for the release.
  • The GitHub Release contains the signed APK.
  • The GitHub Release contains the standalone provisioning ZIP.
  • SHA-256 files are published for both the APK and ZIP.
  • APK identity, version, and signature are verified automatically.
  • The provisioning ZIP contains all required scripts and assets.
  • The provisioning ZIP contains no credentials, tokens, private configuration, keystores, or signing material.
  • Release notes describe the completed changes, supported models, and known limitations.
  • Real-device verification results are recorded before the release is promoted as stable.

Safety and security considerations

  • Do not include server passwords, access tokens, bearer tokens, Wi-Fi passwords, APRS passcodes, private keys, certificate fingerprints, or signing material in the repository or Release.
  • Do not print sensitive values in the console or pass them through visible ADB command arguments.
  • Do not clear Minimum app data automatically.
  • Do not rewrite Android or USB serial numbers.
  • Do not modify Android keylayout files as part of general provisioning.
  • Do not apply T56, T99, or RYKS hardware mappings to another model without physical verification.
  • Do not publish the Release as stable until the claimed hardware acceptance tests have passed.

Activity

  1. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    Implemented the offline/code-complete portion in e3657bf7.

    Provisioning workflow changes

    • The only final PASS is now emitted after Ready before reboot, reboot/return, the same Device ID, and Ready after reboot.
    • -SkipReboot now ends as explicit INCOMPLETE with a non-zero exit instead of a false PASS.
    • Added Windows PowerShell 5.1-safe handling for INSTALL_FAILED_UPDATE_INCOMPATIBLE, with actionable signature-mismatch guidance and no automatic uninstall/data clear.
    • Updated the operator flow to use tokenless six-character Device ID registration.
    • Expanded documentation for supported hardware identities, T56 Location consent, checksum verification, recovery, and intentional manual safety boundaries.

    Release workflow safeguards

    • Added an exact allowlist for bundle files/directories.
    • Rejects symlinks/non-regular entries, unsafe paths, duplicate or extra raw ZIP members, credential/signing paths, and high-confidence credential-like text in both staged and freshly extracted content.
    • Ensures a fresh output ZIP and checksum.
    • Release notes now include the supported-model matrix, physical-test status, known limitations, and an ancestor-safe generated change range.
    • Sol High review approved these scoped changes.

    Verification completed

    • PowerShell AST parsing passed.
    • Workflow YAML and all Bash run: blocks parsed successfully.
    • Android local and GitHub CI gates passed.
    • No tag or release was created.

    Still required before closing

    This issue remains open. We still need an actual protected signing/release workflow execution plus extracted-bundle smoke testing and physical provisioning on T56, T99, and RYKS, including same-ID Ready before/after reboot and model-specific PTT/audio/room-switching/Location acceptance. The next release must not be promoted as stable before those gates pass.

  2. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    T56 recovery acceptance — PASS (not a pristine one-shot)

    A factory T56 provisioning attempt exposed two source-owned blockers. The reviewed fixes are published in draft PR #13 / commit 5545afc:

    • Android 5.1 has no usable
      un-as for the temporary Wi-Fi helper and does not reliably return nested ordered-broadcast JSON. The helper now uses a DUMP-protected exported receiver, non-exported Activity, nonce/path-bound request, fsynced private import/status, sanitized ASCII status markers, host deletion only after private import proof, and verified request/helper cleanup.
    • The radio config trial previously rolled back after the first generic connection error while Wi-Fi was connected. The bounded policy now retains/retries the first two transient connection errors, rejects the third, and still rejects server/other permanent errors immediately.

    Automated/security verification

    • Windows PowerShell 5.1 parser/security fixtures: passed.
    • Wi-Fi helper Gradle build and merged manifest review: passed.
    • Complete FOSS debug unit suite: passed.
    • FOSS debug APK assembly: passed.
    • No Wi-Fi credential, token, private config, or raw helper result was logged or committed.

    Hardware evidence

    • Hardware: UNIPRO / ZX, Android 5.1/API 22
    • ADB serial: cc7e49d on port 5037; other models were never targeted
    • Device ID created by Minimum: E7ROW7`n- Portal registration was performed by the operator; automation did not open or modify the Portal
    • Managed config: active Device ID E7ROW7, config v14, pending=false, lastSuccessMs>0`n- Visible Ready marker verified before reboot
    • Reboot target reidentified as the same cc7e49d UNIPRO/ZX with sys.boot_completed=1`n- Same Device ID/config and visible Ready verified after reboot
    • Zello absent for user 0; Location remained device-only GPS; approved Wi-Fi reconnects; temporary helper and /data/local/tmp/minimum-wifi-*.json were absent
    • Installed recovery APK SHA-256: 4A316203FEA998797D3225B2B2E4DF11D5CEE0BB6545C5336EE843C0A85C5712n- Signing certificate SHA-256: 168F42ED412DA80ADAF27BED0984DBEE191168E9DF04F08AFA240A3F9DE45972n- Package/version: se.lublin.mumla, vc 3070300, 3.7.3-minimum.1-11-ge3657bf7-debug`n

    Acceptance limitation

    This is a successful recovery and same-ID pre/post-reboot acceptance on the originally factory T56, but it is not evidence of a pristine uninterrupted factory one-shot: earlier attempts had already installed Minimum and partially changed Wi-Fi/Location state before the final corrected run. Issue #6 therefore remains open. A clean extracted standalone bundle/release run plus the remaining profile/release gates in the issue are still required before stable promotion or closure.

  3. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    Integration completed

    The reviewed T56 recovery fixes from draft PR #13 have passed all required pull-request checks and are now merged to main.

    • PR: Harden T56 one-shot provisioning #13
    • Reviewed branch commit: 5545afcn- Merge commit now at GitHub main: �e08e6d5e9eee2a63ee497a1b78ce7623fc1dbf4n- Android tests, FOSS debug APK assembly, unsigned release assembly, and release lint: PASS
    • Portal tests, type-check, and production build: PASS
    • Vercel status: PASS (portal source was unchanged; ignored-build behavior was expected)

    The hardware result remains the same: recovered T56 cc7e49d / Device ID E7ROW7 reached visible Ready on active config v14 before reboot and returned to the same ID/config and visible Ready after reboot.

    Issue #6 intentionally remains open. This merged recovery proves the corrected code path on the partially prepared T56, not an uninterrupted pristine factory run from an extracted standalone release bundle. The issue's remaining release/tag/artifact, clean-bundle smoke test, and any still-unclaimed device-profile acceptance gates must be completed before closure or stable promotion.

  4. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    2026-08-14 release-readiness update

    The updater/cellular integration merged through #14 as main commit d4bbaf4be9432433994e7526d2efc0b040a767f6. PR CI and post-merge main CI run 31726824727 passed Android and portal jobs. The exact standalone bundle contract, checksums, package/version/signer verification, updater docs and T56 same-debug-signer physical acceptance are implemented.

    A signed 3.7.3-minimum.2 prerelease was not tagged or dispatched. Security review found that GitHub environment release currently has the required signing secrets and MINIMUM_RELEASE_APPLICATION_ID, but has no deployment protection rules or required reviewers. The repository currently has only one collaborator/admin, so an independent protected approval cannot be fabricated. This is a nonwaivable release-provenance gate.

    Remaining before prerelease:

    1. add an independent trusted reviewer/collaborator;
    2. configure the release environment with required-reviewer protection and reviewed tag/branch policy;
    3. independently review exact main commit/tag and dispatch inputs (3.7.3-minimum.2, versionCode 3070301, prerelease true);
    4. validate all four published assets, checksums, exact one-signer binding and extracted bundle on the workstation;
    5. run only an official-signer SIGNER_MISMATCH ReportOnly/dry-run against E7ROW7—never install the release APK over its debug build;
    6. retain T99/RYKS physical provisioning/updater limitations in prerelease notes.

    This issue remains open and no stable promotion is claimed.

  5. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    Prerelease tag audit (2026-08-14): the first annotated tag 3.7.3-minimum.2 (tag object d50d8ceb826c02ee76668b34989c0cfa7a75d3a9, peeled commit d4bbaf4) produced failed workflow run https://github.com/awatchar/minimum/actions/runs/31727479600. The run failed safely while packaging the standalone updater because PowerShell on Linux wrapped apksigner output; signing and identity verification had already passed. No GitHub Release or assets were created. PR #15 fixes and tests that cross-platform parser, was independently reviewed, and merged as 8ddf60a; PR and post-merge CI are green. Because the failed tag was never published as a Release and has no assets, I will now explicitly delete and recreate the same prerelease tag on exact main 8ddf60a, then rerun the protected signing workflow. This comment is the audit trail for that one-time ref replacement; it is not a stable-release promotion or a claim of an environment-required reviewer (the release environment currently has no enforced reviewer).

  6. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    Second prerelease packaging audit (2026-08-14): workflow run https://github.com/awatchar/minimum/actions/runs/31728926851 on tag 3.7.3-minimum.2 at commit 8ddf60a again failed safely before publication. Signed build, APK signature/identity, updater tests, and helper build passed; extracted bundle verification exposed that PowerShell had already lost/wrapped apksigner stdout before the parser. No GitHub Release or assets exist. PR #16 replaces native stream adaptation with bounded raw Process capture, exact release-APK identity/signer integration coverage, concurrent stdout/stderr drains, timeout/tree cleanup, and injection-resistant platform-specific launch; it was independently reviewed and merged as cc9587a with green PR CI. I will wait for post-merge main CI, then explicitly replace the still-unpublished/no-assets annotated tag once more on exact cc9587a and rerun. The release environment reviewer-protection gap remains unchanged and disclosed.

  7. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    Third prerelease workflow audit (2026-08-14): run https://github.com/awatchar/minimum/actions/runs/31730892695 on tag 3.7.3-minimum.2 at cc9587a failed safely in the newly strengthened updater test, before bundle construction or publication. The signed release build and independent Bash APK signature/identity verification passed; no GitHub Release or assets exist. The log identified two fixture/argv issues: the adversarial .bat test assumed Windows ComSpec on Ubuntu, and the extensionless Linux launcher still received a single reparsed Arguments string. The focused correction uses ProcessStartInfo.ArgumentList for exact Unix argv, validates unsafe .bat paths before checking ComSpec, and adds the real Linux debug APK/apksigner updater suite to ordinary PR/main CI so this path is proven before another signing run. The tag remains unchanged while that fix is reviewed and merged; any later no-assets tag replacement will again be explicit, not silent.

  8. awatchar commented on Aug 13, 2026

    @awatchar
    OwnerAuthor

    Prerelease rerun gate update (2026-08-14): PR #17's final reviewed signer contract is merged as 192ee37 and post-merge CI https://github.com/awatchar/minimum/actions/runs/31733710073 is green, including the ordinary-CI real Linux apksigner/debug-APK test. Verified PEM certificates are authoritative, the single anchored signer-count line must equal the unique PEM set, and any textual digest set must exactly match it. The existing unpublished tag object 481f95ec04436e3df37785c36f32214134812d3e still peels to cc9587a; no Release/assets exist. Per the prior failure audit, I will explicitly replace it on exact 192ee37 and rerun. This remains a prerelease with the already-disclosed missing enforced environment reviewer.

  9. awatchar commented on Aug 20, 2026

    @awatchar
    OwnerAuthor

    2026-08-20 PR #17 / signed prerelease audit

    PR #17 is merged as 192ee37a146ad245cf5482656c410115ec1f82ce; its PR CI and post-merge CI passed. The protected signing workflow also completed successfully:

    A fresh download/extraction on the current project workstation passed the release contract: GitHub asset digests and published checksum hashes matched; the ZIP had exactly 19 reviewed raw members with no duplicates, unsafe paths, reparse points or credential-like text; the manifest had the exact 15-file allowlist and all hashes matched; the standalone and bundled APKs were identical; package se.lublin.mumla, versionCode 3070301, versionName/tag 3.7.3-minimum.2, and exactly one manifest-bound release signer all verified.

    The audit found one packaging portability defect: the published ZIP checksum contains the correct hash but names the GitHub runner's absolute path. The published .2 tag/Release/assets were not mutated. PR #18 fixes future releases to emit and verify the exact asset basename; it merged as 655d89234051c795176341808db19d93b1388d54, and post-merge CI https://github.com/awatchar/minimum/actions/runs/32347826798 passed.

    No radio is currently attached on either configured ADB server, so the release-signer SIGNER_MISMATCH ReportOnly/no-mutation gate on E7ROW7 cannot truthfully be claimed in this audit. No APK installation, reset, uninstall, clear-data, Portal mutation or hardware state change was attempted. The release environment also still has no enforced protection rules/reviewer. Therefore .2 remains an immutable prerelease and this issue remains open; no stable promotion is claimed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions