Manav Manav.id
← All demos
SIGN · 2 of 10

An MSA gets signed with cryptographic human proof.

A Master Services Agreement worth $2M/year is queued for signature. The signing ceremony binds Asha's passkey to the exact contract text. A public proof page anyone can verify is generated - offline, forever, even if Manav no longer exists.

Privacy posture for this scene
The contract carries its own proof - no third-party trust needed.
  • The signature is bound to sha256(canonical_json(contract_body)) - tampering invalidates it.
  • The receipt is Ed25519-signed - verifiable offline forever, even if Manav no longer exists.
  • DocuSign-compatible - drops into existing signature workflows as a higher-assurance option.
Contract · awaiting signature
Master Services Agreement · 18 pages
msa_4421

Acme AI Labs ↔ GreenLeaf Designs LLC

Annual value$2,000,000 / yr
Effective2026-06-01
Counterparty signed2026-05-19 · GreenLeaf
Pending signatureAsha Raman - VP Operations
Document fingerprint sha256:144c172ffba3398c…

The passkey will be bound to sha256(canonical_json(contract)). Any change to the contract text invalidates the signature.

✓

Contract signed - human-attested

Proof: -

Passkey signed sha256:144c172ffba3398c… - this exact document. The Ed25519 receipt below verifies offline without Manav.

Ship this in your own app

Three lines of JavaScript. Demo key mnav_test_demo works on localhost.

JavaScript cURL
// 1. One script: canonicalisation, the ceremony, offline verification
<script src="https://manav.id/js/manav-crypto.js"></script>

// 2. Statement: typed fields + the exact rows the human reads (rule R1: nothing hidden)
const result = await Manav.sign({
  action: 'contract.sign',
  fields: { reference: { type: 'string', value: 'msa_4421' }, /* … */ },
  render: [['Action', 'SIGN CONTRACT'], ['Reference', 'msa_4421'], /* … */],
});
// result.receipt  → Receipt v2, Ed25519 + ML-DSA-87, verifiable offline with /v2/jwks
// result.verdict  → the browser's own verification, no call to Manav
# 1. Statement (the relying party signs it; the issuer checks rules R1–R6)
curl -X POST https://manav.id/v2/statement -H 'Content-Type: application/json' \
  -d '{"action":"contract.sign","fields":{...},"render":[["Action","SIGN CONTRACT"],...]}'
# 2. Ceremony: /v2/sign/options (challenge = stmt_hash) → passkey → /v2/sign → receipt
# 3. Verify anywhere, offline:
curl -s https://manav.id/v2/jwks; curl -s https://manav.id/v2/revocations
node packages/verify-ts/bin/verify.js --receipt receipt.json --jwks jwks.json --revocations revocations.json
🔐

Read, then confirm with your passkey

These rows are exactly what your passkey signs. Nothing else.

Relying party signs the statement (rule R3)
Challenge = sha256(JCS(statement))
Passkey signs it with user verification
Receipt issued (Ed25519 + ML-DSA-87), verified offline