Security → Audit events
POST /api/audit/events, authenticated with a server-to-server API key.GET /api/organizations/<organization_id>/audit-events, scoped strictly to that organization.| Event type | When |
|---|---|
client_connected / agent_connected / relay_connected | A Client, Agent, or Relay completes registration and nonce verification. |
client_disconnected / agent_disconnected | A Client or Agent's WebSocket connection closes. |
tunnel_requested | A Client requests a Tunnel, before policy evaluation. |
access_denied | Organization, Device, protocol, or Agent-access policy rejects the request. |
duplicate_tunnel | A duplicate connection is rejected while an authenticated session is already active. |
p2p_tunnel_established / p2p_tunnel_failed / p2p_tunnel_ended | Direct Tunnel negotiation succeeds, fails, or ends. |
tunnel_started / tunnel_ended | A Relay-mediated Tunnel becomes active or is torn down. |
tunnel_error / relay_error / device_error | A Tunnel, Relay spawn, or Client/Agent-local failure occurs. |
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 or relay), a short reason code, a free-text message, the reporting Device's IP address (when available), and a timestamp.
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.
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.
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.
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.