AXP Magisk resurrection track: Speckit 009 port AXP/LOS22 to LOS23.

Ship Magisk like GOLDEN; KernelSU optional recycle only; parallel to sunfish-a16-rom standby.
This commit is contained in:
sunfish-admin committed 2026-09-16 21:56:22 +00:00
commit 12d2179c20
150 files changed
+26263

No files matched your search

@@ -0,0 +1,39 @@
# Specification Quality Checklist: Restricted native signature spoofing
**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-09-15
**Feature**: [spec.md](../spec.md)
## Content Quality
- [x] No implementation details (languages, frameworks, APIs)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed
## Requirement Completeness
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Success criteria are technology-agnostic (no implementation details)
- [x] All acceptance scenarios are defined
- [x] Edge cases are identified
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified
## Feature Readiness
- [x] All functional requirements have clear acceptance criteria
- [x] User scenarios cover primary flows
- [x] Feature meets measurable outcomes defined in Success Criteria
- [x] No implementation details leak into specification
## Notes
- Oracle path and package names appear as acceptance identifiers (required for
LAB/GOLDEN verification); patch file paths belong in `/speckit-plan`, not here.
- Checklist validated 2026-09-15 after initial draft — ready for `/speckit-plan`.
- Spec updated same day with **First working stack** (US6, FR-010/011, SC-007/008):
folds `004` packaging leftovers + BeaconDB location into this phase; keeps
`006`/`007` out. Re-validated for plan. Plan artifacts generated 2026-09-15.
@@ -0,0 +1,59 @@
# Contract: Spoofing surface (LAB / user-visible)
## Settings
| Interface | Contract |
|-----------|----------|
| Secure setting | `allow_signature_fake` ∈ {`null`/`0`, `1`} |
| Readback | `adb shell settings get secure allow_signature_fake` |
| UI | Developer Options exposes enable/disable; OFF disables effect of grants |
## Permission
| Interface | Contract |
|-----------|----------|
| Permission name | `android.permission.FAKE_PACKAGE_SIGNATURE` |
| `pm list permissions` | Permission is listed (not “Unknown permission”) |
| Grant | Visible in `dumpsys package <pkg>` for authorized packages when user granted |
## PackageManager behaviour
When **toggle ON** and package **has grant** and **has** `meta-data fake-signature`
(or microG’s equivalent spoof path):
- Callers using legacy signature APIs and signing-certificate APIs MUST observe
the faked Google identity for that package (sufficient for microG Self-Check
“correct signature” and Play OAuth registration checks).
When **toggle OFF**:
- Effective spoofing MUST NOT occur (silent deny).
## Allow-list
| Package | Required |
|---------|----------|
| `com.google.android.gms` | yes |
| `com.android.vending` | yes |
| Other packages | denied unless explicitly added later under project policy |
## First-stack package registration
| Package | `pm path` expectation |
|---------|----------------------|
| `com.google.android.gms` | system_ext app path |
| `com.google.android.gsf` | system_ext app path |
| `com.android.vending` | system priv-app Phonesky path |
PRESIGNED APKs in the shipped image MUST verify with APK Signature Scheme v2/v3
(no post-sign strip).
## Location (documentation contract)
Quickstart MUST specify:
1. Open microG → Location
2. Enable network/Wi-Fi location as required by UI
3. Set service URL to BeaconDB (or documented successor), not MLS
No requirement to install UnifiedNlp backend packages.
@@ -0,0 +1,70 @@
# Data model: 005 spoofing + first-stack entities
## GlobalSpoofingToggle
| Field | Description |
|-------|-------------|
| Setting key | `settings secure allow_signature_fake` (AXP/GOLDEN) |
| Values | `0` / unset = OFF; `1` = ON |
| Default | OFF |
| UI | Developer Options → Signature spoofing support → Allow signature spoofing |
| Effect when OFF | Prior per-app grants ignored (silent deny) |
## SpoofingPermission
| Field | Description |
|-------|-------------|
| Name | `android.permission.FAKE_PACKAGE_SIGNATURE` |
| Protection | dangerous (user-grantable), as on GOLDEN |
| Grant state | Per package / per user; GOLDEN uses `USER_SET` for gms + vending |
| Revoke UI | App permissions → Spoof package signature (AXP strings) |
## AuthorizedPackage
| Package | Signer identity | Notes |
|---------|-----------------|-------|
| `com.google.android.gms` | Official microG PRESIGNED | System_ext app; F-Droid updates |
| `com.android.vending` | Project Phonesky JKS | System priv-app; `fake-signature` meta-data |
Extension of this set requires constitution-aligned review (not open allow-all).
## FakeSignatureMetadata
| Field | Description |
|-------|-------------|
| APK meta-data name | `fake-signature` |
| Value | Hex-encoded Google platform certificate (injected by AXP `patch-playstore`) |
| Consumer | PackageManager spoofing path when permission granted + toggle ON |
## PackagingArtifacts (first-stack ship)
| Artifact | Rule |
|----------|------|
| GmsCore / Gsf / Phonesky APKs | PRESIGNED install without zip-realign strip (`REPLACE_PREBUILT`) |
| Phonesky privapp XML | Includes FAKE_PACKAGE + A16 FGS / exact-alarm / Play 52 extras; digest = **our** cert |
| Default-permissions / sysconfig | Align with GOLDEN `er_*` intent (power-save, app-link) as needed |
## LocationConfig (validation, not a package)
| Field | Description |
|-------|-------------|
| Provider | microG built-in network location (0.3.x) |
| Endpoint | Ichnaea-compatible URL (BeaconDB: `https://api.beacondb.net`) |
| Non-goals | UnifiedNlp backend APKs; Mozilla MLS |
## State transitions
```text
[Toggle OFF] --enable in Dev Options--> [Toggle ON]
| |
v v
spoof denied prompts/grants for
for all apps authorized packages
|
v
[Permission granted]
|
v
PackageInfo signatures + signingInfo
present Google identity to callers
```
@@ -0,0 +1,98 @@
# Implementation Plan: Restricted native signature spoofing
**Branch**: `005-restricted-signature-spoofing` | **Date**: 2026-09-15 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/005-restricted-signature-spoofing/spec.md`
## Summary
Deliver the **first working Google-compat stack on LAB**: finish `004` packaging
gates (PRESIGNED replace + Play FGS privapp), add **AXP/EXTENDROM-style
restricted signature spoofing** (Developer Options `allow_signature_fake` +
`FAKE_PACKAGE_SIGNATURE` + allow-list for microG + Phonesky), validate Play auth
/ Self-Check, and document **modern** microG location (BeaconDB). Do **not**
pull `006` banking or `007` root into this phase.
Primary technical approach: attribute patches from
[EXTENDROM_SIGNATURE_SPOOFING](https://github.com/sfX-android/android_vendor_extendrom/wiki/EXTENDROM_SIGNATURE_SPOOFING)
(A15 proven on GOLDEN) and port to **Android 16 / LOS 23.2**, ensuring both
legacy `PackageInfo.signatures` and modern `signingInfo` are spoofed.
## Technical Context
**Language/Version**: Android frameworks Java/Kotlin patches; Settings overlays;
`Android.mk` / product makefiles; bash runbooks on `rom-dev01`
**Primary Dependencies**: LOS 23.2 tree; EXTENDROM/AXP sigspoof patches (A15 →
A16 port); microG 0.3.x; project-signed Phonesky; GOLDEN 2026-09-15 capture
**Storage**: Host `/srv/rom/` prebuilts + secrets; meta-repo `vendor/sunfish-a16/`
**Testing**: LAB flash only; `settings`/`pm`/`dumpsys`; microG Self-Check;
Play login logcat; optional BeaconDB location smoke
**Target Platform**: Pixel 4a LAB `11231JEC207477`; Android 16 / LOS 23.2
**Project Type**: Android ROM frameworks + Settings + packaging overlay
**Performance Goals**: N/A (correctness / compatibility)
**Constraints**: LAB only; no GOLDEN modify; no Magisk/KSU; restricted allow-list;
attributable patches; no proprietary APKs in Git
**Scale/Scope**: frameworks/base (+ services) spoofing; Settings Developer
Options; privapp/default/sysconfig XML updates; one bacon + LAB flash; docs
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
| Gate | Status |
|------|--------|
| LAB only; never GOLDEN | pass |
| Spoofing native, restricted, auditable; no LSPosed | pass (FR-003/006) |
| Prefer package/signer allow-list over open fake-signature | pass |
| Works without optional root | pass (FR-006, US5) |
| Prefer AXP/EXTENDROM behaviour; A16 port if needed | pass |
| No proprietary APKs in Git | pass |
| Small attributable changes | pass (patch series from EXTENDROM/AXP) |
| Do not invent `006`/`007` into this feature | pass (spec Out of Scope) |
**Post-design**: unchanged — design stays spoofing + first-stack ship gates.
## Project Structure
### Documentation (this feature)
```text
specs/005-restricted-signature-spoofing/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── spoofing-surface.md
└── tasks.md # via /speckit-tasks (not this command)
```
### Host + tree
```text
# Meta repo
vendor/sunfish-a16/ # packaging (REPLACE, privapp XML, gms.mk)
docs/a15-a16-delta.md
docs/004-*.md # packaging/selfcheck (update for BeaconDB)
.local-artifacts/002-golden/20260915-spoofing-phonesky/ # oracle
# rom-dev01
/srv/rom/src/lineage/frameworks/base/ # spoofing patches
/srv/rom/src/lineage/packages/apps/Settings/ # Developer Options toggle
/srv/rom/references/… or vendor/extendrom/ # patch source (checkout as needed)
/srv/rom/artifacts/005-…/ # validation zip + evidence
```
**Structure Decision**: Continue `vendor/sunfish-a16` packaging overlay; apply
spoofing as attributable patch series under the LOS tree on `rom-dev01` (not a
megapatch in Git). Meta-repo holds vendor stubs, docs, and specs only.
## Complexity Tracking
| Violation | Why needed | Simpler alternative rejected because |
|-----------|------------|--------------------------------------|
| Frameworks patches | LOS 23.2 has no FAKE_PACKAGE | Magisk/LSPosed forbidden by constitution |
## Phase 0 / Phase 1
See `research.md`, `data-model.md`, `contracts/spoofing-surface.md`, `quickstart.md`.
@@ -0,0 +1,74 @@
# Quickstart: 005 first working stack (LAB only)
**Device**: LAB `11231JEC207477` — never GOLDEN `11071JEC203839`
## Goal
One flash proves: microG + patched Play + restricted spoofing + modern location
docs. Not banking (`006`), not root (`007`).
## Prerequisites
- Artifact zip from `005` bacon (includes `REPLACE_PREBUILT` + updated privapp)
- Laptop `adb`/`fastboot`; hashes verified
- Oracle notes (optional): `.local-artifacts/002-golden/20260915-spoofing-phonesky/README.md`
## Flash
Follow `docs/003-flash-lab.md` pattern with the **005** zip (dtbo → boot/recovery
→ format if needed → sideload). Say **No** to additional packages.
## After first boot
```bash
SERIAL=11231JEC207477
adb -s "$SERIAL" shell getprop ro.lineage.version
adb -s "$SERIAL" shell pm path com.google.android.gms
adb -s "$SERIAL" shell pm path com.google.android.gsf
adb -s "$SERIAL" shell pm path com.android.vending
# expect all three present — no remount push
```
## Spoofing
1. Enable **Developer options**
2. Enable **Allow signature spoofing** (`settings get secure allow_signature_fake` → `1`)
3. Open **microG Settings → Self-Check**
4. Grant spoofing for GmsCore and Play when prompted (or App info → permissions)
5. Confirm Self-Check **correct signature** for GmsCore and Play/Companion
```bash
adb -s "$SERIAL" shell settings get secure allow_signature_fake
adb -s "$SERIAL" shell dumpsys package com.google.android.gms | grep FAKE_PACKAGE_SIGNATURE
adb -s "$SERIAL" shell dumpsys package com.android.vending | grep FAKE_PACKAGE_SIGNATURE
```
## Play auth
1. Open Play Store; sign in
2. Confirm UI stays up (no FGS crash loop)
3. Optional logcat gate: **no** `UNREGISTERED_ON_API_CONSOLE` for Phonesky
In-app Play self-update may still fail (AXP-like) — acceptable.
## Modern location
1. microG Settings → Location
2. Enable network location as shown
3. Configure service URL: `https://api.beacondb.net` (BeaconDB; MLS is dead)
4. Do **not** install Déjà Vu / Nominatim NLP backend APKs
## Pass criteria (SC)
- [x] Toggle + `allow_signature_fake=1` *(LAB 2026-09-15)*
- [x] Self-Check correct signature for gms + vending
- [x] Play sign-in without API-console fingerprint error
- [x] All three packages from zip without remount *(gms/gsf system; vending upgraded in-place for exact-alarm — next bacon restores system path)*
- [x] BeaconDB steps recorded; no UnifiedNlp backends required
- [x] No Magisk/KSU on the build
## Failure
Capture logcat (`vending`, `GmsAuthenticator`, `SelfCheck`, `PackageManager`).
Do not flash GOLDEN. Packaging-only regressions → fix under vendor overlay;
spoofing regressions → frameworks/Settings patches.
@@ -0,0 +1,104 @@
# Research: 005 restricted signature spoofing
## Decision: First working stack = `004` leftovers + spoofing + modern location
**Decision**: Ship one LAB validation build that includes (1) unfinished `004`
packaging fixes, (2) restricted spoofing, (3) BeaconDB location docs — and
**exclude** `006` banking and `007` root.
**Rationale**: Owner: first phase that must work is microG + patched Play +
spoofing. Banking/root are later regressions.
**Alternatives considered**: Separate tiny `004b` rebuild only — rejected;
wastes a flash cycle before spoofing lands. Pulling `006` early — rejected;
blocks focus.
## Decision: Spoofing implementation source = EXTENDROM / AXP (port to A16)
**Decision**: Use [EXTENDROM_SIGNATURE_SPOOFING](https://github.com/sfX-android/android_vendor_extendrom/wiki/EXTENDROM_SIGNATURE_SPOOFING)
as the attributable primary source (matches GOLDEN behaviour:
`allow_signature_fake`, Developer Options, per-app `FAKE_PACKAGE_SIGNATURE`).
Port patches from the closest supported Android line (**A15** is STABLE/tested;
GOLDEN is A15) onto **A16 / LOS 23.2**.
**Rationale**: Stock LOS 23.2 tree on `rom-dev01` has **no**
`FAKE_PACKAGE_SIGNATURE` / `allow_signature_fake` (inventory 2026-09-15). AXP
GOLDEN proves the UX and setting key. Old `android_signature_spoofing` repo is
obsolete per upstream.
**Alternatives considered**:
| Option | Why not |
|--------|---------|
| lineageos4microg unrestricted spoof | Constitution forbids open spoofing |
| Magisk / LSPosed FakeGApps | Forbidden; rootless Compatibility MVP |
| Wait for LOS to grow A16 EXTENDROM dir | Blocks first stack; we port ourselves |
**A16 note**: EXTENDROM wiki table lists A15, not A16. Expect conflict resolution
(`repo diff` / split patches) per EXTENDROM porting guide. Record deltas in
`docs/a15-a16-delta.md`.
## Decision: Must spoof `signingInfo`, not only `signatures[]`
**Decision**: Implementation MUST spoof both legacy `PackageInfo.signatures` and
modern `PackageInfo.signingInfo` (GET_SIGNING_CERTIFICATES).
**Rationale**: microG #2680 / EXTENDROM #48 — Google/Play check `signingInfo` on
modern Android; Self-Check “correct signature” fails if only legacy arrays are
faked. LOS Gerrit has A13–A15 fixes; ensure A16 port includes equivalent.
## Decision: Allow-list = microG GmsCore + project Phonesky
**Decision**: Effective spoofing limited to:
- `com.google.android.gms` — official microG signer (`73aaa390…` short on GOLDEN)
- `com.android.vending` — project Phonesky JKS
SHA-256 digest
`31:31:86:CB:7D:F2:D4:01:33:72:12:07:B7:29:73:E8:52:F6:1C:87:67:C3:21:E5:C7:50:39:01:1B:83:BD:56`
Privapp/default XMLs that bind by cert digest MUST use **our** digest (not
AXP’s `00:5C:98:05:…`).
**Rationale**: Constitution + GOLDEN grants; AXP `er_*` XMLs bind Phonesky by
digest.
## Decision: Global toggle default OFF
**Decision**: `allow_signature_fake` defaults to disabled; user enables in
Developer Options (AXP setup guide).
**Rationale**: Matches oracle docs and reduces surprise attack surface.
## Decision: `004` packaging leftovers are a `005` ship gate
**Decision**: Before declaring `005` done, the flashable zip MUST include:
1. `LOCAL_REPLACE_PREBUILT_APK_INSTALLED` for GmsCore/Gsf/Phonesky (already in
working-tree `vendor/sunfish-a16/Android.mk`)
2. Phonesky privapp extras for Play 52 / A16 FGS:
`FOREGROUND_SERVICE_SYSTEM_EXEMPTED`, `SCHEDULE_EXACT_ALARM` /
`USE_EXACT_ALARM`, plus prior grammatical/status-bar entries
**Rationale**: Measured LAB failures — PRESIGNED strip → no `pm path`; missing
FGS allowlist → VpaService/DownloadService crash. Remount pushes are not the
shipped artifact.
## Decision: Modern location = BeaconDB (not UnifiedNlp backends)
**Decision**: Document configuring microG Location to use an Ichnaea-compatible
URL (`https://api.beacondb.net` or documented successor). Do **not** package
Déjà Vu / Nominatim NLP / MLS apps.
**Rationale**: microG 0.3.x dropped UnifiedNlp backends; MLS retired (2025);
GOLDEN also has no NLP backend packages. Owner wants modern stack.
**Alternatives considered**: Ship UnifiedNlp backends — rejected (obsolete for
0.3.x primary path).
## Decision: Out of scope remains `006`/`007`
**Decision**: No Insular/banking hard-gates; no KSU/SusFS in this feature’s
acceptance.
**Rationale**: Owner confirmation 2026-09-15 — first phase is microG + Play +
spoofing only.
@@ -0,0 +1,277 @@
# Feature Specification: Restricted native signature spoofing
**Feature Branch**: `005-restricted-signature-spoofing`
**Created**: 2026-09-15
**Status**: Draft
**Input**: Advance spoofing after `004` packaging: LAB Play/microG Self-Check and
Google auth fail without AXP-style restricted signature spoofing. GOLDEN capture
2026-09-15 is the behavioural oracle. Prefer modern LOS 23.2 / A16 path to the
**same end state** as AXP (not Magisk modules).
## First working stack (this phase — before `006`/`007`)
This feature closes the **first usable Google-compat stack on LAB**:
| Must work in this phase | Owner |
|-------------------------|--------|
| Official microG + GSF (PRESIGNED, F-Droid-updatable) | `004` packaging + `005` ship |
| Patched Phonesky priv-app (project-signed, disable/enable OK) | `004` + `005` ship |
| Restricted spoofing (Developer Options + grants) | **`005` core** |
| Self-Check correct signature + Play auth (no API-console mismatch) | **`005`** |
| Modern network location (BeaconDB / Ichnaea-compatible URL; not Déjà Vu NLP) | `005` validation / docs |
| `004` packaging leftovers that block a clean flashable zip | **`005` ship gate** (`REPLACE_PREBUILT`, Play FGS privapp) |
**Explicitly later (do not pull forward):**
- `006` — Insular / Yuh / Swissquote banking hard-gates
- `007` — KernelSU-Next / SusFS / root hide
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Developer Options master switch (Priority: P1)
As the developer (and later daily-driver user), I can enable **Allow signature
spoofing** under Developer Options. When off, spoofing has no effect even if
per-app grants remain. When on, authorized apps may use spoofing after grant.
**Why this priority**: Matches GOLDEN/AXP (`settings secure allow_signature_fake`)
and constitution (not unrestricted platform fake-signature).
**Independent Test**: On LAB build with `005`, toggle the setting; read
`settings get secure allow_signature_fake` (0/1); confirm UI strings exist.
**Acceptance Scenarios**:
1. **Given** a `005` build on LAB, **When** Developer Options is opened,
**Then** a **Signature spoofing support** category exposes **Allow signature
spoofing** (AXP-equivalent UX).
2. **Given** the toggle is OFF, **When** an app holds a prior spoofing grant,
**Then** spoofing has **no effect** (same as AXP documented behaviour).
3. **Given** the toggle is ON, **When** `settings get secure allow_signature_fake`
is read, **Then** the value is `1`.
---
### User Story 2 - microG + Phonesky Self-Check signatures (Priority: P1)
As the developer, with global spoofing ON and spoofing permission granted to
microG GmsCore and patched Phonesky, microG Self-Check marks **correct
signature** for both `com.google.android.gms` and `com.android.vending`
(Companion/Play Store line), not only “installed”.
**Why this priority**: Unblocks the `004` gap that packaging alone cannot fix;
required before Play OAuth works.
**Independent Test**: LAB only; no GOLDEN modification; screenshots/log of
Self-Check before/after grants.
**Acceptance Scenarios**:
1. **Given** `004` packages present and global spoofing ON, **When**
`FAKE_PACKAGE_SIGNATURE` is granted to GmsCore and Phonesky, **Then**
Self-Check shows positive **correct signature** for both.
2. **Given** Self-Check, **When** the user taps the resolution for correct
signature on Play/microG, **Then** a grant path exists (system permission UI
or equivalent) — not a missing activity / unknown permission.
3. **Given** global spoofing OFF, **When** Self-Check runs, **Then** correct
signature checks fail even if packages are installed.
---
### User Story 3 - Play login / auth without API-console mismatch (Priority: P1)
As the developer, after spoofing is enabled and granted for Phonesky, Google
account sign-in in Play no longer fails with
`UNREGISTERED_ON_API_CONSOLE` / “SHA-1 certificate fingerprint” mismatch caused
by presenting the project signing key as the Play identity.
**Why this priority**: Owner-observed LAB failure; AXP GOLDEN works with spoofing.
**Independent Test**: LAB logcat during Play sign-in; compare to pre-`005`
failure mode.
**Acceptance Scenarios**:
1. **Given** spoofing ON + Phonesky granted, **When** signing into Play,
**Then** auth token acquisition does not fail with `UNREGISTERED_ON_API_CONSOLE`
due to project cert fingerprint.
2. **Given** Play update prompts that AXP intentionally blocks, **When** the
user tries in-app self-update, **Then** failure remains acceptable (out of
scope to enable stock Play self-update).
---
### User Story 4 - Restricted allow-list only (Priority: P1)
As the project owner, spoofing is **not** a general capability for arbitrary
apps. Only explicitly authorized packages/signers may obtain effective spoofing
(at minimum official microG GmsCore and project-signed patched Phonesky).
**Why this priority**: Constitution: native, restricted, auditable; no LSPosed.
**Independent Test**: Attempt spoofing from a third-party test APK that requests
`FAKE_PACKAGE_SIGNATURE` without being allow-listed → denied.
**Acceptance Scenarios**:
1. **Given** global spoofing ON, **When** a non-authorized app requests
spoofing, **Then** it cannot effectively impersonate Google/platform
signatures.
2. **Given** documentation, **When** reviewed, **Then** the authorized set and
how to extend it are written (for future packages if needed).
---
### User Story 5 - Survives without root (Priority: P2)
As the developer, microG and Phonesky spoofing keep working when optional root /
Zygisk-style functionality is unavailable (Compatibility MVP is rootless).
**Why this priority**: Constitution Compatibility MVP ends at `006` rootless.
**Independent Test**: LAB build without Magisk/KSU; spoofing + Self-Check still
pass.
**Acceptance Scenarios**:
1. **Given** no Magisk/KSU on the `005` validation build, **When** spoofing is
configured, **Then** Self-Check signature lines and basic Play auth path
still succeed.
---
### User Story 6 - First working stack ship gate (Priority: P1)
As the developer, one LAB flash of the `005` validation build includes a
**complete** first stack: packaging fixes from `004` that never landed in a
clean zip, spoofing, and documented modern location setup — without waiting for
banking (`006`) or root (`007`).
**Why this priority**: Owner: this phase must work before later features.
**Independent Test**: Single zip flash on LAB; follow quickstart; no Magisk/KSU.
**Acceptance Scenarios**:
1. **Given** the `005` artifact zip, **When** flashed to LAB, **Then** Phonesky
registers (`pm path`) without remount hacks; APK signatures verify (no
PRESIGNED strip).
2. **Given** that build, **When** spoofing is configured per quickstart,
**Then** Self-Check signature lines and Play auth meet SC-003/SC-004.
3. **Given** microG Location settings, **When** configured for a modern
Ichnaea-compatible endpoint (BeaconDB), **Then** the procedure is documented
and does not depend on legacy UnifiedNlp backend APKs.
---
### Edge Cases
- Stock LOS 23.2 tree on `rom-dev01` has **no** `FAKE_PACKAGE_SIGNATURE` /
`allow_signature_fake` (inventory 2026-09-15) → must port/adapt from
AXP/EXTENDROM patterns, not “enable a hidden LOS flag”.
- Phonesky privapp XML on AXP binds permissions to **cert SHA-256 digest**; our
project digest differs from AXP’s — XML must use **our** digest.
- Play 52.x FGS / privapp extras (`FOREGROUND_SERVICE_SYSTEM_EXEMPTED`, etc.)
remain packaging/`004` follow-ups; `005` must not regress them.
- Disabling Play via App info remains supported (owner: useful on AXP).
- Island/work profile: spoofing grants may need to exist per user — verify at
least owner user 0 for P1; note multi-user as follow-up if broken.
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: ROM MUST provide a Developer Options control equivalent to AXP
**Allow signature spoofing**, persisted as a global setting (GOLDEN:
`settings secure allow_signature_fake`).
- **FR-002**: ROM MUST define and enforce `android.permission.FAKE_PACKAGE_SIGNATURE`
(or AOSP-equivalent restricted spoofing permission) so PackageManager can
honour `meta-data fake-signature` for authorized packages when the global
toggle is ON and the permission is granted.
- **FR-003**: Spoofing MUST be restricted to an explicit allow-list of packages
and/or signers; at minimum `com.google.android.gms` (official microG signer)
and `com.android.vending` (project Phonesky signer). Unrestricted spoofing is
forbidden.
- **FR-004**: With toggle ON and grants present, microG Self-Check MUST report
positive **correct signature** for GmsCore and Phonesky/Play.
- **FR-005**: With toggle ON and Phonesky granted, Play account auth MUST NOT
fail with `UNREGISTERED_ON_API_CONSOLE` caused by exposing the project signing
certificate as Play’s identity.
- **FR-006**: Spoofing MUST NOT depend on Magisk, Zygisk, LSPosed, or other
root modules.
- **FR-007**: Behaviour and UX SHOULD match GOLDEN/AXP where compatible with
Android 16 / LOS 23.2; if the AXP patch set does not apply cleanly, redesign
the path to the **same end state** and record deltas in `docs/a15-a16-delta.md`.
- **FR-008**: Validation MUST be LAB-only (`11231JEC207477`); GOLDEN remains
sample-only.
- **FR-009**: Implementation MUST be attributable (source-linked patches /
EXTENDROM/AXP/LOS references); no opaque megapatch.
- **FR-010**: The `005` validation build MUST incorporate outstanding `004`
packaging fixes required for a clean flashable image: PRESIGNED APKs installed
via replace-prebuilt (no v2/v3 strip), and Phonesky privapp entries needed for
Android 16 / Play 52 FGS (e.g. system-exempted foreground service + exact
alarm) so Play does not crash on setup/download services.
- **FR-011**: First-stack validation MUST document modern microG network
location configuration (Ichnaea-compatible service URL such as BeaconDB); MUST
NOT require shipping legacy UnifiedNlp backend packages (Déjà Vu, Nominatim
NLP apps).
### Key Entities
- **Global spoofing toggle**: User-facing Developer Options switch; gates all
spoofing effect.
- **Spoofing permission**: Per-app dangerous/runtime-style permission the user
(or approved default path) grants to authorized packages.
- **Authorized package set**: microG GmsCore + patched Phonesky (extensible
later under constitution rules).
- **Oracle capture**: `.local-artifacts/002-golden/20260915-spoofing-phonesky/`
(settings, `er_*` XMLs, framework strings, dumpsys grants).
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: On LAB, Developer Options exposes the spoofing master switch;
`allow_signature_fake` reads `1` when enabled.
- **SC-002**: `pm` / permission APIs show `FAKE_PACKAGE_SIGNATURE` defined;
grants visible for GmsCore and Phonesky when configured.
- **SC-003**: microG Self-Check shows **correct signature** checked for GmsCore
and Play/Companion within one configuration session after flash.
- **SC-004**: Play sign-in logcat no longer shows `UNREGISTERED_ON_API_CONSOLE`
fingerprint mismatch for Phonesky under the spoofed identity.
- **SC-005**: A non-allow-listed test app cannot obtain effective Google
signature spoofing with the global toggle ON.
- **SC-007**: One LAB flash of the `005` zip boots without remount overlays for
Phonesky; `apksigner verify` equivalent on-device package is registered; Play
does not crash-loop on VpaService/DownloadService for missing FGS privapp
allowlist entries.
- **SC-008**: Quickstart includes BeaconDB (or successor) location steps;
Self-Check / location UI does not depend on empty UnifiedNlp backend lists.
## Assumptions
- `004` packaging (PRESIGNED `LOCAL_REPLACE_PREBUILT_APK_INSTALLED`, Phonesky
patch with `fake-signature`, privapp XMLs) remains the base; `005` does not
replace FakeStore for Play. Unmerged `004` leftovers ship in the same `005`
validation build (single first-stack artifact).
- Default for the global toggle is **OFF** until the user enables it (AXP
“explicitly enable” model), unless plan proves a safer first-boot prompt.
- Official microG continues to update via F-Droid same-signer; Phonesky via
project JKS.
- Primary patch reference: AXP/EXTENDROM signature spoofing + GOLDEN 2026-09-15
capture; inventory shows stock LOS 23.2 lacks these hooks. Spoofing MUST also
cover modern `PackageInfo.signingInfo` (not only legacy `signatures[]`).
- Play self-update remaining broken/blocked is acceptable (AXP parity).
- Multi-user/Island spoofing parity is best-effort for P1 (user 0 first).
- MLS (Mozilla Location Service) is retired; BeaconDB (or documented successor)
is the modern network-location endpoint for microG 0.3.x.
## Out of Scope
- KernelSU / Magisk / DenyList (`007`)
- Banking Insular hard-gates / Yuh / Swissquote (`006`)
- Call recording / FLAG_SECURE (`008`/`009`)
- Changing Phonesky to Google’s proprietary signer
- Unrestricted signature spoofing for all apps
- Reintroducing UnifiedNlp backend APKs as the primary location design
@@ -0,0 +1,264 @@
# Tasks: Restricted native signature spoofing (first working stack)
**Input**: Design docs from `/specs/005-restricted-signature-spoofing/`
**Prerequisites**: `004` packaging on LAB (Phonesky present); GOLDEN oracle
`.local-artifacts/002-golden/20260915-spoofing-phonesky/`; constitution spoofing rules
**Organization**: First working stack = packaging leftovers + spoofing + BeaconDB.
**Out of scope**: `006` banking, `007` KSU/root.
## Format: `[ID] [P?] [Story] Description`
- **[P]**: Can run in parallel (different files, no incomplete deps)
- **[Story]**: US1…US6 from `spec.md`
## Path conventions
- Meta repo: `vendor/sunfish-a16/`, `docs/`, `specs/005-…/`
- Build host: `/srv/rom/src/lineage/` (frameworks, Settings), `/srv/rom/artifacts/005-…/`
---
## Phase 1: Setup
**Purpose**: Patch sources, dirs, delta notes
- [x] T001 Checkout / mirror EXTENDROM sigspoof sources on `rom-dev01` under
`/srv/rom/references/extendrom/` (or sparse clone
`sfX-android/android_vendor_extendrom`); record commit in
`docs/a15-a16-delta.md`
*(2026-09-15: `f129253c…`; also found stock LuK1337 spoof in LOS tree)*
- [x] T002 [P] Create `/srv/rom/artifacts/005-spoofing/` and
`/srv/rom/logs/005-build/` (android-build writable)
- [x] T003 [P] Add `docs/005-spoofing-runbook.md` stub (EXTENDROM port steps,
allow-list, LAB-only) in meta repo
- [x] T004 [P] Confirm working-tree packaging leftovers present:
`vendor/sunfish-a16/Android.mk` has `LOCAL_REPLACE_PREBUILT_APK_INSTALLED`;
`vendor/sunfish-a16/permissions/privapp-permissions-com.android.vending.xml`
has FGS/exact-alarm + Play 52 entries — sync both to
`/srv/rom/src/lineage/vendor/sunfish-a16/`
---
## Phase 2: Foundational (blocks all stories)
**Purpose**: A16-portable spoofing patch set + product wiring; no bacon yet
**⚠️ CRITICAL**: No US validation flash until this phase completes
- [x] T005 Inventory EXTENDROM A15 patch list vs LOS 23.2 paths; write mapping
table in `docs/a15-a16-delta.md` (frameworks/base, services, Settings,
overlays)
- [x] T006 Apply / port EXTENDROM signature-spoofing patches to
`/srv/rom/src/lineage/frameworks/base/` so
`android.permission.FAKE_PACKAGE_SIGNATURE` exists and
`meta-data fake-signature` is honoured for **both**
`PackageInfo.signatures` and `PackageInfo.signingInfo`
*(extended LuK1337 path via `apply_005_sigspoof.py`)*
- [x] T007 Wire global gate `settings secure allow_signature_fake` in
PackageManager path under
`/srv/rom/src/lineage/frameworks/base/services/` (silent deny when off)
- [x] T008 Restrict effective spoofing to allow-list packages/signers
(`com.google.android.gms` official microG; `com.android.vending` project
Phonesky digest
`31:31:86:CB:7D:F2:D4:01:33:72:12:07:B7:29:73:E8:52:F6:1C:87:67:C3:21:E5:C7:50:39:01:1B:83:BD:56`)
— document mechanism in `docs/005-spoofing-runbook.md`
- [x] T009 [P] Update Phonesky privapp/default XMLs in
`vendor/sunfish-a16/permissions/` to include `FAKE_PACKAGE_SIGNATURE` and
bind Phonesky entries to **our** cert SHA-256 digest (not AXP
`00:5C:98:…`); sync to host tree
*(FAKE_PACKAGE already in privapp; digest enforced in ComputerEngine)*
- [ ] T010 [P] Align GmsCore-related default-permissions / sysconfig intent from
GOLDEN `er_*` files into `vendor/sunfish-a16/` (power-save / app-link as
needed) without inventing GmsCore priv-app
**Checkpoint**: Foundation ready — bacon is next (US6)
---
## Phase 3: User Story 1 — Developer Options master switch (P1) 🎯 MVP slice
**Goal**: Toggle **Allow signature spoofing** in Developer Options
**Independent test**: UI present; `settings get secure allow_signature_fake` is
`1` when ON; OFF disables effect
- [x] T011 [US1] Port EXTENDROM/AXP Settings Developer Options strings +
preference for `allow_signature_fake` into
`/srv/rom/src/lineage/packages/apps/Settings/` (or overlay under
`vendor/sunfish-a16/`) matching GOLDEN UX
(`signature_spoof_category` / Allow signature spoofing)
- [ ] T012 [US1] Verify default is OFF; toggling ON/OFF persists across reboot
(device proof after US6 flash)
**Checkpoint**: US1 code landed in tree (validated on device in US6 flash)
---
## Phase 4: User Story 4 — Restricted allow-list only (P1)
**Goal**: Non-authorized apps cannot effectively spoof
**Independent test**: Third-party test APK requesting FAKE_PACKAGE denied
- [ ] T013 [US4] Add allow-list enforcement tests/notes in
`docs/005-spoofing-runbook.md` (manual LAB procedure + expected deny)
- [ ] T014 [US4] Confirm implementation from T008 rejects non-listed packages
even with toggle ON (code review + LAB check after flash)
**Checkpoint**: Policy documented; enforcement in PMS path
---
## Phase 5: User Story 2 — Self-Check correct signatures (P1)
**Goal**: microG Self-Check marks correct signature for GmsCore + Phonesky
**Independent test**: Self-Check screenshots after grants
- [ ] T015 [US2] Ensure grant path works (permission UI / Self-Check tap) —
no missing `GrantFakeSignaturePermissionActivity` / unknown permission
- [ ] T016 [US2] Update `docs/004-lab-selfcheck.md` with spoofing steps and
expected green signature rows (post-`005`)
**Checkpoint**: Self-Check contract ready; device proof in US6
---
## Phase 6: User Story 3 — Play auth without API-console mismatch (P1)
**Goal**: Play sign-in without `UNREGISTERED_ON_API_CONSOLE`
**Independent test**: logcat during login
- [ ] T017 [US3] Document auth verification commands in
`specs/005-restricted-signature-spoofing/quickstart.md` (already drafted —
tighten failure signatures)
- [ ] T018 [US3] After flash (US6), capture logcat proving absence of
`UNREGISTERED_ON_API_CONSOLE` for Phonesky; store under
`/srv/rom/artifacts/005-spoofing/`
**Checkpoint**: Auth acceptance tied to US6 validation build
---
## Phase 7: User Story 5 — Survives without root (P2)
**Goal**: Spoofing works with no Magisk/KSU
**Independent test**: build props / `pm` show no Magisk
- [ ] T019 [US5] Confirm `005` product makefiles do not pull Magisk/KSU; note in
`docs/005-spoofing-runbook.md` and gate handoff
---
## Phase 8: User Story 6 — First working stack ship gate (P1)
**Goal**: One zip = REPLACE packaging + FGS privapp + spoofing; BeaconDB docs
**Independent test**: `quickstart.md` end-to-end on LAB
- [x] T020 [US6] `mka bacon -j8` on `rom-dev01`; log
`/srv/rom/logs/005-build/bacon.log`; verify intermediate Phonesky APK
`apksigner verify` (v2/v3) under `out/target/product/sunfish/`
*(SUCCESS 2026-09-15T14:27Z, 03:49:11; log
`bacon-20260915T103756Z.log`; zip SHA256
`1f08e00433e073e0b6525eb2539fe9011a291f34604a6917bf1836aecf03e383`;
Phonesky v2+v3 OK)*
- [x] T021 [US6] Stage zip + imgs + SHA256 + VERSIONS + spoofing notes to
`/srv/rom/artifacts/005-spoofing/<date>/` and rsync to
`.local-artifacts/005-spoofing/`
*(host `…/20260915-bacon/`; laptop got SHA+triage+packaging-check;
full zip remains on host)*
- [x] T022 [US6] Flash LAB only (`11231JEC207477`); confirm
`pm path` for gms/gsf/vending without remount
*(gms/gsf `/system_ext/…`; vending from zip then exact-alarm
`adb install -r` → `/data/app/…` until next bacon)*
- [x] T023 [US6] Enable spoofing toggle; grant FAKE_PACKAGE to gms + vending;
Self-Check correct signature green
*(`allow_signature_fake=1`; user 0+10 grants; operator Self-Check pass)*
- [x] T024 [US6] Play sign-in smoke; confirm no FGS VpaService crash loop; record
update-still-blocked as acceptable
*(installs OK both profiles after exact-alarm; UNREGISTERED count=0)*
- [x] T025 [P] [US6] Document BeaconDB location steps in
`docs/004-lab-selfcheck.md` + `quickstart.md` (URL
`https://api.beacondb.net`; no UnifiedNlp backends)
- [x] T026 [US6] Run full `specs/005-restricted-signature-spoofing/quickstart.md`
checklist; tick SC-001…SC-008
*(evidence `/srv/rom/artifacts/005-spoofing/20260915-us6-validation/`)*
**Checkpoint**: First working stack accepted on LAB
---
## Phase 9: Polish
- [x] T027 [P] Update `docs/axp-pro-parity.md` spoofing + microG/Phonesky rows
- [x] T028 [P] Finalize `docs/a15-a16-delta.md` with A15→A16 spoofing port notes
- [x] T029 Handoff: first stack done; next `006` banking rootless — **no** KSU
until after `006`
- [x] T030 Mark remaining `004` tasks superseded/closed where `005` US6 covered
them (`specs/004-microg-phonesky-integration/tasks.md` notes)
---
## Dependencies & Execution Order
### Phase dependencies
- Phase 1 → Phase 2 (foundational patches) → US1/US4 code → US2/US3/US5 docs →
**US6 build/flash validates everything**
- US6 is the integration gate; US1–US5 implementation lands before bacon when
possible, device proof in US6
### User story dependencies
| Story | Depends on |
|-------|------------|
| US1 toggle | T005–T007 (+ T011 Settings) |
| US4 allow-list | T008 |
| US2 Self-Check | T006–T009, US1 toggle |
| US3 Play auth | US2 grants working |
| US5 no root | Product wiring (Phase 2) |
| US6 ship | All above + T004 packaging |
### Parallel opportunities
- T002, T003, T004 after T001 started
- T009, T010 while T006–T008 in progress (XML vs frameworks)
- T025 docs parallel with T020 build
- T027, T028 polish parallel
---
## Parallel example: Foundational
```text
T009 Update Phonesky privapp digest + FAKE_PACKAGE in vendor/sunfish-a16/permissions/
T010 Align GmsCore sysconfig/default-permissions stubs in vendor/sunfish-a16/
T006 Port frameworks FAKE_PACKAGE + signingInfo spoof in frameworks/base/
```
---
## Implementation strategy
### MVP
1. Phase 1–2 (patches + XML)
2. US1 Settings toggle
3. US6 bacon + LAB flash proving toggle + Self-Check + Play auth
### Incremental
After MVP flash: tighten allow-list evidence (US4), BeaconDB doc polish (T025),
parity docs (T027–T029).
### Suggested first implement slice
**T001 → T004 → T005–T011 → T020–T026** (skip polish until green Self-Check).
---
## Notes
- Never flash GOLDEN; LAB serial only
- No Magisk/KSU in this feature
- Do not reintroduce UnifiedNlp backend APKs
- Prefer EXTENDROM attributable patches; record conflicts in delta doc
- User owns git commit/MR; agents only working tree / host build dirs