Journaling: capture at the queue, the built-in journal, retention
ci / fork-checks (pull_request) Successful in 41s
ci / build (pull_request) Successful in 8m2s

Phase 2 of the journaling spec.

- A copy of each message is taken in MessageWrapper::queue, after DLP and
  transport rules, for every enabled journal that takes it (direction and
  scope: everyone, or accounts, groups, domains, tenants). If the copy
  can't be taken the message isn't queued (temporary failure).
- The journal report: the envelope one field a line (sender, To, Cc, Bcc
  from the envelope, list members from their ORCPT, direction, held for
  review), then the queued message byte for byte as message/rfc822.
- The built-in journal under J in the inbuxa subspace: one chain per node
  whose links name each entry by SHA-256, so entries can expire out of
  chain order; purge leaves a marker, and verify catches an entry changed
  or removed early and a report that doesn't match.
- Retention per journal (30 to 3650 days); an entry keeps what it was
  written with. The daily maintenance purges what's due, keeping entries
  whose people a legal hold covers (deleted accounts a hold keeps too),
  and records the counts in the audit log.
- inbuxa:Journal get/set, audited by the request layer. Permissions
  680-683: administrators see and change journals; the Compliance Officer
  sees, searches and exports. Whoever changes journals may grant search and
  export without holding them, so officers can still be appointed.
- Catalog entries (inbuxa:Journal, source "journal"); spec as-built notes.

tests/src/system/journal.rs: validation, internal mail with a Bcc,
outgoing into two journals, incoming over LMTP, the report and its
original, tamper and early removal caught, hold-aware purge, retention
changes leave entries alone, disabled and removed journals take nothing.
This commit is contained in:
2026-09-28 20:46:04 -07:00
parent 792ff9d1ee
commit 441ad0b18e
33 changed files with 2853 additions and 4 deletions
+5
View File
@@ -1755,6 +1755,11 @@ pub enum Permission {
SysDlpPolicyUpdate = 677,
SysDlpReviewGet = 678,
SysDlpReviewUpdate = 679,
// inbuxa: journaling
SysJournalGet = 680,
SysJournalUpdate = 681,
SysJournalSearch = 682,
SysJournalExport = 683,
SysAccountGet = 219,
SysAccountCreate = 220,
SysAccountUpdate = 221,
+13 -1
View File
@@ -7097,6 +7097,10 @@ impl EnumImpl for Permission {
b"sysDlpPolicyUpdate" => Permission::SysDlpPolicyUpdate,
b"sysDlpReviewGet" => Permission::SysDlpReviewGet,
b"sysDlpReviewUpdate" => Permission::SysDlpReviewUpdate,
b"sysJournalGet" => Permission::SysJournalGet,
b"sysJournalUpdate" => Permission::SysJournalUpdate,
b"sysJournalSearch" => Permission::SysJournalSearch,
b"sysJournalExport" => Permission::SysJournalExport,
b"sysAccountGet" => Permission::SysAccountGet,
b"sysAccountCreate" => Permission::SysAccountCreate,
b"sysAccountUpdate" => Permission::SysAccountUpdate,
@@ -7793,6 +7797,10 @@ impl EnumImpl for Permission {
Permission::SysDlpPolicyUpdate => "sysDlpPolicyUpdate",
Permission::SysDlpReviewGet => "sysDlpReviewGet",
Permission::SysDlpReviewUpdate => "sysDlpReviewUpdate",
Permission::SysJournalGet => "sysJournalGet",
Permission::SysJournalUpdate => "sysJournalUpdate",
Permission::SysJournalSearch => "sysJournalSearch",
Permission::SysJournalExport => "sysJournalExport",
Permission::SysAccountGet => "sysAccountGet",
Permission::SysAccountCreate => "sysAccountCreate",
Permission::SysAccountUpdate => "sysAccountUpdate",
@@ -8482,6 +8490,10 @@ impl EnumImpl for Permission {
677 => Some(Permission::SysDlpPolicyUpdate),
678 => Some(Permission::SysDlpReviewGet),
679 => Some(Permission::SysDlpReviewUpdate),
680 => Some(Permission::SysJournalGet),
681 => Some(Permission::SysJournalUpdate),
682 => Some(Permission::SysJournalSearch),
683 => Some(Permission::SysJournalExport),
219 => Some(Permission::SysAccountGet),
220 => Some(Permission::SysAccountCreate),
221 => Some(Permission::SysAccountUpdate),
@@ -8926,7 +8938,7 @@ impl EnumImpl for Permission {
}
}
const COUNT: usize = 680;
const COUNT: usize = 684;
}
impl serde::Serialize for Permission {