Zum Hauptinhalt springen

Unterschriften-Verwaltung — E-Signatur (A-2)

Bezug: A-2, R4, R9, OP-SIGN-1 · Status: Provider-Abstraktion + Niveau-Matrix (Slice 4, 0.4.0) + Unterschriften-Assistent inkl. Vor-Ort-/Demo-Abschluss gebaut (MED-D-198, Akten-Cockpit S5, 0.97.0) + DocuSign-HTTP-Adapter gebaut (MED-D-220, 0.100.0, JWT-Grant/WebCrypto + Envelope + Connect-Webhook, dormant ohne Secret) + echte Vor-Ort-/In-Person-Signatur gebaut (MED-D-236, 0.106.0, embedded/captive recipient + recipient view); die Adapter sind noch nicht live verifiziert (kein Dev-Secret/Netz in der Build-Umgebung — gegen gemocktes fetch unit-getestet); PandaDoc + QES-CSP-Anbindung bleiben offen (OP-SIGN-1 Rest). Ohne konfiguriertes Secret läuft die Strecke weiter gegen die Fake-Provider-Attrappe (durchgehend als Demo gekennzeichnet, MED-KB-5).

Vor-Ort-Signatur: echt (In-Person) vs. Attrappe (MED-D-236)

Die „Vor Ort unterschreiben"-Strecke des Assistenten hat zwei Ausprägungen, je nach aktivem Provider — der Server entscheidet, der Client reagiert (eingebettet-Flag):

AspektEcht (DocuSign In-Person)Attrappe (Fake-Provider)
MechanikEmbedded/captive recipient (clientUserId gesetzt → kein E-Mail-Versand) + recipient view-URL, im iFrame auf dem Berater-GerätabschliessenDemo schließt ohne Roundtrip ab
Rechtswirkungrechtsgültig (SES/AES je Dokumenttyp; QES → CSP-Rest)keine — nur Demo (MED-KB-5)
HostDer eingeloggte Berater (Name = anzeigename, E-Mail = Identität; MED-D-237) — DOCUSIGN_HOST_NAME/_EMAIL nur als Fallback
AbschlussDocuSign-Redirect auf …/oeffentlich/signatur/vor-ort-fertig?event=signing_complete → iFrame-Handler → abgleich (Write-back)direkt → erhalten (Prüfung offen)
Mehrere Dokumentesequenziell (ein iFrame je Envelope, Index-Fortschritt)Sammel-Abschluss
RoutePOST /api/dokumente/:docId/signatur/vor-ort (vorbereiten) + POST /api/signaturen/:id/vor-ort-ansicht (URL)POST /api/signaturen/:id/vor-ort-abschluss

Sicherheitsriegel unverändert: der echte Adapter bietet kein abschliessenDemo → der Attrappen- Abschluss liefert gegen DocuSign weiter 409 (nie fälschbar). Der Assistent blendet den Demo-Schnell- Abschluss bei echten Vorgängen aus; das Demo-Banner erscheint nur, solange die Sitzung gegen den Fake läuft. Landung wie Sign-on-Paper: das Dokument geht auf erhalten (Prüfung offen), nicht automatisch auf geprüft/unterschrieben — der Berater bestätigt die Vor-Ort-Unterschrift (G-4).

Host = eingeloggter Berater (MED-D-237). Der DocuSign-In-Person-Host ist die Person, die die Session leitet — bei uns der eingeloggte Berater (Name aus benutzer.anzeigename, E-Mail aus der Cloudflare-Access- Identität), damit der DocuSign-Audit-Trail den echten Bezeuger zeigt (G-4), statt eines generischen Sammel-Kontos. Harte Voraussetzung: die Berater-E-Mail muss ein Nutzer desselben DocuSign-Accounts sein (sonst lehnt DocuSign den In-Person-Host ab) — jeder Vor-Ort-Berater ist also im DocuSign-Account anzulegen. Fehlt die Identität (Dev/nicht eingeloggt), greift die Default-Konfiguration DOCUSIGN_HOST_NAME/_EMAIL als Fallback. Anlage und Signaturansicht nutzen denselben Host — die In-Person-Session sollte also derselbe Berater durchführen, der sie angelegt hat (DocuSign matcht den Host).

Live-Verifikation offen (OP-SIGN-1): Adapter unit-getestet gegen gemocktes fetch, echter In-Person- Roundtrip noch nicht gefahren — Runbook s. Deploy.md §7d.

Entscheidung (A-2)

Unterschriften werden über einen Standard-E-Signatur-Dienst (DocuSign oder PandaDoc) eingeholt — kein Eigenbau (G-1). Medidentas spricht den Provider über eine Provider-Abstraktion an, sodass der Anbieter austauschbar bleibt und ein zweiter Provider (Fallback / Niveau-spezifisch) ergänzt werden kann.

eIDAS-Niveau je Dokumenttyp (zentral!)

Elektronische Signaturen haben unterschiedliche Rechtswirkung — das Niveau muss zum Dokumenttyp passen (RISK-2):

