Skip to main content

State Channels

Spin up a machine, host pages on it. Every version is hash-committed to your entangled state, the page can compute against the kernel, and there is no separate Vercel, Netlify, or CDN to wire up.

A state channel is a hosted page bound to one of your state machines. You publish HTML; the framework serves the machine's default canvas at /s/<machine>/ and each published page at /s/<machine>/p/<page>/, stores every version as a row in state_machine_pages, and gives the page a same-origin compute proxy into the kernel. It's the third of the framework's three state primitives:

  • State machine — your scoped namespace + identity (state machines).
  • State contract — the deployable logic that runs on its clock (state contracts).
  • State channel — the pages the world sees, hosted on the machine. (this page)

What you get

  • Hosting with provenance. Every publish writes a new versioned row with a proof digest (SHA-256 over machine, page, content hash, version, and publisher ZID) and appends a deploy_published row to your entangled state at the Zeqond it landed. The page you serve is the page you can prove you served.
  • Versioning built in. Publishing flips the old version off and inserts the new one; history lists every version, rollback restores one. Nothing is ever overwritten in place.
  • Compute from the page. Each machine gets an auto-issued Site SDK publish key, held server-side. The hosted page calls the same-origin proxy — /s/<machine>/sdk/zeq/<op> for kernel routes, /s/<machine>/sdk/contracts/… for its contracts — and the proxy attaches the key. No key ever appears in your client code.
  • A sandboxed surface. Hosted pages are served with sandbox/integrity headers and run isolated from the admin surface and other machines; the SDK proxy is the page's only privileged path, rate-limited per machine.

Deploy a page

Three equivalent paths — same validation, same versioned row, same audit linkage:

Workbench — step 7, BUILD & DEPLOY: describe the page, the build flows through the compliance gate and publishes it, then shows the live URL. Pages you've built are listed on your machine's root canvas at /s/<machine>/.

CLI — one command (html is btoa(yourHTML) so it survives the terminal tokeniser):

site deploy hello aGVsbG8= "My Page" # page slug · base64 HTML · title
site list # published pages on this machine
site get hello # title, version, html
site unpublish hello # take it offline

curl — straight to the pages route with your machine key. html is plaintext here; agentZid is your machine's ZID:

curl -sS -X POST https://zeqapi.com/api/state-machines/<your-machine>/pages/hello/publish \
-H "Authorization: Bearer ${ZSM_KEY}" \
-H "Content-Type: application/json" \
-d '{ "title": "My Page", "html": "<!doctype html><h1>hello</h1>", "agentZid": "<your-machine-zid>" }'

The page is live at https://zeqapi.com/s/<your-machine>/p/hello/. The full route set is GET /pages, GET /pages/:page, GET /pages/:page/history, POST /pages/:page/publish, POST /pages/:page/unpublish, POST /pages/:page/rollback — reference: Machine Pages API.

Caps: HTML ≤ 2 MB per page, title ≤ 200 chars, optional pythonScript ≤ 256 KB.


Compute from a hosted page

The proxy makes kernel work same-origin — relative URLs, no credentials in the page:

<script type="module">
// ./sdk/zeq/<op> proxies to /api/zeq/<op> with the machine's
// server-held Site SDK key attached. The page never sees the key.
const r = await fetch("./sdk/zeq/compute", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ operator: "NM19", inputs: { mass_kg: 5, acceleration_ms2: 2 } })
});
const envelope = await r.json(); // the same signed kernel envelope every surface gets
document.body.textContent = JSON.stringify(envelope, null, 2);
</script>

Every compute the page runs lands on your machine's entangled state — the same envelope path the CLI and Workbench use. The proxy is rate-limited (per-machine bucket) with request bodies up to 1 MB; if the machine has no Site SDK key yet, one is auto-issued to the owner on first use.

./sdk/contracts/… works the same way for the machine's state contracts — list them, read state, drive transitions from the page.


Custom domains — Zeq Edge

Out of the box a channel lives under /s/<machine>/. To put it on your own hostname with caching, rules, and DDoS protection, point a CNAME at Zeq Edge and register the site in the Zeq Edge app. Origin TLS is strict by default.


Guarantees

PropertyHow
Tamper-evidentper-version proof digest + deploy_published row on the entangled state; inspect via /api/chain/<machine>/explore or the Observer (/state/?slug=<machine>)
Versionedevery publish is a new state_machine_pages row; history + rollback, never an in-place edit
Computableauto-issued Site SDK key → same-origin /s/<machine>/sdk/* proxy to the kernel and your contracts
Yours to take downsite unpublish / POST .../unpublish; the audit history of what was served remains

Next

  • State Contracts — put logic behind the page, on the same machine's clock.
  • Machine Pages API — field-level reference for the pages routes.
  • State machines — the namespace your channel is bound to.
  • Zeq Edge — custom domains, caching, and edge rules in front of your channel.