Skip to content

CM-71606: Mint and report a hook event id per guardrail hook - #525

Open
Altruistus wants to merge 1 commit into
cycodehq:mainfrom
Altruistus:CM-71606-report-the-hook-event-id
Open

CM-71606: Mint and report a hook event id per guardrail hook#525
Altruistus wants to merge 1 commit into
cycodehq:mainfrom
Altruistus:CM-71606-report-the-hook-event-id

Conversation

@Altruistus

Copy link
Copy Markdown
Collaborator

Summary

Mint one hook event id per ai-guardrails hook and send it on both requests the hook makes, so a Cycode violation can be resolved back to the exact hook event that produced it.

Changes

  • AIHookPayload.hook_event_id — a UUID minted per payload via default_factory. One payload is one hook event, so no per-IDE parser has to change.
  • build_ai_guardrails_scan_parameters — sends it in the guardrail scan metadata, alongside conversation_id / generation_id.
  • AISecurityManagerClient.create_event — sends it as the event's id, the same way create_conversation already sends the conversation id.
  • Tests for the payload (uuid, unique per event, explicit value honoured) and the client (the reported id is the payload's, and two hooks of one prompt report distinct ids).

Why

A guardrail hook makes two independent requests: the scan (which becomes a violation) and the hook event report. Neither can learn an id the other was assigned, and the event is reported in the handler's finally — after the scan has already gone out. Minting the id here is what lets both name the same event without either waiting on the other.

generation_id cannot stand in for it. The IDE mints one per prompt, so every hook of that prompt shares it, and some IDEs supply none at all — codex reads turn_id, cursor reads generation_id, claude-code digs it out of the transcript and may come back with None.

Both consumers already tolerate its absence, so this can ship independently:

  • ai-security-manager treats the event id as optional and mints one itself when it is missing, and accepts a redelivery of an id it already stored (this hook path retries on network failure).
  • secret-detector omits the hook_event_id detection detail entirely when it is not sent.

Testing

pytest tests/cyclient/test_ai_security_manager_client.py tests/cli/commands/ai_guardrails/ — 302 passed.

🤖 Generated with Claude Code

The guardrail scan and the hook event are reported in two separate requests, so
neither can learn an id the other assigned. Mint one per AIHookPayload - one
payload is one hook event - and send it on both: in the scan metadata, so the
detection can name the event it came from, and as the event id itself, the way
the conversation id is already sent.

A generation id cannot stand in for it: the IDE mints one per prompt, so several
hook events share it, and some IDEs supply none at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

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.

1 participant