Règles QA & conformité ANSSI

Ce document définit les règles de qualité et de sécurité applicables à tout le projet gitrust. Chaque lot doit satisfaire ces règles avant merge.


1. Gates de compilation obligatoires

Toute modification doit passer ces 4 gates sans erreur :

Gate Commande Critère
Formatage cargo fmt --all -- --check Zéro diff
Linting cargo clippy --workspace -- -D warnings Zéro warning
Tests unitaires cargo test --workspace 100% pass
Build CSS npx tailwindcss -i static/css/input.css -o static/css/style.css --minify Si templates modifiés

Gates supplémentaires (à mettre en place)

Gate Outil Rôle
Audit dépendances cargo audit Détection CVE dans les deps
Licences & bans cargo deny check Licences compatibles, pas de crate bannie
Secrets dans le code Recherche de patterns sensibles Pas de token/mot de passe en dur

2. Règles de sécurité (ANSSI PA-074)

2.1 Lints Rust obligatoires (déjà en place)

#![forbid(unsafe_code)]                    // core, web, hooks
#![deny(unsafe_code)]                      // git, ssh (FFI nécessaire)
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::indexing_slicing)]
#![deny(clippy::mem_forget)]

2.2 Checklist sécurité par feature

Avant toute implémentation touchant l'authentification, les secrets ou les permissions, vérifier :

  • [ ] Secrets jamais en clair en base — hash SHA-256 ou bcrypt
  • [ ] Secrets jamais loggés — vérifier tracing::info/debug/warn, Display et Debug impls ne révèlent pas le secret
  • [ ] Comparaison constant-timesubtle::ConstantTimeEq pour toute validation de secret (pas de == sur des hash)
  • [ ] Rate-limiting — endpoint d'authentification protégé
  • [ ] CSRF — token valide sur toute action mutante (POST/PUT/DELETE)
  • [ ] Ownership vérifiée (anti-IDOR) — le user ne peut agir que sur ses propres ressources (vérifier user_id côté serveur)
  • [ ] Expiration obligatoire — tout token/session a une durée de vie max
  • [ ] Audit log — création, révocation, utilisation suspecte tracées
  • [ ] Zeroize — types sensibles implémentent Zeroize/ZeroizeOnDrop
  • [ ] Path traversal — validation des chemins disque (pas de .., /, \)

2.3 Marqueurs SEC-

Le code utilise des commentaires // SEC-XX pour tracer les décisions de sécurité. Tout nouveau contrôle doit être marqué avec le prochain numéro disponible dans sa catégorie :

Préfixe Catégorie Exemples
SEC-C Cryptographie Timing attack, CSRF, PKCE
SEC-H HTTP/Headers X-Forwarded-For, cookies, nonce
SEC-L Logique métier Hashing, validation, defaults
SEC-M Mémoire/sessions Rate-limit DoS, refresh tokens

3. Tests requis par catégorie

3.1 Matrice de couverture

Catégorie Quand appliquer Exemples
Unitaire Logique pure (validation, parsing, conversion) RepoSlug::new("../evil") → erreur
Intégration Service avec DB (CRUD, contraintes, transactions) PatService::validate token expiré → None
Handler Endpoint HTTP (status, redirect, CSRF, auth) POST sans CSRF → 403
E2E Playwright Flow utilisateur complet Créer token → copier → cloner un dépôt
Sécurité négatif Tout bypass imaginable Token user A sur ressource user B → 401

3.2 Règles de tests

  1. Tests d'intégration sur vraie DB — pas de mocks pour la couche persistence (les mocks masquent les bugs de migration)
  2. Tests négatifs obligatoires — pour chaque chemin heureux, tester au moins : input invalide, non-authentifié, non-autorisé, expiré, révoqué
  3. Tests E2E en français — cohérent avec l'UI (locale fr-FR)
  4. Pas de sleep() dans les tests — utiliser des retry/poll avec timeout
  5. Données de test isolées — chaque test crée ses propres données (pas de dépendance sur l'ordre d'exécution)

4. Règles de code

4.1 Framework boundary

  • Ne jamais modifier crates/rustwarden-core/
  • Réutiliser les services framework avant d'implémenter (auth, users, sessions, ResourceService, i18n, middleware)
  • Si un service manque, l'étendre côté gitrust (wrappers, trait impls)

4.2 Assets

  • Zéro CDN — tous les CSS/JS servis depuis static/
  • La CSP du framework bloque les domaines externes

4.3 Gestion d'erreurs

  • GitrustError avec IntoResponse pour le mapping HTTP
  • Pas de .unwrap() / .expect() / panic!() / [index]
  • Errors utilisateur : messages génériques (pas de leak d'info interne)

4.4 Validation aux frontières

  • Valider les inputs utilisateur (formulaires, query params, headers)
  • Ne pas re-valider entre services internes
  • Newtypes avec validation à la construction (RepoSlug, TeamSlug, Fingerprint, TokenHash)

5. Checklist pré-merge

Avant chaque merge de lot :

  • [ ] cargo fmt --all -- --check passe
  • [ ] cargo clippy --workspace -- -D warnings passe
  • [ ] cargo test --workspace — tous les tests passent
  • [ ] Tests E2E Playwright passent (npm run test:e2e)
  • [ ] CSS rebuild si templates modifiés
  • [ ] Aucun secret en clair dans le code ou les logs
  • [ ] Checklist sécurité §2.2 validée (si applicable)
  • [ ] Pas de modification dans crates/rustwarden-core/