pipelock dashboard

September 4, 2026 · View on GitHub

Serve the read-only operator dashboard. The Evidence view is a web view over the signed action receipts in a flight-recorder evidence directory. It renders each recorder session with a four-line scorecard — Authentic, Untampered, Anchored, Completeness — where every line is an independent fact. There is deliberately no aggregate "all clear": Completeness is always limited to mediated traffic, Anchored is never green without an external inclusion proof, and signers are only shown as trusted when the operator configured their keys (never trust-on-first-use).

The Exemptions view is a read-only inventory over the loaded Pipelock config. It lists configured exemption-like knobs and flags only the inert or wrong-knob findings produced by the same config semantic analyzer used by pipelock doctor. It does not create, renew, apply, remove, or hot-reload exemptions, and it does not invent lifecycle telemetry: owner, expiry, last-matched, and suppressed-count columns are shown as not tracked.

The command ships in official release builds (enterprise-tagged) and requires a license that grants the agents feature (Pro or Enterprise); without one it refuses to start. The dashboard is read-only: it renders evidence and never mutates policy, receipts, or runtime state.

Views and license tiers

All views use the same dedicated listener, authentication boundary, CSP, access audit, and metadata-versus-raw redaction model.

ViewRouteLicense featurePermissionWhat it proves
Overview/overviewagentsdashboard:evidence:readRanked red/amber facts from the loaded evidence, fleet, governance, budget, and trust sources; no rolled-up green verdict.
Evidence/ and /session/...agentsdashboard:evidence:readPer-session receipt scorecard, timeline, and decision explanation from the configured recorder directory.
Exemptions/exemptionsagentsdashboard:exemptions:readRead-only exemption inventory from --config, with lifecycle metadata overlaid from --exemption-store when configured.
Agents/agents and /agent/...agentsdashboard:agents:readCross-session agent grouping and bounded scorecard rollups; absence means no loaded receipts, not proof the agent was idle.
Budgets/budgetsagentsdashboard:budgets:readCounts-only per-agent forward-proxy budget pressure from --runtime-snapshot-file or the default runtime snapshot. MCP denial-of-wallet counters are not included.
Trust & Keys/trust-keysagentsdashboard:trust_keys:readTrusted-key provenance, receipt blast radius, revocation status where verifiable, and local/Rekor anchor consistency.
Fleet/fleetfleetdashboard:fleet:readEnrolled follower runtime and signed applied-state status from the configured Conductor read source.
Workbench/workbenchfleetdashboard:signed_action:readPrepare, dry-run, and replay guidance for signed Conductor actions; no write path.
Incident/incidentfleetdashboard:incident:readRead-only correlation of a conductor decision, replay divergence, and fleet applied-state summary.

Grant dashboard:raw:read only as an extra elevation. It is never enough by itself to reach a route; the principal also needs that route's read permission.

pipelock dashboard serve

pipelock dashboard serve \
  --receipt-dir /var/lib/pipelock/evidence \
  --config /etc/pipelock/pipelock.yaml \
  --legal-hold-store /var/lib/pipelock/dashboard/legal-holds.json \
  --exemption-store /var/lib/pipelock/dashboard/exemptions.json \
  --auth-token-file /etc/pipelock/dashboard.token \
  --trusted-signer 'file=/etc/pipelock/receipt-signing.pub,source=ops runbook' \
  --conductor-url https://127.0.0.1:8895 \
  --conductor-token-file /etc/pipelock/conductor-auditor.token \
  --conductor-tls-cert /etc/pipelock/dashboard-conductor-client.pem \
  --conductor-tls-key /etc/pipelock/dashboard-conductor-client.key \
  --conductor-server-ca /etc/pipelock/conductor-server-ca.pem \
  --conductor-org org-main \
  --conductor-fleet prod

Then open http://127.0.0.1:8896/ in a browser (https:// when --tls-cert/--tls-key are set). The browser prompts for credentials: enter any username and the token file's contents as the password. Automation can send the same token as a bearer header:

