== CSRF (Session) == OK le jeton fait 64 caractères hexadécimaux OK le jeton est stable sur la session OK un jeton valide est accepté OK un jeton falsifié est refusé OK un jeton vide est refusé OK un jeton non-string est refusé == pullIntendedUrl (Session) == OK URL interne restituée OK URL consommée après lecture OK protocole-relative // refusée OK URL absolue externe refusée OK valeur non-string refusée == TOTP == OK secret en base32 (A-Z2-7) OK code de 6 chiffres OK code déterministe pour un timestamp donné OK code différent pour une autre période OK le code courant est vérifiable OK un code invalide est refusé OK 8 codes de secours générés OK codes de secours uniques == Droits (intégration base front) == OK rôles seedés présents (superadmin, admin, utilisateur, comptabilite) OK rôle lecture_seule supprimé OK utilisateur possède domains.delete (exploitation complète) OK utilisateur ne possède PAS registrar.manage (réservé admin) OK utilisateur ne possède pas settings.admin OK admin possède registrar.manage OK admin possède users.manage (gestion du staff) OK admin ne possède pas users.impersonate (réservé registre) OK comptabilite possède invoices.view OK comptabilite ne possède pas domains.delete OK les droits admin englobent les droits utilisateur OK le rôle superadmin n'a aucune ligne de droits (bypass en code) OK la table audit_log existe == Formulaire d'enregistrement de domaine (données $_POST) == OK les données postées sont lues (erreur « .mc uniquement », pas « obligatoire ») OK aucune demande créée sur erreur Tous les tests passent.