- Remplacement de DocuSeal par solution souveraine Odentas Sign - Système d'authentification OTP pour signataires (bcryptjs + JWT) - 8 routes API: send-otp, verify-otp, sign, pdf-url, positions, status, webhook, signers - Interface moderne avec canvas de signature et animations (framer-motion, confetti) - Système de templates pour auto-détection des positions de signature (CDDU, RG, avenants) - PDF viewer avec @react-pdf-viewer (compatible Next.js) - Stockage S3: source/, signatures/, evidence/, signed/, certs/ - Tables Supabase: sign_requests, signers, sign_positions, sign_events, sign_assets - Evidence bundle automatique (JSON metadata + timestamps) - Templates emails: OTP et completion - Scripts Lambda prêts: pades-sign (KMS seal) et tsaStamp (RFC3161) - Mode test détecté automatiquement (emails whitelist) - Tests complets avec PDF CDDU réel (2 signataires)
371 lines
9.3 KiB
Markdown
371 lines
9.3 KiB
Markdown
# Guide de Test - Odentas Sign
|
|
|
|
Ce guide vous permet de tester Odentas Sign **sans déclencher Odentas Seal**, pour valider le workflow complet de signature électronique en environnement de développement.
|
|
|
|
## 🧪 Mode Test
|
|
|
|
Le système détecte automatiquement le **mode test** quand :
|
|
- La référence du contrat commence par `TEST-`
|
|
- Le PDF source est dans `source/test/`
|
|
- Les emails contiennent `test@` ou `@example.com`
|
|
|
|
En mode test :
|
|
- ✅ Création de la demande de signature
|
|
- ✅ Authentification OTP (code affiché dans les logs)
|
|
- ✅ Capture et upload de la signature
|
|
- ✅ Bundle de preuves (evidence)
|
|
- ❌ **Scellage PAdES désactivé**
|
|
- ❌ **Horodatage TSA désactivé**
|
|
- ❌ **Archivage Object Lock désactivé**
|
|
- ❌ **Envoi d'emails désactivé**
|
|
|
|
## 🚀 Étape 1 : Créer une demande de test
|
|
|
|
### Option A : Via l'API de test (recommandé)
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/api/odentas-sign/test/create-mock \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"title": "Contrat CDDU Test",
|
|
"signerName": "Marie Test",
|
|
"signerEmail": "marie.test@example.com"
|
|
}'
|
|
```
|
|
|
|
**Réponse :**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"test_mode": true,
|
|
"request": {
|
|
"id": "xxx",
|
|
"ref": "TEST-...",
|
|
"title": "Contrat CDDU Test",
|
|
"status": "pending"
|
|
},
|
|
"signers": [
|
|
{
|
|
"signerId": "yyy",
|
|
"role": "Employeur",
|
|
"name": "Jean Dupont (Test)",
|
|
"email": "employeur-test@example.com",
|
|
"signatureUrl": "http://localhost:3000/signer/xxx/yyy"
|
|
},
|
|
{
|
|
"signerId": "zzz",
|
|
"role": "Salarié",
|
|
"name": "Marie Test",
|
|
"email": "marie.test@example.com",
|
|
"signatureUrl": "http://localhost:3000/signer/xxx/zzz"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Option B : Via l'API normale avec un vrai contrat
|
|
|
|
Si vous avez déjà un PDF uploadé dans S3 :
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/api/odentas-sign/requests/create \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"contractId": "votre-contract-id",
|
|
"contractRef": "TEST-2025-0001",
|
|
"pdfS3Key": "source/test/contrat-test.pdf",
|
|
"title": "Contrat de travail CDDU",
|
|
"signers": [
|
|
{
|
|
"role": "Employeur",
|
|
"name": "Votre Nom",
|
|
"email": "vous-test@example.com"
|
|
},
|
|
{
|
|
"role": "Salarié",
|
|
"name": "Salarié Test",
|
|
"email": "salarie-test@example.com"
|
|
}
|
|
],
|
|
"positions": [
|
|
{
|
|
"role": "Employeur",
|
|
"page": 1,
|
|
"x": 100,
|
|
"y": 650,
|
|
"w": 200,
|
|
"h": 60
|
|
},
|
|
{
|
|
"role": "Salarié",
|
|
"page": 1,
|
|
"x": 350,
|
|
"y": 650,
|
|
"w": 200,
|
|
"h": 60
|
|
}
|
|
]
|
|
}'
|
|
```
|
|
|
|
## 🔐 Étape 2 : Tester le flux de signature
|
|
|
|
### 2.1. Ouvrir l'URL de signature
|
|
|
|
Utilisez l'URL retournée dans `signers[].signatureUrl`.
|
|
|
|
**Note :** L'interface frontend n'existe pas encore, donc pour l'instant on teste uniquement les APIs.
|
|
|
|
### 2.2. Demander un code OTP
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/api/odentas-sign/signers/[SIGNER_ID]/send-otp
|
|
```
|
|
|
|
**Réponse :**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"test_mode": true,
|
|
"otp_code_in_logs": true,
|
|
"message": "Mode test : le code OTP est affiché dans les logs serveur",
|
|
"expires_at": "2025-10-27T15:30:00.000Z"
|
|
}
|
|
```
|
|
|
|
**⚠️ Important :** Le code OTP apparaît dans les logs serveur (terminal où Next.js tourne) :
|
|
|
|
```
|
|
[OTP] 🧪 MODE TEST détecté
|
|
[OTP] ========================================
|
|
[OTP] 🔐 CODE OTP POUR marie.test@example.com:
|
|
[OTP] ➡️ 123456
|
|
[OTP] ========================================
|
|
```
|
|
|
|
### 2.3. Vérifier le code OTP
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/api/odentas-sign/signers/[SIGNER_ID]/verify-otp \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"otp": "123456"}'
|
|
```
|
|
|
|
**Réponse :**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"signer": {
|
|
"id": "xxx",
|
|
"name": "Marie Test",
|
|
"email": "marie.test@example.com",
|
|
"role": "Salarié"
|
|
},
|
|
"request": {
|
|
"id": "yyy",
|
|
"ref": "TEST-...",
|
|
"title": "Contrat CDDU Test"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Copiez le `sessionToken`** pour l'étape suivante.
|
|
|
|
### 2.4. Enregistrer la signature
|
|
|
|
Créez une image de signature en base64 (pour tester, voici un petit carré rouge) :
|
|
|
|
```bash
|
|
# Image 100x50 pixels, carré rouge simple
|
|
SIGNATURE_B64="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAyCAYAAACqNX6+AAAABmJLR0QA/wD/AP+gvaeTAAAAeklEQVR4nO3QMQEAAAjAMMC/52ECvlRA00ASAgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQcNkFzQABOWLnlYwAAAAASUVORK5CYII="
|
|
|
|
curl -X POST http://localhost:3000/api/odentas-sign/signers/[SIGNER_ID]/sign \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer [SESSION_TOKEN]" \
|
|
-d "{
|
|
\"signatureImageBase64\": \"$SIGNATURE_B64\",
|
|
\"consentText\": \"Je consens à signer électroniquement ce document.\"
|
|
}"
|
|
```
|
|
|
|
**Réponse :**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Signature enregistrée avec succès",
|
|
"signed_at": "2025-10-27T15:25:00.000Z",
|
|
"all_signed": false,
|
|
"signer": {
|
|
"id": "xxx",
|
|
"name": "Marie Test",
|
|
"role": "Salarié"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2.5. Signer avec le deuxième signataire
|
|
|
|
Répétez les étapes 2.2 à 2.4 avec le deuxième `signerId`.
|
|
|
|
Quand le dernier signataire signe, `"all_signed": true` et le webhook de completion est déclenché.
|
|
|
|
## 📊 Étape 3 : Vérifier les résultats
|
|
|
|
### 3.1. Vérifier le statut de la demande
|
|
|
|
```bash
|
|
curl http://localhost:3000/api/odentas-sign/requests/[REQUEST_ID]
|
|
```
|
|
|
|
**Réponse :**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"request": {
|
|
"id": "xxx",
|
|
"ref": "TEST-...",
|
|
"status": "completed",
|
|
"progress": {
|
|
"total": 2,
|
|
"signed": 2,
|
|
"percentage": 100
|
|
}
|
|
},
|
|
"signers": [
|
|
{
|
|
"id": "yyy",
|
|
"role": "Employeur",
|
|
"signed_at": "2025-10-27T15:20:00.000Z",
|
|
"signature_image_s3": "signatures/xxx/yyy.png"
|
|
},
|
|
{
|
|
"id": "zzz",
|
|
"role": "Salarié",
|
|
"signed_at": "2025-10-27T15:25:00.000Z",
|
|
"signature_image_s3": "signatures/xxx/zzz.png"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 3.2. Vérifier dans Supabase
|
|
|
|
Allez dans Supabase et vérifiez les tables :
|
|
|
|
**`sign_requests`**
|
|
```sql
|
|
SELECT * FROM sign_requests WHERE ref LIKE 'TEST-%' ORDER BY created_at DESC;
|
|
```
|
|
|
|
**`signers`**
|
|
```sql
|
|
SELECT * FROM signers WHERE request_id = '[REQUEST_ID]';
|
|
```
|
|
|
|
**`sign_events`**
|
|
```sql
|
|
SELECT * FROM sign_events WHERE request_id = '[REQUEST_ID]' ORDER BY ts ASC;
|
|
```
|
|
|
|
**`sign_assets`**
|
|
```sql
|
|
SELECT * FROM sign_assets WHERE request_id = '[REQUEST_ID]';
|
|
```
|
|
|
|
### 3.3. Vérifier dans S3
|
|
|
|
Le bucket `odentas-sign` doit contenir :
|
|
|
|
```
|
|
odentas-sign/
|
|
├── source/test/
|
|
│ └── TEST-xxx.pdf # PDF source de test
|
|
├── signatures/
|
|
│ └── [request_id]/
|
|
│ ├── [signer1_id].png # Signature employeur
|
|
│ └── [signer2_id].png # Signature salarié
|
|
└── evidence/
|
|
└── TEST-xxx.json # Bundle de preuves
|
|
```
|
|
|
|
## 📋 Logs attendus
|
|
|
|
Dans votre terminal Next.js, vous devriez voir :
|
|
|
|
```
|
|
[TEST] PDF de test créé: source/test/TEST-xxx.pdf
|
|
[CREATE REQUEST] Création demande: TEST-xxx
|
|
[OTP] 🧪 MODE TEST détecté
|
|
[OTP] 🔐 CODE OTP POUR employeur-test@example.com: 123456
|
|
[OTP] ✅ Mode test - Code affiché dans les logs
|
|
[SIGN] Enregistrement signature pour employeur-test@example.com...
|
|
[SIGN] ✅ Image uploadée: signatures/xxx/yyy.png
|
|
[SIGN] ✅ Signataire mis à jour
|
|
[SIGN] 🎉 Tous les signataires ont signé !
|
|
[WEBHOOK COMPLETION] 🧪 MODE TEST détecté - scellage PAdES désactivé
|
|
[WEBHOOK] 🧪 MODE TEST : Scellage PAdES/TSA/Archive SAUTE
|
|
[WEBHOOK COMPLETION] ✅ Traitement terminé pour TEST-xxx (MODE TEST)
|
|
```
|
|
|
|
## 🧹 Nettoyage après test
|
|
|
|
Pour nettoyer les données de test :
|
|
|
|
```sql
|
|
-- Supprimer les demandes de test (cascade sur signers, positions, events)
|
|
DELETE FROM sign_requests WHERE ref LIKE 'TEST-%';
|
|
|
|
-- Supprimer les assets de test
|
|
DELETE FROM sign_assets WHERE request_id IN (
|
|
SELECT id FROM sign_requests WHERE ref LIKE 'TEST-%'
|
|
);
|
|
```
|
|
|
|
Dans S3, supprimer manuellement :
|
|
- `source/test/`
|
|
- `signatures/[request_ids de test]/`
|
|
- `evidence/TEST-*.json`
|
|
|
|
## 🎯 Checklist de validation
|
|
|
|
- [ ] Création de demande de test réussie
|
|
- [ ] Code OTP visible dans les logs
|
|
- [ ] Vérification OTP réussie avec session token
|
|
- [ ] Upload de la signature réussie
|
|
- [ ] Images de signature présentes dans S3
|
|
- [ ] Statut `completed` après signature complète
|
|
- [ ] Logs confirment le mode test (pas de scellage)
|
|
- [ ] Evidence bundle créé dans S3
|
|
- [ ] Tables Supabase cohérentes
|
|
- [ ] Événements d'audit enregistrés
|
|
|
|
## ⏭️ Prochaine étape
|
|
|
|
Une fois les APIs validées, vous pourrez :
|
|
1. **Créer l'interface frontend** (`/app/signer/[requestId]/[signerId]/page.tsx`)
|
|
2. **Intégrer avec vos contrats existants**
|
|
3. **Créer la Lambda d'orchestration** pour le scellage
|
|
4. **Activer le mode production** (sans TEST-)
|
|
|
|
## 🐛 Dépannage
|
|
|
|
### Le code OTP n'apparaît pas dans les logs
|
|
- Vérifiez que l'email contient `test@` ou `@example.com`
|
|
- Ou que la ref commence par `TEST-`
|
|
|
|
### Erreur "Session invalide"
|
|
- Le JWT expire après 30 minutes
|
|
- Redemandez un OTP et re-vérifiez
|
|
|
|
### Erreur S3
|
|
- Vérifiez que le bucket `odentas-sign` existe
|
|
- Vérifiez les credentials AWS dans `.env.local`
|
|
|
|
### Erreur Supabase
|
|
- Vérifiez que les tables existent (voir définitions dans README)
|
|
- Vérifiez les RLS policies
|
|
|
|
---
|
|
|
|
**Dernière mise à jour :** 27 octobre 2025
|