Site

GDPR Article 30 requires controllers to maintain a written record of processing activities. The exemption for organisations under 250 employees does not apply when processing is regular (yours is — every login is processing), so assume you need this.

This is the register for a stock deployment. It is a starting point you adapt, not a document you file as-is: the controller identity, retention periods, and transfer safeguards are yours to fill in, and any feature you add creates a row that is not here.

Controller

FieldValue
ControllerLEGAL_COMPANY_NAME (see config/app.ts → appConfig.legal)
AddressLEGAL_ADDRESS
RegistrationLEGAL_REGISTRATION_NUMBER
DPODPO_EMAIL — leave unset if you have not appointed one. Publishing a fake DPO contact is worse than publishing none.
Lead supervisory authoritySUPERVISORY_AUTHORITY

Article 37 makes a DPO mandatory for large-scale regular monitoring or large-scale special-category processing. A typical SaaS is below that line, but AI usage logging pushes some deployments closer than operators expect.

Processing activities

1. Account management and authentication

PurposeCreate and secure accounts, authenticate users, manage workspace membership
Legal basisArt. 6(1)(b) performance of a contract
Data subjectsRegistered users, invited workspace members
CategoriesEmail, name, phone, birthday, avatar, auth identifiers, membership role
Tablesprofiles, accounts, memberships, invitations
RecipientsSupabase (hosting + auth), email provider (magic links)
RetentionLife of the account, then the 30-day deletion queue

2. Billing and payments

PurposeProcess subscriptions, credit packs, licenses; invoicing; tax records
Legal basisArt. 6(1)(b) contract; Art. 6(1)(c) legal obligation for tax retention
CategoriesBilling identifiers, provider customer/subscription/payment ids, amounts, currency
Tablessubscriptions, payments, licenses, credit_transactions
RecipientsThe configured payment provider: Stripe, Lemon Squeezy, or Paddle
RetentionStatutory accounting period (commonly 7–10 years) — survives account deletion; state your local period here

Card data never reaches the application; the configured hosted payment provider holds it. The selected provider must match the public privacy notice and current subprocessor register.

3. AI features (chat, agents, RAG)

PurposeGenerate responses to user prompts, index and search uploaded documents
Legal basisArt. 6(1)(b) contract
CategoriesPrompt text, generated output, uploaded document content and embeddings, token counts, model/agent ids
Tableschat_sessions, chat_messages, ai_requests, documents, document_chunks
RecipientsThe LLM providers configured in aiConfig.providers — see /ai-transparency
TransfersProvider-dependent; typically EU + US
RetentionLife of the account; cleanup-sessions purges old sessions on the configured schedule

This is the highest-risk activity in the register. Users paste arbitrary content into prompts, including data about third parties and occasionally special-category data, and it leaves your infrastructure. It is the main reason a DPIA is likely required — see DPIA.

PurposeRecord and demonstrate cookie/marketing consent
Legal basisArt. 6(1)(c) legal obligation (Art. 7(1) demonstrability)
CategoriesConsent category, decision, timestamp, policy version, IP, user agent
Tablesuser_consents (current state), user_consent_events (append-only trail)
RetentionKept beyond withdrawal — the proof is the point

5. Security, audit and operational logging

PurposeDetect abuse, investigate incidents, maintain an admin audit trail
Legal basisArt. 6(1)(f) legitimate interest (securing the service)
CategoriesHashed IP, user agent, event type, geolocation, admin actions, redacted error messages
Tablesuser_access_logs, admin_logs, error_logs
RetentionLOGS_RETENTION_DAYS (default 90), enforced by purge-error-logs

A legitimate-interest basis requires a documented balancing test. Write it down; "we needed it" is not a balancing test.

error_logs uses the following field-level DSAR and erasure policy:

FieldsData exportAccount/user erasure
id, account_id, level, status_code, created_atExported for events attributed to the subject, plus events belonging to the subject's personal Account. Workspace-wide events are never exported to an ordinary member. An export exceeding the automated bound fails explicitly into manual review instead of being silently truncated.Account attribution is removed; only level, status and timestamp remain until normal retention.
actor_user_idUsed to scope the export but omitted from the file so a personal-Account event cannot reveal another operator.Set to NULL.
category, event, route, method, error_code, message, stack_redacted, ip_hash, metadataExcluded from the automated export because caller-controlled, free-form or pseudonymous diagnostics can contain third-party or security-sensitive data. Handle a justified broader DSAR through manual review.Replaced or cleared by the bounded GDPR RPC. A database trigger performs the same scrub atomically if an Auth/Account foreign key loses attribution after the application drain.

The automated export combines actor-attributed events across Accounts with personal-Account events, deduplicates them by id, and caps each source query. The durable deletion processor anonymizes rows before foreign keys can be set to NULL; an attribution-loss trigger closes the concurrent-write window, and direct table updates remain unavailable to ordinary runtime and provider-native client roles.

6. Transactional and marketing email

PurposeMagic links, billing notices, invitations; newsletter where opted in
Legal basisArt. 6(1)(b) for transactional; Art. 6(1)(a) consent for marketing
Tablespending_emails, notification_preferences
RecipientsBrevo or Mailjet, per EMAIL_PROVIDER

7. Referral and affiliate programs

PurposeAttribute referrals, calculate rewards and commissions, prevent fraud
Legal basisArt. 6(1)(b) contract; Art. 6(1)(f) for fraud prevention
CategoriesAttribution links, hashed IP and user agent, application text, commission amounts
Tablesreferral_codes, referrals, affiliate_*
RetentionLife of the account plus any commission dispute window

Only active when REFERRAL_ENABLED / AFFILIATES_ENABLED are on. Remove these rows if you ship with the features off.

8. Push notifications

PurposeDeliver credit alerts and system announcements
Legal basisArt. 6(1)(a) consent (browser permission)
Tablespush_subscriptions, notification_log
RetentionUntil unsubscribed; cleanup-push-subscriptions removes stale tokens

Technical and organisational measures (Art. 32)

Row-level security scoped by Account membership and the verified application actor; separate least-privilege credentials for runtime, workers, maintenance and platform administration; CSRF on state-changing routes; rate limiting; secret redaction and IP hashing in logs; SSRF validation on webhook URLs; constant-time secret comparison; recent-auth gate on sensitive admin actions; and encryption in transit and at rest through the selected managed providers.

Maintenance

Review when you add a table holding personal data, add or change a subprocessor, change a retention period, or change a legal basis. Bump PRIVACY_POLICY_VERSION in config/compliance.ts whenever the change affects what the privacy notice says.

Optional native product insights and AI allowances

Native product measurement stores Account/actor identifiers, milestones and timestamps only after current analytics consent. Withdrawal erases the actor’s measured events and cohort markers. Operational activation progress and AI allowance/accounting records are separate purposes. Events use bounded 90-day retention; first-observation markers prevent cohort resets and remain until withdrawal or erasure. Policy audit and monthly counters use a 365-day retention window; minimal accounting replay keys and unresolved receipts remain until Account erasure. The subject export includes both domains. Update the deployment’s processing register and privacy notice before enabling these purposes; details and configuration are in Product insights and AI controls.