Dispute despatched to CRA-02, certified, with the basis stated and the tradeline identified.
Written once, referenced afterwards
An audit trail that can be edited is a log. This one is append only: a correction is a new entry that points at the entry it corrects, and an export is generated from the entries rather than from the current state of the record.
Hashes and entry identifiers on this page are placeholders.
Anatomy of an entry
Every entry carries the same nine fields, whether it records a despatch, a refusal, a clock extension or a login. The rule reference is on the entry itself, not derived at read time, so a filter by rule returns the same set in five years as it does today.
idMonotonic within the tenant. Gaps are not possible.atUTC, to the millisecond, from the server clock.actorA seat, a system process, or a named external party.eventFrom a closed vocabulary. New events ship in a release, not at runtime.ruleThe statutory reference, where one governs the event.subjectCase, item, document, invoice or seat.detailHuman readable, and never the only place a fact is stored.correctsPoints at the entry this one corrects. Null in the ordinary case.prev_hashThe hash of the previous entry for the tenant.
GET /v3/audit?case=CR-2026-04187
{
"id": "AUD-2026-0918442",
"at": "2026-07-18T08:02:00.114Z",
"actor": "system",
"event": "billing.blocked",
"rule": "CROA 15 U.S.C. 1679b(b)",
"subject": { "invoice": "INV-DRAFT-2211" },
"detail": "no fee is billable before the service is fully performed",
"corrects": null,
"prev_hash": "a41c...9f02"
}A refused action is an entry. Silence is not an audit trail.
Layers, not versions
The outcome of a dispute does not overwrite the correspondence that produced it. Each layer keeps its own timestamp and its own hash, so reading a case backwards is possible without reconstructing anything.
This matters most when a result arrives that nobody expected. The question is never what the record says now. It is what the record said on the day the letter went out.
Written results of the reinvestigation received on day 26 of the thirty day window.
Date of last activity modified. The tradeline itself remains reported. The record states the change, not a promise.
Exports chain to each other
An export is signed, and it carries the hash of the previous export for the tenant. A missing export therefore breaks a chain rather than leaving a gap nobody notices. Verifying a chain needs the tenant public key and nothing else.
Verification is a command, not a support request:underwrite verify --tenant northgate --from 2026-06 --key tenant.pub
Retention
Retention is set per class and per tenant, and the platform will not accept a period below the floor a rule sets. Where no rule sets one, the default is the longest limitation period an operator has needed in practice.
| Class | Default period | Why |
|---|---|---|
| Audit entries | Life of the tenant, plus 7 years | Longest applicable limitation period an operator has raised with us. Configurable upward, never downward. |
| Generated documents | Life of the tenant, plus 7 years | Disclosure receipts and contracts are the evidence the controls depend on. |
| Correspondence and evidence | Life of the tenant, plus 7 years | Proof of despatch and proof of receipt lose their value the moment they are separated from the case. |
| Telemarketing call records | 24 months minimum | Where an operator calls consumers, TSR 16 CFR 310.5 sets the floor. The tenant may set it higher. |
| Signed exports | Life of the tenant | Each export chains to the previous one, so removing an old export breaks the chain visibly. |
| Consumer identity fields | Tenant defined, minimum honoured | Deletion requests are executed against identity fields while the tokenised case history stays intact. |

A deletion request from a consumer is executed against identity fields. The tokenised case history, the clocks and the audit entries survive it, because deleting them would destroy the operator's own evidence of having complied.