# emcli — Phase 4 Status Report **Date:** 2026-06-22 **Branch:** `main` **Phase 4 scope (SPEC §7.2):** `doctor` connectivity/auth diagnostics; admin completeness (`account edit`/`remove`, `config set`/`get`, `audit list`); and a **bubbletea TUI** for `init` and interactive `account add`/`edit`. ## TL;DR **Phase 4 is complete and validated live.** Built test-first; the binary builds as a single static CGO-free executable, `go vet` is clean, and the full suite passes including `-race`. `doctor` and the admin commands were exercised against the two real accounts (mxlogin password auth + Gmail app-password). A real bug — `doctor` running checks with stripped (empty) credentials — was caught by live validation, reproduced with a regression test, and fixed. ## What was built | Area | Change | Status | |---|---|---| | `store` | `UpdateAccount` (partial edit; re-encrypts password/secrets only when non-empty, blank keeps existing); `RecentAuditFor(account, limit)`. | ✅ | | `mail` | `CheckIMAP` (connect+login+logout) and `CheckSMTP` (connect+SASL-PLAIN auth+quit) — no mail transferred. | ✅ | | `cli` | `doctor [--account]` (per-account IMAP/SMTP `ok`/`FAIL`, exit non-zero on any failure, no secrets); `config set`/`get` (validates `audit_retention_days`); `audit list [--account] [--limit]`; `account edit` (flag partial-update) / `account remove [--yes]`. | ✅ | | `tui` (new pkg) | `AccountForm` bubbletea model over `bubbles/textinput`, with pure, fully-tested `Fields` (validation + `store.Account` assembly + edit prefill). | ✅ | | `cli` wiring | `init` (create/open DB, seed `audit_retention_days=90`, add first account via TUI); bare `account add` → TUI; `account edit --name X` (only `--name`) → TUI prefilled. | ✅ | ### Commands added ``` emcli doctor [--account ] emcli config set # e.g. audit_retention_days emcli config get emcli audit list [--account ] [--limit N] emcli account edit --name [--mode|--imap-host|--smtp-host|…] # flag partial-update emcli account edit --name # interactive (TUI) emcli account remove --name --yes emcli account add # interactive (TUI) emcli init # interactive (TUI) ``` ## Live validation Against the two real accounts (`mxlogin` password auth, `gmail` app-password) in an isolated DB: - **`doctor`** — `mxlogin` and `gmail` both report `IMAP ok` / `SMTP ok`; a deliberately bad-password account reports `IMAP FAIL: Invalid credentials` (clean error, **no crash**); SMTP shown `n/a` for RO. Exit `1` when any check fails, `0` when `--account` targets a passing one. - **`config`** — `set`/`get` round-trip; `audit_retention_days=-5` rejected (exit 2). - **`audit list`** — rendered a real `list`/`allowed` row. - **`account edit`** (flag) — set a subject-regex on `mxlogin`; a follow-up `doctor` still passed, proving `UpdateAccount` **preserved the encrypted password** through the edit. - **`account remove --yes`** — deleted an account; gone from `account list`. - **TUI** (`init`/interactive) requires a real terminal; without a TTY it fails cleanly (`could not open a new TTY`), no panic. Drive it interactively to use. ## Bug found and fixed during live validation `doctor` initially authenticated with **empty passwords** for every account — it iterated `ListAccounts()`, which deliberately strips secrets, and passed those credential-less structs to the live checks. Caught immediately against real servers ("Empty username or password"). Fixed by re-fetching each account with `GetAccount` (which decrypts) before checking; locked in with `TestDoctorUsesDecryptedCredentials`. ## Verification ``` CGO_ENABLED=0 go build ./... → OK, single static binary go vet ./... → clean go test ./... → all packages pass (incl. new internal/tui) go test -race ./... → all packages pass ``` New tests: `store` update/audit-filter; `mail` check-fails-cleanly; `cli` doctor (all-ok, failure, RO-skip, account-filter, decrypted-creds regression), config/audit/edit/remove via `Run()`; `tui` Fields validation/assembly/prefill and form submit/cancel. ## Known limitations / deferred - TUI is a minimal keyboard-driven form (bool fields entered as `y/n`, enums as text); no mouse or theming. Sufficient for admin use. - OAuth consent in `init` omitted (OAuth deferred in Phase 3). - Carry-over Minor items from Phase 1 (audit-row completeness, some CLI polish) remain open. ## Project status Phases 1–4 complete: read path, send path, Gmail (app password), and admin/TUI/doctor. The core `emcli` surface from the SPEC is implemented and validated live, with OAuth2 (§10) the one deliberately-deferred item.