# 009 — Sideload system package updates (FR-019) Owner cadence: refresh bundled **system / privileged** packages about every **2–3 months** without a full ROM reflash. **No** AXP OTA / external repos. Status: **documented** — commands and signing gates below define the intended refresh path. The owner has also verified full-ROM upgrades over existing userdata without a wipe. A real individual-APK refresh drill can wait for the final ROM candidate; packaging of the shipping image MUST preserve update eligibility. **Full ROM updates** (new LOS base + rebacon) are a different path: recovery sideload of the project zip. See [`009-upstream-rebase-ota.md`](009-upstream-rebase-ota.md). ## In scope | Component | Intended update path | Signing constraint | |-----------|----------------------|--------------------| | microG GmsCore / companions | `adb install -r` / recovery sideload of upstream APK | **PRESIGNED** / same signer as shipped | | Magisk | Magisk app self-update and/or documented boot re-patch | Manager + boot image must stay matched | | Project Phonesky | Sideload project-signed APK | **Same project key** across releases | | Other bundled system apps | Sideload matching-signer APK (or recovery zip if priv-app needs it) | Same identity as image | ## Out of scope - Network OTA / AXP update servers - Full `bacon` + clean flash for routine APK bumps (still OK for kernel / framework / Magisk boot changes when required) ## Checklist before claiming FR-019 done - [ ] Each row above has a concrete command/runbook step - [ ] `pm install` / PackageManager does not reject for signature mismatch - [ ] Privileged permissions still grant after update (or re-flash privapp XML noted) - [ ] Magisk version after update matches kernel/boot expectation - [ ] Record new versions in `docs/009-version-pins.md` ## Preparation and safety 1. Keep the last known-good full ROM zip and its SHA-256. APK refreshes do not replace a boot/kernel rollback path. 2. Download the new APK from the upstream/project source into a host-only staging directory. Never put it in Git or paste its bytes into evidence. 3. Verify the APK before connecting the phone: ```bash apksigner verify --verbose --print-certs NEW.apk sha256sum NEW.apk ``` 4. Compare the signer with the installed package. For a system app, first record `adb shell pm path PACKAGE` and the installed version. Do not use `-d` for routine refreshes and do not accept a signer mismatch. ## microG / GSF Proxy For a compatible same-signer update on a test device: ```bash adb install -r GmsCore.apk adb install -r GsfProxy.apk adb shell pm path com.google.android.gms adb shell dumpsys package com.google.android.gms | grep -E 'versionName=|versionCode=' adb shell dumpsys package com.google.android.gsf | grep -E 'versionName=|versionCode=' ``` Then run microG Self-Check, open Phonesky, and verify one ordinary app update. If a package is privileged or its signer/permissions change, stop and rebuild the image or provide a recovery package with the matching privapp XML; do not paper over the rejection with a weaker permission policy. ## Project Phonesky Phonesky must remain the project-signed artifact and must retain the same package identity and signer as the image: ```bash adb install -r Phonesky.apk adb shell pm path com.android.vending adb shell dumpsys package com.android.vending | grep -E 'versionName=|versionCode=' adb shell monkey -p com.android.vending 1 ``` Verify an ordinary install/update through Phonesky. A signature mismatch, privileged-permission loss, or broken microG path is a failed refresh; restore the previous APK or the known-good ROM rather than accepting the update. ## Other bundled system apps Aurora, Droidify, Fossify Gallery, Jelly and OpenEUICC may be refreshed only with an APK matching the shipped package identity and signing policy: ```bash adb install -r APP.apk adb shell pm path PACKAGE adb shell dumpsys package PACKAGE | grep -E 'versionName=|versionCode=' ``` For an app whose update must retain system/privileged permissions, verify its normal function and the relevant permissions after install. If PackageManager places the update under `/data/app/`, that is expected only when the signer and permission model remain valid; record the path change and any required XML handling in the version pin record. ## Magisk Magisk manager APK updates and boot-preroot updates are separate: - Manager-only update: use the manager's normal update path, then verify `magisk -v`, Zygisk/DenyList behavior, and the test package before banking experiments. - Boot/runtime update: patch and test a new boot image with the matching Magisk version. This is not an APK-only refresh and must use the full build and LAB-only flash procedure; never mix a new Magisk manager with an older preroot boot image casually. ## Post-update evidence Record the following under the relevant host artifact or release note: ```bash adb shell getprop ro.lineage.version adb shell pm path PACKAGE adb shell dumpsys package PACKAGE adb shell logcat -d -t 500 | grep -E 'PackageManager|avc: denied|FATAL EXCEPTION' ``` Reboot once after privileged/system-package changes and repeat the package path, permissions, microG Self-Check, Phonesky install, and WebView checks. Record versions and SHA-256 values in `docs/009-version-pins.md`.