Explorer/State Machine Docs/Workflow

Workflow State Machine

Domain: workflow · API spec: workflow-openapi.yaml

Task

States

StateDescriptionSLA clock
pending Unassigned task awaiting a caseworker to claim it running
in_progress Task claimed and actively being worked by an assigned caseworker running
completed Task finished with an outcome recorded stopped
escalated Task flagged for supervisor attention due to complexity or urgency running
cancelled Task terminated before completion by a supervisor stopped
awaiting_client Task paused while waiting for a response from the client paused
awaiting_verification Task paused while waiting for a verification result paused
pending_review Task submitted for supervisor review before completion running

Actions

ActionActorsTransitionSteps
claim API →
Caseworker takes ownership of an unassigned pending task
Case Worker, Supervisor pendingin_progress
  • Assign task to the claiming worker sets assignedToId
  • Emit workflow.task.claimed — Emit a domain event recording the claim and who claimed the task
complete API →
Marks an in-progress task done with an outcome and optional notes
Case Worker, Supervisor in_progresscompleted
  • Record when work finished sets completedAt
  • Store the completion outcome from the request sets outcome
  • Store optional completion notes from the request sets completionNotes
  • Emit workflow.task.completed — Emit a domain event recording the completion and its outcome
  • If $request.createFollowUp is true:
    • Create a follow-up task when caller requests one
release API →
Returns an in-progress task to the queue, clearing the assignment
Case Worker, Supervisor in_progresspending
  • Clear assignment so task returns to queue sets assignedToId
  • Emit workflow.task.released — Emit a domain event recording the release and its reason
  • Route SNAP-only tasks to the SNAP intake queue; falls through to the general queue for multi-program or non-SNAP tasks. For tasks linked to an application, SNAP is determined by the application's program list; for standalone tasks, it is determined by the task's programType field.
  • Set expedited priority (1) when the task is flagged as expedited; otherwise set normal priority (3).
escalate API →
Escalate a task; assigned workers can escalate in-progress tasks, supervisors can escalate from any state
Case Worker, Supervisor pendingorin_progressescalated
  • Record when the task was escalated sets escalatedAt
  • Set expedited priority (1) when the task is flagged as expedited; otherwise set normal priority (3).
  • Emit workflow.task.escalated — Emit a domain event recording the escalation
de-escalate API →
Returns an escalated task to the pending queue
Supervisor escalatedpending
  • Route SNAP-only tasks to the SNAP intake queue; falls through to the general queue for multi-program or non-SNAP tasks. For tasks linked to an application, SNAP is determined by the application's program list; for standalone tasks, it is determined by the task's programType field.
  • Set expedited priority (1) when the task is flagged as expedited; otherwise set normal priority (3).
  • Emit workflow.task.de-escalated — Emit a domain event recording the de-escalation
cancel API →
Supervisor cancels a task from any active state
Supervisor pendingorin_progressorescalatedcancelled
  • Record when the task was cancelled sets cancelledAt
  • Emit workflow.task.cancelled — Emit a domain event recording the cancellation
reopen API →
Supervisor returns a cancelled task to the pending queue
Supervisor cancelledpending
  • Clear the cancellation timestamp on reopen sets cancelledAt
  • Route SNAP-only tasks to the SNAP intake queue; falls through to the general queue for multi-program or non-SNAP tasks. For tasks linked to an application, SNAP is determined by the application's program list; for standalone tasks, it is determined by the task's programType field.
  • Set expedited priority (1) when the task is flagged as expedited; otherwise set normal priority (3).
  • Emit workflow.task.reopened — Emit a domain event recording the reopen
await-client API →
Pauses an in-progress task while waiting for a client response
Case Worker, Supervisor in_progressawaiting_client
  • Record when the task entered a waiting state sets blockedAt
  • Schedule auto-cancellation after 30 calendar days of client unresponsiveness.
  • Emit workflow.task.awaiting_client — Emit a domain event recording the block
await-verification API →
Pauses an in-progress task while waiting for a verification result
Case Worker, Supervisor in_progressawaiting_verification
  • Record when the task entered a waiting state sets blockedAt
  • Schedule auto-resume after 7 calendar days waiting on verification.
  • Emit workflow.task.awaiting_verification — Emit a domain event recording the block
resume API →
Resumes a blocked task, cancelling any active wait timers
Case Worker, Supervisor awaiting_clientorawaiting_verificationin_progress
  • Clear the block timestamp on resume sets blockedAt
  • Cancel the client unresponsive timer; idempotent.
  • Cancel the verification timeout timer; idempotent, safe to call even if already fired.
  • Emit workflow.task.resumed — Emit a domain event recording the resumption
