wayleave 0.5.4 → 0.5.5
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.
- package/README.md +20 -1
- package/index.js +14 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Then policy runs per lane: allow, deny, rate-limit — and on routes you price,
|
|
|
25
25
|
|
|
26
26
|
Only the first lane is cryptographic. The other three are read off what the client says about itself, so a bot willing to lie reaches the human lane — see [Guarantees](#guarantees-honestly-stated), and set `strictPricedPaths` on anything you charge for.
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## Three ways to use it
|
|
29
29
|
|
|
30
30
|
**1. The hosted Identity API — no install, any language.** Post a request's
|
|
31
31
|
signature headers and get back who signed it and which lane it belongs in.
|
|
@@ -54,6 +54,25 @@ way to know which to believe.
|
|
|
54
54
|
you do not send. This is the path if you want to price routes, enforce access
|
|
55
55
|
rules, or stay in-process. Start below.
|
|
56
56
|
|
|
57
|
+
**3. A platform adapter — if your code does not run on Node.** This package is
|
|
58
|
+
Express middleware and Node's crypto; it cannot run on a Worker or a Deno
|
|
59
|
+
edge function. These can, share one policy engine with it, and are configured
|
|
60
|
+
the same way:
|
|
61
|
+
|
|
62
|
+
| Where you run | Install |
|
|
63
|
+
|---|---|
|
|
64
|
+
| Cloudflare Workers | [`@wayleave/cloudflare`](https://www.npmjs.com/package/@wayleave/cloudflare) |
|
|
65
|
+
| Vercel middleware | [`@wayleave/vercel`](https://www.npmjs.com/package/@wayleave/vercel) |
|
|
66
|
+
| Supabase Edge Functions | [`@wayleave/supabase`](https://www.npmjs.com/package/@wayleave/supabase) |
|
|
67
|
+
| Netlify Edge Functions | [`@wayleave/netlify`](https://www.npmjs.com/package/@wayleave/netlify) |
|
|
68
|
+
| An MCP server | [`@wayleave/mcp`](https://www.npmjs.com/package/@wayleave/mcp) |
|
|
69
|
+
|
|
70
|
+
All four HTTP adapters default to observe mode and fail open, exactly as this
|
|
71
|
+
one does. The MCP guard is the odd one: an MCP server has no HTTP request to
|
|
72
|
+
inspect and MCP clients carry no signatures, so it does not classify lanes at
|
|
73
|
+
all — it bounds tool calls by rate, budget and repetition instead, and says
|
|
74
|
+
`classification: "unknown"` rather than guessing.
|
|
75
|
+
|
|
57
76
|
## Quickstart: observe first
|
|
58
77
|
|
|
59
78
|
```sh
|
package/index.js
CHANGED
|
@@ -344,7 +344,18 @@ export function classify(req, directories, now, opts = {}) {
|
|
|
344
344
|
if (h['signature'] || h['signature-input'])
|
|
345
345
|
return { lane: LANES.SUSPECT, agentId: null,
|
|
346
346
|
evidence: [`crypto: ${v.reason}`, 'presented invalid signature'] };
|
|
347
|
-
|
|
347
|
+
/* WHICH pattern matched, not merely that one did.
|
|
348
|
+
|
|
349
|
+
This used to be `.some(...)`, and the evidence then quoted the first 40
|
|
350
|
+
characters of the user-agent. Almost every bot UA opens with a Mozilla
|
|
351
|
+
compatibility preamble and names itself at the END, so the quote cut off
|
|
352
|
+
exactly where the identifying part began: 486 crossings on one site all
|
|
353
|
+
recorded as `mozilla/5.0 applewebkit/537.36 (khtml, l`, indistinguishable
|
|
354
|
+
from each other and from a browser.
|
|
355
|
+
|
|
356
|
+
The matched pattern is the name. It was in hand and discarded. */
|
|
357
|
+
const agentMatch = AGENT_UA.map(p => (p.exec(ua) || [])[0]).find(Boolean);
|
|
358
|
+
if (agentMatch) {
|
|
348
359
|
// A UA naming a known operator is a claim, and claims are checkable when
|
|
349
360
|
// the operator publishes its addresses. Claiming to be GPTBot from an
|
|
350
361
|
// address OpenAI does not own is a stronger fraud signal than saying
|
|
@@ -356,10 +367,10 @@ export function classify(req, directories, now, opts = {}) {
|
|
|
356
367
|
: null;
|
|
357
368
|
if (ipOk === false)
|
|
358
369
|
return { lane: LANES.SUSPECT, agentId: null,
|
|
359
|
-
evidence: [`UA claims "${
|
|
370
|
+
evidence: [`UA claims "${agentMatch}"`,
|
|
360
371
|
`but ${opts.ip || 'the client'} is not a published address for it`] };
|
|
361
372
|
return { lane: LANES.DECLARED, agentId: null,
|
|
362
|
-
evidence: [`self-identified
|
|
373
|
+
evidence: [`self-identified as "${agentMatch}"`,
|
|
363
374
|
ipOk === true ? 'source address matches published range'
|
|
364
375
|
: 'no signature presented'] };
|
|
365
376
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wayleave",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Know which AI agents cross your API \u2014 verified by signature, not guessed from an IP. Sorts every request into four lanes, prices the non-human ones with HTTP 402, and never charges a human. Zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|