---
name: spt-mobile-design-grilled
description: spt-mobile v1 design GRILLED+DOCUMENTED 2026-07-06 — paired-peripheral Gateway over iroh JNI slice; docs committed in ../spt-mobile; 2 spt-core seeds pending REMOTE-TRUTH window
metadata: 
  node_type: memory
  type: project
  originSessionId: cfe4ff51-5063-4d00-9082-b4ef0a4f0055
---

spt-mobile (Android Gateway app) design grilled with operator 2026-07-06, all rulings committed in `../spt-mobile` (new repo, first commit): CONTEXT.md glossary + DESIGN.md (10-ruling table, Pebble webhook contract, voice-pipe semantics) + ADR-0001 (phone = paired peripheral of ONE Mobile Gateway endpoint, instance per paired host — never a node/subnet-member; hybrid: Android becomes spt-core build TARGET later, transport swaps not app logic) + ADR-0002 (device link = iroh via embedded Rust JNI slice, cargo-ndk aarch64; node-key addressing solves phone IP roaming; NO tailscale/FCM) + docs/SPT-CORE-NEEDS.md.

Key rulings: multi-host pairing + user-ordered priority IN v1 (failover keys on HOST reachability only, never target liveness — QUEUED=success); star = per-paired-host single endpoint pointer, phone-local; voice pipe = Pebble Index webhook (multipart `transcription`/`recordedAt`, retry-only-on-next-recording → fg-service receiver is the loss boundary) → phone spool (never drop) → user-msg w/ attrs origin="voice" captured=ISO; history = HOST-side per-endpoint log, msg-id dedup + digest `seq` cursor, phone cache = union across hosts; push v1 = foreground service holding iroh conn + host spool (late never lost), ntfy future, FCM ruled out; digest v1 = most-direct-route (co-located paired host only).

**ONE spt-core seed to file with todlando AFTER REMOTE-TRUTH PR #52 merges** (deliberately NOT committed to spt-core mid-PR-window): cross-node digest fetch/subscribe pull-forward (ratified CONTEXT.md:499, gated CROSS_NODE_M4 cli.rs:1384; spt-mobile = forcing customer). Authoritative text: `../spt-mobile/docs/SPT-CORE-NEEDS.md`. Seed #2 (sender attrs) DISSOLVED — operator caught it: `spt send --json-payload` (ADR-0028 W4 metadata axis, REQ-MSG-DELIVERY-AXES, cli.rs:5151) already carries opaque `json="…"` attr alongside body, gate-composed, claude-spt consumes it; voice tag + msg-id ride it as-is. Build-time check: digest echo row preserves json attr for msg-id dedup?

**Why:** operator wants phone functional across wifi/5G IP churn riding spt-core's own networking (no bespoke infra), and one-node-down must not blind the phone.
**How to apply:** when building spt-mobile, instantiate from [[experimplate-traceable-seed-leaks]]-fixed experimplate (upstream defect FIXED @ca13a7c: RELEASE-RUNBOOK.md live tag angle-bracketed); repoint [scan].roots to Gradle+Rust layout; host binary = normal spt adapter (manifest + binary, no spt-mobile-aware code in spt-core per [[adapter-glue-model-boundary]]).

**PRODUCTION-PROVEN 2026-07-06 (flynn report):** operator paired a REAL phone against spt-mobile-host v1.0.1 — two-way messaging live in production: phone-composed user-msg landed on flynn's perch with uuid msg-id dedup, his reply went SENT over the relay and surfaced as a phone notification. The three api.md contract fills (stderr-status rule 3 / poll auth / Going ONLINE, doyle @4406218 off flynn filing #6) were the last missing pieces. spt-mobile cites pinned to live docs anchors @10987a4.
