From 9b27e858b54bc11fc864263e366f91e4bb62adff Mon Sep 17 00:00:00 2001 From: iris <2+iris@noreply.localhost> Date: Mon, 7 Sep 2026 16:30:08 -0400 Subject: [PATCH] docs/RUST.md: APK runtime logs in Dev Updater via an on-device ContentProvider (Iris, 2026-09-07); supersedes the ai-server client-log route Co-Authored-By: Claude Fable 5.1 --- docs/RUST.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/RUST.md b/docs/RUST.md index dd94c8e..2cb9452 100644 --- a/docs/RUST.md +++ b/docs/RUST.md @@ -512,6 +512,33 @@ closes it. - [ ] Scroll clamped at both ends, and Compose's impulse velocity estimator with min/max fling velocity (docs/IRIS_TODO.md, 2026-09-07 later). After the culling fix lands (same file). +- [ ] **APK runtime logs in Dev Updater (Iris, 2026-09-07: "please add + android / apk runtime log support to dev updater").** Supersedes the + ai-server `POST /client-log` route, which becomes the second mechanism + and is deleted once this works (`log_upload.rs`, `app_log.rs`'s + upload half, the route). Design: Android forbids reading another + app's logcat, so the app carries its own log (`client_core::log_ring`, + kept) and **exposes it on-device through a ContentProvider** that Dev + Updater's phone app reads -- no tunnel, no token, no second + enrolment, because the two apps are on the same phone. Authority + `.devlog`, one table `lines(seq, t_ms, level, target, + message)` plus a `dropped` count, queried with `since=` so a poll + is incremental. Dev Updater's phone app: for an APK component whose + installed package resolves that authority (`PackageManager`), the + component gets a **Runtime** tab like a service's; it polls the + provider while the tab is open and forwards new lines to its host + server's existing per-component runtime-log store, so history + survives the phone and the same tab code renders it. Read access + guarded by a permission Dev Updater defines + (`dev.updater.permission.READ_DEVLOG`, protection `normal`; signature + level is not available because the two apps are signed with different + locally generated keys -- state that trade-off in DECISIONS.md). The + provider is Java in `android-app` reading the ring over JNI (platform + glue, allowed by the sharing rule); the Compose app can implement the + same contract later so both apps get the tab. Rejected: Dev Updater + handing its server token to the app it installed (leaks the token + into every managed app); the app posting to ai-server (needs its own + enrolment first and puts the phone's logs in the wrong component). - [ ] Iris app enrolment (decided 2026-09-07): the bench APK's log destination is baked from `AI_APP_LOG_*` at build time, which cannot work for Iris's phone -- the APK is built in the VM, whose CA and