# Kotlin Phone App + Admin > Build spec for Paperclip. Follow the phases in section 11 in order. Do not skip a > phase's Definition of Done. When something is unclear, ask Sam — do not guess. --- ## 1. Purpose and outcome Sam's Android app. It is the **Hub's way in from the phone**, and the **trusted admin surface** for approvals and parental controls. **Outcome (the single success statement):** > Sam talks to the Hub from his phone, hears the answer, and can approve or change > anything from the same app. ## 2. Scope **In scope** - Capture voice and send it to the Hub. - Show the Hub's reply: text, spoken audio, and notifications. - Show approval prompts ("Did you ask for this?") and answer them. - Admin controls: parental controls, by calling the internet control service. - Native phone actions the Hub requests (call, open a link, open an app by deep link). **Out of scope** - The **kids' phone client.** That stays under `internet_use_control`. - **Artemis** (screen control). Separate project. - The **Hub** service itself. - Understanding speech. The Hub does that. **Decision to confirm:** this is **one app with two areas** — Hub (voice) and Admin. Not two apps. ## 3. Users and roles - **Sam only.** This app is not for Jo, Harry, or Finn. - The kids' client is a different app, built under `internet_use_control`. ## 4. Functional requirements | ID | Requirement | |---|---| | FR-1 | Capture voice. Start with **hold-to-talk**; add a wake word later. | | FR-2 | Send the transcript to the Hub (`POST /ask`) and show the reply as text. | | FR-3 | Play the Hub's reply as **TTS on the phone**, when the reply asks for it. | | FR-4 | Show **approval prompts** and return approve or deny to the Hub. | | FR-5 | Admin: list the kids' devices and their state, and lock, unlock, or grant time. | | FR-6 | Admin calls the **internet use control** API directly. The app holds no control logic. | | FR-7 | Gate admin actions behind a **keycode or biometric**. | | FR-8 | Perform native actions the Hub requests: place a call, open a deep link. | | FR-9 | Show Hub `/notify` messages as Android notifications. | | FR-10 | Settings: Hub URL and token. Test the connection. | | FR-11 | Offline: fail cleanly, and never claim a command succeeded. | ## 5. Screens and UX flow **Screens** 1. **Home (Hub)** — a large talk button, the last reply, and recent history. 2. **Approvals** — pending "Did you ask for this?" items with Approve / Deny. 3. **Admin** — the kids' devices, each with its state and quick actions. 4. **Settings** — Hub URL, token, keycode, test connection. **Main flow** ``` Sam holds the button and speaks → the Hub replies → the phone speaks it If the Hub needs approval → a card appears → Sam taps Approve If Sam opens Admin → he locks a phone → the internet control service applies it ``` ## 6. Look and feel Reuse the Family Home Lab design system, adapted to Android. - Source: `/home/sam/Docker/Containers/family-home-lab/DESIGN.md` - Tokens: `/home/sam/Docker/Containers/family-home-lab/portal/static/tokens.css` Map the tokens to the app theme: canvas `#f6f5f4`, one action blue `#0075de`, Inter, 8px spacing, 4px inputs, pill buttons, hairline dividers, dark mode. The login/consent moment is the one dark indigo band. ## 7. Data model On the device only. No server database. | Store | Holds | |---|---| | Settings | Hub URL, Hub token (encrypted), keycode hash | | Cache | recent replies, pending approvals | | Log | last actions, for debugging | ## 8. Integrations | System | Use | |---|---| | **Hub** | `POST /ask`, approval callbacks, `/notify`. Frozen in `central_ai_llm_master/docs/hub-api.md`. | | **Internet use control** | Admin lock, unlock, grant. Direct API call. See `internet_use_control/SYSTEM_MAP.md`. | | **Android telephony** | Native calls and contacts. | | **Deep links** | Opening a specific song or place. | | **Artemis** | Not called from here. The Hub calls it. Native actions stay in this app. | ## 9. Technology (locked) | Item | Value | |---|---| | Language | **Kotlin** (Android) | | Voice | `SpeechRecognizer` first; a wake-word engine later | | Transport | HTTP to the Hub. **LAN, or Tailscale when away** — decide in Phase 1. | | Push | FCM, or polling for approvals — decide in Phase 4 | | Min SDK | Decide in Phase 1. Suggest API 29 (Android 10). | | Repo | `sam/kotlin_phone_app_admin` | ## 10. Rules and constraints 1. **Admin actions need the keycode or biometric.** Never a spoken keycode alone. 2. The app **never** holds control logic. It calls the service. 3. The Hub token lives in encrypted storage. Never in logs. 4. The app never claims success on a failed call. 5. Models go through **OmniRoute** — but this app talks to the Hub, not to models. 6. Own folder, own repo. ## 11. Build order **Phase 1 — Skeleton and settings** Empty app, settings screen, Hub URL + token, test connection. *DoD:* the app reaches the Hub and shows its health. **Phase 2 — Voice in** Hold-to-talk, send to the Hub, show the text reply. *DoD:* a spoken question returns a Hub answer on screen. **Phase 3 — Voice out** Play the reply as TTS on the phone. *DoD:* the phone speaks the Hub's reply. **Phase 4 — Approvals** Fetch pending approvals, show the card, approve or deny. *DoD:* a real "did you ask for this?" from the Hub is answered from the phone. **Phase 5 — Admin** List kids' devices via the internet control API. Lock, unlock, grant. *DoD:* a real device locks in under one second from the app. **Phase 6 — Security gate** Keycode or biometric before admin actions. *DoD:* admin actions are blocked without the gate. **Phase 7 — Notifications and deep links** Hub `/notify` as notifications. Native actions and deep links. *DoD:* a Hub notification arrives, and a deep link opens the right song. **Phase 8 — Wake word (optional)** Replace hold-to-talk with a wake word. *DoD:* the wake word starts listening without touching the phone. **Phase 9 — Documentation** *DoD:* project-docs run; docs updated. ## 12. Acceptance criteria - Sam asks a question by voice and hears the answer on the phone. - An approval prompt can be answered from the phone. - A kids' device can be locked from the app in under one second. - Admin actions require the keycode or biometric. - A Hub notification arrives on the phone. - The app never reports success after a failure. ## 13. Decisions and remaining questions Resolved: 1. **One app for Sam** (Hub + Admin). The kids' client is under `internet_use_control`. 2. **Kotlin**, Android. 3. Admin calls the internet control API directly. No Hub in that path. Remaining: 1. **Hold-to-talk first, wake word later** — agree? 2. How does the app reach the Hub: LAN only, or Tailscale when away? 3. Approvals by FCM push, or polling? 4. Locked-screen behaviour: can approvals be answered from the lock screen? 5. Min SDK version.