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:
| Class | Examples | Default handling |
|---|---|---|
| Stable identifiers | userId, tenantId, requestId, resourceId | Safe for logs, audit records, and error context when access is controlled |
| Business metadata | status, counts, feature names, timestamps | Usually safe when it does not reveal private content |
| User content | messages, bios, comments, uploads, form answers | Store in app repositories or storage only; avoid diagnostic sinks |
| Secrets | passwords, tokens, cookies, provider credentials, API keys | Never log, audit, report, or expose |
| Regulated data | PHI, payment details, government IDs, legal records | Store 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:
| Surface | Typical owner | Retention question |
|---|---|---|
| Primary tables | Feature repositories | How long does the product need this record? |
| Audit logs | Audit adapter and compliance policy | How long must activity be explainable? |
| Object storage | Upload definitions and attachment repositories | When should files be deleted, archived, or quarantined? |
| Outbox and job state | Background workflow adapters | When can completed or failed work be pruned? |
| Devtools persistence | Development tooling config | Is persistence disabled or short-lived outside local development? |
| Logs and error reporting | Provider settings | Does 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:
- authorize the actor and tenant at the use-case boundary
- delete or anonymize feature-owned records through repositories
- remove or tombstone object-storage attachments
- revoke active sessions and tokens
- enqueue background cleanup when providers need asynchronous deletion
- audit that the deletion request was processed without storing the deleted private content
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:
- passwords, password reset tokens, magic links, session tokens, API keys, cookies, authorization headers, and provider credentials
- raw request bodies, multipart upload bodies, private messages, comments, notes, form answers, and user-authored files
- PHI, payment details, government IDs, financial account numbers, and legal documents
- full provider responses when the provider may echo sensitive request data
- presigned upload URLs, signed download URLs, or URLs containing access tokens
- unbounded objects whose shape may grow to include private fields later
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.
Related pages
- Going to production for the pre-launch checklist.
- Audit and activity logging for durable business activity records.
- Logging for structured diagnostic logs.
- Error reporting and alerting for production exception capture.
- Storage and Uploads for file ownership and cleanup.
- Schedules for retention and cleanup jobs.