The design for qbit-email (docs/DESIGN.md): one email service for the whole QQQ system.
Core: builds on MessagingProviderInterface / SendMessageAction; registers a QBIT_EMAIL provider type that writes to the outbox (a bridge for existing callers). Transports live in the qbit because core's SMTP has no auth/STARTTLS/timeouts and its SES is SDK v1 with static keys.
Providers:email_provider rows (SMTP/PMG, SES v2, Postmark, SendGrid, Mailgun, Gmail SMTP app password; Gmail API specified, built on request); credentials as env-var names; Send Test Email action.
Outbox:email_message with claim-by-unique-attempt, leases, backoff, dead letters, idempotency keys, rate limits, provider health (the qbit-webhooks engine pattern).
Templates: versioned Markdown in a branded responsive dark-mode-safe layout, plus MJML (compiled at activation) and HTML; variables schema, preview through /qqq/v1/qbit/email/preview, auto plain text, i18n-ready.
Tracking:/qqq/hooks/email/{kind}/{provider} with SNS, basic-auth, ECDSA and HMAC verification into a durable inbox; email_event; email_suppression; RFC 8058 one-click unsubscribe; a Preferences section on core #1162.
The design for qbit-email (`docs/DESIGN.md`): one email service for the whole QQQ system.
- **Core:** builds on `MessagingProviderInterface` / `SendMessageAction`; registers a `QBIT_EMAIL` provider type that writes to the outbox (a bridge for existing callers). Transports live in the qbit because core's SMTP has no auth/STARTTLS/timeouts and its SES is SDK v1 with static keys.
- **Providers:** `email_provider` rows (SMTP/PMG, SES v2, Postmark, SendGrid, Mailgun, Gmail SMTP app password; Gmail API specified, built on request); credentials as env-var names; Send Test Email action.
- **Outbox:** `email_message` with claim-by-unique-attempt, leases, backoff, dead letters, idempotency keys, rate limits, provider health (the qbit-webhooks engine pattern).
- **Templates:** versioned Markdown in a branded responsive dark-mode-safe layout, plus MJML (compiled at activation) and HTML; variables schema, preview through `/qqq/v1/qbit/email/preview`, auto plain text, i18n-ready.
- **Tracking:** `/qqq/hooks/email/{kind}/{provider}` with SNS, basic-auth, ECDSA and HMAC verification into a durable inbox; `email_event`; `email_suppression`; RFC 8058 one-click unsubscribe; a Preferences section on core #1162.
- **PHI:** PII/PHI variables refused unless `phi_approved`; secure-message default template; HMAC-redacted snapshots and encrypted bodies per SECURED-DATA §15 (#1161); canary egress test.
- Consumers (alerts, collaboration, assistant, easypost, marketing, kof22) and why Authentik keeps its own mail; inbound phase 2.
Owner decisions (2026-10-12): all recommendations accepted.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The design for qbit-email (
docs/DESIGN.md): one email service for the whole QQQ system.MessagingProviderInterface/SendMessageAction; registers aQBIT_EMAILprovider type that writes to the outbox (a bridge for existing callers). Transports live in the qbit because core's SMTP has no auth/STARTTLS/timeouts and its SES is SDK v1 with static keys.email_providerrows (SMTP/PMG, SES v2, Postmark, SendGrid, Mailgun, Gmail SMTP app password; Gmail API specified, built on request); credentials as env-var names; Send Test Email action.email_messagewith claim-by-unique-attempt, leases, backoff, dead letters, idempotency keys, rate limits, provider health (the qbit-webhooks engine pattern)./qqq/v1/qbit/email/preview, auto plain text, i18n-ready./qqq/hooks/email/{kind}/{provider}with SNS, basic-auth, ECDSA and HMAC verification into a durable inbox;email_event;email_suppression; RFC 8058 one-click unsubscribe; a Preferences section on core #1162.phi_approved; secure-message default template; HMAC-redacted snapshots and encrypted bodies per SECURED-DATA §15 (#1161); canary egress test.Owner decisions (2026-10-12): all recommendations accepted.
🤖 Generated with Claude Code