From 2e7aebf651f01734cb9c3f67aa22b790850c3f2a Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Mon, 20 Jul 2026 05:33:46 +0100 Subject: [PATCH] fix(db): enable SQLite foreign_keys explicitly (audit 6c-9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SQLite defaults foreign_keys OFF per connection, and the schema relies on ON DELETE CASCADE (entry_attachments, entries_password_history, recovery_keys). FireDAC is said to default it On but that's undocumented here — set ForeignKeys=On so a permanent delete never orphans encrypted blobs. Correct in both cases (no-op if already On). Base check before fix: 0 orphans. Co-Authored-By: Claude Opus 4.8 --- CODE_AUDIT.md | 7 +++++++ delphi-backend/Source/PM.Database.pas | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/CODE_AUDIT.md b/CODE_AUDIT.md index 7f5fff3..6764f22 100644 --- a/CODE_AUDIT.md +++ b/CODE_AUDIT.md @@ -896,6 +896,13 @@ TJSONHelper.SendJSON(AResponse, LArr); // libère LArr (AOwnsObj=True) ### 6c-9. ❓ `PRAGMA foreign_keys` — à vérifier, non tranché +> ✅ **RÉSOLU 2026-07-16.** `FConn.Params.Values['ForeignKeys'] := 'On'` ajouté +> à la config de connexion FireDAC ([PM.Database.pas](delphi-backend/Source/PM.Database.pas)). +> Correct dans les deux cas (no-op si c'était déjà le défaut). **Vérif base +> avant fix : 0 attachment / 0 history orphelin** — soit le défaut FireDAC était +> déjà On, soit aucun delete-permanent-avec-attachments n'a encore eu lieu ; +> l'explicite lève le doute pour de bon. + `PRAGMA foreign_keys` n'est défini **nulle part**. Le schéma s'appuie pourtant sur `ON DELETE CASCADE` : [Entries.pas:704](delphi-backend/Handlers/PM.Handler.Entries.pas:704) (delete permanent) ne nettoie **ni** `entry_attachments` **ni** diff --git a/delphi-backend/Source/PM.Database.pas b/delphi-backend/Source/PM.Database.pas index 110ea3e..79440b4 100644 --- a/delphi-backend/Source/PM.Database.pas +++ b/delphi-backend/Source/PM.Database.pas @@ -83,6 +83,12 @@ begin FConn.Params.Values['Synchronous'] := 'Normal'; FConn.Params.Values['BusyTimeout'] := '5000'; FConn.Params.Values['JournalMode'] := 'WAL'; + // Explicit ON: SQLite defaults foreign_keys OFF per-connection, and the + // schema relies on ON DELETE CASCADE (entry_attachments, entries_password_ + // history, recovery_keys on user/entry delete). FireDAC is *said* to default + // this On but it's undocumented for us — set it so a permanent delete never + // leaves orphaned encrypted blobs. No-op if it was already On (§6c-9). + FConn.Params.Values['ForeignKeys'] := 'On'; FConn.Open; CreateSchema; ApplyMigrations;