MMANDATE GATE
BUILD NOTES · SEPTEMBER 2026

Useful autonomy needs a boundary.

An agent can be good at choosing actions and still be unsafe to authorize them. Mandate Gate separates those jobs: the agent requests a narrowly defined tool operation, while the server holds the policy, reserves the budget and commits the permitted result.

Working end-to-end sandbox, not a production wallet or payment system. No model, blockchain, paid compute provider or external signer is connected.

بالعربي: ما الذي يعمل فعلاً؟

تعطي الوكيل صلاحية محدودة لتشغيل تحليل نصوص أو حساب بصمات. الطلب يذهب إلى الخادم؛ لا يستطيع الوكيل رفع رصيده أو الموافقة لنفسه. الطلب المسموح يحجز رصيداً تجريبياً، وعند التنفيذ يُحفظ الناتج وخصم الرصيد معاً. يمكن للمتحكم الموافقة على طلب أكبر ضمن الحد، أو إيقاف الوكيل وإلغاء أعماله غير المنفذة.

هذه ليست مجرد اقتراح أو شاشة شكلية: الواجهة البرمجية تنفذ المنع فعلياً للأدوات التجريبية المتصلة بها. لكنها لا تحمي محفظة أو خدمة خارجية حتى يتم ربط نقطة تنفيذ تلك الخدمة بها بشكل لا يستطيع الوكيل تجاوزه. الأمثلة مبرمجة وليست نموذج ذكاء اصطناعي متصلاً.

The specific YZi fit

YZi’s EASY Residency S5 thesis includes delegated authority, least-privilege tool access, policy enforcement and auditability. This project implements a small, testable part of that theme. It is not commissioned, endorsed or reviewed by YZi Labs, CZ or Binance.

NeedImplemented hereBoundary
Delegated authoritySeparate random 256-bit agent and controller bearer credentials; only hashes stored for lookup.A capability identifies a sandbox role, not a verified person. Controller possession is not proof of human presence.
Least privilegeTwo fixed local tools; exact schema and provider/action allowlist.No arbitrary URLs, network forwarding, shell, wallet or provider credentials.
Budget enforcementServer-priced jobs; fixed session cap; hard per-job cap; approval threshold; atomic reservation.Nonmonetary test credits; per-session limits, not organization-wide financial controls.
AccountabilityImmutable job fingerprint, decision history, content/output hashes, hash-linked events and HMAC authentication.No asymmetric signatures, external timestamp anchor or independent proof against the operator.
Containment & recoveryExpiry, cancellation and permanent stop release unexecuted reservations.Completed work is not rolled back; irreversible payments cannot be undone.

Where enforcement happens

The browser is not trusted. Every API command authenticates a role, loads the server-held state, checks the transition and writes a new revision only if the old revision still matches. Concurrent commands retry against fresh state. Policy, reservations, sandbox output, debit and audit changes commit in one database-row update.

The only executable adapters are text.analyze (word counts and frequent words) and text.digest (SHA-256 per document). They produce real deterministic output. The test charge is five credits per document, not a claim about compute market pricing. Free-text documents are data; they are never evaluated as instructions or code.

Automatic approval reserves credits but does not execute. The agent must call execute. Larger requests wait for the controller’s approval of the exact fingerprint. Hard limits cannot be overridden. Reservations are rechecked at execution; expired reservations are reclaimed during subsequent state transitions.

This design’s atomicity applies because the sandbox result lives in the same database state. An external provider cannot be made atomic merely by copying this function. Real integrations need durable dispatch, provider-side idempotency, timeouts marked as uncertain rather than refunded, and reconciliation before releasing reserved funds.

Trust model

The server, database and hosting operator are trusted. An agent should receive only its agent token—not the controller key, an owner browser profile, hosting credentials or the database connection. The demo page intentionally lets one visitor play both roles. Giving an autonomous browser the controller’s session would defeat that separation.

HMAC authenticates records to this server. Downloaded records include the HMAC and hash chain but not the secret. Anyone can check hash linkage; only the server can check HMAC authenticity. The operator can rewrite records and regenerate authentication. An exported head retained elsewhere may help detect later differences; it is not independent notarization.

Not solved

No real-money signing, onchain session keys, end-user identity verification, multi-person approvals, malicious-but-in-scope intent detection, paid-provider delivery verification, compliance certification, high-availability operations or security audit. No claim of a new cryptographic invention. If a malicious action fits the granted scope, this gate can still allow it.

Use it with an agent

First create a sandbox in the app. Keep the controller credential in its browser tab. Use Copy agent token to give your agent the restricted credential. The owner must make the site Public in Hatchable Settings before external clients can reach the API; declaring a route public does not remove the hosting sign-in wall.

Base URL: https://mandate-lab.hatchable.site. Send JSON with an Authorization: Bearer YOUR_AGENT_TOKEN header. Never put a token in a URL, document or public post.

Small agent-only client

Download agent-client.mjs. This optional helper exposes request, execute and status only. It rejects controller-token prefixes. Keep a stable operation key across retries.

import { MandateAgent } from './agent-client.mjs';
const agent = new MandateAgent({
  agentToken: process.env.MANDATE_AGENT_TOKEN
});

const result = await agent.run({
  provider: 'local-text',
  action: 'text.analyze',
  documents: ['Synthetic test data only.']
}, 'my_stable_job_001');

// A pending result needs controller approval in the app.
// Never send the controller credential to the agent.

1. Request a job

