Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Review: Devices (desktop & Android)

Review of the device fabric as described, under the sovereignty litmus. Verdicts cite xenon-runtime main @b0cfc90 and the authed-wake design doc; gap IDs (G-3…G-7) are this beat’s device-side register and feed Part IV. The agent-layer gaps (G-1 resident agent, G-2 delegation) are held in the agent-layer review.

The headline

The device fabric is the most-built layer of this beat, and its launcher crossing is one dispatch call short of complete. Desktops are proven full peers on all three platforms; the phone carries real membership, real consent, and a real audit chain. What is missing is not craftsmanship — it is reach: the phone can dial a desktop’s app list but nothing answers (P-188); a sleeping device usually cannot be woken because the transport that reaches it is the one transport that cannot be OS-socket-activated (G-4); and the reverse lifecycle — lost phone, new laptop — is thin. The fabric holds the device truth honestly; the gaps are all about crossing the gap between two devices.

What the layer does well, it does with unusual care: START_NOT_STICKY sessions that never lie about being up, kill-vs-off audit distinctions, device-name sanitization guarding three sinks at once, hosting-side grant re-checks on every open, and a launcher that shows honest CHANNEL_UNAVAILABLE copy rather than a fake empty list.

Desired vs current

Want (decisions / packets)Have (code @b0cfc90)Delta
Mobile both-track: v1 phone-as-client, v2 Android runtime (d/062)Companion APK: consume + launcher + membership/consent/audit; v2 runtime not in this beatOn track; v1 is real. The launcher list itself is not yet served (G-7).
Every desktop a full peer (P-206)Linux/macOS/Windows all publish + consume native; byte-identical proofsHolds. Windows caveats disclosed (P-201w headless, 0-app catalog).
Catalog IS the launch seam (d/104 PROPOSED)On-device plane + apps.list protocol exist; no launch descriptor ratifiedd/104 unratified — blocks P-202’s two frame cells and unparks P-188.
Authorized peer may wake a device it’s allowed to (P-123)Honest disabled stub (P-169); crypto core designedNo code; the zero-resident-vs-reachability crux is unresolved (G-4).
Litmus: movable memoryGroup doc syncs; app state + agent memory are per-device, localNo cross-device memory layer; phone can’t hold app state offline (G-5).

Gap register (device slice)

G-3 — Device enrollment / recovery lifecycle

Exists: the forward path is solid — runtime enrollment + group-join over iroh (lib.rs:120-171, group.rs:244), an offline-verifiable roster (roster_from group.rs:657), immediate revocation for a live target, and self-revocation detected via a dial refusal → self-revoked.json (group.rs:438). docs/key-recovery-design.md exists on paper.

Why this needs design: the reverse / loss paths are thin. A lost phone’s key can be revoked, but the group must re-mint invites; a new laptop re-enrolls from scratch with no grant carryover (by design — reinstall = new principal, capability-model §4); self-revoked.json is one-way with no surfaced rejoin ceremony; there is no account- or social-recovery of the group authority key itself.

Options / tradeoffs: (a) admin-re-invite as the blessed ceremony — simplest, but a lost authority device is unrecoverable; (b) threshold / social recovery of the authority key — resilient, heavier ceremony; (c) a surfaced rejoin flow that clears self-revoked.json after a fresh invite. Ties to AW-2’s statement-typed policy.

Decides: Luke — key-recovery ratification (litmus: exit without loss).

G-4 — Authed-wake, and the socket-activation crux

Exists: the design is delivered (P-123 → docs/xe-authed-wake-design.md); no code ships beyond the honest disabled [Wake device] stub (P-169). The proposal is tight: a roster-member peer may cause a bounded, idempotent ensure_running on a target it is authorized to wake — nothing more — under four invariants (W-1 wake carries no authority; W-2 sync never wakes / wake never syncs; W-3 the runtime learns only a reason, never a payload; W-4 honest availability).

Why this needs design — the crux (§2.1 of the design): the peer transport that shipped is iroh (QUIC/UDP + relay), and iroh cannot be OS-socket-activated the way launchd or systemd can hold a plain TCP socket and start a process on the first connection. The transport a peer uses to reach a device is precisely the transport that cannot wake a zero-resident device. So the only honest wake is a same-network, zero-resident desktop over an OS-held plain socket; everything else the button honestly refuses with an action. The wakeability matrix (design §2.2):

Target stateWakeable?
Desktop, same network, zero-residentYes (best-effort, OS socket activation)
Desktop, internet-onlyNo (relay cannot socket-activate)
Android, session activeMoot (already up)
Android, force-stoppedNo (needs the unbuilt notifications transport — G-6)
WindowsNo (no socket-activation primitive)
Powered-offNo (out of scope)

Options / tradeoffs: (a) accept same-network-only for v1 and reserve a relay-mailbox design for cross-internet wake later — honest, ships, defers the hard part; (b) design the relay mailbox now — full reach, significant net-new machinery on a route with subtle replay/amplification concerns; (c) per-platform wake shims (launchd/systemd now, Android notifications + Windows later). The crypto core is already designed either way (target-issued WakeAdmissionV1 ≤24h cert, response-free WakeHintV1, durable at-most-once replay admission, per-class amplification budgets).

Decides: Luke — AW-1 (accept the crux) and AW-2 (authorization source: membership-derived + admission, or a group-doc Statement wake-policy type). AW-3 (≤24h stale-revocation ceiling), AW-4 (Android/Windows non-parity for v1), AW-5 (button honesty default; AW-5b default OFF off-trusted-LAN) round it out.

