Ana içerik geç

State Contracts

A state contract is a state machine that lives inside your machine.

You define it in JSON — states, transitions, conditions, and the operator that executes each transition. You deploy it to your machine. Then it advances in one of two ways: you drive it with POST /api/chain/:slug/contracts/:id/transition, or it drives itself — a transition can carry a trigger (a recurring HulyaPulse tick, a cron schedule, an inbound event, or an aggregate over a window) plus pre_actions / post_actions (call an external API before computing; emit an event or override state after).

On every transition the framework runs the operator through the master equation, verifies the proof, wraps the result in a ZSP envelope, writes the transition to contract_transitions, updates current_state, appends a row to your audit entangled state, and mints a tally token. Every step — driven or autonomous — is atomic, signed, on the entangled state, and reproducible.


The shape of a contract

States are named regimes (one initial, any number terminal). Transitions move between them, gated by an operator and an optional condition. This is a real catalogue template — force-threshold-alarm, the classic structural-load watchdog (NM19, F = ma):

{
"name": "force_threshold_alarm",
"version": "1.0",
"created_by": "ZEQ07491829374",
"states": {
"idle": { "initial": true },
"watching": {},
"alert": {},
"cleared": { "terminal": true }
},
"transitions": [
{ "from": "idle", "to": "watching", "operator": "KO42", "proof_required": false, "auto": false },
{ "from": "watching", "to": "alert", "operator": "NM19",
"condition": "input.mass_kg * input.acceleration_ms2 > input.force_limit_n",
"proof_required": true, "auto": false },
{ "from": "alert", "to": "watching", "operator": "NM19",
"condition": "input.mass_kg * input.acceleration_ms2 <= input.force_limit_n",
"proof_required": true, "auto": false },
{ "from": "alert", "to": "cleared", "operator": "KO42",
"condition": "input.acknowledged == true", "proof_required": false, "auto": false }
],
"observers": [], "audit_clock": true, "zeqond_tick_rate": 1
}

Validated by ContractDefinitionSchema.parse and validateContractDefinition (shared/api-core/src/lib/contractEngine.ts). The operator id on each transition must exist in the live registry. KO42 is the always-on substrate operator; the physics operators (NM19 here) carry proof_required: true so each fire is compute → prove → verify.


The condition grammar

Conditions are evaluated with a safe-eval subset — no function calls, no arbitrary property access. The grammar:

expr := or
or := and ('||' and)*
and := comp ('&&' comp)*
comp := term (('==' | '!=' | '<' | '<=' | '>' | '>=') term)?
term := factor (('+' | '-') factor)*
factor := primary (('*' | '/') primary)*
primary := number | string | bool | null | identifier | '(' expr ')'
identifier := [a-zA-Z_][a-zA-Z0-9_.]*

Identifiers resolve from a flat scope built at transition time: the values you pass in body.input (e.g. input.mass_kg), the compute result, contract state (current_state, contract_id, name), framework time (zeqond_now, phase_now), and caller identity (caller_zid). There is no eval, no Function, no DOM, no network — the evaluator walks an AST and rejects anything outside the grammar at deploy time.


The template catalogue

GET /api/contracts/templates returns the live catalogue. Each template ships with a complete definition, a use_cases summary, and the operator sequence it is tested against — and deploys as-is, schema-identical to the canonical create path.

The catalogue is operator-triggered physics machines: states are real regimes, transitions fire when a verbatim operator (≤0.1% precision, NIST-bound) crosses a declared threshold, and every fire is proven on the entangled state. It spans 40+ domains — Mechanics, Quantum, Relativity, Energy & Grid, Structural Engineering, Medical, Seismology and more — plus a domain-agnostic Foundations set.

curl -sS https://zeqapi.com/api/contracts/templates/categories
curl -sS https://zeqapi.com/api/contracts/templates?category=Foundations
curl -sS https://zeqapi.com/api/contracts/templates/force-threshold-alarm

Foundations — the universal primitives

Most templates are domain monitors. The Foundations category is different: domain-agnostic building blocks that drive the autonomous engine. Customise the thresholds, intervals, event names, and external API to your own domain.

IDWhat it doesEngine feature it shows
scheduled-computeSelf-firing transition every N Zeqonds (or a cron expression); emits scheduled_tick each firerecurring trigger
threshold-monitorGeneric watchdog over a reading stream; breaches on the windowed average, with hysteresison_aggregate (avg) + emit
oracle-feedPolls a registered external API every N Zeqonds, binds the response, emits a signed datumrecurring + api_call pre-action
approval-workflowpending → approved on N sign-off events, or → rejected on a single rejecton_aggregate (count) + on_event

A few representative domain monitors, for shape:

IDCategoryUse case
force-threshold-alarmMechanicsNM19 (F = ma) per reading → alert when force crosses your limit
sla-monitorOperationsAvailability vs SLO → breach → escalate, every breach Zeqond-stamped
earthquake-early-warningSeismologyP-wave amplitude gate → warn before the S-wave arrives

Triggers — make a contract autonomous

A transition with no trigger waits for you to drive it. A transition with a trigger fires itself. Six kinds:

kindFires whenKey fields
recurringEvery every_zeqonds ticks, or on a cron scheduleevery_zeqonds or cron (+ cron_tz), max_fires?
one_shotOnce, at a wall-clock Zeqondat_zeqond or at_unix
on_eventAn emitted event landsevent, from_slug?, where?, into?
on_events2–4 events combine (any / all)match, events[], within?
on_logicA recursive AND/OR tree of events matchestree, within?
on_aggregateAn aggregate over a window crosses a boundevent, aggregate{fn,field?}, op, threshold, within

A heartbeat — a self-loop that fires every 60 Zeqonds and emits an event:

