sam-4screen-desktop 2026-10-17:6:51:28
This commit is contained in:
141
200 projects/Tools Software WebUI/Central AI Hub.md
Normal file
141
200 projects/Tools Software WebUI/Central AI Hub.md
Normal file
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: Central AI Hub
|
||||
type: project
|
||||
status: active
|
||||
created: "2026-10-10"
|
||||
updated: "2026-09-26"
|
||||
tags:
|
||||
- ai
|
||||
- project
|
||||
- architecture
|
||||
- central
|
||||
- hub
|
||||
- showcase
|
||||
aliases:
|
||||
- The Hub
|
||||
- central_ai_llm_master
|
||||
skills:
|
||||
- service design
|
||||
- intent routing
|
||||
- authorization and approval flows
|
||||
- event-driven integration
|
||||
tools:
|
||||
- OmniRoute
|
||||
- Home Assistant
|
||||
- Jervis
|
||||
- Paperclip
|
||||
- Artemis
|
||||
- Apprise
|
||||
---
|
||||
|
||||
# Central AI Hub — Overview
|
||||
|
||||
## 💡 What is this project?
|
||||
|
||||
One small service that every way in reaches every ability through. The phone app,
|
||||
the house voice (Jervis), chat (dsh), and the admin app all talk to the Hub. The
|
||||
Hub works out what was asked, checks who asked, sends it to the right place, and
|
||||
returns a short reply.
|
||||
|
||||
It exists to stop the same abilities being built three times. Build once. Every
|
||||
way in gets it.
|
||||
|
||||
The Hub does five steps: **hear → understand → check → route → answer**.
|
||||
|
||||
It is **not** a central brain. It holds no personality and no memory. It is
|
||||
**not** Paperclip — it never waits minutes for an answer.
|
||||
|
||||
## 🌟 Key Highlights (Portfolio & Employment)
|
||||
|
||||
- **Concept**: A thin shared router over several AI systems, with one place for
|
||||
safety and approval. Not a monolith.
|
||||
- **Tools & Skills Showcase**: service design, intent routing with an LLM,
|
||||
authorization and tap-to-approve flows, deterministic handling of
|
||||
high-consequence actions, integration across MQTT, Home Assistant, Paperclip,
|
||||
and a local model gateway.
|
||||
- **Practical Value**: One place to add a new ability. One place to control who
|
||||
may do what. The house, the phone, and chat all behave the same.
|
||||
|
||||
## 📐 Architecture & Flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph IN["Ways in"]
|
||||
PHONE["Phone app<br/>wake word + voice"]
|
||||
ADMIN["Admin app<br/>restricted actions"]
|
||||
ESP["ESP32 voice<br/>Hey Jervis"]
|
||||
DSH["dsh chat"]
|
||||
end
|
||||
|
||||
HUB{{"HUB<br/>hear - understand - check - route - answer"}}
|
||||
|
||||
subgraph OUT["Destinations"]
|
||||
HA["Home Assistant"]
|
||||
SPK["Speakers<br/>Jervis TTS"]
|
||||
NET["Internet control"]
|
||||
ART["Artemis<br/>phone screen"]
|
||||
PC["Paperclip<br/>slow jobs"]
|
||||
WEB["Web search"]
|
||||
APP["Apprise / NTFY"]
|
||||
end
|
||||
|
||||
PHONE --> HUB
|
||||
ESP --> HUB
|
||||
DSH --> HUB
|
||||
ADMIN --> HUB
|
||||
HUB --> HA
|
||||
HUB --> SPK
|
||||
HUB --> NET
|
||||
HUB --> ART
|
||||
HUB --> PC
|
||||
HUB --> WEB
|
||||
HUB --> APP
|
||||
PC -. result .-> HUB
|
||||
```
|
||||
|
||||
### The dividing line
|
||||
|
||||
> Does this need a decision, or does it need to happen?
|
||||
|
||||
- **Happen** — fast and certain. Go straight to the destination. No LLM in the
|
||||
action path.
|
||||
- **Decision** — slow, multi-step, worth recording. Send to Paperclip.
|
||||
|
||||
### How it relates to the other projects
|
||||
|
||||
Every other project is a **peer**, not a sub-project. Each has its own folder,
|
||||
repo, port, interface, and build. Each works without the Hub. The Hub is an
|
||||
**extra** way in.
|
||||
|
||||
- The **Hub asks** a project ("what does Harry have on today?") using one small
|
||||
contract, `/ask`. The project answers about its own data.
|
||||
- A **project tells** the Hub something ("overdue homework found").
|
||||
- **n8n triggers** the project (scan the inbox, scan the school).
|
||||
- **High-consequence control** (cut the kids' internet) does **not** go through
|
||||
the Hub. The admin app calls the internet control service directly, with
|
||||
confirmation on the phone.
|
||||
|
||||
### Safety
|
||||
|
||||
- Voice is shared and has no identity. Anyone in the house can speak.
|
||||
- The admin app is the only trusted door for restricted actions.
|
||||
- A spoken keycode is not the lock. Voice may ask; the admin app confirms with
|
||||
"Did you ask for this?".
|
||||
|
||||
## 🔗 Related Notes & Links
|
||||
|
||||
- Gitea Repo: https://gitea.lab.audasmedia.com.au/sam/central_ai_llm_master
|
||||
- Interactive Map: [Archify Map](https://maps.lab.audasmedia.com.au/central_ai_llm_master/docs/)
|
||||
- AI Context (Outline): https://outline.lab.audasmedia.com.au/collection/central-ai-hub-fYfUzsMooS
|
||||
- Contract: `/ask` — see `docs/ask-contract.md` in the repo.
|
||||
- Local path: `/home/sam/paseo/projects/central_ai_llm_master/`
|
||||
- Related: [[Home Voice Assistant System]] · [[Family Home Lab]] · [[Artemis on GrapheneOS Pixel Mobile]] · [[Front Door Cam]]
|
||||
|
||||
<!--
|
||||
NOTES FOR THE AGENT WRITING THIS NOTE
|
||||
* `type: note` is intentional — this note is written into the INBOX and the
|
||||
obsidian-sorter assigns the real type from its final folder.
|
||||
* Keep `skills:` and `tools:` — they are custom fields the sorter preserves.
|
||||
* Do NOT add a `type` other than `note`, and do NOT choose a folder.
|
||||
* Add the `project` tag so the sorter constrains it to the projects bucket.
|
||||
-->
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
title: "Compass NHS — Harry and Finn's School Service"
|
||||
type: project
|
||||
status: active
|
||||
created: "2026-10-15 20:00"
|
||||
updated: "2026-09-26"
|
||||
tags:
|
||||
- project
|
||||
- family
|
||||
- architecture
|
||||
- go
|
||||
- compass
|
||||
- finn
|
||||
- school
|
||||
- service
|
||||
- sqlite
|
||||
- htmx
|
||||
- playwright
|
||||
- apprise
|
||||
aliases:
|
||||
- Compass NHS
|
||||
- School Service
|
||||
skills:
|
||||
- Go service with no heavy framework
|
||||
- SQLite data modelling with versioned migrations
|
||||
- HTMX server-rendered dashboard with no build step
|
||||
- Headless browser automation (patchright) past a Cloudflare challenge
|
||||
- HTML parsing into structured items
|
||||
- Read-only HTTP contract for another service (the Hub)
|
||||
- Docker and Caddy deployment
|
||||
- n8n scheduling with a restricted SSH trigger
|
||||
tools:
|
||||
- Go
|
||||
- SQLite
|
||||
- HTMX
|
||||
- patchright (headless Playwright)
|
||||
- Docker
|
||||
- Caddy
|
||||
- n8n
|
||||
- Apprise
|
||||
- Home Assistant
|
||||
- OmniRoute
|
||||
---
|
||||
|
||||
# [[Compass NHS — Harry and Finn's School Service]]
|
||||
|
||||
## What is this project?
|
||||
|
||||
This project watches the school for Harry and Finn. Each morning it reads the
|
||||
school system, Compass, and works out what each boy has due. It shows Sam one
|
||||
page with what is overdue first. It then sends each boy his own short brief, and
|
||||
one combined brief to Jo and Sam.
|
||||
|
||||
The point is simple. Nobody has to log into Compass in the morning. The family
|
||||
learns about late work **before** it is late, not after.
|
||||
|
||||
## What it does
|
||||
|
||||
- **Reads Compass** for both children, twice a day apart or on demand.
|
||||
- **Stores every item**: homework, tasks, notices and school events, each against
|
||||
the right child.
|
||||
- **Finds overdue work** and puts it first. Then due today, then due this week.
|
||||
- **Shows a dashboard** with one tab per child. It works on a phone.
|
||||
- **Writes important school events** to the Home Assistant calendar
|
||||
`calendar.school`.
|
||||
- **Sends the morning briefs** at 6:00am on Email and WhatsApp.
|
||||
- **Answers the Hub** to a question such as "what does Harry have on today at
|
||||
school?" That path is read-only.
|
||||
|
||||
## Why it matters (what it shows)
|
||||
|
||||
This is a small but complete home-lab product, not a script. The service is one
|
||||
Go binary with SQLite. It has its own container, its own port, its own login and
|
||||
its own Caddy route. It is read-only against the school: it logs in and reads,
|
||||
and it never posts or messages.
|
||||
|
||||
The interesting engineering part is the login. Compass sits behind **Cloudflare**,
|
||||
and the login form is protected by a managed bot challenge. A normal headless
|
||||
browser gets a 403. The project uses **patchright**, a headless Playwright build
|
||||
that behaves enough like a real browser to pass the challenge. The parent login
|
||||
needed **no** two-factor code.
|
||||
|
||||
The other deliberate design is honesty about failure. A failed scan must never
|
||||
look like a quiet day with no homework. The dashboard, the briefs and the Hub
|
||||
answer all state the real scan state in plain words.
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
N8N["n8n on .13<br/>06:00 daily trigger"] --> SVC["Compass / NHS service<br/>Go + SQLite :8792"]
|
||||
SAM["Sam<br/>browser dashboard"] --> CADDY["Caddy on .35"] --> SVC
|
||||
SVC -->|scan| PATCH["patchright scraper"] -->|login + pages| COMPASS["Compass NHS<br/>read-only"]
|
||||
SVC -->|"create event"| HA["Home Assistant<br/>calendar.school"]
|
||||
SVC -->|briefs| APPRISE["Apprise .35:8210<br/>Email + WhatsApp"]
|
||||
APPRISE --> BOYS["Harry and Finn<br/>per-boy brief"]
|
||||
APPRISE --> PARENTS["Jo and Sam<br/>combined brief"]
|
||||
HUB["Hub :8788<br/>read-only /ask"] --> SVC
|
||||
```
|
||||
|
||||
## What is still missing (state it plainly)
|
||||
|
||||
**Teams (FR-15) is DEFERRED.** The project does not scan Teams for homework. This
|
||||
is a known gap that the brief set aside on purpose. Everything else in the build
|
||||
spec is built, deployed and running. Compass alone already answers what is due
|
||||
and overdue.
|
||||
|
||||
## Where it lives
|
||||
|
||||
- **Code**: Gitea repo `sam/compass_teams_nhs` (`main`).
|
||||
- **Live**: <https://school.lab.audasmedia.com.au> — its own container on `.13`,
|
||||
port 8792, behind Caddy on `.35`.
|
||||
- **Interactive map**:
|
||||
<https://maps.lab.audasmedia.com.au/compass_teams_nhs/docs/>
|
||||
- **AI context**: `docs/outline/` in the repo, and the Outline collection
|
||||
*Compass / NHS (School)*.
|
||||
- **Tasks**: Vikunja project **Compass / NHS (School)** (id 21).
|
||||
- **Diagram source**: `docs/architecture.mmd`, rendered to
|
||||
`docs/diagrams/architecture.png`.
|
||||
|
||||
## Status
|
||||
|
||||
Built and deployed. Phases 1 to 9 are done. Teams (FR-15) is deferred. The service
|
||||
scans both children, shows overdue work first, writes important events to the
|
||||
calendar, and sends the briefs every morning at 6:00am.
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
title: Email Agent — Family Inbox Triage
|
||||
type: project
|
||||
status: active
|
||||
created: "2026-10-13 10:45"
|
||||
updated: "2026-09-26"
|
||||
tags:
|
||||
- tool
|
||||
- project
|
||||
- email
|
||||
- family
|
||||
- architecture
|
||||
- go
|
||||
- inbox
|
||||
- triage
|
||||
- gmail
|
||||
- htmx
|
||||
aliases:
|
||||
- Email Agent
|
||||
- Family Inbox Triage
|
||||
skills:
|
||||
- Go backend development
|
||||
- HTMX server-rendered UI
|
||||
- IMAP and SMTP integration
|
||||
- LLM classification (JEV) and drafting (OmniRoute)
|
||||
- SQLite data modelling
|
||||
- Docker and Caddy deployment
|
||||
tools:
|
||||
- Go
|
||||
- HTMX
|
||||
- SQLite
|
||||
- Gmail IMAP/SMTP
|
||||
- JEV (TypeSafe System One)
|
||||
- OmniRoute
|
||||
- Apprise
|
||||
- Docker
|
||||
- Caddy
|
||||
---
|
||||
|
||||
# [[Email Agent — Family Inbox Triage]]
|
||||
|
||||
## What is this project?
|
||||
|
||||
One page that clears the family inbox. All family mail lands in a single Gmail
|
||||
account, because PurelyMail forwards every domain address there. This app reads
|
||||
that mail, sorts it into categories, recommends what to do, and lets Sam act on
|
||||
whole groups at once.
|
||||
|
||||
The goal is simple: Sam opens one page, spends a few minutes, and knows that
|
||||
nothing important was missed.
|
||||
|
||||
## What it does
|
||||
|
||||
- **Reads Gmail** over IMAP with an app password. It forces IPv4, because IPv6
|
||||
to Gmail is broken from the server.
|
||||
- **Classifies every message** with JEV (a TypeSafe System One model). Each mail
|
||||
gets a category, an importance, a suggested action, and a confidence.
|
||||
- **Shows a triage list** grouped by category, with the recommended action on
|
||||
every row and a bulk select.
|
||||
- **Acts in bulk**: delete, move, or mark. Deletes are recoverable — the app
|
||||
moves mail to a Delete label, never hard-deletes.
|
||||
- **Drafts replies** with an LLM through OmniRoute, from a template or a rule.
|
||||
Sam edits the draft, then sends. It sends as the address the mail arrived at,
|
||||
and there is no auto-send.
|
||||
- **Spotlights unsubscribe links** and keeps an ignore list. It never follows a
|
||||
link by itself.
|
||||
- **Has a rules editor** — plain text, saved and versioned. The classifier obeys
|
||||
the rules.
|
||||
- **Sends a daily summary** by email through Apprise.
|
||||
- **Answers the Hub**: a read-only question like "anything important in my
|
||||
inbox?" returns a short answer.
|
||||
|
||||
## Why it matters (what it shows)
|
||||
|
||||
This is an end-to-end private AI tool, built and run in the home lab. It shows a
|
||||
full path from an idea to a deployed service: a Go backend with no heavyweight
|
||||
framework, an HTMX interface with no build step, a small SQLite store, real
|
||||
mail-server protocols (IMAP and SMTP with an app password), two different model
|
||||
paths (JEV for typed judgement, OmniRoute for text), and a strict "the human
|
||||
confirms every action" design.
|
||||
|
||||
The design keeps the risky actions safe: no auto-send, no auto-delete, every
|
||||
action logged, and deletes recoverable.
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
SAM["Sam<br/>phone or desktop"] --> CADDY["Caddy on .35"]
|
||||
CADDY --> UI["HTMX dashboard<br/>:8790"]
|
||||
UI --> DB[("SQLite")]
|
||||
UI --> GMAIL["Gmail<br/>IMAP + SMTP, IPv4"]
|
||||
UI --> JEV["JEV<br/>classify"]
|
||||
UI --> OMNI["OmniRoute<br/>draft reply"]
|
||||
UI --> APPRISE["Apprise<br/>summary email"]
|
||||
HUB["Central AI Hub :8788"] --> API["Hub API<br/>/ask /capabilities"]
|
||||
API --> DB
|
||||
N8N["n8n schedule"] --> JOBS["CLI jobs"]
|
||||
JOBS --> DB
|
||||
```
|
||||
|
||||
## Where it lives
|
||||
|
||||
- **Code**: Gitea repo `sam/email_agent`.
|
||||
- **Live**: `https://mail.lab.audasmedia.com.au` (container on `.13`, port 8790).
|
||||
- **Interactive map**: https://maps.lab.audasmedia.com.au/email_agent/docs/
|
||||
- **AI context**: Outline collection `Email Agent`.
|
||||
- **Tasks**: Vikunja project `Email Agent`.
|
||||
|
||||
## Status
|
||||
|
||||
Built and deployed. Phases 1 to 7 of the build spec are done and running. The
|
||||
Phase 8 documentation pass wrote this note, the Gitea README and docs, the
|
||||
Outline collection, the Vikunja board, and the architecture map.
|
||||
66
200 projects/Tools Software WebUI/Graphify.md
Normal file
66
200 projects/Tools Software WebUI/Graphify.md
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: Graphify
|
||||
type: project
|
||||
status: active
|
||||
created: "2026-10-13"
|
||||
updated: "2026-09-26"
|
||||
tags:
|
||||
- project
|
||||
- ai-agents
|
||||
- architecture
|
||||
- obsidian
|
||||
- graphify
|
||||
- tool
|
||||
- knowledge-graph
|
||||
- pi-agent
|
||||
- showcase
|
||||
skills:
|
||||
- python
|
||||
- knowledge-graphs
|
||||
- mcp
|
||||
- subagent-orchestration
|
||||
- graph-analytics
|
||||
tools:
|
||||
- graphify (graphifyy)
|
||||
- pi-graphify
|
||||
- mcp
|
||||
- networkx
|
||||
---
|
||||
|
||||
# Graphify — Overview
|
||||
|
||||
## 💡 What is this project?
|
||||
|
||||
Graphify turns a folder of files into a knowledge graph. It reads the files, finds
|
||||
concepts, and links them. The graph answers questions that cross many files.
|
||||
|
||||
I run it on my Obsidian vault. The graph holds 2,171 nodes and 2,770 edges across
|
||||
128 communities. An AI agent reads the graph instead of all 134 notes.
|
||||
|
||||
## 🌟 Key Highlights (Portfolio & Employment)
|
||||
|
||||
- **Concept**: A persistent knowledge graph with an honest audit trail. Every link is tagged EXTRACTED, INFERRED, or AMBIGUOUS.
|
||||
- **Tools & Skills Showcase**: Python, NetworkX community detection, an MCP server, pi extension tools, and subagent orchestration for semantic extraction.
|
||||
- **Practical Value**: One query reads the graph instead of 134 files. The measured cost is 31 times fewer tokens per query.
|
||||
|
||||
## 📐 Architecture & Flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Obsidian vault<br/>134 notes"] --> B["detect + chunk"]
|
||||
B --> C["semantic extraction<br/>pi subagents"]
|
||||
C --> D["graph.json<br/>2171 nodes / 2770 edges"]
|
||||
D --> E["cluster + analyze"]
|
||||
E --> F["GRAPH_REPORT.md"]
|
||||
E --> G["graph.html"]
|
||||
D --> H["MCP server<br/>graphify-vault"]
|
||||
H --> I["AI agents<br/>query_graph"]
|
||||
```
|
||||
|
||||
## 🔗 Related Notes & Links
|
||||
|
||||
- **Graph data**: `/home/sam/graphify/obsidian-vault/graph.json`
|
||||
- **Interactive HTML**: `/home/sam/graphify/obsidian-vault/graph.html`
|
||||
- **Report**: `/home/sam/graphify/obsidian-vault/GRAPH_REPORT.md`
|
||||
- **Interface**: MCP server `graphify-vault` (query from any folder), plus CLI and pi tools.
|
||||
- **AI Context (Outline)**: collection `Graphify`
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: "Internet Use Control — Kids' Screen Time Limits"
|
||||
type: project
|
||||
status: active
|
||||
created: "2026-10-14 12:12"
|
||||
updated: "2026-09-26"
|
||||
tags:
|
||||
- project
|
||||
- family
|
||||
- architecture
|
||||
- go
|
||||
- kids
|
||||
- time
|
||||
- internet-control
|
||||
- mqtt
|
||||
- android
|
||||
- sqlite
|
||||
- htmx
|
||||
aliases:
|
||||
- Internet Use Control
|
||||
- Kids Screen Time
|
||||
skills:
|
||||
- Go backend development
|
||||
- HTMX server-rendered dashboard UI
|
||||
- SQLite data modelling and versioned migrations
|
||||
- MQTT transport with TLS and per-device topic ACLs
|
||||
- Android Accessibility Service and full-screen overlay (Kotlin)
|
||||
- Android VpnService for device-local site filtering
|
||||
- Versioned HTTP API design for a separate consumer
|
||||
- Docker and Caddy deployment
|
||||
tools:
|
||||
- Go
|
||||
- SQLite
|
||||
- HTMX
|
||||
- Mosquitto
|
||||
- Docker
|
||||
- Caddy
|
||||
- Apprise
|
||||
- Kotlin
|
||||
- Android Accessibility Service
|
||||
- Android VpnService
|
||||
---
|
||||
|
||||
# [[Internet Use Control — Kids' Screen Time Limits]]
|
||||
|
||||
## What is this project?
|
||||
|
||||
This project limits screen time on the children's own devices. Harry's phone and
|
||||
Finn's computer should follow their weekly schedule with nobody touching them. Sam
|
||||
sees their usage on one page, and Sam changes a limit from his phone in seconds.
|
||||
|
||||
The rules apply to the kids' devices only. Nothing changes for the rest of the
|
||||
house. There is no router change, no Pi-hole and no DNS change.
|
||||
|
||||
The main piece is the **Control Service**. It runs on `.13` in Docker. It holds the
|
||||
schedules, the block lists, the allow lists and the usage in SQLite. It serves a
|
||||
small web dashboard. It is the one place that writes the rules.
|
||||
|
||||
A device gets its rules over **MQTT**. The Control Service publishes the wanted
|
||||
state for each device as a *retained* message, so a phone that reconnects is
|
||||
limited again at once. The device also sends its status and its usage back over
|
||||
MQTT. If a device cannot reach the broker, it keeps its last rules.
|
||||
|
||||
## What it does
|
||||
|
||||
- **Weekly schedules.** A grid per device, Monday to Sunday. A window means the
|
||||
rules are on. A window can cross midnight.
|
||||
- **Block lists.** An app (Android package name) or a site (hostname).
|
||||
- **Allow lists.** Spotify at night, school sites. The device blocks everything
|
||||
on the block list **except** the allow list.
|
||||
- **Usage.** The dashboard shows a week per device: the daily total, the top apps
|
||||
and the top sites.
|
||||
- **Overrides.** A versioned HTTP API for the admin app (`lock`, `unlock`,
|
||||
`grant`), plus one shared keycode that a child can type on the device for a
|
||||
short exemption.
|
||||
- **Alerts.** Apprise tells Sam when a limit is reached or a device is offline
|
||||
too long.
|
||||
- **A Hub answer.** The family Hub can ask "how long have the kids been on
|
||||
screens today?" and gets a real answer. That question path is read-only.
|
||||
|
||||
## Why it matters (what it shows)
|
||||
|
||||
This is a full home-lab product, not a script. It shows a Go service with no
|
||||
heavy framework, an HTMX dashboard with no build step, a small SQLite store with
|
||||
versioned migrations, real MQTT with TLS, per-device accounts and topic access
|
||||
control, and a versioned API that another project consumes.
|
||||
|
||||
The Android side is the interesting part. **Device Owner was rejected**, because
|
||||
it needs a factory reset of the children's phones. Instead the phone blocks by
|
||||
**interruption**: an Accessibility Service watches the foreground app, and a
|
||||
full-screen overlay covers a blocked app. The child **can** disable it, and that
|
||||
is accepted. The real enforcement is the **tamper alert**: when the Accessibility
|
||||
Service stops, the app is force-stopped, or the overlay permission is removed,
|
||||
the phone reports it and Sam gets an alert. Site filtering uses a device-local
|
||||
`VpnService`. There is no wipe, no Device Owner and no managed profile.
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
SAM["Sam<br/>browser dashboard"] --> CADDY["Caddy on .35"]
|
||||
CADDY --> CS["Control Service<br/>Go + SQLite :8791"]
|
||||
ADMIN["Admin app"] -->|"/api/v1"| CS
|
||||
HUB["Hub"] -->|"read-only /ask"| CS
|
||||
CS -->|"retained config"| MQ["Mosquitto on .13<br/>8883 TLS + topic ACLs"]
|
||||
MQ -->|"own config topic"| PHONE["Kids' Android client<br/>Kotlin"]
|
||||
PHONE -->|"status + telemetry"| MQ
|
||||
MQ -->|reports| CS
|
||||
CS --> APPRISE["Apprise<br/>alerts + tamper"]
|
||||
```
|
||||
|
||||
A picture of the two MQTT planes: port **1883** stays plain and anonymous for
|
||||
legacy consumers, and port **8883** is TLS with per-device credentials and topic
|
||||
ACLs. A device on 8883 may read only its own config topic and write only its own
|
||||
status and telemetry topics. Without that rule a child could publish a fake
|
||||
"unlocked".
|
||||
|
||||
## What is still missing (state it plainly)
|
||||
|
||||
**The Phase 4 Windows computer client is deliberately deferred and is not
|
||||
built.** There is no Python client and no process blocking on a computer. The
|
||||
project stands at **9 of 10** phases for that single reason. Everything else in
|
||||
the build spec is done and running.
|
||||
|
||||
## Where it lives
|
||||
|
||||
- **Code**: Gitea repo `sam/internet_use_control`.
|
||||
- **Live**: <https://webrestrict.lab.audasmedia.com.au> (container on `.13`, port
|
||||
8791, behind Caddy on `.35`).
|
||||
- **Interactive map**: <https://maps.lab.audasmedia.com.au/internet_use_control/docs/>
|
||||
- **AI context**: `docs/outline/` in the repo (00-index and four documents).
|
||||
- **Tasks**: Vikunja project **Internet Use Control** (id 20).
|
||||
- **Diagram source**: `docs/architecture.mmd`, rendered to
|
||||
`docs/diagrams/architecture.png`.
|
||||
|
||||
## Status
|
||||
|
||||
Built and deployed. Phases 1, 2, 3, 5, 6, 7, 8, 9 and 10 are done. The phones
|
||||
are limited by the Android client. Only the Windows client (Phase 4) remains, and
|
||||
it is deferred on purpose.
|
||||
Reference in New Issue
Block a user