Follow-on Gmail and iCloud adapters
Duckbill™ keeps Microsoft Graph as the MVP mailbox. Gmail and iCloud prove the shared adapter port without delaying Graph processing.
Rules
- Both adapters implement
ProviderAdapterinpackages/providers. - Gmail uses recorded fixtures and
historyIdincremental reads. Live product connect usesgmail.readonly; fullmail.google.com, send, and compose scopes are rejected. - iCloud IMAP archive, mark read, flag, delete, and move are enabled (ADR 0032). MAIL-250 adds a product connect form. The app-specific password is encrypted. A second iCloud address stays a separate row. The UI does not label those rows read-only. Send stays off.
- Account loops are independent. A Gmail outage cannot halt Graph.
- MAIL-254 adds live Gmail OAuth as a later product-completion increment. iCloud uses IMAP credentials, not OAuth (ADR 0030). Do not put provider secrets in git or Jira.
ENABLE_SENDandENABLE_DELETEstay false. AI never calls adapters.- Accounts adds a service from one provider list. iCloud is an entry in that list and still connects with an app-specific password. See connected services.
HTTP
Inventory and dry-run routes live under /api/inventory/* and /api/migrations/*. They use recorded or mock adapters when no live follow-on tokens exist.
Code
| Module | Role |
|---|---|
packages/providers/src/gmail/ | Gmail adapter, OAuth helpers, recorded transport |
packages/providers/src/icloud/ | IMAP inventory adapter, mock client, and live IMAP |
packages/application/src/icloud-connect.ts | Session-bound iCloud connect and encrypted app password |
packages/application/src/gmail-oauth.ts | Session-bound Gmail OAuth and encrypted token persistence |
packages/application/src/account-isolation.ts | Independent account loops |
docs/decisions/0027-followon-providers-and-gated-inventory.md | ADR 0027 |
Graph OAuth and live Microsoft connect stay on ADR 0011 / ADR 0015. See live Gmail connect and iCloud read-only connect for the follow-on product paths.