{ "from": "running", "to": "running", "operator": "KO42",
"proof_required": false, "auto": false,
"trigger": { "kind": "recurring", "every_zeqonds": 60 },
"post_actions": [ { "type": "emit", "event": "scheduled_tick" } ] }

The scheduler computes next_fire_at_zeqond at deploy and re-arms after each fire — no external driver needed. (Cron form: "trigger": { "kind": "recurring", "cron": "0 9 * * 1-5", "cron_tz": "Europe/London" }.)

Pre- and post-actions

Each transition can run up to four pre_actions (before compute) and four post_actions (after the audit row commits):

  • api_call (pre) — call a registered external API and bind the response into the transition input: { "type": "api_call", "api": "weather", "path": "/current", "method": "GET", "params": { "q": "London" }, "into": "wx" }.
  • emit (post) — append an event other contracts can react to (optionally on a labelled bus): { "type": "emit", "event": "over_limit", "payload": {}, "tag": "alerts" }.
  • set_state (post) — override the runtime state, last matching when wins: { "type": "set_state", "to": "alert", "when": "result.value > 100" }.

Together, triggers + actions turn a contract from a passive state map into an autonomous agent that polls, computes, decides, and signals on the HulyaPulse cadence.


Deploying a contract

From a template — one call (authenticated with your session or machine key):

curl -sS https://zeqapi.com/api/contracts/templates/force-threshold-alarm/deploy \
-H "Authorization: Bearer ${ZSM_KEY}" \
-H "Content-Type: application/json" \
-d '{"slug":"my-machine"}'

Returns 201 with the freshly-created contract row. The handler loads the template definition, stamps created_by = caller_zid, runs validateContractDefinition against the live operator registry, inserts into contracts with current_state = the template's initial state, and (if any transition carries a time trigger) pre-computes next_fire_at_zeqond.

A custom definition — POST your own JSON to the create route. Same validation, same result:

curl -sS https://zeqapi.com/api/chain/my-machine/contracts \
-H "Authorization: Bearer ${ZSM_KEY}" \
-H "Content-Type: application/json" \
-d @force_threshold_alarm.json

From the terminal, contract deploy <json> does the same and round-trips with contract export. From the Workbench, the Contract IDE (/apps/contract-ide/) authors the JSON with a live state-diagram preview, dry-run, and one-click deploy.


Driving a transition

For transitions you advance yourself (no trigger):

curl -sS https://zeqapi.com/api/chain/my-machine/contracts/${CONTRACT_ID}/transition \
-H "Authorization: Bearer ${ZSM_KEY}" \
-H "Content-Type: application/json" \
-d '{
"to": "alert",
"input": { "mass_kg": 1200, "acceleration_ms2": 9.81, "force_limit_n": 10000 }
}'

The engine:

  1. Resolves the contract and the requested transition (from = current_state, to = body.to).
  2. Evaluates the condition in the safe-eval. Failure → 400 condition_failed.
  3. Calls the operator: compute → prove → verify (the prove step runs ["KO42", contract_operator] as the entangled state).
  4. Wraps the result in a ZSP envelope.
  5. Atomically writes a contract_transitions row AND updates contracts.current_state.
  6. Appends a row to the audit entangled state (audit_log) with the proof digest.
  7. Mints a tally token.
{
"ok": true,
"new_state": "alert",
"previous_state": "watching",
"proof_digest": "7f...64hex",
"zeqond_number": 2287439213,
"tally": { "tokenId": "uuid", "remaining": 999 }
}

The transition is now durable, replayable, and verifiable.


Reading the audit trail

Every transition lands in two places. The full record:

curl -sS https://zeqapi.com/api/chain/my-machine/contracts/${CONTRACT_ID}/audit \
-H "Authorization: Bearer ${ZSM_KEY}"

returns total_transitions plus the ordered list with proofs, results, ZSP envelopes, and timestamps. The compact entangled-state row (just hashes + Zeqonds) is in /api/chain/:slug/explore filtered by transition_type: "contract".


Verifying the entangled state

A standalone integrity check:

curl -sS https://zeqapi.com/api/chain/my-machine/contracts/${CONTRACT_ID}/verify \
-X POST \
-H "Authorization: Bearer ${ZSM_KEY}"

walks every successful transition and checks that each row's from_state matches the previous to_state, terminating at current_state:

{ "ok": true, "valid": true, "broken_at": null, "current_state": "alert", "total_transitions": 1, "zeqond_number": 2287439299 }

This is independent of entangled-state-level PoHC validation. PoHC validates the entangled state (no row tampered); contract verify validates the state progression (no transition out of order). Both must pass for a contract to be trusted.


When transitions fail

StatuserrorCause
400Missing 'to' staterequest body lacked to
400No transition: X → Ythe definition doesn't allow current_statebody.to
400condition_failedthe safe-eval returned false
400INVALID_INPUTa required input is missing or has the wrong type
403forbiddencaller lacks the operator role
404contract_not_foundthe contract id isn't owned by this slug
503compute_failedthe operator sequence hit a runtime error in compute / prove / verify

Failures are still recorded in contract_transitions with success: false and the error message — every attempt is on the audit trail, even the rejected ones.


Next

  • Triggers + the scheduler — the autonomous engine that fires recurring, cron, and event-driven transitions on the HulyaPulse cadence.
  • Protocols — protocols — the operator/API primitives a contract's operators compose.
  • Tally tokens — tally-tokens — the receipt minted on every successful transition.
  • 7-step protocol — seven-step-protocol — what KO42 + the operator does inside the engine.
  • Operators — operators — the verb on each transition.
  • Worked example — Thermal router — a poll → compute → emit contract, end to end.