Skip to content

docs(adr): file de suppression — deux conceptions mortes avant la bonne (ADR-024)#279

Merged
thierryvm merged 1 commit into
mainfrom
docs/adr-024-deletion-queue
Jul 27, 2026
Merged

docs(adr): file de suppression — deux conceptions mortes avant la bonne (ADR-024)#279
thierryvm merged 1 commit into
mainfrom
docs/adr-024-deletion-queue

Conversation

@thierryvm

@thierryvm thierryvm commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Pourquoi cet ADR existe

L'étape 3b doit brancher un exécuteur sur une file de suppression que rien ne vide,
pendant que /app/settings/deletion-status affiche à l'utilisateur une date et un décompte
de jours restants. Ce n'est pas une omission : c'est une affirmation inexacte faite à la
personne concernée
(art. 12(1)) sur un droit garanti par l'art. 17.

Brancher cet exécuteur impose des choix de schéma qui ne se défont pas : statut
supplémentaire, colonne de verrou, index unique partiel, fonction SQL, réécriture de deux
politiques RLS. ADR-023 ne couvrait que le délai de grâce. Doctrine projet : décision en
session N, implémentation en session N+1
— donc zéro ligne de code applicatif ici.

Deux conceptions mortes, consignées exprès

Rien n'invite plus sûrement à réécrire une mauvaise idée que son absence du dossier.

Conception 1 — fonction SECURITY DEFINER atomique. Rejetée.
FORCE ROW LEVEL SECURITY s'applique au propriétaire de la table. Possédée par
postgres, la fonction écrirait zéro ligne sans lever d'erreur si le postgres
hébergé n'a pas BYPASSRLS — ce qu'on ne peut pas mesurer. Compte supprimé, IP et
user-agent conservés, plus aucune clé de jointure pour les retrouver.

Conception 2 — la même en SECURITY INVOKER appelée par service_role. Rejetée aussi.
Mesuré : service_role n'a aucun privilège sur auth.users ni sur
auth.audit_log_entries.

Conséquence : l'atomicité SQL de bout en bout est impossible par toute conception.
Ce n'est pas une limite de notre code, c'est la frontière entre PostgREST et GoTrue.

La décision

La garantie devient l'idempotence et la reprise, pas l'atomicité. Il n'y a qu'une
instruction irréversible ; la précéder d'un nettoyage rejouable suffit. Et surtout :
aucun privilège nouveau n'est demandé — c'est ce qui rend cette conception défendable
là où les deux autres reposaient sur une hypothèse invérifiable.

Trois corollaires contre-intuitifs, écrits pour ne pas être redécouverts :

  • completed / completed_at sont inatteignables — la ligne cascade avec le compte.
  • Un deleteUser « user not found » compte comme un succès, sinon la ligne devient une
    pilule empoisonnée réclamée et échouée chaque jour, pour toujours.
  • Une pseudonymisation touchant 0 ligne est un succès aussi. L'inverse gèlerait la file
    pour tout compte sans événement d'audit — exactement la panne muette qu'on corrige.

Le verrou anti-double-suppression repose sur une nouvelle colonne claimed_at, jamais
sur requested_at : une ligne n'étant réclamable que 14 jours après sa demande, un test
sur requested_at serait toujours vrai et remettrait en file les lignes qu'une
exécution concurrente est en train de traiter.

deletion_self_insert est supprimée plutôt que durcie. Vérifié : aucune insertion
client n'existe dans src/. La politique accorde une capacité que le produit n'utilise
pas — et c'est la capacité, pas sa date, qui est le vecteur de vol de session.

Livraison en deux PR : A inerte (rien ne peut détruire), B armement. La revue de B ne
portera alors que sur une question : est-ce que ça peut partir quand il ne faut pas ?

Contenu

  • docs/adr/ADR-024-… — la décision, ce qui est écarté, et ce qui restera non prouvé
  • docs/plans/step-3b-deletion-queue.md — le plan d'exécution pour la session suivante

Ce qui reste à faire côté @Thierry

Trois lectures SQL en production, aucune écriture (détail dans le plan). La troisième
est un NO-GO de PR-B : toute la conception repose sur un chemin PostgREST service_role
jamais re-vérifié en production depuis le correctif #273.

Portée

Markdown uniquement, aucun code applicatif. plan-reviewer a fait trois tours sur ce
dossier et a bloqué à chaque fois quelque chose de réel — dont, au dernier tour, le fait
que cette décision de schéma ne pouvait pas partir dans la même session que son
implémentation.

