Aller au contenu

PD-262 — Retour d'experience (REX)

1. Resume executif

Metrique Valeur
Objectif initial Module anti-tampering iOS : detection jailbreak, protection Frida, lockout fail-closed, purge secrets
Resultat obtenu Conforme avec reserves (12 invariants implementes, 1 MAJEUR residuel attenue, 3 MINEURS)
Verdict final GO (Gate 8 v1 — 8.25/10)
Tests contractuels 45/45 passes (5 suites)

2. Metriques de convergence

2.1 Temps et iterations

Etape Duree estimee Duree reelle Iterations Ecart
0 - Besoin 30 min 30 min 1 0%
1 - Specification 2h 10 min 1 -92%
2 - Tests 1h 8 min 1 -87%
3 - Gate spec 1h 1h30 2 +50%
4 - Plan 1h 30 min 1 -50%
5 - Gate plan 1h 1h30 2 +50%
6 - Implementation 4h 3h 1 -25%
7 - Acceptabilite 2h 1h 1 -50%
8 - Gate acceptabilite 1h 30 min 1 -50%
9 - REX 30 min 45 min 1 +50%
TOTAL ~14h ~9.5h 12 -32%

2.2 Scores de convergence par gate

Gate Score v1 Score final Delta Iterations
Gate 3 7.44/10 9.125/10 +1.69 2
Gate 5 8.0/10 9.0/10 +1.0 2
Gate 8 8.25/10 8.25/10 0 1

2.3 Ecarts par categorie

Categorie d'ecart Gate 3 Gate 5 Gate 8 Total
ECT (completude/testabilite) 7 6 1 14
DIV (divergence spec/impl) 0 3 4 7
AMB (ambiguite) 8 8 0 16
SEC (securite) 1 0 1 2
PERF (performance) 0 0 0 0
TOTAL ecarts 16 17 6 39

3. Points fluides

Ce qui a bien fonctionne :

  • Specification riche et detaillee : La spec v1 produite par ChatGPT etait deja tres structuree (12 invariants, 19 CA, 15 scenarios, machine a etats explicite, tableau de donnees §3.3). La Gate 3 v1 a identifie des lacunes precises mais le socle etait solide.
  • Plan a 10 composants bien decouple : La decomposition en C1-C10 avec responsabilites claires a permis une implementation sequentielle fluide en 10 commits propres.
  • Gate 8 GO v1 : Pas de boucle de correction post-implementation. L'acceptabilite a identifie 4 faux positifs LLM sur 8 ecarts code review, confirmant la maturite du code.
  • Module natif Swift isole : Le bridge ObjC minimal (TamperingDetectorModule.m) et le module Swift autonome ont bien fonctionne avec le pattern Expo/RN existant.
  • Premiere story app project avec metriques : Premier benchmark pour le projet app dans le systeme de metriques.

4. Points difficiles

Obstacles rencontres :

  • Gate 3 RESERVE v1 (7.44/10) : 11 ecarts dont 1 BLOQUANT (5 TC-INV sans scenario GIVEN/WHEN/THEN) et 5 MAJEURS (frontiere purge, persistance Keychain, flag QA, corruption lockout). Le spec draft manquait de precision sur les mecanismes de persistance et de bootstrapping.
  • Gate 5 RESERVE v1 (8.0/10) : 1 BLOQUANT (device_id_pseudo necessite API native non exposee par le module T1). Le plan initial ne prevoyait pas d'export natif pour identifierForVendor, necessitant l'ajout de getDeviceIdPseudo() dans C1/C2/C5.
  • Faux positifs LLM en Gate 8 : 4/8 ecarts code review (E-01, E-02, E-04, E-06) etaient des faux positifs car le reviewer ChatGPT n'avait pas le module Swift dans son contexte. Le module natif est invisible au reviewer LLM.
  • Coverage 62.33% sous seuil 80% : Justifie par le gating __DEV__ contractuel (INV-262-07) — antiTampering.ts sort immediatement quand shouldBeActive() retourne false en Jest. Coverage effective hors gating > 80%.
  • Sonar Phase 1.5 non applicable : Projet React Native mobile sans sonar-project.properties. Derogation acceptee avec ESLint strict + tsc + Jest comme substitution.

5. Hypotheses revelees tardivement

  • Bootstrapping first_launch_clean — decouverte a l'etape 3 (Gate 3 v1, E-07/E-04). La spec ne definissait pas comment distinguer un premier lancement d'une reinstallation. Resolu par marqueur Keychain + marqueur UserDefaults volatil de session.
  • identifierForVendor est une API native-only — decouverte a l'etape 5 (Gate 5 v1, E-01). Le device_id_pseudo ne peut pas etre calcule cote TypeScript. Resolu par ajout de getDeviceIdPseudo() au module natif.
  • Reconstruction d'etat vs transition — decouverte a l'etape 5 (Gate 5 v1, E-02). Le boot apres lockout reconstruit l'etat LOCKED_PERSISTENT sans passer par TAMPERED_SESSION, ce que la spec interdisait formellement. Resolu par distinction explicite entre reconstruction boot et transition en session.