NiveaueIDASWannBeispiel-Dokumenttyp
SESeinfache Signaturgeringe FormanforderungEinwilligung, Kenntnisnahme
AESfortgeschritten (Identität gebunden, Änderung erkennbar)erhöhte BeweiskraftStandard-Verträge, Vollmachten
QESqualifiziert (= eigenhändige Unterschrift, Zertifikat)Schriftform gesetzlich gefordertformgebundene Verträge

CH: Schweiz nutzt ZertES (nicht eIDAS); QES-Äquivalent ist die qualifizierte ZertES-Signatur. Niveau ist je Dokumenttyp begründet festzulegen (Compliance-Tracker §3).

Einordnung Selfservice-Onboarding & Identverifikation (D-30)

Drei Schichten, die nicht vermischt werden dürfen:

SchichtFrageLösung bei Medidentas
Einwilligung/KenntnisnahmeHat der Kunde zugestimmt?Checkbox + versionierter Text + Audit (öffentl. Onboarding-Formular, Slice 9) — kein Provider nötig (Art. 7 DSGVO: formfrei, Nachweisbarkeit genügt; SES-Fall der Matrix)
Unterschrift (Willenserklärung)Hat er rechtswirksam gezeichnet?DocuSign/PandaDoc am Onboarding-Abschluss: Maklervertrag → AES, Vollmacht → QES (konservativ; § 167 Abs. 2 BGB formfrei — real entscheidet die Akzeptanz der Produktgeber)
IdentitätsverifikationIst er, wer er behauptet?Nur bei GwG-Pflicht (OP-GWG-1/RISK-25): Standard = Berater-Ident im Termin (Ausweis, Mandant+Audit); VideoIdent/PostIdent nur Fallback für terminlose Strecken; QES-Flow enthält die Identifizierung implizit

Anbieterwahl-Heuristik (OP-SIGN-1-Rest): Bei den wichtigsten Produktgebern abfragen, welches Niveau sie für Maklervollmachten akzeptieren — reicht AES → PandaDoc-Tendenz (Kosten/Templates); ist QES nötig → DocuSign mit EU-QES-Partner (CSP). In beiden Fällen: EU-Datenresidenz + AVV/Transfermechanismus (US-Konzern).

Anbietervergleich (OP-SIGN-1 — Entscheidungsgrundlage)

KriteriumDocuSignPandaDoc
Marktreife / Verbreitungsehr hochhoch
eIDAS QES/AESja (über Partner/CSP)ja (über Partner)
EU-Datenresidenzverfügbar (Region wählen)verfügbar
Datenexport USUS-Konzern → Transfer prüfen (DPF/SCC)US-Konzern → Transfer prüfen
Dokument-Erstellung/Templatesstarksehr stark (CPQ/Proposals)
API / Webhooksreif, breitreif
Kostenhöhertendenziell günstiger

Empfehlung (vorläufig): Auswahl an den Pflicht-Niveaus und der Datenresidenz festmachen — wenn QES für formgebundene Verträge nötig ist, den Anbieter mit passender CSP-Anbindung und EU-Residenz wählen. Entscheidung in OP-SIGN-1 mit Begründung dokumentieren.

Provider-Abstraktion

Einheitliche Operationen der Abstraktion: envelopeErstellen(dokument, unterzeichner, niveau) · statusAbfragen(id) · webhookVerarbeiten(event) · signiertesDokumentAbrufen(id).

Sequenz: Unterschrift einholen

Nicht-funktional

  • Idempotenz/Reconciliation: Webhook verpasst? → periodischer Status-Abgleich (RISK-6).
  • Nachweis (G-4): Signatur-Zertifikat/Audit-Trail des Providers zusammen mit dem Dokument archivieren.

Umgesetzt (Slice 4, 0.4.0)

  • Provider-Abstraktion SignaturProvider (server/src/signatur/provider.ts): anfordern + status; FakeSignatur (signatur/fake.ts) für Tests/Staging. Provider-Wahl via SIGNATUR_PROVIDER (MVP: fake).
  • Niveau-Matrix (domain/signatur-niveau.ts, begründet, admin-editierbar gedacht): Vollmacht → QES, Vertrag/Auftrag → AES, Mandat/Einwilligung → SES, Default → AES.
  • Signatur-Dienst (api/signatur-service.ts): anfordern (Niveau aus Matrix) · idempotenter Status-Abgleich (RISK-6) · bei Abschluss Rückablage der signierten Fassung in die Ablage (R9; produktiv R2, MED-D-61) + Dokument-Status unterschrieben (R3) + Onboarding-Item geprüft (R2) — "eine Wahrheit" (G-2).
  • D1-Tabelle signatur_vorgang (Migration v3), Felder R4-F01..08. REST: POST /api/dokumente/:id/signatur, GET /api/mandanten/:id/signaturen, POST /api/signaturen/:id/abgleich, POST /api/signaturen/:id/vor-ort-abschluss (MED-D-198). Ohne Provider/NextCloud503.

Unterschriften-Assistent + Vor-Ort-/Demo-Abschluss (MED-D-198, Akten-Cockpit S5)

