Receipt Dashboard
Chio ships a built-in operator dashboard that visualizes the kernel receipt log in real time. It is a React SPA served directly by the trust-control service, so there is no separate web tier to operate. Point a browser at the trust-control bind address and every receipt, spend line, and budget pressure signal is already indexed and filterable.
What It Shows
The dashboard is a thin skin over the same HTTP API the chio CLI uses. Every panel is driven by a documented endpoint on the trust-control service, so the view in the browser and the view from the CLI stay in sync. No client-side reconstruction, no shadow scoring path.
- Receipts by agent: filter on an agent subject (hex-encoded ed25519 public key) to see only receipts produced against that agent's capability tokens.
- Receipts by tool server and tool name: exact-match filters for narrowing to a single surface.
- Receipts by outcome: the four
Decisionvariants.allow,deny,cancelled,incomplete. - Budget pressure: per-grant utilization with near-limit and exhaustion counters.
- Time range: unix-second
since/untilwindow applied to every query.
The browser and the CLI see the same thing
GET /v1/receipts/query. A dashboard view and the equivalent chio receipt list invocation return the same rows in the same order.Layout at a Glance
The dashboard is a three-pane layout: filters on the left, a composed operator summary across the top, and a paginated receipt table that opens a detail panel on click.
Clicking any row opens a detail panel on the right. The panel renders the full receipt JSON, financial metadata (cost charged, budget remaining, total budget, delegation depth, settlement status, all formatted from minor units), a per-day cost sparkline, and the full delegation chain from root capability to leaf.
Operator Summary
Above the receipt table sits a composed operator summary backed by GET /v1/reports/operator. It is not a client-side reconstruction over paged receipts. The summary is the primary view for answering the question is this agent or tool slice healthy and exportable right now?
| Panel | Surfaces | Use For |
|---|---|---|
| Activity | Receipt totals, allow / deny ratio | Is this slice doing anything at all |
| Spend | Spend totals plus top root budget holder | Who is driving cost in the filtered window |
| Budget Pressure | matchingGrants, nearLimitCount, exhaustedCount | Grants about to trip or already tripped |
| Compliance Posture | checkpointCoverageRate, lineageCoverageRate, uncheckpointedReceipts | Audit readiness of the receipt log |
| Settlement Readiness | pendingSettlementReceipts, failedSettlementReceipts, proof completeness | Is this slice exportable for invoicing |
| Shared Evidence | Reference counts plus the latest referenced partner / share | Federated reputation context |
Export-scope caveats are first class
Filtering Receipts
The left sidebar exposes six filters. All of them map directly to GET /v1/receipts/query. Changing any filter resets pagination to page 1. Results are paginated 50 per page, with cursor-based previous and next controls.
| Filter | Type | Description |
|---|---|---|
| Agent Subject | Hex ed25519 pubkey | Only receipts produced against this agent's capability tokens |
| Tool Server | Exact-match string | Single tool server identifier |
| Tool Name | Exact-match string | Single tool name within a server |
| Outcome | Enum | allow, deny, cancelled, incomplete |
| Since | Unix seconds (u64) | Lower bound on receipt timestamp |
| Until | Unix seconds (u64) | Upper bound on receipt timestamp |
Launching the Dashboard
The dashboard is compiled into the trust-control binary at build time. Starting chio trust serve starts the dashboard too, on the same address as the control API.
Local development
# Default bind: 127.0.0.1:8940
$ chio trust serve \
--receipt-db ./receipts.sqlite \
--authority-db ./authority.sqlite \
--revocation-db ./revocations.sqlite \
--receipt-dashboard-bind 127.0.0.1:8940
# Then open http://127.0.0.1:8940/ in a browserThe trust-control server serves the dashboard bundle as a static catch-all after all API routes, so the same address hosts the API and the UI. There is no second port to open.
Docker compose
services:
chio-trust:
image: chio/trust-control:latest
command:
- chio
- trust
- serve
- --receipt-dashboard-bind
- 0.0.0.0:8940
- --receipt-db
- /var/lib/chio/receipts.sqlite
- --authority-db
- /var/lib/chio/authority.sqlite
- --revocation-db
- /var/lib/chio/revocations.sqlite
ports:
- "8940:8940"
volumes:
- chio-state:/var/lib/chio
environment:
CHIO_ADMIN_TOKEN_FILE: /run/secrets/chio_admin
secrets:
- chio_admin
volumes:
chio-state:
secrets:
chio_admin:
file: ./secrets/chio_admin.txtAuthentication
Every request the dashboard makes is bearer-authenticated. The token is resolved in this order:
sessionStoragekeychio_token(set from a previous visit).- URL query parameter
?token=<value>.
When a token is found in the URL it is promoted to sessionStorage and removed from the URL bar via window.history.replaceState. That keeps the token out of browser history and out of the Referer header on outbound navigations.
# Hand an operator a one-shot URL
$ echo "http://127.0.0.1:8940/?token=$(cat ./secrets/chio_admin.txt)"
http://127.0.0.1:8940/?token=sv_live_8f2c...No token means no data
Closing the tab clears sessionStorage. Reopening the dashboard later requires either a fresh ?token= URL or the previous tab still being alive.
Receipt Detail Panel
Clicking a row opens a right-hand detail panel that renders everything needed for a spot audit without leaving the browser.
- Decision badge (Allow, Deny, Cancelled, Incomplete).
- Tool server and tool name, plus a formatted timestamp.
- Full capability ID.
- Financial metadata when present: cost charged, budget remaining, total budget, delegation depth, settlement status. All formatted from minor units using the receipt's own currency field.
- Agent subject key when attribution metadata is present.
- Cost-over-time sparkline, aggregated per day by the backend analytics API for the receipt subject.
- Raw tool-call parameters.
- Full receipt JSON for copy-paste into tickets.
Delegation chain view
The DelegationChain component fetches GET /v1/lineage/{capability_id}/chain and renders every CapabilitySnapshot in the chain from root to leaf. Each snapshot shows subject_key, issuer_key, issued_at, expires_at, delegation_depth, and the raw grants JSON. Operators can trace exactly how a capability was delegated and attenuated before it reached the agent.
Budget sparkline
When the selected receipt has financial metadata, the panel renders a BudgetSparkline backed by GET /v1/receipts/analytics?agentSubject=...&timeBucket=day. It uses the receipt's attribution subject key, falling back to capability lineage when attribution metadata is absent. The chart is inline SVG, which keeps the dashboard bundle small without pulling in a charting framework.
Portable Reputation Comparison
When the Agent Subject filter is set, an extra panel appears above the receipt table. Operators can upload a passport JSON artifact and the dashboard calls POST /v1/reputation/compare/{subject_key} on the trust-control service.
The panel renders:
- Subject match vs mismatch between the live local subject key and the passport subject DID.
- Current local effective score and resolved tier.
- Optional relying-party acceptance state when the uploaded artifact already carries a verifier-evaluation result.
- Per-credential drift for composite score, reliability, delegation hygiene, and resource stewardship.
- Shared-evidence provenance: partner and share IDs, remote capability IDs, local anchor capability IDs, and local receipt counts.
Single source of truth
chio reputation compare --control-url .... There is no second local scoring path embedded in the dashboard.Shared Evidence API
Trust-control exposes GET /v1/federation/evidence-shares, which returns the same shared-evidence report shape used inside operator reports and portable reputation comparison. The CLI wrapper is:
$ chio trust evidence-share list \
--agent-subject <subject-hex> \
--jsonThis surfaces imported remote evidence references directly without merging foreign receipts into native local receipt history. The dashboard uses the same endpoint for its shared-evidence summary card.
Configuration Reference
A minimal trust-control YAML that exposes the dashboard on the same port as the API looks like this:
trust_control:
bind: 127.0.0.1:8940
receipt_db: ./state/receipts.sqlite
authority_db: ./state/authority.sqlite
revocation_db: ./state/revocations.sqlite
# Dashboard bind defaults to the trust-control bind.
# Override only when you want the UI on a different address.
receipt_dashboard_bind: 127.0.0.1:8940
admin_token_file: ./secrets/chio_admin.txt# Equivalent CLI invocation
$ chio trust serve \
--bind 127.0.0.1:8940 \
--receipt-dashboard-bind 127.0.0.1:8940 \
--receipt-db ./state/receipts.sqlite \
--authority-db ./state/authority.sqlite \
--revocation-db ./state/revocations.sqlite \
--admin-token-file ./secrets/chio_admin.txtFor deeper queries on individual receipts, consult the receipt format reference. The dashboard renders the exact same struct, field for field.