Sam Rolfe e846400338 docs: Phase 1 deploy verified, session secret configured (AUD-61)
Login and dashboard verified over public HTTPS; record the secret path and
the Paperclip card cascade limitation that forced direct configuration.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-11 20:17:15 +11:00

Email Agent

Triage the family inbox from one page: all mail lands in a single Gmail account and this service classifies it, recommends actions, performs bulk actions, drafts replies, and answers the Hub.

The build spec is AGENTS.md. ORIGINAL_NOTES.md is archived pre-planning material and is not authoritative.

Status

Phase 1.2 — Session login + empty dashboard. The Go skeleton (Phase 1.1) plus a single-user session login, a copied Family Home Lab tokens.css, and an HTMX dashboard shell (left nav, centre list, right detail pane) with dark mode. Mail fetch, classification, and the rest come in later phases.

Layout

cmd/email-agent/        service entry point
internal/config/        environment-driven configuration
internal/session/       server-side session store + signed cookie values
internal/store/         SQLite open + schema (internal/store/schema.sql)
internal/server/        HTTP routes, auth middleware, HTMX handlers
internal/version/       build metadata (set via -ldflags)
web/static/             embedded design tokens, Inter fonts, htmx, app.css
web/templates/          embedded server-rendered HTML
Dockerfile              multi-stage, CGO-free build
docker-compose.yml      this project's own container and image

Configuration

All configuration is read from environment variables. Secrets live in ~/.config/environment.d/10-secrets.conf on the host and are passed into the container by docker-compose; no secret value is ever committed. See .env.example for the full list of names.

Key variables:

Variable Default Purpose
EMAIL_AGENT_ENV development development, production, or test
EMAIL_AGENT_ADDR :8790 Listen address
EMAIL_AGENT_PORT 8790 Listen port (used when EMAIL_AGENT_ADDR is unset)
EMAIL_AGENT_DB_PATH data/email_agent.db SQLite file
EMAIL_AGENT_LOG_LEVEL info debug, info, warn, error
EMAIL_AGENT_SESSION_SECRET (empty) Session cookie signing key. If unset, an ephemeral key is used (sessions reset on restart)
EMAIL_AGENT_PASSWORD (empty) Login password for Sam. If unset, EMAIL_AGENT_SESSION_SECRET doubles as the password

Run locally

go run ./cmd/email-agent
curl -s localhost:8790/health

Docker

docker compose up -d --build
curl -s localhost:8790/health

The container is email-agent, image email-agent:latest, named volume email_agent_data mounted at /data, listening on 8790. It runs as an unprivileged user and has a built-in healthcheck (email-agent -healthcheck). Caddy on .35 proxies mail.lab.audasmedia.com.au to this port.

Endpoints (Phase 1)

Method Path Auth Purpose
GET /health public Liveness + database check, JSON
GET /readyz public Readiness, JSON
GET /login public Sign-in form (deep-indigo band)
POST /login public CSRF-checked password sign-in, sets the session cookie
POST /logout session Destroys the session, returns to /login
GET / session Empty dashboard shell
GET /partials/inbox session HTMX fragment for the centre list
GET /static/… public Embedded tokens.css, app.css, Inter fonts, htmx.min.js

Unauthenticated requests to / and /partials/… redirect to /login?next=…. Form posts use a double-submit CSRF token (email_agent_csrf cookie plus a hidden csrf field).

Database

SQLite is opened with the pure-Go modernc.org/sqlite driver (no CGO). The schema in internal/store/schema.sql creates the AGENTS.md §7 tables: messages, classifications, rules, actions_log, unsubscribe, drafts, summaries, plus schema_migrations. Schema init is idempotent and runs on every start.

Description
Email triage agent for the family inbox.
Readme 1 MiB
Languages
Go 87.6%
HTML 7.5%
CSS 4.3%
Dockerfile 0.3%
Makefile 0.3%