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>
This commit is contained in:
47
docs/outline/00-index.md
Normal file
47
docs/outline/00-index.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Internet Use Control — AI Document Index
|
||||
|
||||
> **Target**: AI agents.
|
||||
> **Writing style**: ASD-STE100 Simplified Technical English (`ste-writing`).
|
||||
|
||||
## Document Catalog (inject the exact file)
|
||||
|
||||
Read this index. Then inject only the file that you need. Do not search all files.
|
||||
|
||||
| Document Title | Path | Scope / Description |
|
||||
| :--- | :--- | :--- |
|
||||
| **System Overview** | `docs/outline/01-system-overview.md` | States the purpose, the components, the MQTT planes and the missing Phase 4 client. |
|
||||
| **Configuration and Env** | `docs/outline/02-config-and-env.md` | Lists the environment variables, the config files, the ports and the secrets. |
|
||||
| **Code Map** | `docs/outline/03-code-map.md` | Shows the folder tree, the entry points and the Go dependencies. |
|
||||
| **Agent Runbook** | `docs/outline/04-agent-runbook.md` | Gives the commands to build, test, deploy, verify and resume work. |
|
||||
|
||||
## Source Documents (read before the outline)
|
||||
|
||||
| Document | Path | Scope |
|
||||
| :--- | :--- | :--- |
|
||||
| **Build spec** | `AGENTS.md` | The phases and the definition of done. Section 11 holds the phase checklist. |
|
||||
| **System map** | `SYSTEM_MAP.md` | Names every component and states where the truth lives. |
|
||||
| **Transport design** | `TRANSPORT_DESIGN.md` | The MQTT topics, the payloads, the security rules and the fail-safe rule. |
|
||||
| **README** | `README.md` | The technical reference. Setup, endpoints, payloads and verification. |
|
||||
|
||||
## System Summary
|
||||
|
||||
The Control Service limits the screen use of two children. It holds weekly
|
||||
schedules, blocklists, allowlists and usage in SQLite. It publishes the desired
|
||||
state of each device to MQTT with the retained flag. It serves an HTMX dashboard,
|
||||
a versioned admin API and a read-only Hub API.
|
||||
|
||||
## Core Configuration
|
||||
|
||||
- **Env file**: `environment.d/control-service.env` (gitignored).
|
||||
- **Template**: `environment.d/control-service.env.example`.
|
||||
- **Live port**: `8791` on `.13`.
|
||||
- **Public URL**: `https://webrestrict.lab.audasmedia.com.au`.
|
||||
- **State**: SQLite at `/data/control.db` inside the container.
|
||||
|
||||
## Agent Restart Steps
|
||||
|
||||
1. Read the Document Catalog above. Inject only the required file.
|
||||
2. Read `AGENTS.md` section 11. Confirm the phase checklist.
|
||||
3. Check the tree state: `git status`.
|
||||
4. Check the recent commits: `git log -n 5 --oneline`.
|
||||
5. Run the test suite: `make test`.
|
||||
97
docs/outline/01-system-overview.md
Normal file
97
docs/outline/01-system-overview.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# 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/`.
|
||||
92
docs/outline/02-config-and-env.md
Normal file
92
docs/outline/02-config-and-env.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Internet Use Control — Configuration and Environment
|
||||
|
||||
> **Target**: AI agents. **Writing style**: ASD-STE100 Simplified Technical English.
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Status | Purpose |
|
||||
| :--- | :--- | :--- |
|
||||
| `environment.d/control-service.env` | Live, gitignored | The real values for the container. |
|
||||
| `environment.d/control-service.env.example` | In git | The template. Copy it and set the values. |
|
||||
| `docker-compose.yml` | In git | The container, the port and the env file path. |
|
||||
| `deploy/mosquitto/conf.d/webrestrict.conf` | In git | The TLS listener, the password file and the ACL file. |
|
||||
| `deploy/mosquitto/conf.d/webrestrict.acl` | In git | The per-device topic ACL. |
|
||||
| `deploy/mosquitto/clients.env` | In git | The client names for the verifier. No secrets. |
|
||||
| `deploy/caddy/webrestrict.caddy` | In git | The vhost on `.35`. |
|
||||
|
||||
Secrets come from `environment.d` or from
|
||||
`~/.config/environment.d/10-secrets.conf`. The service reads only the process
|
||||
environment. No secret is in the repository.
|
||||
|
||||
## Ports and Addresses
|
||||
|
||||
| Item | Value |
|
||||
| :--- | :--- |
|
||||
| Control Service | `8791` on `.13` |
|
||||
| Public URL | `https://webrestrict.lab.audasmedia.com.au` (Caddy on `.35`) |
|
||||
| MQTT plain plane | `1883` on `.13`, anonymous |
|
||||
| MQTT TLS plane | `8883` on `.13`, credentials and ACLs |
|
||||
| Apprise | `8210` on `.35` |
|
||||
| Hub | `8788` on `.13` |
|
||||
| Database | `/data/control.db` inside the container |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| :--- | :--- | :--- |
|
||||
| `CONTROL_ADDR` | `:8791` | Listen address. |
|
||||
| `CONTROL_DB_PATH` | `/data/control.db` | SQLite file. |
|
||||
| `CONTROL_SESSION_SECRET` | required | Signs the session cookie. 16 characters minimum. |
|
||||
| `CONTROL_SESSION_TTL` | `12h` | Session lifetime. |
|
||||
| `CONTROL_COOKIE_SECURE` | `true` | Secure cookie flag. Keep it true behind HTTPS. |
|
||||
| `CONTROL_ADMIN_USERNAME` | `sam` | Dashboard login name. |
|
||||
| `CONTROL_ADMIN_PASSWORD` | — | Plaintext password, option A. |
|
||||
| `CONTROL_ADMIN_PASSWORD_HASH` | — | bcrypt hash, option B, preferred. |
|
||||
| `CONTROL_ADMIN_API_TOKEN` | — | Bearer token for the versioned admin API. Empty answers `503`. |
|
||||
| `CONTROL_DEVICE_KEYCODE_HASH` | — | bcrypt hash of the shared device keycode. Seeds SQLite at start-up. |
|
||||
| `CONTROL_APP_ENV` | `production` | Label in the footer. |
|
||||
| `CONTROL_LOG_LEVEL` | `info` | `debug`, `info`, `warn` or `error`. |
|
||||
| `CONTROL_TIMEZONE` | `Australia/Sydney` | IANA zone for the weekly windows. |
|
||||
| `CONTROL_MQTT_ENABLED` | `true` | Turn the broker link on or off. |
|
||||
| `CONTROL_MQTT_BROKER` | `tcp://host.docker.internal:1883` | Broker URL. The live value is `tls://host.docker.internal:8883`. |
|
||||
| `CONTROL_MQTT_CLIENT_ID` | `control-service` | MQTT client id. |
|
||||
| `CONTROL_MQTT_USERNAME` | — | The Control Service broker account. |
|
||||
| `CONTROL_MQTT_PASSWORD` | — | Its password. |
|
||||
| `CONTROL_MQTT_CA_FILE` | `/etc/webrestrict/tls/ca.crt` | PEM bundle that verifies the broker. TLS only. |
|
||||
| `CONTROL_MQTT_INSECURE` | `false` | Allow a plaintext broker with no credentials. The live value is `false`. |
|
||||
| `CONTROL_HUB_TOKEN` | — | Bearer token for `/capabilities`, `/ask` and `/notify`. Empty answers `503`. |
|
||||
| `CONTROL_APPRISE_URL` | `http://192.168.20.35:8210` | The house Apprise API. |
|
||||
| `CONTROL_APPRISE_KEY` | — | Stored Apprise configuration key, option A. |
|
||||
| `CONTROL_APPRISE_URLS` | — | Stateless Apprise destination list, option B. The lab default. |
|
||||
| `CONTROL_APPRISE_TOKEN` | — | Optional bearer token for a protected Apprise API. |
|
||||
| `CONTROL_ALERTS_ENABLED` | `true` | Turn the alert engine on or off. |
|
||||
| `CONTROL_ALERT_OFFLINE_AFTER` | `30m` | Time before an offline device raises an alert. |
|
||||
| `CONTROL_ALERT_INTERVAL` | `30s` | How often the alert engine re-evaluates the devices. |
|
||||
|
||||
The service refuses a non-TLS broker unless `CONTROL_MQTT_INSECURE=true`
|
||||
(AGENTS.md section 10, rule 6). The live deployment does not use that escape
|
||||
hatch.
|
||||
|
||||
## Secrets
|
||||
|
||||
| Secret | Where it lives | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| Dashboard password | `CONTROL_ADMIN_PASSWORD_HASH` | bcrypt. Preferred over the plaintext form. |
|
||||
| Admin API token | `CONTROL_ADMIN_API_TOKEN` | A bearer token. Separate from the session login. |
|
||||
| Hub token | `CONTROL_HUB_TOKEN` | A bearer token. Separate from the admin token. |
|
||||
| Device keycode | SQLite, bcrypt hash | One code for every device. Seeded from `CONTROL_DEVICE_KEYCODE_HASH`. |
|
||||
| MQTT accounts | Mosquitto password file | One account per device plus `control-service`. |
|
||||
|
||||
## Commands That Read or Change Configuration
|
||||
|
||||
```bash
|
||||
# Generate a bcrypt hash without a host Go toolchain.
|
||||
docker run --rm --entrypoint /app/control webrestrict/control:0.7.0-phase9 \
|
||||
hash-password 'your-password'
|
||||
|
||||
# Set the shared device keycode. The code comes from stdin.
|
||||
docker exec -i webrestrict-control /app/control keycode <<< '246810'
|
||||
|
||||
# Print the MQTT identity of every device. Tokens only, no secrets.
|
||||
docker exec webrestrict-control /app/control mqtt-clients
|
||||
```
|
||||
117
docs/outline/03-code-map.md
Normal file
117
docs/outline/03-code-map.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Internet Use Control — Code Map
|
||||
|
||||
> **Target**: AI agents. **Writing style**: ASD-STE100 Simplified Technical English.
|
||||
|
||||
## Module
|
||||
|
||||
`gitea.lab.audasmedia.com.au/sam/internet_use_control`, Go 1.25. The image is
|
||||
CGO-free. SQLite is the pure-Go `modernc.org/sqlite` driver.
|
||||
|
||||
## Folder Tree
|
||||
|
||||
```
|
||||
cmd/control/main.go entry point and subcommands
|
||||
internal/config/ environment configuration and validation
|
||||
internal/auth/ signed-cookie session login and CSRF
|
||||
internal/store/ SQLite: open, migrations, queries
|
||||
store.go connection, migration runner, maintenance loop
|
||||
devices.go device registry and desired state
|
||||
schedules.go weekly windows and the effective state
|
||||
lists.go block and allow lists
|
||||
reports.go presence, telemetry, the daily rollup
|
||||
overrides.go override history and the device keycode
|
||||
alerts.go alert records and per-device dedup state
|
||||
migrations/001_init.sql … 005_alerts.sql
|
||||
internal/mqtt/
|
||||
link.go paho client, subscriptions, publish, TLS
|
||||
payload.go the topic and payload contract for the clients
|
||||
internal/alert/alert.go the limit and offline alert engine
|
||||
internal/apprise/apprise.go the Apprise API client
|
||||
internal/hub/ the Hub contract: capabilities, answers, notify
|
||||
internal/web/
|
||||
server.go routes, middleware, session
|
||||
devices.go the device registry and manual lock/unlock
|
||||
schedules.go the weekly schedule and list editors
|
||||
usage.go the usage screen
|
||||
admin_api.go the versioned admin API and the keycode endpoint
|
||||
hub_api.go /capabilities, /ask, /notify
|
||||
templates/ login, dashboard, editors, usage, partials
|
||||
static/ tokens.css, app.css, theme.js, htmx, fonts
|
||||
android/ the kids' Android client (Gradle, Kotlin)
|
||||
app/src/main/java/au/audasmedia/webrestrict/kids/
|
||||
KidsApp.kt application class
|
||||
MainActivity.kt the kid's status screen
|
||||
BlockAccessibilityService.kt foreground app detection
|
||||
OverlayController.kt the full-screen block overlay
|
||||
BlockEngine.kt the block decision
|
||||
DeviceConfig.kt the config payload model
|
||||
MqttController.kt the broker link
|
||||
TamperReporter.kt the FR-17 tamper report
|
||||
UsageCollector.kt Usage Access telemetry
|
||||
TelemetryReporter.kt telemetry publish
|
||||
SiteFilterVpnService.kt the device-local VpnService
|
||||
SiteFilter.kt the site decision
|
||||
DnsMessage.kt DNS parsing
|
||||
IpPacket.kt IP packet parsing
|
||||
AppPrefs.kt the cached config on disk
|
||||
BootReceiver.kt start after boot
|
||||
TelemetryStore.kt local telemetry buffer
|
||||
tools/emu-proof.sh headless emulator proof
|
||||
deploy/caddy/ the vhost on .35
|
||||
deploy/mosquitto/ the TLS listener, the accounts, the ACL, the verifier
|
||||
deploy/verify-phase8.sh the lock latency proof
|
||||
deploy/verify-phase9.sh the Hub and alert proof
|
||||
docs/ this documentation set
|
||||
```
|
||||
|
||||
## Entry Point
|
||||
|
||||
`cmd/control/main.go` starts the web server. It also holds the subcommands:
|
||||
|
||||
| Subcommand | Purpose |
|
||||
| :--- | :--- |
|
||||
| `hash-password` | Make a bcrypt hash for a password. |
|
||||
| `mqtt-clients` | Print the MQTT identity of every device. |
|
||||
| `rollup` | Rebuild the daily telemetry rollup. |
|
||||
| `keycode` | Set or generate the shared device keycode. |
|
||||
| `alerts` | Print recent alerts. |
|
||||
| `usage` | Print usage from the database. |
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Module | Use |
|
||||
| :--- | :--- |
|
||||
| `github.com/eclipse/paho.mqtt.golang` | The MQTT client. |
|
||||
| `modernc.org/sqlite` | The pure-Go SQLite driver. No CGO. |
|
||||
| `golang.org/x/crypto` | bcrypt for the password and the keycode hashes. |
|
||||
|
||||
The web layer uses the Go standard library only. The UI uses HTMX 2.0.4,
|
||||
vendored under `internal/web/static/`.
|
||||
|
||||
## Database Migrations
|
||||
|
||||
| File | Change |
|
||||
| :--- | :--- |
|
||||
| `001_init.sql` | Devices, schedules, lists, state, telemetry, overrides, audit. |
|
||||
| `002_telemetry_unique.sql` | One telemetry row per (device, day, app, domain). |
|
||||
| `003_usage_rollup.sql` | The daily rollup table. |
|
||||
| `004_overrides_grant.sql` | The grant column and the override history. |
|
||||
| `005_alerts.sql` | The alerts table and the dedup state. |
|
||||
|
||||
Migrations apply in order at start-up. Never hard-delete a device or its history
|
||||
(AGENTS.md section 10, rule 10).
|
||||
|
||||
## Android Client
|
||||
|
||||
The client is a normal Gradle project with its own `gradlew`. The block path is
|
||||
the Accessibility Service plus the overlay. The site path is the local
|
||||
`VpnService`. The tamper path is `TamperReporter.kt`. The client keeps the last
|
||||
config in `AppPrefs.kt`. There is no Device Owner and no managed profile.
|
||||
|
||||
## Known Gaps in the Code
|
||||
|
||||
- **Phase 4, the Windows computer client, does not exist.** No Python client and
|
||||
no process blocking are in the tree.
|
||||
- The MQTT `cmd` and `ack` topics are design only. No code uses them.
|
||||
- The phone client reports telemetry from Usage Access. Site filtering uses the
|
||||
local `VpnService`.
|
||||
100
docs/outline/04-agent-runbook.md
Normal file
100
docs/outline/04-agent-runbook.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Internet Use Control — Agent Runbook
|
||||
|
||||
> **Target**: AI agents. **Writing style**: ASD-STE100 Simplified Technical English.
|
||||
|
||||
## Before You Start
|
||||
|
||||
1. Read `docs/outline/00-index.md`. Inject only the file that you need.
|
||||
2. Read `AGENTS.md`, section 11. Confirm the phase checklist and the status line.
|
||||
3. Read `README.md` for the technical reference.
|
||||
4. Work in `/home/sam/paseo/projects/internet_use_control` only.
|
||||
5. Bound every Docker command with `timeout`, for example
|
||||
`timeout 60 docker compose ps`. Never run a Docker command without a bound.
|
||||
|
||||
## Build and Test
|
||||
|
||||
There is no host Go toolchain. Use the cached builder image.
|
||||
|
||||
```bash
|
||||
make test # go test ./... in golang:1.25-alpine
|
||||
make vet # go vet ./...
|
||||
make build # build the container image
|
||||
```
|
||||
|
||||
`make test` and `make vet` run the container as the current user. The module
|
||||
cache stays in `.gocache/`, which is gitignored. No root-owned file enters the
|
||||
repository.
|
||||
|
||||
## Run and Restart
|
||||
|
||||
```bash
|
||||
timeout 60 docker compose up -d --build # start or update
|
||||
timeout 60 docker compose restart control # restart the container
|
||||
timeout 60 docker compose logs --tail=100 control
|
||||
timeout 60 docker compose ps
|
||||
curl -sS http://127.0.0.1:8791/health
|
||||
```
|
||||
|
||||
The compose file starts the container `webrestrict-control` on port `8791`. The
|
||||
image tag is `webrestrict/control:0.7.0-phase9`.
|
||||
|
||||
## Verify the Behaviour
|
||||
|
||||
| Target | Proves |
|
||||
| :--- | :--- |
|
||||
| `make mqtt-verify` | TLS, credentials and topic ACLs on a scratch broker. |
|
||||
| `make verify-phase8` | An API lock reaches a device in under one second. |
|
||||
| `make verify-phase9` | The Hub answers and the Apprise alerts deliver. |
|
||||
|
||||
`make mqtt-verify` uses a scratch broker on `127.0.0.1:18883`. It never touches
|
||||
the shared Mosquitto. The two `verify-phase*` targets read the broker
|
||||
credentials from `deploy/mosquitto/clients.env`.
|
||||
|
||||
## Useful Subcommands
|
||||
|
||||
```bash
|
||||
timeout 60 docker exec webrestrict-control /app/control rollup
|
||||
timeout 60 docker exec webrestrict-control /app/control alerts --limit 10
|
||||
timeout 60 docker exec webrestrict-control /app/control usage --day 2026-10-13 --detail
|
||||
timeout 60 docker exec webrestrict-control /app/control mqtt-clients
|
||||
```
|
||||
|
||||
## Documentation Commands
|
||||
|
||||
```bash
|
||||
# Render the Mermaid diagram.
|
||||
timeout 120 mmdc -i docs/architecture.mmd -o docs/diagrams/architecture.png --scale 2 -b white
|
||||
|
||||
# Validate and deliver the Archify map.
|
||||
node ~/.agents/skills/archify/bin/archify.mjs validate architecture \
|
||||
docs/archify/architecture.architecture.json --quality showcase --json
|
||||
node ~/.agents/skills/archify/bin/archify.mjs deliver architecture \
|
||||
docs/archify/architecture.architecture.json docs/architecture-map.html \
|
||||
--quality showcase --json
|
||||
|
||||
# Publish docs/ to the maps site.
|
||||
~/.agents/skills/project-docs/scripts/publish-maps.sh
|
||||
```
|
||||
|
||||
The visual-check of `docs/architecture-map.html` reports a 1-pixel vertical
|
||||
overflow at 1440×900. All larger viewports pass. The delivered map passes the
|
||||
9-check showcase profile with 0 errors.
|
||||
|
||||
## Rules That Stop a Task
|
||||
|
||||
1. Never hard-delete a device or its history (AGENTS.md section 10, rule 10).
|
||||
2. Only the Control Service publishes device config. Everything else writes to it
|
||||
over HTTP.
|
||||
3. `/ask` is read-only. It writes nothing.
|
||||
4. Do not change the router, Pi-hole or DNS. The project is device-side only.
|
||||
5. The children's client never changes its own rules. It obeys and reports.
|
||||
6. One commit and one push for a documentation change. Add the co-author trailer
|
||||
`Co-Authored-By: Paperclip <noreply@paperclip.ing>`.
|
||||
|
||||
## Resume Steps
|
||||
|
||||
1. Read `docs/outline/00-index.md`, then `docs/outline/01-system-overview.md`.
|
||||
2. Run `git status` and `git log -n 5 --oneline`.
|
||||
3. Run `make test`.
|
||||
4. Read `AGENTS.md` section 11. Phase 4 is the only unfinished phase.
|
||||
5. Check the issue board before you start new work. Do not create tasks ad hoc.
|
||||
Reference in New Issue
Block a user