fix(admin): chemin d'echec PIN atomique (pin.failed + throttle dans 1 transaction) #30

Merged
Corentin merged 1 commit from fix/pin-failure-atomicity into dev 2026-06-16 14:21:50 +02:00
Owner

Finding LOW (audit 2026-06-16, critique de completude)

Sur un PIN invalide, ProductController ecrivait la trace audit_log pin.failed (autocommit) PUIS appelait PinThrottle::recordFailure (qui ouvrait sa propre transaction) : deux ecritures non atomiques. Un crash entre les deux laisse un etat partiel (trace sans increment, ou l'inverse), en tension avec le claim RG-T08 (audit dans la meme transaction que l'effet, tenu sur le chemin de succes).

Correctif

  • PinThrottle::recordFailureWithin($db, ...) extrait (memes effets : upsert atomique + backoff, sans ouvrir de transaction). recordFailure() reste l'API autonome qui l'enveloppe (contrat public + tests inchanges).
  • ProductController::update/destroy : les chemins d'echec PIN enveloppent logFailedPin($db, ...) + recordFailureWithin($db, ...) dans une transaction. logFailedPin prend le $db de la transaction.

Verification

  • Suite 188 verte, aucun test modifie (les assertions audit/throttle tiennent dans la transaction).
  • PinThrottleDbTest 2/2 contre la vraie MariaDB (user en moindre privilege) : SQL refactore OK end-to-end.
  • PHPStan L6 propre.

Pas de label auto-merge.

## Finding LOW (audit 2026-06-16, critique de completude) Sur un PIN invalide, `ProductController` ecrivait la trace `audit_log` `pin.failed` (autocommit) PUIS appelait `PinThrottle::recordFailure` (qui ouvrait **sa propre** transaction) : deux ecritures **non atomiques**. Un crash entre les deux laisse un etat partiel (trace sans increment, ou l'inverse), en tension avec le claim RG-T08 (audit dans la meme transaction que l'effet, tenu sur le chemin de succes). ## Correctif - `PinThrottle::recordFailureWithin($db, ...)` extrait (memes effets : upsert atomique + backoff, **sans** ouvrir de transaction). `recordFailure()` reste l'API autonome qui l'enveloppe (contrat public + tests inchanges). - `ProductController::update`/`destroy` : les chemins d'echec PIN enveloppent `logFailedPin($db, ...)` + `recordFailureWithin($db, ...)` dans **une** transaction. `logFailedPin` prend le `$db` de la transaction. ## Verification - Suite 188 verte, **aucun test modifie** (les assertions audit/throttle tiennent dans la transaction). - `PinThrottleDbTest` 2/2 contre la vraie MariaDB (user en moindre privilege) : SQL refactore OK end-to-end. - PHPStan L6 propre. Pas de label auto-merge.
Corentin added 1 commit 2026-06-16 14:15:23 +02:00
fix(admin): chemin d'echec PIN atomique (pin.failed + throttle dans 1 transaction)
All checks were successful
CI / php-lint (pull_request) Successful in 25s
CI / static-tests (push) Successful in 37s
CI / auto-merge (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 11s
CI / auto-merge (push) Has been skipped
CI / static-tests (pull_request) Successful in 41s
CI / secret-scan (push) Successful in 8s
CI / php-lint (push) Successful in 24s
a3fa72cf86
Sur un PIN invalide, ProductController ecrivait la trace audit pin.failed
(autocommit) PUIS appelait PinThrottle::recordFailure (qui ouvrait SA propre
transaction) : deux ecritures non atomiques, un crash entre les deux laissait un
etat partiel, en tension avec le claim RG-T08 (audit dans la meme transaction que
l'effet).

- PinThrottle : extraction de recordFailureWithin(db, ...) (memes effets, SANS
  transaction propre) ; recordFailure() reste l'API autonome (l'enveloppe).
- ProductController (update + destroy) : les chemins d'echec PIN enveloppent
  logFailedPin(, ...) + recordFailureWithin(, ...) dans UNE transaction.
- logFailedPin prend desormais le  de la transaction.

Aucun changement de test necessaire (les assertions audit/throttle tiennent dans
la transaction). 188 verts, PinThrottleDbTest 2/2 contre la vraie DB, PHPStan L6.
Corentin merged commit 05da325d05 into dev 2026-06-16 14:21:50 +02:00
Corentin deleted branch fix/pin-failure-atomicity 2026-06-16 14:21:51 +02:00
Sign in to join this conversation.
No reviewers
No labels
auto-merge
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: AcadeNice/corentin_wakdo#30
No description provided.