Approval Dashboard¶
Rampart includes an embedded web dashboard for managing approval-gated decisions. View pending approvals, approve or deny them, and review decision history — all from your browser.
Accessing the Dashboard¶
The dashboard is available when running rampart serve:
# Start the server
rampart serve --config ~/.rampart/policies/my-policy.yaml --port 9090
# Dashboard is at:
# http://localhost:9090/dashboard/
Authentication¶
The dashboard HTML is served without authentication — it contains no secrets. All data is fetched from the /v1/approvals API, which requires a Bearer token.
When rampart serve starts, it prints the token:
Enter this token in the dashboard's token field. It's stored in your browser's localStorage — never sent to any external service.
Admin Token vs. Per-Agent Tokens¶
Rampart has two distinct token types:
- Admin token — generated at startup, printed to stdout, and stored in
~/.rampart/token. Full access to all dashboard APIs. - Per-agent tokens — created with
rampart token create <name>. Scoped to specific policy profiles; useful for restricting what a particular agent can approve or query.
Both token types can authenticate to the dashboard and the /v1/approvals API. The difference is scope: per-agent tokens may be restricted to a subset of policies (e.g., a codex token that can only operate within the standard profile). Use per-agent tokens when running multiple agents with different trust levels.
Features¶
- Pending approvals: See all approval-gated decisions waiting for human input
- Approve / Deny: Click to resolve approvals directly from the browser
- History: View past decisions with timestamps, agents, commands, and who resolved them
- Auto-refresh: Dashboard polls for new approvals automatically
Security Model¶
| Component | Auth Required? | Notes |
|---|---|---|
| Dashboard HTML/CSS/JS | No | Static files, no embedded secrets |
GET /v1/approvals | Yes (Bearer token) | Lists pending and resolved approvals |
POST /v1/approvals/{id}/resolve | Yes (Bearer OR signed URL) | Resolves a pending approval |
Signed URLs: When webhooks fire for approval-gated decisions, the notification includes a self-authenticating signed URL. Recipients can approve/deny by clicking the link without needing the Bearer token.
Network Access¶
By default, rampart serve binds to 127.0.0.1 (localhost only). To expose it:
- LAN access: Use
--addr 0.0.0.0to bind to all interfaces - Tailscale: Use
--addr <tailscale-ip>for secure remote access without exposing to the internet - Reverse proxy: Put nginx/Caddy in front with your own auth
Warning
The dashboard token grants full approval authority. Treat it like a password. Don't expose the port to the public internet without additional authentication.
API Reference¶
The dashboard uses the same REST API available to any client:
# List approvals
curl http://localhost:9090/v1/approvals \
-H "Authorization: Bearer $TOKEN"
# Approve
curl -X POST http://localhost:9090/v1/approvals/APPROVAL_ID/resolve \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"approved": true, "resolved_by": "trevor"}'
# Deny
curl -X POST http://localhost:9090/v1/approvals/APPROVAL_ID/resolve \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"approved": false, "resolved_by": "trevor", "reason": "not authorized"}'
Integration with Hooks¶
When Claude Code triggers an ask policy, the flow is:
- Hook returns
permissionDecision: "ask"— Claude Code shows native approval prompt - Approval is also created in the server's approval store
- Dashboard shows the pending approval
- Webhooks fire (if configured) with signed approve/deny URLs
The first resolution wins — whether from Claude Code's prompt, the dashboard, a webhook link, or the API.