# Système de Vérification de Signature Électronique

## Vue d'ensemble

Ce système permet aux signataires de **vérifier l'authenticité et l'intégrité** de leurs documents signés électroniquement via une page web publique accessible par **URL ou QR code**.

## Architecture

### 1. Page de Vérification Publique
**Fichier**: `app/verify/[id]/page.tsx`

- Route dynamique: `https://espace-paie.odentas.com/verify/{uuid}`
- Accessible sans authentification (RLS public en lecture)
- Affiche tous les détails techniques de la signature

### 2. Table Supabase
**Fichier**: `supabase/migrations/20251028_signature_verifications.sql`

```sql
signature_verifications
├── id (UUID) → Identifiant unique de vérification
├── document_name → Nom du document signé
├── pdf_url → URL du PDF signé
├── signed_at → Date/heure de signature
├── signer_name → Nom du signataire
├── signer_email → Email du signataire
├── signature_hash → Hash SHA-256 du contenu signé
├── signature_hex → Signature complète en hexadécimal
├── certificate_info (JSONB) → Infos du certificat
├── timestamp (JSONB) → Horodatage TSA
├── verification_status (JSONB) → Statuts de validation
├── contract_id → Lien vers le contrat
└── organization_id → Lien vers l'organisation
```

### 3. API de Création
**Fichier**: `app/api/signatures/create-verification/route.ts`

```typescript
POST /api/signatures/create-verification
Body: {
  document_name: string,
  pdf_url: string,
  signer_name: string,
  signer_email: string,
  signature_hash: string,
  organization_id: string,
  // Optionnel:
  signature_hex?: string,
  certificate_info?: object,
  timestamp?: object,
  contract_id?: string
}

Returns: {
  verification_id: string,
  verification_url: string,
  qr_code_data_url: string (PNG en base64)
}
```

### 4. Générateur de PDF de Preuve
**Fichier**: `lib/signature-proof-pdf.ts`

Génère un PDF A4 professionnel contenant:
- En-tête Odentas Sign
- Informations du document signé
- **QR code** (70x70mm, centré)
- URL de vérification
- Détails techniques (hash, algorithme, certificat)
- Note explicative sur le certificat auto-signé

### 5. Hook React
**Fichier**: `hooks/useSignatureProof.ts`

```typescript
const { createSignatureProof, isCreating } = useSignatureProof();

const proof = await createSignatureProof({
  document_name: "Contrat CDDU",
  pdf_url: "https://...",
  signer_name: "Jean Dupont",
  signer_email: "jean@example.com",
  signature_hash: "dafe9a5e...",
  organization_id: "uuid"
});

// Retourne:
// - verification_url
// - qr_code_data_url
// - proof_pdf_blob
```

## Workflow d'Utilisation

### Lors de la Signature d'un Document

1. **Le document est signé** avec Odentas Sign (Lambda PAdES)
2. **Extraction des données** :
   - Hash SHA-256 du contenu signé
   - Certificat de signature
   - Horodatage TSA (si présent)
3. **Appel API** `/api/signatures/create-verification`
4. **Génération** :
   - Entrée dans `signature_verifications`
   - QR code pointant vers `/verify/{id}`
   - PDF de preuve avec QR code
5. **Téléchargement** :
   - Document signé (PDF avec signature PAdES)
   - Preuve de signature (PDF avec QR code)

### Vérification par le Signataire

1. **Scanner le QR code** ou visiter l'URL
2. **Page publique** affiche :
   - ✅ Statut global (Valide / Techniquement Valide)
   - 📄 Informations du document
   - 🛡️ **Odentas Seal** (sceau électronique)
     - Format PAdES-BASELINE-B
     - Intégrité vérifiée (hash SHA-256)
     - Algorithme RSASSA-PSS
     - Détails du certificat
   - 🕐 **Odentas TSA** (horodatage)
     - RFC 3161 conforme
     - Autorité de temps
     - Empreinte horodatée
   - 🔍 **Vérification technique**
     - Structure PAdES valide
     - ByteRange correct
     - signing-certificate-v2 présent
     - MessageDigest intact
     - Statut du certificat (auto-signé ou qualifié)

## Éléments Affichés

### Odentas Seal
- **Format** : PAdES-BASELINE-B (ETSI TS 102 778)
- **Intégrité** : Hash SHA-256 du document
- **Algorithme** : RSASSA-PSS avec SHA-256
- **Certificat** :
  - Émetteur
  - Sujet
  - Période de validité
  - Numéro de série

