espace-paie-odentas/ODENTAS_SIGN_INTERFACE.md
odentas b790faf12c feat: Implémentation complète du système Odentas Sign
- 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)
2025-10-27 19:03:07 +01:00

407 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🎨 Odentas Sign - Interface de Signature (Phase 2)
## 📋 Vue d'ensemble
L'interface de signature Odentas Sign offre une expérience moderne et fluide pour la signature électronique de documents. Elle remplace complètement DocuSeal avec une solution souveraine et conforme eIDAS.
## 🎯 Fonctionnalités
### ✅ Implémenté
- ✨ Design moderne avec Tailwind CSS et Framer Motion
- 🔐 Authentification OTP à 6 chiffres
- ✍️ Canvas de signature HTML5 (souris, trackpad, tactile)
- 📊 Barre de progression en temps réel
- 🎉 Animation de célébration (confetti) après signature
- 📱 Responsive mobile-first
- 🔒 Vérification de consentement obligatoire
- ⏱️ Countdown timer pour l'OTP (15 minutes)
- 🚫 Limite de tentatives (3 maximum)
- 📈 Affichage de la progression des signatures
### 🔄 À venir
- 📄 Visualiseur PDF avec zones de signature surlignées
- 📥 Téléchargement du document signé
- 📧 Notifications email améliorées
## 🗂️ Structure des fichiers
```
app/signer/[requestId]/[signerId]/
├── page.tsx # Page principale avec routing
└── components/
├── ProgressBar.tsx # Barre de progression des étapes
├── OTPVerification.tsx # Écran de vérification OTP
├── SignatureCapture.tsx # Canvas de signature
└── CompletionScreen.tsx # Écran de confirmation
```
## 🎨 Flow utilisateur
### 1⃣ Étape 1 : Vérification OTP
**URL:** `/signer/[requestId]/[signerId]`
**Processus:**
1. L'utilisateur arrive sur la page avec son lien unique
2. Affichage de son nom et email pré-remplis
3. Clic sur "Recevoir le code"
4. En **mode test** : OTP affiché dans les logs serveur
5. En **mode production** : Email SES envoyé
6. Saisie du code à 6 chiffres (auto-focus, auto-submit)
7. Vérification du code → Génération d'un JWT (30min)
8. Transition automatique vers l'étape signature
**Sécurité:**
- Code valide 15 minutes
- Maximum 3 tentatives
- Rate limiting 60 secondes entre envois
- JWT avec expiration
### 2⃣ Étape 2 : Signature
**Processus:**
1. Canvas de signature responsive
2. Dessin avec souris/trackpad/doigt
3. Bouton "Recommencer" pour effacer
4. Checkbox de consentement obligatoire
5. Validation → Upload de l'image PNG
6. Enregistrement en base + S3
7. Si tous ont signé → Déclenchement webhook
8. Transition vers écran de confirmation
**Canvas:**
- Taille adaptative (devicePixelRatio)
- Ligne fluide (lineCap: round)
- Couleur noire (#1e293b)
- Export PNG avec transparence
- Support touch events
### 3⃣ Étape 3 : Confirmation
**Processus:**
1. 🎉 Animation de confetti
2. Affichage des détails (date, référence)
3. Progression des signatures (X/Y signé)
4. Message différent selon statut:
- Tous signés → "Document finalisé"
- En attente → "Attente des autres"
5. Boutons (téléchargement désactivé pour l'instant)
## 🧪 Test de l'interface
### Prérequis
```bash
# 1. Créer une demande de test
node test-odentas-sign.js
# 2. Lancer le serveur Next.js en dev
npm run dev
# 3. Utiliser le script de test interactif
./test-interface-signature.sh
```
### Script de test
Le script `test-interface-signature.sh` offre:
1. **Ouvrir l'interface Employeur** → Ouvre automatiquement le navigateur
2. **Ouvrir l'interface Salarié** → Ouvre automatiquement le navigateur
3. **Afficher l'OTP Employeur** → Trigger l'envoi + instructions pour logs
4. **Afficher l'OTP Salarié** → Trigger l'envoi + instructions pour logs
5. **Vérifier le statut** → Affiche qui a signé, progression
6. **Quitter**
### Mode test vs Production
| Aspect | Mode Test | Mode Production |
|--------|-----------|----------------|
| **Détection** | Ref commence par `TEST-` | Ref normale |
| **OTP** | Logs serveur | Email SES |
| **Scellement** | Sauté | PAdES + TSA |
| **Archive** | Sautée | S3 Object Lock 10 ans |
## 🎨 Design System
### Couleurs
```css
/* Gradients principaux */
from-indigo-600 to-purple-600 /* Header vérification */
from-green-500 to-teal-500 /* Confirmation success */
from-slate-50 via-blue-50 /* Background page */
/* Boutons */
bg-indigo-600 hover:bg-indigo-700 /* Primary action */
bg-slate-100 text-slate-400 /* Disabled */
border-slate-200 /* Secondary */
```
### Animations
```typescript
// Transitions de page
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
// Progress bar fill
initial={{ width: 0 }}
animate={{ width: `${percentage}%` }}
transition={{ duration: 1, ease: 'easeOut' }}
// Confetti celebration
confetti({
particleCount: 50,
startVelocity: 30,
spread: 360,
colors: ['#6366f1', '#8b5cf6', '#ec4899']
})
```
### Composants réutilisables
- `ProgressBar` : Étapes avec cercles et connecteurs
- Icons de Lucide : `Shield`, `Check`, `Clock`, `Users`, `PenTool`
- Modales animées avec `AnimatePresence`
## 🔐 Sécurité
### JWT Session Token
```typescript
{
signerId: string,
requestId: string,
role: string,
iat: number, // Issued at
exp: number, // Expiration (30 minutes)
iss: 'odentas-sign'
}
```
**Utilisation:**
- Généré après validation OTP
- Stocké dans state React (pas de localStorage)
- Envoyé dans header `Authorization: Bearer <token>`
- Vérifié côté serveur pour `/sign`
### Protection CSRF
- Origin checking dans les API routes
- Rate limiting sur `/send-otp`
- Validation des inputs (OTP digits only)
### Données personnelles
- Email affiché mais non modifiable
- IP et User-Agent enregistrés dans `sign_events`
- Consentement explicite requis
- Archivage 10 ans conforme RGPD (base légale: contrat)
## 📊 Tracking des événements
Tous les événements sont loggés dans `sign_events`:
1. `request_created` → Création demande
2. `otp_sent` → Envoi code
3. `otp_verified` → Code validé
4. `otp_verification_failed` → Code invalide
5. `signed` → Signature enregistrée
6. `request_completed` → Tous ont signé
7. `pdf_sealed` → PAdES appliqué
8. `document_timestamped` → TSA horodatage
9. `archived` → Archive S3
## 🌐 URLs
### Signature
```
/signer/[requestId]/[signerId]
```
**Exemple:**
```
/signer/75b4408d-1bbd-464f-a9ea-2b4e5075a817/95c4ccdc-1a26-4426-a56f-653758159b54
```
### API Endpoints utilisés
```
POST /api/odentas-sign/signers/[id]/send-otp
POST /api/odentas-sign/signers/[id]/verify-otp
POST /api/odentas-sign/signers/[id]/sign
GET /api/odentas-sign/signers/[id]/status
```
## 📱 Responsive Design
### Breakpoints
```css
sm: 640px /* Tablettes portrait */
md: 768px /* Tablettes landscape */
lg: 1024px /* Desktop */
xl: 1280px /* Large screens */
```
### Canvas tactile
```typescript
// Disable browser touch gestures
style={{ touchAction: 'none' }}
// Support touch events
onTouchStart={startDrawing}
onTouchMove={draw}
onTouchEnd={stopDrawing}
```
## 🎯 Prochaines étapes
### PDF Viewer intégration
```bash
npm install react-pdf pdfjs-dist
```
**Fonctionnalités:**
- Afficher le PDF dans `SignatureCapture`
- Overlay semi-transparent sur zones de signature
- Scroll automatique vers la zone du signataire
- Zoom responsive
### Email notifications
Templates à créer:
- `signature-completed.html` → Envoyé au signataire après sa signature
- `all-signatures-completed.html` → Envoyé à tous quand finalisé
- Avec lien de téléchargement du PDF signé
### Download du document
```typescript
async function downloadSignedDocument() {
const response = await fetch(`/api/odentas-sign/requests/${requestId}/download`);
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${documentRef}-signed.pdf`;
a.click();
}
```
## 🐛 Debugging
### Logs serveur
```bash
npm run dev
```
Chercher dans les logs:
```
⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
MODE TEST - Code OTP
⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
```
### Console navigateur
```javascript
// État du composant
React DevTools SignerPage state
// Erreurs réseau
Network tab Filter: "odentas-sign"
// JWT decode
JSON.parse(atob(token.split('.')[1]))
```
### Base de données
```sql
-- Derniers événements
SELECT * FROM sign_events
ORDER BY created_at DESC
LIMIT 20;
-- Statut des signataires
SELECT
sr.ref,
s.name,
s.role,
s.has_signed,
s.signed_at
FROM signers s
JOIN sign_requests sr ON s.request_id = sr.id
ORDER BY sr.created_at DESC;
```
## 🎉 Migration depuis DocuSeal
### Coexistence
Les anciennes pages DocuSeal restent actives:
- `/signatures-electroniques` → DocuSeal (employeur)
- `/signature-salarie` → DocuSeal (salarié)
Nouvelles pages Odentas Sign:
- `/signer/[requestId]/[signerId]` → Odentas Sign (tous rôles)
### Migration progressive
1. **Phase 1** : Nouveaux contrats → Odentas Sign
2. **Phase 2** : Anciens contrats → Continuer DocuSeal
3. **Phase 3** : Quand tous migrés → Supprimer DocuSeal
### Détection automatique
```typescript
// Dans le code de création de contrat
const useOdentasSign = process.env.NEXT_PUBLIC_USE_ODENTAS_SIGN === 'true';
if (useOdentasSign) {
// Créer via /api/odentas-sign/requests/create
// Envoyer liens /signer/[requestId]/[signerId]
} else {
// Créer via DocuSeal
// Envoyer liens DocuSeal
}
```
## 📚 Ressources
- [Framer Motion Docs](https://www.framer.com/motion/)
- [Tailwind CSS](https://tailwindcss.com)
- [Lucide Icons](https://lucide.dev)
- [Canvas Confetti](https://www.npmjs.com/package/canvas-confetti)
- [eIDAS Regulation](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=uriserv:OJ.L_.2014.257.01.0073.01.ENG)
## ✅ Checklist de production
Avant mise en production:
- [ ] Tester sur mobile (iOS Safari, Android Chrome)
- [ ] Vérifier accessibilité (contraste, keyboard navigation)
- [ ] Intégrer PDF viewer
- [ ] Ajouter templates email de notification
- [ ] Activer vraie signature PAdES (retirer test mode bypass)
- [ ] Configurer monitoring (Sentry, logs CloudWatch)
- [ ] Load testing (Artillery, k6)
- [ ] Documentation utilisateur finale
- [ ] Formation équipe support
- [ ] Plan de rollback DocuSeal
---
**Créé le:** $(date +%Y-%m-%d)
**Version:** 2.0.0
**Auteur:** GitHub Copilot
**Statut:** ✅ Phase 2 Complète