@foreseal/demo
v0.1.4
Published
Watch Foreseal verify-before-act: an AI agent ACTs on genuine bytes and REFUSEs four tamper/forgery attacks — runs locally in ~1s, no real USDC, no signup, no API key.
Maintainers
Readme
@foreseal/demo
Watch an AI agent refuse tampered data — in one command, in about a second.
npx @foreseal/demoNo install, no signup, no API key, no real USDC. It spins up the whole loop locally — a data seller fronted by the Foreseal Gate, a fake x402 facilitator standing in for settlement, and a buyer running Foreseal Kit's verify-before-act check — then plays six scenarios past the agent: two genuine payloads and four attacks. You watch it decide ACT ✅ or REFUSE ❌ on each.
A genuine receipt, trusted attester ............ ACT ✅
B one tampered byte (64000 → 99999) ............ REFUSE ❌ hash mismatch
C forged receipt (attacker self-signs) ......... REFUSE ❌ signer is not the attester we trust
D missing / empty receipt ...................... REFUSE ❌ fail-closed, no crash
E rewritten domain (chainId 1) ................. REFUSE ❌ consensus-domain pin
F binary (non-UTF-8) payload ................... ACT ✅ bytes survive verbatim, hash matchesThis demo matches the shipped SDK decision on every security leg. The ACT/REFUSE you watch above is hash + signer (recovered under the net-pinned domain) + refusal of a forked wire domain (scenario E) — and the shipped Kit (
@payperbyte/sdkverify()/verifyFromGatewayResponse, ≥ 0.1.5) makes the same decision, including the consensus-domain refusal. The ONE difference is expiry: this demo REFUSEs an expired receipt, while the SDK treatsexpiredas advisory (verdict.expired, for the caller to gate on — provenance is immutable). Integrate against the SDK decision shown below.
What this proves
An agent that spends money must prove the bytes it received are exactly what a
named publisher attested, before it acts on them. Foreseal does that with an
EIP-712 PayloadAttestation: the buyer recomputes the keccak256 hash of the
bytes it actually received and recovers the signer — so it can prove who
produced the bytes and that nothing changed in transit. If the hash doesn't
match, the signer isn't the attester you trust, or the receipt asserts a forked
domain, it refuses — and the shipped SDK makes the same decision. (This demo
additionally refuses an expired receipt; the SDK treats expiry as advisory — see
the note above.)
Two sides of one receipt. The Gate (
@foreseal/gate, on npm; also bundled into this demo) stamps a receipt over the exact bytes you paid for. The Kit (@payperbyte/sdk, on npm) lets the agent verify that receipt before it acts on a single byte. This demo runs both sides locally.
Use it for real
This package is a demonstration — it settles no real money. To wire the verify-before-act check into your own agent, install the Kit:
npm i @payperbyte/sdkWhen you pay a gateway feed, the response carries an X-BYTE-Attestation
header. verifyFromGatewayResponse runs both legs of the check you watched
above — it recomputes keccak256(body) (tamper-evidence) and recovers the
EIP-712 signer, then asserts it equals an attester you pinned out-of-band. A
forged response can't self-certify, because the header's own publisher field
is attacker-controlled — so the pinned expectedAttester is required; omit
it and the call fails closed.
import { verifyFromGatewayResponse, ARBITRUM_SEPOLIA } from "@payperbyte/sdk";
// Pin the gateway's attester out-of-band — read it ONCE from the agent card:
// GET https://x402.payperbyte.io/.well-known/agent.json -> .receipt.attester
const EXPECTED_ATTESTER = "0x…"; // the address from .receipt.attester
const res = await fetch("https://x402.payperbyte.io/feeds/defi-yields", /* …x402-paid… */);
const body = await res.text(); // the EXACT bytes — don't re-stringify
const header = res.headers.get("X-BYTE-Attestation"); // the raw JSON receipt header
const verdict = await verifyFromGatewayResponse(
body,
header,
ARBITRUM_SEPOLIA, // the attestation domain is anchored on Arbitrum (chainId 421614)
EXPECTED_ATTESTER, // REQUIRED — without it the verdict fails closed
);
if (verdict.verified) {
// safe to act — bytes hash-match AND the signature recovers to your pinned attester
} else {
// do NOT act — verdict.reason says why (hash mismatch / wrong signer / missing header)
}verifyFromGatewayResponse is the full decision: hash + signer recovered under
the net-pinned domain and a refusal if the receipt asserts a forked consensus
domain (≥ 0.1.5) — the exact decision the demo above shows, minus the demo's
expiry refusal (the SDK surfaces verdict.expired as advisory). (The lower-level
verifyPayload(bytes, expectedHash) does the hash leg only; it does not
recover or check the signer, so prefer the gateway helper whenever you have the
response body + the X-BYTE-Attestation header.)
Rails, stated honestly: x402 USDC payments settle on Base mainnet; the EIP-712 attestation domain is anchored on Arbitrum (the Kit ships
ARBITRUM_SEPOLIA/ARBITRUM_ONE; mainnet anchoring is audit-gated).
There's also a 15-tool MCP server you can drop into any agent stack:
npx -y byte-mcp-serverHonest scope
This proves authenticity — provenance, tamper-evidence, and signer identity. It does not score whether the data is correct; quality scoring is a separate layer on the roadmap, and we won't pretend otherwise. The project is dogfooded end-to-end; external adoption is the open question we're working on.
- Live feeds: https://x402.payperbyte.io/feeds
- Hosted MCP: https://mcp.payperbyte.io/mcp
- Kit (verify):
@payperbyte/sdk
MIT licensed.
