Legal Document Versioning & Signing
I korthet
Per-language versioning of platform legal documents (ToS, DPA, Billing Terms, SLA) with tenant-scoped append-only acceptance register, automatic supersede chains on publish, clickwrap signing live today and DocuSign + BankID-backed eSignature pending provider credentials — every acceptance carries IP, user-agent, content hash and signing metadata for full audit, and pending-acceptance helpers power the tenant onboarding-guard.
Så fungerar det
Legal documents are platform-scoped and versioned per (type, language). Each LegalDocument carries a SHA-256 content-hash so any byte-level change requires a new version, and a superseded_by link to its successor. Publishing a new version through POST /legal/documents (platform-admin only) automatically sets superseded_by on the previously active version for the same (type, language) pair, so the active version is unambiguous and historical versions remain queryable. The public GET /legal/documents?type=&lang= reads the active version; GET /legal/documents/history (admin) lists every version sorted by effective_date descending.
Acceptance is recorded in a separate, tenant-scoped, append-only collection. LegalDocumentAcceptance is one immutable row per (tenant, type, version) capturing IP, user-agent, a copy of the content-hash at signing time and signing metadata. Today the platform supports clickwrap acceptance through POST /tenants/{id}/legal/{doc_type}/sign-clickwrap — a checkbox flow that records the contextual proof. DocuSign eSignature REST integration plus BankID QR collect-flow are stubbed in the codebase and return 501 until provider credentials land in Azure Key Vault; HMAC-SHA256 webhook validation is designed in. PDF generation via WeasyPrint for both unsigned drafts and signed documents (with signature attestation rendered into the footer) is on the same pending track.
The onboarding integration is what closes the loop. GET /tenants/{id}/legal/pending?lang= returns every document where the tenant either has no acceptance or where the active version requires re-acceptance because of a supersede event with material changes. The is_fully_accepted() service helper returns true exactly when the pending list is empty; the planned onboarding-guard wires this into POST /tenants so a new tenant cannot complete signup without a full acceptance set on file. Contracts will gain a legal_document_acceptances list of PydanticObjectIds linking the contract to the specific document versions accepted at execution, so a future dispute can reconstruct exactly what the parties agreed to and when.
Centrala funktioner
- LegalDocument model versioned per (type, language) with SHA-256 content-hash and superseded_by chain
- LegalDocumentAcceptance append-only register per (tenant, type, version) with IP, UA and signing metadata
- Automatic supersede on publish, setting superseded_by on the previously active version
- Clickwrap signing flow with IP and UA logging today
- DocuSign eSignature REST API integration with HMAC-SHA256 webhook validation (pending credentials)
- BankID QR collect-flow with certificates in Azure Key Vault (pending credentials)
- PDF generation via WeasyPrint for unsigned drafts and signed documents with footer attestation (pending)
- Pending-acceptance and full-acceptance helpers powering tenant onboarding-guard
- Contract-to-document-version linking via legal_document_acceptances list
I praktiken
Legal counsel publishes a new ToS version in English, French and Swedish. POST /legal/documents stamps each as version 4, computes their content-hashes and supersedes version 3 of every language. Existing tenants see version 4 in their pending list the next time they open the admin app; their tenant-admin clicks through the clickwrap flow and a LegalDocumentAcceptance row writes — IP recorded, UA recorded, content-hash copied, timestamp pinned.
A new federation signing up tomorrow gets the onboarding-guard: they cannot complete tenant creation until clickwrap is accepted on ToS v4, DPA v2 and Billing Terms v3 in their selected language. When DocuSign credentials land, the same flow upgrades to a fully-attested eSignature, and BankID gives Swedish tenants a citizen-grade signing path with the certificate trail in Key Vault.
Features i detta subsystem
15| ID | Status | Funktioner |
|---|---|---|
| F16.19.01 | Levererad | LegalDocument-modell (platform-scoped) — versionerad per (type, language), SHA-256 content-hash, superseded_by-länk till efterföljande version. ✅ PL-T094 |
| F16.19.02 | Levererad | LegalDocumentAcceptance-modell (tenant-scoped, append-only) — immutable audit-rad per (tenant, type, version) med IP, UA, content-hash-kopia och signerings-metadata. ✅ PL-T094 |
| F16.19.03 | Levererad | Automatisk supersede: publish_version sätter superseded_by på tidigare aktiv version för samma (type, language). ✅ PL-T094 |
| F16.19.04 | Levererad | GET /legal/documents?type=&lang= — publik läsning av aktiv version. ✅ PL-T094 |
| F16.19.05 | Levererad | POST /legal/documents (platform_admin) — publicera ny version. ✅ PL-T094 |
| F16.19.06 | Levererad | GET /legal/documents/history (platform_admin) — versionshistorik sorterad på effective_date desc. ✅ PL-T094 |
| F16.19.07 | Levererad | POST /tenants/{id}/legal/{doc_type}/sign-clickwrap — checkbox-flöde med IP + UA-logg. ✅ PL-T094 |
| F16.19.08 | Levererad | GET /tenants/{id}/legal/pending?lang= — dokument där tenant saknar acceptance eller aktiv version kräver re-acceptance. ✅ PL-T094 |
| F16.19.09 | Levererad | GET /tenants/{id}/legal/acceptances — full tenant-acceptanshistorik. ✅ PL-T094 |
| F16.19.10 | Levererad | is_fully_accepted() — service-helper för onboarding-guard (True när pending-listan är tom). ✅ PL-T094 |
| F16.19.11 | Levererad | DocuSign eSignature REST v2.1-integration via JWT Grant + RSA-nyckel i Key Vault, create_envelope/get_envelope_status/download_signed_pdf, HMAC-SHA256 webhook-validering. ✅ PL-T289 |
| F16.19.12 | Levererad | BankID v6 RP-flöde (/sign, /collect, /cancel) via mTLS-cert i Key Vault, default-provider för SE-tenants, PNR-redaktering i loggar och i tjänstelagret. ✅ PL-T289 |
| F16.19.13 | Levererad | PDF-rendering för kontrakt + legal-dokument med signatur-attest-sida (signer, signed-at, SHA-256, provider-referens). PDF/A-1b-konformans verifieras av verapdf-cli i CI-jobbet ci-api / pdf-a-conformance. ✅ PL-T289 |
| F16.19.14 | Levererad | Contract.legal_document_acceptances länkar kontrakt till accepterade dokument-versioner. GET /admin/contracts/{id}/legal-coverage exponerar audit-trailen. ✅ PL-T289 |
| F16.19.15 | Levererad | Onboarding-guard i POST /sys/tenants returnerar 422 onboarding_acceptance_incomplete med missing_documents-lista. Sys-konsolens tenant-create-vy visar checklistan och blockerar submit. ✅ PL-T289 |
Relaterade subsystem
Intressenter som behöver detta subsystem
Förekommer i 1 intressentanalyser