curl -H "Authorization: Bearer $(cat /etc/pipelock/dashboard.token)" http://127.0.0.1:8896/

Create the token file once, readable only by the operator:

umask 077
openssl rand -hex 32 > /etc/pipelock/dashboard.token

Failed authentication audit events

When --config supplies emit sinks and token or OIDC authentication is enabled, each rejected dashboard request emits the warning event dashboard_auth_failed. Its structured fields are the event timestamp, remote_addr as the dashboard server received it, path, failure_reason (missing, malformed, or mismatch), and auth_mode (operator_token, oidc, or none when no credential was presented). The presented credential is never included. A count of auth_mode=operator_token events is the operator-token attack count; OIDC failures are attributed separately. Delivery is asynchronous and does not delay the authentication response. The dashboard does not apply rate limiting, throttling, or lockout to authentication attempts.

Authentication modes

The dashboard requires at least one of three authenticators, and each is a complete authenticator on its own — none depends on the others:

  • Operator token (--auth-token-file): a bearer token, optionally paired with a higher-privilege --raw-token-file.
  • OIDC (--oidc-issuer plus its required options): a verified bearer token whose mapped claim grants bounded permissions.
  • Mutual TLS (--require-client-cert plus the three mTLS file flags): a verified client certificate authorized through the role map.

You may combine token and OIDC, but mutual TLS is exclusive: when --require-client-cert is set the verified certificate is authoritative and supplies both route and raw-view permissions, so --auth-token-file and OIDC are neither required nor consulted. Starting with none of the three is a startup error.

Flags

FlagDefaultPurpose
--receipt-dir(required)Flight-recorder evidence directory holding action receipts (the runtime's flight_recorder.dir).
--confignoneOptional Pipelock config file for the read-only Exemptions inventory. When omitted, /exemptions renders an explicit "no config loaded" state and the Evidence view still works.
--auth-token-filenoneFile containing the operator token for token-authenticated requests. Required unless OIDC or --require-client-cert is configured. Grants the redacted metadata view.
--raw-token-filenoneOptional second, higher-privilege token that unlocks raw destinations and signed payloads. Must differ from --auth-token-file.
--legal-hold-storenoneOptional atomic JSON legal-hold metadata store displayed read-only by the governance sections.
--exemption-storenoneOptional exemption lifecycle store. Overlays owner, reason, expiry, and last-match metadata onto the read-only Exemptions inventory.
--delivery-inboxnoneOptional alert delivery inbox file for read-only delivery-health and dead-letter status.
--read-model-indexnoneOptional rebuilt dashboard read-model index file for freshness/source-hash status. Rebuild with pipelock dashboard rebuild-read-model.
--runtime-snapshot-file<receipt-dir>/dashboard/runtime-snapshot.jsonCounts-only proxy runtime snapshot used by the Budgets view.
--listen127.0.0.1:8896Dashboard listener address. Non-loopback addresses require --tls-cert/--tls-key.
--trusted-signernoneTrusted receipt signing key: (inline=HEX_OR_VERSIONED_PUBLIC_KEY|file=/path)[,source=LABEL]. Repeatable. source is shown in the UI as the reason the key is trusted.
--anchor-expectedfalseTreat a session with no anchor-state marker as an anchor audit failure in Trust & Keys.
--anchor-local-lognoneLocal anchor log used to verify anchor bundles produced with the local backend.
--rekor-log-keynonePinned Rekor log public key for verifying Rekor SET, checkpoint, and inclusion proof. Repeat for rotations.
--license-crl-filenoneSigned license revocation list; falls back to PIPELOCK_LICENSE_CRL_FILE.
--tls-cert, --tls-keynoneTLS server certificate and key. Both or neither.
--oidc-issuernoneOIDC issuer URL used for discovery and exact issuer validation.
--oidc-audiencenoneExpected OIDC audience. Required with --oidc-issuer unless --oidc-client-id is set.
--oidc-client-idnoneAlias for --oidc-audience; both values must match when both are set.
--oidc-role-claimnoneVerified token claim containing role or group values. Required with --oidc-issuer.
--oidc-role-mapnoneJSON mapping of verified claim values to bounded dashboard permissions. Required with --oidc-issuer.
--require-client-certfalseRequire a verified client certificate on every TLS connection and authorize it through the role map. Requires all three mTLS file flags below.
--client-ca-filenonePEM bundle of trust anchors used by TLS to verify client certificates. The bundle is capped at 1 MiB at startup.
--client-cert-role-mapnoneYAML file mapping client-certificate SPKI SHA-256 fingerprints to roles and bounded dashboard permissions.
--conductor-urlnoneOptional Conductor HTTPS base URL for read-only live fleet status. When omitted, live fleet panels render the explicit "no conductor source configured" state.
--conductor-token-filenoneFile containing the Conductor read bearer token. Required with --conductor-url; must authorize the configured org/fleet read.
--conductor-tls-cert, --conductor-tls-keynoneClient certificate and key used for Conductor mutual TLS. Both are required with --conductor-url.
--conductor-server-canonePEM CA bundle that signed the Conductor server certificate. Required with --conductor-url; the dashboard never falls back to plaintext or insecure TLS.
--conductor-org, --conductor-fleetnoneThe single org/fleet scope this dashboard is allowed to read from the Conductor. Required with --conductor-url; requests for any other scope are denied before the Conductor is queried.

Mutual TLS client authentication

Mutual TLS is a complete authenticator on its own: enable it with all of --require-client-cert, --client-ca-file, and --client-cert-role-map (plus server TLS via --tls-cert/--tls-key), with or without an operator token or OIDC. When enabled, the verified client certificate is authoritative: TLS requires a certificate on every connection, and the certificate's mapped role supplies both route and raw-view permissions and takes precedence over any token or OIDC principal. An absent, wrong-CA, or unmapped certificate is denied (the TLS layer rejects the first two; the fingerprint role map rejects the third), so a server-wiring or ordering bug cannot silently fall back to token access.

The role map uses the SHA-256 fingerprint of the leaf certificate's DER-encoded SubjectPublicKeyInfo (SPKI). This identity remains stable when a certificate is renewed with the same key. Role permissions must come from the dashboard's bounded permission vocabulary. Grant dashboard:raw:read only to roles that may view raw destinations and signed payloads.

Client certificates with RSA public keys smaller than 2048 bits or larger than 8192 bits are rejected after normal TLS verification and before the request reaches dashboard route authorization. EC and Ed25519 client certificates are unaffected.

version: 1
roles:
  metadata:
    permissions:
      - dashboard:evidence:read
      - dashboard:exemptions:read
      - dashboard:agents:read
      - dashboard:budgets:read
      - dashboard:trust_keys:read
  raw:
    permissions:
      - dashboard:evidence:read
      - dashboard:exemptions:read
      - dashboard:agents:read
      - dashboard:budgets:read
      - dashboard:trust_keys:read
      - dashboard:raw:read
  fleet-auditor:
    permissions:
      - dashboard:evidence:read
      - dashboard:fleet:read
      - dashboard:signed_action:read
      - dashboard:incident:read
certificates:
  0000000000000000000000000000000000000000000000000000000000000000: metadata

Replace the all-zero example key with the client certificate's SPKI SHA-256 fingerprint. The map also accepts colon-separated hexadecimal and an optional sha256: prefix. Unknown permissions, roles, fields, or fingerprints are hard startup errors; an empty certificate map is never treated as allow-all.

Start the dashboard with client-certificate verification as the sole authenticator (no --auth-token-file; add one only if you also want token access to non-mTLS paths, though the certificate role stays authoritative):

pipelock dashboard serve \
  --receipt-dir /var/lib/pipelock/evidence \
  --tls-cert /etc/pipelock/dashboard-server.pem \
  --tls-key /etc/pipelock/dashboard-server.key \
  --require-client-cert \
  --client-ca-file /etc/pipelock/dashboard-client-ca.pem \
  --client-cert-role-map /etc/pipelock/dashboard-client-roles.yaml

The standard library verifies the chain, validity period, and client-auth key usage before HTTP handling. Pipelock then maps only the verified leaf SPKI. A missing, expired, wrong-CA, or unmapped certificate is denied. If a request also carries a token, its certificate role remains authoritative for route and raw-view permissions; a metadata certificate cannot use a raw token to escalate.

OIDC identity-provider setup

In OIDC mode the dashboard validates every bearer token against the configured issuer and audience before authorizing it. Three claim checks are relevant when wiring an identity provider:

  • iss must exactly equal --oidc-issuer.
  • aud must contain --oidc-audience (aliased by --oidc-client-id).
  • azp, when present, must equal that same audience; a token with multiple audiences and no azp is rejected.

The common setup failure is the aud check. Many providers do not put the client ID in the access token's audience by default, so the token is rejected even though sign-in succeeds. Keycloak, for example, issues access tokens with aud: "account" unless you add an audience mapper. To use the dashboard with Keycloak, add an Audience protocol mapper to the client (or to a client scope it uses) whose included client audience is the dashboard client ID, then set --oidc-audience to that same client ID. The issued token then includes the client ID in its aud claim (alongside any audiences the provider already sets, such as account), so the "aud contains --oidc-audience" check passes. A token that then carries multiple audiences must also set azp to the client ID, which Keycloak does for the client that obtained the token; the dashboard requires that azp match when more than one audience is present.

Discovery and JWKS documents are size-bounded, duplicate JSON members are rejected, only RS256 signing keys are accepted, and token claims are decoded only after the signature verifies. An unknown JWT kid triggers at most one bounded JWKS refresh per refresh window. Additional unknown-key requests inside that window fail closed without refetching the JWKS endpoint; a throttled refresh never authenticates the request.

Pick a role source with --oidc-role-claim and map it to bounded dashboard permissions with --oidc-role-map. The role claim can be azp (the client ID, useful for a single-client deployment) or a groups/roles claim your provider adds to the token. As with the mTLS role map, permissions must come from the dashboard's bounded vocabulary and an unmapped principal is denied.

Example OIDC role map:

{
  "claim_values": {
    "pipelock-dashboard-auditor": "auditor"
  },
  "roles": {
    "auditor": [
      "dashboard:evidence:read",
      "dashboard:exemptions:read",
      "dashboard:agents:read",
      "dashboard:budgets:read",
      "dashboard:trust_keys:read"
    ]
  }
}

Upgrade note: OIDC route permissions are now enforced

Earlier releases derived dashboard route permissions from the operator-token tier alone, so any authenticated OIDC principal reached every metadata-tier view regardless of the permissions its mapped role granted. Only raw-view access consulted the role map. Route permissions now come from the mapped role, which is the behavior this page has always described.

If an OIDC role map was written against the earlier behavior it may be narrower than the access its users actually had, and those users will lose views they previously reached. Before upgrading, confirm each role in --oidc-role-map lists every permission its holders need. A principal that reaches a view it is not mapped for is denied, and the denial names the missing permission in the audit log.

dashboard serve loads --config only when the flag is provided, using the normal Pipelock config loader. The loaded config feeds the /exemptions view; it does not grant the dashboard authority to mutate policy or reload runtime state. If --config is omitted, the Exemptions view reports that no config was loaded.

License resolution still follows the paid-surface gate: the command resolves the license token from PIPELOCK_LICENSE_KEY and verifies it against the build-embedded public key (or PIPELOCK_LICENSE_PUBLIC_KEY on unofficial builds). Verification fails closed before any listener binds, and the feature entitlement is re-checked on every request, so a license that expires while the server is running stops serving.

Security model

  • Dedicated listener, never the proxy port. The dashboard binds its own address, following the same port-isolation principle as kill_switch.api_listen: an agent routed through the proxy has no path to its own evidence view. Isolation from an agent running on the same host as a different user is deployment guidance (containment/network policy), not a property this command can enforce by itself — which is why authentication is required even on loopback.
  • The license check is entitlement, not identity. Token-only mode requires the operator token (constant-time comparison), as a Bearer header or as the Basic-auth password. OIDC mode requires a verified bearer token whose mapped roles grant bounded dashboard permissions. With mutual TLS enabled, every connection must present a verified certificate mapped to a role. Missing or invalid authentication gets no evidence.
  • Embedded handlers fail closed without an auth boundary. The pipelock dashboard serve command wires its configured token, OIDC, or mTLS auth boundary into the dashboard handler. Go embedders that construct the dashboard handler directly and authenticate in an outer router must explicitly set TrustedOuterAuth; otherwise, leaving both authorization callbacks nil returns 403 for every route instead of serving unauthenticated.
  • Cleartext refusal. Without TLS the listener only accepts loopback addresses; serving a non-loopback address over plain HTTP is refused at startup because the operator token would transit in cleartext.
  • No trust-on-first-use. Signer keys are trusted only via --trusted-signer. With no trusted keys configured the dashboard still serves, and the Authentic line honestly reports every signer as Unverified.
  • Redacted by default (least privilege). The metadata token sees the scorecard, hashes, timeline verdicts/reasons/timestamps, and the offline verify command — but receipt destinations and full signed payloads are redacted, because a destination URL can carry a capability token and the raw payload is the largest exfil surface. Token-authenticated requests receive raw detail only with --raw-token-file; OIDC and client-certificate requests receive it only when their mapped permissions include dashboard:raw:read (fail closed). Redaction happens before templating, so the raw bytes never reach a metadata-view response. The scorecard — the actual proof — does not depend on the raw fields.
  • Access is audited. Every authenticated request is written to an access log on stderr (role metadata or raw, dashboard permission, method, path, session, remote address, auth method, mapped roles, and redacted principal attribution). Token requests record auth_method=token or auth_method=raw-access-token without token bytes. OIDC requests record the subject only as auth_subject_sha256 plus mapped roles. mTLS requests record the leaf certificate SPKI fingerprint as mtls_spki_sha256 plus the mapped role. Denied authentication and permission checks include a bounded failure category such as missing_token, missing_client_certificate, unmapped_client_certificate, permission_denied, expired, or invalid_token. Audit log compatibility note: this release replaces raw auth_subject output with auth_subject_sha256 and adds mtls_spki_sha256 and permission fields on denial records. SIEM parsers that key on the old raw subject field must migrate to the hashed subject field. Existing denial reason= values for missing tokens, missing client certificates, unverified client certificates, unmapped client certificates, and role permission denial remain stable.
  • Exemptions is inventory only. /exemptions is GET-only and reads the already-loaded config snapshot. It has no POST route, no apply/remove/renew controls, no config write path, and no hot-reload hook.
  • Conductor reads are scoped and read-only. When --conductor-url is set, the dashboard uses mutual TLS plus a bearer token to issue GET requests to the Conductor followers roster, stream metadata, and decision replay-by-hash read endpoints for the configured --conductor-org / --conductor-fleet. It never holds a signing key and has no publish, kill, resume, rollback, enroll, revoke, or delete method.
  • Sensitive by design. Even the metadata view exposes reasons, signer fingerprints, and session IDs. Treat the listener like an admin API: keep it loopback or behind TLS on a network only operators reach.

Verify it yourself

The dashboard is a lens, not the proof. Every session view includes the exact offline pipelock-verifier verify-run command that re-verifies the same receipts against the trusted key, so anything the dashboard claims can be independently re-checked against the signed evidence — without trusting this server.

Free single-session evidence server

pipelock evidence serve is the no-license, single-agent counterpart to the Pro dashboard Evidence view. It binds exactly one session at startup and has no route or query parameter that can switch to another session.

pipelock evidence serve \
  --receipt-dir /var/lib/pipelock/evidence \
  --session agent-a \
  --listen 127.0.0.1:8897

If the receipt directory contains only one session, --session can be omitted. If it contains multiple sessions, --session is required so the free viewer cannot enumerate other agents.

Exemption lifecycle store

The Exemptions page reads config state; lifecycle mutation stays in the CLI. Create and maintain lifecycle records with the dashboard exemption command family, then point dashboard serve at the same store:

pipelock dashboard exemption add \
  --store /var/lib/pipelock/exemptions.json \
  --scope response_scanning.exempt_domains:api.vendor.example \
  --owner security-team \
  --reason "vendor docs include benign instruction-like examples" \
  --expiry 2026-10-01T00:00:00Z

pipelock dashboard exemption list --store /var/lib/pipelock/exemptions.json
pipelock dashboard exemption renew --store /var/lib/pipelock/exemptions.json --id exm_0123456789abcdef --expiry 2026-12-01T00:00:00Z
pipelock dashboard exemption expire --store /var/lib/pipelock/exemptions.json --id exm_0123456789abcdef

add, renew, expire, touch, remove, and list are the mutation and inspection surface. Use the exm_... ID printed by add or list when renewing or expiring a record. The HTTP dashboard overlays owner/reason/expiry/status read-only and redacts owner/reason unless the request has raw access.

Coverage certificates

A coverage certificate is a signed statement about one agent over a time window. It summarizes mediated-egress receipt integrity and completeness for that agent only; it does not claim all agent activity or no bypass outside Pipelock.

Generate requires the Pro agents feature:

pipelock dashboard coverage-cert generate \
  --receipt-dir /var/lib/pipelock/evidence \
  --agent agent-a \
  --window-start 2026-07-01T00:00:00Z \
  --window-end 2026-07-12T00:00:00Z \
  --trusted-receipt-signer file=/etc/pipelock/keys/receipt-signing.pub,source=security-team \
  --signing-key /etc/pipelock/keys/coverage-cert.key \
  --out agent-a-coverage.json

When --trusted-receipt-signer is supplied, generation verifies each session's receipt chain against that trusted signer set. Its CLI output says receipt chains: verified against trusted signer set. Without it, generation uses self-consistency checks and prints receipt chains: self-consistent only.

Verify is free and offline:

pipelock evidence verify-cert \
  --cert agent-a-coverage.json \
  --trusted-signer file=/etc/pipelock/keys/coverage-cert.pub,source=security-team

Verification exits zero only when the certificate signer is in the --trusted-signer set. With no trusted signer, verification fails closed by default. Pass --allow-unpinned only for an explicit structural-only check; that output is labeled STRUCTURAL ONLY and does not report the signer as trusted.

Backup, restore, and read-model rebuild

Dashboard durable stores are the JSON files that cannot be reconstructed from receipts, such as exemption lifecycle state, legal holds, and delivery inbox state. Keep those stores under one state directory and back up that directory:

pipelock dashboard backup \
  --state-dir /var/lib/pipelock/dashboard \
  --legal-hold-store /var/lib/pipelock/dashboard/legal-holds.json \
  --exemption-store /var/lib/pipelock/dashboard/exemptions.json \
  --output /var/backups/pipelock-dashboard-state.tar

pipelock dashboard restore \
  --state-dir /var/lib/pipelock/dashboard \
  --legal-hold-store /var/lib/pipelock/dashboard/legal-holds.json \
  --exemption-store /var/lib/pipelock/dashboard/exemptions.json \
  --input /var/backups/pipelock-dashboard-state.tar

Restore validates the archive and writes each file atomically with best-effort whole-set rollback. It is not a cross-file transaction; if a process crashes between file writes, re-run restore to converge.

The read model is disposable and should be rebuilt from recorder evidence, not backed up as authority:

pipelock dashboard rebuild-read-model \
  --receipt-dir /var/lib/pipelock/evidence \
  --output /var/lib/pipelock/dashboard/read-model-index.json

The web dashboard never creates or releases a hold. An operator changes the durable metadata store through the licensed CLI, then points dashboard serve at the same file:

pipelock dashboard legal-hold add \
  --store /var/lib/pipelock/legal-holds.json \
  --id investigation-2026-07 \
  --scope agent-a \
  --reason 'preserve mediated-egress evidence for active review'

pipelock dashboard legal-hold release \
  --store /var/lib/pipelock/legal-holds.json \
  --id investigation-2026-07

The store contains only metadata that cannot be reconstructed from receipts: ID, scope, reason, creation time, and optional release time. Writes are atomic; the file is mode 0600 and its directory is created as 0750. A corrupt store fails closed at CLI or dashboard startup instead of silently showing no holds.

Signed Action Workbench and Incident Cockpit (Enterprise fleet tier)

The dashboard adds two Enterprise fleet-tier pages, /workbench and /incident. Both require a license that grants the fleet feature; a license with only the agents feature gets 403 on these routes while the agent-tier Evidence, Agents, and Exemptions views keep working. They are served by the same pipelock dashboard serve command and reuse its authentication, cleartext-refusal, audit-log, and redaction seams.

Both pages are prepare / verify / replay only. Neither can execute, submit, or otherwise mutate fleet state:

  • Every route is GET-only; a mutating HTTP method returns 405.
  • The only conductor seam these pages consume is read-only: it re-derives a decision (dry-run / replay) and never publishes, kills, resumes, or rolls back anything. There is no publish/kill/rollback method on that seam and no write path reachable from the dashboard.
  • The operator prepares and submits an action with the shipped conductor CLI outside the dashboard. The workbench's job ends at "here is the predicted effect and the command template to run".

Signed Action Workbench (/workbench)

The workbench has two parts. Prepare and submit guidance is a static, per-request-identical list of the shipped conductor commands an operator runs outside the dashboard: pipelock conductor publish …, pipelock conductor kill … (and resume), and pipelock conductor rollback …. The dashboard only displays these commands; it never runs them.

Verify / replay a past decision: with a conductor decision source wired, supply ?org_id=<org>&fleet_id=<fleet>&artifact_hash=<hash> to re-derive the conductor authorization and effect decision for a past signed action under the current fleet and policy state. The panel surfaces the re-derived verdict and a loud Divergence flag when the re-derived decision no longer matches what was recorded. Replay does not re-derive proxy content-scan verdicts, and does not prove any action executed or was prevented outside the conductor decision. The dashboard sends only the configured org/fleet and canonical artifact hash to Conductor; Conductor resolves the recorded signed artifact server-side and returns only the replay projection, never bundle payloads, signature bytes, or signing material. If no recorded decision matches, the page says no decision was found. If Conductor cannot complete the replay, the page fails closed with an error instead of rendering a clean or no-divergence verdict.

Incident Cockpit (/incident)

A read-only correlation lens. Supply ?org_id=<org>&fleet_id=<fleet>&artifact_hash=<hash> to correlate one conductor decision with its replay divergence (from the read-only decision source) and a bounded fleet applied-state summary — counts of enrolled followers by applied-state source (verified / signed-but-unverified / unsigned / no report), plus drift and apply-failed counts. The cockpit never kills an agent, publishes, or mutates fleet state, and does not prove no bypass occurred outside Pipelock, outside enrolled followers, or outside the report window.

With --conductor-url configured, the fleet applied-state summary reads the configured Conductor follower roster and runtime/applied-state status for the single configured org/fleet. The decision panel uses the same configured Conductor read source to replay by artifact hash. A missing source, a missing recorded decision, and a failed replay are rendered as distinct states.

Redaction on these pages

Like the other views, these pages redact by default. In the metadata view (--auth-token-file), decision artifact/result/recorded hashes, result versions, and the free-text divergence reason are hidden; the computed status — validity, the bounded conflict code, and the loud divergence flag — is always shown. The fleet applied-state summary is counts only, carries no follower identifiers, and is shown in full even in the metadata view. Raw detail is shown only to a request that authenticates with --raw-token-file, or whose verified OIDC or client-certificate mapping contains dashboard:raw:read. There is deliberately no aggregate "all clear".