# Feature Specification: KernelSU-Next on sunfish (LAB) **Feature Branch**: `007-kernelsu-sunfish` **Created**: 2026-09-15 **Status**: In progress (LAB) **Session handoff**: `docs/session-20260916-handoff.md` (2026-09-16) **Input**: After `005` first Google-compat stack works on LAB, skip forcing a rootless Yuh green gate. Prioritize **ReSukiSU** (not Magisk; KSU-Next only as history) on the LineageOS 23.2 sunfish kernel, verified hide for banking UIDs, then SusFS / TEESimulator-class LAB experiments aimed at Yuh KeyMint/RKP failures already logged in `002`. LAB only; never GOLDEN. Personal stock handset for banks remains an optional operator fallback outside this feature. **Spine reminder:** product path is **our** LOS 23.2 (`003`→`004`/`005` bacon) then `007`. Community abu/torukk ROMs and Downloads boots are reference only. ## Context / sequencing vs `006` Constitution originally ordered a **rootless** banking baseline (`006`) before root (`007`). Evidence already shows: | Device | Stack | Swissquote | Yuh | |--------|-------|------------|-----| | GOLDEN | AXP + Magisk DenyList | PASS (owner) | FAIL — HA / “certificate invalid”; KeyMint/`HARDWARE_TYPE_UNAVAILABLE` | | LAB (iodé A16) | No Magisk; BL locked | — | FAIL — same KeyMint/RKP class | So a “rootless Yuh must pass” gate is **not** a credible start condition. This feature **absorbs** the banking regression that `006` would have owned: measure owner + Island UIDs on **our** ROM with root hidden. A separate `006` spec may stay deferred or become a thin historical note — it must not block `007` work. **Explicitly later (do not pull into this feature):** call recording (`008`), `FLAG_SECURE` (`009`), AXP UX leftovers (`010`), project signing/AVB (`011`), incremental Graphene/AXP/Divest **hardening** ports (`012`–`013`). ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Bootable rooted LAB image (Priority: P1) As the developer, I can flash a LAB build whose kernel includes KernelSU-Next compatible with non-GKI Linux 4.14 / sunfish, boot to the lock screen, and confirm root is available only through the KernelSU manager to apps I approve. **Why this priority**: Without a working integrated root path, hide/SusFS/banking experiments cannot run on *our* ROM. **Independent Test**: Flash LAB only; manager shows installed; `su` works for one approved test app and fails for an unapproved app. **Acceptance Scenarios**: 1. **Given** a `007` LAB flash, **When** the device boots, **Then** telephony, Wi‑Fi, and basic UI work at least as well as the last `005` image. 2. **Given** KernelSU manager, **When** root is granted to a single debug app, **Then** that app can obtain root and an unapproved app cannot. 3. **Given** documentation, **When** reviewed, **Then** the exact KernelSU-Next revision (tag/commit) used for the accepted POC is recorded for reproducibility. --- ### User Story 2 - Banking apps never get root; mounts hidden (Priority: P1) As the developer, Yuh and Swissquote (owner and Island/work profile UIDs) are configured so they **never** receive root, and module/overlay mounts that would expose root or custom ROM fingerprints to those UIDs are removed or hidden — verified by a real check, not only a UI toggle. **Why this priority**: Constitution root architecture; Magisk DenyList on GOLDEN is oracle-only, not our production model. **Independent Test**: Per-UID checks (process view of mounts / root binaries) for banking packages on user 0 and work profile; screenshots/logs stored under artifacts. **Acceptance Scenarios**: 1. **Given** Yuh and Swissquote installed (Aurora → Island workflow preferred), **When** root grant lists are reviewed, **Then** those packages are denied root on every relevant user ID. 2. **Given** a module or overlay that would be visible to a normal app, **When** the banking UID is inspected, **Then** that mount is absent or otherwise hidden per the verified umount/profile mechanism. 3. **Given** only a manager “hide” toggle without mount evidence, **When** validation runs, **Then** the story is **not** marked pass. --- ### User Story 3 - SusFS after profiles work (Priority: P2) As the developer, once KernelSU profiles and verified hide work, I can enable a SusFS-capable kernel/config on LAB and confirm the device still boots and that selected path-hiding behaviours are measurable for banking UIDs. **Why this priority**: Needed for hard banks on community sunfish reports; must not destabilize before basic KSU works. Constitution: SusFS only after KernelSU and application profiles work. **Independent Test**: LAB boot + documented SusFS enablement + before/after visibility check for at least one sensitive path from a banking or probe UID. **Acceptance Scenarios**: 1. **Given** US1–US2 green, **When** SusFS is enabled on LAB, **Then** the device boots and KernelSU manager still functions. 2. **Given** SusFS on, **When** a probe from a denied banking UID runs, **Then** at least one previously visible root/custom indicator is hidden (evidence logged). 3. **Given** SusFS causes repeated spontaneous reboot or severe thermal instability, **When** triage completes, **Then** SusFS is reverted or pinned to a known-good revision before continuing banking claims. --- ### User Story 4 - Attestation / KeyMint experiment track (Priority: P1) As the developer, I can run a **LAB-only** attestation-compatibility experiment (TrickyStore-class or equivalent, plus any required microG hardware-attestation toggles) aimed at the Yuh failure mode already captured in `002` (KeyMint / `HARDWARE_TYPE_UNAVAILABLE` / “certificate invalid”), without modifying GOLDEN. **Why this priority**: Root hide alone did not fix Yuh on GOLDEN or iodé LAB; attestation is the open hypothesis. **Yuh PASS is mandatory** for feature acceptance — otherwise root is not worth carrying vs NeoBackup + native `008`/`009` and a stock banking phone. **Independent Test**: Reproduce Yuh launch with logcat focused on `keystore2` / KeyMint / RKP; compare to `002` baselines; diagnostic results required with artifact paths; US5 owns PASS. **Acceptance Scenarios**: 1. **Given** `002` Yuh failure signatures, **When** the experiment stack is applied on LAB, **Then** a new log capture exists that either shows the same class of error or a clear change. 2. **Given** a candidate experiment, **When** the same attestation probe and bank attempt are repeated, **Then** record the before/after result, limitations and rollback outcome. US4 owns diagnostic evidence, not banking acceptance. 3. **Given** persistent KeyMint/RKP messages, **When** results are interpreted, **Then** do not infer causality or failure from those messages alone. US5 exclusively owns the end-to-end banking acceptance decision. --- ### User Story 5 - Banking regression on our ROM (Priority: P1) As the project owner, after hide (and any accepted SusFS/attestation experiments) I have a written regression for **Swissquote** and **Yuh** inside Island on the `007` LAB image: install path, profile UIDs, biometrics if used, and outcome. Revolut/N26 remain non-blocking. **Why this priority**: Compatibility hard-gates; replaces the deferred `006` oracle for “does banking work on our stack”. **Independent Test**: End-to-end on LAB only; evidence under `/srv/rom/artifacts/007-…` (and optional laptop rsync). No GOLDEN flash/wipe. **Acceptance Scenarios**: 1. **Given** Island (or documented equivalent), **When** Swissquote is used in the work profile with root denied + hide verified, **Then** Swissquote MUST PASS with a usable authenticated session, date and build id. 2. **Given** the same setup for Yuh, **When** login/attestation is attempted, **Then** the session MUST **PASS**; an unusable session means `007` is not accepted. 3. **Given** Magisk, **When** proposed as production root, **Then** it is rejected; Magisk A/B diagnostic builds are allowed only as temporary reference per constitution. --- ### Edge Cases - KernelSU-Next revision incompatible with 4.14 → evaluate alternate pin / ReSukiSU only as documented POC fork, not silent default change. - Work-profile UIDs differ from owner → hide/root denial must be tested on both. - `path_umount` missing/broken on 4.14 → story 2 fails until backport/verify. - Attestation modules break Play/microg → revert experiment; keep iterating until both banks PASS or declare `007` blocked/cancelled. - Operator chooses a separate stock phone for banks → interim fallback only; does **not** satisfy the Yuh hard-gate on LAB. ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: Project MUST integrate KernelSU-Next into the LineageOS 23.2–compatible sunfish kernel built with the ROM (not Magisk as production root). - **FR-002**: Root MUST be grantable only to explicitly approved apps; banking packages (at least Yuh and Swissquote) MUST never receive root on owner or work-profile user IDs used in the regression. - **FR-003**: Module/overlay mounts MUST be removable or hidden from selected app processes, with verification beyond manager UI toggles; `path_umount` (or equivalent) support on this kernel MUST be confirmed or explicitly failed. - **FR-004**: The accepted KernelSU-Next revision MUST be pinned and recorded (tag/commit) for reproducible builds. - **FR-005**: SusFS MUST only be enabled after FR-001–FR-003 work on LAB; if enabled, boot stability and at least one measurable hide effect MUST be evidenced. - **FR-006**: Evaluate an attestation candidate with exact source URL, immutable revision or release plus binary hash, dependencies, auditability, baseline, before/after evidence and rollback. KeyMint/RKP causality remains a hypothesis. Banking acceptance is owned solely by FR-007 / US5. - **FR-007**: Both Yuh and Swissquote MUST PASS usable authenticated sessions in the LAB managed profile on the same accepted stack with root denied and hide verified. Failure of either bank leaves `007` incomplete or cancelled. N26/Revolut are non-blocking. - **FR-008**: All flashing, kernel experiments, and attestation modules MUST target LAB (`11231JEC207477`) only; GOLDEN MUST remain read-only oracle. - **FR-009**: Zygisk/LSPosed MUST NOT be introduced as the initial architecture unless a later feature proves no native alternative (out of default `007` scope). - **FR-010**: Feature docs MUST state that deferred `006` rootless-Yuh-pass is not a prerequisite, and must link `002` Yuh/Swissquote evidence paths. ### Key Entities - **LAB device**: Experimental sunfish; only flash target for `007`. - **KernelSU profile**: Per-app (and per-user) root grant / umount policy. - **Banking target apps**: Yuh (`com.yuh`), Swissquote (`com.swissquote.android`). - **Managed profile**: Island (or equivalent) work user hosting banking apps. - **Attestation experiment stack**: Optional LAB modules/toggles aimed at hardware attestation / KeyMint behaviour. - **Pinned root revision**: Exact KernelSU-Next (and SusFS, if used) identifiers. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-001**: LAB boots a `007` image with working selective root within one flash cycle after the accepted kernel build. - **SC-002**: For Yuh and Swissquote on every tested user ID, root grant is denied and mount-hide is evidenced (not toggle-only) for every applicable contract checklist row, for both packages and every tested user ID; no failed or unverified mandatory row is allowed. - **SC-003**: **Yuh PASS** on LAB Island under the `007` stack (root denied + verified hide + accepted SusFS/attestation experiments), with build id and evidence — required to close the feature. - **SC-004**: Swissquote MUST PASS a usable authenticated session on the same image/stack as SC-003, with dated evidence; both are required for acceptance. - **SC-005**: If SusFS is claimed in the release notes for this phase, LAB completes ≥24h soak without SusFS-driven reboot loops, or SusFS is withdrawn from the claim. - **SC-006**: Artifact package contains before/after attestation probe results and correlated banking logs, including unresolved messages and limitations. Absence of a log string alone is not proof of successful attestation. - **SC-007**: No Magisk-based production image is published as the project default root path. ## Assumptions - `005` stack (microG + patched Phonesky + restricted spoofing) remains the userspace base on LAB before/while bringing up `007`. - Island (already used on LAB/GOLDEN) remains the managed-profile vehicle unless a documented substitute is chosen during implementation planning. - If EOL sunfish cannot satisfy Yuh even with SusFS/TrickyStore-class stacks, **`007` stays incomplete** (or is explicitly cancelled) — not “done with Yuh documented FAIL”. Rationale: without Yuh, root adds little over NeoBackup + native `008`/`009`; a stock handset becomes the banking plan instead. - Operator may still use a separate stock phone as interim fallback; that does not count as `007` acceptance. - Full GrapheneOS/AXP/Divest kernel hardening ports remain `013`, not this feature — `007` only changes the kernel as needed for KSU/SusFS/umount. - Community sunfish LOS+KSU+SusFS reports are inspiration, not a drop-in base. ## Out of scope - Flashing or modifying GOLDEN. - Magisk/Magia as default project root. - Making Revolut/N26 hard-gates. - Call recording, FLAG_SECURE, WebView provider work, project AVB lock. - Purchasing or provisioning a second physical phone (operator choice).