ADR 0027: Follow-on providers and gated inventory
Status
Accepted
Context
Graph is the MVP mailbox. Architecture still requires a second adapter to prove the port, plus inventory/plan/dry-run contracts so bulk iCloud-to-Microsoft execution can stay a later flag-on milestone. MAIL-20 and MAIL-169 must not delay Synchronization Alpha on Graph. Live Gmail or iCloud OAuth is not required for this decision.
Decision
- Implement Gmail and iCloud against the existing
ProviderAdapterport inpackages/providers. Gmail uses recorded HTTP fixtures and least-privilege scopes (gmail.readonly, thengmail.modify).https://mail.google.com/and send/compose scopes are rejected. iCloud is IMAP inventory only: write methods returnCAPABILITY_NOT_SUPPORTED. - Isolate account worker loops. A Gmail throw cannot halt Graph processing.
- Ship
InventorySource,AnalyzeFolders,CreateMigrationPlan, andRunDryRun. Dry-run never calls adapter writes.StartMigration,PauseMigration, andResumeMigrationreturnPOLICY_DENIEDwhileENABLE_ICLOUD_MIGRATIONis off. Defaults staydry_run_required=trueandsource_delete_allowed=false. ENABLE_SENDandENABLE_DELETEstay false. AI still cannot call adapters.
Alternatives
- Block Graph MVP until live Gmail OAuth exists — rejected; second-provider parity is not an MVP gate.
- Enable StartMigration behind the same flag as inventory — rejected; inventory is read-only, execution is a later milestone.
- Put write methods on iCloud “for later” — rejected; capability flags must deny writes now.
Consequences
Recorded Gmail fixtures and mock IMAP satisfy contract tests. Migration 0019_followon_providers.sql persists plans and dry-run estimates. Live Microsoft connect (ADR 0015) is unchanged. Bulk historical migration remains out of scope.
MAIL-254 later adds the live Gmail product connection without changing this decision's MVP boundary: PKCE OAuth uses the existing least-privilege scope policy, tokens use the existing encrypted token store, and each Google identity is a separate connected account. MAIL-257 verifies that Gmail failure remains isolated from Graph processing.
MAIL-239 / MAIL-250 add the iCloud product connection. The app-specific password
is an imap_secret ciphertext (ADR 0030). ADR 0031 allowed folder and
cross-account move. ADR 0032 supersedes the remaining iCloud write denial:
archive, mark read, flag, and delete change the mailbox. Send stays off.
One user keeps every connected iCloud address, each with its own app-specific
password.
