We shipped a major compliance and security hardening pass across the starter kit, focused on the parts that matter most when a boilerplate becomes a real production app: account erasure, token storage, audit logging, data export, and admin workflows.
Highlights
Completed GDPR Right to Erasure coverage for non-cascaded personal data.
Hardened password reset and email verification tokens so raw tokens are no longer stored at rest.
Enabled encrypted OAuth access and refresh token storage through Better Auth.
Stopped persisting OAuth ID tokens, since they are not needed after provider validation.
Added cleanup tooling for existing OAuth token rows.
Reduced PII exposure in logs, admin list responses, and user-facing exports.
Added consent and lawful-basis capture to contact and waitlist submissions.
Expanded user data export coverage for GDPR access requests.
Added retention purge tooling for operational data.
Fixed admin users table pagination and rows-per-page behavior.
GDPR Erasure Is More Complete
Account deletion now goes beyond deleting the primary user row. The erasure flow also removes or anonymizes personal data that previously survived because it was not covered by foreign-key cascade behavior.
This includes:
Feedback authored by the user.
Contact submissions tied to the user's email address.
Waitlist entries tied to the user's email address.
Logged-in blog likes tied to the user's user fingerprint.
Security audit log network identifiers and metadata.
Anonymous audit events that reference the user's email address.
Stripe customer deletion as a best-effort processor-side cleanup.
The result is a much stronger Right to Erasure implementation for GDPR Article 17 workflows.
Safer Reset And Verification Tokens
Password reset and email verification tokens are now hashed before they are stored in the database. Raw tokens only travel through the email link sent to the user.
We also removed token values from audit metadata, which means database or log access no longer exposes usable reset or verification tokens.
OAuth Token Storage Hardening
OAuth access and refresh tokens are now encrypted at rest using Better Auth's token encryption support. OAuth ID tokens are no longer persisted, avoiding plaintext storage for a token the app does not need after validation.
A new maintenance script is available for existing databases:
pnpm auth:sanitize-oauth-tokens
It encrypts legacy OAuth access and refresh tokens and clears stored ID tokens from existing account rows.
Cleaner Logs With Less PII
Several server log paths were tightened to avoid printing personal data to stdout:
Profile update request bodies are no longer logged.
Contact form submissions no longer log name and email.
Waitlist invite logs no longer include recipient email addresses.
Stripe webhook logs no longer print user IDs, customer IDs, subscription IDs, or invoice IDs.
Security audit console output now logs operational context without raw metadata.
The database audit trail remains available for authorized audit workflows, but routine logs are much cleaner and safer.
Consent Capture For Intake Forms
Contact and waitlist forms now require explicit privacy-policy acknowledgement before submission.
The database stores:
Consent timestamp.
Privacy policy version.
Lawful basis.
This gives admins a clearer record of why and when personal data was collected.
More Careful Admin Data Exposure
Admin and auth routes now select only the fields they actually need instead of over-fetching full rows. This reduces accidental exposure of sensitive columns in memory and response paths.
Security-log list responses in the admin dashboard are also redacted:
Raw metadata is not returned in list responses.
IP address and user agent are redacted.
Email-looking values in descriptions are masked.
Better User Data Export
The personal-data export endpoint is more complete for GDPR access requests.
Exports now include:
Contact submissions tied to the user's email.
Waitlist entries tied to the user's email.
Security events tied to the user or their email.
Internal feedback admin notes are no longer included in user-facing exports.
Retention Purge Tooling
A new retention script makes it easier to enforce storage-limitation policies:
pnpm data:purge-retained
It can purge old security audit logs, contact submissions, waitlist entries, and expired verification records. Retention windows can be configured with environment variables.
Admin Users Table Fix
The admin users table pagination is now controlled and reliable.
Fixed behavior includes:
Rows-per-page selection now reflects the actual selected value.
Changing rows per page resets back to page 1.
Filtering/searching resets back to page 1.
The "Page 1 of X" display updates correctly after filters and page-size changes.
The mirrored user-dashboard users table received the same pagination fix for consistency.
Why This Matters
This update makes the starter kit much closer to production expectations for SaaS teams selling into real markets. It improves GDPR readiness, reduces breach impact, tightens admin surfaces, and makes the included admin dashboard feel more polished out of the box.