feat(commandboard-api): expose AgentMail (agentbbs mailbox) routes (#86)

Mount @logicsrc/plugin-agentmail in the CommandBoard API so members can
list/read/search/send mail over the existing agentbbs Mailu server.

- src/agentmail.ts: inject imapflow + nodemailer + mailparser drivers into
  the plugin's Mailu transport (kept out of the plugin by design); env-driven
  builder (AGENTMAIL_BACKEND=mailu → bbs Mailu, else in-memory singleton for
  dev/test). Handles STARTTLS cert-vs-loopback via AGENTMAIL_SMTP_TLS_SERVERNAME.
- index.ts: register agentMailPlugin + 7 routes under /api/plugins/agentmail/*
  (mailboxes, list, read, search, send, PATCH flags, delete). Acting member
  from x-agentmail-member header (else AGENTMAIL_MEMBER), paid-gated;
  MailAccessError->402, DraftError->422.
- 6 route tests (in-memory backend) + contract test plugin-id list updated.
  commandboard-api 20/20, builds clean.

Note: run `npm install` to refresh the lockfile for the 3 new deps.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-06-27 08:54:00 -07:00 committed by GitHub
parent 152cc444ae
commit f27210a192
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 520 additions and 4 deletions

View file

@ -68,7 +68,7 @@ describe("CommandBoard API contracts", () => {
};
expect(response.status).toBe(200);
expect(body.plugins.map((plugin) => plugin.id)).toEqual(["coinpay", "ugig", "sh1pt", "c0mpute", "feed-discovery", "social-accounts", "email-accounts"]);
expect(body.plugins.map((plugin) => plugin.id)).toEqual(["coinpay", "ugig", "sh1pt", "c0mpute", "feed-discovery", "social-accounts", "email-accounts", "agentmail"]);
expect(body.plugins.find((plugin) => plugin.id === "sh1pt")).toMatchObject({
enabled: true,
capabilities: expect.arrayContaining(["projects.sync", "actions.publish", "deployments.status"])