---
id: WF-CRM-ACT-005
title: Apply workflow task requests with repeat handling
trigger: >-
  A workflow caller invokes the task service for creation, closing, reassignment, date
  changes or offered-work reads.
product_area: crm
module: activities-tasks
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
implements:
  - CAP-CRM-ACT-017
  - CAP-CRM-ACT-013
moves:
  - STATE-CRM-ACT-002
  - STATE-CRM-ACT-003
  - STATE-CRM-ACT-004
crosses:
  - SVC-CRM-ACT-tasks
idempotency: >-
  Creation deduplicates a retained workflow action reference within the workspace;
  concurrent inserts converge on its unique index and return whether a task was created.
  Later commands keep no delivery ledger and return unchanged when their requested result
  is already satisfied. After an intervening change, a repeated command evaluates the new
  current state. External delivery guarantees are unverified.
concurrency: >-
  Existing-task commands serialize under row locking, while creation relies on the unique
  workflow-origin reference. Competing closure requests follow the committed status. No
  local delivery ledger prevents a previously applied command being applied again after
  another change.
hops:
  - 'n': 1
    actor_or_service: External workflow executor
    action: >-
      Invoke the task function as an allowed service principal for one workspace, carrying
      the originating user as request provenance.
    anchor: 'services-crm:aws/crm.service-functions.ts:tasks'
    seam: sync
    on_failure: >-
      Return CRM errors to the executor; external retry and applied-result policies
      require separate proof.
    left_inconsistent: 'Before local invocation, no CRM change has occurred.'
    observer: The external workflow run owns executor visibility.
    provenance: documented
    source: 'services-crm:modules/tasks/aws/api/tasks-service.routes.ts:tasksServiceRoutes'
  - 'n': 2
    actor_or_service: Task service route
    action: >-
      Reject HTTP or mismatched execution contexts and validate the selected
      service-operation schema.
    anchor: 'services-crm:modules/tasks/aws/api/tasks-service.schemas.ts:taskServiceRequestSchema'
    seam: sync
    on_failure: Return context or body validation errors.
    left_inconsistent: No task change survives rejected route validation.
    observer: The workflow caller receives the refusal.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks-service.e2e.spec.js#answers 403
      context_mismatch to a console caller reaching the route over HTTP, whatever its keys
  - 'n': 3
    actor_or_service: Task operation dispatcher
    action: >-
      Resolve the task from its identifier, creation action reference or agreeing pair;
      invoke the requested operation and log caller attribution.
    anchor: >-
      services-crm:modules/tasks/services/workflow-actions/task-service-operations.ts:runTaskServiceOperation
    seam: sync
    on_failure: Reject an unresolved action reference or disagreeing identifiers.
    left_inconsistent: Resolution failure leaves work unchanged.
    observer: Task function logs record the request.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/workflow-actions/task-service-operations.integration.spec.js#refuses
      an id and a run that name two different tasks (400), and changes neither
  - 'n': 4
    actor_or_service: Task persistence transaction
    action: >-
      Create unfinished work, close it, assign a user or candidate role, or change its due
      day using the service repeat policy and enabled attention synchronization.
    anchor: 'services-crm:modules/tasks/services/persistence/tasks.ts:createTaskWithOutcome'
    seam: sync
    on_failure: >-
      Roll back a changed request that fails lifecycle, locking, origin uniqueness or
      attention checks.
    left_inconsistent: No partial task write commits; external treatment of the refusal remains unverified.
    observer: The service caller receives task data or a coded refusal.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.workflow-actions.integration.spec.js#answers
      a completed task as it is, writing nothing, when asked again idempotently
  - 'n': 5
    actor_or_service: Task service result mapper
    action: >-
      Return the task and creation flag where applicable, or the ordered page of eligible
      offered work.
    anchor: 'services-crm:modules/tasks/aws/api/tasks-service.routes.ts:tasksServiceRoutes'
    seam: sync
    on_failure: An earlier operation error is returned instead of a success result.
    left_inconsistent: A lost response can conceal an already committed task operation.
    observer: The workflow caller receives the response.
    provenance: observed
    source: 'services-crm:modules/tasks/aws/api/tasks-service.routes.ts:tasksServiceRoutes'
branches:
  - >-
    The offered-work read consults the user’s security role assignments and returns
    unfinished, unheld, unqueued offers in creation order without writing.
  - >-
    Role reassignment clears a holder but keeps the queue; assigning a different user
    clears a retained candidate role.
  - A service can route or close work but cannot become its holder or make a user claim.
waits: []
evidence:
  - >-
    services-crm at a8d1364f: aws/crm.service-functions.ts;
    modules/tasks/aws/api/tasks-service.routes.ts, tasks-service.schemas.ts;
    services/workflow-actions/task-service-operations.ts; services/persistence/tasks.ts
    (createTaskWithOutcome, completeTask, cancelTask, assignTask, offerTask,
    setTaskDueDate, listOfferedTasks, rolesHeldBy); services/tasks/task-refusals.ts;
    docs/migrations/task-management/README.md §12.
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-IAM-001, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004]
---

# Apply workflow task requests with repeat handling

## What It Does

The service route gives workflow callers a bounded set of task operations without an HTTP interface. Creation uses an action-origin reference for deduplication. Other commands use current-state repeat checks, so their behavior differs from global exactly-once delivery.

## The Flow

```mermaid
flowchart TD
  A[External executor invokes service function] --> B[Check service context and operation schema]
  B --> C{Read offered work?}
  C -->|Yes| D[Read listed roles and eligible offers]
  C -->|No| E{Create work?}
  E -->|Yes| F[Deduplicate retained action origin]
  E -->|No| G[Lock task and check requested current state]
  G --> H{Already satisfied?}
  H -->|Yes| I[Return unchanged work]
  H -->|No| J[Apply guarded command and enabled attention]
  F --> K[Return work and creation flag]
  J --> L[Commit and return work]
  D --> M[Return offered-work page]
```

The numbered hops specify the request, persistence and integration boundaries in order. Each hop identifies its evidence anchor, synchronization seam and observable failure outcome. Branches distinguish optional and delegated paths.

## When Something Fails

Local errors and coded refusals return to the workflow caller. Already-satisfied service requests return before change-only locking and lifecycle restrictions. The external executor’s retry policy and interpretation of refused actions remain integration evidence requirements.

## Open Design Questions

The registered caller allowlist and executor behavior need external proof before workflow readiness is accepted.