🤖 Generated with Claude Code

Résumé par Sourcery

Documenter la conception de la file d’attente de suppression de compte et le plan de mise en œuvre, en séparant les modifications de schéma et d’orchestration (PR-A) du câblage du cron et de la modification de la période de grâce (PR-B).

Améliorations :

  • Clarifier les implications RGPD et produit du flux de suppression, y compris les sémantiques de suppression idempotente, la gestion du journal d’audit et le périmètre de destruction de l’espace de travail.
  • Consigner les vérifications requises en production, la Definition of Done et les responsabilités QA pour activer en toute sécurité le cron de suppression et la période de grâce de 14 jours.

Documentation :

  • Ajouter ADR-024 documentant la conception choisie de la file d’attente de suppression de compte, les approches rejetées, les invariants et les risques ouverts.
  • Ajouter un plan d’exécution détaillé pour l’étape 3b décrivant comment introduire la file d’attente de suppression, scindé en une PR-A non destructive et une PR-B armant le cron, incluant les tests, les vérifications de déploiement et le rollback.
Original summary in English

Summary by Sourcery

Document the account deletion queue design and implementation plan, separating schema and orchestration changes (PR-A) from cron wiring and grace-period change (PR-B).

Enhancements:

  • Clarify GDPR and product implications of the deletion flow, including idempotent deletion semantics, audit log handling, and workspace destruction radius.
  • Record required production checks, Definition of Done, and QA responsibilities for safely enabling the deletion cron and 14-day grace period.

Documentation:

  • Add ADR-024 documenting the chosen account deletion queue design, rejected approaches, invariants, and open risks.
  • Add a detailed execution plan for step 3b describing how to introduce the deletion queue, split into a non-destructive PR-A and a cron-arming PR-B, including tests, rollout checks, and rollback.

L'étape 3b doit brancher un exécuteur sur une file de suppression que rien ne
vide, pendant que l'écran de statut affiche à l'utilisateur une date et un
décompte de jours. Ce n'est pas une omission, c'est une affirmation inexacte
faite à la personne concernée (art. 12(1)) sur un droit garanti par l'art. 17.

Brancher cet exécuteur impose des choix de schéma qui ne se défont pas :
statut supplémentaire, colonne de verrou, index unique partiel, fonction SQL,
et réécriture de deux politiques RLS. ADR-023 ne couvrait que le délai de
grâce. D'où celui-ci — et, par doctrine, aucune ligne de code applicatif ici.

Deux conceptions ont été écrites puis abandonnées, chacune tuée par une
mesure. Elles sont consignées parce que rien n'invite plus sûrement à les
réécrire que leur absence :

  1. Une fonction SECURITY DEFINER atomique. FORCE ROW LEVEL SECURITY
     s'applique au propriétaire de la table : possédée par postgres, elle
     écrirait zéro ligne SANS ERREUR si le postgres hébergé n'a pas
     BYPASSRLS — ce qu'on ne peut pas mesurer. Compte supprimé, IP et
     user-agent conservés, plus aucune clé pour les retrouver.

  2. La même en SECURITY INVOKER appelée par service_role. Mesuré :
     service_role n'a AUCUN privilège sur auth.users ni sur
     auth.audit_log_entries. Aucune fonction SQL appelée par l'app ne peut
     atteindre le schéma auth.

Conclusion qui contraint tout le reste : l'atomicité SQL de bout en bout est
impossible par toute conception. Ce n'est pas une limite de notre code, c'est
la frontière entre PostgREST et GoTrue.

La garantie devient donc l'idempotence et la reprise. Il n'y a qu'une
instruction irréversible ; la précéder d'un nettoyage rejouable suffit, et
aucun privilège nouveau n'est demandé — c'est ce qui rend cette conception
défendable là où les deux autres reposaient sur une hypothèse invérifiable.

Trois corollaires contre-intuitifs, écrits pour ne pas être redécouverts :
completed/completed_at sont inatteignables (la ligne cascade avec le compte),
un « user not found » compte comme un succès, et une pseudonymisation touchant
zéro ligne aussi — l'inverse gèlerait la file pour tout compte sans événement
d'audit, soit exactement la panne muette que ce chantier corrige.

