Repository navigation
Follow up on data deletions in official clients - #1012
Merged
Merged
Conversation
When a user deletes their account, an admin deletes a user, or a user retracts their approval of an official client, Gamma now records a data deletion request for each official client. Admins clear them on the new data deletion page, within the GDPR deadline of one month. Clearing keeps only the ids, which are removed after a year. While requests are open, a daily email with the deadlines and a link is sent to the configured recipients, and admins see an "Action required" banner when a request is overdue or no one gets the email. The delete account page lists the official clients and links to the owners of the other approved clients. The consent page shows the owner's email to signed in users, and new approvals of clients whose owner is locked are refused. Closes #884 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # app/src/main/java/it/chalmers/gamma/ScheduledTasks.java # app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/user/UserJpaRepository.java # app/src/main/java/it/chalmers/gamma/adapter/secondary/mail/GotifyMailService.java # app/src/main/java/it/chalmers/gamma/app/mail/domain/MailService.java # app/src/main/java/it/chalmers/gamma/app/user/MeFacade.java # e2e/helpers/gamma.ts # e2e/helpers/mail.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tent The banner now takes the card width on pages made of cards, and the full width on pages with tables. The daily email section on the data deletion page is laid out like the rest of the page, and empty tables are hidden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Consent saves do not share the revocation user lock, allowing concurrent re-approval to leave an open deletion request unmarked despite renewed consent.
4 open issues
What changed in this PR
Adds follow-up tracking for data deletion in Gamma’s official clients, connecting account deletion and approval retraction to an admin-managed workflow.
Changes:
- Records deletion requests, tracks re-approvals and clearance, and schedules reminders and retention cleanup.
- Adds an admin dashboard and warning banner, plus user-facing retention information and client-owner contact links.
- Blocks new approvals for locked client owners and adds end-to-end and accessibility coverage.
| File | Description |
|---|---|
| e2e/tests/ui/oauth-locked-owner-blocks-new-approvals.it.ts | Tests locked-owner consent restrictions. |
| e2e/tests/ui/data-deletion-retract-approval-creates-request.it.ts | Tests retraction and re-approval tracking. |
| e2e/tests/ui/data-deletion-daily-email.it.ts | Tests reminder delivery and privacy. |
| e2e/tests/ui/data-deletion-account-delete-creates-request.it.ts | Tests deletion, owner contacts, and admin clearance. |
| e2e/tests/ui/accessibility-wcag-scan.it.ts | Adds deletion pages to accessibility scans. |
| e2e/helpers/test-fixtures.ts | Supports custom test environment variables. |
| e2e/helpers/oauth.ts | Adds pre-consent assertions. |
| app/src/main/resources/templates/pages/my-clients.html | Explains owner-email visibility. |
| app/src/main/resources/templates/pages/delete-your-account.html | Shows approved clients and retention information. |
| app/src/main/resources/templates/pages/data-deletion.html | Adds request and recipient management UI. |
| app/src/main/resources/templates/pages/create-user-client.html | Discloses owner-email sharing. |
| app/src/main/resources/templates/pages/authorize.html | Displays client-owner contact details. |
| app/src/main/resources/templates/common/header.html | Adds admin navigation and warning banner. |
| app/src/main/resources/static/css/main.css | Styles the banner and deletion dashboard. |
| app/src/main/resources/db/migration/V9__DATA_DELETION_REQUESTS.sql | Creates request and recipient tables. |
| app/src/main/resources/application.yml | Configures reminder scheduling. |
| app/src/main/java/it/chalmers/gamma/ScheduledTasks.java | Schedules reminders and cleared-request cleanup. |
| app/src/main/java/it/chalmers/gamma/app/user/UserFacade.java | Records requests during admin user deletion. |
| app/src/main/java/it/chalmers/gamma/app/user/MeFacade.java | Integrates deletion tracking and client-contact summaries. |
| app/src/main/java/it/chalmers/gamma/app/user/domain/UserRepository.java | Defines the user-lock operation. |
| app/src/main/java/it/chalmers/gamma/app/oauth2/GammaAuthorizationConsentService.java | Checks owner locks and records re-approvals. |
| app/src/main/java/it/chalmers/gamma/app/mail/domain/MailService.java | Defines system-mail delivery. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/domain/DataDeletionRequestRepository.java | Defines request persistence operations. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/domain/DataDeletionRequestId.java | Adds typed request identifiers. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/domain/DataDeletionRequest.java | Models request state and deadlines. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/domain/DataDeletionRecipientRepository.java | Defines recipient management operations. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/domain/DataDeletionReason.java | Defines deletion reasons. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/DataDeletionRecorder.java | Records deletion and re-approval events. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/DataDeletionFacade.java | Provides admin operations and dashboard data. |
| app/src/main/java/it/chalmers/gamma/app/datadeletion/DataDeletionDigestService.java | Builds reminders and removes expired cleared records. |
| app/src/main/java/it/chalmers/gamma/app/client/domain/ClientRepository.java | Defines owner-email and lock queries. |
| app/src/main/java/it/chalmers/gamma/app/client/ClientFacade.java | Exposes guarded owner-contact and lock lookups. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/mail/GotifyMailService.java | Supports system mail with delivery results. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/user/UserRepositoryAdapter.java | Implements user locking. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/user/UserJpaRepository.java | Adds locking and narrow owner-data queries. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/datadeletion/DataDeletionRequestRepositoryAdapter.java | Implements request persistence and clearance. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/datadeletion/DataDeletionRequestJpaRepository.java | Adds request queries and state updates. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/datadeletion/DataDeletionRequestEntity.java | Maps stored deletion requests. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/datadeletion/DataDeletionRecipientRepositoryAdapter.java | Implements recipient storage and normalization. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/datadeletion/DataDeletionRecipientJpaRepository.java | Adds recipient persistence access. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/datadeletion/DataDeletionRecipientEntity.java | Maps reminder recipients. |
| app/src/main/java/it/chalmers/gamma/adapter/secondary/jpa/client/ClientRepositoryAdapter.java | Implements owner-email and lock lookups. |
| app/src/main/java/it/chalmers/gamma/adapter/primary/web/ThymeleafAdvice.java | Supplies admin banner data. |
| app/src/main/java/it/chalmers/gamma/adapter/primary/web/MailtoLink.java | Encodes prefilled email subjects and bodies. |
| app/src/main/java/it/chalmers/gamma/adapter/primary/web/DeleteYourAccountController.java | Builds client lists and owner-contact links. |
| app/src/main/java/it/chalmers/gamma/adapter/primary/web/DataDeletionController.java | Handles dashboard and management requests. |
| app/src/main/java/it/chalmers/gamma/adapter/primary/web/ConsentController.java | Shows owner contacts and locked-client messaging. |
Review effort: Balanced
Consent saves take the same user lock as retractions and account deletions, so a re-approval is always marked on the request it follows. Gotify requests time out instead of blocking the daily email, too long recipient emails are refused, and the delete account page also lists official clients with open requests from earlier retractions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # app/src/main/java/it/chalmers/gamma/app/user/UserFacade.java
The retention notice was only shown when the user had approved official clients or had open requests. A user whose requests had all been cleared saw no notice, even though their user id and client ids are kept for a year after clearing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Put what Gamma keeps after the account is deleted under one heading, and say that the records for cleared requests come from approvals the user retracted earlier. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Revoke stored grants and sessions, serialize issuance with withdrawal and deletion, and cascade deletion through owned clients. Queue avatar cleanup with retries, retain dismissible owner contacts after withdrawal, and require client owners to acknowledge erasure before deleting their account. Clarify retention and erasure notices, document operational duties, and cover migration, access, revocation races and storage cleanup with integration tests.
Portals
force-pushed
the
t3/grill-issue-884
branch
from
November 14, 2026 11:30
03c8679 to
85396a6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Closes #884
What this does
When a user deletes their account, an admin deletes a user, or a user retracts their approval of an official client, Gamma now records one data deletion request per (user, official client). Admins use the requests to make sure each official client deletes the data it has about the user.
Recording
g_user_approvalcascades when the user is deleted. The user row is locked withSELECT ... FOR UPDATEfirst, so an approval saved at the same moment is either recorded or refused.ACCOUNT_DELETED/APPROVAL_REVOKED) and when it was created.Admin page
/data-deletion(new "Data deletion" in the admin nav)Daily email and banner
DATA_DELETION_DIGEST_CRON(default0 0 8 * * *, Europe/Stockholm).MailService.sendSystemMail.Users and client owners
/delete-your-accountlists the official clients the user approved and explains what is kept and for how long. Users whose earlier requests have already been cleared are told that a record of the deletion is kept for one year. For clients made by other users, it shows a prefilledmailto:link per owner, grouped by owner.access_denied(400). Users who already approved keep working.ClientRepository.getUserOwnerEmail/isUserOwnerLocked), sinceUserRepositoryhides other users' extended data.Testing
data-deletion-account-delete-creates-request: delete page, owner mailto, consent page email, banner, adding a recipient, clearing.data-deletion-retract-approval-creates-requestdata-deletion-daily-email: the email arrives and has no personal data.data-deletion-cleared-request-retention-notice: a user with only cleared requests is still told what is kept.oauth-locked-owner-blocks-new-approvals/data-deletionand/delete-your-accountwere added to the accessibility scan.Demos
Recorded from commit
85396a6with fictional test users and clients.1. Account deletion and admin follow-up (36 seconds)
Retention information and client-owner contact, account deletion, the admin warning banner, daily-email recipient setup, and clearing a request after confirming downstream erasure.
01-account-and-admin.mp4
2. Withdrawal, retained contacts and reapproval (39 seconds)
The unofficial-client owner's email, contact reminders surviving withdrawal and reload, official-client erasure follow-up requests, and reapproval leaving an existing request open.
02-withdrawal-and-reapproval.mp4
3. Client-owner deletion acknowledgement (25 seconds)
Owned clients and the requirement to erase collected personal information, deletion blocked without acknowledgement, and successful deletion after checking the acknowledgement.
03-client-owner-acknowledgement.mp4