Ricardian contracts in CAN — legal prose that the runtime can enforce
A PDF agreement does not stop a training job or bind runtime state to the exact terms parties signed.
CAN uses a Ricardian contract: legal prose plus machine-enforceable structure (datasets, params, environment, keys, signatures) so train/infer proceed only under that state.
Related: Contract → governed prediction · Contract management — signing keys & verify · Product tour · Merkle / Auditor · KMS DEK/MEK · TEE attest → decrypt · In-repo: RICARDIAN_CONTRACT_GUIDE.md
Status: Creating, previewing, multi-party signing, and SIGNED → train gates are live on the local stack. On-chain deploy and some signature crypto are demo / Phase 1 (see §8). Cloud clean-room key release remains Phase 2 in the TEE narrative.
1. What “Ricardian” means here
Ian Grigg’s Ricardian idea (simplified): one document that humans can read, machines can hash unambiguously, and signatures bind to that byte-exact artifact.
In CAN: legal prose bound to machine-enforceable structure (datasets, training params, privacy, clean-room host).
Legal prose ──hash──► legalDocumentHash ──bound to──► Contract row
▲ │
│ ▼
Human review / signatures Runtime gates (train / infer)
Machine-only → opaque JSON. Legal-only → NDA. Ricardian is both.
2. The dual layer in CAN
| Layer | Fields | Purpose |
|---|---|---|
| Legal | legalDocument (JSONB) |
Title, parties, recitals, terms, accumulated signatures[] |
| Binding digests | legalDocumentHash, ricardianSignature |
Commit to the document bytes; platform-level binding marker |
| Machine / execution | contractDatasets, aiModelIds, trainingParams, environmentSpecs, kmsConfigs, tspCloudProvider, party ids |
What training and policy gates actually read |
Creation (simplified):
- TDC runs the wizard →
POST /api/contracts/ricardian. - Service generates
legalDocumentfrom a template (AI_TRAININGorBASIC). - Canonical JSON → SHA-256 →
legalDocumentHash(0x…). - Platform records
ricardianSignatureover that hash (see §8). - Optional smart-contract address (real chain if configured; otherwise mock).
- Persist
ContractatPENDING_TDP_APPROVALand notify linked TDPs.
Screens: product tour — contract create & sign.
3. Who the parties are
| Role | In the contract | What they do |
|---|---|---|
| TDC | Training Data Consumer | Creates the Ricardian contract; selects datasets & catalog model; starts training after SIGNED |
| TDP | Training Data Provider | Owns data; reviews terms; signs to approve use |
| TSP | Tech Service Provider (formerly CCRP) | Hosts the environment (Local Docker today; cloud confidential compute in design); signs as assigned host |
| Auditor | Not a party | Read-only: Merkle tree + contract review when a model is disputed (Auditor role) |
Design roots sit with iSPIRT DEPA—consent-style, multi-party sharing with identifiers (DEPA IDs) on parties, datasets, contracts, and jobs.
4. Lifecycle: from draft intent to enforced runtime
sequenceDiagram
participant TDC
participant CAN
participant TDP
participant TSP
participant Train
TDC->>CAN: Create Ricardian (legal + machine fields)
CAN->>TDP: Notify PENDING_TDP_APPROVAL
TDP->>CAN: Sign as TDP
CAN->>TSP: Status PENDING_TSP_APPROVAL
TSP->>CAN: Sign as TSP
Note over CAN: status = SIGNED
TDC->>Train: Start training (requires SIGNED)
Train->>CAN: Jobs, provenance, optional G-MASE gates
4.1 Create (TDC)
Five-step UI (CreateRicardianContract):
- Template
- Details & dataset selection (1–3 datasets)
- Environment & TSP (compute, security, KMS refs)
- Review generated legal document
- Submit
4.2 Sign (TDP → TSP)
- TDP signs via
POST /api/contracts/:id/signwithpartyType=TDP→ moves toward TSP approval. - TSP (assigned
tspId) signs → status becomesSIGNED. - Each approval appends to
legalDocument.signatures[]and writes a best-effort SCITT claim (contract_approval).
Runtime note: The training gate today requires status === 'SIGNED' (reached when TSP completes). A separate tdcSigned column exists on the model; do not assume every UML “all three parties must sign” path is what the local trainer enforces. Prefer the live path above.
4.3 Train and infer
- Train:
tdcTrainingExecutionServicerefuses jobs unless the contract is SIGNED (and env / cloud / privacy constraints are present). - Infer: Deployed models stay tied to the training
contractId; Open-GMASE can gate deploy/predict via packageopen_gmase/can_contracts(demo slice).
No signature → no training. That is the product claim that replaces “we emailed a Word doc.”
5. What the machine side binds
These fields are not decoration—they are what jobs and gates consume:
| Binding | Contract fields | Examples |
|---|---|---|
| Data | contractDatasets, primary dataset ids |
Which TDP catalogs are in scope (max 1–3) |
| Model | aiModelIds |
Catalog base model (e.g. DistilBERT for NLP tours) |
| Training rules | trainingParams |
Epochs, DP (epsilon/delta), accuracy floors, run limits |
| Environment | environmentSpecs |
Instance shape, security.attestationRequired, encryption, network isolation |
| Keys | kmsConfigs (often from wizard environmentSpecs.kms) |
Provider, key id / Vault OCID, region — see KMS post |
| Where it runs | tspId, tspCloudProvider |
Local, OCI, Azure, … |
Wizard defaults lean secure: attestation required, encryption at rest/in transit, network isolation—even when the local trainer is Docker rather than a hardware TEE.
6. How the contract shows up in evidence
When a model misbehaves, the contract is the spine of the audit story:
| Evidence path | Contract role |
|---|---|
| Provenance report | Exposes legalDocumentHash, ricardianSignature, parties, jobs |
| Auditor Merkle tree | contract leaf commits to hash, signature, env specs, training params, datasets (Merkle post) |
| SCITT claims | contract_creation / contract_approval markers |
| Open-GMASE | OPA input includes contract_id, contract_status, classification / region hints from the contract |
Auditors do not use the Ricardian text to prove the model was “correct.” They use it to prove which agreement governed the run, then Verify Merkle inclusion for that trail.
7. Why this is better than “PDF + NDA”
| Approach | Stops unauthorized train? | Tamper-evident? | Ties artifact to terms? |
|---|---|---|---|
| PDF in email | No | No | Manual at best |
| Checkbox ToS in UI | Soft | Usually not | Weak |
| CAN Ricardian | Yes — status gate | Hash + signatures + SCITT/Merkle path | Job and model carry contractId |
That is the DEPA-shaped idea applied to AI training: use is licensed by agreement, not by whoever has a copy of the CSV.
8. Phase 1 limits
| Topic | Reality today |
|---|---|
ricardianSignature |
Platform binding digest for demos—not full multi-party ECDSA / cloud KMS signing of the legal hash (production target: IdP + KMS). Deep dive: Contract management — signing & verify |
| On-chain deploy | Real only if blockchain is enabled and available; otherwise mock network/address |
| TDC signature | Model supports tdcSigned; SIGNED for training is driven by the TSP completing the current flow |
| Templates | Built-in AI_TRAINING / BASIC; rich clause libraries / customer templates: roadmap |
| TEE / key release | Contract can require attestation; local Docker is not hardware TEE—see TEE post |
| Naming | Runtime prefers TSP; older templates/DB columns may still say CCRP |
9. Takeaways
- A Ricardian contract in CAN is legal prose plus hashed binding plus machine fields the runtime enforces.
- Lifecycle: create → TDP sign → TSP sign → SIGNED → train/infer.
- Machine bindings (
datasets,trainingParams,environmentSpecs,kmsConfigs, cloud) are first-class—not footnotes. - Provenance, Merkle, SCITT, and Open-GMASE all hang off the same contract id.
- Ask vendors for the hash, the signature trail, and the SIGNED gate—not a PDF alone.
One sentence: CAN’s Ricardian contract is how multi-party AI collaboration becomes enforceable state instead of an email attachment—readable by people, hashed for integrity, and checked before training runs.