Skip to content

spec: lifecycle - the whole legal status graph, enforced on every status write - #16

Open
delchev wants to merge 1 commit into
mainfrom
spec/lifecycle-state-machine
Open

spec: lifecycle - the whole legal status graph, enforced on every status write#16
delchev wants to merge 1 commit into
mainfrom
spec/lifecycle-state-machine

Conversation

@delchev

@delchev delchev commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

The gap

Everything else about statuses is stated one edge at a time: init: names where a record starts, a transitions button guards the flips a user performs through it, a workflow step sets one, a check files a rejected record in another. Nowhere does a conforming file say which moves are legal at all - so any writer that is not a transition button (a workflow branch, a glue action, an API call) can move a document from any status to any other, and nothing notices.

The 1.1 and 1.2 Planned lists named this ("a declarative state machine").

The construct

- name: SalesInvoice
  lifecycle:
    edges:
      - { from: DRAFT,  to: [ISSUED, CANCELLED] }
      - { from: ISSUED, to: [PAID, VOIDED] }

One entry per source status; either side accepts a seeded status name or its id. The graph is always over the entity's function: EntityStatus relation, so it names no column, and the nomenclature must be seeded in the same file (a status entity owned by another model is seeded there, and so is its lifecycle).

Two normative rules

  1. Every status write is validated against the graph - user, workflow, glue, transition button alike - so enforcement belongs to the layer every writer passes through, never to the transition endpoints alone, which would leave every other writer unguarded. Where the status relation declares init:, a record must also be created at the start: entering the lifecycle anywhere else skips the graph rather than travelling it.
  2. transitions become presentation over the edges: each from must reach its setStatus along a declared edge, and a status written by a workflow step or forced by a check's rejection must be one some edge reaches - reported when the file is read. A reject path transiting through an approved status is exactly the mistake the graph exists to catch.

Also in this PR

  • The construct joins the "Status references - name, not number" site list and Appendix A: DSL index.
  • transitions gains a sentence pointing at the graph.
  • "a declarative state machine" leaves the Planned list.

Implemented in Eclipse Dirigible - eclipse-dirigible/dirigible#6714 (PR eclipse-dirigible/dirigible#6733), which is where the wording above was proven out (including the on: key the shape deliberately does not have: it would be redundant, and YAML 1.1 reads a bare on as the boolean true).

…tus write

Everything else about statuses is stated one edge at a time: `init:` names the
start, a `transitions:` button guards the flips a user performs through it, a
workflow step sets one, a check files a rejected record in another. Nowhere does
a file say which moves are legal at all, so any writer that is not a transition
button can move a document from any status to any other.

`lifecycle: { edges: [...] }` states the graph once, over the entity's
`function: EntityStatus` nomenclature. Two normative rules follow:

- Every status write is validated against it - user, workflow, glue, transition
  button alike - which puts enforcement in the layer every writer passes through,
  never in the transition endpoints alone. With `init:` declared, a record must
  also be created at the start.
- `transitions` become presentation over the edges, and a status written by a
  workflow step or forced by a check must be one an edge reaches - reported when
  the file is read, since a reject path transiting through an approved status is
  exactly what the graph exists to catch.

Also: the construct joins the status-by-name list and Appendix A, and leaves the
Planned list (it named "a declarative state machine").

Implemented in Eclipse Dirigible (eclipse-dirigible/dirigible#6714).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant