Quickstart | Concepts | API | Verify
Concepts
Mandate
What you allow an agent to do, signed with your passkey (a WebAuthn assertion over a deterministic CBOR payload; the browser encodes it, the server does not hand you a hash). Anything not listed is denied. Fields: validity (days), currency, purchase budget per 24 h and max per purchase (cents on the wire), allowed recipient domains and addresses, closed data classes, delete policy, publish policy. A new mandate supersedes the previous one for the agent; the old one stays in the ledger.
Verdicts
allow- the call may run. The proxy checks the signed receipt (AAR), presents it (consumes it once), runs the tool, reports the result.deny- not run. The agent getsBlocked by Deus Witness: <reason> (receipt <rid>).defer- held until you approve in the browser (15 minutes). After approval the same call isallowonce; changed text, amount or recipient is a new action.pass- the tool is declared harmless (classpass), forwarded without a receipt.
Reasons
OK, OK_APPROVED, OK_UNSPECIFIED, OK_CIRCLE; deny: RECIPIENT (not an allowed domain/address), DATA_FORBIDDEN (closed data in the text), BUDGET (24 h budget exhausted), PER_ACTION_LIMIT, CLASS_DENIED, CLASS_UNKNOWN, EXPIRED, NO_MANDATE, TOOL_UNMAPPED (tool not in the toolmap), IRREVERSIBLE_DELETE (delete not specified and not reversible), RESOURCE (target not in the allowed list); defer: ESCALATE_DELETE, ESCALATE_PUBLISH, ESCALATE_MONEY, ESCALATE_DATA, ESCALATE_FILE. Source of truth: draft-deus-aar-04 section 8.5 and svidetel_v4/decide.py.
Toolmap
How an MCP tool call becomes an action the witness can judge: the class (message, purchase, delete, publish, file, pass, ...), which argument is the recipient, which are the text, which is the amount. Presets: demo, filesystem, empty. Edit it on the dashboard (validated on save). A tool that is not mapped is denied by default (default: "pass" is honoured only while the map is the one your passkey-signed mandate was signed with; any edit of the map refuses every call of that agent, TOOLMAP_CHANGED, until you sign a new mandate). The recipient may be one path or a list (["$.to", "$.cc", "$.bcc"]): every address must be allowed on its own, and a message tool that is called with an argument that is not mapped (and not listed in extra_keys) is denied (TOOL_ARGS_UNMAPPED). A recipient is exactly one mailbox: a comma list or a second @ in one string is invalid and denied.
What is proven, what is not
Proven: every allow, deny and defer that was judged against a mandate is in an append-only signed ledger (calls that need no judgement - pass tools, unmapped tools, calls without a mandate or with a changed tool map - are only in the service database and the feed, not in the ledger); receipts are signed with the witness key; the mandate and approvals carry your passkey signature; an outsider can recheck the ledger offline; the anchor commits checkpoints to Bitcoin through OpenTimestamps (it can be pending for hours).
Not proven (honest limits):
- Only actions that go through the proxy are covered; an agent with other channels is out of scope.
- Your passkey device does not display the mandate or the action; you trust the page scripts. Their SHA-256 hashes are published on the home page and included in the pack. A hostile server could serve different scripts.
- Login and signing use the same key (a hostile server could present a mandate hash as a login challenge); a separate signing key is future work.
- The key is registered on the witness's own site, so a swap at the moment of registration is not detectable; the key card and the hash-chained registry log in the anchor reduce the window afterwards. No device attestation:
key_attestation: "passkey"is a claim. - Data classification is a literal, case-insensitive match; a paraphrase evades it. The recipient rule is the stronger barrier, but only for the arguments the tool map names as recipients: an address in an argument the map does not know is denied for message tools and ignored for other classes.
- The tool map is bound to the mandate by the server (hash stored when the passkey signed the mandate), not inside the signed mandate: a third party reading the evidence pack cannot see which map applied. The preview of arguments on the approval page is shown by the page and is not signed; what is signed is the action including a hash of all arguments.
- The TypeScript SDK does not verify receipts yet (the Python SDK and the proxy do).
- Reversibility of a delete comes from the toolmap, not from the agent; unknown resources count as irreversible.
- The witness is only as independent as its operator; at this stage the operator is the author of the project. Clock honesty is limited.
- The anchor may be
pending; verify later with the OpenTimestamps tools. Spec and implementations are not reviewed by outside parties yet. - Limits of the free tier: 3 agents, 5000 actions per day, 60 requests per minute per key.