> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# PM-Triggered Business Rule Automation — Integration

> Version: 1.0.0 Status: \U0001F528 In Progress Last Updated: 2026-02-23 PM-Triggered Business Rule Automation Constitution Reference: Section 1.3 (Integrati…

**Version:** 1.0.0\
**Status:** 🔨 In Progress\
**Last Updated:** 2026-02-23\
**Spec:** [PM-19 PM-Triggered Business Rule Automation](../../../specs/pm/specs/PM-19-pm-triggered-business-rule-automation.md)\
**Constitution Reference:** Section 1.3 (Integration Patterns), Section 12 (Automation Governance)

***

## Overview

PM-19 extends the FW-03 Automation Engine to support **PM events** as automation triggers. Billing admins can create rules that run when claim status changes (e.g. denied), charge is approved, or payment is posted. The automation executor subscribes to the `cl_pm_events` channel and matches rules by `trigger_type` and `trigger_config`.

> **Note on channel naming:** The `cl_pm_events` channel uses a `cl_` prefix because it was originally established for CL↔PM cross-core events. PM-only events reuse this channel for consistency with EVENT\_CONTRACTS.md. A future rename to `pm_events` may be considered if the channel scope is formalized.

**Key behavior:**

* **Trigger type:** `pm_event` (stored as `trigger_type: 'pm_event'` in `fw_automation_rules`)
* **Trigger config (JSONB):** `{ "event_type": string, "new_status"?: string, "payer_id"?: string | null }`
* **Channel:** `cl_pm_events` (EVENT\_CONTRACTS)
* **Governance:** All executions logged to `fw_automation_logs`; circuit breaker and dry-run per constitution §12.

***

## Quick Reference

| I need to…                                | Pattern                                                  | Location                                                                |
| ----------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------- |
| Trigger automation when claims are denied | PM event trigger with `event_type` + `new_status` filter | [Event types available as triggers](#event-types-available-as-triggers) |
| Scope rule execution to payer             | Optional `payer_id` filter in trigger config             | [Trigger config shape (FW-03 rule)](#trigger-config-shape-fw-03-rule)   |
| Validate tenant-safe execution            | Match `rule.organization_id` to event org                | [Multi-tenancy and security](#multi-tenancy-and-security)               |
| Verify run behavior and outcomes          | Automation execution logs                                | `fw_automation_logs` and FW-03 runtime                                  |

## Decision Tree

1. Receive PM event on `cl_pm_events`.
2. Load rules where `trigger_type = 'pm_event'`.
3. Match `trigger_config.event_type` to payload `event_type`.
4. Apply optional filters (`new_status`, `payer_id`) when configured.
5. Execute actions for matching rules and persist run logs to `fw_automation_logs`.

## Pattern Library

* **Event subscriber pattern:** FW-03 consumes PM events and drives automation dispatch.
* **Publisher pattern:** PM-07/PM-08/PM-09 emit domain events with automation-ready payloads.
* **Contract-first pattern:** Payload shape governed by `EVENT_CONTRACTS.md`.

## Common Mistakes

| Pitfall                                                 | Impact                         | Fix                                                    |
| ------------------------------------------------------- | ------------------------------ | ------------------------------------------------------ |
| Missing `organization_id` in payload                    | Cross-tenant rule leakage risk | Require `organization_id` on every PM automation event |
| Treating omitted filters as hard requirements           | Rules never match              | Omitted `new_status`/`payer_id` means wildcard match   |
| Using null and omitted inconsistently for payer filters | Inconsistent rule behavior     | Normalize filter semantics in builder and executor     |

## Pre-Flight Checklist

* [ ] Event payload includes `organization_id`.
* [ ] Rule execution enforces `rule.organization_id = event.organization_id`.
* [ ] Runtime writes execution trails to `fw_automation_logs`.
* [ ] Dry-run/circuit-breaker behavior validated for high-volume bursts.
* [ ] Payload schema matches `EVENT_CONTRACTS.md` definitions.

***

## Integration Points

| Owner / Component           | Pattern          | Status     | Purpose                                                                                                                      |
| --------------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **FW-03 Automation Engine** | Event subscriber | 📝 Planned | Subscribes to `cl_pm_events`; matches rules by trigger\_type/trigger\_config; executes actions; logs to `fw_automation_logs` |
| **PM-07**                   | Event publisher  | 📝 Planned | Publishes `charge_approved` / `charge_status_changed` when charge status transitions                                         |
| **PM-08**                   | Event publisher  | 📝 Planned | Publishes `claim_submitted`, `claim_status_changed`, optionally `claim_created`, `denial_received`                           |
| **PM-09**                   | Event publisher  | 📝 Planned | Publishes `payment_posted`, `write_off_approved`                                                                             |
| **EVENT\_CONTRACTS**        | Contract doc     | 📝 Planned | Payload schemas and "PM events as automation triggers" subsection; PM-19 reference                                           |

***

## Event Contracts (Consumed by FW-03)

Payload schemas are defined in [EVENT\_CONTRACTS.md](./EVENT_CONTRACTS.md). This section summarizes the **PM events as automation triggers** contract for PM-19.

### Event types available as triggers

| Event Type              | When Published                  | Payload fields used for filtering                                                                |
| ----------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------ |
| `claim_submitted`       | Claim status → submitted        | `organization_id`, `claim_id`, `payer_id`                                                        |
| `claim_status_changed`  | Claim status changes            | `organization_id`, `claim_id`, `new_status`, `payer_id`                                          |
| `claim_created`         | Optional: claim created (draft) | `organization_id`, `claim_id`, `payer_id`                                                        |
| `denial_received`       | Optional: denial\_codes updated | `organization_id`, `claim_id`, `payer_id`                                                        |
| `charge_approved`       | Charge status → approved        | `organization_id`, `charge_id`                                                                   |
| `charge_status_changed` | Any charge status change        | `organization_id`, `charge_id`, `new_status`                                                     |
| `payment_posted`        | Payment posted                  | `organization_id`, `payment_id`, `claim_id`                                                      |
| `write_off_approved`    | Write-off approved              | `organization_id`, `approval_id`, `payment_id`, `write_off_amount` (optional filter: `claim_id`) |

### Trigger config shape (FW-03 rule)

Stored in `fw_automation_rules.trigger_config` (or equivalent):

```typescript theme={null}
interface PMEventTriggerConfig {
  event_type: 'claim_submitted' | 'claim_status_changed' | 'claim_created' | 'denial_received'
    | 'charge_approved' | 'charge_status_changed' | 'payment_posted' | 'write_off_approved';
  new_status?: string;   // e.g. 'denied', 'approved', 'paid'
  payer_id?: string | null;     // UUID or null; omit = any payer
}
```

**Matching rules:** Executor loads rules where `trigger_type = 'pm_event'` and `trigger_config.event_type` matches the event; then applies optional filters `new_status` and `payer_id`. Omitted filter = any value.

**Example rule (persisted for Executor to load and match):**

```typescript theme={null}
{
  organization_id: uuid,
  trigger_type: 'pm_event',
  trigger_config: {
    event_type: 'claim_status_changed',
    new_status: 'denied',
    payer_id: null  // omit or null = any payer
  },
  actions: [
    { type: 'send_notification', config: { template: 'claim_denied_alert', ... } },
    { type: 'create_task', config: { queue: 'denial_review', ... } }
  ]
}
```

The Executor subscribes to `cl_pm_events`, receives an event, loads rules where `trigger_type = 'pm_event'` and `trigger_config.event_type` matches (e.g. `claim_status_changed`), then applies optional filters (`new_status`, `payer_id`). Matching rules are executed in order; actions run with event payload for context.

### Multi-tenancy and security

* Event payloads MUST include `organization_id`.
* Automation executor MUST only run rules where `rule.organization_id = event.organization_id`.
* Payloads use IDs only (no PII/PHI); actions resolve display data via authorized APIs.

***

## API Contracts

No new synchronous APIs. All integration is event-based (subscribe to `cl_pm_events`).

***

## References

* [EVENT\_CONTRACTS.md](./EVENT_CONTRACTS.md) — Payload schemas and channel `cl_pm_events`
* [PM-19 Spec](../../../specs/pm/specs/PM-19-pm-triggered-business-rule-automation.md)
* Constitution §12 (Automation Governance)
