npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ava-pay/agent

v0.4.1

Published

Developer preview. Agent SDK for AVA Pay. Sign Visa Trusted Agent Protocol (RFC 9421), Google Agent Payments Protocol (AP2), and IETF Web Bot Auth requests. Plus the parsing primitives for building your own verifier. Pre 1.0: API may change.

Readme

@ava-pay/agent

Status: developer preview (0.4.x). The API surface may change before 1.0. 0.4.0 is the floor for anyone verifying Web Bot Auth requests whose key directory serves Appendix B proofs: 0.3.x classifies chatgpt.com's directory proof invalid, so a verifier built on it rejects every ChatGPT-signed request (key_proof_invalid). That failure was closed; nothing that should have failed was accepted. 0.4.0 is additive at the type level. Direct callers of verifyDirectoryProofs must now pass the response's Content-Digest header, or an offered proof is invalid.

(0.3.0 carried three security fixes to the Web Bot Auth and RFC 9421 parsers, two of which let requests that must never verify come back trusted: true. Do not run anything older.) See CHANGELOG.md.

(0.2.0 was a breaking release: the AP2 v0.1 Intent/Cart API buildAp2Headers, signIntentMandate, signCartMandate was removed in favor of AP2 v0.2 dSD-JWT mandate chains. See the AP2 section below.)

