Coco

The dashboard

What the gate decided and the contract it decided with, read in a browser, with the escalation queue a person works.

The dashboard

The dashboard reads what the gate wrote. It does not decide anything, and the one write a person can make through it is a decision on an escalation, through the same ledger call coco approve uses, so the two surfaces cannot drift.

The page is a static shell and everything on it arrives over a JSON API. A filter changes a query rather than reloading a document, and every receipt goes over the wire whole, so the browser can render the findings, the contracts evaluated and the state each verdict was judged against.

The views

ViewWhat it shows
LiveVerdicts as the gate writes them, allows included, with the counts above them
EscalationsThe queue waiting on a person, with approve and deny
ContractsEvery contract in force, as a list and as its own YAML
ReceiptsThe full table, filtered by verdict, searched by reason, exported as CSV
IntegrationHow to point a harness at this gate
SettingsMode, mandate, contracts loaded, and whether the chain verifies

Across the top of Live sit the verdict counts, the block rate, the escalations waiting and whether the receipt chain verifies. Clicking any row opens the receipt whole, with the contract that fired, every check that ran, the state the gate read and the contract source scrolled to the failing line.

That last part is the point of having a page at all. A compliance officer reading a block wants the sentence, the rule and the line of policy behind it on one screen.

Working an escalation

An escalation shows what the agent wanted to do, the contract that paused it and the reason in a sentence. Whoever holds the dashboard key clicks approve or deny and writes one line saying why, and that line goes on the record next to the receipt.

The agent waits. It cannot approve itself, and silence is not a yes.

A receipt that already carries a decision keeps it. A second decision on the same receipt is refused rather than overwriting the first.

The API

Everything the page shows is available directly.

RouteWhat it returns
GET /healthOpen, for an uptime check
GET /api/metricsCounts, block rate, escalations pending, chain status, mode, mandate, contracts loaded
GET /api/receiptsThe receipts, newest first
GET /api/receipts/<id>One receipt whole, including findings and the state it read
GET /api/escalationsThe pending queue
GET /api/rulesThe compiled contract in force
GET /api/packsThe contracts as a list
GET /api/packs/<id>/yamlOne contract's source
GET /receipts.csvThe table as CSV
POST /api/escalations/<id>/approveRecord a decision
POST /api/escalations/<id>/denyThe same

Auth

HTTP Basic when COCO_DASH_KEY is set, falling back to COCO_API_KEY. Any username works and the key is the password. /health stays open, because an uptime monitor holds no secrets.

Without a key set the dashboard binds to localhost only. Setting a key opens it to the network, and COCO_DASH_HOST overrides either way. That default is deliberate, because a governance dashboard reachable with no password is worse than no dashboard.

The JSON posts carry no CSRF token. That is acceptable behind Basic auth on a design partner deployment and it is not acceptable beyond one, and it is named here rather than discovered later.

Running it

The same image carries the dashboard as a second role, as its own container sharing the ledger volume the gate writes. See Self-hosted.

python3 dashboard.py            # read whatever COCO_HOME already holds
python3 dashboard.py --demo     # the x402 pilot demo, with its own home

The demo needs a YAML parser to compile its contracts, and falls back to Node when PyYAML is missing, so it runs from an environment with either.

The pilot demo

--demo plays a payment platform. It holds a wallet ledger, a merchant registry, price history and an entitlement list as fixtures, builds the payload a platform would send, and runs the real gate as a subprocess for every scenario.

Nine scenarios, and each one writes a real receipt.

ScenarioVerdictWhat it shows
Top up API creditsALLOWRegistered payee, inside every limit, offer fresh
Retry-loop top-upsBLOCKEach payment is fine and the run is what the rule reads
Duplicate subscriptionBLOCKThe entitlement ledger remembers what the context window forgot
Abnormal renewal priceESCALATEUnder the budget cap, twice the history, so a person decides
Lookalike payeeBLOCKAn address one character off the registered one
Expired offerBLOCKAn approval cannot resume a stale signature
Monthly budget breachBLOCKThe budget is the wallet's ceiling, not the agent's opinion
Missing ledger stateBLOCKNo snapshot, no evaluation, no signature
Gate unreachableBLOCKThe SDK's own answer when the gate does not respond

The verdicts on screen are the gate's own, produced by the same file a hook install runs. Nothing about a decision is reimplemented for the demo, which is why it is worth showing to someone who does not believe the claim.

The lookalike scenario is the one people remember. The registered address and the poisoned one differ by their last character, and to a model the two strings look equally plausible. The registry does not read plausibility.

Next

On this page