Aller au contenu

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

  1. Tu ne juges que la conformité fonctionnelle (pas l'architecture, pas le style de code).
  2. Chaque constat doit citer la référence spec (invariant, critère, flux) et le fichier/composant concerné.
  3. Classe chaque écart : CONFORME / ÉCART MINEUR / ÉCART MAJEUR.
  4. 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ètement
  • requireReauth() → ouvre le modal si pas de re-auth valide, retourne Promise
  • _handleSubmit(password) → appelle settingsApi.reauthenticate(password)

3. useMfa.ts (hook)

  • loadMfaStatus() → GET status, statusError si échec
  • initEnrollment() → POST init, stocke enrollData en useState
  • verifyCode(code) → POST verify, stocke freshRecoveryCodes en useState
  • disable() → POST disable, reload status
  • regenerateCodes() → POST regenerate, stocke freshRecoveryCodes
  • clearRecoveryCodes() / clearEnrollData() → purge useState
  • Chaque erreur → Alert.alert(t("errors.xxx"))

4. useSettings.ts (hook)

  • loadProfile() → GET profile
  • loadMfaStatus() → GET MFA status
  • loadAll() → 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 : ConfirmationModallogoutServer()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 settings et mfa ajouté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