Le verrou anti-double-suppression repose sur une nouvelle colonne claimed_at,
jamais sur requested_at : une ligne n'étant réclamable que 14 jours après sa
demande, un test sur requested_at serait toujours vrai et remettrait en file
les lignes qu'un run concurrent traite.

deletion_self_insert est supprimée plutôt que durcie : vérifié, aucune
insertion client n'existe dans src/, la politique accorde donc une capacité
que le produit n'utilise pas — et c'est la capacité, pas sa date, qui est le
vecteur de vol de session.

Livraison en deux PR : A inerte (rien ne peut détruire), B armement. La revue
de B ne portera alors que sur une question, est-ce que ça peut partir quand il
ne faut pas.

Le plan d'exécution correspondant part avec, dans docs/plans/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @thierryvm, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ankora Ready Ready Preview, Comment Jul 27, 2026 12:47pm

@sourcery-ai

sourcery-ai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Guide du relecteur

Ajoute l’ADR-024 documentant l’architecture finale et les contraintes de la file d’attente de suppression de compte, ainsi qu’un plan d’exécution détaillé pour l’implémenter en deux PR (A : câblage inert de la file, B : activation via cron), incluant les changements de schéma, invariants, tests et vérifications en production — sans encore modifier le code applicatif.

Diagramme de séquence pour le nouveau traitement de la file d’attente de suppression de compte

sequenceDiagram
  actor Cron
  participant Route_api_cron_gdpr as api_cron_gdpr_route
  participant PostgREST_service_role as PostgREST_service_role
  participant claim_pending_deletions as claim_pending_deletions
  participant DeletionCore as deletion_core_ts
  participant GoTrue as GoTrue_auth_admin
  participant DB as Postgres_public

  Cron->>Route_api_cron_gdpr: GET /api/cron/gdpr
  Route_api_cron_gdpr->>Route_api_cron_gdpr: verifyCronSecret
  Route_api_cron_gdpr->>PostgREST_service_role: claimPendingDeletions(25)
  PostgREST_service_role->>claim_pending_deletions: call(batch_size)
  claim_pending_deletions->>DB: update deletion_requests reset stale processing
  claim_pending_deletions->>DB: update deletion_requests set status=processing, claimed_at=now()
  claim_pending_deletions-->>PostgREST_service_role: return request_id, target_user_id*
  PostgREST_service_role-->>Route_api_cron_gdpr: claimed deletions
  loop for each request
    Route_api_cron_gdpr->>DeletionCore: executeDeletionWith(client, userId)
    DeletionCore->>DB: pseudonymiseAuditLog(client, userId)
    alt [pseudonymiseAuditLog error]
      DeletionCore-->>Route_api_cron_gdpr: error
    else [pseudonymiseAuditLog ok]
      DeletionCore->>GoTrue: auth.admin.deleteUser(userId)
      GoTrue-->>DeletionCore: result (including user not found)
      DeletionCore-->>Route_api_cron_gdpr: success
    end
  end
  Route_api_cron_gdpr->>PostgREST_service_role: purge_audit_log_older_than_12_months()
  Route_api_cron_gdpr-->>Cron: JSON {claimed, deleted, failed, purged, capped}
Loading

Diagramme de relations entre entités pour le schéma mis à jour de la file de suppression

