Skip to content

[auto-rotation feature] feat: add notifications infrastructure for key auto-rotation events#971

Open
Manuthor wants to merge 1 commit into
feat/key-rotation-schedulerfrom
feat/key-rotation-notifications
Open

[auto-rotation feature] feat: add notifications infrastructure for key auto-rotation events#971
Manuthor wants to merge 1 commit into
feat/key-rotation-schedulerfrom
feat/key-rotation-notifications

Conversation

@Manuthor
Copy link
Copy Markdown
Contributor

@Manuthor Manuthor commented May 28, 2026

Summary

Adds the notification subsystem for key rotation events: a NotificationsStore
trait backed by SQL, an SMTP email notifier (via lettre), threshold-based dedup
for renewal warnings, and a REST API for reading notifications from the UI.

This is PR 3 of 4 in the key auto-rotation feature stack (depends on PR 2: #970):

develop
  ← PR 1  docs/key-autorotation-spec          (#968)
  ← PR 2  feat/key-rotation-scheduler          (#970)
  ← PR 3  feat/key-rotation-notifications      ← this PR
  ← PR 4  feat/key-rotation-ui                 (#973)

What's included

NotificationsStore trait — crate/interfaces/src/stores/notifications_store.rs

Persistent notification log with four methods:

Method Description
insert() Persist a new notification event
list(owner) All notifications for a user
unread_count(owner) Count of unread notifications
mark_read(id) / mark_all_read(owner) Mark as read

Implemented for SQLite, PostgreSQL, and MySQL (crate/server_database/).
NoopNotificationsStore provided for the Redis-findex backend (#[cfg(feature = "non-fips")]).

SMTP email notifier — crate/server/src/notifications/email.rs

  • Sends HTML/plain-text emails on rotation_success, rotation_failure, and
    approaching_deadline events
  • Uses lettre 0.11 (async SMTP with TLS)
  • Failures are logged at warn! level and never block the rotation operation

SmtpConfigcrate/server/src/config/command_line/smtp_config.rs

[notifications.smtp]
host     = "smtp.example.com"
port     = 587
username = "kms-alerts@example.com"
password = "..."
from     = "kms-alerts@example.com"
to       = ["ops@example.com"]
starttls = true

RenewalNotificationStrategy

Configures the threshold days (default: [30, 7, 1]) at which renewal warnings
are emitted before a key's next scheduled rotation.

dispatch_renewal_warnings() — wired into auto_rotate.rs

  • Scans all keys with an active rotation policy
  • Computes days until next rotation
  • Emits a warning event only if not already warned at this threshold
    (rotate_last_warning_days attribute for dedup)

HTTP API — crate/server/src/routes/notifications.rs

Endpoint Description
GET /notifications List all notifications for the authenticated user
GET /notifications/unread/count Count of unread notifications
POST /notifications/{id}/read Mark a single notification as read
POST /notifications/read-all Mark all notifications as read

Dependencies added

  • lettre = "0.11" (async SMTP)
  • "0BSD" added to deny.toml allow list (required by quoted_printable,
    a transitive dep of lettre)

Breaking changes

None. Notifications are off by default (no SMTP config → no emails sent;
HTTP API always available).

Reviewer notes

  • The NotificationsStore is injected into KmsServer alongside the
    existing ObjectsStore — no global state.
  • The Redis-findex backend (non-fips feature) uses NoopNotificationsStore
    because Redis-findex has no relational schema.
  • 0BSD license addition to deny.toml is intentional and safe — it is the
    most permissive OSI license (no attribution required).

@Manuthor Manuthor changed the title feat: add notifications infrastructure for key auto-rotation events [auto-rotation feature] feat: add notifications infrastructure for key auto-rotation events May 28, 2026
@Manuthor Manuthor force-pushed the feat/key-rotation-scheduler branch from 4e3e03c to f27b7e5 Compare May 29, 2026 14:03
- NotificationsStore trait + implementations (SQLite, PostgreSQL, MySQL)
- SMTP email notifier (lettre) for renewal warnings and rotation events
- SmtpConfig + RenewalNotificationStrategy configuration
- dispatch_renewal_warnings() background scanner with threshold-based dedup
- rotate_last_warning_days attribute to prevent duplicate warnings
- HTTP API: GET /notifications, GET /notifications/unread/count,
  POST /notifications/{id}/read, POST /notifications/read-all
- NoopNotificationsStore for Redis-findex backend
- Allow 0BSD license (quoted_printable, transitive dep of lettre)
@Manuthor Manuthor force-pushed the feat/key-rotation-notifications branch from 5f074fa to 4b5820b Compare May 29, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant