-
Notifications
You must be signed in to change notification settings - Fork 0
GDPR Export
StaffPortal provides a data-portability export so a member can download everything the system holds about them as a single portable document, satisfying the right to data portability.
The endpoint gathers every personal-data table for the subject. The canonical list lives in GDPR_TABLES in lib/gdpr.ts and the export route:
-
user_profiles,user_roles -
attendance,wfh_records,attendance_corrections -
leave_requests,leave_balances -
expenses,purchase_requests -
diary_entries,visitors(visits the member hosted),feedback,complaints -
audit_logs(events attributed to the member)
The route asserts at module load (assertGdprCoverage) that its SOURCES list covers every table in GDPR_TABLES. Declaring a new personal-data table without wiring it into the export fails the build and the test suite, so an incomplete export can never reach a data subject. The guard is exercised by tests/gdpr.test.mjs.
The response is a JSON document assembled by buildGdprBundle:
{
"schemaVersion": "1.0",
"generatedAt": "2026-05-31T09:00:00.000Z",
"subject": { "userId": "...", "email": "...", "fullName": "..." },
"sections": [ { "table": "user_profiles", "description": "...", "records": [ ... ] } ],
"recordCount": 42
}It is streamed as an attachment with a dated, filesystem-safe filename such as staff-portal-export-ada-acme-com-2026-05-31.json.
- Self-service. Any signed-in member opens Settings, Privacy and data, and selects Download my data. The endpoint defaults to the caller's own records.
-
Administrator. An admin can export another member with
GET /api/gdpr/export?userId=<id>. Non-admins requesting another user receive 403.
Every export, self-service or admin, is recorded in the audit log as a gdpr_export event with the record count and whether it was a self-export.
- Route:
app/api/gdpr/export/route.ts. Resolves the subject, authorises, fetches each table in parallel with the service-role client, and audits the export. - Pure assembly and filename helpers:
lib/gdpr.ts, covered bytests/gdpr.test.mjs.
-
403 Forbidden. Only administrators can export another user. Omit
userIdto export your own data. - A section is empty. The subject has no rows in that table, which is normal.