ADR-0083: VayuMail Role-Based Accounts and Local Mailbox Search
Status: Accepted Date: 2026-06-25 Author: @johalputt
Context
VayuMail's admin-managed accounts were a flat list (email + password + active), with no notion of permissions, and the mailbox had no way to find a message beyond paging through folders. Moving toward a Gmail-like experience requires both, but without violating the single-binary / low-resource / zero-telemetry constitution.
Decision
- Role-based accounts.
vayumail_accountsgains arolecolumn (idempotentALTER TABLE, defaultauthor). Built-in roles areadministrator,editor,author, andreviewer(read-only); operators may also assign a custom role (lowercased,[a-z0-9-_], capped at 32 chars). Permission helpers —RoleCanSend(everyone except reviewer),RoleCanDelete(administrator/editor),RoleCanManageAccounts(administrator) — express capabilities. Account creation and deletion remain restricted to the VayuPress admin session (the/osroutes are admin-only); roles add a finer permission layer for per-account actions and future SMTP submission. - Bounded local search.
Maildir.Searchscans an account's folders for a query in From/To/Subject, falling back to a body read only on a header miss. It is capped (maxScanfiles, resultlimit) so it stays cheap on a 4–8 GB VPS. There is no external search index and no extra service — it reads the same Maildir files already on disk.
Consequences
- Positive: foundational Gmail-like capabilities (permissions + findability)
with zero new dependencies and no daemon; backward compatible (the role column
migrates in place, defaulting existing accounts to
author). - Trade-off: search is linear over Maildir (bounded), not a full inverted index; adequate for personal/team mailboxes, revisited if very large mailboxes need it. Role enforcement on outbound SMTP submission lands with the per-account submission path (v1.14.0 roadmap).
Update (2026-09-25): the reviewer role is enforced, and the helpers are gone
The three helpers above were never called outside their own unit test. The
console offered "Reviewer — read-only" while a reviewer could send (webmail,
SMTP submission) and delete or move (webmail, IMAP, POP3). RoleCanDelete also
described a rule the product never had: author and mailbox holders have
always been able to delete their own mail, and enforcing it would have taken
that away.
They are replaced by one predicate, RoleReadOnly, and one engine question,
Engine.MailboxReadOnly(login). A reviewer's IMAP SELECT opens read-only, POP3
refuses DELE, submission refuses MAIL, and the engine refuses the holder's
own delete and move (writeAuthorised), so every webmail path is covered. An
administrator acting on the mailbox is not bound, because the role describes
its holder. The webmail does not offer a reviewer Compose, Reply, Forward,
Move, Trash or Delete. Each path is tested with a non-reviewer control and
mutation-checked (readonly_role_test.go,
mail_reviewer_readonly_test.go).