Skip to main content

GDPR / CCPA data export runbook

When a member exercises their right to access or right to deletion under GDPR, CCPA, or a similar privacy regime, GreekManage gives them self-service tooling so you rarely need to intervene. This page is the platform admin's reference for what actually happens behind those buttons, what you need to know when a regulator or counsel asks for evidence, and what residual operational work falls to you.

The two flows

GreekManage covers two distinct rights:

  1. Right to access — the member requests a copy of all data the platform holds about them. Handled by Account Settings → Privacy → Request data export.
  2. Right to erasure — the member requests permanent deletion of their account. Handled by Account Settings → Privacy → Delete account with a 30-day cancellation grace period.

Both run as async Celery tasks, generate audit-log entries, and complete without manual platform-admin involvement. A platform admin gets pulled in only when something fails, when a regulator asks for proof, or when a non-member (e.g., a former employee with no current account) is making the request.

Right to access — data export

What the member does

  1. Opens Account Settings → Privacy.
  2. Clicks Request data export.
  3. Re-enters their password (in-form re-auth).
  4. Submits. A new export record is created with status pending and an async task is queued.
  5. Returns later. When the task finishes, the page shows status ready and a Download link valid for 7 days.

What the system does

  1. A Celery task export_user_data picks up the new export.
  2. It collects every row across the database that references the user — accounts, memberships, custom data, profile fields, consents, forum posts, comments, reactions, polls, document uploads, compliance submissions, election votes, donations, recurring pledges, alumni mentor profile, work history, certifications, affiliations, skills, learning enrollments and quiz attempts, in-app notifications, audit log rows where they're the actor or subject.
  3. It writes the payload as JSON, gzips it, and uploads it to a private S3 key in the platform's data-export bucket.
  4. It generates a presigned URL valid for 7 days and saves it on the export record alongside expires_at.
  5. It marks the export ready and writes an audit log entry (action=data_export, resource type DataExport).

What you can do as platform admin

  • Verify the task ran. Pull the audit log filtered by Resource Type = DataExport to see who's requested an export and when.
  • Help a stuck export. Status processing for hours usually means a Celery worker is down or the export hit an unhandled edge case. Inspect Celery and the export's error_message field if it eventually flips to failed.
  • Re-issue a download URL if the original presigned URL expired before the member clicked it. The artifact stays in storage until retention purges it — re-running the export task generates a new 7-day URL.

Rate limit

A single user can request one export per 24 hours. Past that, the API returns 429 with a clear message. This is a defense against runaway scripts; legitimate "I lost the file" requests within 24 hours need a platform-admin assist.

What's included

Everything tied to the user's identity, including:

  • Account fields (email, name, profile photo URL, timestamps)
  • All linked email addresses and their verification state
  • Memberships across every chapter and org
  • Custom field data
  • Member profile (fraternal, professional, degrees, work history, certifications, affiliations, skills)
  • Forum content authored by the user (posts, comments, reactions, polls, saved posts)
  • Compliance submissions
  • Election votes (with the audit log entry, not the anonymized ballot)
  • Donations and recurring pledge metadata
  • Notifications
  • Consent records — what they agreed to, when, what version, and what IP

What's NOT included

  • Encrypted secrets. Payment processor credentials, AI provider keys, identity-provider client secrets are redacted/omitted.
  • Other users' data, even where the user appears (e.g., a forum post they reacted to includes the reaction but not the post author's PII beyond what's already public to them in-app).
  • Archived audit log rows past the org's retention. Audit logs are kept for 1–180 days per org (org admin sets this); anything older has been pruned by the time of the export.

Right to erasure — account deletion

What the member does

  1. Opens Account Settings → Privacy → Delete account.
  2. Re-enters their password.
  3. Submits. The account is immediately deactivated (is_active=false), all JWT refresh tokens are blacklisted, and a 32-byte URL-safe cancel token is generated and returned to them. They're shown a "you have 30 days to cancel" message.
  4. They're signed out and the deletion enters the 30-day grace window.

The grace period

The account stays deactivated but undeleted for 30 days from deletion_requested_at. During that window:

  • The member can cancel by clicking a link with their cancel token (sent by email at request time and shown in the confirmation screen). Cancellation reactivates the account (is_active=true, clears the deletion fields, invalidates the cancel token).
  • All JWT refresh tokens stay blacklisted. If the account is reactivated, the member signs in fresh.
  • Cancellation past 30 days returns 400 with "Cancellation period has expired" — at that point cleanup has already run or is imminent.

What runs on day 30

