Compliance Checks
Loyva evaluates every envelope against the UCC §9-105 requirements below. All 8 checks must pass for full compliance — only a score of 100 means the envelope is compliant.
Each check returns a structured result:
interface UCC9105Check {
requirement: string; // Human-readable requirement
ucc_reference: string; // UCC citation
satisfied: boolean; // Pass/fail
detail: string; // Explanation with envelope-specific data
}
Check 1: Single authoritative copy
UCC §9-105(b)(2) — A single authoritative copy of the record exists that is unique, identifiable, and unalterable.
How Loyva evaluates:
- Verifies
envelopes.vault_file_pathis set - The authoritative PDF is uploaded to the
ucc-vaultbucket withupsert: false, enforcing a single copy - The stored bytes include a UCC watermark so the file itself announces its authoritative status
Fails when: The signed document hasn't been stored in the vault yet.
Check 2: Tamper-evident record
UCC §9-105(b)(4) — The authoritative copy is stored with tamper-evident technology so any change is detectable.
How Loyva evaluates:
- Verifies
envelopes.document_hashcontains a SHA-256 digest of the stored authoritative bytes - Hash is computed once at vault time and written atomically with the path
- Hash is re-verified on every vault download and by the weekly cron job — results are appended to
integrity_check_history
Fails when: No document_hash is stored.
Check 3: Controlling party identified
UCC §9-105(b)(1) — The authoritative copy identifies the person asserting control.
How Loyva evaluates:
- Looks up
custodian_permissionsfor the envelope withstatus = 'accepted' - The first such row is the active custodian (controlling party)
- The queue worker auto-assigns the envelope creator as the initial custodian once the vault pipeline completes, so this check passes without manual action
Fails when: No custodian permission exists in accepted state (rare; only happens if auto-assignment was skipped).
Check 4: All required signatories executed
UCC §9-105(b)(3) — Every party required to sign the record has signed.
How Loyva evaluates:
- Compares
envelopes.submitters[].email(expected signers) withenvelopes.signed_documents[].signer_email(actual signatures) - The check passes if every submitter has a matching signed document, or if there are no submitters recorded (paper uploads)
Fails when: One or more required signers haven't completed signing.
Per-signature hashes are captured on the signature image artifacts, but this check only verifies that each required signer is represented — not a separate per-signature hash value.
Check 5: Non-authoritative copies identifiable
UCC §9-105(b)(5) — Copies of the authoritative copy must be readily identifiable as copies.
How Loyva evaluates:
- Verifies
envelopes.copy_file_pathis set and points into theucc-copiesbucket - Copies are uploaded separately from the authoritative file with a
non_authoritativemetadata flag
Fails when: No copy has been stored in ucc-copies.
Check 6: Electronic record fully executed
UCC §9-105 (general) — The record must actually be a complete, executed electronic record.
How Loyva evaluates:
- Verifies
envelopes.statusiscompletedorvaulted vaultedis a superset — it impliescompletedplus the authoritative copy has been stored
Fails when: The envelope is still pending, sent, or viewed.
Check 7: Audit certificate generated
UCC §9-105 best practice — An audit certificate accompanies the record for inspection.
How Loyva evaluates:
- Verifies
envelopes.vault_out_certificate_pathis set - The certificate is a JSON document stored alongside the authoritative PDF in
ucc-vault - It contains the full check results, signer timeline, document hash, issuer, secured party, and legal notices
Fails when: The certificate hasn't been generated yet (pipeline still running or failed).
Check 8: Secured party identified
UCC §9-105(b)(1) — The authoritative copy identifies the secured party / assignee.
How Loyva evaluates:
- Verifies
envelopes.secured_partyis populated with a non-emptyname - Structured object:
{ name, role?, address?, email?, identifier? } - Surfaced at the top level of the compliance certificate as
secured_party
Fails when: secured_party is null or name is missing/empty.
Resolution: Populate secured_party when you create the envelope via POST /api/v2/partner/envelopes:
{ "secured_party": { "name": "First National Bank", "role": "secured_party", "address": "..." } }
API response example
The compliance evaluator is exposed via GET /api/v2/partner/envelopes/:id/compliance. The response wraps the result under data:
{
"data": {
"envelope_id": "env_x7k9m2p4q1w3",
"external_id": null,
"envelope_status": "vaulted",
"compliance": {
"compliant": true,
"score": 100,
"evaluated_at": "2026-04-11T10:17:00.000Z",
"missing_requirements": [],
"checks": [
{
"requirement": "Single authoritative copy",
"ucc_reference": "UCC §9-105(b)(2)",
"satisfied": true,
"detail": "Authoritative copy stored at: ucc-vault/org_abc/env_x7.../signed.pdf"
},
{
"requirement": "Tamper-evident record",
"ucc_reference": "UCC §9-105(b)(4)",
"satisfied": true,
"detail": "SHA-256 hash: a1b2c3d4..."
},
{
"requirement": "Controlling party identified",
"ucc_reference": "UCC §9-105(b)(1)",
"satisfied": true,
"detail": "Custodian: usr_abc (accepted 2026-04-11T10:16:30.000Z)"
},
{
"requirement": "All required signatories executed record",
"ucc_reference": "UCC §9-105(b)(3)",
"satisfied": true,
"detail": "All 2 required signature(s) present"
},
{
"requirement": "Non-authoritative copies identifiable",
"ucc_reference": "UCC §9-105(b)(5)",
"satisfied": true,
"detail": "Copy path: ucc-copies/org_abc/env_x7.../signed.pdf"
},
{
"requirement": "Electronic record fully executed",
"ucc_reference": "UCC §9-105 general",
"satisfied": true,
"detail": "Envelope status is vaulted"
},
{
"requirement": "Audit certificate generated",
"ucc_reference": "UCC §9-105 best practice",
"satisfied": true,
"detail": "Certificate: ucc-vault/org_abc/env_x7.../certificate.json"
},
{
"requirement": "Secured party identified",
"ucc_reference": "UCC §9-105(b)(1)",
"satisfied": true,
"detail": "Secured party: First National Bank"
}
]
}
}
}
Common failure scenarios
| Scenario | Failing checks | Resolution |
|---|---|---|
| Signing just completed | 1, 2, 5, 7 | Wait for vault pipeline (usually < 30 seconds) |
| No custodian assigned | 3 | Normally auto-assigned on vault; use the custodian API if manual action is needed |
| Signer didn't complete | 4, 6 | Send a reminder or check signer status |
| Pipeline error | 1, 2, 5, 7 | Re-fetch the live score via GET /api/v2/partner/envelopes/:id/compliance once the pipeline has caught up |
| Secured party not set | 8 | Pass secured_party on POST /partner/envelopes when creating the envelope |