@flintverify/verify
v0.1.1
Published
Verify AI agent transactions with FLINT before money moves or paid service is delivered.
Readme
FLINT Verify Kit
FLINT Verify Kit lets buyer agents verify before paying and seller services verify before serving a paid request. FLINT is the identity and authorization layer for agent commerce: it checks financial authority, runtime and wallet signals, produces an ALLOW, STEP-UP, REVIEW, or BLOCK verdict, and issues a signed verification record for the decision.
Release status
PRODUCTION. @flintverify/verify is publicly available from the npm registry. Install without a version to receive the current latest release, or pin an exact version for reproducible deployments.
Each release remains subject to exact-artifact validation, public registry installation tests, and FLINT's explicit publication approval.
Installation
npm install @flintverify/verifyThe package targets Node 18 and later. Framework adapters are optional peer integrations, so core users install only jose at runtime. Contributors can validate the repository source with:
npm install
npm run check
npm pack --dry-run --jsonInstall only the optional peers required by the selected adapter:
| Adapter | Optional peer packages |
|---|---|
| Core client and buyer wrapper | None beyond the package's jose dependency |
| Express | express |
| Hono | hono |
| LangChain middleware | langchain and @langchain/core |
| LangChain tool | langchain, @langchain/core, and zod |
| Coinbase AgentKit | @coinbase/agentkit and zod |
The supported version ranges are authoritative in peerDependencies inside the installed package manifest.
Buyer quickstart
import { createFlintClient, wrapFetchWithVerify } from "@flintverify/verify";
const client = createFlintClient({ partnerId: "your_partner_id", mode: "free" });
const verifiedFetch = wrapFetchWithVerify(fetch, client, {
declaredScope: { max_amount_per_tx_display: "25", allowed_counterparties: ["0xmerchant"],
time_window_end: new Date(Date.now() + 300000).toISOString(), allowed_actions: ["pay"], mandate_version: "v1" },
});
const response = await verifiedFetch("https://merchant.example/paid");Place the FLINT wrapper inside the x402 payment interceptor so FLINT sees the original 402 first on the response path:
application -> x402 payment interceptor -> FLINT wrapper -> network
FLINT returns an allowed 402 unchanged. The x402 layer remains solely responsible for payment construction, signing, settlement, and retry.
Seller quickstart
import { createFlintClient } from "@flintverify/verify";
import { flintVerifyExpress } from "@flintverify/verify/adapters/express";
const client = createFlintClient({ partnerId: "your_partner_id", mode: "free" });
app.use(flintVerifyExpress({ client, enforcement: "observe" }));
app.get("/paid", (req, res) => res.json({ verdict: req.flint?.verdict }));Start in observe mode. Change to enforce after checking real traffic and policy behavior.
API reference
createFlintClient(options)
Creates the core client.
baseUrl: optional FLINT origin, defaulthttps://flint.network.partnerId: required partner identifier attached to every request.mode:freeposts to/api/verify;meteredposts to/api/x402/verify.timeoutMs: per-attempt timeout, default2000.retries: retries after network errors or timeouts, default1for 2 attempts total.fetch: injectable fetch implementation for tests or x402-aware clients.
Every retry receives a fresh UUID v4 nonce and ISO-8601 timestamp. Requests that already returned an HTTP response are never retried.
client.verify(input)
Submits transaction metadata and returns a normalized VerifyResponse with uppercase verdict, score, confidence, top reasons, record ID, compact JWS, and hybrid record envelope. The client option partnerId is authoritative. The client creates nonce and timestamp fields.
The live free endpoint returns the hybrid envelope. The client reads the signed JWS claims to normalize that envelope into the same result shape used by the metered endpoint. Use verifyRecord() when cryptographic trust is required.
client.verifyRecord(envelope)
Fetches /.well-known/jwks.json from the configured FLINT origin and verifies the ES256 compact JWS locally with jose. It returns { valid, claims, error }. Version 1 does not verify the parallel ML-DSA-65 signature because the selected JOSE library does not yet support it.
client.acknowledgeRecord(recordId, options) and acknowledgeRecord()
Computes SHA-256 over the compact JWS payload-segment text and posts the receipt to /api/records/:id/acknowledge. options contains the envelope, acknowledger identity, optional public signature proof, and optional base URL. An unsigned receipt is retained as unverified_claim. A 404 explains that mutual acknowledgment requires record v1.1.
wrapFetchWithVerify(fetchLike, client, policy)
Intercepts an x402 HTTP 402, reads v1 or v2 payment requirements, verifies the proposed payment, and returns the original 402 only when policy allows the x402 payment flow to continue. It never pays, signs, retries a payment, or holds funds.
resolveStepUp(client, response, resolution)
Resubmits the original transaction with the selected remediation evidence and prior_record_id. Current advisory-only STEP-UP responses work even when step_up.options is absent. When the machine-readable menu is present, the selected option must be offered. mint_passport and present_passport promote a returned passport_id; reduce_amount applies the remediated amount.
verifyIncoming(ctx, client, options)
Generic seller and x402 v2 lifecycle-hook integration. Call it before settlement finalization. It maps payer address, amount, chain, passport, and a pre-existing record reference into a FLINT check and returns the full result.
flintVerifyExpress(options)
Express middleware exported from @flintverify/verify/adapters/express. It attaches the result to req.flint. Observe mode always continues. Enforce mode returns HTTP 403 for BLOCK and, by default, REVIEW. Set reviewAction: "pass" to pass REVIEW with flagged context. STEP-UP passes with context so the seller can issue a challenge. The adapter does not issue that challenge itself.
flintVerifyHono(options)
Hono middleware exported from @flintverify/verify/adapters/hono. It attaches the result with c.set("flint", result) and uses the same observe, enforce, REVIEW, and STEP-UP behavior as the Express adapter.
flintVerifyMiddleware(policy)
LangChain-compatible wrapToolCall middleware exported from @flintverify/verify/adapters/langchain. Matching payment tools are verified before execution. BLOCK throws FlintBlockedError. STEP-UP and REVIEW invoke the optional observation callback and proceed so an outer agent-loop policy can challenge interactively.
flintVerifyTool(client, defaults)
Framework-native LangChain tool exported from @flintverify/verify/adapters/langchain-tool. Agents should call it before any payment, x402 request, or checkout. Its observation contains verdict, score, top reasons, record ID, and record URL. The calling agent remains responsible for enforcing the returned verdict.
flintActionProvider(client, defaults)
Coinbase AgentKit-compatible action provider exported from @flintverify/verify/adapters/agentkit. It exposes verify_before_spend and acknowledge_record. The provider is structurally compatible with AgentKit without importing AgentKit runtime code or activating third-party telemetry in this package. The calling agent remains responsible for enforcing the returned verdict.
Adapter behavior
| Surface | Primary use | Built-in enforcement boundary | |---|---|---| | Core client | Normalize free or metered Verify responses | Returns the verdict; caller enforces it | | Buyer wrapper | Inspect an x402 challenge before payment handling | BLOCK stops; STEP-UP and REVIEW require an explicit callback decision; failures close by default | | Express and Hono | Verify an incoming paid-service request after trusted payment metadata is available | Observe continues; enforce blocks BLOCK and REVIEW by default; STEP-UP requires an outer challenge layer | | LangChain middleware | Intercept matching payment-shaped tools | BLOCK stops; STEP-UP and REVIEW are advisory to an outer agent loop | | LangChain tool | Give an agent a callable verify-before-spend tool | Returns an observation only | | AgentKit provider | Add verify-before-spend and acknowledgment actions | Returns action observations only |
Start seller integrations in observe mode. The Express and Hono adapters read payer, amount, network, Passport, record, and merchant-reference metadata from request headers. Those headers are not payment proof and are untrusted if they arrive directly from the public caller. A trusted gateway or payment middleware must verify the x402 proof, strip caller-supplied FLINT metadata, and set the authoritative values before either adapter can be used for enforcement.
Move to enforce only after that trust boundary, traffic, declared scope, REVIEW handling, STEP-UP handling, timeouts, and failure policy have been validated in the target service.
Policy object reference
Buyer and seller policies share these conventions:
declaredScope: transaction authority supplied to FLINT.agentClaim: optional identity and runtime claims.passportId: optionalkya_Agent Passport identifier.failOpen: behavior when FLINT fails before returning a verdict.
Buyer defaults failOpen to false. Seller observe mode defaults it to true; seller enforce mode defaults it to false. BLOCK is always a hard stop regardless of failOpen.
Buyer callbacks:
onVerdict: observes every completed verdict.onStepUp: returnsproceedorabort.onReview: returnsproceedorabort.
Seller controls:
enforcement:observeorenforce.reviewAction:blockby default orpass.
Error taxonomy
FlintError: base package error.FlintBlockedError: hard-stop BLOCK withrecordId,topReasons, andverdict.FlintStepUpError: unresolved STEP-UP or REVIEW with record context.FlintApiError: timeout, network, HTTP, malformed response, and payment-requirement errors. HTTP 402 errors retain the payment requirements inbody.
Messages are complete sentences. Verdict errors include the record URL when a signed record exists.
Free, metered, and marketplace endpoints
Free mode calls https://flint.network/api/verify.
Metered mode calls the high-assurance https://flint.network/api/x402/verify lane, priced at $0.01 USDC per call on Base mainnet through x402. The unpaid challenge is bounded. A paid retry must include a request-bound FLINT capability and DPoP proof in addition to valid x402 payment proof. Version 0.1.x does not mint that capability, create DPoP proof, or manage its owner-control-plane issuance. An injected x402-aware fetch is not sufficient unless the surrounding integration also supplies the required FLINT admission evidence.
The standard marketplace-callable transaction scan is POST /api/x402/scan. Version 0.1.x does not wrap that route. Agents call it with a compatible x402 client, pay for FLINT's scan, and submit a separate intended transaction for evaluation.
The core client never pays. On HTTP 402 it throws FlintApiError with the payment requirements so an integrating payment layer can decide whether to authorize payment. Do not market mode: "metered" as drop-in payment support until the capability and DPoP composition is implemented and verified.
Security
The package never stores or transmits private keys, seed phrases, wallet secrets, or payment signatures. It sends only verification metadata such as amounts, addresses, chain identifiers, hashes, identity hints, and declared authority to FLINT. It never holds, custodies, signs, or moves funds. Wallet and signing libraries stay entirely outside this package.
The package collects no telemetry and contains no analytics, error-reporting SDK, or phone-home path. Framework packages are optional peer integrations. jose is the only runtime dependency.
client.verify() normalizes the API response but does not make local signature verification implicit. Call client.verifyRecord() when the integrating system must cryptographically verify the ES256 compact JWS against FLINT's published JWKS. Version 0.1.x does not independently verify the parallel ML-DSA-65 signature.
Buyer policy fails closed by default. Seller observe mode fails open by default so it can measure traffic without interrupting service. Seller enforce mode fails closed by default. Configure these choices explicitly in production and never treat provider unavailability as an ALLOW verdict.
The seller adapters do not verify x402 payment proofs, settlement, or header provenance. Do not expose their enforcement mode directly to caller-controlled X-FLINT-* or X-PAYMENT-* headers. Enforce only after a trusted component has authenticated and normalized those values.
MCP-native integration
The canonical runtime-discovery surface is the FLINT MCP server. The LangChain tool and AgentKit action provider are framework-native equivalents for applications that register tools directly.
Examples
examples/x402-buyer: verify-before-pay composition with a synthetic or live x402 402.examples/x402-seller-express: observe-first Express seller integration.examples/langchain-agent: payment-shaped tool interception with ALLOW and BLOCK paths.
Build the root package before running an example. Each example reads FLINT_PARTNER_ID, defaulting to sandbox_public for the public sandbox.
npm run build
npm --prefix examples/x402-buyer start
npm --prefix examples/langchain-agent start
npm install --prefix examples/x402-seller-express
npm --prefix examples/x402-seller-express startThe buyer and LangChain examples call the live free Verify sandbox. They do not send payment. The seller example starts a local Express service in observe mode. Set X402_URL for the buyer only when you intentionally want it to contact a real protected resource.
Publication gate
Publication requires all of the following:
- JT controls the 2FA-enforced public
@flintverifynpm scope and separately authorizes package publication. - The exact packed artifact passes isolated ESM, CJS, type, adapter, and example validation.
- The public artifact is installed from npm and its version, exports, README, provenance, and dependency set are verified.
- Public FLINT documentation states
PRODUCTIONonly after registry verification succeeds and must pass the automated release-metadata guard. - Any claim of drop-in high-assurance metered support waits for capability and DPoP composition to be implemented and tested.
Contributing
Every pull request must pass:
npm run typecheck
npm test
npm run lint
npm run build
npm run test:smoke
npm run verify:releaseCI runs separate Node 18 jobs for typecheck, offline unit tests, and dual ESM/CJS build verification. Do not add runtime dependencies, telemetry, secrets, private signing material, or em dashes.
