Gmail: setup guide, honest reconnect status, key-clobber fix, labels API - #258
Open
hilash wants to merge 1 commit into
Open
Gmail: setup guide, honest reconnect status, key-clobber fix, labels API#258hilash wants to merge 1 commit into
hilash wants to merge 1 commit into
Conversation
… fixes, labels API - Integrations > Gmail now has a Telegram-style numbered setup guide with stylized theme-aware mockups of Google's 2SV -> App passwords flow (GmailArt); brand switched from Gmail red to Google blue; removed the redundant collapsed instructions block from GmailSection. - /api/gmail/connect strips whitespace from pasted App Passwords (Google displays them as 'xxxx xxxx xxxx xxxx') and trims the email. - /api/gmail/status verifies the stored password actually decrypts and returns needsReconnect instead of claiming connected; GmailSection shows a reconnect banner with the saved email pre-filled. - getKeySecret() prefers the on-disk .cabinet.env secret over process.env and re-reads after generating, so a sibling process (app vs daemon vs dev worker) can no longer clobber the persisted secret and orphan the stored password. Co-located crypto.test.ts covers round-trip, fresh IV, and tamper rejection. - Gmail labels API: GET/POST /api/gmail/labels, POST /api/gmail/label (apply = IMAP copy to label mailbox), with label-name validation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Four related Gmail improvements, born from a real break: Mailroom fell back to demo mode because the stored App Password could no longer be decrypted, while Integrations still said "Connected".
1. Root cause + fix: encryption-key clobbering
The stored App Password is AES-256-GCM encrypted under a per-install secret in
.cabinet.env.getKeySecret()generated-and-persisted a fresh secret whenever a process booted without it inprocess.env— so a sibling process (Next app vs daemon vs a Turbopack dev worker) could overwrite the persisted secret and orphan every stored password. Confirmed by decrypting the live DB row offline: no available key matched.Fix: the on-disk secret is now the durable source of truth — encryption prefers it over
process.env, and after generating a fresh secret we re-read the file to adopt a concurrent sibling's write. Decrypt already tries env + file + legacy keys, so user-set env overrides still work. Co-locatedcrypto.test.ts(node:test) covers round-trip, fresh-IV, and tamper rejection.2.
/api/gmail/statusno longer liesIt only checked that a credentials row existed, so it reported
connected: truewhile every real call 500'd. It now attempts decryption and returnsneedsReconnect: true; the Integrations panel shows an amber "Reconnect needed" banner with the saved email pre-filled.3. Setup guide with mockups
Integrations → Gmail now has a Telegram/Slack-style numbered setup guide for Google's 2-Step Verification → App passwords flow, drawn as stylized theme-aware mockups (
GmailArt, shared setup-art primitives — no screenshots, no personal data). Brand color switched from Gmail red (read as a danger button) to Google blue./api/gmail/connectnow strips whitespace from pasted App Passwords (Google displays them asxxxx xxxx xxxx xxxx; a verbatim paste failed IMAP auth).4. Gmail labels API
GET/POST /api/gmail/labelsandPOST /api/gmail/label(apply = IMAP copy into the label's mailbox; message stays in inbox), with label-name validation at the trust boundary. Powers the Mailroom label controls.Verification
npx tsc --noEmitclean;npm run lint0 errorsnpx tsx --test src/lib/gmail/crypto.test.ts— 3/3 passGET /api/gmail/statuson the affected install now returns{"connected":false,"needsReconnect":true,...}for the orphaned credential🤖 Generated with Claude Code