Privacy lifecycle

Privacy is an application lifecycle concern, not a single Beignet primitive. Beignet gives you ports, use cases, hooks, audit logs, storage, uploads, and redaction helpers so each app can make sensitive data ownership explicit.

Design the lifecycle before production data arrives: classify the data you collect, decide where it is allowed to live, define retention and deletion behavior, keep exports reproducible, and redact data before it reaches logs, devtools, error reporters, or vendor metadata.

Data classification

Classify app data by risk before choosing what to store or emit:

ClassExamplesDefault handling
Stable identifiersuserId, tenantId, requestId, resourceIdSafe for logs, audit records, and error context when access is controlled
Business metadatastatus, counts, feature names, timestampsUsually safe when it does not reveal private content
User contentmessages, bios, comments, uploads, form answersStore in app repositories or storage only; avoid diagnostic sinks
Secretspasswords, tokens, cookies, provider credentials, API keysNever log, audit, report, or expose
Regulated dataPHI, payment details, government IDs, legal recordsStore only behind explicit product, retention, and vendor controls

Prefer stable IDs over raw content in every operational system. Logs, audit records, devtools, and error reporters should help an operator find the app record that owns the data, not duplicate the data.

Retention

Retention should be owned by app policy and implemented through use cases, repositories, storage adapters, and schedules.

Define retention windows for each durable surface:

SurfaceTypical ownerRetention question
Primary tablesFeature repositoriesHow long does the product need this record?
Audit logsAudit adapter and compliance policyHow long must activity be explainable?
Object storageUpload definitions and attachment repositoriesWhen should files be deleted, archived, or quarantined?
Outbox and job stateBackground workflow adaptersWhen can completed or failed work be pruned?
Devtools persistenceDevelopment tooling configIs persistence disabled or short-lived outside local development?
Logs and error reportingProvider settingsDoes the vendor retention match your data classification?

Use schedules for routine cleanup, and keep cleanup idempotent: deleting the same record twice should be safe, because scheduled work can retry.

Export

Exports should be explicit use cases, not ad hoc database reads. An exportUserData use case authorizes the actor, reads through feature repositories, records an audit entry with counts instead of content, and returns only the fields the user should receive. That keeps authorization, tenancy, audit logging, and redaction in one workflow.

Do not export provider credentials, internal IDs that are not meaningful to the user, audit records about other actors, or records outside the tenant boundary.

Deletion and anonymization

Use deletion when the product and legal model allow the record to disappear. Use anonymization when the app must preserve aggregate history while removing personal identity — for example, a deleteUserAccount use case that anonymizes the user row, tombstones attachments, and records an audit entry inside one Unit of Work transaction. Good deletion workflows:

Deletion does not automatically remove data already copied into logs, error reporters, vendor dashboards, backups, analytics, or support exports. That is why diagnostic surfaces should avoid raw private content in the first place.

Redaction

Use the redactValue and redactHeaders helpers from @beignet/core/ports for generic sensitive structures such as provider payloads and request headers. Generic redaction is not enough for domain privacy: add app-owned redaction for fields such as patient notes, private messages, payment descriptions, and free-form text.

Keep redaction allow-list based when possible. It is safer to choose the fields that may leave the application than to strip a few known-sensitive fields from a large object.

What not to log

Do not send these values to logs, devtools, audit metadata, error reporters, job metadata, provider instrumentation, or alert payloads:

Log stable references instead: request, tenant, actor, and resource IDs, plus hashes for values an operator may need to correlate.

Testing privacy behavior

Privacy behavior should be testable like any other application workflow. Add focused tests for export use cases only returning authorized tenant data, deletion use cases removing or anonymizing every feature-owned record, audit records using stable IDs instead of deleted content, and scheduled cleanup being idempotent. Memory ports make these tests cheap: capture logs, audit entries, jobs, and mail in memory, then assert on the emitted metadata.