6. Invariants complexes

  • INV-262-02 (native-authority) — TC-INV-02, TC-NEG-03. L'autorite de decision doit rester native Swift, mais les tests adversariaux ne sont significatifs que sur device reel (le mock JS remplace le natif en CI). Limitation inherente documentee.
  • INV-262-09 (terminal-state) + INV-262-12 (state-persistence) — TC-NOM-08, TC-NR-02, TC-ERR-09, TC-ERR-10. La combinaison crash mid-transition + reconstruction boot fail-closed + first_launch_clean cree un graphe de cas complexe avec 4 scenarios distincts.
  • INV-262-05 (purge-on-detect) — TC-NOM-04, TC-ERR-05, TC-ERR-11. La frontiere entre "caches crypto purges" et "blobs chiffres conserves" a necessite 2 corrections de spec (Gate 3 E-03, definition glossaire).

7. Dette technique

  • purgeTempFiles est un STUB no-op — impact: faible. Trace vers PD-283. Les artefacts temporaires dechiffres restent potentiellement recuperables sur device compromis. Attenuation : lockout actif + artefacts chiffres en transit.
  • Purge tokens session/refresh incomplete — impact: faible. Scope PD-99. Tokens inutilisables post-lockout car navigation bloquee.
  • Tests adversariaux TC-INV-02/TC-NEG-03 non significatifs en CI — impact: moyen. En test unitaire avec mock, le test valide le mock, pas la resistance native. Necessite tests d'integration sur device reel.
  • Coverage sous 80% — impact: faible. Design contractuel (gating __DEV__). Coverage effective hors gating depasse 80%.

8. Risques residuels

Risque Type Probabilite Impact Mitigation
Faux positif sur device non compromis (path existant) tech faible eleve Fail-closed by design, DETECTOR_ERROR distinct
Fenetre memoire entre detection et zeroize() tech moyen moyen Secrets critiques en Keychain natif, pas en JS
Contournement lockout par suppression Keychain ops faible moyen Absence lockout sans first_launch_clean = fail-closed
Module natif non auditable par LLM ops certain faible Review manuelle Swift obligatoire pre-production

8bis. Matrice de delegation inter-PD

Story Direction Statut Nature de la dependance Probleme rencontre
PD-98 <- depend de DONE keychainStorage.deleteMasterKey() utilise par purge service RAS
PD-107 <- depend de DONE biometricKeychain.deleteBiometricSecret() utilise par purge service RAS
PD-174 <- depend de DONE Learnings injectes (hook JS bypass, AppState patterns) RAS
PD-99 <- depend de DONE (partiel) useAuthStore.clearTokens() — purge tokens incomplete Scope PD-99, tokens inutilisables post-lockout
PD-283 -> bloque TODO Endpoint backend audit ANTI_TAMPERING_LOCKOUT STUB no-op, a creer dans backlog backend

8ter. Bugs de tests

Pattern incorrect Pattern correct Cause Cout
require('react-native').NativeModules expo-modules-core requireNativeModule CC-262-T2 exige pattern Expo 15 min
Mock signature incompatible avec types Mock alignee sur TamperingResult type Refactoring types post-bridge 10 min

8quater. Corrections post-Gate 8

Aucune correction post-Gate 8 necessaire. Gate 8 GO v1.

9. Patterns recurrents detectes

