Compliance & Audit Trail
The platform includes built-in compliance tools for automated data backups, PII (personally identifiable information) deletion, and a full audit trail. These features help meet regulatory requirements like SOC 2, GDPR, and CCPA without third-party services.
Overview
There are three distinct compliance operations, all triggered by the same daily cron job:
| Operation | What It Does | Operates On |
|---|---|---|
| Backup | Exports every configured table as an encrypted JSON snapshot to cloud storage (S3/R2) | Live database → cloud storage |
| Backup Cleanup | Deletes old backup files from cloud storage past their retention period | Cloud storage only |
| PII Deletion | Anonymizes or deletes records in the live database that have exceeded their retention period | Live database only |
Each operation runs independently, on its own cadence, and logs every execution to the Audit table for a permanent record.
Automated Backups
When enabled, the backup system exports a full JSON snapshot of your database tables to S3-compatible cloud storage (default: Cloudflare R2). Each backup is organized by date and optionally encrypted with AES-256-GCM.
How It Works
- A Vercel cron job runs daily (configurable cadence).
- Each configured table is exported as a JSON file.
- If encryption is enabled, files are encrypted before upload.
- A
manifest.jsonis written alongside the table files with checksums and metadata. - Old backups past the retention window are automatically deleted from storage.
Storage Layout
backups/
main/
2026-03-01/
manifest.json
user.json.enc
product.json.enc
order.json.enc
...
2026-03-02/
...Copy to clipboardConfiguration
| Setting | Default | Description |
|---|---|---|
Enabled | Off | Toggle backups on or off |
Cadence (hours) | 24 | How often to run (24 = daily, 168 = weekly) |
Retention (days) | 30 | Backup files older than this are deleted from storage |
Encrypted | On | AES-256-GCM encryption for backup files |
Exclude Tables | site, role, apiKey, webhook, audit, ... | Tables to skip (config/system tables by default) |
PII Deletion
PII deletion automatically removes or anonymizes personal data from your live database after a configurable retention period. This is your data retention policy enforced in code.
Strategies
| Strategy | What Happens | Use When |
|---|---|---|
| Anonymize | PII fields are replaced with [REDACTED] or null. The record itself is preserved. | You need the record for reporting or accounting but don't need the personal details (e.g., shipped orders). |
| Delete | The entire record is permanently removed from the database. | The record has no long-term value (e.g., old contact form submissions). |
Anonymize works only on tables the platform has a PII map for (orders, feedback, coupon usage, sessions, clients). A rule that asks to anonymize any other table fails the run, so it shows up in the compliance heartbeat instead of quietly scrubbing nothing. Use Delete for contacts, subscribers and carts. User accounts are not swept by PII rules; they are erased through account deletion.
Default Rules
These are the pre-configured rules (all customizable in Site Config):
| Table | Strategy | Retention | Trigger |
|---|---|---|---|
| Orders | Anonymize | 30 days | After shipping/delivery/cancellation/refund |
| Contacts | Delete | 90 days | After creation |
| Subscribers | Delete | 90 days | Inactive subscribers only |
| Feedback | Delete | 180 days | After creation |
| Coupon Usage | Anonymize | 90 days | After use |
Audit Trail
Every significant system action is logged to the Audit table, creating a permanent, tamper-evident record of what happened, when, and by whom. Super admins can browse the full audit history in Admin > Audits.
Audit Event Types
| Type | Description | Triggered By |
|---|---|---|
backup | Database backup completed, partially completed, or failed | Cron job or manual trigger |
backup_cleanup | Old backup files were deleted from cloud storage | Runs automatically after each backup |
pii_deletion | PII anonymization or deletion was executed | Cron job or manual trigger |
data_export | An admin exported table data as CSV | Admin user action |
data_import | Data was imported in bulk | Admin user action |
user_deletion | A user account was deleted | Admin or user action |
permission_change | A user's roles or permissions were modified | Admin user action |
config_change | Site configuration was updated | Super admin action |
What Gets Recorded
Each audit record captures:
- Type - The category of event (see table above).
- Status -
completed,partial,failed, orsuccess. - Record count - How many records were affected.
- Details - JSON object with specifics (tables affected, errors, duration, etc.).
- Performed by - The user who triggered it (name, email, IP), or
nullfor automated cron jobs. - Timestamp - When the event occurred.
- Notes - Optional admin-editable notes for context.
Cookie Consent
A site with no code-injected scripts sets no cookies that need consent: the sign-in session is strictly necessary, and the built-in Vercel and Cloudflare analytics are cookieless. So no banner appears by default. Cookie Consent exists for sites that add their own scripts under Developer > Code Injection, and it is included with Code Injection at no extra cost.
Each injected script has a category. As soon as a script tagged Functional, Analytics, or Marketing is live, visitors see a banner at the bottom of every public page:
- Reject all and Accept all are equal-weight buttons, one click each. Customize opens a preference center with one toggle per category and the vendor names and purposes you entered on each script. Nothing is pre-ticked.
- Blocked until allowed. A script in a category the visitor hasn't allowed is left out of the page entirely — it never loads, so it can't set cookies.
- Easy to withdraw. A Cookie preferences link in the footer reopens the preference center from any page. Withdrawing a category removes the cookies those tools left behind in the browser.
- Asked again when things change. Adding a script, or changing a script's name, category, or purpose, asks every visitor again. Editing only the code doesn't. To ask everyone again for another reason (for example after rewording the banner), raise Policy version.
- Choices last six months, then the visitor is asked again.
Proof of consent
Every choice writes an Audit record of type consent: a random consent ID (also stored in the visitor's browser, so one visitor's choices can be linked), the categories granted and refused, the vendor list the visitor was shown, the time, IP address, and browser, and the user if they were signed in. This is the record a regulator asks for to show consent was given.
Settings
- Enabled (on by default) - Turning it off makes every injected script run for everyone without asking. Only do that if none of your scripts set cookies or track visitors.
- Policy version - Raise to ask every visitor again.
- Banner title / message - Plain, honest copy. Never "by continuing to browse you agree" — scrolling isn't consent.
Manual Controls
Super admins can manually trigger backup and PII deletion from Admin > Super Admin Tools > Compliance. Each task has two modes:
- Dry Run - Preview what would happen without modifying any data. Shows which tables and records would be affected.
- Live Run - Execute the operation for real. Results are logged to the audit trail.
How They Work Together
The daily cron job runs both operations in sequence:
- Backup - Snapshot the current database state to cloud storage.
- Backup cleanup - Delete expired backup files from storage.
- PII deletion - Anonymize or delete old records in the live database.
This ordering is intentional: the backup captures the pre-deletion state, so you always have a recovery window. As long as your backup retention period is shorter than your PII retention period, deleted data won't linger in backup files past its deadline.
Getting Started
To enable compliance features for your deployment:
- Set up S3-compatible storage (e.g., Cloudflare R2) and add the connection environment variables.
- Generate an encryption key and add it as an environment variable.
- In Admin > Site Config > Compliance, toggle backup and/or PII deletion on.
- Use Dry Run from the Super Admin tools to verify configuration.
- The automated cron job handles everything from there.
For full setup details including environment variables, encryption, and disaster recovery procedures, see the project README.