Be clear about what each protocol's verdict means. Web Bot Auth and browse-intent Visa TAP prove agent identity ("this request really came from this agent operator"), not that an end user authorized a purchase. The AVA TAP-style profile's mandate is agent-signed in this preview. AP2 v0.2 chains carry a user-rooted delegation (the root mandate is signed by the user/wallet key and delegates to the agent's key), which is the closest thing here to end-user payment authorization.

Sign AI-agent requests for all four protocols the AVA Pay merchant-side verifier accepts, from Node.js (≥20, zero dependencies):

  • Visa Trusted Agent Protocol (real wire format: agent-browser-auth / agent-payer-auth tags)
  • IETF Web Bot Auth (the scheme real ChatGPT agent traffic uses), tracking draft-ietf-webbotauth-httpsig-protocol-00 (formerly draft-meunier-webbotauth-httpsig-protocol-02; adopted 2026-09-01, content-identical, section numbers unchanged)
  • Google Agent Payments Protocol v0.2 (dSD-JWT Checkout / Payment mandate chains)
  • AVA's TAP-style profile (RFC 9421 + Ed25519 + x-ava-mandate)

Plus the parsing/verification primitives to build your own merchant-side verifier.

Install

npm install @ava-pay/agent

Use

Visa Trusted Agent Protocol (real wire format)

import { generateAgentKeyPair, signWithVisaTap } from '@ava-pay/agent';

const { privateKey } = generateAgentKeyPair(); // Ed25519; RSA keys work too (rsa-pss-sha256)

const signed = signWithVisaTap({
  url: 'https://shop.example.com/products/tool-1234',
  privateKey,
  keyid: 'agent_acme_shopping',        // resolvable via the merchant's directory
  tag: 'agent-browser-auth',           // or 'agent-payer-auth' at checkout
});

await fetch(signed.url, { method: signed.method, headers: signed.headers });

Checkout requests can attach the signed body objects (agenticConsumer / agenticPaymentContainer) via signTapObject: kid/alg/nonce must match the message signature.

Web Bot Auth (IETF)

import { generateAgentKeyPair, signWithWebBotAuth, webBotAuthKeyId } from '@ava-pay/agent';

const { publicKey, privateKey } = generateAgentKeyPair();
// Publish publicKey (as a JWK) at
//   https://YOUR-ORIGIN/.well-known/http-message-signatures-directory
// Verifiers resolve it by RFC 7638 thumbprint: webBotAuthKeyId(publicKey).

const signed = signWithWebBotAuth({
  method: 'GET',
  url: 'https://shop.example.com/products/tool-1234',
  signatureAgent: 'https://your-agent.example',
  privateKey,
});

By default this emits the bare-string Signature-Agent form that deployed agents send today. Section 5.2.1 of the draft requires signers to send the dictionary form and to cover the member keyed to their own signature label:

const signed = signWithWebBotAuth({
  method: 'GET',
  url: 'https://shop.example.com/products/tool-1234',
  signatureAgent: 'https://your-agent.example',
  privateKey,
  signatureAgentFormat: 'dictionary',  // Signature-Agent: sig1="https://your-agent.example"
  // keyedSignatureAgentComponent defaults to true here, covering
  //   "signature-agent";key="sig1"  rather than the whole field.
  // signatureAgentType: 'jwks_uri',  // optional §5.5 ;type= parameter
});

Verifiers accept both forms. The draft's Appendix E.2.1 vector verifies against this signer end to end.

Google AP2 v0.2 (mandate chains)

An AP2 v0.2 presentation is a delegated SD-JWT chain: a user-signed open mandate (constraints + the agent's key as cnf) followed by an agent-signed closed mandate committing to a merchant-signed checkout.

import {
  generateAgentKeyPair,
  buildCheckoutMandateChain,
  buildPaymentMandateChain,
  computeCheckoutHash,
} from '@ava-pay/agent';

const user = generateAgentKeyPair();   // the wallet/root key, registered in a directory
const agent = generateAgentKeyPair();  // the agent's key, delegated via cnf

const checkoutChain = buildCheckoutMandateChain({
  user: { privateKey: user.privateKey, kid: 'user_wallet_1' },
  agentPrivateKey: agent.privateKey,
  agentPublicKey: agent.publicKey,
  constraints: [
    { type: 'checkout.allowed_merchants', allowed: [{ name: 'Shop', url: 'https://shop.example.com' }] },
  ],
  checkoutJwt,                          // merchant-signed UCP Checkout JWT
  aud: 'https://shop.example.com',      // the merchant origin
  nonce: crypto.randomUUID(),           // single-use; verifiers deduplicate
});

await fetch('https://shop.example.com/cart', {
  method: 'POST',
  headers: {
    'ap2-checkout-mandate': checkoutChain,
    // optional: 'ap2-payment-mandate': buildPaymentMandateChain({ ... transaction_id: computeCheckoutHash(checkoutJwt) ... }),
  },
});

(The Ap2-Checkout-Mandate / Ap2-Payment-Mandate headers are AVA Pay's HTTP binding of AP2 v0.2; AP2 itself specifies A2A message transport.)

AVA TAP-style profile

import { generateAgentKeyPair, signWithVisa } from '@ava-pay/agent';

const { privateKey } = generateAgentKeyPair();
const signed = signWithVisa({
  method: 'POST',
  url: 'https://shop.example.com/cart',
  body: JSON.stringify({ items: [{ sku: 'TOOL-1234', qty: 1, price: 4999 }] }),
  agentId: 'agent_acme_shopping',
  privateKey,
  mandate: {
    id: `mandate_${Date.now()}`,
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + 600,
    maxAmountMinor: 50_000,
    currency: 'USD',
    allowedMerchants: ['shop.example.com'],
    buyer: { buyerId: 'user_abc' },
  },
});

Build your own verifier

import { parseSignatureInput, buildSignatureBase, verifyEd25519 } from '@ava-pay/agent/protocol/visa';
import { parseSignatureAgent, parseKeyDirectory, ed25519JwkThumbprint } from '@ava-pay/agent/protocol/web-bot-auth';
import { verifyTapSignature, parseVisaJwks, parseIdToken } from '@ava-pay/agent/protocol/visa-tap';
import { verifyChain, checkCheckoutConstraints } from '@ava-pay/agent/protocol/ap2';

API surface

Signers

  • generateAgentKeyPair(): AgentKeyPair: fresh Ed25519 keypair
  • signWithVisaTap(input): SignedRequest / signTapObject(fields, key): real Visa TAP
  • signWithWebBotAuth(input): SignedRequest / webBotAuthKeyId(key): string: Web Bot Auth
  • createRootMandate / presentMandate / buildCheckoutMandateChain / buildPaymentMandateChain / makeCheckoutJwt / computeCheckoutHash: AP2 v0.2 chains
  • signWithVisa(input): SignedRequest / encodeMandate(m): AVA TAP-style profile

Types

  • Mandate, BuyerInfo, IncomingRequest, VerificationResult, VerificationFailureReason
  • VerifiedProtocol, VerifiedAgentIdentity, TapVerificationDetail, OperatorRecord
  • VerificationResult carries an optional conclusive flag on both branches. Each failure reason's value is fixed by the exported REASON_CONCLUSIVE table, which is the list of reasons and their outcomes: false means the verifier could not complete its checks (the reasons are also exported as COULD_NOT_CHECK_REASONS), true means the request was definitively rejected. trusted stays false either way, so fail-closed behavior never depends on the flag. Read an absent value as conclusive. rejection(reason, message) builds a failure result whose flag comes from the table.
  • VerifiedAgentIdentity.binding is 'domain' for a key found through the reserved well-known directory path and 'url-only' for one declared via jwks_uri/cimd, which proves key continuity at a URL with no origin association.
  • CheckoutMandate, OpenCheckoutMandate, PaymentMandate, OpenPaymentMandate, Checkout
  • CheckoutConstraintEvaluator, PaymentConstraintEvaluator (pluggable validator registries)

Subpath imports for low-level work

  • @ava-pay/agent/protocol/visa: RFC 9421 parser, signature base, Ed25519 verify, content-digest
  • @ava-pay/agent/protocol/visa-tap: TAP tags/algorithms, Visa JWKS + PS256 IdToken parsing, signed body objects
  • @ava-pay/agent/protocol/web-bot-auth: Signature-Agent parsing (both wire forms, §5.5 discovery types), RFC 7638 thumbprints, key-directory parsing, Appendix B directory proof-of-possession (verifyDirectoryProofs / signDirectoryResponse)
  • @ava-pay/agent/protocol/ap2: dSD-JWT chain verify, v0.2 mandate shapes, constraint evaluators, compact-JWS helpers

Onboarding

To get a key recognized by AVA Pay merchants, either register it with the AVA Agent Directory (see AGENT_ISSUERS.md) or publish it at your origin's Web Bot Auth key directory. AVA Pay merchants resolve keys through a federated chain (Visa's directories → Web Bot Auth agent cards → the AVA directory), so a key published once works across protocols.

License

MIT