Ein geführter 3-Schritt-Assistent (Client-Overlay md-unterschriften-assistent) bündelt das Einholen: (1) Prüfen (Dokument(e) wählen, eIDAS-Niveau je Typ automatisch aus der Matrix oder manuell überschreiben) · (2) Versenden (Sammel-Umschlag: mehrere Dokumente in einem Zug, Frist → Wiedervorlage) · (3) Verfolgen (Status je Vorgang). Daneben eine Vor-Ort-Strecke für die In-Person-Signatur auf dem Berater-Gerät.

Sicherheitsriegel (nie fälschbare echte Vorgänge): der Vor-Ort-/Demo-Abschluss ist nur am Fake-Provider möglich (SignaturProvider.abschliessenDemo? existiert ausschließlich in FakeSignatur; vorOrtAbschluss in signatur-service.ts liefert 409 gegen einen echten Provider). Der Abschluss läuft über denselben abgleich-Write-back-Pfad → signierte Fassung in die Ablage (R4→R3→R2), Dokument unterschrieben, Onboarding-Item geprüft, Audit (G-4). Der Attrappe-Hinweis ist in der UI durchgehend sichtbar (MED-KB-5).

DocuSign-HTTP-Adapter (MED-D-220, 0.100.0)

Erster echter Provider hinter der Abstraktion: DocuSignSignatur (server/src/signatur/docusign.ts) spricht die DocuSign-eSignature-REST-API direkt via fetch an — das Node-SDK docusign-esign läuft nicht auf Cloudflare Workers, daher hand-gerollt:

  • Auth = JWT Grant (Server-to-Server, kein User-Redirect): RS256-JWT wird in-Worker über WebCrypto (crypto.subtle) signiert (aud=Auth-Host, scope=signature impersonation), gegen /oauth/token getauscht; Access-Token wird gecacht. Der private Schlüssel ist PKCS#8 (PKCS#1 wird explizit abgelehnt — WebCrypto importKey('pkcs8', …)).
  • Envelope-Flow: anfordern lädt die Dokument-Bytes aus der Ablage (via signatur-service.ts, R4→R3), base64-kodiert sie in einen Envelope (status:'sent', Signer = Mandanten-E-Mail/-Name, signHere-Tab), hängt eine eventNotification (Connect-Webhook-URL) an. status(envelopeId) fragt den Envelope ab und lädt bei Abschluss die kombinierte signierte Fassung (/documents/combined) für den Write-back.
  • Connect-Webhook (Push statt Pull): Route POST /oeffentlich/signatur/docusign-webhook (api/app.ts, öffentlich = kein Access-Login, aber HMAC-verifiziert): X-DocuSign-Signature-1 wird gegen DOCUSIGN_WEBHOOK_HMAC per HMAC-SHA256 konstant-zeit geprüft (fail-closed ohne Key → 401), dann envelopeId→interner Vorgang→abgleich. Der bestehende Pull-Abgleich (RISK-6) bleibt als Fallback für verpasste Webhooks.
  • QES→AES-Herabstufung mit Hinweis (Dev-Account-Grenze): ein QES-Dokumenttyp wird über den DocuSign-Dev-Account als AES versendet mit sichtbarem Hinweis — echte QES braucht einen eIDAS-QES-CSP-Vertrag (offen, s. u.). Bewusst festgehalten, nicht still herabgestuft.
  • Sicherheitsriegel bleibt: DocuSign hat kein abschliessenDemovorOrtAbschluss liefert 409; echte Vorgänge sind nie fälschbar (MED-D-198).
  • Dormant ohne Secret: docuSignKonfigAusEnv gibt null zurück, wenn ein Pflicht-Secret fehlt → Provider fällt auf fake zurück / API 503; das Deployment bleibt ohne Secret deploy-sicher (G-5). Secrets: DOCUSIGN_INTEGRATION_KEY, DOCUSIGN_USER_ID, DOCUSIGN_ACCOUNT_ID, DOCUSIGN_PRIVATE_KEY (PKCS#8-PEM), DOCUSIGN_WEBHOOK_HMAC + SIGNATUR_PROVIDER=docusign (s. docs/architektur/Deploy.md).

Offene Punkte

  • OP-SIGN-1 (Rest): Live-Verifikation des DocuSign-Adapters gegen den echten Dev-Account (Secret + Netzzugang außerhalb der Build-Sandbox), PandaDoc-Adapter als Alternative/Fallback + QES-CSP- Anbindung (echte QES statt AES-mit-Hinweis) + Datenresidenz/AVV (US-Transfer, s. Compliance.md). Abstraktion, Niveau-Matrix und der DocuSign-Adapter stehen; Live-Betrieb + zweiter Provider sind der Rest. Schritt-für-Schritt-Runbook (Scharfschalten + Live-Smoke-Test 1–7): docs/architektur/Deploy.md §7d inkl. „7d-Live-Verifikation". Bis dieser Smoke-Test durchlaufen ist, gilt der Adapter als gebaut, aber nicht live verifiziert (Unit-Tests: 10/10 gegen gemocktes fetch, signatur/docusign.test.ts).