Stu Mason
Stu Mason

Activity

StuMason/cleanconnect
Client SaaS
TypeScript
Pull Request Merged

PR #203 merged: fix: GDPR/PECR compliance — consent, unsubscribe, erasure, retention

Summary

Compliance fixes from the audit, in rough order of legal urgency:

  1. Marketing consent is no longer pre-ticked. Pre-ticked boxes are invalid consent under UK GDPR (Planet49/ICO guidance). The registration checkbox now defaults to unchecked and the DB column default flips to false (the application layer already defaulted to false for headless requests).
    • ⚠️ Open decision for you, Stu: the original marketing_opt_in migration defaulted the entire existing user base to true as a deliberate soft opt-in. This PR does not change existing users' values — soft opt-in for existing customers is arguable under PECR reg 22(3), but it's your call whether to keep relying on it or reset pre-migration users to false. Happy to do the reset in a follow-up if you want it.
  2. Launch announcement emails can now be unsubscribed from. They previously had no opt-out at all (PECR reg 22(3)(c) violation). email_signups gets unsubscribed_at, the mailable gets a signed unsubscribe link + footer + RFC 8058 one-click headers, and the signed GET-confirm/POST-act routes mirror the existing user unsubscribe flow.
  3. Erased users are no longer re-targeted. Previously a deleted account's email dropped out of the users-match and became an "unconverted" marketing prospect again. The scope now treats soft-deleted users as converted, and DeleteUserData removes the person's email_signups and email_events rows and anonymises their support requests.
  4. Hard delete no longer destroys financial records. payments FKs (quote/client/cleaner) and payouts.stripe_connect_account_id switch from cascadeOnDelete to nullOnDelete — HMRC requires 6 years of transaction records and GDPR Art 17(3)(b) permits retention under legal obligation.
  5. Right to erasure actually works for clients now. client_profiles.user_id had no ON DELETE action, so the 30-day hard delete hit an FK violation for any client with a profile (only the cleaner path was tested). Now cascades like cleaner_profiles.

Tests

  • Client hard-delete end-to-end (previously only cleaners were covered)
  • Payments survive user hard-delete with the user reference nulled
  • Erasure removes signups/email events and anonymises support requests
  • Signup unsubscribe flow: signed GET confirm, POST act, unsigned rejected, idempotent timestamp, scope exclusion
  • Launch announcement: unsubscribed + erased recipients excluded, unsubscribe link + headers rendered

Not in this PR (follow-ups needing retention-policy decisions)

  • Scheduled purge for old email_events / email_signups (needs a chosen retention period)
  • ID/RTW/DBS document deletion after verification approval (needs a retention rule)
  • Privacy policy rewrite (retention table, processor list, ICO complaint right)
+549
additions
-17
deletions
17
files changed
Stu Mason

Stu Mason

It works on my agent's machine? · UK