G-5 — Cross-device state sync / movable memory

Exists: the group document syncs by gossip/announce; peer-sync-v1-design.md is a design; the on-device plane bridges live host sessions only.

Why this needs design: what actually syncs is the group doc plus anchors — not app data, agent memory, or the audit ledger, all of which are local per-device. The phone cannot hold app state offline because the plane is host-routed and lives only for the session. “Movable memory” is asserted per-document but there is no cross-device memory layer yet.

Options / tradeoffs: (a) extend peer-sync-v1 to named data anchors with last-writer or CRDT merge — general, needs conflict semantics; (b) a designated home device per data class with pull-on-demand — simpler, weaker offline story; (c) leave app data single-homed and document it (status quo).

Decides: Luke — peer-sync-v1 ratification (litmus: movable memory).

G-6 — Notification / wake paths per OS

Exists: the honest matrix above. Android with an active session is moot; Android force-stopped needs an unbuilt notifications transport (d/037 Q3); Windows has no socket-activation primitive; powered-off is out of scope.

Why this needs design: a sovereign push path for a dead Android process is the missing primitive behind both G-4 (Android row) and any “your agent needs you” prompt. The tradeoff is self-hosted vs. vendor: UnifiedPush (sovereign, self-hostable) vs. FCM (vendor, ubiquitous, opt-in).

Options / tradeoffs: (a) UnifiedPush self-hosted — on-thesis, more to run; (b) FCM opt-in — trivial reach, a Google dependency on the wake path; (c) both, user-selected. Decision 037 Q3 parked exactly this.

Decides: Luke — d/037 Q3, tied to AW-4.

G-7 — The unwired apps.list responder (P-188)

Exists: the concrete, code-shaped gap from devices §3.5. adopt_node never dispatches LAUNCHER_APPS_ALPN (group.rs:327-328); the protocol is not accepted inbound (:233,272); the responder serve_list_apps_extra (launcher_apps.rs:271) exists but has no caller. Only the debug TCP adapter serves today. The launcher shows the reviewed CHANNEL_UNAVAILABLE copy in production.

Why this needs design: this is the difference between a launcher that lists a desktop’s apps and one that shows an honest “not available” card. It is small and mechanical — but it is parked on d/104, because the shape it serves should be the ratified launch descriptor, not an improvised one.

Options / tradeoffs: (a) wire the responder behind the member-gated serve loop now, using the current LauncherAppEntry shape — unblocks the demo, risks re-shaping later; (b) ratify d/104 first, then wire once to the descriptor — one implementation, gated on a decision. P-188 R1/R2 is written for option (b).

Decides: Luke — d/104 ratification, then a sol lane implements.

The launch seam (d/104, PROPOSED)

decisions/104-cf-guest-launch-seam.md: the catalog IS the launch seam. The launch descriptor is (app label → plane origin http://<app>.localhost:5454) — no per-app baked guest URLs, one route on every platform. Prism’s fleet catalog (P-197) already navigates controlled frames to arbitrary app origins on desktop; Android’s fix is mechanical. Ratifying it blocks P-202’s two BLOCKED cells (in-frame render, in-frame offline honesty) and unparks P-188. Grounded in d/100 (plane origin) + d/103 (compose UIs are plane origins). Reversal is cheap: if Luke prefers an explicit Prism/IWA install-time guest-manifest contract, it is discarded before any dispatch. The descriptor shape is a Part V candidate: Launch descriptor (d/104).

Sovereignty litmus check

CriterionVerdict for the device fabric
Inspect what it seesHolds. status/doctor reconcile cached vs. live truth without waking; the launcher states are honest (incl. CHANNEL_UNAVAILABLE); every failure string ends in an action.
Fork permissionsPartial. Membership roles (Admin/Member/Observer) and revocation are real and offline-verifiable; but per-device capability granularity for the agent is not here yet (G-2, agent review).
BYO models + keysHolds for keys — device keys are local, group authority is a local signed document, no server. Models are out of the device beat.
Movable memoryWeakest point. Group doc moves; app data + agent memory are single-homed per device; the phone can’t hold app state offline (G-5).
Auditable actionsHolds on-device. Hash-chained session/launcher ledger (wake/kill/off/cross/list/launch/resume), tamper-evident. Caveat: 64-bit truncated hash, not externally anchored.
Exit without lossPartial. A consumer removes a peer and keeps its data; but a lost device has no recovery ceremony beyond admin-re-invite, and a new device inherits no grants (G-3).

Questions for the Luke + Jan session

  1. d/104 — ratify the catalog descriptor as the single launch seam? It unblocks P-202’s two BLOCKED Android frame cells and unparks P-188 (the unwired apps.list responder). Reversal is cheap — no code depends on it.
  2. AW-1 / AW-2 — the authed-wake crux: accept “same-network zero-resident desktop only; cross-internet asleep-wake is out of v1” (relay mailbox reserved), and membership-derived authorization (Observers cannot wake) vs. a group-doc Statement wake-policy type? These are the only AW items needing real interview time.
  3. G-3 recovery — what is the lost-phone / new-laptop ceremony? Admin- re-invite is the current implicit answer; is threshold / social recovery of the group authority key in scope? (Ties to AW-2 and key-recovery-design.)
  4. G-6 push — sovereign push for a force-stopped Android process: UnifiedPush self-hosted, FCM opt-in, or both user-selected? (d/037 Q3.)