Skip to main content

Data lifecycle guarantees

What this covers / who it's for. What the platform keeps, for how long, what actually deletes it, what right-to-be-forgotten does (and refuses to do), and what freeze/closure mean for data. These are commitments you can repeat to a customer or a regulator — each row cites where the fact lives in code.

The universal floor: 7 years

One number governs everything regulated: the compliance retention floor — 2555 days (7 years) (foundation.compliance_retention_floor_days, app-modules/foundation/config/foundation.php). Every prune that touches compliance-relevant data clamps its cutoff up to this floor, even when its own configured window is shorter. A mis-configured short window cannot delete regulated data early — the clamp wins.

And one universal convention: deleted ≠ destroyed. Domain records are soft-deleted (hidden, recoverable, still present for audit) and every write records who did it (the blamable convention). Hard deletion happens only through the named prune mechanisms below.

The retention table

WhatWindowPrune mechanism (today)Source
Vendor request log (every outbound provider call)90 daysDaily prune, live. Telemetry posture: the authoritative KYB record lives elsewhere, so the floor does not apply; a deployment can flip it to compliance-relevant, which clamps it to the floorapp-modules/rails/config/rails.php
Inbound webhook deliveries30 daysDaily prune, liveapp-modules/webhooks/config/webhook-client.php
Async requests (exports/statements poll records)30 days, terminal (succeeded/failed) rows only — a stuck non-terminal row is never pruned (it is an operational signal)Daily prune, live. Never touches the produced artifacts, which live under the owning feature's retentionasync-requests README
Task-run ledger (fleet/background work history)90 days, terminal runs onlyDaily prune, live; the underlying batch bookkeeping ages out separately (48 hours finished / 7 days stuck-or-cancelled)app-modules/task-runner/config/task-runner.php
Command idempotency claims (bus bookkeeping)Soft-deleted after 30 days, hard-deleted 7 days after thatDaily prune, live. Bookkeeping, explicitly exempt from the floorapp-modules/foundation/config/foundation.php
Resolved drift records (provider divergence evidence)Configured 365 days — but clamped to the floor, so effectively 7 years today; unresolved drift is never prunedDaily prune, liveapp-modules/provider-mirror/config/provider-mirror.php
Audit trailNever pruned in-app. Append-only, tamper-evident; the growth strategy is off-platform WORM export — which ships disabled until a write-once bucket is provisionedNo in-app deletion existsaudit README
DLP access/egress logsNever pruned in-app (part of the compliance floor)No in-app deletion existsdlp README
Comms log (every notification/email sent)No window set — kept indefinitely today. The per-class prune mechanism is shipped and scheduled but inert until legal/compliance sign off windows; compliance notices will clamp to the floor when they doShipped, inertnotification README
Document access log (every download served)No window set — kept indefinitely today. Same shipped-but-inert posture, floor-clamped per outcome class when configuredShipped, inertdocuments README

Prune schedules (all daily, staggered) are enumerated in Observability & ops.

Right to be forgotten: crypto-shred

Document erasure is crypto-shred, not file deletion (documents README):

  • The file's own encryption key is destroyed. Each document is encrypted under its own per-file key; dropping that key makes the stored ciphertext permanently unrecoverable without touching the blob. The subject-identifying filename is scrubbed in the same step.
  • The row survives as a tombstone — the metadata proof that the document existed and was erased, with when and under which erasure reference. Every serve path refuses a shredded document explicitly.
  • Blob deletion is optional and off by default for vault-encrypted documents (the key drop already guarantees unreadability; physical deletion awaits WORM sign-off). The exception: documents that arrived via the direct-to-storage path have no per-file key, so for those the verified object delete is the erasure and is mandatory.
  • RTBF is refused inside the retention window — plainly: regulation beats RTBF. A shred request for a document still inside its regulatory window (never shorter than the 7-year floor) is hard-refused with an explicit error. This is by design; do not promise erasure of KYB/KYC material inside the window.
  • It is a deliberate operator console action today — there is no HTTP endpoint and no self-service erasure surface.

Caveat from Where data lives: shredding our copy does not touch the copies the provider holds — a full erasure conversation includes the provider.

Freeze and closure: what happens to data

(Compliance & trust, compliance README)

  • Freeze blocks actions, deletes nothing. A frozen tenant's money-movement and other state-changing actions are refused with an explicit "account frozen" error; data, history, and evidence remain fully intact and operator-visible. Unfreezing releases anything held in the meantime.
  • Closure is terminal — and data is retained per the schedule above. Closing an account ends activity; it does not trigger deletion. Retained documents of closed/offboarded tenants are treated as frozen evidence: integrity checks, retention, and RTBF apply to them exactly as to live tenants.

What you can promise

  1. Nothing regulated is deleted before 7 years — enforced in code, not by policy memo.
  2. The audit trail and DLP logs are never deleted by the application.
  3. Comms and document-access history are currently kept indefinitely (pruning awaits signed-off windows — that is the honest ship-state, and also the current cost/growth story).
  4. Erased documents are cryptographically unrecoverable, provably tombstoned — and erasure inside the retention window is refused, not quietly skipped.
  5. Freezing or closing an account never destroys data.

← Product wiki index