Skip to content

feat: emit policy_enforced events on guard deny (RFC-008 B9)#22

Merged
beonde merged 1 commit into
mainfrom
feat/guard-event-emission
May 6, 2026
Merged

feat: emit policy_enforced events on guard deny (RFC-008 B9)#22
beonde merged 1 commit into
mainfrom
feat/guard-event-emission

Conversation

@beonde
Copy link
Copy Markdown
Member

@beonde beonde commented May 6, 2026

Summary

Adds event emission to the @guard decorator so that DENY decisions are POSTed to the registry's /v1/events endpoint as capiscio.policy_enforced events. This enables real-time observability of policy enforcement in the CapiscIO dashboard.

Changes

New module: capiscio_mcp/events.py

  • GuardEventEmitter — lightweight event emitter using requests (existing dependency)
  • Fire-and-forget via daemon thread (guard decorator never blocks on network I/O)
  • Module-level singleton via get_event_emitter() / set_event_emitter()
  • Best-effort: emission failures are silently logged, never break the guard

Guard (guard.py)

  • Added _emit_deny_event() helper called from both async and sync deny paths
  • Emits structured event with: decision, tool_name, deny_reason, agent_did, trust_level, evidence_id, error_code, requested/presented capability, capability_class, severity
  • Graceful degradation: no-op if no emitter is configured

Connect (connect.py)

  • MCPServerIdentity.connect() now auto-configures the event emitter singleton using the same server_url and api_key

Exports (__init__.py)

  • GuardEventEmitter, get_event_emitter, set_event_emitter added to public API

Testing

  • 384 passed, 0 failures

RFC-008 Sub-task

This implements B9 from the RFC-008 implementation plan.

- Add GuardEventEmitter with fire-and-forget POST to /v1/events
- Add module-level singleton via get_event_emitter/set_event_emitter
- Wire _emit_deny_event into both async and sync guard deny paths
- Auto-configure emitter in MCPServerIdentity.connect()
- Export GuardEventEmitter, get_event_emitter, set_event_emitter
Copilot AI review requested due to automatic review settings May 6, 2026 19:52
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

✅ Integration tests passed! capiscio-core gRPC tests working.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds RFC-008 (B9) policy enforcement telemetry by emitting capiscio.policy_enforced events when @guard denies tool access, enabling real-time observability via the registry /v1/events endpoint.

Changes:

  • Introduces capiscio_mcp/events.py with a module-level singleton GuardEventEmitter that POSTs events (fire-and-forget).
  • Updates capiscio_mcp/guard.py to emit a DENY event from both async and sync deny paths.
  • Updates MCPServerIdentity.connect() to auto-configure the event emitter, and exports the new APIs from capiscio_mcp/__init__.py.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
capiscio_mcp/guard.py Emits capiscio.policy_enforced on deny via the configured emitter singleton.
capiscio_mcp/events.py Adds GuardEventEmitter + singleton accessors; sends events via background thread + requests.
capiscio_mcp/connect.py Auto-configures the global emitter during MCPServerIdentity.connect().
capiscio_mcp/init.py Exposes event emitter types/helpers as part of the public API.

Comment thread capiscio_mcp/events.py
Comment on lines +143 to +145
# Fire-and-forget in a daemon thread
t = threading.Thread(target=self._send, args=(event,), daemon=True)
t.start()
Comment thread capiscio_mcp/guard.py
Comment on lines 505 to 511
result.requested_capability,
result.presented_capability,
result.evidence_id,
)
_emit_deny_event(result, effective_tool_name, capability_class)
raise GuardError(
reason=result.deny_reason or DenyReason.INTERNAL_ERROR,
Comment thread capiscio_mcp/connect.py
Comment on lines 476 to +485
logger.info("MCPServerIdentity ready for server %s: %s", server_id, did)

# Step 6: Auto-configure guard event emitter
set_event_emitter(
GuardEventEmitter(
server_url=server_url,
api_key=api_key,
agent_id=server_id,
)
)
@beonde beonde merged commit 715b7ce into main May 6, 2026
14 checks passed
@beonde beonde deleted the feat/guard-event-emission branch May 6, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants