API Reference — ProbatioVault Backend¶
Version: 1.0.0 Base URL: http://localhost:3000 (développement) API Prefix: /v1 (sauf health check) Documentation Swagger: http://localhost:3000/api/docs (développement uniquement)
Table des matières¶
- Authentification
- Health & Monitoring
- Authentification SRP-6a
- Purge des comptes
- Documents sécurisés
- Upload multipart
- Cryptographie - Key Envelopes
- Audit & Preuves probatoires
- Jobs asynchrones
- Synchronisation multi-device
- Codes d'erreur
Authentification¶
La plupart des endpoints nécessitent un token JWT obtenu via le flow d'authentification SRP-6a.
Header requis¶
Exceptions (endpoints publics)¶
/health//v1/auth/srp-params/v1/auth/register/v1/auth/validate-email/v1/auth/login/challenge/v1/auth/login/verify
Health & Monitoring¶
GET /health¶
Health check pour monitoring infrastructure.
Authentication: Aucune
Response: 200 OK
GET /¶
Informations sur l'API.
Authentication: Aucune
Response: 200 OK
{
"name": "ProbatioVault Backend API",
"version": "1.0.0",
"description": "API REST pour coffre-fort numérique probatoire"
}
GET /v1/health/redis¶
Vérification santé Redis (connexion, TLS, AUTH, mémoire).
Authentication: Aucune
Response: 200 OK
{
"status": "healthy",
"connected": true,
"tlsEnabled": true,
"authEnabled": true,
"memoryUsage": {
"used": "10MB",
"peak": "15MB"
}
}
Référence: PD-21 - Utilisé par Flow Prefect redis_health_flow.py
GET /v1/health/redis/status¶
Statut Redis en cache (sans ping réseau).
Authentication: Aucune
Response: 200 OK
Authentification SRP-6a¶
Architecture Zero-Knowledge : le mot de passe n'est jamais envoyé au serveur.
Référence: PD-23, PD-24
GET /v1/auth/srp-params¶
Récupère les paramètres publics SRP-6a (N, g) nécessaires pour les calculs client.
Authentication: Aucune
Response: 200 OK
Notes: - N: Prime 3072 bits (groupe RFC 5054) - g: Générateur = 2
POST /v1/auth/register¶
Inscription utilisateur Zero-Knowledge.
Authentication: Aucune Guards: ForbidPasswordGuard, RateLimitGuard
Request Body:
Response: 200 OK
Important: - Le client génère salt et verifier localement - Formule: verifier = g^x mod N où x = SHA3-256(salt || K_auth) - K_auth = Argon2id(password, salt, "ProbatioVault_SRP_Auth_v1") - Anti-énumération: Réponse identique si email existe déjà (INV-8)
Erreurs: - 400: Payload invalide ou champ password présent (rejeté par guard) - 429: Rate limit dépassé
POST /v1/auth/validate-email¶
Validation email après inscription (lien reçu par email).
Authentication: Aucune
Request Body:
Response: 200 OK
Notes: - Token UUID v4 valide 1 heure (INV-10) - Transition: PENDING_VALIDATION → ACTIVE - Anti-énumération: Réponse identique si token invalide
POST /v1/auth/login/challenge¶
Phase 1, Étape 1 : Initialisation du challenge SRP-6a.
Authentication: Aucune
Request Body:
Response: 200 OK
Notes: - Le client génère (a, A) où A = g^a mod N - Le serveur valide A mod N ≠ 0 - Le serveur génère (b, B) et retourne salt + B
Erreurs: - 400: Paramètre A invalide - 404: Utilisateur non trouvé
POST /v1/auth/login/verify¶
Phase 1, Étape 2 : Vérification de la preuve client et obtention du JWT.
Authentication: Aucune
Request Body:
Response: 200 OK
Notes: - M1 = SHA3-256(A || B || K) (preuve client) - M2 = SHA3-256(A || M1 || K) (preuve serveur) - Le client doit vérifier M2 pour authentifier le serveur
Erreurs: - 401: Session SRP expirée ou preuve invalide
Purge des comptes¶
Endpoints internes pour la purge automatique des comptes non validés.
Référence: PD-23 INV-10, INV-12
POST /v1/auth/purge/expired¶
Purge des comptes en état PENDING_VALIDATION dont le token a expiré.
Authentication: X-Internal-Api-Key (InternalApiGuard)
Response: 200 OK
Notes: - Appelé automatiquement par Flow Prefect (cron horaire) - Fallback manuel possible par administrateur - Purge également les traces d'audit (conformité RGPD) - Supprime les emails non envoyés de l'outbox
Erreurs: - 401: Non authentifié - 403: Non autorisé (admin requis)
GET /v1/auth/purge/status¶
Statut du système de purge.
Authentication: X-Internal-Api-Key
Response: 200 OK
Usage: - Monitoring healthcheck Prefect - Alerting si comptes en attente de purge
Documents sécurisés¶
Gestion des documents probatoires avec métadonnées chiffrées côté client.
Référence: PD-16 Architecture: RLS PostgreSQL pour isolation utilisateur
POST /v1/documents¶
Créer un nouveau document sécurisé (status=PENDING).
Authentication: JWT Bearer
Request Body:
{
"encryptedMetadata": "base64_encoded_encrypted_metadata",
"keywordDeterministic": ["hash1", "hash2"],
"ovhPath": "550e8400-e29b-41d4-a716-446655440000/doc.enc"
}
Response: 201 Created
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": "user_id",
"encryptedMetadata": "...",
"fileHash": "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
"status": "PENDING",
"createdAt": "2025-01-02T10:30:00.000Z"
}
Notes: - Métadonnées chiffrées AES-256-GCM côté client - PD-38 E-01: Le hash SHA3-256 est calculé côté serveur depuis le fichier S3 (garantie probatoire) - Le hash est vérifié pour détecter les doublons par utilisateur - RLS filtre automatiquement par user_id
Erreurs: - 400: Données invalides, contexte utilisateur manquant, ou fichier S3 introuvable - 409: Document avec ce hash déjà existant
GET /v1/documents¶
Lister tous les documents de l'utilisateur courant.
Authentication: JWT Bearer
Response: 200 OK
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"encryptedMetadata": "...",
"status": "SEALED",
"createdAt": "2025-01-02T10:30:00.000Z"
}
]
Notes: - RLS filtre automatiquement par user_id
GET /v1/documents/:id¶
Récupérer un document par son ID.
Authentication: JWT Bearer
Parameters: - id (UUID): ID du document
Response: 200 OK
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": "user_id",
"encryptedMetadata": "...",
"fileHash": "...",
"status": "SEALED",
"createdAt": "2025-01-02T10:30:00.000Z"
}
Erreurs: - 404: Document non trouvé ou non accessible (RLS)
GET /v1/documents/:id/hash¶
Récupérer le hash probatoire SHA3-256 d'un document (PD-38).
Authentication: JWT Bearer
Parameters: - id (UUID): ID du document
Response: 200 OK
{
"hash": "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
"algorithm": "SHA3-256"
}
Notes: - Hash calculé sur le fichier chiffré (garantie probatoire) - Format: 64 caractères hexadécimaux (256 bits) - Utilisable pour vérification d'intégrité côté client
Erreurs: - 404: Document non trouvé ou non accessible (RLS)
Référence: PD-38
DELETE /v1/documents/:id¶
Supprimer un document.
Authentication: JWT Bearer
Parameters: - id (UUID): ID du document
Response: 204 No Content
Règles RLS: - PENDING: suppression autorisée par propriétaire - EXPIRED: suppression autorisée par propriétaire - SEALED: suppression interdite (sauf probatio_admin)
Erreurs: - 400: Contexte utilisateur manquant - 404: Document non trouvé
Upload multipart¶
Gestion des uploads multipart avec streaming direct vers S3.
Référence: PD-XX (Upload Service) Architecture: Streaming sans buffering (INV-2)
GET /v1/uploads/config¶
Récupérer la configuration upload (quotas, limites).
Authentication: JWT Bearer
Response: 200 OK
{
"maxFileSize": 5368709120,
"minPartSize": 5242880,
"maxPartSize": 104857600,
"maxParts": 1000,
"sessionTTL": 86400,
"allowedMimeTypes": ["application/pdf", "image/jpeg", "image/png"]
}
Notes: - Utilisé pour validation côté client - Audit CA12, CA14
POST /v1/uploads¶
Initialiser une nouvelle session d'upload multipart.
Authentication: JWT Bearer
Request Body:
{
"fileName": "document.pdf",
"fileSize": 10485760,
"mimeType": "application/pdf",
"totalParts": 2
}
Response: 201 Created
{
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"uploadId": "aws_multipart_upload_id",
"expiresAt": "2025-01-03T10:30:00.000Z"
}
Erreurs: - 400: Données invalides - 429: Quota dépassé
PUT /v1/uploads/:sessionId/parts/:partNumber¶
Upload d'une partie (streaming direct vers S3).
Authentication: JWT Bearer Guards: TenantIsolationGuard, SessionOwnerGuard
Parameters: - sessionId (UUID): ID de la session - partNumber (integer): Numéro de la partie (1-indexed)
Headers: - Content-Length: Taille de la partie en bytes
Body: Binary data (streaming)
Response: 200 OK
Erreurs: - 400: Taille ou numéro de partie invalide - 404: Session non trouvée - 409: Conflit partie (contenu différent) - 410: Session expirée
POST /v1/uploads/:sessionId/complete¶
Finaliser l'upload multipart.
Authentication: JWT Bearer Guards: TenantIsolationGuard, SessionOwnerGuard
Parameters: - sessionId (UUID): ID de la session
Response: 200 OK
{
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"fileKey": "s3://bucket/path/to/file",
"fileSize": 10485760,
"completedAt": "2025-01-02T10:35:00.000Z"
}
Erreurs: - 400: Parties manquantes ou invalides - 404: Session non trouvée - 409: Session en état terminal - 410: Session expirée
DELETE /v1/uploads/:sessionId¶
Annuler l'upload.
Authentication: JWT Bearer Guards: TenantIsolationGuard, SessionOwnerGuard
Parameters: - sessionId (UUID): ID de la session
Response: 200 OK
{
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"status": "ABORTED",
"abortedAt": "2025-01-02T10:35:00.000Z"
}
Erreurs: - 404: Session non trouvée - 409: Session déjà complétée
GET /v1/uploads/:sessionId¶
Récupérer le statut d'une session d'upload.
Authentication: JWT Bearer Guards: TenantIsolationGuard, SessionOwnerGuard
Parameters: - sessionId (UUID): ID de la session
Response: 200 OK
{
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"status": "IN_PROGRESS",
"uploadedParts": 1,
"totalParts": 2,
"uploadedBytes": 5242880,
"totalBytes": 10485760,
"expiresAt": "2025-01-03T10:30:00.000Z"
}
Erreurs: - 404: Session non trouvée
Cryptographie - Key Envelopes¶
Gestion des enveloppes de clés (Master, Device, Recovery).
Référence: PD-35 ⚠️ IMPORTANT: JWT authentication temporairement désactivé pour développement. À activer avant production !
POST /v1/crypto/keys/master-envelope¶
Créer Master Envelope lors de la création de compte.
Authentication: ⚠️ Désactivé (dev) - JWT requis en production
Request Body:
Response: 201 Created
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"encryptedEnvelope": "base64_encoded_40_bytes",
"algorithm": "AES-256-KW",
"version": 1
}
Erreurs: - 400: Clés invalides (longueur incorrecte) - 409: Master Envelope existe déjà
POST /v1/crypto/keys/device-envelope¶
Créer Device Envelope lors de l'ajout d'un nouveau device.
Authentication: ⚠️ Désactivé (dev) - JWT requis en production
Request Body:
{
"deviceId": "550e8400-e29b-41d4-a716-446655440000",
"kDeviceBase64": "base64_encoded_32_bytes",
"kMasterUserBase64": "base64_encoded_32_bytes"
}
Response: 201 Created
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"deviceId": "device_uuid",
"encryptedEnvelope": "base64_encoded_40_bytes",
"algorithm": "AES-256-KW",
"version": 1
}
Erreurs: - 400: Clés invalides - 403: Device blacklisté - 409: Device Envelope existe déjà
POST /v1/crypto/keys/recovery-envelope¶
Créer Recovery Envelope (BIP39).
Authentication: ⚠️ Désactivé (dev) - JWT requis en production
Request Body:
Response: 201 Created
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"encryptedEnvelope": "base64_encoded_40_bytes",
"algorithm": "AES-256-KW",
"version": 1
}
Erreurs: - 400: Clés invalides - 409: Recovery Envelope existe déjà
GET /v1/crypto/keys/master-envelope¶
Récupérer Master Envelope (pour changement password).
Authentication: ⚠️ Désactivé (dev) - JWT requis en production
Response: 200 OK
Erreurs: - 404: Master Envelope non trouvée
GET /v1/crypto/keys/device-envelope/:deviceId¶
Récupérer Device Envelope (pour accès document).
Authentication: ⚠️ Désactivé (dev) - JWT requis en production
Parameters: - deviceId (UUID): ID du device
Response: 200 OK
{
"encryptedEnvelope": "base64_encoded_40_bytes",
"algorithm": "AES-256-KW",
"lastUsedAt": "2025-01-02T10:30:00.000Z"
}
Erreurs: - 403: Device blacklisté - 404: Device Envelope non trouvée
GET /v1/crypto/keys/devices¶
Lister tous les devices autorisés de l'utilisateur.
Authentication: ⚠️ Désactivé (dev) - JWT requis en production
Response: 200 OK
[
{
"deviceId": "550e8400-e29b-41d4-a716-446655440000",
"lastUsedAt": "2025-01-02T10:30:00.000Z",
"createdAt": "2025-01-01T08:00:00.000Z"
}
]
DELETE /v1/crypto/keys/devices/:deviceId¶
Révoquer un device.
Authentication: ⚠️ Désactivé (dev) - JWT requis en production
Parameters: - deviceId (UUID): ID du device à révoquer
Request Body:
Response: 204 No Content
Erreurs: - 404: Device non trouvé
Audit & Preuves probatoires¶
Export et vérification de preuves probatoires pour audit indépendant.
Référence: PD-37 E-01 Compliance: NF Z42-013, ISO 14641
GET /v1/audit/proof/:id¶
Exporter une entrée d'audit comme preuve vérifiable.
Authentication: JWT Bearer (implicite)
Parameters: - id (UUID): ID de l'entrée audit
Response: 200 OK
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"entryCanonical": "{\"action\":\"CREATE\",\"timestamp\":\"2025-01-02T10:30:00.000Z\"}",
"entryHash": "sha3_256_hex",
"hsmSignature": "base64_signature",
"hsmKeyId": "key_uuid",
"publicKey": "base64_public_key"
}
Notes: - La preuve contient toutes les données pour vérification indépendante - Vérifiable sans accès HSM
Erreurs: - 404: Entrée audit non trouvée
GET /v1/audit/proof/:id/verify¶
Vérifier une entrée d'audit (HSM-independent).
Authentication: JWT Bearer
Parameters: - id (UUID): ID de l'entrée audit
Response: 200 OK
{
"valid": true,
"entryId": "550e8400-e29b-41d4-a716-446655440000",
"hashValid": true,
"signatureValid": true,
"verifiedAt": "2025-01-02T10:30:00.000Z"
}
POST /v1/audit/proof/verify-batch¶
Vérifier plusieurs entrées d'audit en batch (max 1000).
Authentication: JWT Bearer
Request Body:
Response: 200 OK
{
"total": 2,
"valid": 2,
"invalid": 0,
"results": {
"550e8400-e29b-41d4-a716-446655440000": {
"valid": true,
"hashValid": true,
"signatureValid": true
},
"660e9511-f39c-23e4-b827-557766551111": {
"valid": true,
"hashValid": true,
"signatureValid": true
}
}
}
Erreurs: - 400: IDs manquants ou limite dépassée (max 1000)
POST /v1/audit/proof/verify-external¶
Vérifier une preuve externe (sans accès base de données).
Authentication: JWT Bearer
Request Body:
{
"proof": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"entryCanonical": "{...}",
"entryHash": "sha3_256_hex",
"hsmSignature": "base64_signature",
"hsmKeyId": "key_uuid",
"publicKey": "base64_public_key"
}
}
Response: 200 OK
{
"valid": true,
"hashValid": true,
"signatureValid": true,
"verifiedAt": "2025-01-02T10:30:00.000Z"
}
Notes: - Permet vérification par auditeurs tiers - Ne nécessite pas d'accès au système
Erreurs: - 400: Champs manquants dans la preuve
GET /v1/audit/proof/status¶
Statut de vérification pour entrées récentes.
Authentication: JWT Bearer
Query Parameters: - limit (integer, optional): Nombre d'entrées à vérifier (défaut 100, max 1000)
Response: 200 OK
{
"checked": 0,
"valid": 0,
"invalid": 0,
"message": "Use verify-batch endpoint for actual verification"
}
GET /v1/audit/proof/dlq/stats¶
Statistiques DLQ (Dead Letter Queue).
Authentication: JWT Bearer
Response: 200 OK
Référence: PD-37 E-03
GET /v1/audit/proof/dlq/alerts¶
Vérifier alertes DLQ.
Authentication: JWT Bearer
Response: 200 OK
POST /v1/audit/proof/dlq/retry¶
Déclencher retry DLQ pour entrées en attente.
Authentication: JWT Bearer
Query Parameters: - batchSize (integer, optional): Nombre max d'entrées à traiter (défaut 50, max 200)
Response: 200 OK
Notes: - Appelé par Flow Prefect toutes les 15 minutes
POST /v1/audit/proof/dlq/:id/retry¶
Retry manuel d'une entrée DLQ spécifique.
Authentication: JWT Bearer
Parameters: - id (UUID): ID de l'entrée DLQ
Query Parameters: - by (string, optional): Qui déclenche le retry
Response: 200 OK
POST /v1/audit/proof/dlq/:id/abandon¶
Abandonner une entrée DLQ (marquer comme irrécupérable).
Authentication: JWT Bearer
Parameters: - id (UUID): ID de l'entrée DLQ
Query Parameters: - reason (string, optional): Raison de l'abandon - by (string, optional): Qui abandonne
Response: 200 OK
Jobs asynchrones¶
Gestion des jobs asynchrones via BullMQ + Redis.
Référence: PD-21 Architecture: Orchestration Prefect
POST /v1/jobs¶
Soumettre un nouveau job pour traitement asynchrone.
Authentication: JWT Bearer
Request Body:
{
"type": "EMAIL_VALIDATION",
"payload": {
"email": "user@example.com",
"token": "validation_token"
}
}
Response: 202 Accepted
{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "PENDING",
"submittedAt": "2025-01-02T10:30:00.000Z"
}
Notes: - Retour immédiat sans attendre l'exécution (INV-1: Non-blocage) - Job enqueued pour traitement par worker
Erreurs: - 400: Type de job ou payload invalide - 503: Queue indisponible
GET /v1/jobs/:jobId¶
Récupérer le statut d'un job par ID.
Authentication: JWT Bearer
Parameters: - jobId (UUID): ID du job
Response: 200 OK
{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"type": "EMAIL_VALIDATION",
"status": "COMPLETED",
"submittedAt": "2025-01-02T10:30:00.000Z",
"completedAt": "2025-01-02T10:30:05.000Z",
"result": {
"success": true
}
}
Notes: - Implémente CA-3: Traçabilité consultable
Erreurs: - 404: Job non trouvé
GET /v1/jobs/failed¶
Lister les jobs échoués (pour Flow Prefect retry).
Authentication: JWT Bearer
Query Parameters: - retryable (boolean, optional): Filtrer par statut retryable - jobType (string, optional): Filtrer par type de job - since (date, optional): Jobs échoués depuis cette date - limit (integer, optional): Nombre max de jobs à retourner
Response: 200 OK
{
"jobs": [
{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"type": "EMAIL_VALIDATION",
"status": "FAILED",
"failedAt": "2025-01-02T10:30:00.000Z",
"error": "SMTP connection timeout",
"retryable": true
}
],
"total": 1
}
Notes: - Utilisé par jobs_dlq_retry_flow.py
POST /v1/jobs/:jobId/retry¶
Retry d'un job échoué.
Authentication: JWT Bearer
Parameters: - jobId (UUID): ID du job à retry
Response: 202 Accepted
{
"jobId": "660e9511-f39c-23e4-b827-557766551111",
"originalJobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "PENDING",
"retryCount": 1,
"submittedAt": "2025-01-02T10:35:00.000Z"
}
Notes: - Crée un nouveau job avec compteur de retry incrémenté - Job original marqué RETRIED
Erreurs: - 404: Job non trouvé - 400: Job non retryable, max retries atteint, ou statut invalide
GET /v1/jobs/stats¶
Statistiques jobs pour monitoring.
Authentication: JWT Bearer
Response: 200 OK
{
"pending": 10,
"active": 5,
"completed": 1000,
"failed": 20,
"retried": 15,
"totalProcessed": 1035
}
Notes: - Utilisé par Prefect pour monitoring et alerting
GET /v1/jobs/purgeable¶
Lister les jobs éligibles pour purge.
Authentication: JWT Bearer
Query Parameters: - olderThan (string, optional): Seuil d'âge (ex: "30d", "7d")
Response: 200 OK
{
"jobs": [
{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"type": "EMAIL_VALIDATION",
"status": "COMPLETED",
"completedAt": "2024-12-01T10:30:00.000Z"
}
],
"total": 1
}
Notes: - Utilisé par jobs_purge_flow.py pour preview
DELETE /v1/jobs/purge¶
Purger les jobs anciens selon politique de rétention.
Authentication: JWT Bearer
Query Parameters: - target (enum: db | redis, optional): Cible de purge - olderThan (string, optional): Seuil d'âge (ex: "30d" pour DB, "7d" pour Redis) - dryRun (boolean, optional): Mode preview (affiche ce qui serait purgé)
Response: 200 OK
Notes: - Implémente I-5: Politique de rétention formelle
Synchronisation multi-device¶
Synchronisation d'objets avec détection et résolution de conflits.
Référence: PD-171 Architecture: Détection conflits, résolution automatique, journalisation probatoire
POST /v1/sync¶
Synchroniser un objet existant.
Authentication: JWT Bearer Guards: DeviceAuthGuard, SchemaVersionGuard Interceptors: SyncAuditInterceptor
Request Body:
{
"objectId": "550e8400-e29b-41d4-a716-446655440000",
"version": 2,
"baseVersion": 1,
"delta": {
"field1": "new_value"
}
}
Response: 200 OK (sans conflit)
Response: 409 Conflict (avec conflit)
{
"status": "CONFLICT",
"objectId": "550e8400-e29b-41d4-a716-446655440000",
"conflictType": "CONCURRENT_MODIFICATION",
"serverVersion": 3,
"clientVersion": 2
}
Notes: - Flux N1 (sans conflit) ou N2 (avec conflit) - Résolution automatique selon règles configurées
Erreurs: - 404: Objet non trouvé
POST /v1/sync/create¶
Créer un nouvel objet synchronisé.
Authentication: JWT Bearer Guards: DeviceAuthGuard, SchemaVersionGuard
Request Body:
Response: 201 Created
Erreurs: - 409: Objet existe déjà
GET /v1/sync/:objectId¶
Récupérer l'état canonique d'un objet.
Authentication: JWT Bearer Guards: DeviceAuthGuard
Parameters: - objectId (UUID): ID de l'objet
Response: 200 OK
{
"objectId": "550e8400-e29b-41d4-a716-446655440000",
"version": 3,
"data": {
"field1": "value1"
},
"lastModifiedAt": "2025-01-02T10:30:00.000Z"
}
Erreurs: - 404: Objet non trouvé
GET /v1/sync¶
Lister les objets de l'utilisateur.
Authentication: JWT Bearer Guards: DeviceAuthGuard
Query Parameters: - includeDeleted (boolean, optional): Inclure objets supprimés
Response: 200 OK
{
"objects": [
{
"objectId": "550e8400-e29b-41d4-a716-446655440000",
"version": 3,
"lastModifiedAt": "2025-01-02T10:30:00.000Z"
}
],
"total": 1
}
GET /v1/sync/:objectId/history¶
Récupérer l'historique complet des versions.
Authentication: JWT Bearer Guards: DeviceAuthGuard
Parameters: - objectId (UUID): ID de l'objet
Response: 200 OK
{
"objectId": "550e8400-e29b-41d4-a716-446655440000",
"history": [
{
"id": "version_id_1",
"version": 1,
"baseVersion": null,
"status": "APPLIED",
"conflictType": null,
"ruleApplied": null,
"syncRequestId": "sync_req_1",
"deviceId": "device_1",
"timestamp": "2025-01-02T10:00:00.000Z"
},
{
"id": "version_id_2",
"version": 2,
"baseVersion": 1,
"status": "APPLIED",
"conflictType": null,
"ruleApplied": null,
"syncRequestId": "sync_req_2",
"deviceId": "device_2",
"timestamp": "2025-01-02T10:30:00.000Z"
}
]
}
Notes: - Historique complet pour audit (§5.8)
Erreurs: - 404: Objet non trouvé
GET /v1/sync/:objectId/export¶
Exporter objet pour audit (format canonique RFC 8785).
Authentication: JWT Bearer Guards: DeviceAuthGuard
Parameters: - objectId (UUID): ID de l'objet
Response: 200 OK
{
"object_id": "550e8400-e29b-41d4-a716-446655440000",
"exported_at": "2025-01-02T10:30:00.000Z",
"canonical_version": 3,
"history": [
{
"version": 1,
"timestamp": "2025-01-02T10:00:00.000Z",
"device_id": "device_1"
}
]
}
Notes: - Export en JSON canonique (§5.10) - Vérifiable indépendamment
Erreurs: - 404: Objet non trouvé
Codes d'erreur¶
Codes HTTP standards¶
| Code | Signification | Usage |
|---|---|---|
| 200 | OK | Requête réussie |
| 201 | Created | Ressource créée avec succès |
| 202 | Accepted | Requête acceptée (traitement asynchrone) |
| 204 | No Content | Requête réussie, pas de contenu retourné |
| 400 | Bad Request | Données invalides |
| 401 | Unauthorized | Non authentifié |
| 403 | Forbidden | Non autorisé (permissions insuffisantes) |
| 404 | Not Found | Ressource non trouvée |
| 409 | Conflict | Conflit (doublon, état invalide) |
| 410 | Gone | Ressource expirée |
| 429 | Too Many Requests | Rate limit dépassé |
| 500 | Internal Server Error | Erreur serveur |
| 503 | Service Unavailable | Service indisponible |
Format des erreurs¶
{
"statusCode": 400,
"message": "Invalid email format",
"error": "Bad Request",
"timestamp": "2025-01-02T10:30:00.000Z",
"path": "/v1/auth/register"
}
Notes de sécurité¶
Architecture Zero-Knowledge¶
- Le mot de passe n'est jamais envoyé au serveur
- Authentification SRP-6a avec salt + verifier
- Métadonnées documents chiffrées AES-256-GCM côté client
Isolation des données¶
- RLS (Row Level Security) PostgreSQL
- Filtre automatique par
user_id - Guards NestJS pour contrôle d'accès supplémentaire
Rate Limiting¶
- Protection anti-automatisation sur endpoints sensibles
- Quotas configurables par plan utilisateur
Audit & Compliance¶
- Journalisation probatoire de toutes les actions critiques
- Signatures HSM pour preuves vérifiables
- Conformité NF Z42-013, ISO 14641, RGPD
Endpoints manquants (roadmap)¶
Selon EPIC PD-192, ces endpoints sont prévus mais non implémentés :
POST /v1/documents/upload(upload complet intégré)GET /v1/documents/:id/download(download sécurisé)PUT /v1/documents/:id/metadata(mise à jour métadonnées)POST /v1/documents/search(recherche avancée)GET /v1/documents/:id/proof(preuve probatoire spécifique document)POST /v1/documents/:id/share(partage PRE/délégation)- Versioning documents (PD-69)
Ressources¶
- Swagger UI:
http://localhost:3000/api/docs(développement) - TypeDoc:
/docs/reference/typedoc/backend/ - EPIC Docs-API:
/docs/epics/docs-api/PD-192-epic.md - Architecture: Architecture Executive ProbatioVault v4.x
Dernière mise à jour: 2026-01-05 Généré automatiquement par: Claude Code