A ctlplne studio product

Data Retention Matrix

What this is. One privacy map for the data probectl keeps: what kind of data it is, why it exists, where it lives, and what clock deletes it. ELI5: every data set is a labeled box. The label says what is inside, why we are allowed to keep it, which shelf it sits on, and which timer removes it.

This page is a governance/control map, not a new retention engine. Today, retention is still enforced by the owning stores and lifecycle paths: ClickHouse TTLs plus ClickHouse hourly rollups, the in-memory TSDB window, derived identity-cache pruning, audit pruning after durable export, AI-answer pruning on write, and tenant/subject erasure. The audit-retention runner wakes hourly in every profile. The single deployment profile defaults to 0 (provider rows keep forever), while a finite tenant audit_retention_days override can still tighten its own local rows. multi-tenant and regulated default to a finite 8760h (365-day) deployment maximum and require WORM/SIEM watermark configuration before startup. /v1/lifecycle/retention lets a tenant set stricter per-plane clocks for flow, OTLP, eBPF, path, audit, persisted AI answers, object artifacts, and derived identity caches; NULL means the deployment default remains in force. Where a backing store cannot safely delete one tenant's older rows locally (for example a remote aggregate TSDB or object store lifecycle), the sweeper emits an honest delegated/not-capable receipt instead of pretending it pruned.

The machine-checkable data inventory lives in internal/govern.DataInventory(). The privacy gate fails if a row lacks owner, data classes, retention, processors, export behavior, tenant deletion semantics, or subject deletion semantics. Current inventory IDs: audit-evidence, ai-artifacts, backups-snapshots, device-endpoint-state, ebpf-telemetry, flow-telemetry, identity-rbac-scim, object-artifacts, otlp-traces-logs, path-topology, probe-results, shared-open-data, siem-cursors.

Enforcement Model

  • Tenant first, then purpose. Every retained row, object key, metric, and export cursor is tenant-scoped before RBAC or governance policy is considered. If the tenant cannot be proven, the read/delete path returns nothing.
  • Age retention is store-owned. High-volume ClickHouse stores use delete TTLs for raw rows and hourly rollup tables for lower-resolution history; the in-memory TSDB uses an arrival-time window; audit logs prune only after WORM/SIEM export proves the evidence survived elsewhere.
  • Lifecycle deletion is wider than age retention. Tenant erase and subject erase are the privacy "big brooms": they remove or project data across live stores even when a store has no age TTL.
  • Policy and proof commit together. A tenant retention-policy update and its explicit lifecycle.retention_set audit event use the same tenant-scoped PostgreSQL transaction. If either write fails, neither becomes visible.
  • Engine-owned prunes are audit-gated. Before the lifecycle engine deletes session detail, flow/OTLP/eBPF/path rows, persisted AI answers, endpoint history, or derived topology/endpoint cache entries, a bounded provider-audit intent must commit. Its non-secret attempt_id pairs it with an enforced/failed count-only terminal receipt. Failed intent means no prune; failed terminal append is returned to the scheduler instead of being hidden in a warning.
  • Delegated clocks are receipts, not triggers. The tenant objects clock describes external object lifecycle, so the lifecycle engine emits one delegated receipt and does not claim an intent or deletion it did not invoke. Audit is different: its dedicated hourly runner resolves the tenant's effective bounded window and emits audit.retention_prune only when a SIEM-watermarked prefix is actually removed.
  • Copies keep their own clock. Backups, WORM exports, and customer SIEM destinations are not live stores. probectl records the configured backup window and export cursor, but the destination system owns its own retention.
  • No object-store age TTL is enforced by FSStore. The filesystem object store keeps objects until tenant erase/subject erase, explicit prefix delete, or the operator's bucket/filesystem lifecycle policy removes them.

Data-Class And Purpose Matrix

