Files
selfpost/docs/plans/inbound-quarantine.md
T
mixandClaude Opus 5 b29f4845ba
test / test (push) Has been cancelled
docs: retire the code-review plan, its content now lives where it belongs
The review document was the last place several findings existed, so it could
not just be deleted. Everything still useful moved out first:

- roadmap items csrf-tokens, template-data-typing, structured-logging and
  review-2026-08-followups are now self-contained — each row names the file,
  the symptom and what "done" means, instead of pointing at a paragraph number
  in a plan file.
- security.md's CSRF accepted-risk bullet now names the csrf-tokens item, so
  the two records of that decision cannot drift apart unnoticed; the item says
  the same in the other direction.
- CHANGELOG [Unreleased] records the review itself in its intro rather than as
  an added file: the document was created and removed inside one unreleased
  cycle, so it never was part of a release.
- the declined finding (//go:build linux for the /proc reader) keeps its
  rationale in the roadmap so it is not raised again.

Also repaired three links to inbound-relay.md, deleted back when that feature's
plan was cleaned up: the two inbound plans now point at architecture.md § Mail
path for the as-built behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 00:48:13 +03:00

2.8 KiB

Plan: inbound-quarantine

Status: candidate — design TBD; needs explicit agreement before any code
Version: TBD (1.x MINOR if opt-in and backward-compatible; may warrant 2.x if it changes inbound storage or backup contract).


Goal (draft)

Let the operator hold suspicious inbound mail instead of only accept/reject at the milter — review in the panel, then release to the configured upstream, delete, or add sender to allow/deny lists.

This is a product boundary question, not a settled design. The item exists so we can compare approaches before committing.

Why it is separate from inbound-antispam-panel

inbound-antispam-panel.md covers metadata (journal + lists). Quarantine implies storing message bodies (or a durable reference to them) under /data, retention, release workflow, and a wider attack/backup surface — closer to "mini-mailbox" than pure relay.

Open questions (to decide before a checklist)

  1. Where mail lives
    • SelfPost store under /data/quarantine/ (panel owns lifecycle), or
    • delegate to rspamd/Redis and panel only proxies release (less storage in SelfPost, tighter rspamd coupling).
  2. What "release" means
    • inject into Postfix as a new delivery to the domain's upstream transport;
    • or manual download only (no automatic forward).
  3. Retention and caps
    • max age, max total bytes, per-domain limits; interaction with backup size.
  4. RBAC
    • global admin only vs domain-admin for assigned inbound domains.
  5. Threat model
    • malware in stored MIME, path traversal on extract, quota DoS on busy MX.
  6. Product fit
    • does this violate product.md "no mailboxes" if we only hold spam suspects briefly? Explicit product decision required.

Context (as-built)

  • Inbound relay forwards or rejects; no local delivery (architecture.md § Mail path).
  • Optional INBOUND_ANTISPAM_MILTER — external rspamd may quarantine on its own today, without panel integration.
  • DMARC p=quarantine is unrelated (outbound policy for receivers).

Likely out of scope (until revisited)

  • IMAP/webmail for quarantined mail.
  • End-user self-service quarantine (non-admin recipients).
  • Outbound quarantine.

Dependencies

  • Inbound relay, shipped in [1.4.0] — as built in architecture.md § Mail path.
  • Sensible to decide after or alongside inbound-antispam-panel.md (journal/lists), but not blocked on it for design discussion.

Done when (placeholder)

TBD once approach is chosen. Minimum bar would include: opt-in flag, panel list/detail, release or discard action, retention, backup inclusion documented, security review.

Implementation checklist

None yet — expand this plan after the open questions above are answered.