# Workflow Engine — Design

The workflow engine provides multi-stage, form-driven processes with team
validation, SLA enforcement, and public entry. Workflows are kernel primitives;
workflow **surfaces** (admin UI, public landing pages) are extension packages.

---

## Core Concepts

### Workflow Definition

A workflow is a named process template owned by a team. Each workflow defines an
ordered list of **stages** that instances progress through.

| Field | Description |
|-------|-------------|
| `name` | Human-readable workflow name |
| `slug` | URL-safe identifier (unique per scope) |
| `scope` | Owning team or org |
| `stages` | Ordered list of stage definitions |
| `entry_mode` | `internal` (authenticated users) or `public_link` (landing page) |
| `sla_hours` | Optional SLA deadline for instance completion |

### Stage Types

Each stage has a `mode` that determines how participants interact:

| Mode | Behavior |
|------|----------|
| `form_only` | Structured form submission. Stage advances when form is complete. |
| `form_chat` | Form plus threaded discussion. Useful for review with comments. |
| `review` | Approval/rejection gate. Designated reviewers must sign off. |
| `custom` | Delegates entirely to a surface package. Enables extension-driven UIs. |

Stages declare an `assignee_mode` (individual, team, role-based) and optional
form schemas (JSON Schema validated at submission time).

### Workflow Instances

An instance is a running execution of a workflow definition. It tracks:

- Current stage index and overall status (`active`, `completed`, `cancelled`, `stale`)
- Per-stage completion records with timestamps and actor IDs
- Form data submitted at each stage
- Assignment and claim history

Instances use optimistic locking (`claimed_by` + `claimed_at`) to prevent
concurrent stage advancement. A claim expires after a configurable timeout.

---

## Multi-Party Validation (Signoff Table)

The `workflow_signoffs` table enables multi-party approval gates:

| Column | Purpose |
|--------|---------|
| `instance_id` | Which instance |
| `stage_index` | Which stage requires signoff |
| `user_id` | Who signed |
| `decision` | `approved` or `rejected` |
| `comment` | Optional rationale |
| `signed_at` | Timestamp |

The engine checks signoff requirements before advancing past a `review` stage.
Requirements are configurable: unanimous, majority, or N-of-M.

---

## SLA Scanner + Staleness Sweep

Two periodic background jobs maintain workflow health:

**SLA Scanner** — Runs on a configurable interval. Identifies instances that have
exceeded their workflow's `sla_hours` deadline. Fires a `workflow.sla.breached`
event (consumed by notification extensions or triggers).

**Staleness Sweep** — Identifies instances that have been idle (no stage
advancement) beyond a configurable threshold. Marks them as `stale` and fires
`workflow.instance.stale`. Stale instances can be resumed or cancelled.

Both jobs are distributed-safe: all cluster nodes run them, but operations are
idempotent (UPDATE with WHERE guards).

---

## Public Entry

Workflows with `entry_mode: public_link` are accessible at:

```
/w/:scope/:slug
```

The landing page renders the first stage's form without requiring authentication.
On submission, the kernel creates an instance and stores the form data. Subsequent
stages may require authentication depending on their assignee configuration.

Public entry enables use cases like intake forms, support requests, and
application submissions where the initiator is external.

---

## Extension Points

- **Surface packages** provide workflow admin UIs and participant views
- **Trigger extensions** can react to workflow events (`instance.created`,
  `stage.advanced`, `sla.breached`, `instance.completed`)
- **Custom stage mode** delegates rendering and advancement logic entirely to
  an extension, enabling arbitrary UIs within a workflow stage
