Aller au contenu

PD-172 — Review de spécification (audit indépendant) — v2

Itération : v2 (post-correction v1 NON_CONFORME score 5.25) Documents audités : - PD-172-specification.md v2 (contractuel, fournie en entrée) - PD-172-tests.md v1 (matrice de couverture + scénarios + §9 règles non testables) Périmètre : conformité contractuelle, testabilité, cohérence Spec ↔ Tests, sécurité/conformité. Hors périmètre : qualité d'implémentation, choix d'algorithme Redis, couverture totale tests.


0. Synthèse exécutive

Indicateur v1 v2
Bloquants 4 1
Majeurs 13 11
Mineurs 11 7
Total écarts 28 19
Verdict de testabilité (vu auditeur) Partiellement testable, contrat insuffisamment fermé Globalement testable, défaut majeur de synchronisation Spec ↔ Tests

Progrès v1 → v2 : - §5.2 désormais entièrement borné (valeurs burst/sustained chiffrées, redis_timeout_unavailable_ms, key_ttl_max_seconds, redis_memory_budget_mb_db2, etc.). - §5.3 SLA temporels intégralement fournis (TTL burst=15s, sustained=65s, degraded_clearing_cycles=3). - Q-172-01 à 06 tranchées (cf. §10.2). - Définition formelle Redis indisponible (§3) : 3 conditions explicites. - INV-172-10 contractualise l'atomicité Lua (1 EVALSHA). - INV-172-11/12 tranchent RGPD : HMAC dans Redis, IP brute en logs 7j. - §5bis ajoute 3 diagrammes Mermaid (état requête, état système, séquence).

Points sensibles persistants : - Le document de tests v1 n'a pas été régénéré après mise à jour de la spec V2. §9 du doc tests classe encore comme « Bloquant / Non testable » des éléments désormais tranchés (8 entrées obsolètes). Cause racine dominante de l'écart de testabilité résiduel. - Définitions circulaires de « Endpoint sensible » et « fail-open contrôlé ». - Une contradiction RGPD interne (INV-172-12 vs §5.2 borne raw_ip_log_retention_days). - Plusieurs invariants critiques (RGPD, garde-fou tenant, profil santé) absents de la matrice de couverture §2 du doc tests.


1. Ambiguïtés

A-01

Type        : Ambiguïté
Référence   : §3 Définitions — termes « Endpoint sensible », « Endpoint coûteux »
Description : « Endpoint sensible : Endpoint avec protection plus restrictive que le profil générique » est circulaire — un endpoint est sensible parce qu'il est traité plus strictement, et inversement. Aucune liste fermée n'est rattachée à la définition. La table §5.2 « Profils contractuels » impose des seuils par profil mais ne précise pas le critère qui détermine l'appartenance d'une nouvelle route à `auth/costly/read_standard`. Idem pour « Endpoint coûteux ».
Impact      : INV-172-04 (« endpoints sensibles plus restrictifs sur au moins une fenêtre OU une dimension ») n'est pas testable globalement : impossible de garantir qu'un futur endpoint sera correctement classé. CA-172-03 et TC-NOM-03 reposent sur l'idée d'une classification stable mais non spécifiée.
Gravité     : Majeur

A-02

Type        : Ambiguïté
Référence   : §3 Définitions « fail-open » + §5.4 transition `BYPASS_DEGRADED` + §5.7 réconciliation
Description : Le qualificatif « contrôlé » apparaît plusieurs fois (§5.4, §5.7, §6 ERR-172-08 « dégradation contrôlée ») sans définition opérationnelle. La définition §3 de `fail-open` est binaire (autorisée). Aucun observable secondaire n'est attaché : limite locale en mémoire ? quota dégradé ? throttling proportionnel ? Le contrat se limite à « bypass », ce qui rend le « contrôlé » purement décoratif.
Impact      : TC-NOM-09 et TC-ERR-08 testent la décision binaire mais ne peuvent pas vérifier la dimension « contrôlée ». Si l'implémentation se contente d'autoriser tout, le test passe.
Gravité     : Majeur

