Journaling: search, read and export over JMAP, and the chain check
ci / fork-checks (pull_request) Successful in 16s
ci / build (pull_request) Successful in 8m0s

Phase 4 of the journaling spec.

- inbuxa:JournalEntry/query and /get (sysJournalSearch): filter by time,
  sender, recipient, either, direction, subject words, Message-ID and
  journal, newest first; the whole report only when asked for.
- inbuxa:JournalExport/set (sysJournalExport): a reason is required; a
  ZIP of the matching reports with manifest.csv, exceptions.csv and
  manifest.sha256, up to 10,000 reports and 1 GB.
- inbuxa:JournalVerification/set (sysJournalGet): chains and reports
  rechecked.
- Every search, listing, read, export and check is written to the audit
  log before anything is returned, with existing actions only.
- Catalog entries for the three objects; spec as-built notes.

journal_tests: administrators can't search; a Compliance Officer searches,
lists, reads a report, exports (reason required) and checks the chain;
the officer can't change journals; each of those is in the audit log.
This commit is contained in:
2026-09-28 21:45:09 -07:00
parent abd5811420
commit daa486f7e7
17 changed files with 1725 additions and 2 deletions
+30
View File
@@ -136,6 +136,36 @@ retention = "object-life"
note = ["content"]
acceptedBy = ["identifier"]
[object."inbuxa:JournalEntry"]
file = "inbuxa_journal_entry.rs"
default = "none"
whose = ["holder", "correspondent"]
where = ["data-store", "blob-store"]
scope = "server"
retention = { setting = "inbuxa:Journal.retentionDays" }
[object."inbuxa:JournalEntry".properties]
sender = ["identifier", "contact"]
recipients = ["identifier", "contact"]
subject = ["content"]
messageId = ["identifier"]
report = ["content", "identifier", "contact", "metadata"]
[object."inbuxa:JournalExport"]
file = "inbuxa_journal_entry.rs"
default = "none"
whose = ["holder", "correspondent"]
where = ["blob-store"]
scope = "server"
retention = { setting = "x:Jmap.uploadTtl" }
[object."inbuxa:JournalExport".properties]
blobId = ["identifier", "contact", "content"]
filter = ["identifier", "contact"]
reason = ["content"]
[object."inbuxa:JournalVerification"]
file = "inbuxa_journal_entry.rs"
default = "none"
[object."inbuxa:LegalHold"]
file = "inbuxa_legal_hold.rs"
default = "none"