### Odentas TSA (si présent)
- **Standard** : RFC 3161
- **Autorité** : URL du TSA
- **Timestamp** : Date/heure certifiée
- **Empreinte** : Hash horodaté

### Vérification Technique
- ✅ Structure PAdES valide
- ✅ ByteRange correct et complet
- ✅ Attribut signing-certificate-v2 présent
- ✅ MessageDigest intact
- ⚠️ Certificat auto-signé (ou ✅ si qualifié)

## Statuts de Validation

### "Signature Valide" ✅
- Certificat **qualifié** reconnu par les autorités européennes
- Tous les contrôles techniques passent
- **Valeur légale** : QES (Qualified Electronic Signature)

### "Signature Techniquement Valide" ⚠️
- Certificat **auto-signé** (Odentas Media SAS)
- Tous les contrôles techniques passent
- **Valeur légale** : SES (Simple Electronic Signature)
- Note explicative affichée

## Sécurité

### Row Level Security (RLS)
```sql
-- Lecture publique (vérification accessible à tous)
CREATE POLICY "Vérifications publiques" ON signature_verifications
  FOR SELECT USING (true);

-- Seul le système peut créer/modifier
CREATE POLICY "Système peut gérer" ON signature_verifications
  FOR ALL USING (auth.uid() IS NOT NULL);
```

### Données Publiques
Les informations exposées sont **volontairement publiques** :
- Nom du signataire
- Email du signataire
- Nom du document
- Hash SHA-256
- Certificat de signature

**Aucune donnée sensible** (contenu du document, IBAN, etc.) n'est stockée.

## Intégration dans l'Application

### Dans les Contrats CDDU/RG

Après signature via Docuseal + Odentas Sign :

```typescript
import { useSignatureProof } from "@/hooks/useSignatureProof";

const { createSignatureProof } = useSignatureProof();

// Après réception du document signé
const proof = await createSignatureProof({
  document_name: `Contrat ${employee.prenom} ${employee.nom}`,
  pdf_url: signedPdfUrl,
  signer_name: `${employee.prenom} ${employee.nom}`,
  signer_email: employee.email,
  signature_hash: extractedHash,
  contract_id: contract.id,
  organization_id: contract.organization_id,
});

// Télécharger les deux fichiers:
// 1. Document signé (PDF PAdES)
// 2. Preuve de signature (PDF avec QR code)
downloadFile(signedPdfUrl, "contrat-signe.pdf");
downloadFile(URL.createObjectURL(proof.proof_pdf_blob), "preuve-signature.pdf");
```

## Design

### Page de Vérification
- **Layout** : Gradient slate 50→100
- **Cards** : Blanc avec shadow-xl et border-radius 16px
- **Statuts** :
  - ✅ Vert (green-600) pour valide
  - ⚠️ Orange (orange-600) pour techniquement valide
  - ❌ Rouge (red-600) pour invalide
- **Icônes** : Lucide React (CheckCircle2, Shield, Clock, FileText)

### PDF de Preuve
- **Format** : A4 portrait
- **En-tête** : Indigo (Odentas branding)
- **QR Code** : 70x70mm, centré, haute qualité
- **Sections** :
  - Document signé (fond slate-100)
  - QR code avec URL
  - Détails techniques
  - Note importante (fond orange-50)

## Variables d'Environnement

```env
NEXT_PUBLIC_APP_URL=https://espace-paie.odentas.com
```

Utilisée pour générer les URLs de vérification.

## Migration Supabase

```bash
# Appliquer la migration
supabase db push

# Ou manuellement
psql -h db.xxx.supabase.co -U postgres -d postgres -f supabase/migrations/20251028_signature_verifications.sql
```

## Exemples d'URLs

```
https://espace-paie.odentas.com/verify/550e8400-e29b-41d4-a716-446655440000
```

## TODO / Améliorations Futures

- [ ] Support multi-signatures (plusieurs signataires)
- [ ] Historique de vérifications (analytics)
- [ ] Notifications email avec lien de vérification
- [ ] API publique de vérification (pour intégrations tierces)
- [ ] Support certificats qualifiés (badge "Qualifié eIDAS")
- [ ] Archivage long terme (LTV avec DSS/LTA)
- [ ] Export PDF/A pour archivage légal

## Conformité

- ✅ **PAdES-BASELINE-B** : ETSI TS 102 778
- ✅ **RFC 3161** : Horodatage électronique
- ✅ **RFC 5035** : signing-certificate-v2
- ✅ **RGPD** : Données publiques consenties
- ⚠️ **eIDAS** : SES (auto-signé) ou QES (avec certificat qualifié)

---

**Odentas Media SAS** - Signature électronique sécurisée