A-03

Type        : Ambiguïté
Référence   : §3 Définitions « Redis indisponible » — condition « circuit-breaker local en état OPEN »
Description : Le circuit-breaker est mentionné comme déclencheur de l'état dégradé mais sa configuration (seuil de défaillances, fenêtre de comptage, durée d'OPEN, transition HALF_OPEN) n'est pas spécifiée. Sans paramétrage, deux implémentations conformes peuvent diverger fortement (ex : déclenchement après 1 erreur vs 50).
Impact      : INV-172-01 (cohérence inter-instance) peut être violée si chaque instance a son propre paramétrage breaker non synchronisé. Tests TC-NOM-09/10/11 et TC-NEG-08 supposent un déclenchement implicite.
Gravité     : Majeur

A-04

Type        : Ambiguïté
Référence   : §10.3 Q-172-04 « Liste exhaustive des routes read métier »
Description : Q-172-04 classée « impact : couverture fonctionnelle à finaliser côté PO » (donc non bloquant). Or sans cette liste, le profil `read_standard` ne peut être appliqué de manière déterministe ; toute route non profilée fait défaut. Le contrat §5.2 ne définit pas le profil par défaut appliqué à une route non listée.
Impact      : ERR-172-05 (« Profil de limite manquant/invalide au boot ») — une route sans profil déclenche-t-elle un refus de démarrage ? Ou bénéficie-t-elle d'un profil par défaut ? Comportement non contractualisé. CA-172-07 (matrice fail-open/fail-closed) inapplicable sur route inconnue.
Gravité     : Majeur

A-05

