Concepts

Délégation & mandat de scellement

Tracer toute la chaîne de responsabilité quand un eSeal est apposé : qui a cliqué, pour quelle société, avec quel sceau, sous quel mandat. Crucial pour les cas d'eSeal partagé entre plusieurs entités clientes.

Le problème : qui est responsable de quoi ?

Un eSeal qualifié appartient juridiquement à une personne morale (PM) — une société identifiée par son immatriculation. Mais dans la pratique, deux configurations coexistent :

Mode OWN

eSeal propre à la société

La société cliente détient elle-même son certificat eSeal qualifié, émis à son nom par un PSCo. Le sceau apposé engage directement la société.

Exemple : ACME SAS achète son propre certificat Yousign qualifié au nom d'ACME SAS et l'utilise via notre app pour signer ses contrats.

Mode DELEGATED

eSeal partagé (mandat)

L'app métier (par exemple MyRole) détient un eSeal qualifié à son nom, utilisé en mandat pour le compte de plusieurs sociétés clientes. Le sceau apposé est celui de l'app métier, qui agit comme mandataire pour la PM signataire.

Exemple : MyRole détient un certificat Yousign à son nom. ACME SAS, cliente de MyRole, demande à MyRole d'apposer son sceau sur les avenants RH d'ACME — en mandat explicite.

Pour le mode DELEGATED : ce qu'il faut tracer

Le mandat doit être prouvé cryptographiquement, sinon le sceau générique ne distingue pas une apposition légitime d'une fraude interne. La chaîne de responsabilité comprend 3 acteurs :

        ┌─────────────────────────┐
        │   PP (personne physique)│  M. Directeur RH d'ACME SAS
        │   actor_user_id         │  → s'authentifie via OTP (sole control eIDAS)
        │   actor_metadata        │  → nom complet, rôle dans la société
        └─────────────────────────┘
                    │ agit pour
                    ▼
        ┌─────────────────────────┐
        │   PM signataire         │  ACME SAS (SIRET 12345...)
        │   signatory_entity      │  → la société dont la signature engage
        │                         │  → c'est SES contrats qui sont signés
        └─────────────────────────┘
                    │ délègue au mandataire
                    ▼
        ┌─────────────────────────┐
        │   PM mandataire         │  MyRole (organisation_id)
        │   organisation_id (= app)     │  → notre client direct API
        │   + seal_certificate    │  → détient le eSeal "générique"
        │     mode = DELEGATED    │  → engage sa responsabilité via le mandat
        └─────────────────────────┘
        

Modèle de données proposé (V2)

À POST /v1/sessions, on enrichit avec un objet signing_context :

{
  "actor_user_id":     "emp-12345",
  "actor_metadata": {                          // la PP en clair (lisible bénéficiaire)
    "full_name":      "Jean Directeur",
    "role":           "Directeur de production",
    "employee_id":    "EMP-001"
  },
  "signing_context": {
    "signatory_entity": {                       // la PM dont la signature engage
      "kind":         "company",
      "legal_name":   "ACME SAS",
      "registration": { "scheme": "siret", "value": "12345678901234" }
    },
    "seal_certificate": {                        // quel eSeal est apposé
      "mode":               "OWN" | "DELEGATED",
      "issuer":             "Yousign Qualified Seal v3",
      "fingerprint_sha256": "abcdef..."
    },
    "mandate": {                                 // requis si mode=DELEGATED
      "organisation_attests":   true,                  // l'organisation déclare le mandat
      "scope":            "Signature contrats RH",
      "reference":        "CGU MyRole §4.2 + accord ACME 2026-03-15"
    }
  },
  "planned_operations": [...]
}

Comportement du service

  1. Persiste signing_context sur la session (JSONB)
  2. Au moment du validate OTP, append une entrée SIGNING_CONTEXT_ATTESTED dans la chaîne, avec payload_hash = sha256(canonical(signing_context)). Co-signée Ed25519 par organisation + master → immuable.
  3. Embarque dans le bundle ASiC-E : SIGNING_CONTEXT.json + DELEGATION.txt lisible humain
  4. Affiche dans le mail récap au bénéficiaire les trois entités (PP, PM signataire, PM mandataire si applicable)
  5. Affiche dans l'admin session detail le contexte complet + le mode du sceau

Pourquoi ça suffit juridiquement

Pour casser la preuve d'un mandat attesté, il faudrait que :

  • L'organisation ait menti dans mandate.organisation_attests — mais alors c'est lui qui engage sa responsabilité contractuelle envers la PM signataire (responsabilité civile + pénale pour faux et usage de faux)
  • OU le directeur ait usurpé l'identité — mais l'OTP au moment de l'attestation prouve sole control au sens eIDAS Art.26
  • OU les clés Ed25519 (organisation + master) aient été compromises simultanément — peu probable, et détectable par les canaries

L'attestation co-signée à l'instant T est donc un mandat opposable, même si l'eSeal apposé n'est pas celui de la PM signataire.

Cas typique : parapheur RH avec eSeal partagé

Un service de parapheur (l'app métier MyRole, notre organisation) signe en bloc 15 avenants RH pour ACME SAS (cliente de MyRole). Le directeur RH de ACME, M. Durand, valide l'opération dans l'interface MyRole. Le sceau apposé sur les 15 PDFs est celui de MyRole, en mandat d'ACME.

Le bundle de preuve ProofIt contient alors :

  • L'attestation SIGNING_CONTEXT_ATTESTED : "MyRole atteste qu'ACME SAS (SIRET …) a mandaté la signature de ces 15 avenants RH par MyRole en utilisant son seal qualifié partagé. Mandant : M. Durand, directeur RH d'ACME"
  • Le manifest prévisionnel (S41) : la liste exacte des 15 contrats avec leurs op_id
  • L'OTP validé par M. Durand : sole control prouvé
  • Le sceau eSeal apposé par MyRole sur chaque PDF : artifact attaché à la chaîne
  • Verdict S41 MATCH : tous les contrats prévus ont été signés avec les hashes attendus

→ Si demain ACME conteste un avenant : MyRole produit le bundle, montre le mandat attesté co-signé + l'OTP + le manifest, et l'apposition est opposable comme si ACME avait scellé elle-même.

État d'implémentation : livré. Le signing_context structuré (mode OWN / DELEGATED, entité signataire, mandat avec organisation_attests) se passe à l'ouverture de session ; il est figé dans la chaîne par une entrée SIGNING_CONTEXT_ATTESTED co-signée (son payload_hash est l'empreinte canonique du contexte) — toute modification a posteriori du mandat casserait la co-signature. Le contexte attesté figure dans le bundle de preuve.