Skip to content

fix(webhook) missing fields in payload - #2164

Merged
chrislatimer merged 1 commit into
mainfrom
feat/memory-defense-event-siem-enrichment
Jun 12, 2026
Merged

fix(webhook) missing fields in payload#2164
chrislatimer merged 1 commit into
mainfrom
feat/memory-defense-event-siem-enrichment

Conversation

@chrislatimer

Copy link
Copy Markdown
Contributor

Summary

Two small fixes that close gaps left after the SIEM-enrichment schema add in #2157:

  1. webhooks/manager.py: serialize the queued payload with model_dump_json(exclude_none=True) at both fire sites (fire_event and fire_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: null on every OSS delivery. OSS payloads now contain only what OSS actually populates; cloud payloads contain only what cloud actually populates.

  2. engine/retain/orchestrator.py:_fire_memory_defense_webhook: read the four optional SIEM-enrichment fields off the decision via getattr (severity,
    api_key_name, memory_unit_id, receipt_uri) and forward them to MemoryDefenseEventData. OSS's DefenseDecision dataclass doesn't carry these fields and OSS
    leaves them None — but downstream extensions (e.g. hindsight-cloud's _CloudDefenseDecision subclass) populate them on the decision they return from screen(),
    and without this passthrough they were silently dropped at the orchestrator boundary. Reading via getattr keeps OSS agnostic to extension subclasses while still
    routing 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.violation event, and an OSS-only user sees a strictly smaller payload (no noisy nulls) than before.

Backward compatibility

  • exclude_none removes keys from the JSON, not from the schema. Receivers that decode the payload into the published Pydantic models still get None defaults for
    absent 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 (whose DefenseDecision has no extra
    attributes).

Test plan

  • Existing webhook flow tests still green: test_retain_fires_webhook_on_redact, test_retain_fires_webhook_on_block.
  • ruff check + ty check clean.
  • Verified end-to-end with the cloud extension: cloud's _CloudDefenseDecision now populates severity and api_key_name, and both fields arrive on the n8n
    receiver instead of being null.

@chrislatimer
chrislatimer merged commit 87448b1 into main Jun 12, 2026
181 of 182 checks passed
@chrislatimer
chrislatimer deleted the feat/memory-defense-event-siem-enrichment branch June 12, 2026 06:48
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