Skip to main content

ZeqStream

Every other pipeline in this section is a one-shot compute: you POST inputs, you get one sealed result. ZeqStream is the standing version: it streams a state contract — an editable definition of what fires — on a cadence, seals one proof each fire, and hands the output to your software in whatever shape you choose. Put the stream's own API key in your game, sensor, instrument, or plugin and pull the data.

(Note the words: this is ZeqStream — distinct from Zeq Studio (the builder) and from state channels (hosted pages). A ZeqStream streams a state contract.)

Each fire is exactly one Zeqond (T_Z = 0.777000777 s). On every fire the contract runs and seals one ZEQ envelope + ZEQOND receipt onto the entangled-state chain — the same seal, the same 7-step wizard, the same reality check as calling the solver directly. The stream persists: an id, its own key, a fire count, a rolling tickRoot, and a head state you can read back. Canonical paths are /api/zeq/streams/* (the older /api/zeq/stream/channels/* still work).

The state contract, and shaping its output

A stream carries an editable state contract — what fires (the solver + its constants, with room for guard/rule logic) — and an output format — how the fired result is shaped for whatever consumes it:

  • json (default) — the raw sealed tick.
  • template — a payload you code in your target language, with {{placeholders}} filled each fire. No code is executed — placeholders are substituted — so a hosted template is safe. {{value}}, {{unit}}, {{zeqond}}, {{zeqProof}}, {{tickRoot}}, {{result.<field>}} all resolve.

That's how you build plugins for any software: pick a preset (Unity C#, Unreal C++, Python dict, Lua table, CSV, custom JSON) or write your own, and the stream emits exactly what your simulation expects.

The compute always happens here — the payload is only delivery

Every fire runs the real math on the framework and seals it. The template does not move the computation to your side — it shapes how the sealed result is delivered so your precoded handler can fire it around your state contract. So every payload carries the proof it was computed: sealed: true, zeqProof, tokenId, envelopeUrl, and a verify pointer ({{zeqProof}} / {{envelopeUrl}} / {{verify}} resolve in templates too). The ZeqProof is the approval that the computation definitely happened — the receiver never has to trust an unverified answer.

Local compute — running the math on your hardware from the operator equations we publish (/api/operators, /api/kernel) — is a separate, subscription-tier capability (gated by bracket), not the default. By default, you compute with us and get the proof.

# edit the contract + output at any time
curl -sX POST https://www.zeq.dev/api/zeq/streams/$ID/update \
-H 'Authorization: Bearer YOUR_KEY' -H 'Content-Type: application/json' \
-d '{ "outputFormat":"template",
"payloadTemplate":"{ value = {{value}}, unit = \"{{unit}}\", z = {{zeqond}} }" }'

Pull the fired data

Point your simulation at the stream's pull endpoint with the stream key — you get the last fired output in the format you chose, with the right Content-Type:

curl -H 'Authorization: Bearer YOUR_STREAM_KEY' \
https://www.zeq.dev/api/zeq/streams/$ID/latest
# → your exact payload, e.g. { value = -0.0747, unit = "1/t", z = 2298889279 }

The WebSocket (wss://…/ws/stream?channel=$ID) pushes the same rendered payload the instant it fires; …/latest is the poll/pull fallback. Both are "sent to your simulation."

The app

There's a DNA-UI app at /stream/ (https://www.zeq.dev/stream/) to build, edit, and watch streams without touching curl. It's scoped to your session — your streams, your keys — and each stream shows its own unique machine API key, pull endpoint, and wss:// URL.

  • Build — pick the contract's solver, set constants, choose a seal cadence (every Zeqond, per minute/hour, or the 24-hour tick), pick the output (JSON or a coded payload with live preset preview), toggle auto-tick, create. The one-time key is shown to copy into your software.
  • Edit — an Edit contract button opens the contract (JSON) + the output format + payload template inline; save and the next fire uses it.
  • Watch — the live viewer streams every fire over WebSocket: latest value, a sparkline, the rendered output your plugin pulls, the tickRoot, and the proof — with a ticking-diamond beat on the HulyaPulse.
  • Hand offOpen in Zeq Studio (/apps/zeq-studio/?repo=zeq-streams), Save to ZeqGit (writes streams/<id>.json into your repo via the bridge), and Deploy as a contract (copies a contract stanza and opens the contract IDE).

Worked example — a quantum particle falling into a black hole

The blackhole solver is a genuine semiclassical computation: a radial Schwarzschild geodesic (GR) plus a quantum overlay (de Broglie wavelength, a Hawking temperature, a horizon-emission estimate). It is not quantum gravity, and says so. Its Schwarzschild radius and Hawking temperature match the textbook values; the geodesic's specific energy is conserved to ~10⁻¹⁴ %, which is what it seals against.

Stream it with autotick and watch the particle fall. Fire by fire, r → r_s, so the far-observer time-dilation dτ/dt → 0 and the redshift → ∞:

r/rs=10.00 dτ/dt=0.9487 redshift=×1.05 v/c=0.000
r/rs= 2.49 dτ/dt=0.7733 redshift=×1.29 v/c=0.579
r/rs= 1.02 dτ/dt=0.1477 redshift=×6.77 v/c=0.988
r/rs= 1.00 dτ/dt=0 redshift=∞ frozen=true

What happens to the particle: from far away it never crosses — it freezes and reddens at the horizon (dτ/dt→0, redshift→∞); in its own frame it crossed in finite proper time. In the app, the ◍ Black-hole demo button creates this stream in one click.

One-click from a Zeq Envelope

Every sealed envelope in the Envelopes manager (/vault/envelopes/) now has a ◆ Stream button. One click hands the token to the Studio, which resolves the solver the envelope came from, creates a live ticking channel from it, and opens it — turning a one-shot proof into a standing one.

Fairness — sub-ticks are free, the seal is what you pay for

A hosted channel evolves every Zeqond, but sealing every Zeqond would charge one credit-compute every 0.777 s — unfair across plans and a standing drain. So ZeqStream splits the two:

  • sub-ticks — the Zeqonds a channel advances between seals. Free local compute, hash-chained into tickRoot, never individually billed.
  • seal tick — the credit-compute. It fires once per tickIntervalZeqonds, mints one envelope, and commits tickRoot. This is what a subscription meters. A fair 24-hour tick is simply a large interval (≈ 111,197 Zeqonds ≈ 24 h at 0.777000777 s) — one sealed proof a day, however many Zeqonds passed underneath it.

tickIntervalZeqonds is a per-channel knob; the plan-based default is applied in code so the 24-hour tier plugs in without a schema change. Client-driven REST ticks seal on every call (you pay per call); auto-tick channels seal on the cadence.

Honest scope

The external cadence is per-Zeqond, and tickRoot is a rolling hash chain over the channel's sealed ticks — it commits the count of Zeqonds folded in, not a distinct physics state per pico-Zeqond. True per-sub-step physics arrives when a solver gains an incremental step(); today's solvers recompute per tick. Nothing here claims a sealed envelope per pico-Zeqond.

The lifecycle (REST — live)

VerbEndpointWhoDoes
createPOST /api/zeq/stream/channelsowner key/sessionmake a channel, mint its own key (shown once)
listGET /api/zeq/stream/channelsowneryour channels
getGET /api/zeq/stream/channels/:idownerread the channel head
tickPOST /api/zeq/stream/channels/:id/tickchannel keyadvance one Zeqond, seal it
closePOST /api/zeq/stream/channels/:id/closeownerclose + revoke the channel key

1 — create a channel

curl -sX POST https://www.zeq.dev/api/zeq/stream/channels \
-H 'Authorization: Bearer YOUR_KEY' -H 'Content-Type: application/json' \
-d '{ "solver": "lorenz", "label": "reactor-probe", "constants": { "steps": 400 } }'

solver is any solver-registry key (or send a natural-language query and it is classified, exactly like ZeqAuto). The reply carries the channel and — once, never again — the channel's own key:

{ "ok": true, "protocol": "ZeqStream",
"channel": { "id": "d5901d63-…", "solver": "lorenz", "status": "open", "tick": 0,
"endpoint": "https://www.zeq.dev/api/zeq/stream/channels/d5901d63-…/tick",
"wsUrl": "wss://www.zeq.dev/ws/stream?channel=d5901d63-…", "keyPrefix": "zeq_ak_113be7d6…" },
"domain": "Chaotic Dynamics",
"key": "zeq_ak_113be7d61db5…",
"keyNotice": "Save this key now — it is shown once." }

That key is what a sensor or game embeds. It is a real API key scoped to the channel's owner; ticking with it bills the owner and revoking it (close) cannot be undone.

2 — tick it (the sensor/game path)

curl -sX POST https://www.zeq.dev/api/zeq/stream/channels/d5901d63-…/tick \
-H 'Authorization: Bearer zeq_ak_113be7d61db5…' -H 'Content-Type: application/json' \
-d '{ "inputs": { "sigma": 10.0 } }'
{ "ok": true, "protocol": "ZeqStream", "channel": "d5901d63-…", "tick": 0, "zeqond": 2298886511,
"solver": "lorenz", "domain": "Chaotic Dynamics", "operators": ["KO42", "NL10"],
"value": -0.0747, "unit": "1/t",
"zeqProof": "0b09dbd2f246ae3e…", "envelope": { "tokenId": "ZT-zeq7yh3b198",},
"zeqond_receipt": {} }

inputs are merged over the channel's base constants for that tick, so an instrument streams its latest reading each Zeqond and gets back a sealed number bound to it. The channel's tick count advances and its head state persists.

3 — read the head, or close

curl -s https://www.zeq.dev/api/zeq/stream/channels/d5901d63-… -H 'Authorization: Bearer YOUR_KEY'
curl -sX POST https://www.zeq.dev/api/zeq/stream/channels/d5901d63-…/close -H 'Authorization: Bearer YOUR_KEY'

Only the current head lives in the channel row — the full per-tick history is the chain of sealed envelopes, browsable in the state observer. A channel at one tick per Zeqond is ~40.6M ticks a year; storing a row per tick would be the exact mistake the idle-tick throttle exists to avoid.

The seal always travels — you cannot fake an envelope

Every pull and every tick response carries the seal as headers a template cannot touch, whatever output format you chose:

X-Zeq-Sealed: true
X-Zeq-Proof: 51315f14308283c2dc9f67bd6ef8abef6a211352971c3ab2792bd223b211b09d
X-Zeq-Token: ZT-…-0878f693
X-Zeq-Zeqond: 2298962292
X-Zeq-Verify: POST /api/zeq/verify

The body is yours to shape (JSON or a coded template); the envelope — value, proof, token — is ours and rides along. A device can always verify, and a stream owner can never edit or hide the seal. Every fire still only seals when it clears the ≤0.1% tolerance.

Keyless pull — no API key, no .env

A signed capability URL: the signature is the credential, so a device pulls it with nothing but the URL. The signing secret stays server-side (in ZSC), never on the wire.

# owner: mint a keyless, expiring pull URL
curl -sX POST https://www.zeq.dev/api/zeq/streams/$ID/link \
-H 'Authorization: Bearer YOUR_KEY' -H 'Content-Type: application/json' \
-d '{ "ttlSeconds": 2592000 }'
# → { "url": ".../streams/$ID/pull?scope=latest&exp=…&sig=…", "expiresAt": "…" }

# device: pull it. no key, no cookie, no .env.
curl -s "https://www.zeq.dev/api/zeq/streams/$ID/pull?scope=latest&exp=…&sig=…"
# → your latest sealed payload; the seal is in the X-Zeq-* headers above.

Revoke by letting it expire or closing the stream. A tampered signature is rejected (401).

Encrypted line — ZeqSSH

A private, authenticated, forward-secret line over the stream. Not a shell: an AES-256-GCM channel whose plaintext is the sealed envelope, keyed by the same per-Zeqond HKDF record layer Zeq-SSL uses. Nothing sealed travels in the clear, and a captured frame's key never reopens a later one.

# owner: open the line — the secret is shown ONCE (keep it in memory, not a .env)
curl -sX POST https://www.zeq.dev/api/zeq/streams/$ID/secure/open \
-H 'Authorization: Bearer YOUR_KEY'
# → { "sessionId": "…", "sessionSecret": "…", "cipherSuite": "ZEQ-SSL-AES256-GCM-…",
# "pull": ".../streams/$ID/secure/pull?session=…" }

# device: pull an encrypted frame — keyless (the secret is what decrypts it)
curl -s "https://www.zeq.dev/api/zeq/streams/$ID/secure/pull?session=…"
# → { "iv": "…", "ct": "…(base64)…", "tag": "…", "zeqond": 2298962292 }

Decrypt it — the device derives the key itself; the server never sends it:

const crypto = require("crypto");
const key = crypto.hkdfSync("sha256",
Buffer.from(SESSION_SECRET, "hex"), // ikm
Buffer.from(SESSION_ID, "hex"), // salt
Buffer.from("zeq-ssl-record/s2c/" + f.zeqond),// info (rekeys every Zeqond)
32);
const dec = crypto.createDecipheriv("aes-256-gcm", Buffer.from(key), Buffer.from(f.iv, "hex"));
dec.setAuthTag(Buffer.from(f.tag, "hex"));
const env = JSON.parse(Buffer.concat([dec.update(Buffer.from(f.ct, "base64")), dec.final()]).toString());
// env = the sealed envelope: value, unit, zeqProof, tokenId, …

The 🔓 Keyless link and 🔐 Encrypted line buttons in the stream app generate all of this for you.

From the CLI

zeq stream create solver=lorenz label=reactor-probe steps=400
zeq stream tick <id> sigma=10
zeq stream get <id>
zeq stream list
zeq stream close <id>

stream create prints the channel key once — save it. stream tick prints the sealed value, the Zeqond, and the proof.

Billing

Every tick is a sealed compute: it charges the owner and mints an envelope, exactly like any /api/zeq/* call. On the free tier the daily compute cap applies to ticks too. There is no separate "streaming" price — a tick costs what the underlying solver costs.

Live push — WebSocket

Subscribe to a channel and receive every sealed tick the moment it seals (whether a REST call or the auto-tick daemon produced it). REST …/tick stays the fallback for clients that can't hold a socket.

// browsers can't set WS headers, so the channel key rides as a subprotocol
const ws = new WebSocket("wss://www.zeq.dev/ws/stream?channel=" + id,
["zeq-bearer", channelKey]);
// (or, for a device: wss://…/ws/stream?channel=<id>&key=zeq_ak_…)
ws.onmessage = (e) => {
const t = JSON.parse(e.data); // { type:"tick", zeqond, value, unit, zeqProof, tokenId, tickRoot }
};

The first frame is { type: "ws:ready", channel, solver, status, tick }; every subsequent frame is a sealed tick. Auth is the channel key (or any of the owner's keys).

Hosted auto-tick

Create a channel with autotick: true and the server advances it on its cadence — no client needed. A dashboard just subscribes over WebSocket and watches a hosted simulation evolve.

curl -sX POST https://www.zeq.dev/api/zeq/stream/channels \
-H 'Authorization: Bearer YOUR_KEY' -H 'Content-Type: application/json' \
-d '{ "solver":"lorenz", "autotick":true, "tickIntervalZeqonds":111197, "constants":{"steps":400} }'

Auto-tick is off by default — a channel only self-ticks when you opt in, and if the owner runs out of credits the daemon switches that channel's auto-tick off (it stops, it does not hammer the burn). Set tickIntervalZeqonds to the cadence you want; leave it unset to take your plan's fair default.

From MCP

Agents drive channels with one tool, zeq_stream:

zeq_stream action=create solver=lorenz autotick=false
zeq_stream action=tick channel=<id> inputs={"sigma":10}
zeq_stream action=get|list|close channel=<id>

create returns the channel key once; tick seals and returns the value, proof, envelope token, and tickRoot.

Not yet — true sub-step physics

The one thing deliberately not claimed: per-sub-step physics between seals. tickRoot commits how many Zeqonds were folded into each seal, but today's solvers recompute per tick rather than carrying state forward a nano-Zeqond at a time. When a solver gains an incremental step(), those real sub-steps fold into the same tickRoot with no change to the envelope-per-cadence rule.