Make the Rust client the sole app
This commit is contained in:
1 parent
a8602c1626
commit
d8bb1699a8
230 files changed
+762
-27300
No files matched your search
+3
-3
@@ -1,6 +1,6 @@
|
||||
# `app-rust`'s `client` module
|
||||
# `app`'s `client` module
|
||||
|
||||
`app-rust/src/client` contains platform- and UI-independent client logic. It
|
||||
`app/src/client` contains platform- and UI-independent client logic. It
|
||||
must not depend on iris; a `use iris::` below this directory is a layering
|
||||
defect. `event-model` remains a separate crate because the server and client
|
||||
both depend on that wire contract.
|
||||
@@ -71,4 +71,4 @@ shared non-UI consumer needs them.
|
||||
|
||||
Run `./scripts/run-tests.sh` from the repository root. For this crate alone,
|
||||
run `cargo test`, `cargo clippy --all-targets`, and `cargo fmt --check` from
|
||||
`app-rust/`.
|
||||
`app/`.
|
||||
+4
-4
@@ -16,16 +16,16 @@ Framework capabilities needed by `RUST.md`'s port plan:
|
||||
- [ ] **Expose the distance from a `LazySpan` viewport to its unloaded
|
||||
edge.** (**P1**.) `viewport_len` and the visible extents are already
|
||||
measured internally, but a paging caller cannot ask whether it is within
|
||||
the Compose app's six-viewport `HISTORY_SCREENS` cushion. The API should
|
||||
the product's six-viewport `HISTORY_SCREENS` cushion. The API should
|
||||
answer in pixels or viewport multiples, never rows: a row ranges from one
|
||||
line to a screen, so a fixed row count is not a distance.
|
||||
- [ ] **Let an image fit a bounded box while preserving its aspect ratio.**
|
||||
(**P1**.) `Image` currently always reports and draws the decoded texture's
|
||||
natural pixel size. Decoding and fetching a server-produced attachment
|
||||
belong in `app-rust`; iris only owes the generic fit/scale widget used to
|
||||
belong in `app`; iris only owes the generic fit/scale widget used to
|
||||
draw its thumbnail.
|
||||
- [ ] **Per-range backgrounds for rich text.** (**P1**.) Inline code is
|
||||
already monospace and coloured, but matching Compose's chip also needs
|
||||
already monospace and coloured, but the inline-code chip also needs
|
||||
the glyph run's boxes so a surface can be drawn behind exactly that byte
|
||||
range. The shared `TextSelection` engine already computes the same geometry
|
||||
for selection highlights; expose one shared primitive rather than giving
|
||||
@@ -53,7 +53,7 @@ Framework capabilities needed by `RUST.md`'s port plan:
|
||||
pay nothing and import nothing for them.
|
||||
|
||||
- [ ] **Remove `WidgetView` unless a real composite adopts it.** Every
|
||||
composite in `app-rust/src/ui` uses ordinary child handles plus a root;
|
||||
composite in `app/src/ui` uses ordinary child handles plus a root;
|
||||
`WidgetView` and its derive are used only by `iris/examples/view.rs`.
|
||||
It currently demonstrates itself rather than shortening production code.
|
||||
|
||||
|
||||
+11
-14
@@ -6,8 +6,8 @@ need a front end at all, and owning the client means fixing what the official
|
||||
app gets wrong (it won't deliver a typed message until the turn fully
|
||||
finishes, where the TUI injects it at the next tool boundary).
|
||||
|
||||
Same shape as `../dev-updater`: a Rust (Axum) backend on the desktop, a
|
||||
Kotlin/Compose Android app, pinned self-signed TLS between them.
|
||||
Same shape as `../dev-updater`: a Rust/Axum backend on the desktop and a
|
||||
shared Rust client for Android and desktop, with pinned self-signed TLS.
|
||||
|
||||
This file records decisions with their date, their rationale, and what was
|
||||
rejected. Update it in place when one changes; `AGENTS.md` is the working
|
||||
@@ -23,7 +23,7 @@ screens). SSH falls out of the same shape: a remote session is the identical
|
||||
command wrapped in `ssh host …`, and the driver never learns which it got.
|
||||
|
||||
```
|
||||
Android app (Compose)
|
||||
Android or desktop app (Rust/iris)
|
||||
│ HTTPS (pinned CA) — REST for actions, SSE for live events
|
||||
▼
|
||||
backend (Rust/Axum, desktop)
|
||||
@@ -702,15 +702,10 @@ ssh case are one implementation.
|
||||
a hardcoded IP. The CA is created once and left alone; the leaf is reissued
|
||||
every start, so covering a new address is a restart. **Regenerating the CA
|
||||
strands the installed app** — the one-way door.
|
||||
- Unlike dev-updater, the pinned CA is **not a constant in the source**:
|
||||
the build reads `$XDG_CONFIG_HOME/ai-app/certs/ca.pem` from the machine
|
||||
doing the build and generates the constant (`generatePinnedCert` in
|
||||
`app/androidApp/build.gradle.kts`; `AI_APP_CA` overrides). That does
|
||||
three things at once — the trust anchor follows the build machine, so an
|
||||
APK built in the dev VM is only good for its emulator; there is no second
|
||||
anchor to add for development and forget to remove; and regenerating a CA
|
||||
needs a rebuild rather than a paste, so a stale constant cannot quietly
|
||||
disagree with the server.
|
||||
- The enrollment link carries the CA certificate. `app/src/client/config.rs`
|
||||
decodes it and the transport pins it for every connection. A malformed or
|
||||
absent CA refuses enrollment rather than silently weakening TLS. This lets
|
||||
one APK enroll against either the host or an isolated development server.
|
||||
- **The dev VM is untrusted** (2026-08-25): not malicious, but it could
|
||||
become so. The repo is a read-write mount shared between the VM and the
|
||||
backend host, so everything in it — source, binaries, and the shell scripts
|
||||
@@ -797,8 +792,10 @@ ssh case are one implementation.
|
||||
|
||||
## App (`app/`)
|
||||
|
||||
Kotlin + Compose Multiplatform, single `:androidApp` module, same versions as
|
||||
dev-updater (Kotlin 2.4.x, CMP 1.11.x, JDK 21).
|
||||
One Rust crate owns platform-free client logic and Iris widget trees. Android
|
||||
and desktop entry points contain only their host integration. Android is
|
||||
packaged by a thin Java activity under `android-project/`; it does not contain
|
||||
a second UI implementation.
|
||||
|
||||
1. **Session list** — kind icon, title, setup, model, status, last activity.
|
||||
Sessions awaiting an answer sort to the top: the "your turn" inbox.
|
||||
|
||||
+198
-906
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -235,7 +235,7 @@ without a scroll-widget special case.
|
||||
|
||||
## The transcript's wiring
|
||||
|
||||
`app-rust/src/ui/mod.rs`, `build_tree`.
|
||||
`app/src/ui/mod.rs`, `build_tree`.
|
||||
|
||||
The transcript registers the wheel **by hand rather than calling
|
||||
`LazySpan::scrollable()`**, and this is not an oversight. That helper also
|
||||
|
||||
Reference in new issue
Block a user