mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-10-03 05:07:10 +00:00
Add AgentMail plugin: paid-member mailbox client for humans + agents
@logicsrc/plugin-agentmail provides read/search/compose/send/flag/delete over an injected MailTransport, gated to Founding Lifetime (paid) members. Returns plain JSON-serializable domain objects so the same API serves a human TUI, the CLI, MCP, and bots. - domain.ts: transport-agnostic types + pure helpers (parse/format address, normalizeDraft, isValidEmail, snippet) - ports.ts: MailTransport seam - service.ts: AgentMailService (inbox/list/read/search/send/reply/flag/delete) - access.ts: paid-member gate (assertPaid) + capability constants - transports/memory.ts: complete in-memory backend (tests/dev/reference) - transports/mailu.ts: self-hosted Mailu seam (mail.profullstack.com IMAP + smtp.profullstack.com submission) with injected IMAP/SMTP drivers - index.ts: PluginDefinition (manifest, routes, capabilities, tuiPanels) - registered in the root build; 20 vitest tests pass Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
bf046ae280
commit
e304eac761
14 changed files with 908 additions and 1 deletions
40
plugins/agentmail/src/access.ts
Normal file
40
plugins/agentmail/src/access.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Access control for AgentMail. Mail is a Founding Lifetime Member (paid) perk,
|
||||
// so every service call is gated on a paid identity. Capability constants keep
|
||||
// route/manifest wiring and runtime checks in sync.
|
||||
|
||||
export const AGENTMAIL_CAPABILITIES = {
|
||||
mailboxList: "mailbox.list",
|
||||
messageList: "message.list",
|
||||
messageRead: "message.read",
|
||||
messageSearch: "message.search",
|
||||
messageCompose: "message.compose",
|
||||
messageSend: "message.send",
|
||||
messageFlag: "message.flag",
|
||||
messageDelete: "message.delete",
|
||||
accessGate: "access.gate"
|
||||
} as const;
|
||||
|
||||
export type AgentMailCapability = (typeof AGENTMAIL_CAPABILITIES)[keyof typeof AGENTMAIL_CAPABILITIES];
|
||||
|
||||
/** Who is acting: a BBS member name and whether they hold the paid membership. */
|
||||
export interface MailIdentity {
|
||||
/** The member's local-part / handle, e.g. "alice". */
|
||||
name: string;
|
||||
/** True for a Founding Lifetime Member; mail is gated on this. */
|
||||
paid: boolean;
|
||||
}
|
||||
|
||||
/** Raised when a non-paid (or missing) identity attempts a mail action. */
|
||||
export class MailAccessError extends Error {
|
||||
constructor(message = "AgentMail is a Founding Lifetime Member feature ($99 one-time) — upgrade: ssh join@bbs.profullstack.com") {
|
||||
super(message);
|
||||
this.name = "MailAccessError";
|
||||
}
|
||||
}
|
||||
|
||||
/** Throws MailAccessError unless the identity is a paid member. */
|
||||
export function assertPaid(identity: MailIdentity): void {
|
||||
if (!identity || !identity.name || !identity.paid) {
|
||||
throw new MailAccessError();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue