diff --git a/Android/docs/argus-rollout-policy.md b/Android/docs/argus-rollout-policy.md index ef1e15c2..6f1633ee 100644 --- a/Android/docs/argus-rollout-policy.md +++ b/Android/docs/argus-rollout-policy.md @@ -14,7 +14,7 @@ - Argus publication is SSH-only and must follow `G:/Repos/Marketplace/ARGUS_PUBLICATION.md`: copy the APK to the Pi, write metadata to `/srv/argus-data/argus.db`, and store package bytes under `/srv/argus-data/Packages`. Do not add or use HTTP `/api/admin/*` publication routes from this repository. - The in-app updater must use the public read-only manifest endpoint, treat HTTP `404` as no update, compare `release.version` with the installed version, download `ARGUS_BASE_URL + release.downloadPath`, verify `release.packageSizeBytes` and `release.sha256`, and only then start Android package installation. - The in-app updater must not bypass certificate mismatch. `AppUpdateManager` validates package name, newer installed APK metadata, optional Argus `androidVersionCode` when present, manifest version, and signer digest before starting Android package installation. -- A client installed from the debug-signed `1.3.5` / `33` Argus APK cannot be moved to the current production-signed stable APK (`1.3.13` / `41` as of 2026-06-12) by the in-app updater because the signer digest check intentionally fails. +- A client installed from the debug-signed `1.3.5` / `33` Argus APK cannot be moved to the current production-signed stable APK (`1.3.14` / `42` as of 2026-06-13) by the in-app updater because the signer digest check intentionally fails. - For debug-signed `1.3.5` installs, the supported migration path is: back up unsynced local files, uninstall the debug-signed build, then install the current stable QSfera APK from Argus. - On certificate mismatch, the Android app must show an explicit reinstall-required dialog instead of a generic update error. diff --git a/PRODUCTION_READINESS.md b/PRODUCTION_READINESS.md index 089ba8cc..eb4a5e44 100644 --- a/PRODUCTION_READINESS.md +++ b/PRODUCTION_READINESS.md @@ -24,6 +24,7 @@ Date: 2026-06-08. - Android release builds now fail fast when release signing variables are missing, so unsigned release artifacts cannot be published by accident. - Android version was raised to `1.3.12` with `versionCode` `40`. - Android version was raised to `1.3.13` with `versionCode` `41` for the next Argus publication. +- Android version was raised to `1.3.14` with `versionCode` `42` for the updated SSH-only Argus publication flow. - Android now has QSfera-specific Argus publishing scripts: local upload-keystore generation, signed APK staging, APK metadata verification, debug-certificate rejection, and SSH-only Argus publication through the `/srv/argus-data/argus.db` and `/srv/argus-data/Packages` workflow required by `G:/Repos/Marketplace/ARGUS_PUBLICATION.md`; HTTP `/api/admin/*` publication is not used. - Android Argus update and publication were realigned with `G:/Repos/Marketplace/ARGUS_PUBLICATION.md` on 2026-06-13: `Android/scripts/publish-release.ps1` now generates and runs the SSH/SQLite/Data/Packages server-side publication block, and `AppUpdateManager` uses only the public read-only manifest contract for update discovery. - Android now has `Android/scripts/verify-release-signing-material.ps1` to verify local release signing properties, keystore readability, release certificate SHA-256, and optionally the latest published Argus APK certificate without printing signing secrets. @@ -33,6 +34,7 @@ Date: 2026-06-08. - Android `1.3.11`/`39` was published to Argus as `qsfera-mobile` on 2026-06-10. Argus upload returned release id `3dbac5ad-b19c-46e6-b24f-8f22e1c466dd`, package size `12234884`, and SHA-256 `c9eae41bbaae421e1a69721e891d8431ce599684e0f655b71693a422aa83720a`. - Android `1.3.12`/`40` was published to Argus as `qsfera-mobile` on 2026-06-10. Argus upload returned release id `615b58c5-b5f7-4a2a-b6de-03f821eb43a4`, package size `12237552`, and SHA-256 `279d00c6a43072caa0b26269f547fb0dc3268088aae5cd9f4ccfbbb485c35ded`. - Android `1.3.13`/`41` was published to Argus as `qsfera-mobile` on 2026-06-12. Argus upload returned release id `39072ada-7557-48f3-ab42-ad68703d00b0`, package size `12261408`, and SHA-256 `f065e6584e6a09999e72ba0eeeaae903e93fb8980a0426e4b39b5e2366bf6611`. +- Android `1.3.14`/`42` was published to Argus as `qsfera-mobile` on 2026-06-13 through the SSH/SQLite/Data/Packages workflow from `G:/Repos/Marketplace/ARGUS_PUBLICATION.md`. The server-side publication block returned release id `4394333f-a84a-4a3b-9bc7-6a48d054d4fe`, stored path `qsfera-mobile/20260613170521-1.3.14-4394333FA84A4A3B9BC76A48D054D4FE.apk`, package size `12262908`, and SHA-256 `8ddfbb9d3dbff3f7bc1030024a0f03a7928771b06cb373c8996c96fb22ad5a18`. - `Android/scripts/verify-release-signing-material.ps1 -VerifyPublishedApk` passed on 2026-06-12: local `Android/argus-signing.local.properties` and `Android/signing/argus-upload.jks` are complete/readable, alias `argus-upload` exists, and both the keystore certificate and the latest published Argus APK report certificate SHA-256 `ea5c304c78ee333f6586f54c933d986c1f865da9c4e3595f8fe0df274c1ab877`. - Android auto-upload source paths are normalized and new/first source folders start from timestamp `0`, so existing media is eligible for initial backup. - Android auto-upload validates persisted read permission and `DocumentFile.canRead()` before scanning SAF folders. @@ -66,6 +68,7 @@ Date: 2026-06-08. - `scripts/verify-production-state.ps1 -VerifyAndroidDownload` passed on 2026-06-10: server `edition=stable`/`productversion=7.0.0`, Android `1.3.12`/`40`, downloaded APK size `12237552`, APK SHA-256 `279d00c6a43072caa0b26269f547fb0dc3268088aae5cd9f4ccfbbb485c35ded`, and valid Desktop no-update feed. - `scripts/verify-production-state.ps1 -VerifyAndroidDownload` passed on 2026-06-12: server `edition=stable`/`productversion=7.0.0`, Android release id `39072ada-7557-48f3-ab42-ad68703d00b0`, Android `1.3.13`/`41`, APK filename `qsfera-mobile-41.apk`, content type `application/vnd.android.package-archive`, downloaded APK size `12261408`, APK SHA-256 `f065e6584e6a09999e72ba0eeeaae903e93fb8980a0426e4b39b5e2366bf6611`, and valid Desktop no-update feed. - `scripts/verify-production-state.ps1 -VerifyAndroidDownload` passed on 2026-06-13 against the current public Argus manifest contract: server `edition=stable`/`productversion=7.0.0`, Android release id `39072ada-7557-48f3-ab42-ad68703d00b0`, Android version `1.3.13`, APK filename `qsfera-mobile-41.apk`, content type `application/vnd.android.package-archive`, downloaded APK size `12261408`, APK SHA-256 `f065e6584e6a09999e72ba0eeeaae903e93fb8980a0426e4b39b5e2366bf6611`, and valid Desktop no-update feed. The live manifest currently omits `androidPackageName` and `androidVersionCode`; the verifier treats both as optional unless strict switches are set. +- `scripts/verify-production-state.ps1 -VerifyAndroidDownload` passed on 2026-06-13 after publishing Android `1.3.14`: server `edition=stable`/`productversion=7.0.0`, Android release id `4394333f-a84a-4a3b-9bc7-6a48d054d4fe`, Android version `1.3.14`, APK filename `qsfera-mobile-42.apk`, content type `application/vnd.android.package-archive`, downloaded APK size `12262908`, APK SHA-256 `8ddfbb9d3dbff3f7bc1030024a0f03a7928771b06cb373c8996c96fb22ad5a18`, and valid Desktop no-update feed. - Added `Server/scripts/verify-rpi-production.sh`, declared a loopback-only Pi metrics port in `Server/docker-compose.rpi5.yml`, and expanded the Raspberry Pi Docker runbook with local/public status checks, container/image checks, Prometheus metrics verification, backup/restore drill steps, and Docker data-root/retention planning. - Added systemd monitoring units for the Pi: `Server/systemd/qsfera-rpi-production-check.service`, `Server/systemd/qsfera-rpi-production-check.timer`, `Server/systemd/qsfera-rpi-production-check-alert@.service`, `Server/systemd/rpi-production-check.env.example`, plus installer `Server/scripts/install-rpi-production-monitoring.sh` and alert helper `Server/scripts/alert-rpi-production-check-failure.sh`. - Deployed the Pi metrics/checker update on 2026-06-09. Before upload, `/mnt/data/qsfera/cloud-server/src/docker-compose.rpi5.yml` was backed up to `/mnt/data/qsfera/backups/docker-compose.rpi5.yml-20260609-181614.bak`; `docker compose -f docker-compose.rpi5.yml up -d` recreated and started `qsfera-cloud-server`; `docker compose ps` reported loopback ports `127.0.0.1:9200->9200/tcp` and `127.0.0.1:9205->9205/tcp`. @@ -86,16 +89,16 @@ Date: 2026-06-08. ## Android Argus Publication Check -- Current public Argus manifest for `https://argus.kusoft.xyz/api/apps/qsfera-mobile/manifest?platform=android&channel=stable` reports release id `39072ada-7557-48f3-ab42-ad68703d00b0`, version `1.3.13`, channel `stable`, platform `android`, package kind `apk`, original file name `qsfera-mobile-41.apk`, content type `application/vnd.android.package-archive`, package size `12261408`, and SHA-256 `f065e6584e6a09999e72ba0eeeaae903e93fb8980a0426e4b39b5e2366bf6611`. It does not currently include legacy Android-specific root `androidPackageName` or release `androidVersionCode` fields. -- Independent download verification of `https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable` produced a `12261408` byte APK with the same SHA-256 `f065e6584e6a09999e72ba0eeeaae903e93fb8980a0426e4b39b5e2366bf6611`. +- Current public Argus manifest for `https://argus.kusoft.xyz/api/apps/qsfera-mobile/manifest?platform=android&channel=stable` reports release id `4394333f-a84a-4a3b-9bc7-6a48d054d4fe`, version `1.3.14`, channel `stable`, platform `android`, package kind `apk`, original file name `qsfera-mobile-42.apk`, content type `application/vnd.android.package-archive`, package size `12262908`, and SHA-256 `8ddfbb9d3dbff3f7bc1030024a0f03a7928771b06cb373c8996c96fb22ad5a18`. It does not currently include legacy Android-specific root `androidPackageName` or release `androidVersionCode` fields. +- Independent download verification of `https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable` produced a `12262908` byte APK with the same SHA-256 `8ddfbb9d3dbff3f7bc1030024a0f03a7928771b06cb373c8996c96fb22ad5a18`. - The previously published `1.3.5`/`33` APK matched Argus SHA-256 `b7d5bdcb49527c00983a15849252fa42189dee4287754803c46cf2f32e2130f3`, but `apksigner` reported `CN=Android Debug` with certificate SHA-256 `b86d745cecb01ca24bda03092fe94ca7801678513b97edd1175bcabfdea4e941`. -- The current production-signed `1.3.13`/`41` APK is signed by `CN=QSfera Argus Upload, O=QSfera, C=RU` with certificate SHA-256 `ea5c304c78ee333f6586f54c933d986c1f865da9c4e3595f8fe0df274c1ab877`. +- The current production-signed `1.3.14`/`42` APK is signed by `CN=QSfera Argus Upload, O=QSfera, C=RU` with certificate SHA-256 `ea5c304c78ee333f6586f54c933d986c1f865da9c4e3595f8fe0df274c1ab877`. - `AppUpdateManager` follows the public read-only Argus manifest contract from `G:/Repos/Marketplace/ARGUS_PUBLICATION.md`: HTTP `404` is treated as no update, `release.version` is compared with the installed version, downloads use `ARGUS_BASE_URL + release.downloadPath`, `release.packageSizeBytes` and `release.sha256` are verified before install, and the downloaded APK package name/version/signature are checked against the installed app. Because of that local code path, devices that installed debug-signed `1.3.5` should be treated as needing reinstall or an explicit migration plan before they can move to the current production-signed stable APK. - The rollout policy for debug-signed `1.3.5` devices is documented in `Android/docs/argus-rollout-policy.md`: the app does not bypass signer mismatch; users must back up unsynced local files, uninstall the debug-signed build, then install the current stable APK from Argus. The Android app now shows a reinstall-required dialog for this certificate-mismatch path. ## Remaining P0 -- Back up the gitignored Android release signing files created under `Android/signing/` and `Android/argus-signing.local.properties` in a secure external secret store. Without this key material, future in-place Android updates from the production-signed `1.3.13` cannot be signed with the same certificate. +- Back up the gitignored Android release signing files created under `Android/signing/` and `Android/argus-signing.local.properties` in a secure external secret store. Without this key material, future in-place Android updates from the production-signed `1.3.14` cannot be signed with the same certificate. - Provide CI/Argus signing secrets derived from the same release key: `QSFERA_RELEASE_KEYSTORE`, `QSFERA_RELEASE_KEYSTORE_PASSWORD`, `QSFERA_RELEASE_KEY_ALIAS`, and `QSFERA_RELEASE_KEY_PASSWORD`. - Fill production domains, ACME email, admin passwords, Keycloak passwords, and storage secrets from a secret manager. Do not commit real values. - Run `./validate-production-env.sh .env` or `.\scripts\validate-server-production-env.ps1 -EnvPath ...` and then `docker compose config` for `Server/devtools/deployments/qsfera_full` with a filled production `.env`; Docker CLI is not available in this local environment, so compose rendering is not locally verified. diff --git a/scripts/verify-production-state.ps1 b/scripts/verify-production-state.ps1 index 90c78f54..1ed90078 100644 --- a/scripts/verify-production-state.ps1 +++ b/scripts/verify-production-state.ps1 @@ -7,17 +7,17 @@ param( [string]$ExpectedAndroidSlug = "qsfera-mobile", [string]$ExpectedAndroidPackageName = "eu.qsfera.android", [switch]$RequireAndroidPackageName, - [string]$ExpectedAndroidVersion = "1.3.13", - [int]$ExpectedAndroidVersionCode = 41, + [string]$ExpectedAndroidVersion = "1.3.14", + [int]$ExpectedAndroidVersionCode = 42, [switch]$RequireAndroidVersionCode, [string]$ExpectedAndroidChannel = "stable", [string]$ExpectedAndroidPlatform = "android", [string]$ExpectedAndroidPackageKind = "apk", - [string]$ExpectedAndroidReleaseId = "39072ada-7557-48f3-ab42-ad68703d00b0", - [string]$ExpectedAndroidOriginalFileName = "qsfera-mobile-41.apk", + [string]$ExpectedAndroidReleaseId = "4394333f-a84a-4a3b-9bc7-6a48d054d4fe", + [string]$ExpectedAndroidOriginalFileName = "qsfera-mobile-42.apk", [string]$ExpectedAndroidContentType = "application/vnd.android.package-archive", - [int64]$ExpectedAndroidPackageSizeBytes = 12261408, - [string]$ExpectedAndroidSha256 = "f065e6584e6a09999e72ba0eeeaae903e93fb8980a0426e4b39b5e2366bf6611", + [int64]$ExpectedAndroidPackageSizeBytes = 12262908, + [string]$ExpectedAndroidSha256 = "8ddfbb9d3dbff3f7bc1030024a0f03a7928771b06cb373c8996c96fb22ad5a18", [string]$AndroidDownloadUrl = "https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable", [switch]$VerifyAndroidDownload,