Files
Inboxintel/docs/discovery/multi-provider/12-migration-guide.md
T
cesnimda 4ce2df0a2b
CI / backend (push) Successful in 52s
CI / frontend (push) Successful in 14s
Deploy Staging / deploy (push) Successful in 18s
CI / backend (pull_request) Successful in 52s
CI / frontend (pull_request) Successful in 15s
Security / secrets (push) Successful in 4s
Security / dependencies (push) Successful in 55s
Security / secrets (pull_request) Successful in 4s
Security / dependencies (pull_request) Successful in 54s
docs: discovery blueprint + multi-provider design (#8)
2026-07-01 19:59:53 +02:00

53 lines
3.3 KiB
Markdown

# 12 — Migration Guide (Part 10)
Moving the current **single-account Gmail** app to the **multi-provider, multi-user** model
**additive and reversible**, no destructive step. Executed as ordered EF Core migrations +
idempotent backfills, behind a short maintenance window.
## Principles
- **Additive first:** create new tables/columns before moving data; keep old columns until parity is verified.
- **Idempotent backfills:** safe to re-run; keyed on stable ids.
- **Flag-gated cutover:** the new sign-in/model activates behind flags; the old path stays until removed.
- **Reversible:** each step has a documented rollback; no data is deleted during migration.
## Step-by-step
1. **Schema (additive migration)**
- Create `users`, `accounts`, `provider_tokens`, `sessions`, `user_settings`,
`system_settings`, `feature_flags`, `audit_logs`.
- Add `account_id`, `user_id` (nullable) to the current email/thread tables; widen
`search_vector`; add nullable `embedding vector(768)` + `pgvector` extension.
2. **Identity backfill**
- For the existing operator/user, create a `users` row; mark the **first user = Admin**.
- Create one **`Google` `account`** per existing identity (`is_login_identity=true`); move
current encrypted Gmail tokens → `provider_tokens`.
3. **Email backfill**
- Set `account_id`/`user_id` on all existing `Email`/thread rows to the default Google account.
- Regenerate the widened `search_vector`; leave `embedding` null (backfilled later by the AI phase).
- Enforce the new unique keys `(account_id, provider_message_id)` / `(account_id, provider_thread_id)`.
4. **Config seed**
- Seed `feature_flags`: `provider.google=on`, `provider.microsoft=off`, `provider.imap=off`,
`ai.enabled` = derived from the current `Ai:Mode` (Disabled→off), `ai.*`=off, `maintenance.*`=off.
- Create `system_settings` singleton; create `user_settings` from any existing per-user prefs (else defaults).
5. **Cutover**
- Enable the new OAuth-as-login + unified sync behind their flags; verify on **staging** first
(the pipeline we built), then production via a tagged release.
6. **Cleanup (later, separate migration)**
- Once parity is confirmed in production, drop obsolete columns/paths. Not part of the cutover.
## Verification checklist
- Existing user signs in via Google → lands on their mail unchanged.
- Email counts match pre/post; search returns identical results for sample queries.
- Tokens decrypt and refresh; sync resumes from the correct cursor.
- No cross-user rows visible (isolation test).
## Rollback
- **Pre-cutover:** additive changes are inert → simply don't flip the flags; drop new tables if aborting.
- **Post-cutover issue:** flip flags off / redeploy previous **tag**; old columns still present →
the legacy path still works. No data was deleted, so no data rollback is needed.
## Provider-app prerequisites (operator setup)
- **Google:** OAuth client (existing) + redirect `/(…)/signin/google`; scopes `gmail.readonly gmail.modify`.
- **Microsoft:** register an Entra app; redirect `/(…)/signin/microsoft`; scopes `Mail.Read Mail.ReadWrite offline_access`; admin consent if required.
- **IMAP (future):** per-account host/credentials; validated against the SSRF allowlist.
- Because providers are flag-gated, an unconfigured provider is simply hidden — configure, then enable.