Skip to content

design: EntityLifecycle for ProcessInstance — two revokers (delete vs cancel) + POST-style revoker method #281

@jwulf

Description

@jwulf

Context

Spinning out of the scope discussion on #280 (EntityLifecycle scenario template). ProcessInstance is the missing 11th OCA entity kind by every shape criterion except the revoker, where it has two open questions that warrant a dedicated design conversation before being folded into the standard EntityLifecycle template.

Why ProcessInstance doesn't fit the #280 template as-drawn

Standard EntityLifecycle (#280) assumes:

shape: "entity"
  establishedBy: POST  → 201
  observableVia: GET   → 200
  revokedBy:     DELETE → 204

ProcessInstance breaks two of those:

createProcessInstance: POST   /process-instances                            → 201   ✅
getProcessInstance:    GET    /process-instances/{processInstanceKey}       → 200   ✅
deleteProcessInstance: POST   /process-instances/{processInstanceKey}/deletion     ❌ POST, not DELETE
cancelProcessInstance: POST   /process-instances/{processInstanceKey}/cancellation ❌ POST, not DELETE

So:

  1. Revoker method isn't DELETE — both candidate revokers are POST /…/deletion and POST /…/cancellation (RPC-style action endpoints, not CRUD-style DELETE).
  2. Two distinct revokers with different semanticscancelProcessInstance is the engine-level termination (stops execution, leaves audit trail); deleteProcessInstance is the audit-cleanup operation (removes the historical record). They're not interchangeable; a lifecycle test needs to decide which one to exercise (or test both).

Open design questions

  1. Which revoker is "the" revoker for the lifecycle suite?

    • cancelProcessInstance — closer to "delete" from a user's mental model (the instance stops doing work); but the instance is still queryable as a completed/terminated record afterward, so observe-absent via getProcessInstance would return 200 with state: "CANCELED", not 404.
    • deleteProcessInstance — gives the 404 we want for observe-absent, but is a privileged audit-cleanup operation that's not the normal end-of-life for an instance.
    • Both — emit two lifecycle suites (cancel-then-delete chain, or two independent suites).
  2. How should the schema constraint on revokedBy accommodate POST-style revokers?

    • Relax the L3 invariant from "method = DELETE" to "method ∈ {DELETE, POST}" with a heuristic (path ending in /deletion, /cancellation, /resolution)?
    • Add an explicit revokeShape: "delete" | "action" field on EntityKind?
    • Carve out a new EntityKind shape (e.g. shape: "engine-entity") with looser invariants?
  3. Observe-absent semantics for cancel are not 404. They're "GET returns 200 with state: CANCELED". This is the same shape as the existing runtime-states.json witness predicate (e.g. ProcessInstanceCompleted.witness already encodes a JSONPath equals-check on state). Should the EntityLifecycle template grow a witness-shape observe step alongside the 404 one?

Related entities with the same shape

If the answer to #3 is "yes, add a witness-shape observe", several engine-managed concepts likely fit the same generalised template:

  • ProcessInstanceIncidentresolveProcessInstanceIncidents (bulk POST); observe-absent is "GET incident returns 200 with state: RESOLVED" or "search returns empty for this incidentKey".
  • Job — completion/failure via completeJob/failJob/throwJobError; observe-final-state via state field.
  • UserTaskassignUserTask/unassignUserTask/completeUserTask; observe via state field.

These are out of scope for #280 (CRUD entities) and out of scope for this issue (ProcessInstance specifically), but the design choice on #3 above sets the direction for how they'd eventually be modelled.

Acceptance criteria (to be confirmed once design questions resolved)

  • Design decision recorded on questions 1–3 above.
  • If schema relaxation: entityKindsSchema.ts updated and L3 invariants extended.
  • If new shape: new shape added with its own all-or-nothing rule.
  • ProcessInstance entry added to configs/camunda-oca/ontology/entity-kinds.json.
  • Lifecycle suite(s) emitted for ProcessInstance.
  • L3 invariant updated to include ProcessInstance in the expected suite enumeration.

Out of scope

Parent / related: #279, #280

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions