Developers
Integration guide
Architecture
- Web app + API (Next.js on Vercel): consumer app, institution portal, public verification API.
- PostgreSQL with row-level security: trust registry, receipts, cases, protected actions, hash-chained audit log. A trigger independently enforces the protected-action state machine.
- Media service (Python, CPU): voice anti-spoofing model, transcription and C2PA validation/signing. Reachable only by the backend with a bearer token.
Tumaini authorisation receipts
A receipt is a compact JWS (RFC 7515) signed with Ed25519 (alg: EdDSA, typ: tumaini-receipt+jws, kid = issuer key id). The payload:
{
"v": 1,
"iss": "tumaini:issuer:falcon-demo-bank",
"jti": "5b0c…", // unique id: revocation + single use
"iat": 1794200000, "exp": 1794286400, // max lifetime 30 days
"aud": "tumaini:customer:TUM-4F2A9K", // or "*" for public notices (never for payments)
"purpose": "card_annual_fee",
"scope": { "action": "payment",
"payment": { "amount_minor": 15000, "currency": "AED",
"beneficiary_name": "Falcon Demo Bank — Card Services",
"beneficiary_account": "AE07 0331 2345 6789 0123 456" } },
"content_sha256": "…" // SHA-256 of canonical {title, body}
}content_sha256 is the SHA-256 of canonical JSON (sorted keys, NFC-normalised, trimmed) of { title, body }. It binds the signature to the exact words the recipient sees.
Verification order
- Format and size; header
typ,kid; nocrit. - Algorithm must be EdDSA (prevents algorithm confusion).
- Issuer must exist in the trust registry and be active.
- Key must be registered to that issuer and not revoked.
- Ed25519 signature verification against the registered public key.
- Validity window (30 s clock tolerance; lifetime ≤ 30 days).
- Receipt not revoked by the issuer.
- Audience: issued to this recipient (payments are never broadcast).
- Content integrity: hash of the presented text matches.
- Scope: the intended action (type, amount, currency, beneficiary account) matches exactly.
- Single use: not already consumed by another action.
The first failing check sets the outcome; all checks are returned for explainability. The verifier never throws on untrusted input.
Outcomes
| Outcome | Meaning |
|---|---|
valid | All checks passed for the supplied context. |
malformed | Not a well-formed v1 receipt, or lifetime out of bounds. |
unsupported_algorithm | Anything other than EdDSA. |
unknown_issuer / suspended_issuer | Issuer not in the registry, or suspended. |
unknown_key / revoked_key | Key not registered to the issuer, or revoked. |
invalid_signature | Signature does not verify (payload or signature altered, or wrong key). |
expired / not_yet_valid | Outside the validity window. |
revoked | Issuer withdrew this receipt. |
audience_mismatch | Issued to someone else, or a payment receipt addressed to *. |
content_mismatch | Text was altered after signing. |
missing_scope / scope_mismatch | Does not authorise this kind of action / differs in amount, currency or account. |
replayed | Already used to authorise an action. |
Protecting an action
Create a protected action with POST /api/actions. Tumaini runs the risk policy, verifies any receipt against that exact payment, and moves the action to VERIFIED (valid in-scope receipt, consumed atomically) or HELD. From HELD, a trusted-contact challenge can move it through PENDING_VERIFICATION to VERIFIED. Only VERIFIED can become RELEASED, and the database re-checks the evidence on every transition.
CREATED → ASSESSING → HELD | VERIFIED
HELD → PENDING_VERIFICATION → VERIFIED | HELD (unreachable/expired) | CANCELLED (denied)
VERIFIED → RELEASED
any non-terminal → CANCELLED · held/pending/verified → EXPIREDSecurity considerations
- Keep issuer private keys in an HSM or KMS in production. The prototype encrypts them with AES-256-GCM under a server-held master key and destroys them on revocation.
- Never put a verification phone number or link in the message itself — trusted contacts must be registered beforehand.
- Treat model output and uploaded media as untrusted input. The risk policy is deterministic; AI can add caution only.
- The demo trust registry is not an official UAE trust list. A production registry needs a governance body and an onboarding process.