Skip to content

Automatically delete expired WKD keys and notify users before expiration #1082

@0x46616c6b

Description

@0x46616c6b

Currently, the keyExpireTime field on OpenPgpKey is populated during import but never evaluated. Expired keys remain stored and served via WKD indefinitely.

Goals

  1. Notify users before their OpenPGP key expires via email, so they can upload a new key in time
  2. Automatically delete expired OpenPGP keys to avoid serving outdated keys via WKD

Proposed Implementation

1. New UserNotificationType: OPENPGP_KEY_EXPIRING

  • Add a new enum case for upcoming key expiration
  • Display a notification banner on the account page with a link to the OpenPGP key management page (similar to password_compromised)

2. Email notification via UserNotificationEvent

  • Add a listener for UserNotificationEvent that sends an email to the user
  • Use the existing Builder/Sender pattern (new OpenPgpKeyExpiringMessageBuilder + OpenPgpKeyExpiringMessageSender)
  • The UserNotificationRateLimiter already prevents duplicate notifications, ensuring the email is only sent once per rate-limit window
  • This approach also benefits PASSWORD_COMPROMISED — the same listener could handle email delivery for all notification types in the future

3. New scheduled task: CheckExpiredOpenPgpKeys

  • Add a new daily message + handler to MaintenanceSchedule
  • The handler should:
    • Notify: Find keys expiring within the next 30 days and create a UserNotification of type OPENPGP_KEY_EXPIRING (using the rate limiter to avoid duplicates), which triggers the email via the event listener
    • Delete: Find keys where keyExpireTime < now and remove them (triggering cache invalidation via the existing InvalidateOpenPgpKeyCacheListener)

4. Notification cleanup

  • Remove the OPENPGP_KEY_EXPIRING notification when the user uploads a new key

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions