fix(webhook) missing fields in payload - #2164
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two small fixes that close gaps left after the SIEM-enrichment schema add in #2157:
webhooks/manager.py: serialize the queued payload withmodel_dump_json(exclude_none=True)at both fire sites (fire_eventandfire_event_with_conn).Null fields drop from the wire, so receivers don't see promised-but-unfilled keys like
severity: null/api_key_name: null/memory_unit_id: null/receipt_uri: nullon every OSS delivery. OSS payloads now contain only what OSS actually populates; cloud payloads contain only what cloud actually populates.engine/retain/orchestrator.py:_fire_memory_defense_webhook: read the four optional SIEM-enrichment fields off the decision viagetattr(severity,api_key_name,memory_unit_id,receipt_uri) and forward them toMemoryDefenseEventData. OSS'sDefenseDecisiondataclass doesn't carry these fields and OSSleaves them
None— but downstream extensions (e.g. hindsight-cloud's_CloudDefenseDecisionsubclass) populate them on the decision they return fromscreen(),and without this passthrough they were silently dropped at the orchestrator boundary. Reading via
getattrkeeps OSS agnostic to extension subclasses while stillrouting the data through.
Combined with #1, this means a cloud user subscribing to a per-bank webhook now sees the same SIEM-actionable enrichment they used to see on the deprecated
memory_defense.violationevent, and an OSS-only user sees a strictly smaller payload (no noisy nulls) than before.Backward compatibility
exclude_noneremoves keys from the JSON, not from the schema. Receivers that decode the payload into the published Pydantic models still getNonedefaults forabsent fields. Receivers that key by string presence already had to handle the previous-null case anyway.
getattr(decision, "...", None)returns the same default the model had — no behavior change for OSS's regex defense (whoseDefenseDecisionhas no extraattributes).
Test plan
test_retain_fires_webhook_on_redact,test_retain_fires_webhook_on_block.ruff check+ty checkclean._CloudDefenseDecisionnow populatesseverityandapi_key_name, and both fields arrive on the n8nreceiver instead of being null.