# Require it — the gate a venue runs (VTR-1 / MIZAN)

A marketplace, vault, copy-trading venue, allocator or agent framework can require a MIZAN credential before capital, listing or payment in twenty lines. The rule: **allow only a PASS credential in good standing; refuse with the reason; fail closed.**

## Python (stdlib only)

```python
from mizan.gate import require_credential          # pip install mizan-sdk  (or copy gate.py)

d = require_credential("blackbox-fractional")      # credential id, agent name, wallet or ERC-8004 id
if not d.allow:
    refuse(d.reason)                               # "verdict FAIL" · "revoked: …" · "UNVERIFIED" · "unverifiable … fail closed"
```

With the agent's signed receipt (verified offline against the published key when `cryptography` is installed):

```python
d = require_credential("", receipt=request.headers["X-Mizan-Receipt"])
```

FastAPI dependency:

```python
from fastapi import HTTPException
def gated(agent: str):
    d = require_credential(agent)
    if not d.allow: raise HTTPException(403, {"error": d.reason, "status": d.status})
```

## JavaScript (zero dependencies)

```js
import { requireCredential } from "@mizan/sdk/gate.mjs";
app.use("/allocate", async (req, res, next) => {
  const d = await requireCredential(req.body.agent, { receipt: req.get("X-Mizan-Receipt") });
  if (!d.allow) return res.status(403).json({ error: d.reason, status: d.status });
  next();
});
```

## Policy text (paste-ready)

> Agents allocated capital, listed, copied or paid here must present a MIZAN credential under VTR-1 v1.0 with verdict PASS in good standing. We verify the credential's signed receipt against MIZAN's published key and check its live status before each allocation. A refused, revoked or unverifiable credential is refused; refusals are logged. A credential attests to the honesty of a historical record, not to future returns.

## Before money moves: the allocate-check (one call, one signed answer)

```python
from mizan.gate import allocate_check
d = allocate_check("agent-name-or-credential", amount=10_000, currency="USDC", purpose="vault allocation")
if not d.allow: refuse(d.reason)          # d.status["checks"] = every check with clause; d.status["token"] = signed 24 h decision
```
```js
import { allocateCheck } from "@mizan/sdk/gate.mjs";
const d = await allocateCheck("agent-name-or-credential", { amount: 10000, currency: "USDC" });
if (!d.allow) refuse(d.reasons);          // keep d.token
```
HTTP: `POST https://studio.mizan.market/api/allocate-check {agent, amount, currency, purpose, receipt?, require_forward?, record?}`. It performs VTR-1 Agent Profile §06 (A-26..A-31): identity → registry → live status → verdict as issued → receipt → bundle hash + Bitcoin anchor → log inclusion → provenance class → record age. Thresholds are your policy (`require_forward=true` refuses backtests). With your API key and `record=true` the check is a public log leaf. Re-verify any token at `POST /api/allocate-check/verify`.

## After you relied on one: counter-sign it

```
POST https://studio.mizan.market/api/receipt/attest   Authorization: Bearer mzn_…
{"credential": "blackbox-fractional", "purpose": "listed on our marketplace", "public_name": "optional"}
```

It becomes a public leaf of the verdict log and an edge in the reliance graph (`GET /api/graph`). Stay hashed or opt into a name. Zero means zero; nothing is synthesised.

## What the gate checks, in order

1. Receipt (if given): EdDSA signature against `https://studio.mizan.market/.well-known/mizan-keys.json`, expiry.
2. Live status `GET /api/status/{id}`: `good` / `revoked` (reason, log index) / `superseded` / `unknown`.
3. If unknown by id: `GET /api/agents/check?q=` by name, wallet or ERC-8004 id.
4. Any network or server error → refuse, reason "unverifiable", never allow.

Full API: https://studio.mizan.market/app/api.html · MCP tools `require_credential`, `allocate_check` · A2A skills `require_credential`, `allocate_check`.
