[VS-NfD] Add retention for mail_outbox #234

Closed
opened 2026-07-30 01:44:01 +02:00 by fable-5 · 1 comment
Collaborator

Plan reference: n/a — 10-ist-aufnahme.md -> I-23
ADR: n/a
Effort: S (1 AT)
Depends on:

Context

Sent mails are kept forever, and digest mails contain page titles plus who
edited them. For a classified page the title alone can be protected
information, so this is an unbounded copy of content-adjacent data.

Current state

  • MailOutbox stores text_body and html_body permanently
    (apps/api/prisma/schema.prisma:683–697); no pruning job is registered.
  • Digest mails include page titles and actor names:
    apps/api/src/notifications/digest.service.ts:16,125,146
    (- ${page.pageTitle}: … (${actorNames})).
  • Transactional mails carry no content — greeting, i18n body, link only
    (apps/api/src/mail/mail-templates.ts:25–44).

Acceptance criteria

  • Sent and permanently failed entries are deleted after a configurable
    period with a documented default; the retry logic for pending
    entries is unaffected.
  • Test: sent entry past the period removed, pending entry kept,
    failed-and-retryable entry kept.
  • docs/architecture/security.md (privacy section) and #229 name the
    period.
  • Whether digest mails should carry page titles at all for classified
    pages is decided and recorded — either suppressed or accepted in
    #231.

Out of scope

Changing the mail templates' content beyond that decision, and mail
delivery logging.

**Plan reference:** n/a — `10-ist-aufnahme.md` -> I-23 **ADR:** n/a **Effort:** S (1 AT) **Depends on:** — ## Context Sent mails are kept forever, and digest mails contain page titles plus who edited them. For a classified page the title alone can be protected information, so this is an unbounded copy of content-adjacent data. ## Current state - `MailOutbox` stores `text_body` and `html_body` permanently (`apps/api/prisma/schema.prisma:683–697`); no pruning job is registered. - Digest mails include page titles and actor names: `apps/api/src/notifications/digest.service.ts:16,125,146` (`- ${page.pageTitle}: … (${actorNames})`). - Transactional mails carry no content — greeting, i18n body, link only (`apps/api/src/mail/mail-templates.ts:25–44`). ## Acceptance criteria - [ ] Sent and permanently failed entries are deleted after a configurable period with a documented default; the retry logic for pending entries is unaffected. - [ ] Test: sent entry past the period removed, pending entry kept, failed-and-retryable entry kept. - [ ] `docs/architecture/security.md` (privacy section) and #229 name the period. - [ ] Whether digest mails should carry page titles at all for classified pages is decided and recorded — either suppressed or accepted in #231. ## Out of scope Changing the mail templates' content beyond that decision, and mail delivery logging.
fable-5 added this to the M24 — VS-NfD: security quick wins milestone 2026-07-30 01:44:01 +02:00
fable-5 added the
area:storage
vs-nfd
effort:S
labels 2026-07-30 01:44:01 +02:00
Author
Collaborator

Implemented in PR #255 (commit 69d9072, CI run 511 green, fast-forward merged on Stefan's standing go-ahead for the M24 merges).

Evidence against the acceptance criteria:

  • Sent and permanently failed entries deleted after a configurable period: daily job mail-outbox-retention removes SENT rows by sentAt and FAILED rows by nextAttemptAt (last attempt's stamp) once past mail.outboxRetentionDays (new instance setting, default 30, documented in operations.md and security.md Privacy).
  • Retry logic unaffected: PENDING rows - including failed-but-retryable ones - are never matched; asserted in mail-outbox-retention.e2e.db.test.ts (sent-old removed, pending-retry and sent-fresh kept, no-op run).
  • security.md Privacy names the period; the deletion-chapter addition for #229 is recorded as a comment there; residual-risk entry on #231.
  • Digest-title decision recorded (security.md Privacy + #231): titles stay for now - no per-page classification marking exists yet to key a suppression on (ADR 0022 / M32 revisits); retention bounds the copy; a VS-NfD reference configuration can leave SMTP unconfigured.

Full api suite green (473) on a fresh DB. CD verification follows.

Implemented in PR #255 (commit 69d9072, CI run 511 green, fast-forward merged on Stefan's standing go-ahead for the M24 merges). Evidence against the acceptance criteria: - Sent and permanently failed entries deleted after a configurable period: daily job mail-outbox-retention removes SENT rows by sentAt and FAILED rows by nextAttemptAt (last attempt's stamp) once past mail.outboxRetentionDays (new instance setting, default 30, documented in operations.md and security.md Privacy). - Retry logic unaffected: PENDING rows - including failed-but-retryable ones - are never matched; asserted in mail-outbox-retention.e2e.db.test.ts (sent-old removed, pending-retry and sent-fresh kept, no-op run). - security.md Privacy names the period; the deletion-chapter addition for #229 is recorded as a comment there; residual-risk entry on #231. - Digest-title decision recorded (security.md Privacy + #231): titles stay for now - no per-page classification marking exists yet to key a suppression on (ADR 0022 / M32 revisits); retention bounds the copy; a VS-NfD reference configuration can leave SMTP unconfigured. Full api suite green (473) on a fresh DB. CD verification follows.
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#234
No description provided.