# CEM CRM Side-effect Authority

Phase 9C0 introduces an explicit ownership decision between CRM eligibility and action execution. It enables no real CRM or WebSocket effects. The legacy listener remains authoritative by default. Related architecture: MPBX-002, MPBX-004, MPBX-006 and MPBX-CONF-001.

## Authority modes

- `LEGACY`: the legacy listener owns the effect; CEM may plan and audit only.
- `CEM`: the scope is nominated for CEM ownership, subject to every independent execution gate.
- `SHADOW`: CEM plans and audits without effects.
- `BLOCKED`: execution and automatic promotion are prohibited.

The global default is `LEGACY`. A global `CEM` default is invalid, unknown future action types resolve to `BLOCKED`, and no implicit CEM fallback exists.

## Resolution precedence

Rules are matched deterministically from most to least specific:

1. tenant + environment + action type + queue + extension;
2. tenant + environment + action type + extension;
3. tenant + environment + action type + queue;
4. tenant + environment + action type;
5. tenant/environment default;
6. global safe default.

Exact duplicate or conflicting rule scopes make configuration invalid. Supported action types are `POPUP_RING`, `POPUP_ANSWERED`, `ACTIVITY_COMPLETED`, `ACTIVITY_MISSED` and `RECORDING_LINK`.

## Execution gates and audit

Execution permission is:

```text
consumer enabled
AND authority = CEM
AND cutover interlock enabled
AND adapter enabled
AND idempotency/reconciliation permits execution
```

Authority alone never enables an adapter. Each non-dry-run plan records a minimized append-only decision containing action/correlation identifiers, safe scope, resolved mode, rule ID, interlock state, permission and reason. It excludes caller identity, canonical payload, AMI data, CRM records, credentials and recording paths. Non-CEM or blocked actions remain `PLANNED`; they are never marked `COMMITTED`.

## Legacy coexistence and interlock limitation

Phase 9C0.1 adds a shared, expiring local authority snapshot read independently by both runtimes. Phase 9C2.1 adds a short generation-bound health lease. The listener preserves existing behavior when either artifact is missing or unsafe. CEM blocks execution on unsafe authority state. A `CEM` rule suppresses the corresponding legacy effect only while the snapshot is valid, its interlock is true, and the matching lease proves all local readiness gates.

The lease contains only consumer identity/scope, readiness booleans, timestamps, authority generation and checksum. It excludes event, caller, contact, CRM, AMI, recording and secret data. The default lease is valid for 15 seconds and refreshed every five seconds by a healthy follow loop. Controlled shutdown marks it non-ready; crash recovery relies on bounded expiry. A passive TCP connect-only probe establishes bridge reachability without sending a popup frame and is not browser-display acknowledgement.

Authority generation rotation invalidates the previous lease for new actions immediately. Phase 9C2.3 also binds each `POPUP_RING` action to one immutable authority generation. This closes the stopped/disabled/unhealthy consumer no-owner gap without allowing the listener and consumer to choose different generations for the same action.

## Phase 9C2.3 action-generation coordination

Legacy and CEM both receive the same PBX Linkedid early enough for ring ownership. The canonical correlation ID is deliberately not used because it additionally incorporates capture-session identity. Before either side decides one `POPUP_RING`, it derives a SHA-256 call-reference hash and atomically creates or reads a short-lived action pin. The pin contains only generation, hashed call reference, action, extension, tenant/environment scope, timestamps, the generation's health result and checksum. It contains no raw Linkedid, caller, CRM or AMI payload.

The authority writer preserves a restrictive immutable copy of each generated snapshot. Both sides resolve the pinned action against that generation copy, not the mutable current pathname. Thus a rotation affects the next action while an in-flight action remains on its original owner. Pin creation also freezes whether a matching ready lease existed for the selected CEM generation; an absent or unhealthy lease selects fail-safe legacy ownership. Missing identity, invalid pin, missing generation copy or integrity failure preserves legacy and blocks CEM.

Pins default to 30 seconds, expire rather than becoming reusable ownership state, and old files are removed by bounded maintenance. This is local atomic filesystem coordination, not a distributed lock or global exactly-once guarantee. Adapter execution remains protected separately by idempotency and reconciliation.

## Phase 9C2.2 dual scopes

A CEM rule may distinguish its precise `execution_scope` from its explicit `legacy_suppression_scope`. CEM evaluates execution using tenant, environment, action, canonical queue and extension. The queue-unaware legacy guard evaluates only the linked suppression scope using tenant, environment, action and extension. Authority snapshot schema version 2 serializes both under the same rule and generation. Older schema state is rejected fail-safely until a reviewed snapshot is re-exported; a null queue in an old flat rule never implies suppression.

For Phase 9C2.2 the only permitted broadening is dropping `queue_id`. Tenant, environment, action and agent extension must remain identical, and the feature is restricted to queue-scoped `POPUP_RING`. The rule is rejected unless it also carries a reviewed `DEDICATED_EXTENSION_TO_EXECUTION_QUEUE` constraint and a safe evidence reference. Duplicate suppression scopes, global/wildcard suppression, different extensions and disconnected scopes are rejected.

A `POPUP_RING` CEM rule without an explicit suppression scope cannot execute even if its other CEM gates pass. Legacy remains owner. This prevents an older or partially migrated execution-only rule from creating duplicate popup ownership.

This constraint is substantive: while the scope is active, the suppressed extension must receive pilot calls only from the execution queue. If another queue can ring the same extension, legacy would be suppressed while CEM correctly rejects the non-matching queue, creating no owner. The implementation makes that risk explicit and refuses unconstrained dual scope, but it does not dynamically prove PBX queue exclusivity.

No queue-eligibility suppression claim is published by the Gateway. Phase 9C2.3 uses the shared Linkedid only to choose an authority generation atomically; either runtime may create the pin first, so it has no publication-order dependency and does not weaken the dedicated-extension constraint.

This is filesystem coordination, not a distributed lock or transaction. Snapshot export is reviewed and explicit; no network or database coordination is introduced. See Implementation Guide: CEM_CRM_CUTOVER_INTERLOCK.

Phase 9C1 does not weaken these gates. Its TCP popup adapter is reachable only for an explicitly CEM-owned `POPUP_RING` scope after consumer, snapshot interlock, adapter and idempotency checks all pass. Other action types remain legacy-owned under the controlled rollout policy.

## Rollback

Rollback requires no data migration:

1. change the affected scope to `LEGACY`;
2. set the cutover interlock to false.

Existing audit and idempotency records remain immutable evidence. Production authority is unchanged by Phase 9C0.
