Events
Every governed syscall generates an event. Events are the source of truth for audit, and the basis for detecting drift between agent and server.
Event schema
message Event { string event_id = 1; // UUID v7 string agent_id = 2; // daemon UUID string discovered_agent_id = 3; // optional — which AI process EventKind kind = 4; // FILE_READ, FILE_WRITE, EXEC, NET_CONNECT, TLS string resource = 5; // path, command, IP:port, SNI Verdict verdict = 6; // ALLOW, DENY, ALERT Severity severity = 7; // LOW, MEDIUM, HIGH, CRITICAL string policy_id = 8; // policy version that evaluated int64 pid = 9; string process_exe = 10; string cmdline = 11; int64 timestamp_ns = 12; map<string,string> metadata = 13;}See proto/events.proto for the full definition.
Verdict types
| Verdict | Meaning | Syscall outcome |
|---|---|---|
ALLOW | Policy explicitly permitted, or no rule matched in allow-mode | proceeds |
DENY | Policy denied | returns EPERM |
ALERT | No block, but flagged for review | proceeds |
Future: REQUIRE_APPROVAL (roadmap) — syscall pauses until an operator acknowledges in the UI.
Drift detection
Every event is re-evaluated on the server with the canonical policy. The result is compared to the agent’s verdict.
| agent_verdict | server_verdict | drift_detected | meaning |
|---|---|---|---|
ALLOW | ALLOW | false | normal |
DENY | DENY | false | normal |
ALERT | ALERT | false | normal |
ALLOW | DENY | true | agent missed a deny — stale policy or tampered |
DENY | ALLOW | true | agent blocked something it shouldn’t have |
ALERT | DENY | true | severe — kernel let it through, should not have |
Drift-detected events are surfaced prominently in the UI and can be queried:
SELECT * FROM events WHERE drift_detected = true ORDER BY ts DESC;Persistence
Events are written to PostgreSQL. Indexing:
agent_id + tsfor per-host timelines.kind + verdict + tsfor dashboard summaries.drift_detectedpartial index for the drift view.
Retention is installation-dependent — schedule a periodic DELETE FROM events WHERE ts < now() - interval '30 days' if you need to cap storage.
Live streaming
- gRPC (
:7700) — agent → server. mTLS, bidirectional. - SSE (
:7701at/api/v1/events/stream) — server → UI/CLI. JWT-authenticated. - CLI tail —
tyr audit tail [--agent <name>]consumes the SSE stream.
Inject (admin only)
For testing or bridging from external sources:
curl -X POST https://tyr.example.com:7701/api/v1/events/inject \ -H "Authorization: Bearer <jwt>" \ -d '{...event json...}'Injected events go through the same drift-detection path and SSE broadcast.
→ Next: Enforcement · Monitoring