Guide de contribution - ProbatioVault Backend¶
Merci de contribuer au projet ProbatioVault Backend ! Ce guide vous aidera à respecter les standards de qualité et les conventions du projet.
Table des matières¶
- Code de conduite
- Workflow de développement
- Standards de code
- Conventions de nommage
- Tests
- Commits et branches
- Revue de code
- Documentation
Code de conduite¶
- Respectez les autres contributeurs
- Soyez constructif dans vos feedbacks
- Privilégiez la collaboration
- Suivez les guidelines techniques
Workflow de développement¶
1. Créer une branche¶
# Format: type/PD-XX-description-courte
git checkout -b feature/PD-25-implement-srp-auth
git checkout -b fix/PD-42-fix-merkle-proof
git checkout -b refactor/PD-50-optimize-hash-service
Types de branches : - feature/ : Nouvelle fonctionnalité - fix/ : Correction de bug - refactor/ : Refactoring sans changement fonctionnel - docs/ : Documentation uniquement - test/ : Ajout/modification de tests - chore/ : Maintenance (dépendances, config, etc.)
2. Développer la fonctionnalité¶
# Installer les dépendances
npm install
# Lancer le mode développement
npm run start:dev
# Exécuter les tests en parallèle
npm run test:watch
3. Vérifier la qualité¶
# Linter + formatage
npm run lint
npm run format
# Type checking
npm run type-check
# Tests complets avec couverture
npm run test:cov
4. Commiter les changements¶
Voir section Commits et branches
5. Créer une Merge Request¶
- Pusher la branche sur GitLab
- Créer une MR vers
dev - Remplir le template de MR
- Assigner 2 reviewers minimum
- Lier la PD correspondante
Standards de code¶
TypeScript strict mode¶
À faire :
// Types explicites
function calculateHash(data: Buffer): string {
return sha3_256(data);
}
// Interfaces pour les objets
interface DocumentMetadata {
name: string;
size: number;
mimeType: string;
}
// Nullish coalescing
const port = config.get<number>('PORT') ?? 3000;
À éviter :
// Any interdit (sauf cas exceptionnels documentés)
function process(data: any) { ... }
// Types implicites
function calculate(x, y) { ... }
// Assertions non vérifiées
const user = data as User;
ESLint¶
Le projet utilise des règles strictes :
// Complexité maximale
'complexity': ['warn', 15]
'max-lines-per-function': ['warn', 150]
// Sécurité
'security/detect-object-injection': 'error'
'security/detect-unsafe-regex': 'error'
// Imports organisés
'import/order': ['error', {
'groups': ['builtin', 'external', 'internal'],
'newlines-between': 'always',
'alphabetize': { order: 'asc' }
}]
NestJS Best Practices¶
// Injection de dépendances
@Injectable()
export class DocumentsService {
constructor(
@InjectRepository(Document)
private readonly documentsRepo: Repository<Document>,
private readonly cryptoService: CryptoService,
) {}
}
// DTOs avec validation
export class CreateDocumentDto {
@IsString()
@IsNotEmpty()
name!: string;
@IsNumber()
@Min(1)
size!: number;
}
// Gestion d'erreurs explicite
if (!document) {
throw new NotFoundException(`Document ${id} not found`);
}
Conventions de nommage¶
Fichiers¶
auth.module.ts # Modules
auth.service.ts # Services
auth.controller.ts # Controllers
auth.service.spec.ts # Tests unitaires
auth.e2e-spec.ts # Tests E2E
login.dto.ts # DTOs
user.entity.ts # Entities TypeORM
jwt-auth.guard.ts # Guards
logging.interceptor.ts # Interceptors
Code¶
// Classes : PascalCase
class AuthService {}
class JwtStrategy {}
// Variables/fonctions : camelCase
const userToken = generateToken();
function validateUser() {}
// Constantes : UPPER_SNAKE_CASE
const MAX_FILE_SIZE = 10 * 1024 * 1024;
const DEFAULT_TIMEOUT = 5000;
// Interfaces : PascalCase avec I préfixe (optionnel)
interface DocumentMetadata {}
interface IUserRepository {}
// Types : PascalCase
type UserId = string;
type DocumentStatus = 'pending' | 'active' | 'archived';
// Enums : PascalCase
enum UserRole {
Admin = 'admin',
User = 'user',
Guest = 'guest',
}
Tests¶
Couverture minimale¶
- Branches : 80%
- Functions : 85%
- Lines : 85%
- Statements : 85%
Structure des tests¶
describe('HashService', () => {
let service: HashService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [HashService],
}).compile();
service = module.get<HashService>(HashService);
});
describe('hash', () => {
it('should hash data with SHA3-256', () => {
const data = 'test';
const hash = service.hash(data);
expect(hash).toBeDefined();
expect(hash.length).toBe(64);
});
it('should produce consistent hashes', () => {
const hash1 = service.hash('test');
const hash2 = service.hash('test');
expect(hash1).toBe(hash2);
});
});
});
Tests obligatoires¶
Pour chaque service/controller : - Au moins 1 test par méthode publique - Test des cas nominaux - Test des cas d'erreur - Test des edge cases
Commits et branches¶
Format des commits (Conventional Commits)¶
Types : - feat: Nouvelle fonctionnalité - fix: Correction de bug - refactor: Refactoring - test: Ajout/modification de tests - docs: Documentation - style: Formatage (sans changement de code) - perf: Amélioration de performance - chore: Maintenance (dépendances, config)
Exemples :
feat(auth): implement SRP-6a authentication protocol
fix(crypto): correct AES-GCM decryption padding issue
refactor(documents): extract upload logic to separate service
test(merkle): add comprehensive Merkle tree test suite
docs(readme): update installation instructions
Branches¶
# Format
<type>/PD-<numero>-<description-kebab-case>
# Exemples
feature/PD-25-implement-srp-authentication
fix/PD-42-fix-merkle-proof-generation
refactor/PD-50-optimize-hash-performance
Revue de code¶
Checklist du développeur (avant MR)¶
- Code respecte les standards ESLint/Prettier
- TypeScript compile sans erreur ni warning
- Tous les tests passent (couverture >= 85%)
- Documentation à jour (JSDoc, README)
- Pas de console.log / code de debug
- Pas de secrets/credentials en dur
- Pas de dépendances inutiles ajoutées
- Commits bien formatés (Conventional Commits)
Checklist du reviewer¶
- Code respecte l'architecture du projet
- Logique métier correcte
- Gestion d'erreurs appropriée
- Pas de vulnérabilités de sécurité
- Performance acceptable
- Tests pertinents et suffisants
- Documentation claire
Process de review¶
- 2 approbations minimum requises
- Pipeline CI/CD doit être verte
- Commentaires résolus avant merge
- Squash commits lors du merge (optionnel)
Documentation¶
JSDoc obligatoire¶
/**
* Hash une donnée avec SHA3-256
*
* @param data - Données à hasher (string ou Buffer)
* @returns Hash SHA3-256 en hexadécimal (64 caractères)
* @throws {Error} Si les données sont invalides
*
* @example
* const hash = hashService.hash('my data');
* console.log(hash); // "a7b3c4d5..."
*/
hash(data: string | Buffer): string {
// Implementation
}
Documentation à mettre à jour¶
Lors de changements significatifs : - [ ] README.md - [ ] Swagger/OpenAPI (via decorators NestJS) - [ ] Architecture Decision Records (ADR) - [ ] Diagrammes (si architecture modifiée)
Sécurité¶
Principes de sécurité¶
- Validation des entrées : Toujours valider avec
class-validator - Pas de secrets en dur : Utiliser les variables d'environnement
- Sanitization : Échapper les données utilisateur
- Least privilege : Permissions minimales
- Audit trail : Logger les actions sensibles
Rapport de vulnérabilité¶
Si vous découvrez une vulnérabilité : 1. NE PAS créer d'issue publique 2. Contacter l'équipe sécurité : security@probatiovault.com 3. Fournir un POC si possible
Contact¶
Questions ou problèmes ? Contactez l'équipe : - Slack : #probatiovault-backend - Email : dev@probatiovault.com - GitLab Issues : Pour les bugs/features