Skip to content

🔒 GDPR export+erasure controller + /api/users/me/data routes + re-auth #3884

Description

@PierreBrisorgueil

Reintroduce the user-facing erasure endpoint + route wiring, orchestrated over the provider registry (no static cross-module imports).

Scope — users.data.controller.js + routes

Erasure orchestration (DELETE /api/users/me/data):

  1. Re-auth proof required (see re-auth hardening sub-issue) + strict rate limiter (limiters.auth) on the route.
  2. Re-entrancy guard: in-flight erasure flag → concurrent DELETE = 409.
  3. Resolve + snapshot axes ONCE: { soleOwnedOrgIds, sharedOrgIds } via memberships.
  4. Write the ErasureRequest ledger doc BEFORE the first destructive call — a retry re-reads the snapshot (memberships are deleted mid-run; request-time re-resolution after a partial failure would silently skip org-axis providers).
  5. Run validate() across ALL providers — any blocker aborts before any deletion (predictable blockers surface pre-destruction).
  6. Phases: external + org-axis (sole-owned only) → user-axis → organizations/memberships → clear cross-refs (referredBy) → confirmation email (Art 12(3), terminal outward action)UserService.remove LAST.
  7. Response = erasure receipt (per-provider {removed, retained, messages}).
  • REMOVE DELETE /api/users entirely (single erasure door; breaking note in MIGRATIONS.md). A deprecated-but-routable legacy route would remain a second door that still orphans data.
  • usersExportProjection: exclude password, reset/verification tokens, lockout counters; strip OAuth tokens from providerData and additionalProvidersData.
  • Routes /api/users/me/data (+ /me/data/exports wiring for the async export sub-issue): passport jwt + policy.isAllowed; moderate limiter on the export-request route (fan-out endpoint).

DoD

  • Integration: phase order enforced; retry-after-mid-failure still runs org-axis providers (ledger snapshot); re-entrancy 409; legacy DELETE /api/users gone (404).
  • /verify + /dev:verify-qa green.

Depends on: registry leaf v2, ErasureRequest ledger.

Created via /dev:issue · contract v2 2026-07-03

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions