Demos · DEMO-HACK
Gate walkthrough
Same REST/JSON shape as a news poll API: different authority object. Each call carries a one-shot twin proof; the gate burns the nonce before it validates.
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
Happy path
Client canonicalizes → challenges → responds → assembles the envelope. Server burns, validates, then fetches headlines. Transcript tags match the platform observability taxonomy.
- canon0.00s
Canonicalized request body
method=POST endpoint=news.eni6ma.demo/api/news/poll
- challenge0.04s
Circuit challenge issued
tau bound · freshness window 5000ms
- respond0.18s
Twin respond completed
bearings spent · proof_hash attached
- envelope0.19s
Envelope assembled
nonce_uuid reserved · request_hash bound
- burn0.21s
Nonce burned before validate
ledger: RESERVED → SPENT
- verdict0.27s
ALLOW: twin validated
application policy passed · resource served
Screenshot pending
Client Poll UI: CNN allow
Gate order
- 01
Request hash
Recompute digests; reject on mismatch
- 02
Endpoint
endpoint_id matches server constant
- 03
Policy
policy_hash from server POLICY_STRING
- 04
Anchor
Circuit handle active in registry
- 05
Freshness
tau within the call window
- 06
Burn nonce
Spend before twin validation
- 07
Validate
Twin proof check (local or registry)
- 08
Serve
Application policy, then resource
Reject stages
Every failed submission still teaches the same lesson: the gate order is load-bearing. Below is what each emitted stage means, framed as how the mechanism works, not as a catalog of residual risk.
stage=request-hash
Body or binding mismatch
The gate recomputes the composite digest. Changing feed, limit, or any bound field without a fresh prove fails here.
stage=endpoint
Endpoint retarget
endpoint_id is compared to a server constant. A relayed proof aimed at another route fails the binding.
stage=policy-hash
Policy loosen attempt
policy_hash is derived from the server POLICY_STRING, not attacker-supplied policy text.
stage=anchor
Inactive circuit
The handle must be active. Revocation is one registry state change (deactivated circuits never reach serve).
stage=freshness
Stale tau
Envelopes outside the freshness window are rejected before burn.
stage=nonce
Replay of a fossil
Burn-before-validate spends the nonce on first submission. A second identical envelope dies at nonce.
stage=validate-proof
Twin failure
After burn, twin validation must still pass. Failed validation does not unspend the nonce.
stage=policy
Application policy
Even a valid twin must satisfy route policy (feeds, limits) before the protected resource runs.
- canon0.00s
Canonicalized request body
identical bytes to prior envelope
- envelope0.01s
Envelope received
same nonce_uuid as previous ALLOW
- burn0.02s
Nonce already consumed
stage=nonce · replay detected
- verdict0.02s
REJECT: fossil envelope
capture ≠ authority for a second spend
Screenshot pending
Adversary replay → nonce reject
Binding & burn
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);
}