erDiagram
  auth_users {
    uuid id
  }

  public_users {
    uuid id
    uuid auth_user_id
  }

  deletion_requests {
    uuid id
    uuid user_id
    text status
    timestamptz requested_at
    timestamptz scheduled_for
    timestamptz claimed_at
  }

  audit_log {
    uuid id
    uuid user_id
    inet ip_address
    text user_agent
  }

  auth_users ||--o{ public_users : auth_cascade
  public_users ||--o{ deletion_requests : user_cascade
  public_users ||--o{ audit_log : on_delete_set_null

  %% Unique partial index conceptually: one active request per user
  deletion_requests }o..o{ deletion_requests : one_active_pending_or_processing_per_user
Loading

Modifications au niveau des fichiers

Changement Détails Fichiers
Introduction de l’ADR-024 décrivant la conception choisie pour la file d’attente de suppression de compte, les conceptions rejetées, les invariants et les lacunes de conformité encore ouvertes.
  • Documenter pourquoi une atomicité SQL complète pour la suppression de compte est impossible étant donné les frontières PostgREST/GoTrue et les privilèges Supabase actuels.
  • Définir la conception finale basée sur une suppression idempotente et rejouable : pseudonymisation des journaux d’audit en premier, puis suppression de l’utilisateur via GoTrue, sans nécessiter de nouveaux privilèges de base de données.
  • Spécifier la sémantique de la file et le modèle de verrouillage en utilisant un seuil de réessai basé sur claimed_at, un index partiel unique sur les requêtes actives, et des contraintes entre maxDuration et la fenêtre de réessai.
  • Clarifier les changements de politiques RLS : suppression de la capacité d’insertion côté client, restriction des auto-mises à jour à pending→cancelled, et changement de purge_audit_log_older_than_12_months() en SECURITY INVOKER.
  • Énumérer les vérifications pré-prod en production, les implications en termes de rayon de destruction, la dette de documentation autour du délai de grâce 30→14 jours, et les hypothèses résiduelles non prouvées après implémentation.
docs/adr/ADR-024-file-de-suppression-de-compte.md
Ajout d’un plan d’implémentation étape 3b détaillant comment appliquer les décisions de l’ADR-024 en deux PR, couvrant les migrations, les types Supabase, l’extraction de l’orchestration, les mises à jour UI/i18n, les tests, la route cron et les étapes de vérification en production.
  • Décrire les étapes de la PR-A (file inert) : nouveau statut deletion_requests et claimed_at, déduplication et index partiel unique, fonction SQL claim_pending_deletions et changements RLS, et passage de purge_audit_log_older_than_12_months() en SECURITY INVOKER.
  • Définir le workflow de dev autour des migrations : supabase db push sur la production liée, régénération des types Supabase, et séquencement des vérifications de types.
  • Planifier l’extraction de l’orchestration de suppression dans un module core non-server-only pour permettre de vrais tests e2e, tout en conservant un wrapper server-only pour la création de client privilégié et la surface d’API.
  • Détailler les changements requis pour les flux de demande/annulation de suppression, la gestion d’état UI pour le nouveau statut processing, et les chaînes i18n pour toutes les locales, y compris le comportement lorsque l’annulation est impossible.
  • Spécifier la couverture de tests unitaires et e2e nécessaire pour le comportement de la file, la sémantique de pseudonymisation, les critères de succès de suppression, les restrictions RLS, ainsi que les specs Playwright authentifiées, plus le câblage CI et les exigences de falsification.
  • Décrire les étapes de la PR-B (armement) : comportement et sécurité de la route cron (CRON_SECRET, comparaison résistante au timing, isolation des erreurs, logs structurés, contraintes de maxDuration), câblage du cron Vercel, mise à jour du délai de grâce 30→14 jours dans le code, la doc et l’i18n, ainsi que la vérification post-merge de l’armement.
  • Lister trois vérifications SQL obligatoires en lecture seule en production, les étapes de rollback (y compris le dégel de la file), et les attentes de Definition of Done pour les deux PR et leurs responsables QA.
docs/plans/step-3b-deletion-queue.md

Conseils et commandes

Interagir avec Sourcery

  • Déclencher une nouvelle revue : Commentez @sourcery-ai review sur la pull request.
  • Poursuivre les discussions : Répondez directement aux commentaires de revue de Sourcery.
  • Générer un ticket GitHub à partir d’un commentaire de revue : Demandez à Sourcery de créer un
    ticket à partir d’un commentaire de revue en y répondant. Vous pouvez également répondre à un
    commentaire de revue avec @sourcery-ai issue pour créer un ticket à partir de celui-ci.
  • Générer un titre de pull request : Écrivez @sourcery-ai n’importe où dans le titre
    de la pull request pour générer un titre à tout moment. Vous pouvez aussi commenter
    @sourcery-ai title sur la pull request pour (re)générer le titre à tout moment.
  • Générer un résumé de pull request : Écrivez @sourcery-ai summary n’importe où dans
    le corps de la pull request pour générer un résumé de PR à tout moment exactement là où
    vous le souhaitez. Vous pouvez aussi commenter @sourcery-ai summary sur la pull request
    pour (re)générer le résumé à tout moment.
  • Générer un guide du relecteur : Commentez @sourcery-ai guide sur la pull request
    pour (re)générer le guide du relecteur à tout moment.
  • Résoudre tous les commentaires Sourcery : Commentez @sourcery-ai resolve sur la pull
    request pour résoudre tous les commentaires Sourcery. Utile si vous avez déjà
    traité tous les commentaires et ne voulez plus les voir.
  • Rejeter toutes les revues Sourcery : Commentez @sourcery-ai dismiss sur la pull
    request pour rejeter toutes les revues Sourcery existantes. Particulièrement utile si vous
    voulez repartir de zéro avec une nouvelle revue — n’oubliez pas de commenter
    @sourcery-ai review pour déclencher une nouvelle revue !

Personnaliser votre expérience

Accédez à votre dashboard pour :

  • Activer ou désactiver des fonctionnalités de revue telles que le résumé de pull request
    généré par Sourcery, le guide du relecteur, et d’autres.
  • Changer la langue de revue.
  • Ajouter, supprimer ou modifier des instructions de revue personnalisées.
  • Ajuster d’autres paramètres de revue.

Obtenir de l’aide

Original review guide in English

Reviewer's Guide

Adds ADR-024 documenting the final architecture and constraints for the account deletion queue, and a detailed execution plan for implementing it in two PRs (A: inert queue wiring, B: cron arming), including schema changes, invariants, tests, and production checks—without changing any application code yet.

Sequence diagram for the new account deletion queue processing

sequenceDiagram
  actor Cron
  participant Route_api_cron_gdpr as api_cron_gdpr_route
  participant PostgREST_service_role as PostgREST_service_role
  participant claim_pending_deletions as claim_pending_deletions
  participant DeletionCore as deletion_core_ts
  participant GoTrue as GoTrue_auth_admin
  participant DB as Postgres_public

  Cron->>Route_api_cron_gdpr: GET /api/cron/gdpr
  Route_api_cron_gdpr->>Route_api_cron_gdpr: verifyCronSecret
  Route_api_cron_gdpr->>PostgREST_service_role: claimPendingDeletions(25)
  PostgREST_service_role->>claim_pending_deletions: call(batch_size)
  claim_pending_deletions->>DB: update deletion_requests reset stale processing
  claim_pending_deletions->>DB: update deletion_requests set status=processing, claimed_at=now()
  claim_pending_deletions-->>PostgREST_service_role: return request_id, target_user_id*
  PostgREST_service_role-->>Route_api_cron_gdpr: claimed deletions
  loop for each request
    Route_api_cron_gdpr->>DeletionCore: executeDeletionWith(client, userId)
    DeletionCore->>DB: pseudonymiseAuditLog(client, userId)
    alt [pseudonymiseAuditLog error]
      DeletionCore-->>Route_api_cron_gdpr: error
    else [pseudonymiseAuditLog ok]
      DeletionCore->>GoTrue: auth.admin.deleteUser(userId)
      GoTrue-->>DeletionCore: result (including user not found)
      DeletionCore-->>Route_api_cron_gdpr: success
    end
  end
  Route_api_cron_gdpr->>PostgREST_service_role: purge_audit_log_older_than_12_months()
  Route_api_cron_gdpr-->>Cron: JSON {claimed, deleted, failed, purged, capped}
Loading

Entity relationship diagram for the updated deletion queue schema

erDiagram
  auth_users {
    uuid id
  }

  public_users {
    uuid id
    uuid auth_user_id
  }

  deletion_requests {
    uuid id
    uuid user_id
    text status
    timestamptz requested_at
    timestamptz scheduled_for
    timestamptz claimed_at
  }

  audit_log {
    uuid id
    uuid user_id
    inet ip_address
    text user_agent
  }

  auth_users ||--o{ public_users : auth_cascade
  public_users ||--o{ deletion_requests : user_cascade
  public_users ||--o{ audit_log : on_delete_set_null

  %% Unique partial index conceptually: one active request per user
  deletion_requests }o..o{ deletion_requests : one_active_pending_or_processing_per_user
Loading

File-Level Changes

Change Details Files
Introduce ADR-024 describing the chosen design for the account deletion queue, rejected designs, invariants, and open compliance gaps.
  • Document why full SQL atomicity for account deletion is impossible given PostgREST/GoTrue boundaries and current Supabase privileges.
  • Define the final design based on idempotent, replayable deletion: pseudonymising audit logs first, then deleting the user via GoTrue, without requiring new database privileges.
  • Specify the queue semantics and locking model using a claimed_at-based retry threshold, unique-partial index over active requests, and constraints on maxDuration vs. retry window.
  • Clarify RLS policy changes: dropping client-side insert capability, restricting self-updates to pending→cancelled, and changing purge_audit_log_older_than_12_months() to SECURITY INVOKER.
  • Enumerate pre-prod production checks, the destruction radius implications, documentation debt around 30→14 day grace, and residual unproven assumptions after implementation.
docs/adr/ADR-024-file-de-suppression-de-compte.md
Add a step-3b implementation plan detailing how to apply the ADR-024 decisions over two PRs, covering migrations, Supabase types, orchestration extraction, UI/i18n updates, tests, cron route, and production verification steps.
  • Describe PR-A (inert queue) steps: new deletion_requests status and claimed_at, duplicate collapse and partial unique index, claim_pending_deletions SQL function and RLS changes, and flipping purge_audit_log_older_than_12_months() to SECURITY INVOKER.
  • Lay out dev workflow around migrations: supabase db push against linked production, regeneration of Supabase types, and typecheck sequencing.
  • Plan extraction of deletion orchestration into a non-server-only core module to enable real e2e tests, while keeping a server-only wrapper for privileged client creation and API surface.
  • Detail required changes to deletion request/cancel flows, UI state handling for the new processing status, and i18n strings for all locales, including behavior when cancellation is impossible.
  • Specify unit and e2e test coverage needed for queue behavior, pseudonymisation semantics, deletion success criteria, RLS restrictions, and Playwright authenticated specs, plus CI plumbing and falsification requirements.
  • Describe PR-B (arming) steps: cron route behavior and security (CRON_SECRET, timing-safe comparison, error isolation, structured logging, maxDuration constraints), Vercel cron wiring, 30→14 day grace updates across code, docs, and i18n, along with post-merge arming verification.
  • List three mandatory read-only SQL checks in production, rollback steps (including queue unfreezing), and Definition of Done expectations for both PRs and their QA agents.
docs/plans/step-3b-deletion-queue.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@thierryvm
thierryvm merged commit 7a81a4b into main Jul 27, 2026
11 checks passed
@thierryvm
thierryvm deleted the docs/adr-024-deletion-queue branch July 27, 2026 12:57
thierryvm added a commit that referenced this pull request Jul 27, 2026
#280)

## Pourquoi maintenant

Règle durable du projet : **le ROADMAP se remet à jour avant d'ouvrir la
branche suivante,
pas après.** La branche suivante est PR-A de l'étape 3b. Deux écarts à
solder d'abord.

## Écart 1 — l'étape 3 était annoncée « suivante »

Elle est en cours depuis deux jours, et son détail vaut d'être lisible.
L'exécution des
spécifications a montré que le préalable n'était pas la file de
suppression, mais **ce sur
quoi elle repose** : le journal d'audit n'enregistrait rien depuis
avril, et trois
affirmations publiques étaient inexactes.

Six lots livrés (#273#279), deux restants (PR-A inerte, PR-B
armement), et un écart
art. 17 mesuré qui part en session dédiée (#278).

Le **verrou de PR-B** est désormais écrit dans le ROADMAP : trois
lectures production, dont
une NO-GO — toute la conception repose sur un chemin PostgREST
`service_role` jamais
re-vérifié en production depuis #273.

## Écart 2 — une dette réglée encore listée comme ouverte

« Angle mort du préflight comptes » figurait dans les dettes ouvertes
alors que #276 l'a
comblé ce matin. Un ROADMAP qui garde une dette réglée est aussi
trompeur qu'un qui en
oublie une : il fait perdre du temps à qui la reprend.

## Portée

Un seul fichier, markdown. Aucun code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

## Summary by Sourcery

Mettre à jour le ROADMAP pour refléter l’état actuel et la répartition
détaillée de l’étape 3, ainsi que la résolution récente de la dette.

Documentation :
- Ajouter une sous-section détaillée documentant l’avancement de l’étape
3, les lots livrés, les PR restantes et les contraintes associées en
matière d’audit/journalisation.
- Marquer la dette « Angle mort du préflight comptes » comme résolue,
avec une explication mise à jour du nouveau comportement de vérification
pour les comptes Supabase et Vercel.

<details>
<summary>Original summary in English</summary>

## Summary by Sourcery

Update the ROADMAP to reflect the current status and detailed breakdown
of step 3 and recent debt resolution.

Documentation:
- Add a detailed sub-section documenting step 3 progress, delivered
lots, remaining PRs, and associated audit/logging constraints.
- Mark the 'Angle mort du préflight comptes' debt as resolved with an
updated explanation of the new verification behavior for Supabase and
Vercel accounts.

</details>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:review-needed Ready for review type:docs Documentation only

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant