Core Engine Model Specification¶
Status¶
Accepted baseline for core engine assessment and implementation planning.
Source discussion: DISC-01.
This spec supersedes earlier designs that placed chain-link fields inside the business action payload or modeled spawned child creation as a separate staged/server-signed event.
Primitives¶
-
The engine has three core primitives: processes, workflows, and events.
-
Processes collectively hold the current state of the system.
- Each process has a stable
process_id. - Each process has a
chain_tip. chain_tipis the hash of the latest event that resulted in that process's current state.-
Each process is governed by exactly one workflow.
-
Workflows define the allowed actions for process state transitions.
- A workflow defines the action names, roles, guards, effects, and validation rules for the process it governs.
- Every workflow MUST define a
createaction. -
The
createaction defines how a process governed by that workflow is initialized. -
Events contain concrete action executions.
- Events are the only mechanism by which process state changes.
- Every accepted state change MUST be represented by an event.
- No process state may be created or mutated outside event application.
Event and Action Boundaries¶
- Chain position is event-level metadata.
- Business intent is action-level data.
An event envelope MUST contain:
event_hash— content hash of the accepted event.prev_hash— event hash this event appends to.process_id— the active process in which this event is created.action— concrete business action payload.header— actor/signature/registry metadata required for verification.
A canonical action payload MUST contain the signed business intent and witnessed chain link:
process_idprev_hashnameworkflowinput
The action payload MUST NOT contain legacy or derived chain-link fields such as:
latest_hashchain_tip
prev_hash is intentionally part of the signed action so the actor attests to the chain tip they observed.
Event Chain Rule¶
- Events form a global hash-linked chain/DAG using
event_hash -> prev_hash. prev_hashis always the event hash this event appends to.process.chain_tipis the current pointer used asprev_hashwhen appending to that process.
For a normal event inside process P:
```text precondition: event.process_id = P.process_id event.prev_hash = P.chain_tip
postcondition: P.chain_tip = event.event_hash ```
Process Creation Rule¶
- A process is created only by executing the
createaction of the workflow that will govern the new process. - A create event MUST occur within an already-active process.
- The active process supplies the chain context for the create event.
- The target workflow supplies the
createaction semantics for the new process.
For create event E initiated inside active process P and creating process C:
```text before: P.chain_tip = H0
create event: E.process_id = P.process_id E.prev_hash = H0 E.action.name = "create" E.action.workflow = C.workflow E.event_hash = H1
after: P.chain_tip = H1 C.process_id = server-assigned UUID C.workflow = E.action.workflow C.chain_tip = H1 ```
The same create event is the shared branch point for both processes.
A create event MUST NOT create a second synthetic system event.
A new business process MUST NOT start from zero hash.
Branching Rule¶
After a create event, the active process and newly created process may continue independently.
```text parent process P: H0 -> H1 -> H2 -> H3
child process C: H1 -> C2 -> C3 ```
H1is stored once in the events table.H1is the event that was created inside parent processP.H1is also the initialchain_tipof child processC.- Subsequent child events append to
C.chain_tip. - Subsequent parent events append to
P.chain_tip.
This creates an uninterrupted audit path from every process branch back to genesis.
Genesis Rule¶
- Only the absolute system genesis event may use
ZERO_HASHasprev_hash.
text
system_genesis.prev_hash = ZERO_HASH
- No business process may be rootless.
- Every business process MUST trace back to system genesis through global
event_hash -> prev_hashtraversal.
Chain Traversal Rule¶
Process history is reconstructed by pointer walk, not by filtering event rows by process_id.
To traverse process P:
text
h = P.chain_tip
while h != ZERO_HASH:
event = events[event_hash = h]
h = event.prev_hash
Important implications:
events.event_hashis the global primary lookup key.events.process_ididentifies the active process that created the event.events.process_idis NOT exclusive chain membership.- A shared branch-point event is stored once and may be part of multiple process histories by reference.
- Querying
WHERE process_id = child_idis not sufficient to reconstruct the child process chain, because the child root event was created inside the parent process.
Storage Rules¶
events.event_hashMUST be globally unique.events.prev_hashMUST reference an existing event hash, except for the singleton system genesis event.processes.process_idMUST be globally unique.processes.chain_tipMUST NOT be globally unique.- A create event hash is referenced by both the parent and child process immediately after creation.
- Process rows store current state and
chain_tippointers. - Event rows are append-only and immutable.
- Process rows do not own event rows; process histories are derived by walking global event pointers.
Validation Rules¶
For every submitted event:
- Resolve
event.process_idto an active processP. - Verify
event.prev_hash == P.chain_tip. - Resolve the workflow that governs the action:
- for non-create actions:
P.workflow. - for create actions:
event.action.workflow, the workflow of the process being created. - Verify the action exists in that workflow.
- Verify actor authorization, guards, input schema, and workflow rules.
- Verify signature and event hash according to the canonical crypto specification.
- Apply effects atomically.
- Update all affected process
chain_tippointers.
If validation fails, no event is inserted and no process state is changed.
Atomicity Rules¶
Event application is atomic.
For a normal event:
- insert event row
- update active process state
- update active process
chain_tip
For a create event:
- insert one event row
- update active process
chain_tip - insert new child process row
- set child process state from the target workflow's
createaction effects - set child process
chain_tipto the same event hash
All operations MUST commit or roll back together.
Create postcondition:
text
create_event.event_hash == parent.chain_tip == child.chain_tip
Signing and Hashing Rules¶
- Create events use the same signing and hashing formula as all other events.
- There is no staged signing.
- There is no server-side child create signature.
- There is no second child genesis event.
The signed canonical bytes MUST include the event-level chain position and the business action payload. The exact canonical byte layout and event-hash formula MUST be pinned in the crypto/parity spec and tested across Rust, WASM, and TypeScript.
Required parity coverage:
- ordinary non-create event
- system genesis event
- create event with shared branch point
- rejected/stale
prev_hash - cross-process audit traversal
Child Process ID Rule¶
- Child
process_idis assigned by the server duringprocess_event. - The client MUST NOT choose the child
process_idfor create events. - The server returns the child id in the
process_eventresponse.
For create events, response shape MUST include:
json
{
"event_hash": "...",
"chain_tip": "...",
"child_process_id": "..."
}
For non-create events, child_process_id is omitted.
Workflow Snapshot Rule¶
- Event validation MUST use the workflow definition effective at decision time.
- Workflow definitions used for accepted events MUST be auditable and immutable for that event.
- Future workflow updates MUST NOT change the meaning of already accepted events.
Edge Cases¶
| Case | Required behavior |
|---|---|
| System genesis | Only event allowed to use prev_hash = ZERO_HASH. |
| Manual customer create | Create occurs inside the system/root process and creates the customer process as a shared branch point. |
| Spawned child process | Same as create: parent process is active process; target workflow create initializes child. |
| Multiple creates from same parent | They occur sequentially; each create appends to the parent's current chain_tip. |
| Recursive create/spawn | Allowed only through sequential accepted events; each create has one active process and one target workflow. |
| Validation failure | No event insert, no parent update, no child row. |
Stale prev_hash |
Reject because event.prev_hash != active_process.chain_tip. |
| Child chain query | Must walk from child.chain_tip by global event_hash -> prev_hash, not filter by child process_id. |
Non-Negotiable Invariants¶
- Every process is governed by exactly one workflow.
- Every workflow defines
create. - Every event happens inside exactly one active process.
- Every non-genesis event appends to the active process
chain_tip. - Every business process is created by an accepted
createevent. - Every create event is a shared branch point between active process and new process.
- No business process starts from
ZERO_HASH. - Event rows are immutable and append-only.
- Process state is derived only from accepted events.
- Full audit traversal is by global event hash pointers.
Implementation Assessment Checklist¶
Existing code must be assessed and adjusted against this spec:
- Rename process state
latest_hashsemantics tochain_tip. - Remove legacy
latest_hashfrom business action payloads. - Keep canonical signed
action.prev_hashand event rowprev_hashaligned. - Ensure
process_eventvalidatesprev_hashagainst active processchain_tip. - Ensure
createinserts one event and one child process row atomically. - Ensure create postcondition:
event_hash == parent.chain_tip == child.chain_tip. - Ensure
processes.chain_tipis not treated as globally unique. - Ensure event traversal uses global
event_hashlookup. - Update EventBuilder, Rust core, WASM, TypeScript, SQL schema, tests, and parity vectors.
- Reset/reseed development database after implementation.