---
type: reference
---

# Dashboard

The customer's account UI — one of four [management modalities](management-api.md), alongside OpenAPI, MCP, and Terraform. All four read and write the same canonical management API; the dashboard is the human-facing surface.

## Signing in

Three paths into the dashboard — magic link, Continue with GitHub, Continue with Google. All three resolve to the same account row keyed by email; the platform stores your email and nothing else. Mechanism in [account-login](account-login.md); step-by-step in [guides/sign-up-and-login](guides/sign-up-and-login.md). The session itself is D1-backed and revocable — sign out anywhere kills the session immediately.

Per site key, the dashboard exposes:

| Surface | Purpose |
|---|---|
| Public site key | Used in the [widget](widget.md)'s `sitekey` attribute |
| Secret | Used by the customer backend when calling [`/siteverify`](api.md#post-siteverify-customer-backend--platform). Rotatable. |
| Allowed domains | Origin allowlist for the widget |
| Aggregate stats | `sessions started`, `sessions client-completed`, `sessions server-verified` — counts only |
| Integration health diagnostics | Derived from gaps between the three counts above |

## What is intentionally absent

- **No game pool config.** Pool selection is a widget-side `games=` attribute — see [widget](widget.md). There is no server-side allowlist or pinned set. See [principles](principles.md#honesty-over-theater).
- **No game allowlist.** Customers choose their own games per page; the platform doesn't gate which ones they're allowed to use.
- **No user data anywhere.** Per-site-key aggregate counters only — no IPs, no UAs, no geo, no per-user history. See [privacy](privacy.md).
- **No risk thresholds, score histograms, or behavioral charts.** The score is [game metadata](principles.md#game-data-is-metadata-not-security), not a security signal.

## Integration health diagnostics

The three counters are deliberately structured so their gaps tell you something useful:

- `sessions started` – `sessions client-completed` ≈ user drop-off (game too hard, slow load, accessibility gap)
- `sessions client-completed` – `sessions server-verified` ≈ customer integration problem (forgot to call `/siteverify`, bad secret, network issue on backend)

That's the entire analytics layer. Anything more would require collecting data we structurally [refuse to collect](privacy.md).

## Secret rotation

Customers can rotate the secret at any time. The dashboard issues a new secret; the old secret continues to verify tokens for a short overlap window so the customer can deploy the new one without downtime. (Specific window length will be documented when the rotation flow ships in [phase 3](roadmap.md#build-phases).)

## Site key shape

- Public key: `cpt_pub_...`
- Secret: `cpt_sec_...`

Prefixes make leaked-secret detection (e.g. GitHub secret scanning) trivial to wire up later.

## Management API tokens

Account-level credentials for the non-UI [management modalities](management-api.md) (OpenAPI, MCP, Terraform). Distinct from the per-site-key `cpt_sec_...` (which is for runtime [`/siteverify`](api.md#post-siteverify-customer-backend--platform) only).

| Surface | Purpose |
|---|---|
| Token issue | Mint a new management token (`cpt_pat_...`). Shown once at issue time; not retrievable afterwards. |
| Token list | Names, prefixes, last-used timestamp, scope (when scopes ship). Never the full token. |
| Token revoke | Immediate; revoked tokens stop authenticating on the next request. |

A leaked management token compromises account configuration; a leaked `cpt_sec_...` only compromises one site key's verification. Different blast radii — different rotation cadences are appropriate.

## Paid-tier surfaces

Visible only on paid site keys. Free-tier accounts do not see these sections.

| Surface | Purpose |
|---|---|
| Hosted verification toggle | Enables the [hosted-verification](hosted-verification.md) forwarder for the site key |
| Destination configuration | Webhook URL and / or email address. Both can be enabled simultaneously. |
| Webhook signing key | Issued when a webhook destination is added; used by the customer's handler to verify incoming requests |
| Forwarder URL | The Caputchin URL the customer points their form's `action` at |

Hosted-verification configuration follows the same posture as the rest of the dashboard: aggregate counters on delivery success / failure, no per-submission history. See [ADR-0007](adr/0007-hosted-verification-paid-only.md) for the rationale.

## Scoreboards (Post-MVP)

Per-site-key, per-game leaderboard view. Surfaces top-N entries plus an aggregate score distribution. Entries display the session-scoped 3-letter handle collected by the [widget](widget.md); rows whose nickname was never submitted render as `---`. No sort, filter, or query by nickname is exposed — the column is display-only. Same privacy posture as the rest of the dashboard: no per-user dimension, no IPs / UAs / geo, no cross-session linkage. See [ADR-0014](adr/0014-scoreboard-3letter-async-naming.md) for the design.
