# Policy Engine · Change Events Prep (POLICY-ENGINE-30-003) - **Date:** 2025-11-20 - **Depends on:** Overlay projection (30-001) and simulation bridge (30-002) - **Working directory:** `src/Policy/StellaOps.Policy.Engine` ## Event envelope - Topic: `policy.overlay.changed` - Payload fields: - `tenant` (string) - `ruleId` (string) - `version` (int) — matches projection version - `changeType` (`created|updated|deprecated|deleted`) - `projection` (OverlayProjection) — single item; for `deleted`, include last-known `projection` with `decision: "defer"`. - `delta` (object, optional) — produced when triggered from simulation `whatif`: `baselineDecision`, `candidateDecision`, `diffReason`. - `artifacts` — `evidenceHash`, `treeDigest?`, `dsseEnvelopeHash?` - `emittedAt` (ISO-8601 UTC) - `correlationId` (string) — propagate from incoming request or run id. ## Delivery guarantees - At-least-once on the bus; projection storage is source of truth. Events carry idempotency key `tenant:ruleId:version`. - Ordering per `ruleId` is preserved by publishing after storage commit. ## Consumers - Scheduler uses events to enqueue re-evaluation jobs keyed by `tenant` + `ruleId`. - UI/CLI preview listens for `changeType` ≠ `created` to refresh overlays without polling. ## Acceptance for prep completion - Topic, payload, and idempotency key are fixed; downstream scheduler/UI/CLI can wire without further contract churn.