# Task F5: Approval Automation Foundation

## Scope Delivered

- Added approval automation schema for reminder policies and escalation policies.
- Added step timing state to approval requests so automation can reason about the current step safely.
- Added automation scheduler and pending queue monitor on top of the existing approval and notification foundations.
- Added admin APIs and settings pages for reminder and escalation policy management.

## Data Model

### Approval request timing

`crm_approval_requests` now stores:

- `current_step_started_at`

This becomes the source of truth for waiting-time, reminder, escalation, and timeout calculations.

### Reminder policies

`crm_approval_reminder_policies`

One policy per workflow step:

- `workflow_id`
- `step_number`
- `sla_hours`
- `reminder_offsets_hours`
- `calendar_mode`
- `timeout_action`
- `is_active`

This lets each step define SLA, reminder schedule, and timeout behavior without changing runtime approval ownership.

### Escalation policies

`crm_approval_escalation_policies`

Supports one or more escalation rules per workflow step:

- `workflow_id`
- `step_number`
- `trigger_after_hours`
- `target_type`
- `target_value`
- `is_active`

Supported targets:

- `manager`
- `requester`
- `explicit_user`
- `role`
- `permission_group`

## Scheduler Model

Core service:

- `processApprovalAutomation()`

Current behavior:

1. Load pending approval requests.
2. Resolve the current workflow step and timing baseline from `current_step_started_at`.
3. Send reminder events for every configured reminder threshold crossed.
4. Send escalation events for every active escalation threshold crossed.
5. Execute timeout action when SLA is reached.

The scheduler is safe to rerun because notification publication uses deterministic `dedupeKey` values per request, step, and threshold.

## Timeout Model

Supported timeout actions:

- `none`
- `auto_reject`
- `auto_cancel`
- `auto_escalate`

Notes:

- `auto_reject` and `auto_cancel` create approval action history and synchronize entity status.
- `auto_escalate` keeps the approval pending and publishes a timeout notification event to resolved escalation targets.
- This foundation intentionally does not reassign approver ownership or introduce delegation.

## Notification Integration

F.5 reuses `publishNotificationEvent()` from the F.4 notification foundation.

New event types:

- `approval.reminder`
- `approval.escalated`
- `approval.timeout`

Channels remain in-app only for now.

## Queue Monitor

Core service:

- `getPendingApprovalQueue()`

Current queue output includes:

- pending count
- due today count
- overdue count
- escalated count
- per-request waiting hours
- SLA hours
- remaining hours
- due timestamp

## APIs

Added:

- `GET /api/crm/approval/automation/pending`
- `POST /api/crm/approval/automation/run`
- `GET /api/crm/approval/reminder-policies`
- `POST /api/crm/approval/reminder-policies`
- `PATCH /api/crm/approval/reminder-policies/[id]`
- `DELETE /api/crm/approval/reminder-policies/[id]`
- `GET /api/crm/approval/escalation-policies`
- `POST /api/crm/approval/escalation-policies`
- `PATCH /api/crm/approval/escalation-policies/[id]`
- `DELETE /api/crm/approval/escalation-policies/[id]`

## UI

Added settings pages:

- `/dashboard/crm/settings/approval-reminder-policies`
- `/dashboard/crm/settings/approval-escalation-policies`

The reminder page also includes:

- queue monitor cards
- a compact pending queue view
- a manual “Run Automation” action for verification and operations

## Permissions

Added:

- `crm.approval.automation.read`
- `crm.approval.automation.run`
- `crm.approval.reminder.manage`
- `crm.approval.escalation.manage`

These are grouped under the approval permission section and added to the default CRM admin configuration surface.

## Audit Events

F.5 records:

- `approval_reminder_sent`
- `approval_escalated`
- `approval_timeout`
- `approval_policy_created`
- `approval_policy_updated`
- `approval_policy_deleted`

## Current Limitations

- calendar support is `calendar_days` only
- no holiday calendar yet
- no working-hours window yet
- no delegation or vacation replacement yet
- no background cron orchestration yet; manual run endpoint is the current operator entrypoint
