Security → Audit events

Audit events

Current status: shipped. The Central Server reports Tunnel lifecycle events to an organization-scoped audit API in real time, they are stored in a durable database keyed by organization, and organization members can view them in a filterable, paginated activity log. This is live today, not a roadmap item.

How it works

  1. The Central Server posts each lifecycle event to POST /api/audit/events, authenticated with a server-to-server API key.
  2. Events are stored durably, one row per event, indexed by organization ID and creation time.
  3. Organization members can view their own organization's events at Activity in the admin console, filterable by event type and paginated.
  4. Events can also be retrieved programmatically via GET /api/organizations/<organization_id>/audit-events, scoped strictly to that organization.

Event types reported today

Event typeWhen
client_connectedA Client completes registration and nonce verification.
agent_connectedAn Agent completes registration and nonce verification.
relay_connectedA customer Private Relay completes registration and nonce verification.
client_disconnectedA Client WebSocket connection closes.
agent_disconnectedAn Agent WebSocket connection closes.
tunnel_requestedA Client requests a Tunnel, before policy evaluation.
access_deniedOrganization, Device, protocol, or Agent-access policy rejects the request.
duplicate_tunnelA duplicate connection is rejected while an authenticated session is already active.
p2p_tunnel_establishedDirect Tunnel negotiation succeeds.
p2p_tunnel_failedDirect Tunnel negotiation fails.
p2p_tunnel_endedAn established direct Tunnel ends.
tunnel_startedA Relay-mediated Tunnel becomes active.
tunnel_endedA Relay-mediated Tunnel is torn down.
tunnel_errorA Tunnel setup or connection operation fails.
relay_errorA Relay process or Relay connection fails.
device_errorAn authenticated Client or Agent reports a local failure.
tls_observedThe Client observes a TLS endpoint certificate. The event records the endpoint, transport, verification result, hostname-verification result, leaf-certificate SHA-256, and whether the stored baseline changed.

These 17 values are the complete organization audit-event contract accepted by the management API. Server operational logs such as device_authentication, control_message_signature, and audit_event_delivery are deliberately kept out of the organization Activity log.

What each event contains

Every stored event carries: organization ID, event type, Tunnel/session ID, Client and Agent identifiers and hostnames, requesting username, Relay identifier and kind (if a Relay was used), the requested Service and port, transport (p2p, p2p_tcp, p2p_udp, or relay), a short reason code, a free-text message, the reporting Device's IP address and cached location (when available), and a timestamp. A successful UDP direct-Tunnel event can additionally include path (direct_host for a LAN/VPN candidate or direct_nat for a STUN-mapped candidate), client_peer_address, and agent_peer_address. Peer addresses may be private LAN/VPN addresses or public mapped addresses.

tls_observed additionally carries tls_endpoint, tls_transport, tls_verified, tls_hostname_verified, tls_leaf_sha256, and tls_baseline_changed. TunnelCrib records the leaf certificate's SHA-256 fingerprint; it does not store the certificate chain in the audit event.

Events do not contain WebSocket bearer tokens, private keys, SSH public-key material, nonce values, raw WebSocket payloads, or Service application traffic — the audit pipeline only ever receives the structured fields above, not arbitrary connection data.

One nuance worth stating precisely: the device_error event's message field is free text supplied by the reporting Client or Agent (truncated to 2000 characters) describing a local failure — for example a failed dial or a private-host substitution. It comes from an already-authenticated Device, not an arbitrary source, but it is not a strictly allowlisted structured field the way the other columns are. Avoid characterizing every field in the audit log as fully server-validated metadata; this one is reporter-supplied text.

Access and retention

Audit events are scoped to the reporting organization at both the ingestion and read paths; there is no cross-organization query surface. Viewing the activity log in the admin console requires an authenticated session in that organization.

Last reviewed 2026-10-22.

For the underlying event-type constants and API implementation, see the app/api.py module in TunnelCrib admin and server/main.py in the engineering repository.