Skip to main content

Breach Notification Policy

The breach-notification policy category enforces regulatory deadlines on breach disclosure. When a breach signal is present on the run context, this handler computes the elapsed time since onset and:

  • Warns when the SLA is approaching (configurable threshold)
  • Blocks all further agent activity until the tenant flips breach_notified = true
  • Blocks when the SLA is exceeded without notification

Aligned to GDPR Art-33 (72h breach notification) and HIPAA §164.404 (Breach Notification Rule).

Rules

RuleTypeDefaultDescription
breach_signalsstring[]["data_breach", "pii_leak"]Signal slugs that indicate a breach (matched case-insensitively against context.metadata["breach_signal"])
notification_sla_hoursinteger72Hard regulatory SLA in hours (GDPR = 72; HIPAA = 1440 / 60d)
warn_threshold_hoursinteger24Warn this many hours before the SLA hits
block_on_overduebooleantrueBlock all further activity when SLA exceeded without notification
action_on_breachstring"block"Action when breach detected: "block" or "warn"

How It Works

The breach-notification handler runs at before_workflow, mid_execution, and after_workflow so the deadline is re-evaluated at every checkpoint.

PhaseBehavior
before_workflowCheck for breach signal + elapsed SLA before any work begins
mid_executionRe-evaluate during long-running runs (signal may surface mid-flight)
after_workflowCatch breaches detected from final output content scans

Decision Flow

  1. No breach signalALLOW (fast common case)
  2. Breach signal present but not in breach_signals listALLOW (a different breach policy may target it)
  3. breach_notified = trueALLOW with reason "notification dispatched; proceeding with remediation"
  4. No breach_event_at timestampBLOCK (cannot compute SLA)
  5. SLA exceeded + block_on_overdueBLOCK
  6. Within warn_threshold_hours of SLAWARN
  7. Breach known, within SLA, not notifiedBLOCK (default) -- this is the exact failure mode the regulation targets

Context Attributes Read

AttributePhasePurpose
context.metadata["breach_signal"]allSlug of the breach kind (e.g., "pii_leak")
context.metadata["breach_event_at"]allISO timestamp or epoch float of breach onset
context.metadata["breach_notified"]allBoolean flag tenant flips after dispatching notifications

breach_event_at accepts ISO strings ("2026-05-09T12:00:00Z") and float epoch seconds.

Example Policy

{
"breach_signals": ["data_breach", "pii_leak", "ransomware"],
"notification_sla_hours": 72,
"warn_threshold_hours": 24,
"block_on_overdue": true,
"action_on_breach": "block"
}

SDK Integration

import waxell_observe as waxell
waxell.init()

@waxell.observe(agent_name="claims-agent", enforce_policy=True)
async def process_claim(claim: dict) -> dict:
return await adjudicate(claim)

Tenants set breach metadata via their incident-response pipeline:

# When IR confirms a breach
ctx.metadata["breach_signal"] = "pii_leak"
ctx.metadata["breach_event_at"] = "2026-05-25T08:00:00Z"

# After notifications dispatched
ctx.metadata["breach_notified"] = True

Observability

FieldExample
Categorybreach-notification
Actionblock
Reason"Breach 'pii_leak' notification SLA (72h) exceeded by 4.3h. Dispatch notifications before resuming agent activity."
Metadata{"signal": "breach_sla_overdue", "elapsed_hours": 76.3, "sla_hours": 72, "remaining_hours": -4.3, "gdpr": "Art-33", "hipaa": "§164.404"}

Common Gotchas

  1. Missing breach_event_at blocks by default. A breach signal without a timestamp is treated as "block until IR captures onset time". This is intentional -- proceeding without knowing when the breach started makes the SLA un-computable.

  2. Empty breach_signals list = match-all. If breach_signals is omitted or empty, ANY non-empty context.metadata["breach_signal"] triggers evaluation. Scope it explicitly to avoid surprise blocks.

  3. breach_notified accepts truthy variants. True, "true", 1, "1" all count as notified. Other truthy values ("yes", "done") do NOT.

  4. The handler does not dispatch notifications. It is a deadline enforcer. Tenants must wire their own incident-response system (PagerDuty, email-to-counsel, regulatory portal) and flip breach_notified when complete.

  5. GDPR is 72 hours; HIPAA is 60 days. Use separate policies (one per regulation) with different breach_signals if you need both -- e.g., breach_signals: ["pii_leak"] at 72h for GDPR, breach_signals: ["phi_leak"] at 1440h for HIPAA.

  6. action_on_breach = "warn" weakens the block. Use "warn" only when downstream automation will hard-block via another mechanism (kill-switch, CI gate).

Next Steps