POST /api/gate/agent
Authorization: Bearer YOUR_AGENT_TOKEN
Content-Type: application/json

{
  "op": "request",
  "key": "job_example_001",
  "provider": "local-text",
  "action": "text.analyze",
  "documents": ["A short sample document."]
}

The response contains result and session. Possible request states: authorized, pending or blocked. Only authorized is executable. The job ID is the request key. Do not trust an old idempotent acknowledgement as current authorization; inspect current session state or attempt the gated execution.

2. Execute the exact stored job

POST /api/gate/agent
Authorization: Bearer YOUR_AGENT_TOKEN
Content-Type: application/json

{
  "op": "execute",
  "key": "execute_example_001",
  "jobId": "job_example_001"
}

Never send a price, balance, status or replacement document on execution. Those fields are not accepted. If the response is lost, retry the identical command with the same key. A repeated execute—even with a new execution key—cannot charge or run the committed job twice.

3. Human/controller decisions

Use the page’s review dialog. The separate controller API is POST /api/gate/controller with its controller bearer credential. Approval requires {op:"approve", key, jobId, fingerprint}. Decline uses the same shape with op:"decline". Cancel uses {op:"cancel", key, jobId}. Stop uses {op:"revoke", key}. The agent credential is not accepted on this route.

RoutePurposeCredential
POST /api/gate/createIssue isolated sandbox. Body {policy:{budget,maxJob,auto}}; include X-Mandate-Client: v1.None, subject to hosting wall and capacity cap.
GET /api/gate/agentRead that sandbox’s state.Agent
POST /api/gate/agentRequest / execute only.Agent
GET /api/gate/controllerRead that sandbox’s state.Controller
POST /api/gate/controllerApprove / decline / cancel / stop.Controller
GET /api/gate/verifyVerify the current server-held audit chain.Controller

Error handling

401 means invalid/missing role credential. 403 means wrong-role operation or blocked origin. 400 means invalid fields. 409 means state, fingerprint or idempotency conflict. 410 means expired session. 429 means capacity reached. A 503 means unavailable: keep the same command key, inspect state and retry; do not issue replacement work blindly.

Test the boundary, not the promise

The app’s live test runner creates a separate sandbox and makes real API calls. It checks missing credentials, role separation, price tampering, unapproved tools, hard caps, approvals, duplicate execution, changed idempotency payloads, concurrent reservations, revocation and HMAC verification. Results are produced at run time, not pre-filled.

Development also uses 43 core checks for policy validation, expiry, state transitions, SHA-256 output and modified audit records. Passing tests is evidence of the tested behavior—not an independent security audit or proof that every attack is covered.

Try to falsify it

Useful feedback is specific: can an agent execute without approval, exceed the cap using simultaneous requests, reuse an approval for changed details, execute after stop, access another sandbox, or get charged twice after a retry? Record the job ID and observed state. Do not send keys or sensitive text. This app has no automatic feedback submission or notifications.

Data & limits

Use synthetic text only. Sample documents, results and audit records are stored in the project database. Tokens last 24 hours; expiration disables API access but does not automatically erase stored records. The demo has no self-service deletion or recovery flow. The controller keys stay in this tab’s session storage and should be treated as secrets; closing the tab may remove your access.

Bounds: 40 documents per job, 400 characters each, 50 jobs and 180 state-changing command keys per sandbox. The hosted prototype permits at most 80 new sandboxes per UTC day and 500 total, including test runs. These are capacity safeguards, not a complete anti-abuse/rate-limiting service. The maximum configured budget is 1,000 nonmonetary test credits. New sandboxes have separate budgets.

The older browser-local invoice workspace remains at /desk.html; its existing IndexedDB records are untouched. The earlier visual lab remains at /lab.html. Neither page is the new server-enforced control plane.

What a real pilot would need

  1. Choose one paid tool and a pilot customer with a measurable unauthorized-use problem.
  2. Keep the provider credential or wallet signer exclusively behind the gate; restrict direct access at the provider. A policy endpoint alone is bypassable.
  3. Add authenticated operator accounts, stronger approval authentication, durable execution/reconciliation and secure key management.
  4. Test the adapter in a provider sandbox or testnet with failure injection, then obtain an independent security review before real funds.

Existing wallets and gateways already implement important parts of this stack. A credible product must prove easier integration or better operational control for a narrow workflow; this prototype does not establish novelty or market demand.

Ideas used, with their boundaries

Selected primary technical sources and public builder material, reviewed September 16, 2026. This is not an exhaustive survey of the internet or social media. Principles are combined in original application code; these services are not integrated or implied partners.

SourceInfluence
YZi Labs — EASY S5 thesisScoped authority and accountability as the problem selection.
OWASP — AI Agent SecurityLeast privilege, independent authorization and adversarial tests.
OWASP — Transaction AuthorizationServer-side checks, meaningful details, immutable approval binding and final execution checks.
ZeroDev — composable permissions
Kernel repository
Separate who can act, under which conditions, and what action is permitted. No Kernel code or smart contract is integrated.
Turnkey — delegated agent signingKeep delegated agent authority distinct from the owner’s authority. This prototype has no Turnkey signer.
Stripe — idempotent requestsStable command keys for retries; reject reuse with different details. No Stripe integration.
BNB Chain — public X discussionDiscovery lead on fund policies and human co-signing. Only the indexed excerpt was accessible; it is not security evidence.

Return to the working sandbox →

Built on Hatchable