auto-resume API →
System resumes a verification-blocked task when the timeout fires or a verification result arrives
System awaiting_verificationin_progress
  • Clear the block timestamp on system resume sets blockedAt
  • Cancel the verification timeout timer; idempotent, safe to call even if already fired.
  • Emit workflow.task.resumed — Emit a domain event recording the automated resumption; causationid links to the triggering event
sla-escalate API →
System escalates a task when an SLA timer fires (creation deadline, warning, or breach)
System pendingorin_progressorescalatedescalated
  • If escalatedAt is not set:
    • Record first escalation time; not overwritten on subsequent timer-triggered escalations sets escalatedAt
  • Set expedited priority (1) when the task is flagged as expedited; otherwise set normal priority (3).
  • If reason is "sla_deadline_exceeded":
    Else:
auto-cancel API →
System cancels a client-blocked task after 30 days without a response
System awaiting_clientcancelled
  • Record when the task was automatically cancelled sets cancelledAt
  • Emit workflow.task.cancelled — Emit a domain event recording the automatic cancellation
submit-for-review API →
Worker submits a completed task to a supervisor for review and approval
Case Worker, Supervisor in_progressorescalatedpending_review
approve API →
Supervisor approves a submitted task and records the final outcome
Supervisor pending_reviewcompleted
  • Record when work was approved and completed sets completedAt
  • Store the outcome from the supervisor's approval sets outcome
  • Store optional notes from the supervisor sets completionNotes
  • Emit workflow.task.approved — Emit a domain event recording the approval
return-to-worker API →
Supervisor sends a review-pending task back to the worker with feedback
Supervisor pending_reviewin_progress
assign API →
Supervisor reassigns a task to a specific caseworker or moves it to a different queue
Supervisor no state change
  • Assign the task to the specified caseworker sets assignedToId
  • Optionally move the task to a different queue sets queueId
  • Emit workflow.task.assigned — Emit a domain event recording the assignment
set-priority API →
Supervisor manually overrides the task priority
Supervisor no state change

Event Subscriptions

EventEmitted byHandler steps
workflow.task.created unknown
  • Route SNAP-only tasks to the SNAP intake queue; falls through to the general queue for multi-program or non-SNAP tasks. For tasks linked to an application, SNAP is determined by the application's program list; for standalone tasks, it is determined by the task's programType field.
  • Set expedited priority (1) when the task is flagged as expedited; otherwise set normal priority (3).
  • Schedule auto-escalation 72 business hours after task creation.
workflow.task.updated unknown
  • If $this.data.changes.exists(c, c.field is "isExpedited" || c.field is "programType"):
    • Set expedited priority (1) when the task is flagged as expedited; otherwise set normal priority (3).
  • If $this.data.changes.exists(c, c.field is "programType" || c.field is "queueId"):
    • Route SNAP-only tasks to the SNAP intake queue; falls through to the general queue for multi-program or non-SNAP tasks. For tasks linked to an application, SNAP is determined by the application's program list; for standalone tasks, it is determined by the task's programType field.
  • If $this.data.changes.exists(c, c.field is "slaDeadline") and slaDeadline is set:
    • Schedule SLA warning escalation 48 hours before the task SLA deadline.
    • Schedule SLA breach escalation at the task SLA deadline.
workflow.creation_deadline unknown
  • Auto-escalate after 72h creation deadline
workflow.sla_warning unknown
  • Auto-escalate 48h before SLA deadline
workflow.sla_breach unknown
  • Escalate and record SLA breach at deadline
workflow.client_timeout unknown
  • Auto-cancel after 30 days client unresponsive
workflow.verification_timeout unknown
  • Auto-resume after 7 days verification timeout; passes timer event ID as causationid
eligibility.application.expedited Eligibility/Determination
  • If id is set:
    • {"PATCH":"workflow/tasks/$task.id","body":{"isExpedited":true,"slaType":"snap_expedited"}}
intake.application.submitted Intake/Application
  • Create an intake review task when an application is submitted
intake.application.closed Intake/Application
  • If id is set and status is "pending_review":
    • Complete the caseworker task that was awaiting supervisor approval
  • If id is set and status is "in_progress":
    • Complete the active caseworker task on application close
  • If id is set and status is "pending":
    • Cancel the unclaimed caseworker task when the application was auto-determined at submission
  • If id is set:
    • Complete the supervisor approval task
intake.determination.approval_needed Intake/Application
  • If id is set:
    • Move caseworker task to pending_review while supervisor reviews the determination
  • Create a supervisor approval task
intake.determination.rejected Intake/Application
  • If id is set:
    • Return the caseworker task to in_progress for revision
  • If id is set:
    • Complete the supervisor approval task with a rejected outcome