agent402-tollbooth 0.10.8 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +24 -1
  2. package/edge.js +1 -1
  3. package/index.js +17 -0
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -186,7 +186,7 @@ import { ExactEvmScheme } from "@x402/evm/exact/server";
186
186
  const server = new x402ResourceServer(new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" }))
187
187
  .register("eip155:8453", new ExactEvmScheme());
188
188
  const x402 = paymentMiddleware(
189
- { "GET /*": { accepts: [{ scheme: "exact", network: "eip155:8453", price: "$0.001", payTo: "0xYourWallet" }] } },
189
+ { "/*": { accepts: [{ scheme: "exact", network: "eip155:8453", price: "$0.001", payTo: "0xYourWallet" }] } },
190
190
  server,
191
191
  );
192
192
 
@@ -211,6 +211,13 @@ What you get on every charged request:
211
211
  with the reference client - proven in the parent repo's CI by a real mppx
212
212
  purchase through this package.
213
213
  - **Proof-of-work first**, unchanged: a walletless agent always has a free path.
214
+ - **Only a taken payment opens the gate.** The middleware calls `next()` for a
215
+ request it does not price (a method or path outside its routes, OPTIONS on a
216
+ wildcard). A charged request passes only when it carries a payment and the
217
+ middleware took it (it buffered the response to settle after the handler, or
218
+ set a settlement header); anything else gets the gate's 402. Price every
219
+ method you serve in the middleware's routes (`"/*"` covers every method
220
+ except OPTIONS).
214
221
 
215
222
  Set a stable `TOLLBOOTH_SECRET` (or `mppSecret`) so MPP challenge ids verify
216
223
  across workers - the same caveat as proof-of-work tokens.
@@ -586,6 +593,22 @@ as drop-in copyable snippets.
586
593
  stop relying on detection entirely, use `mode: "all"` / `mode: "strict"`, and
587
594
  turn on `adaptive` so high-volume abuse pays escalating proof-of-work.
588
595
 
596
+ ## Upgrading from 0.10.8 or earlier
597
+
598
+ In x402 middleware mode, a request the gate charges now needs a payment the
599
+ middleware took. Before, when the middleware did not price the request's method
600
+ it called `next()` and the request passed through unpaid; now it gets the
601
+ gate's 402. With only `"GET /*"` priced, for example, a charged POST, PUT or
602
+ DELETE was served free before and is refused now.
603
+
604
+ - **Price every method you serve.** `"/*"` prices every method except OPTIONS;
605
+ list explicit routes (`"POST /*"`, `"PUT /*"`, ...) when a method needs its
606
+ own price.
607
+ - **OPTIONS:** the middleware's `"/*"` never matches it, so a charged OPTIONS
608
+ request gets the 402. Price it with an explicit `"OPTIONS /*"` route, or keep
609
+ it out of the charge with a `charge(req)` predicate.
610
+ - The reverse proxy CLI already prices `"/*"` and needs no change.
611
+
589
612
  ## Notes
590
613
 
591
614
  - Proof-of-work tokens are HMAC-signed, expiry-checked, single-use, and bound to
package/edge.js CHANGED
@@ -225,7 +225,7 @@ export function createEdgeTollbooth(config = {}) {
225
225
  const resource = origin + u.pathname + u.search;
226
226
  // Additionally bind the HTTP METHOD in the PoW challenge (x402 `resource`
227
227
  // stays a plain URL for wire compatibility).
228
- const powResource = `${request.method || "GET"} ${resource}`;
228
+ const powResource = `${String(request.method || "GET").toUpperCase()} ${resource}`;
229
229
 
230
230
  // An x402 payment presented on either header name. @x402/core emits
231
231
  // PAYMENT-SIGNATURE while older clients send X-PAYMENT, and a gate that
package/index.js CHANGED
@@ -507,7 +507,24 @@ export function createTollbooth(config = {}) {
507
507
  res.json = guard(realJson);
508
508
  res.send = guard(realSend);
509
509
  res.end = guard(realEnd);
510
+ const guardedEnd = res.end;
511
+ // The middleware calls next() for a request it does not price at all
512
+ // (@x402/express: a method or path outside its routes, OPTIONS on a
513
+ // wildcard), not only for a verified payment. This gate has already
514
+ // decided the request pays, so next() grants only with a payment on the
515
+ // request AND evidence the middleware took it: it buffered the response
516
+ // to settle after the handler (res.end wrapped), or set a settlement
517
+ // header already. Anything else is answered with the gate's 402.
518
+ const credentialSent = !!(req.headers["payment-signature"] || req.headers["x-payment"]);
519
+ const paymentTaken = () => res.end !== guardedEnd
520
+ || !!(res.getHeader("PAYMENT-RESPONSE") || res.getHeader("X-PAYMENT-RESPONSE"));
510
521
  const grant = () => {
522
+ if (!credentialSent || !paymentTaken()) {
523
+ if (granted || res.headersSent) return undefined;
524
+ restore();
525
+ res.setHeader("X-Tollbooth-Error", credentialSent ? "x402-payment-not-taken" : "x402-route-not-priced");
526
+ return send402();
527
+ }
511
528
  granted = true;
512
529
  intercepting = false;
513
530
  incr(viaMpp ? "mppPaid" : "x402Paid");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent402-tollbooth",
3
- "version": "0.10.8",
3
+ "version": "0.11.0",
4
4
  "description": "Agent402 tollbooth: open-source, self-hostable pay-per-crawl for x402 AND MPP (the sell side of Agentic Finance): charge AI bots per request (USDC via x402, or MPP - the Machine Payments Protocol - through the same settlement, or USDG on Robinhood Chain, or free proof-of-work) while humans browse free. Drop-in Express middleware or reverse proxy that settles both wires from env alone, on your own server with no account or signup.",
5
5
  "type": "module",
6
6
  "main": "index.js",