[Decision] Email notification delivery through mail capability #2

Closed
opened 2026-07-13 01:57:36 +02:00 by zemion · 3 comments
Owner

Decide and implement how notification messages should be delivered as email when the mail module is enabled.

Acceptance Criteria

  • Decide whether email notifications are only available when the mail module provides a delivery capability, or whether notifications may keep a standalone SMTP/file-mail fallback.
  • Define the capability contract for mail-backed notification delivery, including recipient handling, tenant scoping, credentials/profile selection, and failure reporting.
  • Implement the chosen adapter without creating a hard dependency from notifications to mail.
  • Expose delivery status clearly in the notification center and keep in-app notifications working without mail.

Notes

  • This is intentionally marked for triage because the product decision affects module coupling and deployment expectations.
  • Existing local file mail delivery in notifications is useful for development but should not become an accidental production mail stack.
Decide and implement how notification messages should be delivered as email when the mail module is enabled. ## Acceptance Criteria - [ ] Decide whether email notifications are only available when the mail module provides a delivery capability, or whether notifications may keep a standalone SMTP/file-mail fallback. - [ ] Define the capability contract for mail-backed notification delivery, including recipient handling, tenant scoping, credentials/profile selection, and failure reporting. - [ ] Implement the chosen adapter without creating a hard dependency from notifications to mail. - [ ] Expose delivery status clearly in the notification center and keep in-app notifications working without mail. ## Notes - This is intentionally marked for triage because the product decision affects module coupling and deployment expectations. - Existing local file mail delivery in notifications is useful for development but should not become an accidental production mail stack. <!-- codex-source:notification-followups-2026-07-13 -->
Author
Owner

Decision briefing

Recommended production boundary:

  • The in-app notification is the canonical durable record and always works without Mail.
  • Email is a secondary delivery attempt submitted through the optional durable Mail delivery capability. Notifications never owns SMTP credentials, profiles, retries, or a second production transport stack.
  • Local file/EML delivery is a development adapter only and must be explicitly marked non-production.
  • Mail absence or disablement makes the email channel unavailable or paused; it must not lose the in-app notification or mark it failed.
  • A system/tenant policy selects an allowed notification Mail profile. Users may control channel/category/frequency within policy, but may not inject arbitrary SMTP credentials.
  • The first slice should use a verified primary account address, freeze the effective address at enqueue time, redact it from logs/events, and expose queued/accepted/failed/paused status separately from read state.

Remaining bounded product choices:

  1. Email opt-in or opt-out by default.
  2. Which categories are immediate, digestible, or in-app only.
  3. Whether mandatory security/administrative notices may override user preference.
  4. Whether only the verified primary address is allowed initially.
  5. Whether digest delivery belongs in the first slice.

Suggested baseline: verified primary address only; immediate email for action_required and security notices, optional email for informational notices, no digest in the first slice, and mandatory categories controlled transparently by Policy.

## Decision briefing Recommended production boundary: - The in-app notification is the canonical durable record and always works without Mail. - Email is a secondary delivery attempt submitted through the optional durable Mail delivery capability. Notifications never owns SMTP credentials, profiles, retries, or a second production transport stack. - Local file/EML delivery is a development adapter only and must be explicitly marked non-production. - Mail absence or disablement makes the email channel `unavailable` or `paused`; it must not lose the in-app notification or mark it failed. - A system/tenant policy selects an allowed notification Mail profile. Users may control channel/category/frequency within policy, but may not inject arbitrary SMTP credentials. - The first slice should use a verified primary account address, freeze the effective address at enqueue time, redact it from logs/events, and expose queued/accepted/failed/paused status separately from read state. Remaining bounded product choices: 1. Email opt-in or opt-out by default. 2. Which categories are immediate, digestible, or in-app only. 3. Whether mandatory security/administrative notices may override user preference. 4. Whether only the verified primary address is allowed initially. 5. Whether digest delivery belongs in the first slice. Suggested baseline: verified primary address only; immediate email for `action_required` and security notices, optional email for informational notices, no digest in the first slice, and mandatory categories controlled transparently by Policy.
Author
Owner

Implemented according to the accepted recommendation and pushed in Core f0898fc, Mail 0cb6719, and Notifications 8153a1d.

In-app notifications remain canonical and work without Mail. Production email is submitted only through the optional mail.notification_delivery capability; Notifications has no hard Mail import or standalone production SMTP stack. Mail owns tenant/profile resolution, credentials, durable submission, retry and failure behavior. EML/file delivery is explicitly development-only. When Mail or a usable profile is absent, email delivery is reported as paused while the in-app notification remains available.

The notification center exposes sending, accepted and paused states. Verification: 13 Notifications tests, 2 Mail capability tests, all module permutations, and the full boundary battery pass.

Implemented according to the accepted recommendation and pushed in Core `f0898fc`, Mail `0cb6719`, and Notifications `8153a1d`. In-app notifications remain canonical and work without Mail. Production email is submitted only through the optional `mail.notification_delivery` capability; Notifications has no hard Mail import or standalone production SMTP stack. Mail owns tenant/profile resolution, credentials, durable submission, retry and failure behavior. EML/file delivery is explicitly development-only. When Mail or a usable profile is absent, email delivery is reported as paused while the in-app notification remains available. The notification center exposes sending, accepted and paused states. Verification: 13 Notifications tests, 2 Mail capability tests, all module permutations, and the full boundary battery pass.
zemion removed the codex/needs-human
status
needs-info
labels 2026-07-30 17:46:58 +02:00
Author
Owner

Codex State: note

Summary

  • Decision confirmed: production email notifications are delivered only through the optional Mail capability.
  • File delivery remains development-only and must not be presented as a production transport.
## Codex State: note ### Summary - Decision confirmed: production email notifications are delivered only through the optional Mail capability. - File delivery remains development-only and must not be presented as a production transport.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GovOPlaN/govoplan-notifications#2