Type        : Ambiguïté
Référence   : §5.1 « identifier_raw » + INV-172-11 « identifier_hmac »
Description : Le secret HMAC utilisé dans `hex(lower(HMAC-SHA256(secret, identifier_raw)))` n'est jamais spécifié : taille minimale, source (Vault ? variable d'environnement ?), rotation, comportement en cas de rotation (re-keying des compteurs ou perte d'historique ?). En cas de compromission du secret, l'énumération `identifier_raw` est triviale (256 IPs IPv4 = ~4 milliards précomputables).
Impact      : INV-172-11 (« Redis NE DOIT PAS contenir d'IP brute ») devient une protection théorique si le secret est faible/statique. Risque sécurité non documenté.
Gravité     : Majeur

A-06

Type        : Ambiguïté
Référence   : §5.5 « Émission log structuré : Async immédiat » + INV-172-03
Description : « Async immédiat » est un oxymore : soit l'émission est synchrone et bloquante, soit asynchrone et fire-and-forget. Aucun mécanisme de retry, buffer borné, ou drop-policy n'est spécifié. Sans contrat de garantie at-least-once, INV-172-03 (« DOIT produire un événement observable ») peut échouer silencieusement sous charge ou en cas de saturation du backend de logs.
Impact      : Couplage faible avec INV-172-03 : rien ne garantit l'observabilité revendiquée. CA-172-06 / TC-NOM-07 ne peuvent pas vérifier l'absence de pertes en charge.
Gravité     : Mineur

A-07

Type        : Ambiguïté
Référence   : §5.2 « Garde-fou global tenant » — `route_key="__global__"`
Description : Le marqueur `__global__` n'est pas défini dans la table §5.1 (regex `route_key` exige `^[A-Za-z0-9_-]{1,344}$`, ce qui accepte `__global__` mais le sens — sentinelle réservée — n'est pas formalisé). Risque de collision si un client construit une route normalisée valant `__global__` après base64url.
Impact      : INV-172-01 et CA-172-15 dépendent de la sentinelle. Pas de risque exploit majeur (base64url n'émet pas `__global__` à partir d'une URL classique), mais ambiguïté de spécification.
Gravité     : Mineur

2. Contradictions

C-01

Type        : Contradiction
Référence   : INV-172-12 vs §5.2 ligne `raw_ip_log_retention_days`
Description : INV-172-12 affirme « rétention maximale 7 jours » pour client_ip_raw. La table §5.2 fixe `raw_ip_log_retention_days = 7` avec un max admis de 30. La borne max de 30 contredit explicitement l'invariant qui plafonne à 7. Si un opérateur configure 30, le système est conforme §5.2 mais viole INV-172-12 (donc Article RGPD).
Impact      : Risque de configuration non conforme RGPD validée par la couche de validation au boot. CA-172-12 / H-172-03 dépendent du plafond strict 7j.
Gravité     : Bloquant

C-02

Type        : Contradiction Spec ↔ Tests (massive)
Référence   : `PD-172-tests.md` §9 « Règles non testables » vs `PD-172-specification.md` v2 §5.2 / §5.3 / §6 / §10.2
Description : Le document de tests classe encore comme « Bloquant » ou « Majeur — non testable » 8 éléments désormais tranchés en spec V2 :
  - « Valeurs exactes burst.max_requests » → §5.2 fournit `5/3/30/2000`
  - « Valeurs exactes burst.window_seconds » → §5.2 fournit `10s` partout
  - « Valeurs exactes sustained.max_requests » → §5.2 fournit `20/10/120/10000`
  - « Valeurs exactes sustained.window_seconds » → §5.2 fournit `60s`
  - « burst_window_ttl / sustained_window_ttl » → §5.3 fournit `15s / 65s`
  - « degraded_clearing_cycles » → §5.3 fournit `3`
  - « Code HTTP exact fail-closed » → §6 ERR-172-02 fixe `503` ; INV-172-05 confirme
  - « Format final identifier (brut vs pseudonymisé) » → INV-172-11 + §5.1 trancent (HMAC en Redis, IP brute en logs)
  - « Politique santé/monitoring vs no-whitelist » → INV-172-13 tranche explicitement (« profil dédié, PAS une whitelist »)
Impact      : Le verdict QA §10 du document tests (« Testable partiellement avec réserves ») est obsolète. Le document tests doit être régénéré sur la base de la spec V2 avant Gate 3, sinon une boucle de correction inutile sera déclenchée. Ne reflète pas la maturité réelle du contrat.
Gravité     : Bloquant

C-03

Type        : Contradiction Spec ↔ Tests
Référence   : §5.1 ligne `identifier_raw` (max 256 chars) vs `PD-172-tests.md` TC-NEG-03
Description : §5.1 fixe la taille max de `identifier_raw` à 256 caractères avec regex spécifique par dimension. Le test TC-NEG-03 énonce : « identifier invalide (caractère interdit / >128) ». La borne 128 ne correspond à aucune valeur de la spec.
Impact      : TC-NEG-03 vérifie une limite incorrecte. Faux positif/négatif possible : un identifier de 200 chars sera rejeté côté implémentation conforme spec mais accepté côté test attendant 128.
Gravité     : Majeur

C-04

Type        : Contradiction interne (normative)
Référence   : §5.5 « Crash post-décision / pré-observabilité : incident d'exploitation (non-conformité INV-172-03) » vs INV-172-03 « Tout refus DOIT produire un événement observable »
Description : §5.5 reconnaît qu'un crash entre la décision et l'émission observable produit une violation de INV-172-03. Or INV-172-03 est listé comme invariant non négociable. Le contrat ne peut pas à la fois (a) déclarer l'invariant inviolable et (b) prévoir explicitement des cas de violation tolérés.
Impact      : Contradiction normative qui fragilise tous les tests d'observabilité (TC-NOM-07, TC-NR-07). Ouvre la porte à un trou d'audit en exploitation. Soit l'invariant doit être assoupli (« best-effort ») soit la spec doit imposer un mécanisme de durabilité (write-ahead log, queue persistante).
Gravité     : Majeur

C-05

Type        : Contradiction
Référence   : INV-172-04 « au moins une fenêtre OU une dimension » vs CA-172-03 (seuils chiffrés)
Description : INV-172-04 autorise un endpoint sensible à différer du générique sur une fenêtre OU une dimension. Le « OU » permet théoriquement un profil sensible identique en seuils sur burst+sustained mais variant uniquement sur la liste des dimensions évaluées. Or les profils §5.2 ont tous le même set de dimensions (`ip,user_id,tenant,route`). Donc en pratique, la seule différenciation possible est par seuil — le « OU dimension » est inopérant.
Impact      : Mécanisme contractuel partiellement vide. Risque d'interprétation divergente entre implémenteurs.
Gravité     : Mineur

C-06

Type        : Contradiction
Référence   : §5.2 ligne `dimensions_count_v1` (min=max=4) vs §5.2 « Garde-fou global tenant » (1 seule dimension `tenant`)
Description : `dimensions_count_v1 = 4 (min=4, max=4)` impose strictement 4 dimensions. Mais le garde-fou tenant n'évalue qu'une dimension. Soit `dimensions_count_v1` ne s'applique qu'aux profils de routes (à préciser), soit le garde-fou viole le contrat numérique.
Impact      : Ambiguïté de validation au boot (ERR-172-05). Test TC-ERR-05 ne peut pas trancher si « 1 dimension » sur tenant global est conforme ou rejeté.
Gravité     : Mineur

3. Règles non testables / Incohérences testabilité Spec ↔ Tests

NT-01

Type        : Incohérence Spec↔Tests
Référence   : INV-172-11 + CA-172-11 vs `PD-172-tests.md` §2 matrice de couverture
Description : INV-172-11 (« Redis ne contient pas d'identifiants bruts ») et CA-172-11 (« Redis ne stocke que des identifiants pseudonymisés HMAC ») n'apparaissent pas dans la matrice de couverture §2 du document tests. ST-172-12 dans la spec décrit le test attendu (« inspection clés Redis → identifiants uniquement en HMAC ») mais aucun TC-NOM correspondant n'a été produit dans le doc tests v1.
Impact      : Invariant RGPD critique sans test dédié. Risque de régression silencieuse. Couverture incomplète Gate 8.
Gravité     : Majeur

NT-02

Type        : Incohérence Spec↔Tests
Référence   : INV-172-12 + CA-172-12 vs `PD-172-tests.md` §2
Description : Rétention IP brute (7 jours) absente de la matrice et sans TC dédié. ST-172-12 ne couvre pas la rétention. Aucun test ne vérifie que la purge effective des logs après 7 jours.
Impact      : Conformité RGPD non vérifiable. H-172-03 (purge 7j) sans observable.
Gravité     : Majeur

NT-03

Type        : Incohérence Spec↔Tests
Référence   : INV-172-13 + CA-172-13 + ST-172-13 vs `PD-172-tests.md` §2
Description : Profil santé/monitoring (10000 req/min) sans entrée dans la matrice §2. ST-172-13 défini en spec mais aucun TC-NOM correspondant.
Impact      : Risque de basculer la santé sous le seuil par défaut, bloquant les sondes Kubernetes/load balancer en cas de bug de classification.
Gravité     : Majeur

NT-04

Type        : Incohérence Spec↔Tests
Référence   : INV-172-14 + CA-172-14 + ST-172-15 vs `PD-172-tests.md` §2
Description : Budget mémoire 256MB et TTL max 3600s mentionnés en spec, ST-172-15 décrit le test (« budget > 256MB → circuit-breaker OPEN »), mais matrice §2 ne couvre que partiellement via TC-ERR-08 (« saturation cardinalité » sans seuil chiffré). Pas de vérification du TTL max.
Impact      : INV-172-14 partiellement testé. Risque DoS mémoire non encadré.
Gravité     : Majeur

NT-05

Type        : Incohérence Spec↔Tests
Référence   : CA-172-15 + ST-172-14 vs `PD-172-tests.md` §2
Description : Garde-fou global tenant (500 req/min sur dimension tenant, sentinelle `__global__`) défini en spec, ST-172-14 décrit le test (« total > 500 req/min throttling tenant global »), mais aucun TC-NOM correspondant dans la matrice ni dans la liste §3 du doc tests.
Impact      : Mécanisme transverse de protection tenant non vérifié. Risque d'amplification cross-routes.
Gravité     : Majeur

NT-06

Type        : Règle non testable (limite Redis)
Référence   : §5.2 `redis_memory_budget_mb_db2 = 256 MB` + INV-172-14 + ST-172-15
Description : Redis ne segmente PAS la mémoire par DB index. La commande `INFO MEMORY` retourne la mémoire totale du serveur Redis ; il n'existe pas de mesure native par DB. La mesure du budget « 256 MB sur db=2 » nécessite estimation indirecte (cardinalité × taille moyenne d'entrée), donc approximation. Aucun protocole de mesure n'est spécifié.
Impact      : INV-172-14 partiellement vérifiable. CA-172-14 et ST-172-15 dépendent d'une métrique non native. Risque d'interprétations divergentes ou alarme tardive.
Gravité     : Majeur

NT-07

Type        : Incohérence Spec↔Tests
Référence   : §5.4 bis Machine d'états système (RECOVERING → HEALTHY) + ST-172-16 vs `PD-172-tests.md`
Description : ST-172-16 (« 3 sondes successives réussies → RECOVERING → HEALTHY ») défini en spec mais aucun TC-NOM correspondant. La machine d'états système est un mécanisme inter-requêtes critique pour la sortie de mode dégradé ; sans test, le retour à HEALTHY peut rester bloqué silencieusement (système figé en DEGRADED).
Impact      : Disponibilité du sous-système non vérifiée. Risque opérationnel : restauration de Redis non détectée.
Gravité     : Majeur

NT-08

Type        : Règle non testable
Référence   : §5.5 « Émission log : Async immédiat » + INV-172-03
Description : Sans contrat de durabilité ou métrique de drop-rate sur le canal d'émission log/métrique, l'absence de pertes en charge ne peut pas être prouvée. TC-NOM-07 vérifie qu'un refus produit une trace, mais ne peut pas mesurer la perte sous saturation.
Impact      : INV-172-03 réputé respecté tant que les tests passent à charge nominale, sans garantie en pic.
Gravité     : Mineur

NT-09

Type        : Règle non testable (vérification documentaire)
Référence   : INV-172-09 + TC-INV-09 (`PD-172-tests.md`)
Description : INV-172-09 impose §5.1 comme source de vérité unique. TC-INV-09 propose une « vérification de cohérence comparant tous formats/enums/regex utilisés ». Cette vérification est fondamentalement statique/documentaire (comparaison de schémas) et ne peut pas être un test runtime déterministe au sens habituel.
Impact      : Conformité contrôlée par revue manuelle ou linting de schéma, à intégrer dans CI mais non couvert par scénario classique.
Gravité     : Mineur

4. Hypothèses dangereuses

H-01

Type        : Hypothèse dangereuse
Référence   : H-172-01 « Normalisation des templates de route NestJS est déterministe »
Description : Hypothèse externalisée sur le framework. Si NestJS change de version, ou si un middleware réordonne les paramètres dynamiques, le `route_key` peut diverger entre instances ayant chargé des modules dans un ordre différent. Aucun test au boot ne valide la stabilité de la normalisation.
Impact      : Violation silencieuse de INV-172-01 (cohérence inter-instance). Détection uniquement par observation a posteriori d'un quota incohérent.
Gravité     : Majeur

H-02

Type        : Hypothèse dangereuse
Référence   : §3 Définitions « Redis indisponible » + condition « circuit-breaker local en état OPEN »
Description : Le breaker est local à chaque instance. Implicitement, chaque instance peut entrer en `DEGRADED` à un instant différent. Les profils fail-open/fail-closed s'appliquent localement. En cas de partition réseau partielle (instance A voit Redis, instance B non), un même client peut recevoir des décisions divergentes selon l'instance routée.
Impact      : INV-172-01 (cohérence inter-instance) violée par construction en mode dégradé. Le contrat ne précise pas si cette divergence est acceptée.
Gravité     : Majeur

H-03

Type        : Hypothèse dangereuse
Référence   : §5.2 / §5.3 — algorithme de fenêtre non spécifié (fixed vs sliding)
Description : La spec impose des compteurs `burst` / `sustained` avec TTL = window_seconds + padding (§5.3). Cette construction suggère des fenêtres fixes (pattern `INCR + EXPIRE`). Or les tests TC-NOM-05 et TC-NOM-06 supposent une comptabilisation déterministe sans préciser le comportement aux frontières de fenêtre. Avec fenêtres fixes, un attaquant peut envoyer 2× le seuil à cheval sur deux fenêtres consécutives (boundary attack).
Impact      : Attaque de débordement de fenêtre non couverte. Risque sécurité matériel sur `auth/login` (10 req sur 2s au lieu de 5/10s effectif perçu).
Gravité     : Majeur

H-04

Type        : Hypothèse dangereuse
Référence   : Implicite — synchronisation horloge entre instances backend
Description : TC-NOM-12 (P99 ≤ 5ms) et la mécanique de fenêtres dépendent d'une horloge cohérente. La spec ne spécifie aucun SLA NTP / clock skew max entre instances. Une dérive de quelques secondes peut amplifier les attaques de boundary (H-03).
Impact      : INV-172-01 partiellement violée. Mesure P99 (CA-172-08) potentiellement inexacte si les horloges divergent.
Gravité     : Mineur

H-05

Type        : Hypothèse dangereuse
Référence   : Q-172-11 « Stratégie proxy trust multi-environnements » classée résiduelle
Description : Sans politique de trust X-Forwarded-For documentée, la résolution `client_ip` peut accepter une IP forgée par le client final si la chaîne proxy a une étape mal configurée. ERR-172-07 prévoit un rejet 400, mais sans liste de proxies de confiance ni saut acceptable, le mécanisme est défensif uniquement quand la chaîne est manifestement ambiguë.
Impact      : Risque de spoofing IP → contournement quota par dimension `ip`. Sécurité dégradée en frontaux mal configurés.
Gravité     : Majeur

5. Cohérence des diagrammes (§5bis)

D-01

Type        : Cohérence diagramme — état requête
Référence   : §5bis stateDiagram-v2 « état requête »
Description : Diagramme cohérent avec §5.4 : 5 transitions sortantes depuis RECEIVED, 5 états terminaux. Aucune transition supplémentaire ni manquante. Conditions affichées en label correspondent aux règles §5.4.
Impact      : Aucun écart.
Gravité     : OK

D-02

Type        : Cohérence diagramme — état système
Référence   : §5bis stateDiagram-v2 « état système »
Description : Diagramme cohérent avec §5.4bis : HEALTHY → DEGRADED → RECOVERING → HEALTHY (avec retour vers DEGRADED en cas d'échec sonde). Pas de transition directe HEALTHY → RECOVERING (cohérent). Pas de label numérique sur le « N succès consécutifs » mais §5.3 précise `degraded_clearing_cycles=3`.
Impact      : Aucun écart bloquant. Le diagramme pourrait gagner à mentionner explicitement N=3 pour cohérence visuelle.
Gravité     : OK (suggestion mineure)

D-03

Type        : Cohérence diagramme — séquence
Référence   : §5bis sequenceDiagram
Description : Diagramme cohérent avec §5.5 (1 EVALSHA par requête, retour multi-clé). Mais :
  (a) le format/structure du retour Lua « {decision, remaining, retry_after, system_state} » n'est pas spécifié (JSON ? table Redis ? ARRAY ?). Aucune ligne dans §5.1 ne contractualise ce format.
  (b) la branche `REJECTED_INVALID_CONTEXT` (5e état terminal §5.4) est absente du diagramme — le `alt` ne couvre que 4 cas. Incohérent avec §5.4.
  (c) la normalisation route + identifier_hmac est représentée comme étapes locales API mais sans préciser quand la validation §5.1 est appliquée (avant ou après EVALSHA ?).
Impact      : (a) ambiguïté contrat de retour Lua — risque de divergence implémentation. (b) incohérence formelle avec §5.4. (c) ordre de validation impacte l'observabilité (REJECTED_INVALID_CONTEXT doit-il quand même appeler Redis ?).
Gravité     : Majeur

6. Risques sécurité / conformité

S-01

Type        : Risque sécurité / conformité
Référence   : INV-172-12 + §5.1 « client_ip_raw en logs sécurité »
Description : Logs sécurité autorisés à contenir `client_ip_raw`. Aucune indication sur : (a) le système de log destinataire (fichier local ? SIEM ? Loki ?), (b) le mécanisme de purge automatique à 7 jours (rotation logrotate ? politique de rétention SIEM ?), (c) le contrôle d'accès opérationnel (« SOC/SRE » mentionné en note C-03 mais sans IAM concret), (d) le format de log structuré (champ JSON dédié ? noyé dans le message ?).
Impact      : Conformité RGPD non garantie en exploitation. Risque de fuite IP au-delà de 7 jours si purge non implémentée. INV-172-12 dépend d'un mécanisme externe non spécifié.
Gravité     : Majeur

S-02

Type        : Risque sécurité
Référence   : §5.2 profils + algorithme implicite fixed window (cf. H-03)
Description : Si fenêtres fixes, attaque de débordement à la frontière : 5 req à t=9.9s + 5 req à t=10.1s = 10 req en 200 ms tout en respectant `5/10s` sur chaque fenêtre. Particulièrement critique sur `/auth/login` (bruteforce). Aucun mécanisme de sliding window ou de token bucket mentionné.
Impact      : Protection bruteforce auth dégradée par construction. Justification d'une éventuelle revue d'algorithme.
Gravité     : Majeur

S-03

Type        : Risque opérationnel
Référence   : INV-172-07 « Aucun mécanisme de whitelist/bypass autorisé en V1 »
Description : Pas de procédure d'urgence documentée pour exonérer un client critique faussement bloqué (ex : client institutionnel coincé sur `/auth/login` après bug de password manager). En production, l'absence totale de bypass exclut toute intervention SRE rapide ; le seul recours est de désactiver le rate-limit globalement (impact sécurité majeur) ou redéployer avec config modifiée (latence d'intervention élevée).
Impact      : Risque de SLA non tenu sur incident client. Trade-off sécurité/disponibilité non explicité dans la spec.
Gravité     : Mineur

S-04

Type        : Risque sécurité (audit fail-closed)
Référence   : §5.5 + INV-172-03 (cf. C-04)
Description : Crash post-décision pré-observabilité = trou d'audit reconnu. Sur un endpoint `auth`, une suite de refus non tracés masque potentiellement un bruteforce en cours.
Impact      : Détection d'attaque retardée. Conformité audit (Articles III, IV CONSTITUTIONAL) compromise sur cas limite.
Gravité     : Majeur

7. Récapitulatif par gravité

Gravité ID Sujet
Bloquant C-01 INV-172-12 (rétention 7j) vs §5.2 (max 30j) — contradiction RGPD
Bloquant C-02 Document tests v1 obsolète vs spec V2 — 8 entrées §9 incorrectes
Majeur A-01 « Endpoint sensible » définition circulaire
Majeur A-02 « fail-open contrôlé » sans définition opérationnelle
Majeur A-03 Circuit-breaker non paramétré
Majeur A-04 Liste routes read (Q-172-04) — impact profil par défaut non spécifié
Majeur A-05 Secret HMAC : gestion/rotation/source non spécifiées
Majeur C-03 TC-NEG-03 borne 128 chars vs §5.1 (256)
Majeur C-04 INV-172-03 inviolable vs §5.5 cas de violation tolérés
Majeur NT-01 INV-172-11 (HMAC) absent matrice tests
Majeur NT-02 INV-172-12 (rétention IP) sans test
Majeur NT-03 INV-172-13 (profil santé) sans TC-NOM
Majeur NT-04 INV-172-14 (budget mémoire/TTL) partiellement testé
Majeur NT-05 CA-172-15 (garde-fou tenant) sans TC-NOM
Majeur NT-06 Mesure budget 256MB sur db=2 — Redis non segmenté
Majeur NT-07 ST-172-16 (RECOVERING → HEALTHY) sans TC-NOM
Majeur H-01 Normalisation route NestJS — pas de validation au boot
Majeur H-02 Breaker local — divergence inter-instances en partition
Majeur H-03 Fenêtre fixe vs sliding non spécifié — boundary attack
Majeur H-05 Trust proxy non documenté — spoofing IP
Majeur D-03 Diagramme séquence : format Lua + branche REJECTED manquante
Majeur S-01 client_ip_raw : système log/purge/IAM non spécifiés
Majeur S-02 Bruteforce frontière de fenêtre
Majeur S-04 Trou d'audit fail-closed sur crash
Mineur A-06 « Async immédiat » — pas de garantie at-least-once
Mineur A-07 Sentinelle __global__ non formalisée
Mineur C-05 INV-172-04 « OU dimension » inopérant
Mineur C-06 dimensions_count_v1=4 vs garde-fou tenant (1 dim)
Mineur NT-08 Pas de mesure de drop-rate logs
Mineur NT-09 TC-INV-09 vérification documentaire
Mineur H-04 Synchro horloge non contractualisée
Mineur S-03 Pas de procédure SRE bypass d'urgence

8. Conclusion auditeur

La spécification V2 a comblé l'essentiel des manques bloquants de la v1 (paramètres chiffrés, atomicité Lua, RGPD tranché, diagrammes ajoutés). Le contrat est désormais globalement testable.

Deux blocages persistent :

  1. C-01 : contradiction RGPD interne (raw_ip_log_retention_days accepte 30j alors que INV-172-12 plafonne à 7j). Borne max=7 à corriger en §5.2.
  2. C-02 : le document de tests v1 n'a pas été régénéré. Les 8 entrées de §9 « non testables » sont obsolètes. Sans régénération du doc tests sur la base de la spec V2, le scoring testabilité Gate 3 sera artificiellement bas et la couverture matrice §2 restera trouée (NT-01 à NT-05, NT-07).

Recommandation auditeur : - Corriger C-01 dans la spec (1 ligne). - Régénérer le document de tests v2 pour résorber C-02 et NT-01..NT-05/07 simultanément. - Trancher A-04 (Q-172-04) : soit fournir la liste exhaustive read, soit définir le profil par défaut et son comportement au boot. - Documenter la gestion du secret HMAC (A-05) comme dépendance Vault explicite.

Les écarts Majeurs restants (algorithme de fenêtre, breaker local, trust proxy, observabilité durabilité) relèvent d'arbitrages techniques qui peuvent être documentés sans remettre en cause le contrat fonctionnel — mais ils doivent l'être avant Gate 5 (plan d'implémentation).