-
Notifications
You must be signed in to change notification settings - Fork 1
Manage Retention
Auditors do not just want your evidence — they want proof that you kept it for
as long as the regulator demands, and that nobody quietly shortened that window.
Evidentia's retention surface tracks per-record retention metadata: a
regulator-aligned classification, a mandatory-retention lock_until date, a
WORM-style extend-only lock, an optional legal hold, and a forward-only lifecycle
that walks a record from active through to purged. This guide walks the full
lifecycle with the evidentia retention commands and shows the equivalent in the
web console.
This surface tracks the metadata about a record's retention — it does not move or delete the underlying evidence. Deleting a retention record removes only the tracking entry, never the file it points at.
- Evidentia installed (
pip install evidentiaor the monorepo dev checkout). No extra is required for the CLI retention verbs. - For the web console: the API server running with the
[gui]extra. See Serve the local web UI.
Each record carries a RetentionLifecycleStage, a four-member enum, and a
classification that sets the regulator-stated minimum retention period. The
lifecycle is a forward-and-recoverable state machine — active and
preserved can move between each other, but once a record expires it can only be
purged, and purged is terminal:
active ──> preserved ──> expired ──> purged
▲ │ (terminal)
└───────────┘
-
active— in its retention window; the default for a new record. -
preserved— held for a specific reason (for example a legal hold or an audit in progress). -
expired— past its retention window; eligible to be purged. -
purged— securely removed; terminal.
The state machine rejects any illegal jump and tells you the legal next stages. A legal hold blocks expiry/purge regardless of stage — it is the brake you pull when litigation or an investigation freezes a record in place.
evidentia retention set --classification sec-17a-4 --record-pointer "s3://audit-bucket/2026/trade-blotter.parquet"--classification is the only required flag. It selects the regulator regime,
which sets the default retention period: one of sec-17a-4, finra-3110,
irs-tax, sox-404, hipaa, glba, pci-dss, model-risk, gdpr, or
generic. The command echoes the new record id and the computed lock_until:
Tracked retention record (id: e8aa2085-c9c8-4b24-9d6e-4f13f75ec02c);
classification: sec-17a-4; lock_until: 2032-06-20
Override the regulator default with --retention-period-days, point at the
underlying record with --record-pointer (a file path or S3/Azure URL), freeze
the record from the start with --legal-hold, cross-reference a written policy
with --policy-name, and attach free-text context with --notes:
evidentia retention set --classification finra-3110 --retention-period-days 2555 --record-pointer "/evidence/2026/comms-archive.zip" --legal-hold --policy-name "RR-2026-comms" --notes "Frozen pending FINRA inquiry"evidentia retention listlist prints a table of every tracked record — id, classification, lifecycle
stage, lock-until date, whether it is currently locked, whether a legal hold is
set, and the record pointer:
Retention records (1 total)
┌──────────┬────────────┬────────┬────────────┬─────────┬───────┬─────────────┐
│ ID │ Classific… │ Stage │ Lock-until │ Locked? │ Hold? │ Pointer │
├──────────┼────────────┼────────┼────────────┼─────────┼───────┼─────────────┤
│ e8aa2085 │ sec-17a-4 │ active │ 2032-06-20 │ ✓ │ — │ s3://audit… │
└──────────┴────────────┴────────┴────────────┴─────────┴───────┴─────────────┘
Narrow the list with --classification and --lifecycle (one of active,
preserved, expired, purged), and add --json for machine-readable output:
evidentia retention list --classification sec-17a-4 --lifecycle active --jsonShow one record in full — including its created/updated timestamps and notes:
evidentia retention show e8aa2085-c9c8-4b24-9d6e-4f13f75ec02cRetention record (e8aa2085-c9c8-4b24-9d6e-4f13f75ec02c)
Classification: sec-17a-4
Lifecycle stage: active
Retention period: 2190 days
Lock-until: 2032-06-20
Currently locked: YES
Legal hold: no
Record pointer: s3://audit-bucket/2026/trade-blotter.parquet
show also accepts --json. (retention show and the lifecycle verbs accept
either the full UUID or the short 8-character prefix shown in list.)
Retention is WORM-style: you can push the lock_until date later, never
earlier. This is what makes the record auditor-defensible — the mandatory window
can grow (for a legal hold or a longer regime) but can never be quietly trimmed.
evidentia retention extend e8aa2085-c9c8-4b24-9d6e-4f13f75ec02c --new-lock-until 2035-01-01Extended retention id=e8aa2085; lock_until: 2032-06-20 → 2035-01-01
--new-lock-until takes an ISO-8601 YYYY-MM-DD date and is required. Asking
for an earlier date is rejected:
Error: WORM forbids shortening retention (current lock_until=2035-01-01;
requested=2026-01-01).
evidentia retention transition e8aa2085-c9c8-4b24-9d6e-4f13f75ec02c --new-stage preservedTransitioned retention id=e8aa2085: active → preserved
--new-stage is required and must be a legal next stage. The state machine
blocks any illegal jump and names the valid targets:
Error: Illegal transition: preserved → purged. Valid from preserved: ['active',
'expired']
To purge a record you must first walk it to expired, then transition to
purged. A record under legal hold cannot be expired or purged at all.
evidentia retention reportThis prints a Markdown audit summary to stdout: a stage-by-stage count, how many records are locked and under legal hold, and a per-classification distribution.
# Retention Posture Report
_As of 2026-06-22, 1 record(s) tracked across the audit chain-of-custody._
| Stage | Count |
| --- | --- |
| ACTIVE | 1 |
...
Write it to a file (and overwrite an existing file) instead of printing:
evidentia retention report --output retention-posture.md --forceevidentia retention delete e8aa2085-c9c8-4b24-9d6e-4f13f75ec02cThis removes only the metadata record, not the underlying evidence. It is for
cleaning up tracking entries for records that were deleted by other means — a
mis-imported entry or a test fixture. For an actual evidence purge, transition
the lifecycle to purged first. delete prompts for confirmation unless you
pass --yes.
Everything above also works from the browser. Start the server with
evidentia serve and open the Retention screen from the sidebar (under
Govern; route /retention). The screen mirrors the CLI surface and the same
server-side state machine, so it never offers a transition the API would reject.
-
Add a record. The New retention record form sits at the top. Pick a
classification (the only required field — the server defaults the
retention period to the regulator-stated minimum when you leave the days
blank), optionally set the retention period, record pointer, policy name, and
notes, and tick Place under legal hold to freeze it from the start. Click
Add record and it lands in the inventory below. This calls
POST /api/retention. -
Generate a report. The Retention report card has a Generate report
button that fetches the same Markdown summary as
retention report(viaGET /api/retention/report) and renders it inline as preformatted text. -
Filter. Two chip rows narrow the inventory without a page reload — one by
classification and one by lifecycle stage — the same two axes the
retention list --classification/--lifecycleflags control. Click a chip to apply it; click All … to clear that axis. - Select. Click a record card to open its detail panel in place. The panel repeats the classification, lifecycle stage, and any legal-hold badge, and shows the retention period, lock-until, policy, and timestamps.
-
Extend the lock-until. The Extend lock-until form takes a date and
issues the same WORM extend-only change as
retention extend(viaPOST /api/retention/{id}/extend). A shorten attempt is rejected server-side and the error surfaces inline. -
Transition the stage. The Transition stage controls offer only the
legal next stages for the current stage —
activeoffers Preserved and Expired;expiredoffers only Purged; apurgedrecord offers nothing (it is terminal). Clicking issuesPOST /api/retention/{id}/transition. -
Delete. Delete record asks for an in-panel confirmation, then issues
DELETE /api/retention/{id}— metadata only, the same as the CLI verb.
- Prove the evidence itself is intact: Sign and verify evidence and Concepts → Evidence integrity cover the cryptographic chain-of-custody that retention metadata sits alongside.
- Track remediation work to a deadline: Manage a POA&M uses the same forward-only-lifecycle discipline for gap closure.
- Run a recurring compliance cadence: CONMON deployment.
-
"Retention record '…' not found" — confirm the id with
evidentia retention list(it shows the short 8-character prefix; you can pass either that prefix or the full UUID). -
"WORM forbids shortening retention" —
extendonly moves the lock-until later. There is no supported way to shorten a retention window; that is the WORM guarantee. -
"Illegal transition: … → …" — the lifecycle is a state machine. The error
lists the legal next stages; to purge a record, walk it through
expiredfirst. -
A record won't expire or purge — check for a legal hold (
Hold?column inlist, or the Legal hold badge in the console). A held record is frozen against expiry and purge by design. -
The console can't fetch records — the page shows "Could not fetch retention
records. Is the backend running?" if the API is down. Start it with
evidentia serve.
-
- AI Governance
- Air Gapped Install
- Ci Integration
- CONMON Deployment
- Emit Cyclonedx VEX
- Emit OCSF Detection
- Emit SARIF
- Emit Traceability Matrix
- Explain Controls
- Generate And Quantify Risk
- Governance Metrics And Workflows
- Ingest OCSF
- Manage Catalogs
- Manage Model Risk
- Manage POAM
- Manage Retention
- Manage Third Party Risk
- MCP Client Setup
- OSPS Self Assessment
- Push To Integrations
- Run Collectors
- Run Gap Analysis
- Serve The Web Ui
- Sign And Verify Evidence
- Track Evidence Lineage