Export what a legal hold keeps as a ZIP (LH-12) #73

Merged
jcoffey-dev merged 1 commits from feature/hold-export into main 2026-09-28 04:51:16 +00:00
Owner

Phase 4 of the audit-hold-lock spec: inbuxa:HoldExport.

  • set starts an export of a hold (optionally some of its accounts) with a reason; it's built in the background and get reports running / ready / failed, with item count, size and the ZIP's SHA-256.
  • The ZIP: per account, mail/<folder>/*.eml, calendar/, contacts/, files/, archived/<kind>/; manifest.csv with a SHA-256 per file, and manifest.sha256.
  • Follows the hold: uncovered accounts are left out; its date range applies to live mail, events and archived items alike.
  • The file is a blob of whoever started it, lasting as long as an upload (uploadTtl, default kept). Exports are never changed or destroyed. Needs sysLegalHoldExport, an active hold and a reason; recorded in the audit log.
  • Built in memory, capped at 2 GB with a clear error.

Tested: jmap unit tests; legal_hold_tests on RocksDB, PostgreSQL and MySQL; end to end from the console against a local server. Not covered: archived-item ranges with two differently ranged holds over one account.

Console side: inbuxa-admin feature/hold-export.

Phase 4 of the audit-hold-lock spec: `inbuxa:HoldExport`. - `set` starts an export of a hold (optionally some of its accounts) with a reason; it's built in the background and `get` reports running / ready / failed, with item count, size and the ZIP's SHA-256. - The ZIP: per account, `mail/<folder>/*.eml`, `calendar/`, `contacts/`, `files/`, `archived/<kind>/`; `manifest.csv` with a SHA-256 per file, and `manifest.sha256`. - Follows the hold: uncovered accounts are left out; its date range applies to live mail, events and archived items alike. - The file is a blob of whoever started it, lasting as long as an upload (`uploadTtl`, default kept). Exports are never changed or destroyed. Needs `sysLegalHoldExport`, an active hold and a reason; recorded in the audit log. - Built in memory, capped at 2 GB with a clear error. Tested: jmap unit tests; `legal_hold_tests` on RocksDB, PostgreSQL and MySQL; end to end from the console against a local server. Not covered: archived-item ranges with two differently ranged holds over one account. Console side: inbuxa-admin `feature/hold-export`.
jcoffey-dev added 1 commit 2026-09-28 04:46:20 +00:00
Export what a legal hold keeps as a ZIP (LH-12)
ci / build (pull_request) Successful in 4m47s
ci / fork-checks (pull_request) Successful in 14s
68dd749291
inbuxa:HoldExport/set takes a hold, optionally some of the accounts it
covers, and a reason; the collection runs in the background and get
says when it's ready. The ZIP has, per account, mail as .eml under its
folders, calendars as .ics, contacts as .vcf, files as stored, and the
archived items the hold keeps under archived/; a manifest.csv gives each
entry's account, kind, folder, date, whether it was archived, size and
SHA-256, and manifest.sha256 hashes the manifest. Accounts the hold
doesn't cover are left out, and items outside its date range are too:
live mail by arrival, events by start, and archived items the same way,
so an export doesn't carry deleted items that only another hold keeps.

The finished file is a blob of whoever started the export, so only they
download it, and it lasts as long as any upload (uploadTtl). Exports
are records under the hold (SUBSPACE_INBUXA H/e): never changed or
destroyed, each with its status, counts, size and checksum. Starting
one needs sysLegalHoldExport, an active hold and a reason, and is
recorded in the audit log like the audit log's own export.

The build is in memory and capped at 2 GB; bigger holds fail with a
message saying so, and are split by picking accounts.

Tested: unit tests for safe ZIP names and the manifest and its hash;
the legal_hold system test, on RocksDB, PostgreSQL and MySQL, exports a
hold end to end (live and archived mail, the manifest's hash, an asked-
for account the hold doesn't cover left out) and checks the refusals
(no reason, a user without the permission, a released hold) and the
audit record; and by hand from the console on a local server. Not
covered by a test: the archived-item date range with two holds of
different ranges over one account.
jcoffey-dev merged commit 1d5f4a2cd3 into main 2026-09-28 04:51:16 +00:00
jcoffey-dev deleted branch feature/hold-export 2026-09-28 04:51:17 +00:00
jcoffey-dev referenced this issue from a commit 2026-09-28 04:55:58 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: inbuxa/inbuxa-server#73