Written to be run later rather than now, so it says what changed underneath and where a failure will land: the routes moved verbatim, but the transport (browser → proxy → sidecar HTTP) and the source of user identity (X-Officer-User instead of userMiddleware) did not, and that is where breakage will cluster. Includes the attribution table — 503 vs 502 vs 401 each point at a different half — and flags the two things that are expected rather than wrong: sync still runs platform-side on purpose, and the channel handlers' "sync emails" was already broken before this. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5.1 KiB
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
/emailloads 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/statsrenders — 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/:emailIdin 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
/emailopen, 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:newused 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: 1800for the whole/api/emailprefix. - P2
/api/email/messagesreturns 503 (not a hang or a 500) whileofficer-emailis 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 officermentions 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.