PD-72 — Expression de besoin¶
1. Titre¶
Créer worker PRE transfert coffre entreprise → salarié
2. Contexte¶
Dans le cas d'usage RH (bulletins de paie probatoires), l'entreprise chiffre le document avec une clé documentaire issue de son espace professionnel (K_docEntreprise). Conformément à l'architecture RH (Architecture Technique v4.1), l'entreprise ne doit pas conserver le contenu lisible après remise au salarié.
Le transfert vers le coffre personnel du salarié doit :
- Maintenir le modèle Zero-Knowledge (le worker ne voit jamais le document en clair)
- Produire une preuve de remise juridiquement opposable
- Journaliser et ancrer l'opération dans la chaîne de preuve composite
- Être révocable jusqu'au scellement final
Ce transfert repose sur le mécanisme Legal PRE (Proxy Re-Encryption) décrit dans la fiche brevet n°803.
3. Objectif¶
Implémenter un worker BullMQ asynchrone qui orchestre le re-chiffrement probatoire d'un document RH du coffre entreprise vers le coffre personnel du salarié. Le worker est un orchestrateur métier RH : il appelle les modules existants sans réimplémenter de primitive cryptographique.
4. Périmètre fonctionnel¶
4.1 Ce que PD-72 implémente¶
| Composant | Description |
|---|---|
Worker BullMQ pre-transfer | Job asynchrone déclenché sur événement DOCUMENT_SEALED |
Entité DocumentTransfer | Nouvelle entité avec machine d'états dédiée |
| Orchestration PRE | Appel au PRE engine (Umbral/PD-41) pour re-chiffrement aveugle |
Événement probatoire TRANSFER_EMPLOYEE | Création, signature HSM, inclusion Merkle |
| Acte de remise signé | Document probatoire (identités, hash, TSA, signature HSM, tx_id) |
| Notification salarié | In-app + email neutre (sans contenu sensible) |
Gestion policy copy / transfer | Enregistrement de la policy RH, déclenchement révocation si transfer |
4.2 Ce que PD-72 n'implémente PAS (modules existants)¶
| Module | Story source | Rôle |
|---|---|---|
| PRE engine (Umbral) | PD-41 | Re-encryption K_docEntreprise → K_docSalarié |
| HSM signing | module crypto | Signature événements probatoires |
| TSA client | module TSA | Horodatage RFC 3161 |
| Merkle batch | module anchoring | Inclusion dans batch d'ancrage |
| Blockchain anchoring | module anchoring | Ancrage périodique |
| Audit log WORM | module audit | Journal append-only |
| Bundle preuve composite | module preuve | Génération proof_bundle.json |
4.3 Hors scope explicite¶
- UX consentement salarié (futur ticket) — PD-72 suppose
employee_consent = TRUE - Logique cryptographique de révocation complète (module PRE / key lifecycle)
- Format bundle preuve (ProofEnvelope canonical existant)
5. Entité DocumentTransfer¶
5.1 Schéma¶
Document
│
└── DocumentTransfer
├ id (UUID)
├ document_id (FK → Document)
├ status (enum)
├ source_vault_id (FK → Vault entreprise)
├ target_vault_id (FK → Vault salarié)
├ transfer_policy ('copy' | 'transfer')
├ rk_id (identifiant clé de re-chiffrement, nullable post-zeroization)
├ proof_id (FK → Proof, nullable avant création preuve)
├ error_code (nullable)
├ retry_count (default 0)
├ created_at
├ updated_at
└ completed_at (nullable)
5.2 Machine d'états¶
PENDING
↓
READY_FOR_TRANSFER
↓
TRANSFER_IN_PROGRESS
↓
TRANSFERRED
↓
PROOF_PENDING_ANCHOR
↓
ANCHOR_CONFIRMED
En cas d'échec :
FAILED → retry (max 3) → READY_FOR_TRANSFER
BLOCKED_WAITING_CONSENT (si consentement absent)
6. Flux nominal¶
- Déclenchement : Un document RH passe au statut
SEALED→ job BullMQpre-transfercréé - Vérification préconditions :
- Salarié dispose d'un compte ProbatioVault actif
- Clé publique salarié (
PK_encSalarié) disponible et certifiée employee_consent = TRUE- Génération auth_token : Token signé par HSM (modèle Legal PRE)
- Génération clé de re-chiffrement :
rk_Entreprise→Salarié(locale, éphémère) - Re-chiffrement aveugle :
wrap_Salarié = PRE.ReEncrypt(wrap_Entreprise, rk) - Zeroization : Destruction immédiate de
rken mémoire - Événement probatoire : Création
TRANSFER_EMPLOYEEavecdoc_id,employee_id,hash_doc,timestamp,hsm_signature,previous_merkle_root - Signature HSM de l'événement
- Inclusion Merkle batch
- Horodatage TSA RFC 3161
- Ancrage blockchain (périodique, via batch)
- Acte de remise : Génération du document probatoire signé
- Notification salarié : In-app + email neutre
- Policy check : Si
transfer_policy = 'transfer'→ déclencher révocation accès entreprise
7. Exigences fonctionnelles¶
| ID | Exigence | Description |
|---|---|---|
| EF-01 | Re-chiffrement aveugle | PRE engine Umbral (PD-41), le worker ne manipule jamais K_doc en clair |
| EF-02 | Zero-Knowledge absolu | Jamais de déchiffrement, jamais de persistance de rk |
| EF-03 | Journalisation probatoire | Événement append-only : doc_id, employee_id, hash_doc, timestamp, hsm_signature, previous_merkle_root |
| EF-04 | Acte de remise signé | Identité entreprise + salarié, hash document, timestamp TSA, signature HSM, tx_id blockchain |
| EF-05 | Notification sécurisée | In-app + email neutre (sans contenu sensible) |
| EF-06 | Policy copy/transfer | Enregistrement de la policy, déclenchement révocation si transfer |
8. Exigences non fonctionnelles¶
| ID | Exigence | Cible |
|---|---|---|
| ENF-01 | Isolation | Pod isolé, pas d'accès direct S3, accès limité enveloppes HSM |
| ENF-02 | Idempotence | Relance job = pas de double transfert/signature/ancrage |
| ENF-03 | Performance | < 3 secondes par transfert (hors ancrage batch) |
| ENF-04 | Scalabilité | 10k transferts/mois, scaling horizontal BullMQ |
9. Invariants de sécurité (non négociables)¶
| ID | Invariant |
|---|---|
| INV-01 | K_docEntreprise n'est jamais modifiée |
| INV-02 | wrap_Entreprise reste archivée pour preuve historique |
| INV-03 | rk est détruite immédiatement après usage (zeroization mémoire) |
| INV-04 | Le HSM ne détient jamais K_doc |
| INV-05 | Chaque transfert est inclus dans un Merkle root ancré publiquement |
| INV-06 | Aucune copie lisible n'est conservée côté entreprise après transfert (modèle RGPD strict, si policy = transfer) |
| INV-07 | Le worker ne déchiffre jamais le document |
10. Cas d'erreur¶
| Code | Cas | Comportement attendu |
|---|---|---|
| PRE-01 | Salarié sans compte | BLOCKED_WAITING_CONSENT, notification RH |
| PRE-02 | Clé publique invalide | FAILED, alerte sécurité |
| PRE-03 | Signature HSM impossible | FAILED, retry (max 3), escalade si persistant |
| PRE-04 | TSA indisponible | FAILED, retry avec backoff |
| PRE-05 | Blockchain ancrage différé | Non bloquant — PROOF_PENDING_ANCHOR, ancrage au prochain batch |
| PRE-06 | Tentative de replay | Rejet idempotent, log sécurité |
11. Critères d'acceptation¶
- CA-01 : Le salarié peut ouvrir le document via son coffre personnel après transfert
- CA-02 : L'entreprise ne peut plus accéder au contenu si
transfer_policy = 'transfer' - CA-03 : Une preuve composite exportable est générée (ProofEnvelope canonical)
- CA-04 : Vérification offline possible via bundle JSON
- CA-05 : Audit externe valide la chaîne Merkle → TSA → blockchain
- CA-06 : Le worker est idempotent (relance = même résultat, pas de duplication)
- CA-07 : Performance < 3s par transfert (hors ancrage batch)
- CA-08 : Les 7 invariants de sécurité sont respectés
12. Dépendances¶
| Story | Module | Statut |
|---|---|---|
| PD-41 | PRE engine (Umbral) | Implémenté |
| PD-38 | SHA3 hash | Implémenté |
| PD-39 | TSA RFC 3161 | Implémenté |
| PD-55 | Worker ancrage blockchain | Implémenté |
| PD-37 | HSM audit signature | Implémenté |
13. Learnings injectés¶
- crypto.randomUUID() obligatoire pour tout ID aléatoire (PD-63 — Sonar S2245)
- crypto.verify(null, hash, key, sig) pour raw ECDSA HSM — jamais
createVerify()(PD-282 — double-hash) - Centralisation constantes crypto dans
constants.ts(PD-243) - Timing-safe comparison pour tokens de sécurité (PD-238)
- Branded types pour UUIDs sémantiquement distincts (
DocumentTransferId,VaultId,ProofId)
14. Impact stratégique¶
Ce worker est : - Le cœur du modèle RH différenciant - La preuve que l'entreprise ne conserve pas les données personnelles (RGPD) - Un levier majeur ARR B2B
Il concrétise la promesse : "Fusion logique coffre pro / perso, sans duplication, avec séparation probatoire."