fix(mail): DSGVO Art. 17 — manuelles Sample-Cleanup bei Account-Delete
MailClassificationSample hat keine userId-FK-Cascade im Schema (connectionId ist nullable). Samples ohne connectionId blieben nach deleteAllMailConnections() als Orphans stehen. Neuer Helper deleteUserMailClassificationSamples() löscht explizit nach userId — wird in delete.delete.ts parallel zu anderen Lösch-Ops ausgeführt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
bdd93668ae
commit
343f9ab567
@ -9,7 +9,10 @@ import {
|
|||||||
deleteUserCoachSessions,
|
deleteUserCoachSessions,
|
||||||
} from "../../db/user";
|
} from "../../db/user";
|
||||||
import { deleteProfile } from "../../db/profile";
|
import { deleteProfile } from "../../db/profile";
|
||||||
import { deleteAllMailConnections } from "../../db/mail";
|
import {
|
||||||
|
deleteAllMailConnections,
|
||||||
|
deleteUserMailClassificationSamples,
|
||||||
|
} from "../../db/mail";
|
||||||
import { writeConsentRevoke } from "../../db/consent";
|
import { writeConsentRevoke } from "../../db/consent";
|
||||||
import { usePrisma } from "../../utils/prisma";
|
import { usePrisma } from "../../utils/prisma";
|
||||||
|
|
||||||
@ -44,6 +47,9 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete all user data (DSGVO Art. 17)
|
// Delete all user data (DSGVO Art. 17)
|
||||||
|
// Reihenfolge: Samples VOR Connections löschen (oder parallel — FK-Reihenfolge
|
||||||
|
// egal weil wir nach userId filtern). Samples haben keine userId-FK-Cascade
|
||||||
|
// im Schema (connectionId ist nullable), daher manuelles Cleanup zwingend.
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
deleteUserUrgeLogs(userId),
|
deleteUserUrgeLogs(userId),
|
||||||
deleteUserSosSessions(userId),
|
deleteUserSosSessions(userId),
|
||||||
@ -52,6 +58,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
deleteAllUserCustomDomains(userId),
|
deleteAllUserCustomDomains(userId),
|
||||||
deleteUserTrustedContacts(userId),
|
deleteUserTrustedContacts(userId),
|
||||||
deleteUserCoachSessions(userId),
|
deleteUserCoachSessions(userId),
|
||||||
|
deleteUserMailClassificationSamples(userId),
|
||||||
deleteAllMailConnections(userId),
|
deleteAllMailConnections(userId),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@ -193,13 +193,33 @@ export async function insertMailBlocked(
|
|||||||
|
|
||||||
// ─── MailClassificationSample ─────────────────────────────────────────────────
|
// ─── MailClassificationSample ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Löscht alle MailClassificationSamples eines Users.
|
||||||
|
*
|
||||||
|
* Warum manuell und nicht via Prisma-Cascade:
|
||||||
|
* MailClassificationSample hat KEINE userId-Relation mit onDelete: Cascade im Schema
|
||||||
|
* (connectionId hat Cascade, aber connectionId ist nullable). Samples mit
|
||||||
|
* connectionId=null wären nach deleteAllMailConnections() Orphans.
|
||||||
|
*
|
||||||
|
* Muss in delete.delete.ts VOR deleteAllMailConnections() aufgerufen werden
|
||||||
|
* (oder in Promise.all parallel) — FK-Reihenfolge spielt keine Rolle weil wir
|
||||||
|
* nach userId filtern, nicht nach connectionId.
|
||||||
|
*
|
||||||
|
* DSGVO Art. 17: User-Daten müssen vollständig gelöscht werden.
|
||||||
|
*/
|
||||||
|
export async function deleteUserMailClassificationSamples(userId: string) {
|
||||||
|
const db = usePrisma();
|
||||||
|
return db.mailClassificationSample.deleteMany({ where: { userId } });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schreibt einen Klassifikations-Sample-Eintrag für ML-Phase 3.
|
* Schreibt einen Klassifikations-Sample-Eintrag für ML-Phase 3.
|
||||||
* Wird nach JEDER Klassifikation aufgerufen (außer Layer 0 / Already-blocked Skips).
|
* Wird nach JEDER Klassifikation aufgerufen (außer Layer 0 / Already-blocked Skips).
|
||||||
*
|
*
|
||||||
* DSGVO: Nur Features, keine Mail-Inhalte (kein Body). Subject + Sender sind
|
* DSGVO: Nur Features, keine Mail-Inhalte (kein Body). Subject + Sender sind
|
||||||
* kurzlebige Detection-Signale, kein narrativer Inhalt. Cascade-Delete bei
|
* kurzlebige Detection-Signale, kein narrativer Inhalt.
|
||||||
* User-Löschung (Art. 17).
|
* Vollständige Löschung bei Account-Delete via deleteUserMailClassificationSamples()
|
||||||
|
* (Art. 17) — NICHT via Prisma-Cascade, da userId keine FK-Relation hat.
|
||||||
*/
|
*/
|
||||||
export async function insertMailClassificationSample(entry: {
|
export async function insertMailClassificationSample(entry: {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user