MAIL_TRANSPORT was a fallback left from the old registration flow that sent
confirmation mail. That flow is gone; the variable outlived it.
It was never the primary source anyway. getTransport reads server_config
('server-settings' → smtp) first, which already backs a full UI at Settings →
Server → SMTP and its API in api/server-settings/smtp.ts, supporting resend,
smtp and mailhog. The env var only answered when that was absent — which is a
second source of truth for something the owner can already set, with the failure
mode that a stale URL in .env silently answers for a server whose settings row
is simply empty.
Removed from transport.ts, .env.example and the setup script's Environment
section, which no longer asks for it. setup-old/ still mentions it; that is the
archive and is left alone.
Also split the try. It wrapped the read AND the transport construction and
swallowed both, so three different problems produced one message. Unreachable
database, nothing configured, and stored settings that do not build a transport
now say different things, because the fix for each is different and this message
is all the caller ever sees.
The two consumers — queue/engine.ts and auth/forgot-password.ts — now raise
until SMTP is set in the UI, which is the honest answer rather than a regression.
Not typechecked: node_modules is empty here and installs are frozen. transport.ts
parses under `bun build --no-bundle`; the setup script was run and no longer
prompts for or writes the variable.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Officer is single-user: the server owner is the only account, created once by
/auth/bootstrap. Everything that existed to serve additional users was
unreachable, so it is gone rather than left looking like it does something.
Accounts: drop the invite / resend-invite / delete / list-users routes and the
Users settings screen, the inert /auth/signup handler, and the account
verification chain it fed (verify, resend-verification, VerifyScreen, the
UserInvite + VerifyAdmin + VerifyRegistration templates). /auth/verify-token
survives for password resets only, and now requires a reset-password token
rather than accepting any signed JWT.
Roles: drop the users.role column and the four-value USER_ROLES enum. The
permissions table granted every role identical methods, and every
role === 'Super Admin' check was permanently true. The JWT no longer carries a
role claim.
Sandbox: remove sidecar/sandbox.ts and its five call sites. bwrap was selected
only for non-Super-Admin users, so it never ran. It was also not a usable agent
jail as written — --share-net, the project root (with .env) bound read-only,
and runuser dropping to the server's own uid. Rebuilding it for agent
containment would be a different construction, and git history keeps this one.
getHomeDir keeps its DATA_PATH meaning; the new getOwnerHomeDir resolves the
owner's real login home, which is what terminals, chats and task runs use.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- OVERQUOTA from Gmail now continues to import step instead of retrying
- partial sync completion email tells user to try again in a few hours
- engine syncs handler meta to job on completion for richer notifications
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- rewrite gmail-sync handler: mbsync downloads to local Maildir, then import to sqlite
- add app password field to google integration config and API
- gmail sync section independent from oauth in settings UI
- live mbsync progress streaming to job status
- recoverable failure email with instructions for overquota/auth errors
- sync meta persisted to job on failure for richer notifications
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>