ia_dev/projects/lecoffreio/docs/ANCRAGE_COMPLETE.md
Nicolas Cantu 61cec6f430 Sync ia_dev: token resolution via .secrets/<env>/ia_token, doc updates
**Motivations:**
- Align master with current codebase (token from projects/<id>/.secrets/<env>/ia_token)
- Id resolution by mail To or by API token; no slug

**Root causes:**
- Token moved from conf.json to .secrets/<env>/ia_token; env from directory name

**Correctifs:**
- Server and scripts resolve project+env by scanning all projects and envs

**Evolutions:**
- tickets-fetch-inbox routes by To address; notary-ai agents and API doc updated

**Pages affectées:**
- ai_working_help/server.js, docs, project_config.py, lib/project_config.sh
- projects/README.md, lecoffreio/docs/API.md, gitea-issues/tickets-fetch-inbox.py
2026-03-16 15:00:23 +01:00

842 lines
26 KiB
Markdown

# Documentation Complète de l'Ancrage Blockchain - LeCoffre.io
**Dernière mise à jour** : 2025-11-24
**Version** : 3.1.2
Ce document consolide toute la documentation relative à l'ancrage blockchain des documents et dossiers dans LeCoffre.io.
---
## 📋 Table des Matières
1. [Vue d'Ensemble](#1-vue-densemble)
2. [Architecture V3](#2-architecture-v3)
3. [Processus d'Ancrage](#3-processus-dancrage)
4. [Certificats et ZIP](#4-certificats-et-zip)
5. [Vérification et Statuts](#5-vérification-et-statuts)
6. [Scripts et Maintenance](#6-scripts-et-maintenance)
7. [Troubleshooting](#7-troubleshooting)
8. [Références](#8-références)
---
## 1. Vue d'Ensemble
### Évolution des Versions
| Version | Blockchain | Périmètre | Déclenchement | Filigrane | Fallback |
|---------|-----------|-----------|---------------|-----------|----------|
| **V1** | Tezos | Dossiers uniquement | Manuel | ❌ Non | ⚠️ Lecture seule |
| **V2** | Bitcoin Signet | Docs + Dossiers | Auto | ❌ Non | - |
| **V3** | Bitcoin Signet | Docs + Dossiers | Auto | ✅ Oui | ✅ Tezos masqué |
### Nouveautés V3
1. **Filigrane automatique** : "lecoffre.io" sur tous documents
2. **Double version** : Original + filigrané (conservés en BDD)
3. **ZIP enrichi** : Originaux + filigranés + certificats + preuves JSON
4. **Preuves structurées** : JSON standardisé pour vérification externe
5. **Ancrage dossier** : Hash du ZIP complet (pas seulement Merkle tree)
6. **Fallback Tezos** : Accès masqué aux anciens ancrages (lecture seule)
### Principes Fondamentaux
- **Ancrage immédiat** : L'ancrage est déclenché automatiquement lors de la validation d'un document
- **Hash filigrané** : Seule la version filigranée est ancrée sur blockchain
- **Double hash** : Hash original et hash filigrané sont stockés pour vérification
- **Preuve on-chain** : Le `tx_id` (transaction ID Bitcoin) est la seule preuve fiable d'ancrage
---
## 2. Architecture V3
### Services Backend
#### WatermarkService
**Fichier** : `lecoffre-back-main/src/services/common/WatermarkService/WatermarkService.ts`
**Responsabilités** :
- Conversion documents → PDF (si nécessaire)
- Ajout filigrane "lecoffre.io" (diagonal, 15% opacité)
- Upload version filigranée vers S3/IPFS
- Gestion formats : PDF, images, Word, PowerPoint
**Méthodes principales** :
```typescript
async addWatermarkAndUpload(fileUid: string): Promise<{
watermarkedS3Key: string;
watermarkedSize: number;
watermarkedMimetype: string;
}>
```
#### DocumentAnchorsService
**Fichier** : `lecoffre-back-main/src/services/notary/DocumentAnchorsService/DocumentAnchorsService.ts`
**Workflow d'ancrage** :
1. Vérification ancrage Tezos existant (fallback)
2. Génération version filigranée si absente
3. Calcul hash version filigranée
4. Vérification ancrage Signet existant
5. Création ancrage `QUEUED`
6. Ancrage blockchain Bitcoin Signet
7. Génération `proof_data` (incluant fallback Tezos)
8. Mise à jour ancrage avec `tx_id`
**Méthodes principales** :
```typescript
async anchorDocument(documentUid: string, anchoredByUid?: string): Promise<DocumentAnchors>
async getByDocumentUid(documentUid: string): Promise<DocumentAnchors | null>
async getByFileHash(fileHash: string): Promise<DocumentAnchors | null>
```
#### OfficeFolderAnchorsService
**Fichier** : `lecoffre-back-main/src/services/notary/OfficeFolderAnchorsService/OfficeFolderAnchorsService.ts`
**Workflow d'ancrage dossier** :
1. Récupération tous documents validés
2. Génération filigranes manquants
3. Génération ZIP complet dossier
4. Upload ZIP vers S3
5. Ancrage hash ZIP complet
6. Génération preuve dossier
**Structure ZIP** :
```text
dossier_12345678/
├── _LISEZ-MOI.txt
├── 01_originaux/
├── 02_filigranes/
├── 03_certificats/
└── 04_preuves/
```
#### ProofDataService
**Fichier** : `lecoffre-back-main/src/services/notary/ProofDataService/ProofDataService.ts`
**Responsabilités** :
- Génération JSON de preuve d'ancrage
- Format standard pour vérification externe
- Inclusion toutes données blockchain
**Structure JSON** :
```json
{
"version": "3.0.0",
"timestamp": "2025-10-29T16:30:00.000Z",
"document": {
"uid": "abc123...",
"name": "Acte de vente",
"original_hash": "e3b0c442...",
"watermarked_hash": "5feceb66..."
},
"anchor": {
"blockchain": "BITCOIN_SIGNET",
"status": "VERIFIED_ON_CHAIN",
"txid": "a1b2c3d4...",
"tx_link": "https://mempool.4nkweb.com/signet/tx/a1b2c3d4...",
"block_height": 123456,
"confirmations": 6
},
"tezos_fallback": {
"legacy": true,
"blockchain": "TEZOS",
"txid": "old_tezos_tx..."
}
}
```
#### BitcoinSignetService
**Fichier** : `lecoffre-back-main/src/services/common/BitcoinSignetService/BitcoinSignetService.ts`
**Responsabilités** :
- Ancrage hash sur Bitcoin Signet
- Vérification statut transaction
- Récupération métadonnées blockchain
**Méthodes principales** :
```typescript
async anchorHash(hash: string): Promise<{
txid: string;
tx_hash: string;
tx_link: string;
}>
async verifyAnchor(txId: string): Promise<{
confirmed: boolean;
confirmations: number;
block_height: number;
}>
```
### Base de Données
#### Schéma Prisma
**Table `files`** :
```prisma
model Files {
uid String @id @unique @default(uuid())
file_name String
s3_key String?
// V3 : Version filigranée
watermarked_s3_key String?
watermarked_at DateTime?
original_hash String? // Hash fichier original
document_uid String?
document Documents? @relation(...)
}
```
**Table `document_anchors`** :
```prisma
model DocumentAnchors {
uid String @id @unique @default(uuid())
document_uid String @unique
// Hash de la version FILIGRANNÉE (V3)
file_hash String
blockchain EBlockchainName @default(BITCOIN_SIGNET)
status EAnchoringStatus @default(QUEUED)
// Données blockchain
tx_id String? // ⚠️ CRITIQUE : Seul indicateur fiable
tx_link String?
tx_hash String?
block_height Int?
block_time DateTime?
confirmations Int?
// V3 : Données de preuve (JSON)
proof_data Json?
anchored_at DateTime?
anchored_by_uid String?
}
```
**Table `office_folder_anchors`** :
```prisma
model OfficeFolderAnchors {
uid String @id @unique @default(uuid())
// Hashs sources (Merkle tree)
root_hash String
// V3 : ZIP complet
zip_hash String?
zip_s3_key String?
zip_size Float?
blockchain EBlockchainName @default(BITCOIN_SIGNET)
status EAnchoringStatus @default(QUEUED)
// Données blockchain
tx_id String? // ⚠️ CRITIQUE : Seul indicateur fiable
tx_link String?
tx_hash String?
block_height Int?
confirmations Int?
// V3 : Données de preuve (JSON)
proof_data Json?
}
```
**Enums** :
```prisma
enum EBlockchainName {
TEZOS // ⚠️ Conservé pour fallback (lecture seule)
BITCOIN_SIGNET
}
enum EAnchoringStatus {
QUEUED // ⚠️ OBSOLÈTE : Non utilisé de manière fiable
ATTEMPTING // ⚠️ OBSOLÈTE : Non utilisé de manière fiable
VERIFIED_ON_CHAIN // ⚠️ OBSOLÈTE : Le système se base uniquement sur tx_id
FAILED
ABANDONED
}
```
**⚠️ IMPORTANT** : Le champ `status` n'est plus utilisé de manière fiable. Le système vérifie uniquement la présence de `tx_id` :
- `tx_id` présent = Ancrage réussi
- `tx_id` absent = Ancrage non effectué
---
## 3. Processus d'Ancrage
### Séquence de Traitement (Upload)
Pour **tous les documents** (Client, Tiers, Notaire invité, Notaire), la séquence est :
1. **Calcul hash original** (fichier original)
2. **Filigrane** (sur fichier original non chiffré)
3. **Calcul hash filigrané et ancrage blockchain** (hash filigrané, génération txid)
4. **Chiffrement** du document filigrané
5. **Upload IPFS** du document chiffré
6. **Stockage métadonnées** fichier (hash original + hash filigrané)
7. **Stockage certificat BDD** (document_anchor avec hash filigrané + hash original + txid)
### Ancrage Automatique lors de la Validation
**Déclenchement** : Lors de la validation d'un document via `PUT /api/v1/notary/documents/:uid`
**Fichier** : `lecoffre-back-main/src/app/api/notary/DocumentsController.ts`
**Workflow** :
```typescript
if (documentEntityUpdated.document_status === EDocumentStatus.VALIDATED && firstFileUid) {
// Ancrage automatique (asynchrone, non bloquant)
if (userUid) {
void this.documentAnchorsService
.anchorDocument(documentEntityUpdated.uid, userUid)
.then((anchor) => {
SafeLogger.info(`✅ Document ${documentEntityUpdated.uid} automatically anchored`);
})
.catch((error) => {
SafeLogger.error(`❌ Auto-anchoring failed: ${error}`);
});
}
}
```
**Points importants** :
- ✅ L'ancrage est **asynchrone** (non bloquant)
- ✅ L'ancrage est lancé en **arrière-plan**
- ✅ Si l'ancrage échoue, le document reste validé
### Ancrage Document
**Workflow détaillé** :
1. **Récupération document + fichier**
2. **Vérification ancrage Tezos existant** (fallback)
3. **Génération version filigranée** si absente
4. **Téléchargement version filigranée** et calcul hash
5. **Vérification ancrage Signet existant**
6. **Création ancrage `QUEUED`**
7. **Ancrage blockchain** via `BitcoinSignetService.anchorHash()`
8. **Génération `proof_data`** (incluant fallback Tezos)
9. **Mise à jour ancrage** avec `tx_id`, `tx_link`, `proof_data`
### Ancrage Dossier
**Workflow détaillé** :
1. **Récupération tous documents validés** du dossier
2. **Génération filigranes manquants** pour tous documents
3. **Génération ZIP complet** du dossier :
- Originaux (01_originaux/)
- Filigranés (02_filigranes/)
- Certificats (03_certificats/)
- Preuves JSON (04_preuves/)
4. **Upload ZIP vers S3**
5. **Ancrage hash ZIP complet** sur blockchain
6. **Génération preuve dossier**
7. **Création/Mise à jour ancrage dossier**
**Condition** : Le dossier doit être à **100% de complétion** (tous documents validés)
---
## 4. Certificats et ZIP
### Génération Automatique de Certificats
#### Téléchargement Individuel (Document Validé et Ancré)
**Endpoints** :
- Notaire : `GET /api/v1/notary/files/download/:uid`
- Client : `GET /api/v1/customer/files/download/:uid`
**Comportement automatique** : Pour les documents validés (`VALIDATED`) et ancrés avec statut `VERIFIED_ON_CHAIN`, le téléchargement génère **automatiquement** un ZIP contenant :
1. **PDF filigrané** : Document avec filigrane appliqué (suffixe `_aplc.pdf`)
2. **Certificat d'ancrage** : Certificat PDF Bitcoin Signet (préfixe `certificat_`)
**Exemple de ZIP** :
```text
document_001_CNI_DUPONT_Jean_avec_certificat.zip
├── 001_CNI_DUPONT_Jean_aplc.pdf (PDF filigrané)
└── certificat_001_CNI_DUPONT_Jean.pdf (Certificat d'ancrage)
```
#### Téléchargement Multiple (ZIP de Fichiers)
**Service** : `ZipService.createZipFromFiles()`
**Workflow de recherche d'ancrage** :
1. **PRIORITÉ** : Recherche par `document_uid` (plus fiable)
2. **FALLBACK** : Si pas trouvé, recherche par hash du fichier
3. **Vérification statut** : Le certificat n'est généré que si `status === VERIFIED_ON_CHAIN`
#### Téléchargement Dossier Complet
**Service** : `OfficeFolderAnchorsService.generateFolderZip()`
**Structure ZIP** :
```text
dossier_12345678_Acte_de_vente/
├── _LISEZ-MOI.txt (Instructions vérification)
├── 01_originaux/
│ ├── acte_vente.pdf (Version originale)
│ └── compromis_vente.pdf
├── 02_filigranes/
│ ├── acte_vente.pdf (⚠️ VERSION ANCRÉE avec filigrane)
│ └── compromis_vente.pdf
├── 03_certificats/
│ ├── certificat_acte_vente.pdf (PDF certif blockchain)
│ └── certificat_compromis_vente.pdf
└── 04_preuves/
├── preuve_acte_vente.json (JSON avec hashs + TX)
└── preuve_compromis_vente.json
```
### Contenu des Certificats PDF
**Informations affichées** :
1. **Hashs complets** :
- Empreinte SHA-256 (original) : Hash complet du document initial (64 caractères hex)
- Empreinte SHA-256 (filigrané) : Hash complet du document avec filigrane (64 caractères hex)
- Source : `proof_data.document.original_hash` et `proof_data.document.watermarked_hash`
2. **Lien de transaction** :
- Format : `https://mempool.4nkweb.com/fr/tx/<txid>`
- Construit automatiquement à partir de `anchor.tx_id` si disponible
- Fallback sur `anchor.tx_link` si `tx_id` absent
3. **Autres informations** :
- Identifiant unique du document
- Informations du dossier (numéro, nom)
- Informations de l'office notarial
- Type de document
- Déposant
- Validateur (UID)
- Nom de fichier normé
- Blockchain utilisée (Bitcoin Signet Notaires)
- Statut d'ancrage
- ID de transaction
- Hauteur de bloc (si disponible)
- Date d'ancrage
### Filigrane Visuel
**Spécifications** :
- **Texte** : "lecoffre.io"
- **Position** : Diagonal (45°), centré sur chaque page
- **Opacité** : 15% (visible mais non gênant)
- **Couleur** : Gris clair (#CCCCCC)
- **Police** : Arial, 48pt
- **Pages** : Toutes les pages du PDF
---
## 5. Vérification et Statuts
### Logique de Vérification
**⚠️ IMPORTANT** : Le système d'ancrage V3 ne fonctionne plus avec des statuts intermédiaires. L'ancrage est maintenant **immédiat** :
-**Ancré** : L'ancrage a un `tx_id` (transaction ID Bitcoin)
-**Non ancré** : L'ancrage n'a pas de `tx_id`
**Il n'y a plus d'étape intermédiaire** comme `ATTEMPTING`, `QUEUED`, ou `VERIFYING_ON_CHAIN`.
### Backend
Le backend vérifie uniquement la présence de `tx_id` :
```typescript
if (anchorStatus.tx_id) {
setAnchorStatus(AnchorStatus.VERIFIED_ON_CHAIN);
} else {
setAnchorStatus(AnchorStatus.NOT_ANCHORED);
}
```
### Frontend
Le frontend utilise l'enum `AnchorStatus` mais ne vérifie que `tx_id` :
```typescript
export enum AnchorStatus {
"VERIFIED_ON_CHAIN" = "VERIFIED_ON_CHAIN",
"NOT_ANCHORED" = "NOT_ANCHORED",
}
// Vérification
if (anchorStatus.tx_id) {
setAnchorStatus(AnchorStatus.VERIFIED_ON_CHAIN);
} else {
setAnchorStatus(AnchorStatus.NOT_ANCHORED);
}
```
### Masquage du Statut "Ancrage en cours"
**Objectif** : Améliorer l'expérience utilisateur en ne montrant pas le statut transitoire "Ancrage en cours" pour les documents validés.
**Comportement** : Pour les documents avec `document_status === VALIDATED`, le statut "Ancrage en cours" (`ATTEMPTING`) n'est **pas affiché** dans l'interface utilisateur.
**Composant `AnchorBadge`** :
```typescript
if (documentStatus === "VALIDATED" && status === "ATTEMPTING") {
return null; // Badge not displayed
}
```
### Vérification Publique
**Endpoints** :
- `GET /api/v1/public/verify/:hash` : Vérification par hash (SANS authentification)
- `POST /api/v1/public/verify-file` : Vérification par upload fichier (SANS authentification)
**Page frontend** : `/verify-document`
**Fonctionnalités** :
- Upload fichier (drag & drop ou sélection)
- Calcul hash automatique (SHA256)
- Appel API public (aucune authentification requise)
- Affichage résultat (success/error)
- Lien explorateur blockchain
### Procédure de Vérification
**Pour utilisateur final** :
1. Télécharger ZIP complet du dossier
2. Extraire le ZIP
3. Ouvrir fichier dans `04_preuves/preuve_XXX.json`
4. Noter le `watermarked_hash`
5. Calculer hash du fichier dans `02_filigranes/` :
```bash
shasum -a 256 02_filigranes/acte_vente.pdf
```
6. Comparer les deux hashs (doivent être identiques)
7. Vérifier TX : Ouvrir `tx_link` du JSON dans navigateur
8. ✅ **Validé** si hash OK + TX confirmée sur blockchain
**Pour audit technique** :
1. Parser JSON de preuve
2. Extraire `watermarked_hash`, `txid`, `block_height`
3. Requête API blockchain (Mempool Space) :
```bash
curl https://mempool.4nkweb.com/signet/api/tx/{txid}
```
4. Vérifier :
- TX existe
- Hash dans OP_RETURN correspond
- Block confirmé
5. Recalculer hash fichier filigrané
6. Comparer avec `watermarked_hash`
7. ✅ **Preuve authentique** si tout correspond
---
## 6. Scripts et Maintenance
### Scripts Disponibles
#### Audit des Ancrages Manquants
**Script** : `audit-missing-anchors.js`
**Usage** :
```bash
ENV=prod npm run anchorage:audit
```
**Description** :
- Analyse tous les documents validés sans ancrage
- Analyse tous les dossiers archivés sans ancrage
- Génère un CSV avec la liste des documents/dossiers à réancrer
- Ne modifie aucune donnée (lecture seule)
**Résultat** :
- Affichage console avec statistiques
- CSV généré : `logs/audit-missing-anchors_YYYYMMDD_HHMMSS.csv`
#### Ancrage V3 de Dossiers Existants
**Script** : `anchor-existing-folders-v3.js`
**Usage** :
```bash
# Ancrage tous dossiers LIVE + ARCHIVED (par défaut)
ENV=prod npm run anchorage
# Dry-run (simulation)
ENV=prod npm run anchorage -- --all --batch=1 --dry-run
# Ancrage réel avec limite batch
ENV=prod npm run anchorage -- --all --batch=5
# Ancrage de dossiers spécifiques
ENV=prod npm run anchorage -- --folder-uids=uid1,uid2,uid3
```
**Options** :
- `--all-archived` : Tous les dossiers ARCHIVED sans ancrage
- `--all-validated` : Tous les dossiers VALIDATED sans ancrage
- `--all` : Tous les dossiers VALIDATED + ARCHIVED
- `--folder-uids=uid1,uid2,...` : Liste UIDs dossiers spécifiques
- `--batch=N` : Nombre max de dossiers par batch (défaut: 10)
- `--dry-run` : Simulation sans ancrage réel
- `--skip-documents` : Ancrer seulement dossiers (pas documents individuels)
#### Vérifications Systématisées des Colonnes d'Ancrage
Depuis 2025-01-XX, les scripts de déploiement vérifient systématiquement la présence des colonnes indispensables pour l'ancrage avant d'exécuter le réancrage.
**Colonnes vérifiées** :
- `document_anchors.proof_data` (JSONB) - Données de preuve structurées
- `document_anchors.confirmations` (INTEGER) - Nombre de confirmations blockchain
- `document_anchors.anchor_job_id` (VARCHAR) - ID du job d'ancrage
- `document_notary_anchors.proof_data` (JSONB) - Données de preuve structurées
- `document_notary_anchors.confirmations` (INTEGER) - Nombre de confirmations blockchain
**Garanties** :
- ✅ Vérification de l'existence des tables avant toute modification
- ✅ Ajout automatique des colonnes manquantes (8 points de vérification)
- ✅ Blocage du réancrage si colonnes manquantes détectées
- ✅ Messages d'erreur explicites indiquant les colonnes manquantes
**Ordre d'exécution garanti** :
```text
resetDatabase → migrateResolveDatabase → reanchorAll
↓ ↓ ↓
Base vide Colonnes ajoutées Vérification finale
↓ ↓
Si manquantes → Blocage si manquantes
```
📖 Voir [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) et [DEPLOYMENT.md](./DEPLOYMENT.md) pour les corrections sur les colonnes d'ancrage.
#### Réancrage de Documents/Dossiers
**Script** : `reanchor-documents.js`
**Usage** :
```bash
# Dry-run (simulation)
ENV=prod npm run anchorage:reanchor -- --dry-run
# Réancrage réel
ENV=prod npm run anchorage:reanchor -- --document-uids=uid1,uid2
```
**Options** :
- `--document-uids=uid1,uid2,...` : Liste UIDs documents spécifiques
- `--folder-uids=uid1,uid2,...` : Liste UIDs dossiers spécifiques
- `--all-missing` : Réancrer TOUS les documents/dossiers sans ancrage (⚠️)
- `--batch=N` : Nombre max de documents/dossiers par batch (défaut: 50)
- `--dry-run` : Simulation sans ancrage réel
#### Nettoyage Ancres Dossiers Incomplets
**Script** : `clean-incomplete-folder-anchors.ts`
**Contexte** :
- Certains dossiers peuvent avoir été ancrés alors qu'ils n'étaient pas à 100%
- Seuls les dossiers complets (100% documents validés) doivent être ancrés
**Usage** :
```bash
# Depuis le conteneur backend
cd lecoffre-back-main
npx ts-node src/scripts/clean-incomplete-folder-anchors.ts --dry-run
npx ts-node src/scripts/clean-incomplete-folder-anchors.ts
```
**Actions** :
- Identifie les dossiers ancrés avec complétion < 100%
- Supprime les ancres correspondantes dans `office_folder_anchors`
- Réinitialise les liens `folder_anchor_uid = NULL` dans `office_folders`
### ⚠️ IMPORTANT : Prérequis
1. **Colonnes V3** : La base doit avoir toutes les colonnes V3 (`watermarked_s3_key`, `watermarked_at`, `zip_hash`, `zip_s3_key`, `zip_size`, `proof_data`)
2. **Prisma Client** : Le client Prisma doit être généré avec le bon schéma
3. **Connexion BDD** : Les scripts utilisent `DATABASE_URL` (configurée sur le serveur ou via `.env.<env>`)
### Workflow Recommandé
1. **Audit initial** :
```bash
ENV=prod npm run anchorage:audit
```
2. **Test avec dry-run** :
```bash
ENV=prod npm run anchorage -- --all-archived --batch=1 --dry-run
```
3. **Ancrage réel** :
```bash
ENV=prod npm run anchorage -- --all-archived --batch=5
```
---
## 7. Troubleshooting
### Certificats Manquants dans le ZIP
**Symptôme** : Lors de la validation d'un document, le document apparaît comme validé, mais le certificat d'ancrage n'est pas présent dans le ZIP téléchargé.
**Root Cause** :
1. Recherche par hash uniquement (peut échouer)
2. Pas de vérification du statut avant génération
**Solution** :
1. Recherche prioritaire par `document_uid` (plus fiable)
2. Fallback par hash si nécessaire
3. Vérification du statut (`status === VERIFIED_ON_CHAIN`) avant génération
### Timing et Synchronisation
**Scénario typique** :
1. **T0** : Document validé → Ancrage lancé en arrière-plan
2. **T0+2s** : Ancrage créé avec `status = ATTEMPTING`
3. **T0+5s** : Transaction Bitcoin confirmée → `status = VERIFIED_ON_CHAIN` (après 6 confirmations)
4. **T0+10s** : Utilisateur télécharge le ZIP → Certificat inclus ✅
**Cas limite** : Si l'utilisateur télécharge le ZIP **immédiatement après validation** (avant que l'ancrage soit vérifié) :
- ⚠️ L'ancrage peut être en statut `ATTEMPTING` ou `QUEUED`
- ⚠️ Le certificat **ne sera pas inclus** dans le ZIP
- ✅ L'utilisateur peut **relancer le téléchargement** plus tard pour obtenir le certificat
### Fichiers Sans Clé de Chiffrement (.expired)
**Contexte** : Les dumps de base de données provenant de versions antérieures peuvent contenir des fichiers avec `key = null` (clé de chiffrement perdue).
**Solution implémentée** :
- `FilesService.download()` : Retourne fichier vide `.expired` si `key = null`
- `WatermarkService.addWatermarkAndUpload()` : Upload fichier vide `.expired` sur IPFS
- `DocumentAnchorsService.anchorDocument()` : Ancrage avec hash du buffer vide
**Résultat** :
- ✅ Scripts d'ancrage ne crashent plus sur fichiers sans clé
- ✅ Fichiers `.expired` créés automatiquement
- ✅ Ancrage blockchain avec hash du buffer vide
- ⚠️ Utilisateur informé que fichier non récupérable
### Checklist de Vérification
Pour diagnostiquer un problème de certificat manquant dans un ZIP :
- [ ] Vérifier que le document est **validé** (`document_status === VALIDATED`)
- [ ] Vérifier qu'un ancrage existe pour ce document (`document_anchors` table)
- [ ] Vérifier le **statut de l'ancrage** (`status === VERIFIED_ON_CHAIN`)
- [ ] Vérifier les **logs backend** pour voir si l'ancrage a été trouvé
- [ ] Vérifier que `includeAnchors = true` lors de l'appel à `createZipFromFiles`
- [ ] Vérifier que le fichier n'est pas un `isNotaryFiles` (pas d'ancrage pour les fichiers notaire)
---
## 8. Références
### Documentation Détaillée
- **Architecture V3** : `docs/ANCRAGE_V3_ARCHITECTURE.md` - Architecture complète V3
- **Certificats et ZIP** : `docs/ANCRAGE_CERTIFICATS_ZIP.md` - Génération certificats et ZIP
- **Scripts** : `docs/SCRIPTS.md` - Scripts d'audit et d'ancrage
- **Statuts** : `docs/ANCHOR_STATUS_VERIFICATION.md` - Vérification des statuts d'ancrage
- **Séquences de traitement** : `docs/DOCUMENT_PROCESSING_SEQUENCES_V2.md` - Séquence complète upload/ancrage
### Services Backend
- **WatermarkService** : `lecoffre-back-main/src/services/common/WatermarkService/WatermarkService.ts`
- **DocumentAnchorsService** : `lecoffre-back-main/src/services/notary/DocumentAnchorsService/DocumentAnchorsService.ts`
- **OfficeFolderAnchorsService** : `lecoffre-back-main/src/services/notary/OfficeFolderAnchorsService/OfficeFolderAnchorsService.ts`
- **ProofDataService** : `lecoffre-back-main/src/services/notary/ProofDataService/ProofDataService.ts`
- **BitcoinSignetService** : `lecoffre-back-main/src/services/common/BitcoinSignetService/BitcoinSignetService.ts`
- **AnchorCertificateService** : `lecoffre-back-main/src/services/notary/AnchorCertificateService/AnchorCertificateService.ts`
- **ZipService** : `lecoffre-back-main/src/services/common/ZipService/ZipService.ts`
### Controllers
- **DocumentsController** : `lecoffre-back-main/src/app/api/notary/DocumentsController.ts`
- **FilesController (Notary)** : `lecoffre-back-main/src/app/api/notary/FilesController.ts`
- **FilesController (Customer)** : `lecoffre-back-main/src/app/api/customer/FilesController.ts`
- **PublicAnchorVerificationController** : `lecoffre-back-main/src/app/api/public/PublicAnchorVerificationController.ts`
### Scripts
- **Audit** : `lecoffre-back-main/src/scripts/audit-missing-anchors.ts`
- **Ancrage dossiers** : `lecoffre-back-main/src/scripts/anchor-existing-folders-v3.ts`
- **Réancrage** : `lecoffre-back-main/src/scripts/reanchor-documents.ts`
- **Nettoyage** : `lecoffre-back-main/src/scripts/clean-incomplete-folder-anchors.ts`
### Frontend
- **Page vérification** : `lecoffre-front-main/src/pages/verify-document.tsx`
- **Composant AnchorBadge** : `lecoffre-front-main/src/front/Components/DesignSystem/AnchorBadge/`
---
**Dernière mise à jour** : 2025-11-24
**Version** : 3.1.2