9.1 Patterns confirmes (deja vus dans d'autres stories)

  • Machine a etats explicite avec transitions autorisees/interdites — aussi dans PD-82, PD-250, PD-264, PD-251, PD-279, PD-280, PD-282, PD-265 (19 occurrences precedentes, 20eme avec PD-262)
  • Stubs inter-PD acceptes en Gate 8 si documentes avec story destination — aussi dans PD-63, PD-82, PD-250, PD-251, PD-282 (14 occurrences precedentes). PD-262 : STUB PD-283 accepte.
  • Faux positifs LLM systematiques en reviews — aussi dans PD-251, PD-276, PD-277, PD-281 (18 occurrences precedentes). PD-262 : 4/8 faux positifs car module Swift non visible au reviewer.
  • Format non contractualise dans spec v1 bloque en Gate 3 — aussi dans PD-32, PD-250, PD-264 (20 occurrences precedentes). PD-262 : frontiere purge, persistance Keychain, flag QA non contractualises.
  • Guard de securite fail-closed obligatoire — aussi dans PD-238, PD-240, PD-250, PD-282, PD-265 (13 occurrences precedentes). PD-262 : fail-closed central a toute la story.

9.2 Nouveaux patterns identifies

  • Module natif invisible au reviewer LLM (faux positifs structurels) — Les reviews LLM ne recoivent que le code TypeScript. Le module natif Swift/ObjC est hors contexte, generant des faux positifs sur les invariants d'autorite native (INV-262-02), de gating (INV-262-07) et de persistance (INV-262-12). A surveiller pour toute story avec composant natif.
  • Coverage sous seuil justifiee par gating contractuel (__DEV__ / shouldBeActive()) — Le gating environnement fait que des branches entieres sont inatteignables en test. La coverage globale est trompeuse. A formaliser comme derogation type dans le processus.
  • Bootstrapping circulaire (first_launch_clean) — Detecter le premier lancement vs une reinstallation necessite un marqueur qui doit exister avant le premier controle. Ce pattern de bootstrapping circulaire revient dans tout module de persistance stateful iOS.
  • Reconstruction d'etat au boot vs transition en session — La machine a etats a deux modes : transitions (en session) et reconstruction (au boot). La spec doit distinguer explicitement les deux pour eviter les ambiguites sur les transitions "interdites" qui sont en fait des initialisations.

10. Ameliorations du workflow

10.1 Ameliorations des prompts/templates

Fichier Amelioration suggeree Priorite
templates/prompts/7a Review Code.md Injecter les fichiers natifs Swift/ObjC dans le contexte pour projets mobile avec module natif haute
templates/prompts/7b Review Tests.md Injecter les fichiers .test.ts dans le prompt pour eviter reviews aveugles haute
templates/prompts/1 Specification.md Ajouter section obligatoire "Persistance et bootstrapping" pour stories avec etat local iOS moyenne
templates/prompts/1 Specification.md Distinguer "transitions en session" vs "reconstruction au boot" dans le template machine a etats moyenne
templates/prompts/8 Revue Acceptabilite.md Ajouter flag project_type: mobile-native pour adapter les criteres (coverage gating, Sonar) moyenne

10.2 Ameliorations des agents

Agent Amelioration suggeree Justification
config/agents step 7 Injecter project_type: mobile-native avec liste des fichiers natifs dans le system prompt 4/8 faux positifs dus au module Swift invisible
config/agents step 6 Pour stories mobile avec module natif, generer le Swift et le bridge AVANT les services TS Le bridge TS depend du module natif, pas l'inverse

10.3 Ameliorations du processus

  • Derogation Sonar formalisee pour projets React Native : Projet mobile sans sonar-project.properties — formaliser ESLint strict + tsc + Jest comme substitution acceptee.
  • Seuil coverage adaptable par type de projet : 80% global est inadapte quand le gating __DEV__ rend des branches inatteignables. Proposer coverage effective (hors gating) comme metrique alternative.

11. Enseignements cles

  1. Les modules natifs sont des angles morts LLM — Les reviewers LLM ne voient que le code TypeScript. Pour les stories avec composant natif Swift/ObjC, injecter explicitement les fichiers natifs dans le contexte de review ou accepter les faux positifs comme structurels.

  2. Le bootstrapping d'etat local iOS cree des circularites — Distinguer premier lancement, mise a jour et reinstallation necessite un marqueur qui doit exister avant le premier controle. Contractualiser le mecanisme de bootstrapping des l'etape 1 (spec).

  3. Gate 3 RESERVE + corrections enrichissantes = Gate 8 GO v1 — Les 11 ecarts Gate 3 ont force une spec v2 beaucoup plus precise (persistance Keychain, first_launch_clean, flag compile, frontiere purge). Le rebond RESERVE -> GO est un indicateur de qualite du processus de confrontation.

  4. Reconstruction d'etat vs transition sont deux concepts distincts — Une machine a etats iOS a deux modes : transitions (regles de session) et reconstruction (initialisation au boot depuis persistance). La spec doit les separer pour eviter les ambiguites.

  5. La coverage globale est trompeuse avec gating contractuel — Quand le design contractuel rend des branches inatteignables en test (shouldBeActive() retourne false en Jest), la coverage globale est un indicateur trompeur. Utiliser la coverage effective hors gating.

12. Metriques cumulatives (auto-calculees)

Metrique Cette story Moyenne projet Tendance
Temps total 9.5h 6.46h n/a (1ere story app)
Iterations gates 5 5.32 ->
Ecarts totaux 39 23.2 n/a (1ere story app)
Score convergence moyen 8.79/10 8.47/10 n/a (1ere story app)