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:
158
docs/outline/03-code-map.md
Normal file
158
docs/outline/03-code-map.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Email Agent — Code Map
|
||||
|
||||
## Folder structure
|
||||
|
||||
```
|
||||
email_agent/
|
||||
├── AGENTS.md Build spec (phases 1-8, requirements, rules).
|
||||
├── README.md Technical repository README.
|
||||
├── cmd/email-agent/
|
||||
│ └── main.go Entry point. HTTP server and every CLI flag.
|
||||
├── internal/
|
||||
│ ├── apprise/ Apprise API client for the daily summary email.
|
||||
│ ├── classify/ JEV client, rule engine, classification orchestration.
|
||||
│ ├── config/ Environment-driven configuration.
|
||||
│ ├── hub/ Hub contract: capabilities, /ask answerer, notify.
|
||||
│ ├── mailfetch/ Stdlib-only IMAP client, MIME parse, FR-2 source address.
|
||||
│ ├── mailops/ Gmail label moves, flag changes, and SMTP sending.
|
||||
│ ├── reply/ OmniRoute LLM drafts and reply templates.
|
||||
│ ├── server/ HTTP routes, auth middleware, HTMX handlers.
|
||||
│ ├── session/ Server-side session store and signed cookie values.
|
||||
│ ├── store/ SQLite open, schema, migrations, all queries.
|
||||
│ ├── summary/ Deterministic daily-summary builder.
|
||||
│ ├── unsubscribe/ RFC 2369/8058 and body unsubscribe-link detection.
|
||||
│ └── version/ Build metadata (-ldflags).
|
||||
├── web/
|
||||
│ ├── embed.go Embeds the static and template files.
|
||||
│ ├── static/ tokens.css, app.css, Inter fonts, htmx.min.js.
|
||||
│ └── templates/ login, dashboard, inbox, message, categories, rules,
|
||||
│ unsubscribe, reports.
|
||||
├── docs/ Phase evidence, AI context, map, diagrams.
|
||||
├── Dockerfile Multi-stage, CGO-free build.
|
||||
├── docker-compose.yml Own container, image, port, and volume.
|
||||
└── Makefile Build, test, and run targets.
|
||||
```
|
||||
|
||||
## Entry points
|
||||
|
||||
| Entry point | Language | Role |
|
||||
| :--- | :--- | :--- |
|
||||
| `cmd/email-agent/main.go` | Go | Service and CLI. |
|
||||
| `internal/server/server.go` | Go | HTTP router and middleware. |
|
||||
| `internal/store/schema.sql` | SQL | The AGENTS.md section 7 tables. |
|
||||
|
||||
## CLI flags
|
||||
|
||||
| Flag | Effect |
|
||||
| :--- | :--- |
|
||||
| `-version` | Print version, commit, and build time. |
|
||||
| `-healthcheck` | Probe the local `/health` endpoint and exit. |
|
||||
| `-fetch` | Run one Gmail IMAP scan and exit (FR-1). |
|
||||
| `-classify` | Classify pending messages with JEV and exit. |
|
||||
| `-classify-all` | Re-classify every stored message. |
|
||||
| `-check-smtp` | Verify SMTP IPv4, STARTTLS, and login. Sends no mail. |
|
||||
| `-check-thread <id>` | Confirm a stored thread has a sent reply. Read-only. |
|
||||
| `-summary` | Build today's summary, store it, and print it. Sends nothing. |
|
||||
| `-summary-send` | Build the summary and deliver it by email via Apprise. |
|
||||
| `-notify` | Send one notification to the Hub (`POST /notify`). |
|
||||
| `-retain` | Clear old message bodies and cap `actions_log` (AGENTS.md section 7). |
|
||||
|
||||
## HTTP routes
|
||||
|
||||
| Method | Path | Auth | Purpose |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `GET` | `/health` | public | Liveness and database check. |
|
||||
| `GET` | `/readyz` | public | Readiness. |
|
||||
| `GET` | `/login` | public | Sign-in form. |
|
||||
| `POST` | `/login` | public | CSRF-checked sign-in. |
|
||||
| `POST` | `/logout` | session | End the session. |
|
||||
| `GET` | `/` | session | Dashboard. |
|
||||
| `GET` | `/partials/inbox` | session | HTMX inbox fragment. |
|
||||
| `POST` | `/actions/fetch` | session + CSRF | One IMAP scan. |
|
||||
| `POST` | `/actions/classify` | session + CSRF | Classify pending messages. |
|
||||
| `POST` | `/actions/reclassify` | session + CSRF | Re-classify every message. |
|
||||
| `POST` | `/actions/bulk` | session + CSRF | Bulk delete, move, mark, restore. |
|
||||
| `GET` | `/partials/message` | session | Message detail fragment. |
|
||||
| `POST` | `/actions/draft` | session + CSRF | Generate and store a reply draft. |
|
||||
| `POST` | `/actions/draft/save` | session + CSRF | Save draft edits. |
|
||||
| `POST` | `/actions/send` | session + CSRF + confirm | Send a reply over SMTP. |
|
||||
| `GET` | `/categories` | session | Category editor (FR-14). |
|
||||
| `POST` | `/categories/add` | session + CSRF | Add a category. |
|
||||
| `POST` | `/categories/rename` | session + CSRF | Rename and cascade. |
|
||||
| `POST` | `/categories/remove` | session + CSRF | Remove and reassign. |
|
||||
| `GET` | `/rules` | session | Rules editor (FR-11). |
|
||||
| `POST` | `/rules/save` | session + CSRF | Save a new rules version. |
|
||||
| `POST` | `/rules/restore` | session + CSRF | Restore an older version. |
|
||||
| `POST` | `/rules/reclassify` | session + CSRF | Re-classify with current rules. |
|
||||
| `GET` | `/unsubscribe` | session | Unsubscribe links and ignore list (FR-7). |
|
||||
| `POST` | `/unsubscribe/ignore` | session + CSRF | Add a domain to the ignore list. |
|
||||
| `POST` | `/unsubscribe/unignore` | session + CSRF | Remove a domain record. |
|
||||
| `POST` | `/unsubscribe/mark` | session + CSRF + confirm | Record a domain. No link is followed. |
|
||||
| `GET` | `/reports` | session | Daily summary and delete-report. |
|
||||
| `GET` | `/capabilities` | Hub bearer | Hub capability list (FR-12). |
|
||||
| `POST` | `/ask` | Hub bearer | Read-only short answer. |
|
||||
| `GET` | `/static/...` | public | Embedded CSS, fonts, htmx. |
|
||||
|
||||
## Data model
|
||||
|
||||
SQLite. The schema is in `internal/store/schema.sql`. Migrations run at start
|
||||
and are recorded in `schema_migrations`.
|
||||
|
||||
| Table | Holds |
|
||||
| :--- | :--- |
|
||||
| `messages` | Gmail id, thread id, headers, from, to, subject, body, source address. |
|
||||
| `classifications` | Category, importance, action, confidence, model. |
|
||||
| `categories` | The editable category list (FR-14). |
|
||||
| `rules` | Plain-text rules, versioned (FR-11). |
|
||||
| `actions_log` | Append-only action log (FR-13). Capped by `-retain`. |
|
||||
| `unsubscribe` | Detected domains, status, and ignore list (FR-7). |
|
||||
| `drafts` | Reply draft body, template, and sent state (FR-8). |
|
||||
| `summaries` | Daily summary text and delivery target (FR-10). |
|
||||
|
||||
Migrations: v2 adds IMAP UID fields. v3 seeds the first categories and rules.
|
||||
v4 adds `folder` and `mailbox`. v5 adds `message_id_header` and `drafts.sent_at`.
|
||||
v6 adds `list_unsubscribe` fields and `unsubscribe.url`.
|
||||
|
||||
## Key modules
|
||||
|
||||
| Module | Role |
|
||||
| :--- | :--- |
|
||||
| `internal/mailfetch/imap.go` | Minimal IMAP client. Forces `tcp4`. |
|
||||
| `internal/mailfetch/message.go` | MIME parse and the FR-2 source address. |
|
||||
| `internal/mailfetch/imap_write.go` | IMAP MOVE, COPY, and flag changes. |
|
||||
| `internal/classify/jev.go` | JEV `/v1/systemone` client. Three Choice questions. |
|
||||
| `internal/classify/rules.go` | Rule parse and first-match-wins engine (FR-4). |
|
||||
| `internal/mailops/mailops.go` | App folder to Gmail label mapping. |
|
||||
| `internal/mailops/smtp.go` | SMTP send with IPv4 and STARTTLS. |
|
||||
| `internal/reply/draft.go` | Reply prompt and OmniRoute call. |
|
||||
| `internal/reply/templates.go` | Built-in reply templates. |
|
||||
| `internal/store/retention.go` | Body clearing and `actions_log` cap. |
|
||||
| `internal/hub/ask.go` | Deterministic, read-only answerer. |
|
||||
|
||||
## Tests
|
||||
|
||||
All Go tests run in a container:
|
||||
|
||||
```sh
|
||||
timeout 600 docker run --rm -v "$PWD":/src -w /src golang:1.25-alpine go test ./...
|
||||
```
|
||||
|
||||
| Package | Coverage |
|
||||
| :--- | :--- |
|
||||
| `internal/classify` | JEV client, rule engine, orchestration. |
|
||||
| `internal/hub` | Answer intents, auth, read-only proof, notify. |
|
||||
| `internal/mailfetch` | IMAP parse, MIME, FR-2, write ops. |
|
||||
| `internal/mailops` | Label mapping, SMTP. |
|
||||
| `internal/reply` | Draft prompts and templates. |
|
||||
| `internal/server` | Auth, routes, CSRF, handlers. |
|
||||
| `internal/store` | Schema, retention, triage, categories, summaries. |
|
||||
| `internal/summary` | Counts, ordering, text. |
|
||||
| `internal/unsubscribe` | Link detection. |
|
||||
| `internal/apprise`, `internal/config`, `internal/session` | Client and config. |
|
||||
|
||||
## Dependencies
|
||||
|
||||
Go 1.25. The only database driver is `modernc.org/sqlite` (pure Go, no CGO).
|
||||
The mail path uses the Go standard library plus a minimal IMAP client. The UI
|
||||
uses vendored HTMX and the Family Home Lab `tokens.css`. No JavaScript build
|
||||
step.
|
||||
Reference in New Issue
Block a user