Audience: auditors, data protection officers, and compliance reviewers.
This page documents the Right to Erasure (“Right to be forgotten”,
GDPR Article 17) implementation for an entire organisation tenant.
Purpose
When an organisation Admin requests deletion of their organisation, FocusFlow performs an irreversible, cascading erasure of the organisation and all of its associated records — including every member’s authentication account and personal data — and produces a tamper-evident audit record that the request was fulfilled. The control is self-service (initiated by the customer’s own Admin) and requires no operator intervention, satisfying the controller’s obligation to act on an erasure request without undue delay.Legal basis & scope
| Aspect | Detail |
|---|---|
| Regulation | EU GDPR Article 17 — Right to erasure |
| Trigger | Organisation Admin action in Settings → Danger Zone |
| Scope | One organisation tenant and every record linked to it |
| Authorisation | admin role only, scoped to the Admin’s own organisation |
| Reversibility | None — hard delete |
| Evidence retained | Minimal audit record (see Audit evidence) |
Who can initiate
Authorisation
Only a user with the
admin role may initiate erasure. Enforced in both
the UI (the control is hidden for non-admins) and server-side (the function
returns 403 for non-admins).Scope binding
The target organisation is derived from the caller’s own profile — an Admin
cannot delete another organisation, even by tampering with the request.
Explicit confirmation
The Admin must type the exact organisation name to confirm. A mismatch is
rejected with 400 before any data is touched.
No self-exception
The Admin’s own account is included in the erasure — this is whole-tenant
deletion, not a transfer of ownership.
Data inventory
The following table is the authoritative inventory of what is stored against an organisation and how each item is handled during erasure.| Data store | Contains | Personal data? | Action on erasure |
|---|---|---|---|
organisations | Org name, settings, Stripe identifiers | Indirect | Deleted (root of cascade) |
profiles | Member name, email, role, avatar URL | Yes | Deleted (cascade) |
devices | Enrolled device identifiers & metadata | Indirect | Deleted (cascade) |
nfc_tags | NFC tag UIDs, locations | No | Deleted (cascade) |
restriction_profiles | App/category restriction sets | No | Deleted (cascade) |
policies | Policy rules and targets | No | Deleted (cascade) |
scan_events | Scan history, optional geolocation | Yes | Deleted (cascade) |
auth.users | Login credentials, email (PII) | Yes | Deleted (explicit, per member) |
Storage — organisation-logos | Org logo image | No | Deleted (explicit) |
Storage — avatars | Member profile images | Yes | Deleted (explicit, per member) |
| Stripe subscription | Billing relationship | Indirect | Cancelled (best-effort) |
organisation_deletion_log | Erasure evidence | Minimal (requester email) | Created & retained |
Cascade map
Database deletion is enforced at the schema level byON DELETE CASCADE foreign
keys. Deleting the single organisations row removes every dependent record
atomically within the database:
auth.users records are not removed by the database cascade — they live in
the authentication schema and are deleted explicitly per member by the
erasure function. This is what removes login credentials and email PII.The erasure process
The erasure is performed by a single server-side function (offboard) running with
elevated privileges. Steps execute in a deliberate order so that the data subject is
notified before their own contact details are destroyed.
Authenticate & authorise
The caller’s session is verified. Their profile is loaded and the
admin
role is confirmed. The target organisation is taken from the caller’s profile —
not from client input.Confirm intent
The submitted confirmation text must exactly match the organisation name.
Any mismatch aborts the request before any data is modified.
Enumerate members
All member accounts in the organisation are listed so their auth records and
avatars can be removed, and so the confirmation email can be addressed.
Send confirmation email — before erasure
A confirmation email is sent to the requesting Admin while personal data is
still intact, because their own account and email are about to be deleted.
This closes the loop on the erasure request. Email failure is logged but does
not block the erasure.
Cancel subscription
Any active Stripe subscription is cancelled (best-effort). Failure is logged
and does not block the erasure.
Delete the organisation (cascade)
The
organisations row is deleted, cascading to all dependent tables
(profiles, devices, nfc_tags, restriction_profiles, policies, scan_events).Delete authentication accounts
Each member’s
auth.users record is deleted, erasing login credentials and
email PII. Per-user outcomes are tracked.Processing order rationale
The confirmation email is intentionally sent before the destructive steps.
Once a member’s
auth.users record and profiles row are deleted, their email
address no longer exists in the system and cannot be contacted. Sending first
guarantees the data subject receives closure evidence.Notification to the data subject
A transactional email is generated and sent via Resend to the requesting Admin. It confirms the erasure and itemises what was removed.| Field | Value |
|---|---|
| Recipient | Requesting Admin’s email |
| Channel | Resend transactional API |
| Timing | Before any personal data is deleted |
| Contents | Organisation name, member count removed, completion timestamp, list of erased data categories, retention notice |
By default only the initiating Admin is notified. Notifying every member
individually is supported by the same mechanism but is not enabled by default.
Audit evidence
To evidence that the erasure request was fulfilled, a single record is written to theorganisation_deletion_log table. This table is deliberately designed to outlive
the deleted organisation:
- It holds no foreign keys, so the cascade cannot remove it.
- It is protected by Row Level Security with no access policies, so it is reachable only by the privileged server-side process — never by API clients, members, or admins.
- It retains the minimum personal data necessary to evidence the request: the requester’s email.
| Column | Purpose |
|---|---|
id | Unique record identifier |
organisation_id | The erased organisation (no longer resolvable) |
organisation_name | Human-readable identification of the tenant |
requested_by | The Admin’s former user id |
requested_by_email | Who exercised the right (evidence) |
member_count | Number of member accounts in scope |
deleted_user_count | Number of auth accounts actually deleted |
notification_sent | Whether the confirmation email succeeded |
notification_email | Address the confirmation was sent to |
status | completed or completed_with_errors |
created_at | Timestamp of completion |
Failure handling & integrity
| Sub-step | On failure |
|---|---|
| Authorisation / confirmation | Request aborted; no data modified |
| Confirmation email | Logged; erasure continues; notification_sent = false recorded |
| Stripe cancellation | Logged; erasure continues |
| Storage cleanup | Logged; erasure continues |
| Organisation delete | Request fails with 500; cascade is atomic (all-or-nothing) |
| Per-member auth delete | Failures recorded in deleted_user_count and status |
| Audit log write | Logged; request still reports success (data already erased) |
The database cascade is atomic — the organisation and all dependent rows are
removed in a single transaction, so the relational data cannot be left in a
partially-deleted state.
Residual data & third parties
Backups
Personal data may persist in encrypted database backups for up to
30 days, after which the backups age out and the data is purged. Backups
are not used to restore individual tenants.
Stripe
The subscription is cancelled. Billing/transaction records retained by Stripe
are governed by Stripe’s own retention and legal/tax obligations.
Email provider
The confirmation email transits Resend and may appear in their delivery logs
per their retention policy.
Observability
Operational logs reference identifiers (e.g. user ids) but are not the system
of record and age out per the logging retention policy.
Summary for reviewers
Erasure is self-service, Admin-only, and scoped to the caller’s own tenant.
Explicit name-match confirmation is required before any change.
All organisation-linked records are removed via atomic database cascade.
Authentication accounts (credentials + email PII) are explicitly deleted.
Stored files (logos, avatars) are removed; subscription is cancelled.
The data subject is notified before their contact details are destroyed.
A minimal, access-restricted audit record evidences fulfilment of the request.

