background gif

Demos · Gate walkthrough

On a REST-shaped news-poll API you already know how to reason about, a reusable authorization header is still replayable authority. Replace it with a one-shot proof and watch the successful path once, then every way Gate rejects a bad envelope.

One protected endpoint, one envelope per call

The wire shape is a plain REST/JSON POST to /api/news/poll, so from your client's point of view nothing exotic is happening. What is different is the authorization object. Each call carries an envelope (a one-time cryptographic authorization for a single request, replacing the reusable bearer token or API key) that is request-bound (the proof is cryptographically tied to this exact HTTP method, endpoint, body hash, policy, and timestamp; a captured proof does not work for any other request), and Gate (the enforcement component: a reverse proxy, SDK middleware, MCP wrapper, or sidecar that sits between callers and a protected route and requires a valid envelope for each request) burns the nonce in the nonce ledger (a durable append-only log that hands out single-use request tokens and records the moment each one is spent) before it validates the proof.

For a developer, the integration lift is small: keep your existing route, put Gate in front of it, and swap the Authorization header for an envelope. For a sysadmin, ENI6MA replaces the authorization layer (Bearer tokens, API keys, long-lived JWTs) and coexists with authentication (OIDC, SAML, mTLS) and with the reverse proxy, API gateway, service mesh, or WAF you already run. For a business reader: this is what a stolen credential is worth against an ENI6MA-protected route, which is one request that has already fired.

Burn-before-validate is the structural reason a second submission of the same envelope always fails.ShippingGate stage 5 spends the nonce in the durable ledger before stage 6 validates the proof.Holds under the reference architecture

Authority expires at the end of each request.The envelope binds method, endpoint_id, request hash, policy hash, tau, and nonce (one message, one use).Holds under the reference architecture

The allow path

On a good request, the client canonicalizes the body, runs the challenge and response with its compiled twin (the per-identity binary a workload runs to prove itself, produced by the Foundry minting appliance), and assembles the envelope. The server burns the nonce, validates the proof, and only then fetches headlines and returns them. The transcript on the left uses the same observability tags the production platform emits, so what you learn here maps directly onto what will show up in your logs.

Allow path transcript6 events
  • canon

    Canonicalized request body

    method=POST endpoint=news.eni6ma.demo/api/news/poll

    0.00s
  • challenge

    Twin challenge issued for this request

    τ bound into proof; freshness window 5000 ms

    0.04s
  • respond

    Twin response computed

    bearings spent · proof_hash attached to envelope

    0.18s
  • envelope

    Envelope assembled

    nonce_uuid reserved · request_hash bound

    0.19s
  • burn

    Nonce burned before validate

    ledger: RESERVED → SPENT

    0.21s
  • verdict

    ALLOW: twin validated

    application policy passed · resource served

    0.27s
Screenshot pending: the news client after the first successful poll returns headlines.

Gate order

  1. 01

    Request hash

    Recompute digests; reject on mismatch

  2. 02

    Endpoint

    endpoint_id matches server constant

  3. 03

    Policy

    policy_hash from server POLICY_STRING

  4. 04

    Anchor

    Circuit handle active in registry

  5. 05

    Freshness

    tau within the call window

  6. 06

    Burn nonce

    Spend before twin validation

  7. 07

    Validate

    Twin proof check (local or registry)

  8. 08

    Serve

    Application policy, then resource

Happy-path envelope accept

Happy-path envelope accept through challenge respond burn allow

Every way the gate can reject

Every failed submission teaches the same lesson: the gate order (the fixed eight-stage sequence of checks Gate runs on every untrusted request before application logic executes) is load-bearing, and each stage exists because something specific goes wrong when it is missing. The eight blocks below explain what each emitted stage means. This is a description of how the mechanism works, not a catalog of residual risk; the residual-risk numbers for your own deployment are what Verify (a customer-runnable attack suite that exercises a Gate deployment with adversarial traffic before real users do) is for.

stage=request-hash

Body or binding mismatch

Gate recomputes the composite digest for the exact request that just arrived. If the caller changed the feed, the row limit, or any field bound into the proof without re-running the ceremony, the digest no longer matches and the request is rejected before any policy check runs. This is what protects the demo from a captured envelope that an attacker retargeted to a different query.

stage=endpoint

Endpoint retarget

The endpoint identifier baked into the envelope is compared to a server-side constant for the current route. A proof that was minted for one route and then relayed to another route fails this check, so an envelope for /api/news/poll cannot be reused against /api/admin.

stage=policy-hash

Policy loosen attempt

The policy hash is derived on the server from the server-owned policy string, not from anything the caller supplied. An attacker who submits a permissive-looking policy alongside the envelope does not get to change what the gate considers valid.

stage=anchor

Inactive identity

The handle (the stable identifier for an identity or workload; deactivating a handle in Control is how revocation happens as a single state change) must be active in the registry. Deactivated identities never reach the validation step, so revoking a compromised workload is a single state change with immediate effect.

stage=freshness

Stale timestamp

Envelopes carry τ (tau, the microsecond timestamp the ledger records when a nonce is reserved, bound into the proof so a captured envelope goes stale within seconds). Anything outside the freshness window is rejected before the nonce is even spent, which bounds the lifetime of any captured envelope to a handful of seconds.

stage=nonce

Replay of a spent envelope

This is where burn-before-validate (the ledger records the nonce as spent before the cryptographic proof is checked, so a captured request cannot be re-submitted even if validation later rejects it) does its work. The first submission of a nonce spends it in the ledger; a second identical submission dies at this stage regardless of who the caller is.

stage=validate-proof

Twin validation failure

After the nonce has been burned, the compiled twin proof still has to pass. A failed proof does not un-spend the nonce, so an attacker cannot use a rejected request as a retry token or as a way to keep a nonce alive.

stage=policy

Application policy

Even a valid proof has to satisfy the route-level policy: the feed has to be one this endpoint is allowed to poll, the row limit has to be in range, and any other business rule declared for this route has to hold. Only then does the protected endpoint actually run.

Replay reject transcript4 events
  • canon

    Canonicalized request body

    identical bytes to prior envelope

    0.00s
  • envelope

    Envelope received

    same nonce_uuid as previous ALLOW

    0.01s
  • burn

    Nonce already consumed

    stage=nonce · replay detected

    0.02s
  • verdict

    REJECT: envelope already spent

    A captured envelope is not authority to spend the request a second time.

    0.02s
Screenshot pending: the adversary console showing the second submission dying at stage=nonce.

Gate reject matrix

Gate reject stages shown as red X and gold burn outcomes

What binding and burn look like in code

Two snippets, both short. The first shows how the request hash is derived from the fields that are actually bound into the proof, which is why an attacker cannot edit the body and reuse the envelope. The second shows why the ledger is written before the proof is checked, which is why a captured envelope cannot be re-spent even during a race.

function requestHash({ method, endpoint_id, requestBodyHash, policyHash, tau, nonce_uuid }) {
  const input = [method, endpoint_id, requestBodyHash, policyHash, String(tau), nonce_uuid].join('||');
  return sha256(input);
}

Envelope binding

Binding formula visual linking request fields to proof