181 lines
6.8 KiB
Markdown
181 lines
6.8 KiB
Markdown
# 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.
|