A scheduled task cleanup_deleted_accounts runs daily and processes any user whose deletion_requested_at is older than 30 days and whose account is still inactive. For each one, it:

  1. Reassigns content the user authored (forum posts, comments, attachments, content flags) to a sentinel "Deleted User" account. This preserves thread integrity for other members — the original author identity is removed, but a "deleted user said: …" stub remains for context.
  2. Hard-deletes user-owned junction rows (forum memberships, reactions, saved posts, etc.).
  3. Deletes the user record itself.

The sentinel-user pattern is the standard approach for "destructive but conversation-preserving" deletion. If a regulator asks "do you actually delete?", the answer is yes — the original User row is gone, and forum threads show "Deleted User" rather than the original name.

What you can do as platform admin

  • Audit the deletion. Pull the audit log for entries where the user was the actor in the last 90 days. The retention window for some logs is shorter, so capture evidence promptly.
  • Recover a regretted deletion within 30 days. Use the cancel-deletion flow with the member's cancel token. If they've lost the token, you have no recovery path — there's no admin "undo deletion" button.
  • Handle non-self-service deletion requests. A former member without a working sign-in (e.g., never verified their email) cannot use the in-product flow. Document the request, verify identity by some external means (counsel-level signoff is a good bar), and run the deletion task manually against their user ID.

PII encryption and key rotation

Sensitive fields throughout the platform (AI provider API keys, payment processor secrets, identity-provider client secrets, storage credentials) are encrypted at rest with Fernet using the platform's encryption key. The user-facing PII (email, name, phone, work history) is not field-encrypted at the column level — that's covered by storage-level encryption-at-rest (the database disk) plus access control.

Encryption-key rotation is a separate platform operation that re-encrypts every encrypted field with the new key. After rotation, old key material can be retired according to your retention policy. Document the rotation in your runbook so an auditor can trace key versions.

What gets exported vs what gets archived

DataExport includesSurvives deletion (sentinel-attributed)Archived elsewhere
Profile, memberships, custom fieldsYesNo (deleted)Per-org JSON export if taken before deletion
Forum posts and commentsYes (authored content)Yes — re-attributed to Deleted UserSame
Compliance submissionsYesDeletedSame
Election votesYes (audit row)Audit row stays; ballot anonymizedSame
DonationsYes (member's records)Donor record may stay for tax-receipt audit trailTax receipts retained per FoundationConfig policy
Consent recordsYesDeletedPer-org JSON export if taken before deletion
Audit log entries about themYes (within retention)Deleted with user, except where retained for forensics

Tell the member up front: deleting their account does not retroactively un-publish forum content they authored — it strips their identity from it. If they want their posts removed, ask them to delete the posts before deleting the account.

UserConsent as evidence trail

Every consent the member grants (privacy policy, terms of service, marketing, analytics, plus any org-specific consent template) is recorded with version, granted-at timestamp, IP address, and a foreign key to the consent template if applicable. Revocations stamp a revoked_at and are preserved as the consent's audit history.

When a regulator asks "did this user agree to X version of your policy on Y date?", pull the consent records — they're the answer.

Audit log retention vs export

Audit log retention is governed by OrgAuditRetentionConfig at the org level. Each org has a single retention window between 1 and 180 days, defaulting to 180. Older entries are pruned by the retention task — they cannot be re-fetched after pruning.

For a user export, only audit log entries currently within their org's retention window appear. For long-horizon evidence retention beyond 180 days, capture per-org JSON exports periodically and store them outside the application.

What's NOT in the box

  • No regulator-grade audit log archive longer than 180 days. Capture periodic exports yourself.
  • No bulk member-export flow. Each user requests their own; you can't export "all users in this org" through this path. Use the org-wide JSON export for that.
  • No automated DSAR (Data Subject Access Request) intake. Users still need to be authenticated to trigger the export.
  • No "freeze" state. An account is either active, deactivated-pending-deletion, or deleted.

Tips

  • Acknowledge DSARs in writing within your jurisdiction's window. GDPR is 30 days; CCPA is 45 (extendable to 90). The product runs the export in minutes, but your obligation is the response timeline, not the file delivery.
  • Capture an org-wide JSON export before processing a high-value deletion. Deletion is irreversible after 30 days. If counsel later asks for evidence, you'll be glad you have a pre-deletion snapshot.
  • Verify identity before a manual deletion. A regulator-driven request needs a paper trail beyond the in-product password re-auth.
  • Document the runbook outside GreekManage. When the platform is degraded is exactly when a DSAR clock ticks down.

Last verified against v0.62.1 (2026-05-11).