Skip to content

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_tip is 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 create action.
  • The create action 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_id
  • prev_hash
  • name
  • workflow
  • input

The action payload MUST NOT contain legacy or derived chain-link fields such as:

  • latest_hash
  • chain_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_hash is always the event hash this event appends to.
  • process.chain_tip is the current pointer used as prev_hash when 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 create action 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 create action 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 ```

  • H1 is stored once in the events table.
  • H1 is the event that was created inside parent process P.
  • H1 is also the initial chain_tip of child process C.
  • 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_HASH as prev_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_hash traversal.

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_hash is the global primary lookup key.
  • events.process_id identifies the active process that created the event.
  • events.process_id is 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_id is not sufficient to reconstruct the child process chain, because the child root event was created inside the parent process.

Storage Rules

  • events.event_hash MUST be globally unique.
  • events.prev_hash MUST reference an existing event hash, except for the singleton system genesis event.
  • processes.process_id MUST be globally unique.
  • processes.chain_tip MUST 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_tip pointers.
  • 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:

  1. Resolve event.process_id to an active process P.
  2. Verify event.prev_hash == P.chain_tip.
  3. Resolve the workflow that governs the action:
  4. for non-create actions: P.workflow.
  5. for create actions: event.action.workflow, the workflow of the process being created.
  6. Verify the action exists in that workflow.
  7. Verify actor authorization, guards, input schema, and workflow rules.
  8. Verify signature and event hash according to the canonical crypto specification.
  9. Apply effects atomically.
  10. Update all affected process chain_tip pointers.

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 create action effects
  • set child process chain_tip to 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_id is assigned by the server during process_event.
  • The client MUST NOT choose the child process_id for create events.
  • The server returns the child id in the process_event response.

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 create event.
  • 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_hash semantics to chain_tip.
  • Remove legacy latest_hash from business action payloads.
  • Keep canonical signed action.prev_hash and event row prev_hash aligned.
  • Ensure process_event validates prev_hash against active process chain_tip.
  • Ensure create inserts one event and one child process row atomically.
  • Ensure create postcondition: event_hash == parent.chain_tip == child.chain_tip.
  • Ensure processes.chain_tip is not treated as globally unique.
  • Ensure event traversal uses global event_hash lookup.
  • Update EventBuilder, Rust core, WASM, TypeScript, SQL schema, tests, and parity vectors.
  • Reset/reseed development database after implementation.