📘 Development Guide - ProbatioVault¶
Date: 10 novembre 2025 Version: 1.0.0 Auteur: ProbatioVault Team
📋 Table des matières¶
- Architecture du projet
- Structure des dossiers
- Conventions de nommage
- Standards de qualité
- Pipeline CI/CD
- Tests et couverture
- Sécurité
🏗️ Architecture du projet¶
Principes architecturaux¶
ProbatioVault suit une architecture modulaire et scalable basée sur les principes suivants :
- Separation of Concerns (SoC) - Séparation claire entre couches
- Domain-Driven Design (DDD) - Organisation par domaine métier
- Single Responsibility - Une responsabilité par module
- Type Safety - TypeScript strict mode activé
Couches de l'application¶
┌─────────────────────────────────────┐
│ UI Layer (Screens) │ ← React Native Components
├─────────────────────────────────────┤
│ Presentation Layer (Hooks) │ ← Business Logic
├─────────────────────────────────────┤
│ State Management Layer (Stores) │ ← Zustand + Persistence
├─────────────────────────────────────┤
│ Services Layer (Services) │ ← Crypto, API, Storage
├─────────────────────────────────────┤
│ Infrastructure Layer (Utils) │ ← Helpers, Constants
└─────────────────────────────────────┘
📁 Structure des dossiers¶
Structure cible (conforme PD-96)¶
src/
├── components/ # Composants réutilisables
│ ├── common/ # Composants génériques (UI)
│ │ ├── Button.tsx
│ │ ├── Input.tsx
│ │ ├── HeaderLeft.tsx
│ │ └── ProgressBar.tsx
│ ├── vault/ # Composants métier coffre-fort
│ │ ├── DocumentRow.tsx
│ │ ├── FolderCard.tsx
│ │ └── ProofBadge.tsx
│ ├── security/ # Composants sécurité
│ │ ├── BiometricPrompt.tsx
│ │ ├── PinInput.tsx
│ │ └── SecurityIndicator.tsx
│ └── index.ts # Export centralisé
│
├── screens/ # Écrans de l'application
│ ├── auth/ # Authentification
│ │ ├── LoginScreen.tsx
│ │ ├── RegisterScreen.tsx
│ │ └── BiometricSetupScreen.tsx
│ ├── vault/ # Coffre-fort
│ │ ├── HomeScreen.tsx
│ │ ├── FolderDetailScreen.tsx
│ │ ├── CreateFolderScreen.tsx
│ │ ├── UploadDocumentScreen.tsx
│ │ ├── DocumentProofScreen.tsx
│ │ └── MediaPreviewScreen.tsx
│ ├── settings/ # Paramètres
│ │ ├── SettingsScreen.tsx
│ │ ├── SecuritySettingsScreen.tsx
│ │ └── AboutScreen.tsx
│ └── index.ts # Export centralisé
│
├── hooks/ # Custom React Hooks
│ ├── useAuth.ts # Authentification
│ ├── useVault.ts # Gestion coffre-fort
│ ├── useBiometric.ts # Authentification biométrique
│ └── index.ts # Export centralisé
│
├── services/ # Services métier
│ ├── crypto.ts # Chiffrement (AES-256-GCM)
│ ├── storage.ts # FileSystem + SecureStore
│ ├── api.ts # Backend API client
│ └── index.ts # Export centralisé
│
├── store/ # State Management (Zustand)
│ ├── useAuthStore.ts # Authentification
│ ├── useVaultStore.ts # Coffre-fort unifié
│ ├── useAppStore.ts # État global app
│ └── index.ts # Export centralisé
│
├── navigation/ # Navigation
│ ├── AppNavigator.tsx # Navigateur principal
│ └── types.ts # Types navigation
│
├── types/ # Types TypeScript
│ ├── document.ts
│ ├── folder.ts
│ ├── proof.ts
│ └── index.ts # Export centralisé
│
├── constants/ # Constantes
│ ├── categories.ts
│ ├── subcases.ts
│ └── colors.ts
│
├── utils/ # Utilitaires
│ ├── telemetry.ts # Télémétrie
│ ├── documentStatus.ts # Statuts documents
│ └── validators.ts # Validateurs
│
├── i18n/ # Internationalisation
│ ├── index.ts
│ ├── fr/
│ │ └── translation.json
│ └── en/
│ └── translation.json
│
├── context/ # React Context (legacy)
│ └── AuthContext.tsx # À migrer vers hooks/useAuth.ts
│
├── __tests__/ # Tests unitaires
│ ├── useVaultStore.test.ts
│ ├── useAuth.test.ts
│ └── crypto.test.ts
│
└── __mocks__/ # Mocks Jest
├── expo-file-system.ts
├── expo-secure-store.ts
└── @react-native-async-storage/
🏷️ Conventions de nommage¶
Fichiers¶
| Type | Convention | Exemple |
|---|---|---|
| Composants React | PascalCase.tsx | DocumentRow.tsx |
| Screens | PascalCase.tsx + "Screen" | FolderDetailScreen.tsx |
| Hooks | camelCase.ts + "use" prefix | useAuth.ts, useVault.ts |
| Services | camelCase.ts | crypto.ts, storage.ts |
| Stores | camelCase.ts + "Store" suffix | useVaultStore.ts |
| Types | camelCase.ts | document.ts, folder.ts |
| Utils | camelCase.ts | telemetry.ts, validators.ts |
| Tests | camelCase.test.ts | useVaultStore.test.ts |
| Mocks | kebab-case.ts | expo-file-system.ts |
Variables et fonctions¶
// ✅ CORRECT
// Constants - SCREAMING_SNAKE_CASE
const MAX_FILE_SIZE = 10 * 1024 * 1024;
const ENCRYPTION_KEY = "pv-vault-key";
// Variables - camelCase
const documentId = "doc123";
const folderName = "Contrats";
// Functions - camelCase (verbe d'action)
function addDocument(doc: Document): void {}
function deleteFolder(id: string): Promise<void> {}
// React Components - PascalCase
const DocumentRow: React.FC<Props> = ({ document }) => {};
// Types/Interfaces - PascalCase
interface Document {
id: string;
name: string;
}
type DocumentStatus = "pending" | "local" | "cloud";
// Enum - PascalCase pour le type, SCREAMING_SNAKE_CASE pour les valeurs
enum FileType {
PDF = "application/pdf",
IMAGE = "image/jpeg",
}
Nommage des fonctions¶
| Préfixe | Usage | Exemple |
|---|---|---|
get | Récupération synchrone | getDocumentById() |
fetch | Récupération asynchrone | fetchDocuments() |
add | Ajout | addFolder() |
update | Mise à jour | updateDocument() |
delete | Suppression | deleteFolder() |
remove | Retrait (sans suppression physique) | removeFromList() |
is | Booléen (état) | isAuthenticated() |
has | Booléen (possession) | hasProof() |
can | Booléen (permission) | canUpload() |
handle | Gestionnaire d'événement | handlePress() |
on | Callback | onDocumentAdded() |
use | Custom Hook | useAuth(), useVault() |
✅ Standards de qualité¶
PD-96 : Exigences de couverture¶
Coverage Thresholds:
statements: 70% # Minimum 70% des instructions testées
branches: 60% # Minimum 60% des branches testées
functions: 70% # Minimum 70% des fonctions testées
lines: 70% # Minimum 70% des lignes testées
Configuration Jest (jest.config.js):
// TODO(PD-96): enforce coverageThreshold >= 70% once test suite is complete.
coverageThreshold: {
global: {
statements: 70,
branches: 60,
functions: 70,
lines: 70
}
}
ESLint Rules¶
Configuration : .eslintrc.js
Règles critiques :
- ✅
sonarjs/no-unused-vars- Pas de variable inutilisée - ✅
sonarjs/no-duplicate-string- Pas de duplication de chaînes - ✅
sonarjs/cognitive-complexity- Complexité max 15 - ✅
sonarjs/no-hardcoded-passwords- Pas de mot de passe en dur - ✅
@typescript-eslint/no-explicit-any- Pas deany - ✅
@typescript-eslint/strict-boolean-expressions- Booléens stricts
TypeScript Strict Mode¶
Configuration : tsconfig.json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true
}
}
🔄 Pipeline CI/CD¶
Étapes CI (conforme PD-96)¶
# .gitlab-ci.yml ou .github/workflows/ci.yml
stages:
- install
- lint
- test
- build
- deploy
# 1. Installation des dépendances
install:
stage: install
script:
- npm ci
cache:
paths:
- node_modules/
# 2. Vérification qualité code
lint:
stage: lint
script:
- npm run lint # ESLint
- npm run typecheck # TypeScript
dependencies:
- install
# 3. Tests unitaires + couverture
test:
stage: test
script:
- npm run test:ci # Jest avec coverage
coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
paths:
- coverage/
dependencies:
- install
# ❌ FAIL si coverage < 70% (PD-96)
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
# 4. SonarQube Analysis
sonarqube:
stage: test
script:
- sonar-scanner
-Dsonar.projectKey=probatiovault-app
-Dsonar.sources=src
-Dsonar.tests=src/__tests__
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
-Dsonar.coverage.exclusions=**/*.test.ts,**/__mocks__/**
dependencies:
- test
only:
- main
- develop
# 5. Build de production
build:
stage: build
script:
- npx expo export --platform all
- npx eas build --platform all --non-interactive
artifacts:
paths:
- dist/
only:
- main
- tags
# 6. Déploiement
deploy:staging:
stage: deploy
script:
- npx eas update --branch staging
only:
- develop
deploy:production:
stage: deploy
script:
- npx eas update --branch production
only:
- main
Scripts package.json requis¶
{
"scripts": {
// Développement
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
// Qualité code
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
"lint:fix": "eslint 'src/**/*.{js,jsx,ts,tsx}' --fix",
"typecheck": "tsc --noEmit",
"format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,md}'",
// Tests
"test": "jest --watch",
"test:ci": "cross-env EXPO_OS=ios jest --ci --maxWorkers=2",
"test:coverage": "jest --coverage",
// Build
"build:android": "eas build --platform android",
"build:ios": "eas build --platform ios",
"build:all": "eas build --platform all"
}
}
🧪 Tests et couverture¶
Stratégie de tests¶
Tests Pyramid (PD-96):
/\
/ \ E2E Tests (10%)
/----\ - Critical user flows
/ \
/--------\ Integration Tests (20%)
/ \ - API + Store + UI
/------------\
/ \ Unit Tests (70%)
/________________\ - Services, Hooks, Utils
Organisation des tests¶
src/__tests__/
├── unit/ # Tests unitaires
│ ├── stores/
│ │ ├── useVaultStore.test.ts ✅ 25 tests
│ │ ├── useAuthStore.test.ts 🔄 À créer
│ │ └── useAppStore.test.ts 🔄 À créer
│ ├── services/
│ │ ├── crypto.test.ts 🔄 À créer (PD-96)
│ │ ├── storage.test.ts 🔄 À créer (PD-96)
│ │ └── api.test.ts 🔄 À créer (PD-96)
│ ├── hooks/
│ │ ├── useAuth.test.ts 🔄 À créer (PD-96)
│ │ ├── useVault.test.ts 🔄 À créer (PD-96)
│ │ └── useBiometric.test.ts 🔄 À créer (PD-96)
│ └── utils/
│ ├── validators.test.ts 🔄 À créer
│ └── telemetry.test.ts 🔄 À créer
│
├── integration/ # Tests d'intégration
│ ├── document-upload.test.ts 🔄 À créer
│ └── folder-management.test.ts 🔄 À créer
│
└── e2e/ # Tests end-to-end
└── critical-flows.test.ts 🔄 À créer
Couverture actuelle vs objectif PD-96¶
| Métrique | Actuel | Objectif PD-96 | Écart |
|---|---|---|---|
| Statements | 23.42% | 70% | -46.58% ❌ |
| Branches | 13.14% | 60% | -46.86% ❌ |
| Functions | 28.11% | 70% | -41.89% ❌ |
| Lines | 22.73% | 70% | -47.27% ❌ |
Priorités pour atteindre 70% :
- ✅ useVaultStore.ts (fait - 25 tests)
- 🔄 services/crypto.ts (~40 tests estimés)
- 🔄 hooks/useAuth.ts (~20 tests estimés)
- 🔄 hooks/useVault.ts (~15 tests estimés)
- 🔄 services/storage.ts (~15 tests estimés)
Commandes de test¶
# Mode watch (développement)
npm test
# CI mode (avec coverage)
npm run test:ci
# Coverage HTML report
npm run test:coverage
open coverage/lcov-report/index.html
# Test un fichier spécifique
npm test -- useVaultStore.test.ts
# Test avec verbose
npm test -- --verbose
# Update snapshots
npm test -- -u
🔒 Sécurité¶
Standards de sécurité¶
Chiffrement :
- ✅ AES-256-GCM pour fichiers (authentifié, empêche tampering)
- ✅ AES-256-CBC pour données JSON store (rétrocompatibilité V2)
- ✅ PBKDF2-SHA256 100k itérations pour Master Key
- ✅ Salt 32 bytes, IV 12 bytes (GCM) / 16 bytes (CBC)
Stockage :
- ✅ SecureStore pour données sensibles (tokens, passwords)
- ✅ AsyncStorage chiffré pour état Zustand
- ✅ Fichiers chiffrés dans FileSystem local
Authentification :
- ✅ Master Key jamais en clair
- ✅ Biométrie avec fallback PIN
- ✅ JWT tokens avec refresh (backend)
Audit de sécurité¶
# Audit npm dependencies
npm audit
# Fix vulnérabilités automatiquement
npm audit fix
# Audit avec rapport détaillé
npm audit --json > security-audit.json
# Vérification hardcoded secrets (via ESLint)
npm run lint
Checklist sécurité¶
- Pas de secrets hardcodés (cf. ESLint
sonarjs/no-hardcoded-passwords) - Pas de console.log de données sensibles en production
- HTTPS uniquement pour API calls
- Validation des inputs utilisateur
- Sanitization des URLs
- Gestion des erreurs sans leaks d'info
- Timeouts sur toutes les requêtes réseau
- Rate limiting côté client
📚 Documentation additionnelle¶
- Index documentation - Vue d'ensemble du projet
- ARCHITECTURE_REFACTOR.md - Refactoring architecture
- STORE_FUSION.md - Fusion des stores
- Tests - Stratégie de tests
🎯 Checklist avant merge (Pull Request)¶
Qualité code¶
- ESLint 0 erreur :
npm run lint - TypeScript 0 erreur :
npm run typecheck - Code formaté :
npm run format
Tests¶
- Tous les tests passent :
npm run test:ci - Nouveaux tests pour nouvelle feature
- Coverage ≥ 70% (ou justification si < 70%)
Documentation¶
- README.md mis à jour si nécessaire
- Commentaires JSDoc pour fonctions publiques
- CHANGELOG.md mis à jour
Sécurité¶
- Pas de secrets hardcodés
- Audit npm :
npm auditclean - Revue de code sécurité (peer review)
CI/CD¶
- Pipeline CI passe ✅
- SonarQube Quality Gate OK
- Build de production réussit
🚀 Workflows recommandés¶
Workflow Git¶
# 1. Créer une branche feature
git checkout -b feature/PD-123-add-document-preview
# 2. Développer + tests
npm test -- --watch
# 3. Vérifier qualité
npm run lint
npm run typecheck
npm run test:ci
# 4. Commit (conventional commits)
git add .
git commit -m "feat(vault): add document preview with zoom
- Add DocumentPreviewScreen with pinch-to-zoom
- Support PDF, images, videos
- Add tests for preview component
Closes PD-123"
# 5. Push et créer PR
git push -u origin feature/PD-123-add-document-preview
# 6. Attendre review + CI ✅
# 7. Merge dans develop/main
Conventional Commits¶
Types :
feat: Nouvelle fonctionnalitéfix: Correction de bugrefactor: Refactoring (pas de changement fonctionnel)test: Ajout/modification de testsdocs: Documentationstyle: Formatage (prettier, etc.)perf: Amélioration de performancechore: Tâches de maintenance
Exemples :
feat(vault): add cascade delete for folders
fix(crypto): handle empty file encryption
refactor(store): merge 3 stores into useVaultStore
test(vault): add 25 tests for useVaultStore
docs(readme): update folder structure
✉️ Contact¶
Questions sur le guide : support@probatiovault.com Documentation : https://probatiovault.com/docs CI/CD : https://gitlab.com/probatiovault/app
"Code quality is not an act, it's a habit." — Aristotle