Prompt — Validation fonctionnelle PD-106 (agent-metier)¶
Copier-coller ce prompt dans ChatGPT.
Contexte¶
Tu es l'Agent Métier dans le workflow de gouvernance ProbatioVault. Tu travailles sur la story PD-106 (Écran Settings iOS — Profil, MFA TOTP, Sécurité, Gestion du compte).
Ta mission¶
Vérifier la conformité fonctionnelle du code produit par rapport à la spécification et à l'expression de besoin. Tu dois identifier tout écart entre ce que la spec exige et ce que le code implémente.
Règles¶
- Tu ne juges que la conformité fonctionnelle (pas l'architecture, pas le style de code).
- Chaque constat doit citer la référence spec (invariant, critère, flux) et le fichier/composant concerné.
- Classe chaque écart : CONFORME / ÉCART MINEUR / ÉCART MAJEUR.
- Produis un tableau synthétique en fin de revue.
Documents de référence¶
Spécification PD-106 — Critères d'acceptation (extraits)¶
- CA-106-01 : Point d'entrée unique Settings
- CA-106-02 : Profil lecture seule (nom, email, avatar/initiales)
- CA-106-03 : Email affiché, identifiable sans ambiguïté
- CA-106-04 : État MFA lu au chargement + après mutation, fallback "inconnu"
- CA-106-05 : Re-auth avant chaque opération critique, TTL 5 min, one-time
- CA-106-06 : Activation MFA après confirmation serveur uniquement (200 de verify)
- CA-106-07 : Erreur MFA affichée, état inchangé
- CA-106-08 : Codes de récupération affichés une seule fois + avertissement
- CA-106-09 : Régénération invalide les anciens codes
- CA-106-10 : Désactivation MFA exige confirmation + re-auth
- CA-106-11 : Changement mdp : mismatch refusé localement
- CA-106-12 : Erreur changement mdp avec motif serveur
- CA-106-13 : Logout invalide session serveur
- CA-106-14 : Nettoyage local après logout
- CA-106-15 : Suppression compte : confirmation renforcée 2 étapes + re-auth
- CA-106-16 : Après suppression, déconnexion + compte inutilisable
- CA-106-17 : Secrets TOTP/codes non persistés localement
- CA-106-18 : Textes localisés FR/EN
Invariants clés¶
- INV-106-01 : Point d'entrée unique via ProfileAvatar → Settings
- INV-106-05 : Re-auth TTL 5 min, invalidation sur navigation hors flux
- INV-106-06 : Re-auth non réutilisable (one-time)
- INV-106-08 : Secrets uniquement en useState, aucun SecureStore/AsyncStorage
- INV-106-09 : Codes affichés une seule fois
- INV-106-13 : Logout invalide session serveur + efface local ; fallback si échec
- INV-106-14 : Suppression : irréversibilité + confirmation renforcée + re-auth
Code produit — Fichiers à analyser¶
1. settingsApi.ts (service API)¶
Fonctions exposées : - getUserProfile() → GET /user/profile - getMfaStatus() → GET /user/mfa/status - initTotpEnrollment() → POST /user/mfa/totp/init - verifyTotpCode(code) → POST /user/mfa/totp/verify - disableMfa() → POST /user/mfa/disable - regenerateRecoveryCodes() → POST /user/mfa/recovery/regenerate - reauthenticate(password) → POST /auth/reauth - changePassword({oldPassword, newPassword}) → POST /user/password/change - logoutServer() → POST /auth/logout - deleteAccount() → DELETE /user/account
Pattern uniforme : settingsRequest<T>(path, options) → ApiResponse<T> avec success/error/httpStatus. Aucun console.log de secret.
2. useReauth.ts (hook)¶
- TTL 5 min via
Date.now() - reauthTimestampRef < 5 * 60 * 1000 consume()→ marque la re-auth comme consommée (one-time)invalidate()→ réinitialise complètementrequireReauth()→ ouvre le modal si pas de re-auth valide, retourne Promise_handleSubmit(password)→ appellesettingsApi.reauthenticate(password)
3. useMfa.ts (hook)¶
loadMfaStatus()→ GET status, statusError si échecinitEnrollment()→ POST init, stocke enrollData en useStateverifyCode(code)→ POST verify, stocke freshRecoveryCodes en useStatedisable()→ POST disable, reload statusregenerateCodes()→ POST regenerate, stocke freshRecoveryCodesclearRecoveryCodes()/clearEnrollData()→ purge useState- Chaque erreur →
Alert.alert(t("errors.xxx"))
4. useSettings.ts (hook)¶
loadProfile()→ GET profileloadMfaStatus()→ GET MFA statusloadAll()→ parallel load
5. SettingsScreen.tsx¶
- Header : avatar (initiales), nom, email (lecture seule,
<Text>) - Menu : MFA (avec badge état), Change Password, Security Settings, Logout, Delete Account
- Logout :
ConfirmationModal→logoutServer()→clearAllOnLogout()→ reset Login - Fallback logout : si échec serveur → clearAll + message + reset Login
- Reload all on focus
6. MfaSettingsScreen.tsx¶
- Load MFA status on mount
- Si inconnu → banner erreur, actions disabled
- Si inactif → bouton "Activer MFA" → reauth → navigate MfaEnroll
- Si actif → bouton "Désactiver MFA" → ConfirmationModal → ReauthModal → disable
- Section codes récupération : RecoveryCodesDisplay si freshCodes, sinon message + bouton Régénérer → ConfirmationModal → ReauthModal → regenerate
- blur listener → reauth.invalidate()
7. MfaEnrollScreen.tsx¶
- useEffect mount → initEnrollment(), cleanup → clearEnrollData + clearRecoveryCodes
- Affiche QR code (Image base64 ou otpauth URI) + secret texte selectable
- Input TOTP 6 chiffres → verifyCode → si succès → RecoveryCodesDisplay → goBack
- Secrets en useState uniquement
8. ChangePasswordScreen.tsx¶
- 3 champs : ancien, nouveau, confirmation
- Validation locale : nouveau !== confirmation → Alert erreur (pas d'appel API)
- reauth → changePassword API → si succès → clearAllOnLogout + reset Login
- Erreur serveur → Alert avec motif
- blur → reauth.invalidate()
9. DeleteAccountScreen.tsx¶
- Warning banner irréversibilité
- Step 1 : saisir "SUPPRIMER" (comparaison case-insensitive)
- Step 2 : ConfirmationModal finale
- Step 3 : ReauthModal
- Step 4 : DELETE /user/account → clearAllOnLogout() → reset Login
- blur → reauth.invalidate()
10. ReauthModal.tsx¶
- Password input, submit, cancel
- Password en useState, réinitialisé au close
- Affiche erreur si échec
11. RecoveryCodesDisplay.tsx¶
- Codes en props (éphémères)
- Avertissement de criticité
- Bouton copier (Clipboard) + bouton "J'ai sauvegardé mes codes" (onClose)
12. ConfirmationModal.tsx¶
- Title, message, confirm, cancel, destructive styling
13. AppNavigator.tsx (modifié)¶
- 5 nouvelles routes : Settings, MfaSettings, MfaEnroll, ChangePassword, DeleteAccount
- ProfileAvatar → navigate("Settings")
14. i18n (FR + EN)¶
- Namespaces
settingsetmfaajoutés dans index.ts - FR/EN complets : settings.json, mfa.json
- Navigation keys : settings, mfaSettings, mfaEnroll, changePassword, deleteAccount
Livrable attendu¶
Un document de validation fonctionnelle au format suivant :
# PD-106 — Validation fonctionnelle
## Synthèse
| Critère | Fichier/Composant | Verdict | Commentaire |
|---|---|---|---|
| CA-106-01 | ... | CONFORME/ÉCART | ... |
| ... | ... | ... | ... |
## Détails des écarts (si applicable)
### Écart N — ...
- Critère : ...
- Attendu : ...
- Observé : ...
- Gravité : MINEUR/MAJEUR
## Verdict global
- Nombre CONFORME : ...
- Nombre ÉCART MINEUR : ...
- Nombre ÉCART MAJEUR : ...
- Statut : CONFORME / CONFORME AVEC RÉSERVES / NON CONFORME
Sauvegarde le résultat dans : docs/epics/mobile-ios/PD-106-mfa-settings/PD-106-validation-fonctionnelle.md