Chio/Docs

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 Decision variants. allow, deny, cancelled, incomplete.
  • Budget pressure: per-grant utilization with near-limit and exhaustion counters.
  • Time range: unix-second since / until window applied to every query.

The browser and the CLI see the same thing

Every filter on the sidebar maps directly to a query parameter on 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.

rendering…
Three-pane dashboard: filter sidebar on the left, composed operator summary across the top, paginated receipt table beneath.

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?

PanelSurfacesUse For
ActivityReceipt totals, allow / deny ratioIs this slice doing anything at all
SpendSpend totals plus top root budget holderWho is driving cost in the filtered window
Budget PressurematchingGrants, nearLimitCount, exhaustedCountGrants about to trip or already tripped
Compliance PosturecheckpointCoverageRate, lineageCoverageRate, uncheckpointedReceiptsAudit readiness of the receipt log
Settlement ReadinesspendingSettlementReceipts, failedSettlementReceipts, proof completenessIs this slice exportable for invoicing
Shared EvidenceReference counts plus the latest referenced partner / shareFederated reputation context

Export-scope caveats are first class

The settlement readiness card calls out export-scope caveats directly. If a slice has pending settlement receipts, failed settlement receipts, or incomplete proofs, the dashboard tells you before you attempt an invoice export instead of after.

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.

FilterTypeDescription
Agent SubjectHex ed25519 pubkeyOnly receipts produced against this agent's capability tokens
Tool ServerExact-match stringSingle tool server identifier
Tool NameExact-match stringSingle tool name within a server
OutcomeEnumallow, deny, cancelled, incomplete
SinceUnix seconds (u64)Lower bound on receipt timestamp
UntilUnix 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

bash
# 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 browser

The 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

docker-compose.yml
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.txt

Authentication

Every request the dashboard makes is bearer-authenticated. The token is resolved in this order:

  1. sessionStorage key chio_token (set from a previous visit).
  2. 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.

bash
# 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

If no token is present the dashboard renders an explicit operator guidance state. It does not fall back to issuing unauthenticated requests, so a misconfigured deployment fails loud instead of silently leaking receipt metadata.

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

The browser uses the same comparison contract as 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:

bash
$ chio trust evidence-share list \
    --agent-subject <subject-hex> \
    --json

This 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:

chio-trust.yaml
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
bash
# 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.txt

For deeper queries on individual receipts, consult the receipt format reference. The dashboard renders the exact same struct, field for field.

Receipt Dashboard · Chio Docs