Observability / SIEM
Every governed call, detection, policy verdict, and tool invocation is written to the TapPass audit trail. The SIEM export pipeline ships those events downstream so they live alongside the rest of your security telemetry.
Shipped destinations
Section titled “Shipped destinations”| Destination | destination value |
Formats | Go to |
|---|---|---|---|
| Splunk HEC | splunk_hec |
CEF, JSON | Splunk HEC |
| Azure Sentinel | azure_sentinel |
JSON | Azure Sentinel |
| Generic webhook | webhook |
JSON, CEF, OCSF | Webhooks |
Pipeline
Section titled “Pipeline”audit events ──▶ format (CEF | OCSF | JSON) ──▶ filter ──▶ redact ──▶ buffer/batch ──▶ destination- Format —
ceffor SIEMs that parse it natively (Splunk, ArcSight);ocsffor OCSF consumers;jsonfor everything else. - Filter — minimum severity (
all|detection|action|block) and event-type include/exclude lists. - Redact — API keys, tokens, connection strings, and absolute file paths are stripped automatically before export; large content fields are truncated.
- Buffering — events are flushed in batches (configurable size / interval) with retries and exponential backoff.
Configure
Section titled “Configure”The export is enabled by setting a SIEM URL:
TAPPASS_SIEM_URL=https://splunk.example.com:8088/services/collectorTAPPASS_SIEM_DESTINATION=splunk_hec # splunk_hec | azure_sentinel | webhookTAPPASS_SIEM_AUTH_TOKEN=<hec-token>Or at runtime via the settings API (stored, takes effect immediately):
GET /api/settings/siem— current configuration (token redacted)PUT /api/settings/siem— update configurationPOST /api/settings/siem/test— send a test event to verify connectivityGET /api/settings/siem/stats— export pipeline statistics
Example update:
curl -X PUT https://tappass.example.com/api/settings/siem \ -H "Authorization: Bearer $ADMIN_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "destination": "splunk_hec", "url": "https://splunk.example.com:8088/services/collector", "auth_token": "<hec-token>", "format": "cef", "severity_filter": "detection" }'OTLP governance spans
Section titled “OTLP governance spans”Alongside the SIEM pipeline, TapPass can export every governance decision as an OpenTelemetry span — so decisions land in the same tracing backend as the rest of your system (Datadog, Honeycomb, Grafana Tempo, or any OTLP collector), correlated by the standard trace attributes.
This is a second sink on the same audit stream. Each span carries the decision’s verdict, reason, rule id, behavior type, agent/org, model, tokens, and cost; blocked decisions surface as span errors.
Enable it with two environment variables — the standard OTLP endpoint plus the opt-in flag:
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317TAPPASS_OTLP_AUDIT_SPANS=1Backends are pure configuration — point OTEL_EXPORTER_OTLP_ENDPOINT (and OTEL_EXPORTER_OTLP_HEADERS) at your collector; there is no per-vendor code.
It’s off by default on purpose: the gateway and MCP server already emit live spans for the calls they trace, so turn this on when you want uniform OTLP coverage of every decision — including direct /v1/govern and chat — not just those two paths.
Per-tenant destinations (SaaS)
Section titled “Per-tenant destinations (SaaS)”The OTEL_EXPORTER_OTLP_ENDPOINT above is a deployment-wide setting — one collector for the whole server, ideal for self-hosting and for TapPass’s own operational telemetry. In a multi-tenant SaaS deployment, each org instead configures its own destination, so company A streams its governance decisions to A’s Datadog and company B to B’s Honeycomb — same install, separate backends.
Per-tenant destinations are org-scoped config, managed via the settings API (org-admin):
| Endpoint | Purpose |
|---|---|
GET /api/settings/export-destinations |
List this org’s destinations (auth tokens redacted to ****last4) |
POST /api/settings/export-destinations |
Add a destination (kind, endpoint, secret_header, token, event_filter, and format for SIEM kinds) |
PUT /api/settings/export-destinations/{id} |
Update — echo the masked token to leave it unchanged |
DELETE /api/settings/export-destinations/{id} |
Remove it (and its stored secret) |
POST /api/settings/export-destinations/{id}/test |
Route a test decision to verify delivery |
How it stays safe:
- Strict isolation — routing keys on the decision’s authoritative
org_id; a tenant only ever receives its own decisions. - Encrypted secrets — auth tokens are stored encrypted at rest in the credential vault, never in plaintext; the API only returns the last four characters.
- SSRF-guarded — tenant-supplied endpoints are validated (DNS-resolving, fail-closed), so a destination can’t point at internal or metadata addresses.
- Fail-safe — a destination whose token is missing is skipped, never sent unauthenticated.
Both destination families are delivered end-to-end:
otlp— spans to the org’s OpenTelemetry backend (Datadog / Honeycomb / Grafana Tempo / any collector).- SIEM —
splunk_hec,azure_sentinel,webhook, each with aformat(cef/ocsf/json). The token is the destination’s own auth material (Splunk HEC token, Sentinel shared key, webhook secret); events are formatted and redacted through the same pipeline the global SIEM export uses, so secrets never leave in payloads.
Two layers coexist. The deployment-wide sinks — the OTEL_EXPORTER_OTLP_ENDPOINT collector and the super_admin-configured global SIEM — are TapPass’s own operator telemetry (Layer 1): they see every org’s decisions, for platform monitoring. Per-tenant destinations (Layer 2) are each org’s own: strictly isolated by org_id, so a tenant only ever receives — and authenticates as — itself.
Alerting (separate from SIEM export)
Section titled “Alerting (separate from SIEM export)”For real-time notifications on governance events, TapPass can also fire a webhook to Slack, Teams, or a generic endpoint:
TAPPASS_ALERT_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../xxxTAPPASS_ALERT_WEBHOOK_TYPE=slack # slack | teams | genericTAPPASS_ALERT_MIN_SEVERITY=block # block | detect | allConfigurable at runtime via GET/PUT/POST /api/settings/alerting (plus /test and /delivery-log). This is fire-and-forget and never blocks the governance path. This deployment-wide webhook is the operator’s own channel (Layer 1, super_admin).
Per-tenant alert destinations (SaaS)
Section titled “Per-tenant alert destinations (SaaS)”Each org can also route its own governance alerts to its own Slack/Teams/generic webhook — a Layer-2 peer to the deployment-wide webhook above. Org-admins manage them via the settings API:
| Endpoint | Purpose |
|---|---|
GET /api/settings/alert-destinations |
List this org’s alert destinations (webhook URLs masked to ****last4) |
POST /api/settings/alert-destinations |
Add one (webhook_type, webhook_url, min_severity) |
PUT /api/settings/alert-destinations/{id} |
Update — echo the masked URL to leave it unchanged |
DELETE /api/settings/alert-destinations/{id} |
Remove it (and its stored secret) |
POST /api/settings/alert-destinations/{id}/test |
Send a test alert to verify delivery |
GET /api/settings/alert-destinations/{id}/delivery-log |
This org’s recent delivery outcomes |
Same isolation guarantees as export destinations: routed strictly by the decision’s org_id, webhook URLs stored encrypted in the vault (the API returns only the last four characters), SSRF-guarded, and each org’s delivery log is separate — an org only ever sees its own alerts. Each destination has its own min_severity (all/detect/block), so one org can get every detection while another gets only blocks.