|
| 1 | +--- |
| 2 | +title: Personal-data map and erasure verification |
| 3 | +description: The authoritative map from personal-data stores to export, retention, and erasure controls. |
| 4 | +--- |
| 5 | + |
| 6 | +# Personal-data map and erasure verification |
| 7 | + |
| 8 | +This inventory maps each personal-data store to its removal control and executable evidence. Add a |
| 9 | +store or derived copy here, with an erasure or retention test, before it receives personal data: |
| 10 | +`PersonalDataMapArchTest` fails the build when a database table is named in neither this map nor the |
| 11 | +test's own list of tables that hold no personal data, and when a source or test cited below has |
| 12 | +moved. |
| 13 | +Workspace purge applies storage limitation when a workspace loses its purpose; a verified |
| 14 | +person-erasure request follows the separate account or operator path. |
| 15 | + |
| 16 | +| Store / copy | Data and access path | Workspace removal | Person erasure | Residual retention and evidence | |
| 17 | +|---|---|---|---|---| |
| 18 | +| PostgreSQL account, identity and authentication rows — `account`, `account_feature`, `account_export`, `identity_link`, `issued_jwt`, `user_preferences`, `consent_decision`, `auth_event`, `config_audit_event` | Sign-in identity; self-service export plus operator supplement | Account-global rows remain | 48-hour cooldown, then account purge | Audit rows detach the actor and expire after 365 days; exports expire after 48 hours. `server/application/src/test/java/de/tum/cit/aet/hephaestus/core/auth/AccountHardDeleteSweeperIntegrationTest.java` and `server/application/src/test/java/de/tum/cit/aet/hephaestus/core/auth/export/AccountExportRetentionIntegrationTest.java`. | |
| 19 | +| PostgreSQL product feedback and surveys — `product_feedback`, `product_survey_submission` | Data supplied by the account holder; operator supplement | Purge contributors remove workspace-owned rows | Account purge removes account-owned rows | `server/application/src/test/java/de/tum/cit/aet/hephaestus/workspace/WorkspacePurgeIntegrationTest.java` and account-purge coverage above. | |
| 20 | +| PostgreSQL SCM mirror — `user`, `organization`, `organization_membership`, `team`, `team_membership`, `team_repository_permission`, `repository`, `repository_collaborator`, `pull_request`, `pull_request_requested_reviewers`, `pull_request_review`, `pull_request_review_comment`, `pull_request_review_thread`, `issue`, `issue_assignee`, `issue_comment`, `milestone`, `discussion`, `discussion_comment`, `git_commit`, `commit_contributor`, `commit_file_change`, `project`, `project_item`, `project_field_value`, `project_status_update` | GitHub/GitLab profiles and authored work; source-provider export plus operator supplement | Last repository/connection removal and workspace purge erase the active mirror | Verified source-account matching; shared authorship may be pseudonymised where an exception applies | `server/application/src/test/java/de/tum/cit/aet/hephaestus/workspace/ScmWorkspaceErasureIntegrationTest.java`. | |
| 21 | +| PostgreSQL Slack mirror — `slack_message`, `slack_thread`, `slack_monitored_channel`, `slack_participant_consent`, `slack_channel_consent_event`, `mentor_slack_thread` | Messages, identities and attribution; operator supplement | Disconnect and workspace purge | Slack opt-out and verified operator path | `server/application/src/test/java/de/tum/cit/aet/hephaestus/integration/slack/retention/SlackRetentionErasureIntegrationTest.java` and `server/application/src/test/java/de/tum/cit/aet/hephaestus/integration/slack/interactivity/SlackAppHomeOptOutErasureIntegrationTest.java`. | |
| 22 | +| PostgreSQL Outline mirror — `outline_document`, `outline_collection`, `outline_document_event` | Documents and attribution; operator supplement | Collection removal, disconnect and workspace purge | Verified operator path | `server/application/src/test/java/de/tum/cit/aet/hephaestus/integration/outline/lifecycle/OutlineWorkspacePurgeAdapterIntegrationTest.java`. | |
| 23 | +| PostgreSQL mentor, observations, feedback, recognition and activity read models — `chat_thread`, `chat_message`, `chat_message_vote`, `observation`, `reaction`, `feedback`, `feedback_observation`, `feedback_dispatch`, `feedback_placement`, `feedback_approval`, `delivery_policy_evaluation`, `activity_event`, `user_achievement`, `workspace_membership` | Conversations and derived judgements; operator supplement | Purge contributors remove each workspace-owned family | Account or source identity is removed; conversation-derived feedback is erased | `server/application/src/test/java/de/tum/cit/aet/hephaestus/workspace/WorkspacePurgeIntegrationTest.java` exercises the assembled purge chain. | |
| 24 | +| PostgreSQL review-scope selection — `practice_review_person_target` | Which people a workspace administrator selected for practice review; operator supplement | Removed with the workspace: the row cascades from the `workspace_membership` row the purge deletes (`sfk_practice_review_person_target_membership`, `ON DELETE CASCADE`) | Removed with the membership | No independent retention window. `server/application/src/test/java/de/tum/cit/aet/hephaestus/workspace/WorkspacePurgeIntegrationTest.java` proves the membership deletion the cascade follows. | |
| 25 | +| PostgreSQL operator-action and operational-history records — `connection_audit`, `sync_job`, `artifact_signal`, `review_backfill_run`, `review_sweep_schedule` | Which account requested, configured or was selected for a workspace operation, and which artifacts a review campaign covered; operator supplement | **Retained.** Purge transitions connections to `UNINSTALLED` and marks the workspace `PURGED` instead of deleting either row, so neither a purge contributor nor the `ON DELETE CASCADE` on `workspace` reaches these tables | The stored account reference is a login snapshot without a foreign key, or a nullable `user` reference cleared by the database (`sfk_artifact_signal_requested_by`, `ON DELETE SET NULL`); either way it resolves to nothing once the referenced row is gone | `sync_job` keeps only the newest 50 rows per connection, pruned on each insert, and stops changing once the connection is uninstalled. The other four have no retention window and are removed only through the operator-executed erasure path. `server/application/src/main/java/de/tum/cit/aet/hephaestus/integration/core/connection/ConnectionPurgeContributor.java` and `server/application/src/main/java/de/tum/cit/aet/hephaestus/integration/core/sync/SyncJobRepository.java`. | |
| 26 | +| PostgreSQL instance-administration records — `instance_settings`, `instance_llm_settings`, `product_survey` | Which administrator last engaged the instance brake or changed instance LLM policy, kept as a login snapshot (`silent_mode_changed_by`, `updated_by`), and which account authored a survey (`created_by_account_id`); operator supplement | Instance-scoped: workspace purge does not reach them, and a survey aimed at one workspace keeps its definition | The record of who acted deliberately survives account deletion. `silent_mode_changed_by` and `updated_by` are login snapshots with no foreign key, and an account purge does not clear them. `product_survey.created_by_account_id` is a foreign key (`fk_product_survey_creator`, `ON DELETE SET NULL`), but an account purge keeps the account row as a tombstone rather than deleting it, so the reference survives and resolves to a tombstone that carries no personal data | No independent window. A settings row carries only the administrator of the most recent change and the next change overwrites them; a survey carries its author id for as long as the survey exists; the account it points at is a tombstone once that account is purged. `server/application/src/main/java/de/tum/cit/aet/hephaestus/core/settings/InstanceSettings.java`, `server/application/src/main/java/de/tum/cit/aet/hephaestus/agent/catalog/InstanceLlmSettings.java`, `server/application/src/main/java/de/tum/cit/aet/hephaestus/productfeedback/Survey.java`, `server/application/src/main/java/de/tum/cit/aet/hephaestus/core/auth/AccountPurger.java`. | |
| 27 | +| PostgreSQL `agent_job`, manifests, evidence references and diagnostics | Review inputs, outputs and provenance; operator supplement | `AgentWorkspacePurgeAdapter` deletes workspace jobs before workspace configuration | No independent subject lookup; rows leave with workspace purge or retention | `server/application/src/test/java/de/tum/cit/aet/hephaestus/agent/AgentWorkspacePurgeIntegrationTest.java`, `server/application/src/test/java/de/tum/cit/aet/hephaestus/agent/job/AgentJobRetentionServiceTest.java`, and `server/application/src/test/java/de/tum/cit/aet/hephaestus/agent/job/AgentJobRetentionObservationIntegrationTest.java` cover purge, 14-day diagnostics and 90-day rows. | |
| 28 | +| PostgreSQL `llm_usage_event` | Token/cost accounting with workspace and opaque source identifier; monthly workspace/admin reports | Retained for accounting until its retention sweep | The identifier is not a foreign key; deleting a source row leaves nothing for it to resolve | The window and its operator control are in the [record of processing](./record-of-processing.md). `server/application/src/test/java/de/tum/cit/aet/hephaestus/agent/usage/LlmUsageRetentionIntegrationTest.java` proves the cutoff across workspaces; `server/application/src/test/java/de/tum/cit/aet/hephaestus/agent/usage/LlmUsageRetentionSweeperTest.java` verifies job outcomes. | |
| 29 | +| NATS JetStream | Buffered webhook, message and document payloads; not directly included in self-service export | No selective deletion | No selective deletion | Slack/Outline expire after 72 hours; GitHub/GitLab after 180 days; byte ceilings can shorten both. Stream configuration tests enforce these bounds. | |
| 30 | +| PostgreSQL evidence bytes | Bounded review input snapshots; operator supplement | SQL authority is erased with its owning rows | Removed with owning rows | Diagnostic payloads expire after 14 days and job provenance after 90 days; evidence retention tests are linked in the `agent_job` row. | |
| 31 | +| Replay directories and content-addressed blobs | Working copies and immutable blobs; not directly included in self-service export | No selective deletion | No selective deletion | Replay directories and unreferenced blobs become eligible after 30 days. [`artifact-source-governance.md`](./artifact-source-governance.md) owns this control. | |
| 32 | +| Configured LLM provider | Prompts and responses for enabled purposes; provider/operator access process | A completed request cannot be retracted | Provider process | Deployment-specific provider terms must define the bound before processing starts; see the [processor checklist](./processor-checklist.md). | |
| 33 | +| GitHub/GitLab/Slack delivery destination | Posted feedback; source-provider export | Not silently crawled or rewritten | Best-effort correction/removal through the operator path | The provider controls its copy and audit history. | |
| 34 | +| Application metrics | Aggregate operational counts without account, workspace, export or source labels | Not applicable | No subject-level series exists | Backend retention is deployment-specific; operators must record it. | |
| 35 | +| Container logs and support bundles | Operational output; logging policy excludes raw request bodies and secrets, but operators must assess exported bundles | No selective deletion | No selective deletion | Shipped container logs rotate by size; support-bundle retention is deployment-specific. | |
| 36 | +| PostgreSQL and filesystem backups | A copy of the backed-up personal-data corpus | No selective deletion inside a backup | Expiry of the backup copy | The application does not configure off-host backups. Operators who add them must document and enforce their retention; see [backup and restore](../backup-restore.mdx). | |
| 37 | + |
| 38 | +## Operator verification |
| 39 | + |
| 40 | +Each erasure, export and retention job publishes a bounded success/failure counter and an |
| 41 | +affected-row counter; the names, labels and cardinality guarantee are in the |
| 42 | +[observability contract](../observability.mdx). Alert configuration remains deployment-owned: alert |
| 43 | +on `outcome="failure"`, on `outcome="incomplete"` — a retention pass that ran out of its time budget |
| 44 | +with expired rows still in place — and on a missing successful daily `llm_usage_retention` run for |
| 45 | +more than 48 hours. Broader alert routing is tracked in |
| 46 | +[#1369](https://github.com/hephaestus-build/Hephaestus/issues/1369). |
| 47 | + |
| 48 | +Review this map with the [record of processing](./record-of-processing.md), |
| 49 | +[artifact-source governance](./artifact-source-governance.md), and the public privacy statement. |
0 commit comments