Skip to content

ADR 0030: iCloud IMAP credential connect

Status

Accepted

Context

ADR 0027 made iCloud a read-only IMAP inventory adapter and rejected write methods. Sprint 10b needs a product path that connects Apple infrastructure (jskoch67@icloud.com) and legacy Apple (Jason.s.koch@icloud.com) without OAuth. Apple issues an app-specific password for IMAP. That secret must not be stored in git, Jira, or logs.

Decision

  1. /accounts posts the address and app-specific password to /api/providers/icloud/connect over the existing session and CSRF check.
  2. The server speaks IMAP to imap.mail.me.com:993, requires a successful login and a non-empty mailbox list, then upserts connected_accounts with provider icloud and a read-only capability profile.
  3. The password is stored only as provider_tokens.token_type = imap_secret ciphertext under TOKEN_ENCRYPTION_KEY. It is not an OAuth access token and is not returned on the health API.
  4. One user may have multiple iCloud rows. Identity is the lowercased address. The UI labels every iCloud row read-only and does not render archive, move, or delete controls.
  5. Write methods on the adapter stay CAPABILITY_NOT_SUPPORTED.

Alternatives

Consequences

Migration 0021_icloud_imap_secret.sql extends the token type check. ADR 0031 later makes iCloud read-write for move. Live login remains owner-gated because the app-specific password is not an environment variable. Gmail OAuth and Microsoft Graph connect are unchanged. ADR 0032 replaces the read-only label and the denied iCloud write methods: archive, mark read, flag, delete, and move run, and a second iCloud connect keeps the first row.