Files
internet_use_control/docs/outline/01-system-overview.md
Sam Rolfe eb300b6701 Phase 10: publish the documentation set + tick AGENTS.md 9 of 10
Phase 10 (the last phase of this project) is the project-docs pass. Update the
Gitea README, add the Mermaid source and rendered PNG, build the interactive
Archify map, add the Vikunja board tasks, and write the Outline AI-context
collection in Simplified Technical English.

Deliverables:
- README.md: status header, Phase 4 gap statement, "Architecture" section with
  embedded Mermaid + image + Archify link, "Documentation set" table, an
  explicit two-plane MQTT section (1883 plain+anonymous, 8883 TLS+ACLs), and
  the Android client's Usage Access and VpnService paths.
- AGENTS.md section 11: tick Phase 10, leave Phase 4 unticked, status line now
  "9 of 10 done - only Phase 4 outstanding".
- docs/architecture.mmd + docs/diagrams/architecture.png (mmdc).
- docs/archify/architecture.architecture.json + docs/architecture-map.html
  (Archify, showcase, 9/9 checks, 0 errors).
- docs/outline/00-index.md .. 04-agent-runbook.md (STE).
- docs/vikunja-tasks.json (Vikunja project "Internet Use Control", id 20).
- Obsidian note written to 010 inbox on .27; the obsidian-sorter proposed a
  folder and waits for the vault owner's approval.

Phase 4 (Python Windows computer client) is deliberately deferred and is NOT
built. Every document says so.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-14 12:13:21 +11:00

98 lines
4.4 KiB
Markdown

# Internet Use Control — System Overview
> **Target**: AI agents. **Writing style**: ASD-STE100 Simplified Technical English.
## Purpose
The project limits the screen use of two children, Harry and Finn. It applies
per-device weekly schedules, blocklists and allowlists. It collects usage. It
lets Sam override a rule in seconds. The work applies to the children's devices
only. No router change, no Pi-hole and no house-wide rule.
## Components
| Component | What it is | Where it runs | Language |
| :--- | :--- | :--- | :--- |
| **Control Service** | The brain and the source of truth. Schedules, blocklists, state and usage. | `.13`, Docker, port `8791` | Go + SQLite |
| **Web dashboard** | The admin screen in a browser. HTMX, server-rendered. | Served by the Control Service | HTMX |
| **Broker** | The message bus. Pushes state to devices and collects their reports. | `.13`, Mosquitto | — |
| **Kids' phone client** | Enforces the rules on a phone and shows the blocked state. | The children's phones | Kotlin |
| **Admin app** | The remote override surface. A separate project. | Sam's phone | Kotlin |
| **Hub** | A peer. It asks questions only. It never controls. | `.13`, port `8788` | separate project |
## Data Flow
1. Sam changes a rule in the dashboard or the admin app.
2. The Control Service writes the change to SQLite and to the audit log.
3. The Control Service publishes the device config to MQTT, retained.
4. The device receives its own config topic and applies the rule.
5. The device reports status and telemetry on its own topics.
6. The Control Service writes the report to SQLite.
The Control Service is the only writer of config. Everything else writes to the
Control Service over HTTP.
## MQTT Has Two Planes
The shared Mosquitto on `.13` has two listeners. State them correctly.
| Plane | Port | Security | Use |
| :--- | :--- | :--- | :--- |
| **Plain** | `1883` | Plain text, anonymous | Legacy and other consumers. Unchanged. |
| **TLS** | `8883` | TLS, per-device credentials, topic ACLs | The Control Service and every kid device. |
On the TLS plane a device reads only its own `restrict/<device>/config` topic. It
writes only its own `restrict/<device>/status` and
`restrict/<device>/telemetry` topics. The Control Service is the only identity
that may publish config. `deploy/mosquitto/` holds the ACL, the accounts and the
verifier.
One caveat: `per_listener_settings true` is deprecated in Mosquitto 2.1 and is
removed in 3.0. Pin the broker image tag, or rework the two planes.
## Enforcement Model (the phone client)
The phone client blocks by **interruption**. It does not suspend an app.
- An **Accessibility Service** detects the foreground app.
- A full-screen **overlay** covers a blocked app.
- **Usage Access** supplies telemetry.
- A device-local **VpnService** filters sites.
The client is **not** a Device Owner. There is no factory reset and no managed
profile. A child can disable the client. That is accepted. The enforcement is the
**tamper alert**: when the Accessibility Service stops, the app is force-stopped,
or the overlay permission is revoked, the client reports the event and Sam gets
an alert (FR-17).
## Fail Safe
The device keeps its last config when it cannot reach the broker (FR-14). An
outage changes nothing. The device caches its config on disk. One shared admin
keycode overrides the state.
## What Is Missing (state this plainly)
**Phase 4, the Windows computer client, is deliberately deferred and NOT built.**
No Python computer client exists in this repository. No Windows process blocking
is implemented or tested. The `docs` and the `README` name this gap on purpose.
Do not describe the computer client as complete.
## Interfaces
| Interface | Shape | Consumer |
| :--- | :--- | :--- |
| **Admin API** | `GET /api/v1/admin/devices`, and `lock`, `unlock`, `grant` and `override` under the same prefix. Bearer token. | The separate project `kotlin_phone_app_admin`. |
| **Hub API** | `GET /capabilities`, read-only `POST /ask`, `POST /notify`. Bearer token. | The Hub. Control never goes through the Hub. |
| **Dashboard** | Session login with a signed cookie and CSRF tokens. | Sam in a browser. |
The admin API shape is small on purpose. Another project consumes it. Keep it
stable and versioned.
## Related
- Build spec and phase checklist: `AGENTS.md` section 11.
- Component names: `SYSTEM_MAP.md`.
- MQTT design and payloads: `TRANSPORT_DESIGN.md`.
- Interactive map: `https://maps.lab.audasmedia.com.au/internet_use_control/docs/`.