Files
email_agent/README.md
Sam Rolfe 3c0030c9a3 Phase 1.2: session login + empty HTMX dashboard
- Session login for the single user Sam: server-side session store with an
  HMAC-signed session cookie, POST /login, POST /logout, and double-submit
  CSRF on every form post. Unauthenticated requests to / and /partials/*
  redirect to /login?next=...
- Empty dashboard shell in the Family Home Lab design system: left nav
  (category and folder placeholders), centre list, right detail pane.
- Copy tokens.css and the self-hosted Inter fonts from the family-home-lab
  design system into web/static; vendor htmx 2.0.4. No cross-project imports
  at runtime.
- Dark mode via prefers-color-scheme plus a persisted toggle; phone-first
  layout with 44px touch targets, hairline borders, 8px grid, pill CTAs.
- Config: EMAIL_AGENT_PASSWORD for the login password, falling back to
  EMAIL_AGENT_SESSION_SECRET so one configured secret is enough.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-11 19:58:25 +11:00

94 lines
3.8 KiB
Markdown

# 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`](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`](.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
```sh
go run ./cmd/email-agent
curl -s localhost:8790/health
```
## Docker
```sh
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.