Data set Default class Purpose Primary home Retention and deletion clock
Synthetic/canary probe results, including DNS answers pii for IPs/targets; internal for labels; result attributes may carry tenant data Network and SLO troubleshooting: "did this tenant's path resolve and respond?" TSDB series, result views, and bus payloads under tenant_id Lightweight mode uses PROBECTL_TSDB_MEMORY_RETENTION (0 means the built-in 1h window). Remote Prometheus/VictoriaMetrics retention is configured in that TSDB. Tenant erase deletes in-memory series or calls the Prometheus admin delete-series path when enabled; otherwise the attestation records the manual step. Subject export/erase covers in-memory metric names and labels via tsdb_metrics; remote TSDB subject workflows are recorded as aggregate-backend/manual delete-series or retention age-out. DNS answers live inside result attributes, so they follow the probe-result clock.
Flow telemetry pii for source/destination IPs; confidential for ports/protocols/ASN enrichment Traffic accounting, segmentation evidence, incident context, and cost attribution ClickHouse probectl_flows plus hourly probectl_flow_rollups_hour, or in-memory flow store PROBECTL_FLOW_RETENTION_DAYS defaults to 90 days and applies a ClickHouse delete TTL to raw rows; 0 is an explicit keep-forever opt-out. Hourly rollups are tenant-partitioned and backfillable. Migration v5 stores the raw row's subject-match identity values in subject_keys, so new rollups remain verifiably subject-erasable after raw rows age out; it also replaces still-backfillable pre-v5 rollups without deleting older rollup-only history. Per-tenant flow_retention_days can tighten the raw-row clock.
eBPF host/L7 flow telemetry pii for peer IPs and process/user-adjacent labels; confidential for service edges Host/service dependency mapping, L7 observability, and NDR-lite signals ClickHouse eBPF tables or in-memory eBPF store PROBECTL_EBPF_RETENTION_DAYS defaults to 30 days and applies eBPF ClickHouse TTLs; 0 disables that age TTL. Tenant erase removes the tenant's live eBPF rows. Subject lifecycle removes/export matches from backends with subject-capable workload-label filtering and otherwise records the aggregate age-out clock.
Path/traceroute evidence, Topology labels, and device identity-conflict claims pii for hop/management/interface IPs; internal or confidential for hostnames, device/interface labels, sites, source agents, and topology annotations Change-aware topology, path RCA, blast-radius reasoning, and review of conflicting attribution ClickHouse path tables plus hourly path hop/link rollups and tenant-partitioned internal/topology memory/index stores PROBECTL_PATH_RETENTION_DAYS defaults to 90 days for raw path/traceroute ClickHouse TTLs. Hourly hop/link rollups keep lower-resolution tenant-scoped history while raw path rows age out. The topology memory/index store is a replayable derived identity cache: PROBECTL_DERIVED_IDENTITY_RETENTION_DAYS defaults to 90 days and prunes stale nodes, edges, and normalized identity-conflict claims from query/export surfaces, with lifecycle.retention_sweep receipts for deleted evidence. Conflict storage is capped per tenant and contains normalized provenance only—never raw telemetry or credentials. Tenant erasure drops the entire tenant graph and every conflict claim. Subject lifecycle filters/removes matching topology labels and connected edges in subject-capable graph stores; device nodes are counted separately in the receipt. A tighter tenant flow_retention_days also tightens this derived-cache clock.
OTLP traces and logs pii or restricted when attributes/bodies contain user IDs, IPs, emails, tokens, or request data Application/host correlation with network incidents ClickHouse OTLP store or memory store PROBECTL_OTEL_RETENTION_DAYS defaults to 30 days for ClickHouse trace/log TTLs; 0 disables that TTL. Attribute/body caps and redaction reduce blast radius, but tenant/subject erase is the privacy deletion path for matching OTLP data.
Device telemetry, LLDP/CDP neighbor evidence, endpoint/DEM metrics, and SNMP/gNMI attributes pii for management/interface IPs and endpoint-user identifiers; confidential for hostnames, physical adjacency, inventory, and config posture Device health, physical-link correlation, endpoint experience, and operational inventory TSDB, forced-RLS device_neighbor_evidence, device/endpoint stores, topology device nodes, and tenant-scoped API views Metric samples follow the TSDB retention clock (PROBECTL_TSDB_MEMORY_RETENTION in memory mode or the remote TSDB's policy). LLDP/CDP rows are current-snapshot evidence: each source snapshot replaces its prior rows, storage is capped at 256 rows/device and 16,384 rows/tenant, reads at 500, and evidence older than 24h is pruned on write. Tenant deletion cascades all neighbor rows. Endpoint latest-view labels are a derived identity cache pruned by PROBECTL_DERIVED_IDENTITY_RETENTION_DAYS with lifecycle.retention_sweep receipts. Subject lifecycle removes/exports matching endpoint labels and topology device nodes where supported; aggregate copies report their retention basis. The device agent's correlation cache prunes stale sysName/interface labels with PROBECTL_DEVICE_CORRELATION_RETENTION (default 90 days, 0 disables). Durable inventory/config rows are lifecycle-managed and erased with the tenant or data subject.
User directory attributes, RBAC, SCIM, sessions, and tenant membership pii for names/emails; restricted for credentials/tokens; confidential for roles and groups Authentication, authorization, provisioning, and audit attribution Postgres tenant tables with RLS and envelope-sealed secrets where applicable; the global pre-tenant locator contains only credential kind/row UUID/hash/tenant/inactive timestamps, never identity or session PII Kept while the identity/tenant is active. User deprovision, subject erase, and tenant erase are the deletion paths, including deletion of locator/revocation metadata. Tokens/secrets are stored as hashes or sealed values; no age TTL exists for directory rows unless the owning subsystem adds one.
Audit entries, provider audit, break-glass records, and WORM segments confidential to restricted because they prove who touched what Non-repudiation, compliance evidence, incident response, and break-glass accountability Postgres audit chains, tenant-routed audit_subject_erasures hash projections, plus optional signed WORM object segments PROBECTL_AUDIT_RETENTION defaults to 0 (provider keep forever) in the single profile and to 8760h (365 days) in multi-tenant / regulated. A finite tenant audit_retention_days value tightens its own window; positive deployment windows are hard maxima and longer tenant values are rejected. Production-like profiles fail closed unless PROBECTL_AUDIT_WORM_DIR, a stable WORM signing key, and SIEM export are configured. Tenant rows prune only below the durable siem_delivery cursor; provider rows always use the deployment window and prune only below the signed WORM segment watermark. The pruner deletes only a contiguous eligible prefix and emits an audit.retention_prune receipt with the effective window. Before an exported privacy.subject_erase marker can leave that prefix, its tenant-scoped one-way hash is atomically captured in the append-only projection table; this lets later eligible rows progress while reads/exports stay redacted. Un-exported evidence is never deleted. /readyz.audit_retention and /metrics expose the deployment-level provider posture.
AI prompts and answers, feedback, citations, and model/config hashes pii or restricted when evidence contains tenant telemetry, operator text, or secrets RCA reproducibility, dispute resolution, and answer quality feedback Optional privacy-minimized Postgres answer artifacts and feedback rows; remote model side only when explicitly enabled PROBECTL_AI_PERSIST_ANSWERS=false means answers are not persisted by default. When enabled, the stored answer and ai.ask audit question are tokenized before they enter Postgres; PROBECTL_AI_ANSWER_RETENTION defaults to 2160h (90 days) and is pruned opportunistically on write. Tenant/subject erase removes matching persisted answers. Remote model retention is outside probectl and is allowed only through the remote-AI egress gates.
Shared incident evidence snapshots confidential after mandatory tenant/secret stripping plus the configured privacy redaction (PII and IP masking are default-on) Reproduce a cited incident-room investigation for another authorized tenant user Postgres incident_share_artifacts with forced RLS and explicit tenant_id predicates Each snapshot has a mandatory expiry: seven days by default, shortened by a tighter tenant object_retention_days value. Expired/revoked rows are unreadable and are pruned opportunistically on creation; tenant erase removes all rows by tenant cascade. Every successful create/read is audited.
Incident investigation journal confidential; bounded human-authored plain text plus IDs/details from an already-redacted cited share Preserve local hypotheses, checkpoints, and conclusions through an incident Postgres incident_journal_entries with forced RLS, explicit tenant_id predicates, and a composite tenant+incident foreign key Entries expire after 90 days by default, shortened by a tighter tenant object_retention_days value. Reads return at most 200 live rows. Checkpoint sources are re-authorized on append and read; expired/revoked/missing/foreign references expose no evidence details. Expired rows are pruned opportunistically, tenant erase cascades them, and subject export/erasure covers matching body/author data. Appends and reads are audited.
Incident correlation overrides confidential; operator identity, reason text, and network target/prefix Preserve an explicit human decision to split falsely grouped incident evidence until reversal Postgres incident_correlation_overrides with forced RLS and composite tenant-bound foreign keys Retained with the incident unless explicitly reversed or deleted by lifecycle. Tenant erase cascades all rows. Subject export/erasure count-verifies deletion when the subject matches creator/reverser identity, target/prefix, or reason text; the immutable tenant audit chain keeps a hash-projected receipt without retaining the erased subject literal.
Saved dashboards, report schedules, and PDF/CSV report artifacts confidential; exact values may include tenant topology/traffic posture, while owner/generator fields may be pii Repeatable tenant evidence snapshots and operator-requested local report delivery Postgres dashboard_views, dashboard_report_schedules, and capped dashboard_report_artifacts, all with forced RLS and composite tenant foreign keys Kept until the saved dashboard or tenant is deleted; tenant deletion cascades through all three tables. Core currently exposes no artifact age-TTL or single-artifact delete route, so operators must include these tables in their PostgreSQL retention policy instead of assuming the tenant object_retention_days clock applies. Artifact download and every create/delivery action are audited.
Object artifacts: support bundles, lifecycle exports, test bundles, browser artifacts, backup/WORM files Usually confidential; may be restricted when logs, configs, screenshots, or audit evidence are included Portability, support, test distribution, backup/restore, and immutable audit export Object store: filesystem, S3, or MinIO under tenant prefixes/buckets No object-store age TTL is enforced by FSStore. Tenant erase deletes the tenant prefix through the objectstore DeletePrefix path. Backup files follow PROBECTL_BACKUP_RETENTION_DAYS and PROBECTL_BACKUP_RETENTION_NOTE in the deletion attestation, plus the operator's bucket/object-lock lifecycle policy.
Open-data and threat-intel shared feeds public or source-license-governed shared data Enrichment: ASN/RPKI/peering, outage context, CT/threat-intel matches Shared feed caches and threat/opendata stores These are ingested once, read-only, and scoped when joined to tenant data. They are not tenant telemetry. Retention/cache TTL is source-specific and must honor source AUP/provenance; source outages degrade gracefully.
SIEM-exported copies and SIEM cursors Exported events are confidential; redaction removes known secrets/PII keys before forwarding Customer SOC correlation and long-term security evidence Customer SIEM plus probectl's per-tenant delivery cursor SIEM retention is owned by the destination SIEM. probectl keeps only the cursor needed to resume delivery without dropping events; audit retention may prune local events only after durable WORM/SIEM export.
Backups and snapshots Same class as the source data, usually restricted Disaster recovery and regulated rollback Operator backup system, sealed backups, database/object-store snapshots Live-store erasure does not instantly purge historical backups. PROBECTL_BACKUP_RETENTION_DAYS records a concrete backup-erasure deadline in the tenant-erasure attestation; PROBECTL_BACKUP_RETENTION_NOTE records the operator's human-readable backup policy.

Config Clocks

Clock Default Scope What it controls
PROBECTL_TSDB_MEMORY_RETENTION 0 = built-in 1h Deployment In-memory TSDB sample window.
PROBECTL_FLOW_RETENTION_DAYS 90 Deployment, with tenant override via flow_retention_days ClickHouse raw-flow delete TTL; hourly flow rollups remain until lifecycle deletion.
PROBECTL_EBPF_RETENTION_DAYS 30 Deployment ClickHouse eBPF delete TTL.
PROBECTL_PATH_RETENTION_DAYS 90 Deployment ClickHouse raw path/traceroute delete TTL; hourly path rollups remain until lifecycle deletion.
PROBECTL_OTEL_RETENTION_DAYS 30 Deployment ClickHouse OTLP trace/log delete TTL.
PROBECTL_DERIVED_IDENTITY_RETENTION_DAYS 90 Deployment, tightened by tenant flow_retention_days Topology and endpoint latest-view identity labels derived from source stores; deletion emits lifecycle.retention_sweep receipts.
PROBECTL_DEVICE_CORRELATION_RETENTION 2160h Device agent In-agent SNMP/gNMI correlation cache for sysName/interface labels; 0 disables agent-local age pruning.
PROBECTL_AUDIT_RETENTION 0 in single; 8760h in multi-tenant / regulated Deployment maximum, tightened by tenant audit_retention_days Provider rows use this window; 0 keeps them forever. Tenant NULL inherits it and a finite tenant value can tighten even a keep-forever single deployment. Tenant rows require the SIEM cursor, provider rows require the WORM watermark, and actual prune receipts carry the effective window. Production-like profiles reject 0 and missing WORM/SIEM watermarks.
PROBECTL_AI_PERSIST_ANSWERS false Deployment Whether AI answers are stored at all.
PROBECTL_AI_ANSWER_RETENTION 2160h Deployment Age window for persisted AI answers when persistence is enabled.
PROBECTL_BACKUP_RETENTION_DAYS 0 = note-only Deployment/operator policy Backup-erasure deadline recorded in deletion attestations.
PROBECTL_BACKUP_RETENTION_NOTE Generic fallback Deployment/operator policy Human-readable backup retention statement in deletion attestations.

Practical Reading

  • If an auditor asks "how long do flow rows live?", start at the flow row and check PROBECTL_FLOW_RETENTION_DAYS, then check whether the tenant has a tighter flow_retention_days override.
  • If they ask about topology or endpoint labels, check PROBECTL_DERIVED_IDENTITY_RETENTION_DAYS; a tenant's tighter flow_retention_days shortens that derived-cache window too.
  • If they ask about a person, use subject export/erase. Age TTLs are coarse timers; subject lifecycle is the tenant-scoped privacy control. Its manifest lists every privacy-relevant plane with exported/deleted counts, projected audit status, not-deployed status, covered_by_parent for RUM labels covered by tsdb_metrics, retained_encrypted_evidence for the provider-only IR sidecar that ordinary subject reads cannot access, or not_capable plus the age-out/delete-series basis for aggregate backends that cannot safely delete one subject locally. A subject erasure receipt is complete:true only when every deployed plane was erased, count-verified clean, or explicitly preserved as separately encrypted evidence; any deployed not_capable plane keeps it complete:false while the report is still hashed and written to provider audit.
  • If they ask about backups or SIEM, give the probectl attestation/cursor plus the operator's SIEM or backup policy. probectl cannot truthfully promise the destination deleted its copy.
Rendered live from github.com/ctlplne/probectl — found a mistake? edit this page.