wayleave 0.5.0 → 0.5.1

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 (3) hide show
  1. package/README.md +4 -8
  2. package/index.js +31 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -32,7 +32,7 @@ signature headers and get back who signed it and which lane it belongs in.
32
32
  Nothing is stored, and your traffic never routes through us.
33
33
 
34
34
  ```sh
35
- curl -X POST https://wayleave-api-production.up.railway.app/v1/identify \
35
+ curl -X POST https://api.wayleave.dev/v1/identify \
36
36
  -H "Authorization: Bearer $WAYLEAVE_API_KEY" \
37
37
  -H "Content-Type: application/json" \
38
38
  -d '{"method":"GET","url":"https://api.yourapp.com/v1/data",
@@ -48,8 +48,7 @@ curl -X POST https://wayleave-api-production.up.railway.app/v1/identify \
48
48
 
49
49
  The same evaluator answers here and in the middleware, and a test asserts they
50
50
  agree — if the two front doors disagreed about one request you would have no
51
- way to know which to believe. (`api.wayleave.dev` is the intended hostname and
52
- has no DNS record yet; the URL above is the one that answers today.)
51
+ way to know which to believe.
53
52
 
54
53
  **2. The middleware — in your own process.** Nothing leaves your server that
55
54
  you do not send. This is the path if you want to price routes, enforce access
@@ -122,10 +121,7 @@ rather than quietly denying every payment.
122
121
 
123
122
  ## Enforce rules you set elsewhere
124
123
 
125
- > Requires 0.5.0. npm currently serves **0.4.1**, which has no `policy` option —
126
- > installing from npm and pasting this will silently do nothing. Until 0.5.0 is
127
- > published, install from source:
128
- > `npm install github:gibrancorbin11-hub/wayleave`
124
+ > Requires 0.5.0 or later, which is what `npm install wayleave` now gives you.
129
125
 
130
126
  A policy the gate fetches, rather than configuration compiled into your app:
131
127
 
@@ -192,7 +188,7 @@ that tooling in the wild does fetch.
192
188
 
193
189
  ## Status
194
190
 
195
- v0.5.0 — 155 tests, zero dependencies. Published on npm: 0.4.1.
191
+ v0.5.0 — 155 tests, zero dependencies. Published on npm.
196
192
 
197
193
  **0.5.0** does three things. Rules you set are now *enforced*: `policy: { url, publicKey }` fetches a
198
194
  signed policy, verifies it, caches it, and evaluates per request — denials carry the rule id in
package/index.js CHANGED
@@ -802,6 +802,20 @@ export class Wayleave {
802
802
 
803
803
  express() {
804
804
  return async (req, res, next) => {
805
+ /* The discovery document is answered first: before classification,
806
+ before rate limiting, before pricing. A manifest an agent must pay
807
+ to read cannot be discovered, and one that is classified as bot
808
+ traffic gets a 402 instead of the price list.
809
+
810
+ This lived only on manifestFor() until 0.5.1, so `app.use(gate.express())`
811
+ -- the integration the Quickstart shows -- served no manifest at all
812
+ while the README said every install with a priced route does. */
813
+ const manifest = this.manifestFor({
814
+ path: req.path || (req.url || '').split('?')[0],
815
+ headers: req.headers,
816
+ });
817
+ if (manifest) return res.status(manifest.status).set(manifest.headers).json(manifest.body);
818
+
805
819
  const r = await this.handleAsync({
806
820
  method: req.method, path: req.path || req.url,
807
821
  authority: req.headers.host || '',
@@ -816,10 +830,25 @@ export class Wayleave {
816
830
  }, undefined, req.headers['x-payment-proof'] || '');
817
831
  req.wayleave = r;
818
832
  if (r.status === 200) return next();
819
- if (r.status === 402)
833
+ if (r.status === 402) {
834
+ /* The 402 body and the manifest must come from one source, or an
835
+ index quotes a price the origin does not honour. `accepts` is
836
+ built by the same call the manifest is, so they cannot drift.
837
+
838
+ Without a payment config there is nothing spec-shaped to say --
839
+ no payee, no network, no asset -- so the internal challenge is
840
+ all that is sent, and `accepts` is absent rather than empty.
841
+ An empty accepts array would read as "priced at nothing". */
842
+ const body = { error: r.why, challenge: r.challenge };
843
+ const requirements = this.paymentRequirements({
844
+ path: req.path || (req.url || '').split('?')[0],
845
+ headers: req.headers,
846
+ });
847
+ if (requirements) { body.x402Version = 1; body.accepts = [requirements]; }
820
848
  return res.status(402)
821
849
  .set('x-payment-challenge', JSON.stringify(r.challenge))
822
- .json({ error: r.why, challenge: r.challenge });
850
+ .json(body);
851
+ }
823
852
  return res.status(r.status).json({ error: r.why });
824
853
  };
825
854
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wayleave",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Know which AI agents cross your API — 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",