docs: Phase 8 documentation - Gitea, Obsidian, Outline, Vikunja, map (AUD-74)

- README: architecture Mermaid, Phase 8 status, Phase 7 endpoints, Documentation index
- docs/outline/: AI-context collection (index, system, config, code map, runbook)
- docs/email-agent-architecture.mmd + rendered PNG + Archify map (showcase pass)
- docs/vikunja-tasks.json (Vikunja project 17, tasks 179-185)
- docs/phase8-documentation.md evidence
This commit is contained in:
Documenter
2026-10-13 10:46:21 +11:00
parent 77febe6470
commit c5760db43d
12 changed files with 14575 additions and 26 deletions

View File

@@ -0,0 +1,98 @@
# Email Agent — System Overview
## Purpose
The Email Agent triages the family inbox. All mail lands in one Gmail account
(`samuelrolfe@gmail.com`). PurelyMail forwards every domain address there.
Sam opens one page. He clears the inbox in a few minutes. He knows that nothing
important was missed.
The build spec is `AGENTS.md`. The outcome statement is in `AGENTS.md` section 1.
## Architecture
```
Sam (phone or desktop browser)
-> Caddy on .35 (mail.lab.audasmedia.com.au)
-> Email Agent container on .13 :8790
|- HTMX dashboard (Go, server-rendered HTML)
|- SQLite (/data/email_agent.db, own volume)
|- IMAP read -> imap.gmail.com:993 (IPv4 only)
|- SMTP send -> smtp.gmail.com:587 (IPv4 only, STARTTLS)
|- JEV -> https://api.typesafe.ai (classification)
|- OmniRoute -> http://192.168.20.13:20129/v1 (reply drafts)
|- Apprise -> http://192.168.20.35:8210 (daily summary email)
\- Hub API -> read-only /ask, /capabilities, /notify
Hub on .13 :8788 asks this service with a shared bearer token.
n8n runs the CLI jobs (-fetch, -classify, -summary-send) on a schedule.
```
## Services and connections
| Service | Host | Address | Role |
| :--- | :--- | :--- | :--- |
| `email-agent` | `.13` | `:8790` | Web app, API, and CLI jobs. |
| Caddy | `.35` | `:443` | TLS reverse proxy for `mail.lab.audasmedia.com.au`. |
| Gmail IMAP | cloud | `imap.gmail.com:993` | Read mail. Force IPv4. |
| Gmail SMTP | cloud | `smtp.gmail.com:587` | Send replies. Force IPv4. |
| JEV | cloud | `api.typesafe.ai` | Classify each message. |
| OmniRoute | `.13` | `:20129` | Draft reply replies. Not JEV. |
| Apprise | `.35` | `:8210` | Deliver the daily summary by email. |
| Central AI Hub | `.13` | `:8788` | Ask questions. Read-only. |
| n8n | `.13` | — | Trigger the CLI jobs. |
## Functional requirements in use
| ID | Requirement | Where |
| :--- | :--- | :--- |
| FR-1 | Fetch mail with the Gmail path on a schedule. | `-fetch`, `/actions/fetch` |
| FR-2 | Record the source address from `X-Pm-Original-To`. | `internal/mailfetch` |
| FR-3 | Classify with JEV: category, importance, action, confidence. | `internal/classify` |
| FR-4 | Apply user rules over the classification. | `internal/classify/rules.go` |
| FR-5 | Show a triage list grouped by category. | `internal/server/inbox.go` |
| FR-6 | Bulk delete, move, and mark. | `internal/server/actions.go` |
| FR-7 | Detect unsubscribe links. Keep an ignore list. | `internal/unsubscribe` |
| FR-8 | Draft a reply with the LLM. Edit, then send. | `internal/reply`, `internal/mailops` |
| FR-9 | Move mail to Gmail labels. Deletes are recoverable. | `internal/mailops` |
| FR-10 | Build a daily summary and send it by email. | `internal/summary`, `internal/apprise` |
| FR-11 | Edit rules as plain text. Save and version. | `/rules`, `internal/server/rules.go` |
| FR-12 | Expose `GET /capabilities`, `POST /ask`, `POST /notify`. | `internal/hub` |
| FR-13 | Log every action. | `internal/store` `actions_log` |
| FR-14 | Edit the category list in the UI. | `/categories` |
| FR-15 | Send as the address the mail arrived at. | `internal/reply`, FR-2 value |
## Build phase status
Phases 1 to 7 are complete and deployed. Phase 8 documents the project.
| Phase | Scope | State |
| :--- | :--- | :--- |
| 1 | Go skeleton, SQLite, session login, Docker, Caddy. | Done. |
| 2 | Gmail IMAP read, FR-2 source address. | Done. |
| 3 | JEV classification, rules table, editable categories. | Done. |
| 4 | Triage actions: delete, move, mark, bulk select. | Done. |
| 5 | Reply drafts, edit, send. | Done. |
| 6 | Unsubscribe detection and the rules editor. | Done. |
| 7 | Daily summary by email and the read-only Hub API. | Done. |
| 8 | Documentation across Gitea, Obsidian, Outline, Vikunja, and the map. | Done. |
## Key rules
- Force IPv4 for every Gmail connection. IPv6 to Gmail failed from `.13`.
- The source address header is `X-Pm-Original-To`. Never use `Delivered-To`.
- `/ask` is read-only. It never changes state.
- Spam is recommended, never auto-deleted.
- Deletes are recoverable. The app uses a Delete label.
- Sending a reply needs Sam's action in the UI. No auto-send.
- Every action is logged.
- Message bodies are kept for one month. The `-retain` job clears older bodies
and caps `actions_log`. Metadata stays.
## Related documents
- `AGENTS.md` — the build spec and the phase plan.
- `README.md` — the technical repository README.
- `docs/phase7-summary-hub.md` — the Phase 7 evidence.
- `docs/outline/` — these AI-context documents.
- `docs/email-agent-map.html` — the interactive architecture map.