# Email sidecar migration — test checklist For `7c173b4`, which moved the mail store and all 14 routes out of the platform and into `officer-email`. Each line is a single yes/no. Report as "M3 ok, R2 needs fix". **Pre-req:** `pm2 restart officer-email && pm2 restart officer`, then hard-refresh. Both are needed — the sidecar gained an HTTP listener and the platform became a proxy; restarting only one leaves them speaking different protocols. **Why this needs testing at all:** the routes moved *verbatim*, so the logic should be identical. What changed underneath is the transport (browser → platform proxy → sidecar HTTP) and where the user identity comes from (`X-Officer-User` header instead of the platform's `userMiddleware`). Failures will cluster in those two places, not in mail logic. --- ## M — Messages and folders - [ ] **M1** `/email` loads and lists messages. - [ ] **M2** Folder switching works, and per-folder counts look right (inbox / sent / all). - [ ] **M3** Paging past the first page works. - [ ] **M4** `/email/stats` renders — the totals panel is populated, not zeroed. - [ ] **M5** Labels/folders list is populated. ## R — Reading a message - [ ] **R1** Open a message → body, sender, date, recipients all render. - [ ] **R2** Open a thread → the whole conversation, in order. - [ ] **R3** Mark as read → state sticks after a refresh. - [ ] **R4** Mark a whole thread read. - [ ] **R5** Delete a message → it disappears and stays gone after a refresh. - [ ] **R6** Deep-link `/email/:emailId` in a fresh tab opens that message. ## S — Search and contacts - [ ] **S1** Search returns sensible results. - [ ] **S2** Search with an apostrophe or quote in the term behaves (`it's`, `"x"`), i.e. no 500. - [ ] **S3** Contacts list populates (used by the compose autocomplete). ## A — Attachments - [ ] **A1** A message with attachments shows them. - [ ] **A2** Extracting/downloading an attachment works and the file is intact. *Attachments write under `DATA_PATH`; the sidecar does this now, so a permissions problem would surface here first.* ## L — Live updates (the SSE path) - [ ] **L1** Leave `/email` open, send yourself mail → it appears without a manual refresh. - [ ] **L2** No repeated reconnect errors in the browser console while the page sits idle. *This is the biggest structural change: `email:new` used to travel sidecar → platform → SSE. The stream is inside the sidecar now and the IDLE watcher pushes to it in-process.* ## C — Accounts - [ ] **C1** The accounts screen lists the account with its status. - [ ] **C2** Sync status / last-synced is shown and looks current. - [ ] **C3** Trigger a manual sync → it starts. - [ ] **C4** Adding an account still validates the IMAP connection (test with a deliberately wrong password and expect a clear failure, not a hang). ## X — Sync regression (still platform-side, deliberately) The two sync handlers did **not** move; they still run in the platform queue and now import the store from its new location. So this block is checking nothing *broke*, not that anything improved. - [ ] **X1** New mail still arrives — the periodic sync is running. - [ ] **X2** Email sync jobs still appear in the Jobs list (they will stop doing so in stage 2, by design — option A). ## P — Proxy behaviour Run from the host. Mint a token the same way the app does, or reuse a browser one. - [ ] **P1** A long request survives: trigger a from-scratch resync and confirm it isn't cut off around 60s. The proxy sets `timeoutSeconds: 1800` for the whole `/api/email` prefix. - [ ] **P2** `/api/email/messages` returns 503 (not a hang or a 500) while `officer-email` is stopped: ```bash pm2 stop officer-email curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $TOK" \ -H 'Host: officer.pastilhas.dev' http://127.0.0.1:9010/api/email/messages # expect 503 pm2 start officer-email ``` - [ ] **P3** Nothing in `pm2 logs officer` mentions email internals any more — the platform should be logging proxy failures at most, never mail. --- ## Attributing a failure The split makes this quick: | symptom | look at | |---|---| | `503 email sidecar not available` | the sidecar isn't running, or hasn't announced its port — `pm2 logs officer-email` | | `502 email sidecar unreachable` | it announced a port but died; check for a crash on boot | | `401 missing X-Officer-User` | the proxy didn't inject the header — a platform-side problem | | anything about messages, folders, IMAP | the sidecar — `pm2 logs officer-email` | `pm2 logs officer-email` should now carry everything mail-related. If mail errors are still appearing in `pm2 logs officer`, something didn't move. ## Known-broken already, not caused by this `gmail-sync` is hardcoded in all three channel handlers (telegram, discord, whatsapp), but the only account is `provider=gmail, auth_type=password`, which routes to IMAP. So "sync emails" from a chat channel was already failing before this change. It gets fixed in stage 2, when the channels stop opening the mail store directly and ask the sidecar over HTTP.