# escalation-rules

Per-location escalation rule shape. The default tree below is what every new location starts with; operators edit it in the app.

## Shape

```yaml
location: <id>
brand: <id>
chain:
  - role: gm
    contact:
      name:  "<GM name>"
      email: "<email>"
      phone: "<E.164 or null>"
    sla_minutes: 60
  - role: owner
    contact:
      name:  "<owner name>"
      email: "<email>"
      phone: "<E.164 or null>"
    sla_minutes: 240
  - role: regional
    contact: ...
    sla_minutes: 720
  - role: brand_hq
    contact: ...
    sla_minutes: 1440
overrides:
  - when:   "rating <= 2"
    first:  "owner"
    alert_channel: "both"
  - when:   "topic == 'cleanliness'"
    first:  "regional"
    alert_channel: "email"
preferences:
  alert_channel_default: "email"
  vacation:
    active:    false
    until:     null
    redirect_to_role: "owner"
```

## Default tree (single-store operator on Operator SKU)

```yaml
chain:
  - role: gm
    sla_minutes: 60
  - role: owner   # for single-store, same person as the GM
    sla_minutes: 720
preferences:
  alert_channel_default: "email"
```

## Default tree (multi-unit owner on Owner SKU)

```yaml
chain:
  - role: gm
    sla_minutes: 60
  - role: owner
    sla_minutes: 240
  - role: regional   # optional; only if the owner has named one
    sla_minutes: 720
```

## Default tree (Enterprise brand HQ)

```yaml
chain:
  - role: gm
    sla_minutes: 60
  - role: owner       # franchisee for the location
    sla_minutes: 240
  - role: regional    # brand's regional rep
    sla_minutes: 720
  - role: brand_hq
    sla_minutes: 1440
overrides:
  - when:   "rating == 1"
    first:  "owner"
    alert_channel: "both"
```

## How escalation-router reads this

The router resolves the first responder based on:
1. The default chain start (`chain[0]`).
2. Override matches (first override whose `when` matches wins).
3. Vacation redirect (if `preferences.vacation.active` is true and the resolved role matches `vacation.redirect_to_role`, the next-role-down in the chain becomes the first responder).

SLAs are wall-clock minutes from the review post timestamp. Off-hours rules (no SMS at 2am unless rating==1) are a future enhancement; for now, alerts fire on the SLA tick regardless of time.

## What operators edit in the app

- Contact details per role.
- SLA minutes per role.
- Override rules.
- Vacation toggle.

What operators do NOT edit:
- The set of roles. (Adding "shift-lead" as a role is a CL, not a per-tenant change.)
- The `alert_channel` enum.
