camunda / camunda/api-test-generator

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

Open
#281 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

OCA
Dominant language
TypeScript
Stars
0
Forks
3
Avg merge
13h 41m
Merged PRs (30d)
23

Description

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

  • All other engine-managed concepts (Job, UserTask, Incident) — once a pattern is settled here, those follow as separate issues.
  • The 10 standard CRUD entities are covered by #280.

Parent / related: #279, #280

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the design discussion in #280 and the schema entry point in entityKindsSchema.ts, then compare the existing configs/camunda-oca/ontology/entity-kinds.json entries. Trace how L3 invariants and lifecycle suites are emitted; done means recording decisions for questions 1–3 and satisfying the corresponding schema, ProcessInstance, suite, and invariant acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
openapi, typescript
Domain
api, testing, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.