Files
emcli/specifications/PHASE3-STATUS.md
T
steve 193815dd25 docs: Phase 3 decision — Gmail via app password; OAuth2 deferred
Evaluated OAuth2 (SPEC §10) and chose not to build it this phase. A self-built,
unverified OAuth app suffers Google's 7-day refresh-token expiry in Testing
status (or the unverified-warning + restricted-scope verification cost in
Production). For a single-user personal tool, a Gmail App Password (2FA) is
strictly simpler and reuses the IMAP/SMTP password auth from Phases 1–2.

Validated live against a real Gmail account over app-password auth: list/get/
search, send, and a full SMTP-out → IMAP-in round-trip. No code changes were
required; the speculative OAuth store fields started mid-session were reverted.
OAuth2 remains a clean future addition (schema columns already present).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 18:16:20 +01:00

80 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# emcli — Phase 3 Status Report
**Date:** 2026-06-22
**Branch:** `main`
**Phase 3 (as specified):** OAuth2 — Gmail loopback consent + token refresh (SPEC §10).
## Outcome: OAuth2 deferred; Gmail handled via app password on the existing auth path
After evaluating the OAuth2 design against the actual use case (a personal, self-built CLI for
one Gmail account), we chose **not** to build the OAuth2 machinery in this phase. Gmail is instead
accessed with a **Google App Password** over emcli's existing password auth (Phases 12) — and it
was validated live, end-to-end. No new code was required.
### Why OAuth2 was deferred (not just "skipped")
A self-built tool cannot replicate the "Log in with Google" experience of verified clients
(Mailspring, Thunderbird, Aerion) without owning a **verified, published** OAuth app. For a
personal embed the options are all poor:
- **Unverified app in "Testing" publishing status** → Google expires refresh tokens **every 7
days**, forcing weekly re-consent. Unusable for an unattended tool.
- **Unverified app in "Production" status** → refresh tokens are long-lived, but every login shows
the "Google hasn't verified this app" warning, and `https://mail.google.com/` is a **restricted
scope** (full verification needs a paid security assessment). Workable, but heavy setup for one
user.
- **App Password (chosen)** → requires only that 2-Step Verification is enabled. Yields a permanent
16-character credential usable with standard IMAP/SMTP password auth. No consent screen, no
7-day expiry, no client ID/secret, no Google Cloud project. Revoked only on manual revoke,
main-password change, or disabling 2FA.
For a single-user personal tool, the App Password is strictly simpler and more robust, and it
reuses the IMAP/SMTP password path already shipped and tested in Phases 12.
> OAuth2 remains a clean future addition (SPEC §10, schema columns already present) if emcli ever
> needs multi-user/provider support or a verified app. The mechanism would be: x/oauth2 loopback
> consent + an XOAUTH2 `sasl.Client` (go-sasl ships OAUTHBEARER but not XOAUTH2) wired into the
> existing `mail.Dial`/`SendSMTP` auth branch. Nothing in Phases 12 blocks it.
## Live validation (real Gmail account, app password)
A real personal Gmail account over verified TLS (`imap.gmail.com:993`, `smtp.gmail.com:465`),
authenticating with a Gmail **app password** via the existing password auth:
- **`list`:** returned real INBOX headers (newest-first), `has_attachments` correct.
- **`get`:** returned the full decoded plain-text body of a Gmail message.
- **`search`:** `--from`/`--subject-contains` narrowed correctly server-side.
- **`send`:** delivered a message to `me@stevecliff.com``{"sent":true}`, exit 0.
- **Round-trip:** a self-addressed send arrived and was found via IMAP `search` on the first poll
— full SMTP-out → IMAP-in proof.
- All over emcli's existing code; the app password is sealed at rest in the encrypted DB.
## Gmail setup (app password)
1. Enable **2-Step Verification** on the Google account (required — the app-passwords page is
hidden otherwise).
2. Create a 16-character app password at <https://myaccount.google.com/apppasswords> (name it
e.g. "emcli").
3. Enable IMAP in Gmail: **Settings → Forwarding and POP/IMAP → Enable IMAP**.
4. Add the account (app password is entered as the password; spaces are stripped):
```
emcli account add --name gmail --mode RW \
--imap-host imap.gmail.com --imap-port 993 --imap-security tls \
--smtp-host smtp.gmail.com --smtp-port 465 --smtp-security tls \
--username you@gmail.com --password '<16-char-app-password>'
```
App passwords are revoked by a main-password change or disabling 2FA; regenerate and re-run
`account add` if that happens.
## Code changes
**None.** The speculative OAuth store fields/tests started early in the session were reverted; the
working tree is byte-for-byte the Phase 2 code plus this document. Full suite remains green.
## Known limitations / deferred
- **OAuth2 (SPEC §10)** — deferred as above; revisit for multi-user/provider or a verified app.
- **Phase 4 — admin TUI + `doctor`** — unchanged; next up.
- Carry-over Minor items from Phase 1 remain open.