Story : PD-180 — Webhooks événements utilisateur
Date : 2026-03-07
Itération : v2 (après correction des 15 écarts v1)
1. Résolution des écarts v1
| ECT v1 | Statut v2 |
| ECT-01 (BLOQ) Codes HTTP succès | RÉSOLU — 2xx = DELIVERED spécifié |
| ECT-02 (BLOQ) Append-only vs rétention | RÉSOLU — purge technique vs mutation métier |
| ECT-03 (BLOQ) SSRF | RÉSOLU — INV-15 ajouté, IP privées bloquées |
| ECT-04 (BLOQ) Canonicalisation JSON | RÉSOLU — JSON.stringify ECMAScript |
| ECT-05 (MAJ) ERR-05/06 émetteur | RÉSOLU — reformulé côté émetteur |
| ECT-06 (MAJ) GWT invariants manquants | RÉSOLU — GWT ajoutés |
| ECT-07 (MAJ) Race rotation secret | RÉSOLU — relecture DB à chaque tentative |
| ECT-08 (MAJ) Schéma payload | RÉSOLU — whitelist additionalProperties:false |
| ECT-09 (MAJ) Encodage hash | RÉSOLU — hex lowercase 64 chars |
| ECT-10 (MAJ) Retry complet | RÉSOLU — séquence 10 tentatives complète |
| ECT-11 (MAJ) Secret CSPRNG | RÉSOLU — 32 bytes CSPRNG, SHA-256 en DB |
| ECT-12 (MIN) Code quota | RÉSOLU — 409 fixé |
| ECT-13 (MIN) DELETED terminal | RÉSOLU — "résolution manuelle" retiré |
| ECT-14 (MIN) Fenêtre rate-limit | RÉSOLU — sliding window |
| ECT-15 (MIN) Schémas exotiques | RÉSOLU — INV-04 étendu à tout schéma non-HTTPS |
2. Nouveaux écarts identifiés en v2
BLOQUANTS (2)
| ID | Type | Description | Source |
| ECT-16 | Contradiction | HMAC secret brut vs hash : le partenaire reçoit S brut et vérifie HMAC(S, msg), mais le système stocke SHA-256(S) et "dérive" la clé de signature. Incompatible sans documentation côté partenaire. | Review v2 R-01 |
| ECT-17 | Ambiguïté | Schéma payload strict (additionalProperties:false) avec doc_id/hash obligatoires, mais account.device.revoked et webhook.ping ne sont pas liés à un document. Champs non nullable pour ces events. | Review v2 R-02 |
MAJEURS (5)
| ID | Type | Description | Source |
| ECT-18 | Ambiguïté | Timeout HTTP livraison non spécifié (valeur contractuelle absente) | Review v2 R-03 |
| ECT-19 | Incohérence | Références ECT-XX dans les tests pointent vers un artefact inexistant | Review v2 R-04 |
| ECT-20 | Ambiguïté | Critères d'éligibilité au replay non définis (quels events, quels états) | Review v2 R-05 |
| ECT-21 | Ambiguïté | Attributs modifiables dans le flux Update non listés | Review v2 R-06 |
| ECT-22 | Ambiguïté | Méthode de dérivation clé signature depuis hash non spécifiée | Review v2 R-07 |
MINEURS (4)
| ID | Type | Description | Source |
| ECT-23 | Ambiguïté | Rate limit : unité de comptage (intentions vs tentatives HTTP) | Review v2 R-08 |
| ECT-24 | Hypothèse | JSON.stringify fragile si middleware reconstruit l'objet | Review v2 R-09 |
| ECT-25 | Ambiguïté | Périmètre exact de purge >30j non contractualisé | Review v2 R-10 |
| ECT-26 | Risque | Secret brut affiché une seule fois, irrécovrable si perdu | Review v2 R-11 |
3. Scoring par critère
| Critère | Écarts assignés | Score |
| completeness | ECT-17 (BLOQ), ECT-20 (MAJ), ECT-21 (MAJ) | 10 - 2 - 2 = 6.0 |
| testability | ECT-19 (MAJ), ECT-18 (MAJ) | 10 - 2 = 8.0 |
| clarity | ECT-16 (BLOQ), ECT-22 (MAJ), ECT-23 (MIN), ECT-24 (MIN) | 10 - 2 - 1 - 0.5 = 6.5 |
| traceability | ECT-25 (MIN), ECT-26 (MIN) | 10 - 0.5 = 9.5 |
Moyenne : (6.0 + 8.0 + 6.5 + 9.5) / 4 = 7.5
4. Convergence
- v1 mean: 6.0
- v2 mean: 7.5
- Delta: +1.5 (amélioration significative)
5. Verdict
- Moyenne 7.5 >= 7 : OK
- Tous scores >= 6 : OK
- completeness 6.0 < 8 ET clarity 6.5 < 8 → RESERVE