feat: UI catch-up — 5 new pages + grammar wiring + DNS modal + MTA fixes #4051
1 changed file+7−2
ModifiedCLAUDE.md+7−2View fileUnifiedSplit
@@ -660,6 +660,11 @@ larger storage, unlimited accounts, dedicated support. Billing wiring pending
660660| 41 | **Connected-account mail is never persisted (empty inbox after connect)** — the Gmail/Outlook sync engine fetches + parses but its store is a stub: `fetchAndStoreGmailMessage` (apps/api/src/sync/engine.ts) and the Outlook loop only `console.log` instead of writing to `emails`. So connecting Gmail/Outlook syncs nothing, and direct history import for those providers can't work either. | HIGH | 2026-06-13 | FIXED 2026-06-15 — `apps/api/src/sync/engine.ts`: added `decodeBase64Url()` helper + recursive `extractGmailBodies()` MIME walker; `fetchAndStoreGmailMessage()` now calls `storeReceivedEmail({ accountId, source: "gmail", ... })` with base64url-decoded bodies. Outlook loop similarly wired. Both use conditional spread for optional `receivedAt` to satisfy `exactOptionalPropertyTypes`. AI auto-triage (Claude Haiku, fire-and-forget) added to `received-email-store.ts` — classifies priority/category/actionRequired/summary into `emails.metadata` on every insert. Merged in PR #72. |
661661| 42 | **MTA worker not running on box** — emails queue via BullMQ but the `alecrae-mta` systemd service doesn't exist yet on 149.28.119.158; emails are stored in DB + queued in Redis but never consumed → never sent. Also: `POST /v1/messages/send` returned a raw 500 if Redis was unavailable (no error handling around `queue.add()`). | HIGH | 2026-06-15 | PARTIALLY FIXED 2026-06-15 — `queue.add()` now wrapped in try/catch → returns HTTP 503 with actionable message instead of raw 500. Runbook `docs/infra/mta-box-setup.md` created (Redis install, systemd service file, test send, queue inspection). `box-deploy.sh` updated to restart `alecrae-mta` if it exists. **Craig still needs to run the runbook on the box.** |
662662| 40 | **Systemic scope/auth trap blocked the whole management surface from the web** — (a) session JWTs only ever carried `messages:* + account:manage`, but `domains`/`mailboxes`/`workspace-import`/`organizations`/`import` routes require `domains:manage`/`account:read`/`team:manage`/`import:*` — scopes no session token (and for `account:read`/`import:*`, no API key either) ever had → blanket 403; (b) `/v1/mailboxes` had NO `authMiddleware` mount at all and `/v1/domains` (bare list/create) was only covered by `/v1/domains/*` (which doesn't match the bare path) → 401 with no auth context. So even the "working" Domains page actually 401'd. | HIGH | 2026-06-13 | FIXED 2026-06-13 — session tokens now carry role-derived scopes (`createAccessToken` → `scopesForRole`: owner/admin get domains:manage, account:read, team:manage, analytics:read, webhooks:manage, api_keys:manage, import:read/write; member keeps the prior baseline + account:read; viewer read-only). All handlers stay account-scoped so an owner only reaches their OWN account; cross-account `/v1/admin/*` stays role-gated via `requireAdmin` (NOT widened). Added the missing `authMiddleware` mounts for bare `/v1/domains` and `/v1/mailboxes`(+`/*`). 143/143 api tests green. |
663| 43 | **React hydration error #418** — `navigator.onLine` initialized as `true` in `OfflineComposeBanner` + `OfflineBadge` (SyncStatusBar) caused server/client HTML mismatch; browser console showed "Error: Minified React error #418" + infinite GET /v1/connect/accounts 403 render loop | MEDIUM | 2026-06-15 | FIXED 2026-06-16 — `isOnline` initialized as `null` (not `true`) so both server and client render `null` initially; `useEffect` sets the real value after hydration. Loop was a side-effect of the stale-token 403 on every render — fixed by sign-out/sign-in to get a fresh JWT. |
664| 44 | **MTA health server crashed on port 8080** — `vapron-bun-gateway` also uses port 8080; MTA service crashed on startup with "Failed to start server. Is port 8080 in use?" and exited, so the outbound queue was never consumed | HIGH | 2026-06-15 | FIXED 2026-06-16 — default `HEALTH_PORT` changed from 8080 to 8082; health server startup made non-fatal (catch + warn, continue without health endpoint) so MTA keeps running even if the health port is taken. |
665| 45 | **AI Grammar checking never triggered** — `_checkGrammar` callback (1.5s debounce → grammarApi) was defined in compose/page.tsx but `ComposeEditor` had no `onBodyChange` prop, so typing in the compose body never called the grammar API; the AI Suggestions panel never appeared | MEDIUM | 2026-06-16 | FIXED 2026-06-16 — added `onBodyChange?: (text: string) => void` prop to `ComposeEditor` (packages/ui), called on every textarea keystroke; compose page passes `onBodyChange={_checkGrammar}`. Fixed `onApplySuggestion` no-op too (dismisses applied suggestion from list). |
666| 46 | **Domains page "View Records" button did nothing** — `onViewRecords={() => { /* no-op */ }}` was a placeholder; users couldn't see what DNS records to add to their provider after adding a domain | MEDIUM | 2026-06-16 | FIXED 2026-06-16 — implemented `DnsRecordsModal` in domains/page.tsx: shows all 4 DNS records (type/name/value), one-click copy per value, verified/pending badges, propagation note. |
667| 47 | **~45% of backend had zero UI** — 96 API route groups, only ~20 web pages; Smart Folders, Mail Merge, Shared Inboxes, Delegation, Team Chat all built on backend but missing from the web app entirely | HIGH | 2026-06-16 | FIXED 2026-06-16 — 5 new pages built and committed: Smart Folders (full filter CRUD, open in inbox), Mail Merge (campaigns + CSV import + per-recipient status), Shared Inboxes (team inboxes + member management), Delegation (delegate to/from with permissions), Team Chat (channel list + message thread + send). All sidebar entries added. |
663668
664669---
665670
@@ -809,9 +814,9 @@ legacy with no customers. Do not add domains to Vercel or propose CNAMEs back.
809814 surface exists in this repo).
810815
811816
812**Last updated:** 2026-06-15 23:30 UTC
817**Last updated:** 2026-06-16 02:30 UTC
813818**Current phase:** Phase 1 — Beta Launch in Progress
814**Current focus:** Box is live at 149.28.119.158. Google sign-in working, HTTPS working, owner role showing. Resend SMTP relay configured for outbound (alecrae.com domain verification in progress). Three remaining Craig tasks: (1) uninstall Vercel GitHub App — settings → integrations → GitHub Apps → Vercel → uninstall; (2) complete Resend domain verification (DNS records added, click Verify in resend.com/domains); (3) set up MTA worker on box (Redis + alecrae-mta systemd service — see `docs/infra/mta-box-setup.md`). PRs #72–75 merged. `morning-setup.md` is the single runbook.
819**Current focus:** Box is live at 149.28.119.158. MTA worker operational. Massive UI catch-up: 5 new pages built (Smart Folders, Shared Inboxes/Delegation, Mail Merge, Team Chat, plus grammar wiring + DNS records modal). Web app UI now covers ~55% of backend. Three remaining Craig tasks: (1) uninstall Vercel GitHub App; (2) complete Resend domain verification; (3) add alecrae.com as domain + create craig@alecrae.com mailbox in Workspace page. PRs #72–75 merged + current branch `claude/code-audit-vapron-migration-6jya3k` ready for PR.
815820**Build completion:** TIER 1-4 (36/36) + 7 bonus + 31 advanced (S10/10 + A7/7 + B8/8 + C6/10) + 20 expansion (Tier 5) + 9 platform (Tier 6) + 6 intelligence (Tier 7) + 6 deep AI (Tier 8)
816821
817822**Next review:** Before any major architectural change, before any production deployment, at the start of every session.
818823
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts