diff --git a/Android/docs/argus-rollout-policy.md b/Android/docs/argus-rollout-policy.md index 9dd8eed9..33f76c9b 100644 --- a/Android/docs/argus-rollout-policy.md +++ b/Android/docs/argus-rollout-policy.md @@ -9,9 +9,9 @@ ## Policy -- Stable Argus releases for `qsfera-mobile` must keep the same package name and production signing certificate after the production-signed `1.3.11` / `39` release. +- Stable Argus releases for `qsfera-mobile` must keep the same package name and production signing certificate after the first production-signed `1.3.11` / `39` release. - The in-app updater must not bypass certificate mismatch. `AppUpdateManager` validates package name, monotonically newer `versionCode`, Argus `androidVersionCode`, 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 production-signed `1.3.11` / `39` APK 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.12` / `40` as of 2026-06-10) 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/Android/qsferaApp/build.gradle b/Android/qsferaApp/build.gradle index 863a0262..8fe59d31 100644 --- a/Android/qsferaApp/build.gradle +++ b/Android/qsferaApp/build.gradle @@ -135,8 +135,8 @@ android { testInstrumentationRunner "eu.qsfera.android.utils.OCTestAndroidJUnitRunner" - versionCode = 39 - versionName = "1.3.11" + versionCode = 40 + versionName = "1.3.12" buildConfigField "String", gitRemote, "\"" + getGitOriginRemote() + "\"" buildConfigField "String", commitSHA1, "\"" + getLatestGitHash() + "\"" diff --git a/PRODUCTION_READINESS.md b/PRODUCTION_READINESS.md index a9a510a8..47dc9008 100644 --- a/PRODUCTION_READINESS.md +++ b/PRODUCTION_READINESS.md @@ -22,11 +22,12 @@ Date: 2026-06-08. ## Completed In This Pass - 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.11` with `versionCode` `39`. +- Android version was raised to `1.3.12` with `versionCode` `40`. - Android now has QSfera-specific Argus publishing scripts: local upload-keystore generation, signed APK staging, APK metadata verification, debug-certificate rejection, and Argus upload. - Android `1.3.9`/`37` was published to Argus as `qsfera-mobile` on 2026-06-10. Argus upload returned release id `53ecc24e-106b-43a5-a39e-ffacd72a43f8`, package size `12226572`, and SHA-256 `cbd2c25328e395ea4da4e0f582feac39dec18d2d47b3e105d344904d8a24f017`. - Android `1.3.10`/`38` was published to Argus as `qsfera-mobile` on 2026-06-10. Argus upload returned release id `8465ba6d-a008-45f5-9c70-e6cd2c94317a`, package size `12228464`, and SHA-256 `ce33a73ce122de6c9c797e7cb552e5493b628c60ddc98fda6a9e230e3c1ed7fe`. - 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 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. - Android immediate auto-upload scheduling no longer blocks the caller while waiting for WorkManager state. @@ -48,7 +49,7 @@ Date: 2026-06-08. - Windows tray "Show" now brings the settings window to the foreground after restoring it to an available screen. The same `Application::showSettings()` path is used by tray menu actions and `qsfera.exe --show`, and Win32 window enumeration on 2026-06-10 reported `Visible=True`, `Foreground=True`, title `КуСфера`. - Windows Desktop now has repeatable local packaging and feed-publication scripts. `scripts/package-windows-desktop.ps1` produced a smoke-tested `4.0.0` x64 package with Qt/MSVC runtime files; `scripts/publish-windows-desktop.ps1` generated a valid local `stable.xml` feed for that MSI and refuses remote publication unless the MSI is Authenticode-signed. - Added `scripts/verify-production-state.ps1` as a repeatable live production endpoint gate for the public server status, Android Argus manifest/download, and Desktop update feed. -- `scripts/verify-production-state.ps1 -VerifyAndroidDownload` passed on 2026-06-10: server `edition=stable`/`productversion=7.0.0`, Android `1.3.11`/`39`, downloaded APK size `12234884`, APK SHA-256 `c9eae41bbaae421e1a69721e891d8431ce599684e0f655b71693a422aa83720a`, and valid Desktop no-update feed. +- `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. - 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`. @@ -69,16 +70,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 `3dbac5ad-b19c-46e6-b24f-8f22e1c466dd`, version `1.3.11`, channel `stable`, platform `android`, package kind `apk`, `androidVersionCode` `39`, package size `12234884`, and SHA-256 `c9eae41bbaae421e1a69721e891d8431ce599684e0f655b71693a422aa83720a`. -- Independent download verification of `https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable` produced a `12234884` byte APK with the same SHA-256 `c9eae41bbaae421e1a69721e891d8431ce599684e0f655b71693a422aa83720a`. +- Current public Argus manifest for `https://argus.kusoft.xyz/api/apps/qsfera-mobile/manifest?platform=android&channel=stable` reports release id `615b58c5-b5f7-4a2a-b6de-03f821eb43a4`, version `1.3.12`, channel `stable`, platform `android`, package kind `apk`, `androidVersionCode` `40`, package size `12237552`, and SHA-256 `279d00c6a43072caa0b26269f547fb0dc3268088aae5cd9f4ccfbbb485c35ded`. +- Independent download verification of `https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable` produced a `12237552` byte APK with the same SHA-256 `279d00c6a43072caa0b26269f547fb0dc3268088aae5cd9f4ccfbbb485c35ded`. - 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 new `1.3.11`/`39` APK is signed by `CN=QSfera Argus Upload, O=QSfera, C=RU` with certificate SHA-256 `ea5c304c78ee333f6586f54c933d986c1f865da9c4e3595f8fe0df274c1ab877`. -- `AppUpdateManager` validates downloaded APK package name, greater `versionCode`, Argus `androidVersionCode`, and signer digest against the installed app signature. 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 production-signed `1.3.11`. +- The new `1.3.12`/`40` APK is signed by `CN=QSfera Argus Upload, O=QSfera, C=RU` with certificate SHA-256 `ea5c304c78ee333f6586f54c933d986c1f865da9c4e3595f8fe0df274c1ab877`. +- `AppUpdateManager` validates downloaded APK package name, greater `versionCode`, Argus `androidVersionCode`, and signer digest against the installed app signature. 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.11` 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.12` 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` 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 8bf46d26..c19ef984 100644 --- a/scripts/verify-production-state.ps1 +++ b/scripts/verify-production-state.ps1 @@ -6,12 +6,12 @@ param( [string]$AndroidManifestUrl = "https://argus.kusoft.xyz/api/apps/qsfera-mobile/manifest?platform=android&channel=stable", [string]$ExpectedAndroidSlug = "qsfera-mobile", [string]$ExpectedAndroidPackageName = "eu.qsfera.android", - [string]$ExpectedAndroidVersion = "1.3.11", - [int]$ExpectedAndroidVersionCode = 39, + [string]$ExpectedAndroidVersion = "1.3.12", + [int]$ExpectedAndroidVersionCode = 40, [string]$ExpectedAndroidChannel = "stable", [string]$ExpectedAndroidPlatform = "android", [string]$ExpectedAndroidPackageKind = "apk", - [string]$ExpectedAndroidSha256 = "c9eae41bbaae421e1a69721e891d8431ce599684e0f655b71693a422aa83720a", + [string]$ExpectedAndroidSha256 = "279d00c6a43072caa0b26269f547fb0dc3268088aae5cd9f4ccfbbb485c35ded", [string]$AndroidDownloadUrl = "https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable", [switch]$VerifyAndroidDownload,