@stigmer/outbound 3.34.0 → 3.36.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.
package/README.md CHANGED
@@ -4,7 +4,7 @@ The rules a Stigmer process follows when it dials a URL a user supplied, shared
4
4
 
5
5
  Two entry points:
6
6
 
7
- - `@stigmer/outbound/egress`: which addresses a process refuses to dial (`blockedReason`, two postures, `strict` for managed cloud processes and `relaxed` for a machine that belongs to the user), the check that applies a policy to a URL after resolving every address it has (`checkEgress`), and the fetch that applies it to every redirect hop (`guardedFetch`). A process composes one guarded fetch at its root and hands it to every module that dials; the modules hold no `fetch` of their own.
7
+ - `@stigmer/outbound/egress`: which addresses a process refuses to dial (`blockedReason`, two postures, `strict` for managed cloud processes and `relaxed` for a machine that belongs to the user), the check that applies a policy to a URL after resolving every address it has (`checkEgress`), and the fetch that applies it to every redirect hop and bounds every response body (`guardedFetch`). A process composes one guarded fetch at its root and hands it to every module that dials; the modules hold no `fetch` of their own.
8
8
  - `@stigmer/outbound/mcp-oauth`: how an MCP endpoint's authentication is read without a credential (`isOAuthChallenge`, the complete `initializeRequest`, `probeEndpointAuth`) and how its login server is found (`resolveAuthorizationServers` over RFC 9728, `readAuthorizationServerMetadata` over RFC 8414 with the issuer's path and OpenID's document).
9
9
 
10
10
  ## Why one library
@@ -1 +1 @@
1
- {"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../../src/egress/address.ts"],"names":[],"mappings":"AAkCA,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC/C;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAK3E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAoBpF"}
1
+ {"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../src/egress/address.ts"],"names":[],"mappings":"AAkCA,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC/C;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAK3E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAoBpF"}
@@ -1 +1 @@
1
- {"version":3,"file":"address.js","sourceRoot":"","sources":["../../src/egress/address.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"address.js","sourceRoot":"","sources":["../src/egress/address.ts"],"names":[],"mappings":"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"}
package/egress/check.d.ts CHANGED
@@ -24,6 +24,10 @@ export type EgressRefusal = {
24
24
  readonly kind: "too-many-redirects";
25
25
  readonly url: URL;
26
26
  readonly hops: number;
27
+ } | {
28
+ readonly kind: "response-too-large";
29
+ readonly url: URL;
30
+ readonly maxBytes: number;
27
31
  };
28
32
  export type EgressCheck = {
29
33
  readonly ok: true;
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/egress/check.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,4EAA4E;AAC5E,MAAM,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;AAExE,uFAAuF;AACvF,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC/E;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtF,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC/E;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;CAClD;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAiB9D;AAED,2DAA2D;AAC3D,qBAAa,WAAY,SAAQ,KAAK;IACxB,QAAQ,CAAC,OAAO,EAAE,aAAa;gBAAtB,OAAO,EAAE,aAAa;CAI5C;AAED,uEAAuE;AACvE,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAyB/H"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/egress/check.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,4EAA4E;AAC5E,MAAM,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;AAExE,uFAAuF;AACvF,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC/E;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjF;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1F,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC/E;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;CAClD;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAmB9D;AAED,2DAA2D;AAC3D,qBAAa,WAAY,SAAQ,KAAK;IACxB,QAAQ,CAAC,OAAO,EAAE,aAAa;gBAAtB,OAAO,EAAE,aAAa;CAI5C;AAED,uEAAuE;AACvE,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAyB/H"}
package/egress/check.js CHANGED
@@ -39,6 +39,8 @@ export function describeRefusal(refusal) {
39
39
  return `Refusing to reach ${refusal.hostname}: it resolves to ${refusal.address}, a ${refusal.reason} address the ${refusal.policy} egress policy does not dial.`;
40
40
  case "too-many-redirects":
41
41
  return `Refusing to follow more than ${refusal.hops} redirects from ${refusal.url.href}.`;
42
+ case "response-too-large":
43
+ return `Refusing to read more than ${refusal.maxBytes} bytes from ${refusal.url.href}.`;
42
44
  default: {
43
45
  const exhaustive = refusal;
44
46
  return exhaustive;
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/egress/check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAgChC,gEAAgE;AAChE,MAAM,UAAU,eAAe,CAAC,OAAsB;IACpD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,aAAa;YAChB,OAAO,gBAAgB,OAAO,CAAC,GAAG,EAAE,CAAC;QACvC,KAAK,oBAAoB;YACvB,OAAO,2BAA2B,OAAO,CAAC,MAAM,qCAAqC,CAAC;QACxF,KAAK,cAAc;YACjB,OAAO,+BAA+B,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC3D,KAAK,SAAS;YACZ,OAAO,qBAAqB,OAAO,CAAC,QAAQ,oBAAoB,OAAO,CAAC,OAAO,OAAO,OAAO,CAAC,MAAM,gBAAgB,OAAO,CAAC,MAAM,+BAA+B,CAAC;QACpK,KAAK,oBAAoB;YACvB,OAAO,gCAAgC,OAAO,CAAC,IAAI,mBAAmB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;QAC5F,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,UAAU,GAAU,OAAO,CAAC;YAClC,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;AACH,CAAC;AAED,2DAA2D;AAC3D,MAAM,OAAO,WAAY,SAAQ,KAAK;IACf;IAArB,YAAqB,OAAsB;QACzC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QADb,YAAO,GAAP,OAAO,CAAe;QAEzC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAoB,EAAE,MAAoB,EAAE,OAA2B;IACvG,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;IAC9E,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;IAC7G,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;IACvF,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACxH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,OAA2B;IAC3E,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI;YAAE,MAAM,KAAK,CAAC;QAClD,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAI,OAAmB,EAAE,MAAsC;IAChF,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC5D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,uEAAuE;QACvE,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CACV,CAAC,KAAK,EAAE,EAAE;YACR,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,MAAmB;IACtC,OAAO,MAAM,CAAC,MAAM,IAAI,IAAI,YAAY,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC;AACvF,CAAC"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/egress/check.ts"],"names":[],"mappings":"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"}
package/egress/fetch.d.ts CHANGED
@@ -20,6 +20,17 @@
20
20
  * one host never travels to another. A 303, or a 301/302 answering a
21
21
  * non-GET, becomes a GET without a body; 307 and 308 keep method and body.
22
22
  *
23
+ * Every response body is bounded (`maxResponseBytes`, a mebibyte by
24
+ * default). The URLs these callers dial are written by users, so a document
25
+ * that never ends is an attack on the process that reads it, and every
26
+ * caller today reads a small document: a JWKS, a discovery or metadata
27
+ * document, a token response. The bound applies to the body, not the dial:
28
+ * the response resolves as it came, and reading past the bound rejects with
29
+ * an `EgressError` whose refusal is `response-too-large`, so each caller's
30
+ * existing "could not read the document" arm answers it. A declared
31
+ * `Content-Length` over the bound rejects on the first read, before any byte
32
+ * is buffered. A caller that streams passes `Number.POSITIVE_INFINITY`.
33
+ *
23
34
  * `OutboundFetch` takes a string or a URL, never a `Request`: a Request
24
35
  * carries its own headers and body that a wrapper would have to merge, and
25
36
  * no caller here builds one. The global `fetch` is assignable to it, so a
@@ -36,9 +47,13 @@ export interface GuardedFetchOptions {
36
47
  readonly lookup: LookupFn;
37
48
  /** Hops followed before refusing; default 3. */
38
49
  readonly maxRedirects?: number;
50
+ /** Bytes of a response body read before refusing; default one mebibyte. */
51
+ readonly maxResponseBytes?: number;
39
52
  }
40
53
  /** The default hop budget: a scheme upgrade and a canonicalisation, with one to spare. */
41
54
  export declare const DEFAULT_MAX_REDIRECTS = 3;
55
+ /** The default body bound: a thousand times a large JWKS, far below what a pod can buffer. */
56
+ export declare const DEFAULT_MAX_RESPONSE_BYTES: number;
42
57
  /**
43
58
  * An `OutboundFetch` in the global `fetch`'s shape, for a seam typed
44
59
  * `typeof fetch`. A `Request` input is refused rather than flattened: this
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/egress/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAA4B,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAErE,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEzF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAIvC;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,KAAK,CAK7D;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa,CAyC9F"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/egress/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAA4B,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAErE,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEzF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,8FAA8F;AAC9F,eAAO,MAAM,0BAA0B,QAAc,CAAC;AAOtD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,KAAK,CAK7D;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa,CA0C9F"}
package/egress/fetch.js CHANGED
@@ -1,7 +1,11 @@
1
1
  import { checkEgress, EgressError } from "./check.js";
2
2
  /** The default hop budget: a scheme upgrade and a canonicalisation, with one to spare. */
3
3
  export const DEFAULT_MAX_REDIRECTS = 3;
4
+ /** The default body bound: a thousand times a large JWKS, far below what a pod can buffer. */
5
+ export const DEFAULT_MAX_RESPONSE_BYTES = 1024 * 1024;
4
6
  const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
7
+ /** Statuses whose responses carry no body, which `new Response` refuses to give one. */
8
+ const NULL_BODY_STATUSES = new Set([101, 204, 205, 304]);
5
9
  /**
6
10
  * An `OutboundFetch` in the global `fetch`'s shape, for a seam typed
7
11
  * `typeof fetch`. A `Request` input is refused rather than flattened: this
@@ -19,6 +23,7 @@ export function asFetch(outbound) {
19
23
  /** Compose a fetch that judges every URL and every hop under `policy`. */
20
24
  export function guardedFetch(policy, options) {
21
25
  const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
26
+ const maxResponseBytes = options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
22
27
  return async (input, init) => {
23
28
  let url = new URL(input);
24
29
  let method = (init?.method ?? "GET").toUpperCase();
@@ -32,7 +37,7 @@ export function guardedFetch(policy, options) {
32
37
  const response = await options.fetchImpl(url, { ...init, method, body, headers, redirect: "manual" });
33
38
  const location = response.headers.get("location");
34
39
  if (!REDIRECT_STATUSES.has(response.status) || location === null || callerRedirect === "manual") {
35
- return response;
40
+ return boundedResponse(response, url, maxResponseBytes);
36
41
  }
37
42
  if (callerRedirect === "error") {
38
43
  await response.body?.cancel();
@@ -56,4 +61,32 @@ export function guardedFetch(policy, options) {
56
61
  }
57
62
  };
58
63
  }
64
+ /**
65
+ * The response with its body bounded: the same status and headers over a
66
+ * body that errors once it passes `maxBytes`, or at once when the declared
67
+ * length already does.
68
+ */
69
+ function boundedResponse(response, url, maxBytes) {
70
+ if (response.body === null || NULL_BODY_STATUSES.has(response.status) || !Number.isFinite(maxBytes)) {
71
+ return response;
72
+ }
73
+ const tooLarge = () => new EgressError({ kind: "response-too-large", url, maxBytes });
74
+ const declared = Number(response.headers.get("content-length") ?? Number.NaN);
75
+ let read = 0;
76
+ const body = response.body.pipeThrough(new TransformStream({
77
+ start(controller) {
78
+ if (Number.isFinite(declared) && declared > maxBytes)
79
+ controller.error(tooLarge());
80
+ },
81
+ transform(chunk, controller) {
82
+ read += chunk.byteLength;
83
+ if (read > maxBytes) {
84
+ controller.error(tooLarge());
85
+ return;
86
+ }
87
+ controller.enqueue(chunk);
88
+ },
89
+ }));
90
+ return new Response(body, { status: response.status, statusText: response.statusText, headers: response.headers });
91
+ }
59
92
  //# sourceMappingURL=fetch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/egress/fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/egress/fetch.ts"],"names":[],"mappings":"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"}
package/egress/index.d.ts CHANGED
@@ -5,6 +5,6 @@
5
5
  */
6
6
  export { blockedReason, egressPolicyForPosture, type EgressPolicy, type EgressPosture } from "./address.js";
7
7
  export { checkEgress, describeRefusal, EgressError, type EgressCheck, type EgressCheckOptions, type EgressRefusal, type LookupFn, } from "./check.js";
8
- export { asFetch, DEFAULT_MAX_REDIRECTS, guardedFetch, type GuardedFetchOptions, type OutboundFetch } from "./fetch.js";
8
+ export { asFetch, DEFAULT_MAX_REDIRECTS, DEFAULT_MAX_RESPONSE_BYTES, guardedFetch, type GuardedFetchOptions, type OutboundFetch } from "./fetch.js";
9
9
  export { nodeLookup } from "./node-lookup.js";
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/egress/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,QAAQ,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACxH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/egress/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,QAAQ,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACpJ,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
package/egress/index.js CHANGED
@@ -5,6 +5,6 @@
5
5
  */
6
6
  export { blockedReason, egressPolicyForPosture } from "./address.js";
7
7
  export { checkEgress, describeRefusal, EgressError, } from "./check.js";
8
- export { asFetch, DEFAULT_MAX_REDIRECTS, guardedFetch } from "./fetch.js";
8
+ export { asFetch, DEFAULT_MAX_REDIRECTS, DEFAULT_MAX_RESPONSE_BYTES, guardedFetch } from "./fetch.js";
9
9
  export { nodeLookup } from "./node-lookup.js";
10
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/egress/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAyC,MAAM,cAAc,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,GAKZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAgD,MAAM,YAAY,CAAC;AACxH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/egress/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAyC,MAAM,cAAc,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,GAKZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,YAAY,EAAgD,MAAM,YAAY,CAAC;AACpJ,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"node-lookup.d.ts","sourceRoot":"","sources":["../../src/egress/node-lookup.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,+EAA+E;AAC/E,wBAAgB,UAAU,IAAI,QAAQ,CAKrC"}
1
+ {"version":3,"file":"node-lookup.d.ts","sourceRoot":"","sources":["../src/egress/node-lookup.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,+EAA+E;AAC/E,wBAAgB,UAAU,IAAI,QAAQ,CAKrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"node-lookup.js","sourceRoot":"","sources":["../../src/egress/node-lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3C,+EAA+E;AAC/E,MAAM,UAAU,UAAU;IACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"node-lookup.js","sourceRoot":"","sources":["../src/egress/node-lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3C,+EAA+E;AAC/E,MAAM,UAAU,UAAU;IACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC;AACJ,CAAC"}
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../src/mcp-oauth/challenge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAIjE;AAED,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGpF"}
1
+ {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../src/mcp-oauth/challenge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAIjE;AAED,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGpF"}
@@ -1 +1 @@
1
- {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../../src/mcp-oauth/challenge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,gEAAgE;AAChE,MAAM,UAAU,gBAAgB,CAAC,eAAuB;IACtD,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AACxE,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,wBAAwB,CAAC,eAAuB;IAC9D,MAAM,KAAK,GAAG,8BAA8B,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACnE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../src/mcp-oauth/challenge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,gEAAgE;AAChE,MAAM,UAAU,gBAAgB,CAAC,eAAuB;IACtD,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AACxE,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,wBAAwB,CAAC,eAAuB;IAC9D,MAAM,KAAK,GAAG,8BAA8B,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACnE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp-oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,+BAA+B,EAC/B,2BAA2B,EAC3B,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACjG,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/mcp-oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,+BAA+B,EAC/B,2BAA2B,EAC3B,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACjG,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp-oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,+BAA+B,EAC/B,2BAA2B,GAK5B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAoD,MAAM,YAAY,CAAC;AACjG,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,GAEjB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/mcp-oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,+BAA+B,EAC/B,2BAA2B,GAK5B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAoD,MAAM,YAAY,CAAC;AACjG,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,GAEjB,MAAM,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/mcp-oauth/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,6FAA6F;AAC7F,MAAM,WAAW,2BAA2B;IAC1C,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,6BAA6B,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3D;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qGAAqG;IACrG,QAAQ,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,gBAAgB,CAAC;CAChE;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,GACzH;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC;AAElF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,mBAAmB;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,yEAAyE;AACzE,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,GAAG,GAAG,SAAS,MAAM,EAAE,CAI9E;AAED,iHAAiH;AACjH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,MAAM,EAAE,CAS9E;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC,CAUjG;AAED,wFAAwF;AACxF,wBAAsB,+BAA+B,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCnH"}
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/mcp-oauth/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,6FAA6F;AAC7F,MAAM,WAAW,2BAA2B;IAC1C,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,6BAA6B,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3D;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qGAAqG;IACrG,QAAQ,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,gBAAgB,CAAC;CAChE;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,GACzH;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC;AAElF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,mBAAmB;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,yEAAyE;AACzE,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,GAAG,GAAG,SAAS,MAAM,EAAE,CAI9E;AAED,iHAAiH;AACjH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,MAAM,EAAE,CAS9E;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC,CAUjG;AAED,wFAAwF;AACxF,wBAAsB,+BAA+B,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCnH"}
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/mcp-oauth/metadata.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/mcp-oauth/metadata.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/mcp-oauth/probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,MAAM,mBAAmB;AAC7B,oHAAoH;AAClH;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE;AAC1G,6GAA6G;GAC3G;IAAE,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AACtE,qEAAqE;GACnE;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACxD,6BAA6B;GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAC1D,kFAAkF;GAChF;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,mEAAmE;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,iFAAiF;AACjF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,EACrD,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CA2B9B"}
1
+ {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../src/mcp-oauth/probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,MAAM,mBAAmB;AAC7B,oHAAoH;AAClH;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE;AAC1G,6GAA6G;GAC3G;IAAE,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AACtE,qEAAqE;GACnE;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACxD,6BAA6B;GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAC1D,kFAAkF;GAChF;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,mEAAmE;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,iFAAiF;AACjF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,EACrD,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CA2B9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/mcp-oauth/probe.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAsBjD,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAW,EACX,OAAqD,EACrD,IAAuB;IAEvB,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC5D,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE;YACnC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE;YAC/B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;SAC5C,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9D,CAAC;IAED,yEAAyE;IACzE,sDAAsD;IACtD,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;QACjE,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,SAAS,EAAE,CAAC;QACpF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,wBAAwB,CAAC,SAAS,CAAC,EAAE,CAAC;IAChG,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACvD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACpF,CAAC"}
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/mcp-oauth/probe.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAsBjD,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAW,EACX,OAAqD,EACrD,IAAuB;IAEvB,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC5D,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE;YACnC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE;YAC/B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;SAC5C,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9D,CAAC;IAED,yEAAyE;IACzE,sDAAsD;IACtD,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;QACjE,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,SAAS,EAAE,CAAC;QACpF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,wBAAwB,CAAC,SAAS,CAAC,EAAE,CAAC;IAChG,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACvD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACpF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/mcp-oauth/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,kBAAkB,CAepH;AAED,kGAAkG;AAClG,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAQnH"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/mcp-oauth/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,kBAAkB,CAepH;AAED,kGAAkG;AAClG,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAQnH"}
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/mcp-oauth/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AASjD,kFAAkF;AAClF,SAAS,WAAW,CAAC,OAAqD;IACxE,OAAO;QACL,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,qCAAqC;QAC7C,sBAAsB,EAAE,oBAAoB;QAC5C,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;KACnB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,OAA0C;IAC9F,OAAO;QACL,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;QAC7B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,CAAC;YACL,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE;gBACN,eAAe,EAAE,oBAAoB;gBACrC,YAAY,EAAE,EAAE;gBAChB,UAAU,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE;aAC/C;SACF,CAAC;KACH,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA0C,EAAE,SAAkB;IAC7F,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,SAAS,KAAK,SAAS;QAAE,MAAM,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC;IACpE,OAAO;QACL,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;KAClF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../src/mcp-oauth/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AASjD,kFAAkF;AAClF,SAAS,WAAW,CAAC,OAAqD;IACxE,OAAO;QACL,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,qCAAqC;QAC7C,sBAAsB,EAAE,oBAAoB;QAC5C,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;KACnB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,OAA0C;IAC9F,OAAO;QACL,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;QAC7B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,CAAC;YACL,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE;gBACN,eAAe,EAAE,oBAAoB;gBACrC,YAAY,EAAE,EAAE;gBAChB,UAAU,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE;aAC/C;SACF,CAAC;KACH,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA0C,EAAE,SAAkB;IAC7F,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,SAAS,KAAK,SAAS;QAAE,MAAM,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC;IACpE,OAAO;QACL,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;KAClF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/outbound",
3
- "version": "3.34.0",
3
+ "version": "3.36.0",
4
4
  "description": "The rules Stigmer's TypeScript processes dial a user-supplied endpoint by, shared by the control plane, the runner and the catalogue audit: the egress address policy and its guarded fetch, and the way an MCP endpoint's authentication is read (the OAuth-challenge rule, the complete initialize handshake, the RFC 9728 / RFC 8414 / OpenID resolution of its login server)",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -45,7 +45,8 @@ export type EgressRefusal =
45
45
  readonly reason: string;
46
46
  readonly policy: string;
47
47
  }
48
- | { readonly kind: "too-many-redirects"; readonly url: URL; readonly hops: number };
48
+ | { readonly kind: "too-many-redirects"; readonly url: URL; readonly hops: number }
49
+ | { readonly kind: "response-too-large"; readonly url: URL; readonly maxBytes: number };
49
50
 
50
51
  export type EgressCheck =
51
52
  | { readonly ok: true; readonly url: URL; readonly addresses: readonly string[] }
@@ -70,6 +71,8 @@ export function describeRefusal(refusal: EgressRefusal): string {
70
71
  return `Refusing to reach ${refusal.hostname}: it resolves to ${refusal.address}, a ${refusal.reason} address the ${refusal.policy} egress policy does not dial.`;
71
72
  case "too-many-redirects":
72
73
  return `Refusing to follow more than ${refusal.hops} redirects from ${refusal.url.href}.`;
74
+ case "response-too-large":
75
+ return `Refusing to read more than ${refusal.maxBytes} bytes from ${refusal.url.href}.`;
73
76
  default: {
74
77
  const exhaustive: never = refusal;
75
78
  return exhaustive;
@@ -20,6 +20,17 @@
20
20
  * one host never travels to another. A 303, or a 301/302 answering a
21
21
  * non-GET, becomes a GET without a body; 307 and 308 keep method and body.
22
22
  *
23
+ * Every response body is bounded (`maxResponseBytes`, a mebibyte by
24
+ * default). The URLs these callers dial are written by users, so a document
25
+ * that never ends is an attack on the process that reads it, and every
26
+ * caller today reads a small document: a JWKS, a discovery or metadata
27
+ * document, a token response. The bound applies to the body, not the dial:
28
+ * the response resolves as it came, and reading past the bound rejects with
29
+ * an `EgressError` whose refusal is `response-too-large`, so each caller's
30
+ * existing "could not read the document" arm answers it. A declared
31
+ * `Content-Length` over the bound rejects on the first read, before any byte
32
+ * is buffered. A caller that streams passes `Number.POSITIVE_INFINITY`.
33
+ *
23
34
  * `OutboundFetch` takes a string or a URL, never a `Request`: a Request
24
35
  * carries its own headers and body that a wrapper would have to merge, and
25
36
  * no caller here builds one. The global `fetch` is assignable to it, so a
@@ -38,13 +49,21 @@ export interface GuardedFetchOptions {
38
49
  readonly lookup: LookupFn;
39
50
  /** Hops followed before refusing; default 3. */
40
51
  readonly maxRedirects?: number;
52
+ /** Bytes of a response body read before refusing; default one mebibyte. */
53
+ readonly maxResponseBytes?: number;
41
54
  }
42
55
 
43
56
  /** The default hop budget: a scheme upgrade and a canonicalisation, with one to spare. */
44
57
  export const DEFAULT_MAX_REDIRECTS = 3;
45
58
 
59
+ /** The default body bound: a thousand times a large JWKS, far below what a pod can buffer. */
60
+ export const DEFAULT_MAX_RESPONSE_BYTES = 1024 * 1024;
61
+
46
62
  const REDIRECT_STATUSES: ReadonlySet<number> = new Set([301, 302, 303, 307, 308]);
47
63
 
64
+ /** Statuses whose responses carry no body, which `new Response` refuses to give one. */
65
+ const NULL_BODY_STATUSES: ReadonlySet<number> = new Set([101, 204, 205, 304]);
66
+
48
67
  /**
49
68
  * An `OutboundFetch` in the global `fetch`'s shape, for a seam typed
50
69
  * `typeof fetch`. A `Request` input is refused rather than flattened: this
@@ -62,6 +81,7 @@ export function asFetch(outbound: OutboundFetch): typeof fetch {
62
81
  /** Compose a fetch that judges every URL and every hop under `policy`. */
63
82
  export function guardedFetch(policy: EgressPolicy, options: GuardedFetchOptions): OutboundFetch {
64
83
  const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
84
+ const maxResponseBytes = options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
65
85
 
66
86
  return async (input, init) => {
67
87
  let url = new URL(input);
@@ -78,7 +98,7 @@ export function guardedFetch(policy: EgressPolicy, options: GuardedFetchOptions)
78
98
 
79
99
  const location = response.headers.get("location");
80
100
  if (!REDIRECT_STATUSES.has(response.status) || location === null || callerRedirect === "manual") {
81
- return response;
101
+ return boundedResponse(response, url, maxResponseBytes);
82
102
  }
83
103
  if (callerRedirect === "error") {
84
104
  await response.body?.cancel();
@@ -102,3 +122,33 @@ export function guardedFetch(policy: EgressPolicy, options: GuardedFetchOptions)
102
122
  }
103
123
  };
104
124
  }
125
+
126
+ /**
127
+ * The response with its body bounded: the same status and headers over a
128
+ * body that errors once it passes `maxBytes`, or at once when the declared
129
+ * length already does.
130
+ */
131
+ function boundedResponse(response: Response, url: URL, maxBytes: number): Response {
132
+ if (response.body === null || NULL_BODY_STATUSES.has(response.status) || !Number.isFinite(maxBytes)) {
133
+ return response;
134
+ }
135
+ const tooLarge = (): EgressError => new EgressError({ kind: "response-too-large", url, maxBytes });
136
+ const declared = Number(response.headers.get("content-length") ?? Number.NaN);
137
+ let read = 0;
138
+ const body = response.body.pipeThrough(
139
+ new TransformStream<Uint8Array, Uint8Array>({
140
+ start(controller) {
141
+ if (Number.isFinite(declared) && declared > maxBytes) controller.error(tooLarge());
142
+ },
143
+ transform(chunk, controller) {
144
+ read += chunk.byteLength;
145
+ if (read > maxBytes) {
146
+ controller.error(tooLarge());
147
+ return;
148
+ }
149
+ controller.enqueue(chunk);
150
+ },
151
+ }),
152
+ );
153
+ return new Response(body, { status: response.status, statusText: response.statusText, headers: response.headers });
154
+ }
@@ -13,5 +13,5 @@ export {
13
13
  type EgressRefusal,
14
14
  type LookupFn,
15
15
  } from "./check.js";
16
- export { asFetch, DEFAULT_MAX_REDIRECTS, guardedFetch, type GuardedFetchOptions, type OutboundFetch } from "./fetch.js";
16
+ export { asFetch, DEFAULT_MAX_REDIRECTS, DEFAULT_MAX_RESPONSE_BYTES, guardedFetch, type GuardedFetchOptions, type OutboundFetch } from "./fetch.js";
17
17
  export { nodeLookup } from "./node-lookup.js";
@@ -1,88 +0,0 @@
1
- /**
2
- * Pins the address classification under both postures: the runner's cases,
3
- * moved here byte for byte when the rule became shared, plus the policy
4
- * shape a consumer composes.
5
- */
6
- import { describe, expect, it } from "vitest";
7
-
8
- import { blockedReason, egressPolicyForPosture } from "../egress/address.js";
9
-
10
- describe("blockedReason, strict posture", () => {
11
- it.each([
12
- ["127.0.0.1", "loopback"],
13
- ["127.255.255.255", "loopback"],
14
- ["0.0.0.0", "unspecified"],
15
- ["10.0.0.1", "private (RFC 1918)"],
16
- ["172.16.0.1", "private (RFC 1918)"],
17
- ["172.31.255.255", "private (RFC 1918)"],
18
- ["192.168.1.1", "private (RFC 1918)"],
19
- ["169.254.169.254", "link-local (cloud metadata)"],
20
- ["169.254.0.1", "link-local (cloud metadata)"],
21
- ])("blocks %s as %s", (address, reason) => {
22
- expect(blockedReason(address, "strict")).toBe(reason);
23
- });
24
-
25
- it.each(["8.8.8.8", "104.16.0.1", "172.15.0.1", "172.32.0.1", "192.169.0.1"])("allows public IPv4 %s", (address) => {
26
- expect(blockedReason(address, "strict")).toBeNull();
27
- });
28
-
29
- it.each([
30
- ["::1", "loopback"],
31
- ["::", "unspecified"],
32
- ["fc00::1", "private (unique local)"],
33
- ["fd12:3456::1", "private (unique local)"],
34
- ["fe80::1", "link-local (cloud metadata)"],
35
- ["febf::1", "link-local (cloud metadata)"],
36
- ])("blocks IPv6 %s as %s", (address, reason) => {
37
- expect(blockedReason(address, "strict")).toBe(reason);
38
- });
39
-
40
- it("allows public IPv6", () => {
41
- expect(blockedReason("2606:4700::6810:1", "strict")).toBeNull();
42
- });
43
-
44
- it("blocks IPv4-mapped IPv6 carrying a blocked v4 (dotted form)", () => {
45
- expect(blockedReason("::ffff:127.0.0.1", "strict")).toBe("loopback");
46
- expect(blockedReason("::ffff:10.0.0.1", "strict")).toBe("private (RFC 1918)");
47
- });
48
-
49
- it("blocks IPv4-mapped IPv6 carrying a blocked v4 (hex form)", () => {
50
- expect(blockedReason("::ffff:7f00:1", "strict")).toBe("loopback");
51
- expect(blockedReason("::ffff:a9fe:a9fe", "strict")).toBe("link-local (cloud metadata)");
52
- });
53
-
54
- it("allows IPv4-mapped IPv6 carrying a public v4", () => {
55
- expect(blockedReason("::ffff:8.8.8.8", "strict")).toBeNull();
56
- });
57
-
58
- it("ignores a zone suffix when classifying", () => {
59
- expect(blockedReason("fe80::1%eth0", "strict")).toBe("link-local (cloud metadata)");
60
- });
61
-
62
- it("fails closed on garbage", () => {
63
- expect(blockedReason("not-an-ip", "strict")).toBe("unrecognized");
64
- });
65
- });
66
-
67
- describe("blockedReason, relaxed posture", () => {
68
- it.each(["127.0.0.1", "10.0.0.1", "192.168.1.1", "::1", "fd00::1"])("allows private/loopback %s (the machine belongs to the user)", (address) => {
69
- expect(blockedReason(address, "relaxed")).toBeNull();
70
- });
71
-
72
- it("still blocks the cloud metadata range", () => {
73
- expect(blockedReason("169.254.169.254", "relaxed")).toBe("link-local (cloud metadata)");
74
- expect(blockedReason("fe80::1", "relaxed")).toBe("link-local (cloud metadata)");
75
- expect(blockedReason("::ffff:169.254.169.254", "relaxed")).toBe("link-local (cloud metadata)");
76
- });
77
- });
78
-
79
- describe("egressPolicyForPosture", () => {
80
- it("names the posture and applies its classification", () => {
81
- const strict = egressPolicyForPosture("strict");
82
- const relaxed = egressPolicyForPosture("relaxed");
83
- expect(strict.name).toBe("strict");
84
- expect(relaxed.name).toBe("relaxed");
85
- expect(strict.blockedReason("10.0.0.1")).toBe("private (RFC 1918)");
86
- expect(relaxed.blockedReason("10.0.0.1")).toBeNull();
87
- });
88
- });
@@ -1,41 +0,0 @@
1
- /**
2
- * Pins the OAuth-challenge rule: the runner's cases, moved here when the
3
- * rule became shared, and the `resource_metadata` pointer read.
4
- */
5
- import { describe, expect, it } from "vitest";
6
-
7
- import { isOAuthChallenge, parseResourceMetadataUrl } from "../mcp-oauth/challenge.js";
8
-
9
- describe("isOAuthChallenge", () => {
10
- it("matches the MCP auth spec Bearer + OAuth realm challenge", () => {
11
- expect(isOAuthChallenge('Bearer realm="OAuth", resource_metadata="https://mcp.vendor.test/.well-known/oauth-protected-resource"')).toBe(true);
12
- });
13
-
14
- it("matches a Bearer challenge that only advertises resource_metadata", () => {
15
- expect(isOAuthChallenge('Bearer resource_metadata="https://mcp.vendor.test/.well-known/oauth-protected-resource"')).toBe(true);
16
- });
17
-
18
- it("does not match a plain Bearer 401 (an invalid API key, not an OAuth requirement)", () => {
19
- expect(isOAuthChallenge('Bearer error="invalid_token"')).toBe(false);
20
- });
21
-
22
- it("does not match a non-Bearer scheme", () => {
23
- expect(isOAuthChallenge('Basic realm="OAuth"')).toBe(false);
24
- });
25
-
26
- it("is empty-safe", () => {
27
- expect(isOAuthChallenge("")).toBe(false);
28
- });
29
- });
30
-
31
- describe("parseResourceMetadataUrl", () => {
32
- it("extracts the resource_metadata URL", () => {
33
- expect(parseResourceMetadataUrl('Bearer realm="OAuth", resource_metadata="https://mcp.vendor.test/.well-known/oauth-protected-resource"')).toBe(
34
- "https://mcp.vendor.test/.well-known/oauth-protected-resource",
35
- );
36
- });
37
-
38
- it("returns undefined when absent", () => {
39
- expect(parseResourceMetadataUrl('Bearer realm="OAuth"')).toBeUndefined();
40
- });
41
- });
@@ -1,98 +0,0 @@
1
- /**
2
- * Pins the egress check: scheme first, then every resolved address, literal
3
- * hosts without a lookup, an unresolvable name refused, and the caller's
4
- * signal bounding a resolver that never answers.
5
- */
6
- import { describe, expect, it } from "vitest";
7
-
8
- import { egressPolicyForPosture } from "../egress/address.js";
9
- import { checkEgress, describeRefusal, EgressError, type LookupFn } from "../egress/check.js";
10
-
11
- const strict = egressPolicyForPosture("strict");
12
- const relaxed = egressPolicyForPosture("relaxed");
13
-
14
- function table(entries: Record<string, readonly string[]>): LookupFn {
15
- return async (hostname) => {
16
- const found = entries[hostname];
17
- if (found === undefined) throw new Error(`ENOTFOUND ${hostname}`);
18
- return found;
19
- };
20
- }
21
-
22
- describe("checkEgress", () => {
23
- it("refuses a malformed URL before resolving anything", async () => {
24
- const result = await checkEgress("not a url", strict, { lookup: table({}) });
25
- expect(result).toEqual({ ok: false, refusal: { kind: "invalid-url", url: "not a url" } });
26
- });
27
-
28
- it.each(["file:///etc/passwd", "ftp://vendor.test/x", "gopher://vendor.test"])("refuses the scheme of %s", async (url) => {
29
- const result = await checkEgress(url, strict, { lookup: table({}) });
30
- expect(result.ok).toBe(false);
31
- if (!result.ok) expect(result.refusal.kind).toBe("unsupported-scheme");
32
- });
33
-
34
- it("judges a literal IP host without a lookup", async () => {
35
- let lookups = 0;
36
- const lookup: LookupFn = async () => {
37
- lookups += 1;
38
- return [];
39
- };
40
- const refused = await checkEgress("http://127.0.0.1:8080/x", strict, { lookup });
41
- expect(refused.ok).toBe(false);
42
- if (!refused.ok) expect(refused.refusal).toMatchObject({ kind: "blocked", address: "127.0.0.1", reason: "loopback", policy: "strict" });
43
- const allowed = await checkEgress("http://127.0.0.1:3000/mcp", relaxed, { lookup });
44
- expect(allowed).toMatchObject({ ok: true, addresses: ["127.0.0.1"] });
45
- const bracketed = await checkEgress("http://[::1]/", strict, { lookup });
46
- expect(bracketed.ok).toBe(false);
47
- expect(lookups).toBe(0);
48
- });
49
-
50
- it("refuses a name when ANY of its addresses is blocked", async () => {
51
- const lookup = table({ "split.vendor.test": ["104.16.0.1", "10.0.0.7"] });
52
- const result = await checkEgress("https://split.vendor.test/mcp", strict, { lookup });
53
- expect(result.ok).toBe(false);
54
- if (!result.ok) expect(result.refusal).toMatchObject({ kind: "blocked", hostname: "split.vendor.test", address: "10.0.0.7" });
55
- });
56
-
57
- it("allows a name whose every address the policy allows, and reports them", async () => {
58
- const lookup = table({ "mcp.vendor.test": ["104.16.0.1", "2606:4700::6810:1"] });
59
- const result = await checkEgress("https://mcp.vendor.test/mcp", strict, { lookup });
60
- expect(result).toMatchObject({ ok: true, addresses: ["104.16.0.1", "2606:4700::6810:1"] });
61
- });
62
-
63
- it("refuses an unresolvable name", async () => {
64
- const result = await checkEgress("https://nowhere.vendor.test/", strict, { lookup: table({}) });
65
- expect(result).toMatchObject({ ok: false, refusal: { kind: "unresolvable", hostname: "nowhere.vendor.test" } });
66
- });
67
-
68
- it("refuses a name that resolves to nothing", async () => {
69
- const result = await checkEgress("https://empty.vendor.test/", strict, { lookup: table({ "empty.vendor.test": [] }) });
70
- expect(result).toMatchObject({ ok: false, refusal: { kind: "unresolvable" } });
71
- });
72
-
73
- it("gives up on a resolver that never answers when the signal aborts", async () => {
74
- const hanging: LookupFn = () => new Promise(() => undefined);
75
- const controller = new AbortController();
76
- const pending = checkEgress("https://slow.vendor.test/", strict, { lookup: hanging, signal: controller.signal });
77
- controller.abort(new Error("deadline"));
78
- await expect(pending).rejects.toThrow("deadline");
79
- });
80
-
81
- it("rejects at once on an already-aborted signal", async () => {
82
- const controller = new AbortController();
83
- controller.abort(new Error("gone"));
84
- await expect(checkEgress("https://slow.vendor.test/", strict, { lookup: table({}), signal: controller.signal })).rejects.toThrow("gone");
85
- });
86
- });
87
-
88
- describe("describeRefusal and EgressError", () => {
89
- it("renders one sentence per refusal and the error carries the refusal", () => {
90
- const url = new URL("https://split.vendor.test/mcp");
91
- const error = new EgressError({ kind: "blocked", url, hostname: url.hostname, address: "10.0.0.7", reason: "private (RFC 1918)", policy: "strict" });
92
- expect(error.name).toBe("EgressError");
93
- expect(error.message).toBe("Refusing to reach split.vendor.test: it resolves to 10.0.0.7, a private (RFC 1918) address the strict egress policy does not dial.");
94
- expect(error.refusal.kind).toBe("blocked");
95
- expect(describeRefusal({ kind: "unsupported-scheme", url: new URL("ftp://x.test/"), scheme: "ftp" })).toBe('Unsupported URL scheme "ftp": only http and https are allowed.');
96
- expect(describeRefusal({ kind: "too-many-redirects", url, hops: 3 })).toBe("Refusing to follow more than 3 redirects from https://split.vendor.test/mcp.");
97
- });
98
- });
@@ -1,161 +0,0 @@
1
- /**
2
- * Pins the guarded fetch: the first URL and every hop judged, a caller's
3
- * `redirect: "manual"` honoured, `redirect: "error"` thrown like fetch, the
4
- * hop budget, the Authorization header dropped across origins, and the
5
- * method rewrite a 303 (or a 301/302 on a POST) implies.
6
- */
7
- import { describe, expect, it } from "vitest";
8
-
9
- import { egressPolicyForPosture } from "../egress/address.js";
10
- import { EgressError, type LookupFn } from "../egress/check.js";
11
- import { asFetch, guardedFetch, type OutboundFetch } from "../egress/fetch.js";
12
-
13
- const strict = egressPolicyForPosture("strict");
14
-
15
- const lookup: LookupFn = async (hostname) => {
16
- const table: Record<string, readonly string[]> = {
17
- "a.vendor.test": ["104.16.0.1"],
18
- "b.vendor.test": ["104.16.0.2"],
19
- "internal.vendor.test": ["10.0.0.5"],
20
- };
21
- const found = table[hostname];
22
- if (found === undefined) throw new Error(`ENOTFOUND ${hostname}`);
23
- return found;
24
- };
25
-
26
- interface Seen {
27
- readonly url: string;
28
- readonly method: string;
29
- readonly headers: Headers;
30
- readonly body: RequestInit["body"];
31
- readonly redirect: RequestInit["redirect"];
32
- }
33
-
34
- function scripted(answers: Record<string, () => Response>): { fetchImpl: OutboundFetch; seen: Seen[] } {
35
- const seen: Seen[] = [];
36
- const fetchImpl: OutboundFetch = async (url, init) => {
37
- const key = String(url);
38
- seen.push({ url: key, method: init?.method ?? "GET", headers: new Headers(init?.headers), body: init?.body, redirect: init?.redirect });
39
- const answer = answers[key];
40
- if (answer === undefined) throw new Error(`unscripted ${key}`);
41
- return answer();
42
- };
43
- return { fetchImpl, seen };
44
- }
45
-
46
- const redirect = (status: number, location: string): Response => new Response(null, { status, headers: { location } });
47
- const ok = (): Response => new Response("ok", { status: 200 });
48
-
49
- describe("guardedFetch", () => {
50
- it("judges the URL before dialling and refuses a blocked one without calling fetch", async () => {
51
- const { fetchImpl, seen } = scripted({});
52
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
53
- await expect(fetchGuarded("https://internal.vendor.test/mcp")).rejects.toBeInstanceOf(EgressError);
54
- expect(seen).toHaveLength(0);
55
- });
56
-
57
- it("dials an allowed URL with the caller's init and asks the underlying fetch for manual redirects", async () => {
58
- const { fetchImpl, seen } = scripted({ "https://a.vendor.test/mcp": ok });
59
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
60
- const response = await fetchGuarded("https://a.vendor.test/mcp", { method: "POST", body: "{}", headers: { Accept: "application/json" } });
61
- expect(response.status).toBe(200);
62
- expect(seen).toHaveLength(1);
63
- expect(seen[0]).toMatchObject({ method: "POST", body: "{}", redirect: "manual" });
64
- expect(seen[0]?.headers.get("accept")).toBe("application/json");
65
- });
66
-
67
- it("follows a redirect and judges the hop, refusing one that lands on a blocked address", async () => {
68
- const { fetchImpl, seen } = scripted({
69
- "https://a.vendor.test/mcp": () => redirect(302, "https://internal.vendor.test/mcp"),
70
- });
71
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
72
- await expect(fetchGuarded("https://a.vendor.test/mcp")).rejects.toMatchObject({ refusal: { kind: "blocked", hostname: "internal.vendor.test" } });
73
- expect(seen.map((s) => s.url)).toEqual(["https://a.vendor.test/mcp"]);
74
- });
75
-
76
- it("follows an allowed hop and resolves a relative Location against the current URL", async () => {
77
- const { fetchImpl, seen } = scripted({
78
- "https://a.vendor.test/mcp": () => redirect(301, "/mcp/"),
79
- "https://a.vendor.test/mcp/": ok,
80
- });
81
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
82
- const response = await fetchGuarded("https://a.vendor.test/mcp");
83
- expect(response.status).toBe(200);
84
- expect(seen.map((s) => s.url)).toEqual(["https://a.vendor.test/mcp", "https://a.vendor.test/mcp/"]);
85
- });
86
-
87
- it("returns the 3xx untouched when the caller asked for manual redirects", async () => {
88
- const { fetchImpl, seen } = scripted({ "https://a.vendor.test/authorize": () => redirect(302, "https://b.vendor.test/login") });
89
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
90
- const response = await fetchGuarded("https://a.vendor.test/authorize", { redirect: "manual" });
91
- expect(response.status).toBe(302);
92
- expect(seen).toHaveLength(1);
93
- });
94
-
95
- it("throws a TypeError on a redirect when the caller asked for redirect: error", async () => {
96
- const { fetchImpl } = scripted({ "https://a.vendor.test/x": () => redirect(302, "https://b.vendor.test/y") });
97
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
98
- await expect(fetchGuarded("https://a.vendor.test/x", { redirect: "error" })).rejects.toBeInstanceOf(TypeError);
99
- });
100
-
101
- it("refuses past the hop budget", async () => {
102
- const { fetchImpl, seen } = scripted({
103
- "https://a.vendor.test/1": () => redirect(302, "https://a.vendor.test/2"),
104
- "https://a.vendor.test/2": () => redirect(302, "https://a.vendor.test/3"),
105
- "https://a.vendor.test/3": () => redirect(302, "https://a.vendor.test/4"),
106
- "https://a.vendor.test/4": () => redirect(302, "https://a.vendor.test/5"),
107
- });
108
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
109
- await expect(fetchGuarded("https://a.vendor.test/1")).rejects.toMatchObject({ refusal: { kind: "too-many-redirects", hops: 3 } });
110
- expect(seen).toHaveLength(4);
111
- });
112
-
113
- it("drops the Authorization header on a cross-origin hop and keeps it on a same-origin one", async () => {
114
- const { fetchImpl, seen } = scripted({
115
- "https://a.vendor.test/x": () => redirect(307, "https://a.vendor.test/y"),
116
- "https://a.vendor.test/y": () => redirect(307, "https://b.vendor.test/z"),
117
- "https://b.vendor.test/z": ok,
118
- });
119
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
120
- await fetchGuarded("https://a.vendor.test/x", { method: "POST", body: "{}", headers: { Authorization: "Bearer t" } });
121
- expect(seen[0]?.headers.get("authorization")).toBe("Bearer t");
122
- expect(seen[1]?.headers.get("authorization")).toBe("Bearer t");
123
- expect(seen[2]?.headers.get("authorization")).toBeNull();
124
- // 307 keeps the method and the body.
125
- expect(seen[2]).toMatchObject({ method: "POST", body: "{}" });
126
- });
127
-
128
- it("turns a 303, or a 301/302 answering a POST, into a GET without a body", async () => {
129
- const { fetchImpl, seen } = scripted({
130
- "https://a.vendor.test/post": () => redirect(303, "https://a.vendor.test/result"),
131
- "https://a.vendor.test/result": ok,
132
- "https://a.vendor.test/post2": () => redirect(302, "https://a.vendor.test/result2"),
133
- "https://a.vendor.test/result2": ok,
134
- });
135
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup });
136
- await fetchGuarded("https://a.vendor.test/post", { method: "POST", body: "{}", headers: { "Content-Type": "application/json" } });
137
- expect(seen[1]).toMatchObject({ method: "GET", body: undefined });
138
- expect(seen[1]?.headers.get("content-type")).toBeNull();
139
- await fetchGuarded("https://a.vendor.test/post2", { method: "POST", body: "{}" });
140
- expect(seen[3]).toMatchObject({ method: "GET", body: undefined });
141
- });
142
-
143
- it("asFetch wears the global fetch's shape and refuses a Request input rather than flattening it", async () => {
144
- const { fetchImpl, seen } = scripted({ "https://a.vendor.test/mcp": ok });
145
- const wrapped = asFetch(guardedFetch(strict, { fetchImpl, lookup }));
146
- await expect(wrapped("https://a.vendor.test/mcp")).resolves.toHaveProperty("status", 200);
147
- await expect(wrapped(new URL("https://a.vendor.test/mcp"))).resolves.toHaveProperty("status", 200);
148
- await expect(wrapped(new Request("https://a.vendor.test/mcp"))).rejects.toBeInstanceOf(TypeError);
149
- expect(seen).toHaveLength(2);
150
- });
151
-
152
- it("passes the caller's signal through to the check and to every hop", async () => {
153
- const controller = new AbortController();
154
- const { fetchImpl } = scripted({});
155
- const hanging: LookupFn = () => new Promise(() => undefined);
156
- const fetchGuarded = guardedFetch(strict, { fetchImpl, lookup: hanging });
157
- const pending = fetchGuarded("https://a.vendor.test/mcp", { signal: controller.signal });
158
- controller.abort(new Error("deadline"));
159
- await expect(pending).rejects.toThrow("deadline");
160
- });
161
- });
@@ -1,171 +0,0 @@
1
- /**
2
- * Pins the login-server walk: the RFC 9728 documents tried most specific
3
- * first, the RFC 8414 well-known segment inserted BEFORE an issuer's path,
4
- * OpenID's document as the fallback, the challenge's pointer preferred, and
5
- * every attempt recorded so a caller can name the document it failed on.
6
- */
7
- import { describe, expect, it } from "vitest";
8
-
9
- import type { OutboundFetch } from "../egress/fetch.js";
10
- import {
11
- authorizationServerMetadataUrls,
12
- protectedResourceMetadataUrls,
13
- readAuthorizationServerMetadata,
14
- resolveAuthorizationServers,
15
- } from "../mcp-oauth/metadata.js";
16
-
17
- const deps = { timeoutMs: 1_000 };
18
-
19
- function serving(documents: Record<string, unknown | { status: number; body?: unknown }>): { fetchImpl: OutboundFetch; requested: string[] } {
20
- const requested: string[] = [];
21
- const fetchImpl: OutboundFetch = async (url) => {
22
- const key = String(url);
23
- requested.push(key);
24
- const entry = documents[key];
25
- if (entry === undefined) return new Response(JSON.stringify({ error: "not found" }), { status: 404 });
26
- if (typeof entry === "object" && entry !== null && "status" in entry && typeof (entry as { status: unknown }).status === "number") {
27
- const { status, body } = entry as { status: number; body?: unknown };
28
- return new Response(body === undefined ? null : JSON.stringify(body), { status });
29
- }
30
- return new Response(JSON.stringify(entry), { status: 200, headers: { "content-type": "application/json" } });
31
- };
32
- return { fetchImpl, requested };
33
- }
34
-
35
- const ISSUER_DOCUMENT = {
36
- issuer: "https://login.vendor.test",
37
- authorization_endpoint: "https://login.vendor.test/authorize",
38
- token_endpoint: "https://login.vendor.test/token",
39
- registration_endpoint: "https://login.vendor.test/register",
40
- scopes_supported: ["read"],
41
- code_challenge_methods_supported: ["S256"],
42
- };
43
-
44
- describe("protectedResourceMetadataUrls", () => {
45
- it("tries the path-suffixed document first, then the bare one", () => {
46
- expect(protectedResourceMetadataUrls(new URL("https://mcp.vendor.test/mcp/"))).toEqual([
47
- "https://mcp.vendor.test/.well-known/oauth-protected-resource/mcp",
48
- "https://mcp.vendor.test/.well-known/oauth-protected-resource",
49
- ]);
50
- });
51
-
52
- it("tries only the bare document for a root resource", () => {
53
- expect(protectedResourceMetadataUrls(new URL("https://mcp.vendor.test/"))).toEqual(["https://mcp.vendor.test/.well-known/oauth-protected-resource"]);
54
- });
55
- });
56
-
57
- describe("authorizationServerMetadataUrls", () => {
58
- it("inserts the well-known segment before an issuer's path (RFC 8414 section 3), then falls back", () => {
59
- expect(authorizationServerMetadataUrls(new URL("https://login.vendor.test/tenant"))).toEqual([
60
- "https://login.vendor.test/.well-known/oauth-authorization-server/tenant",
61
- "https://login.vendor.test/.well-known/oauth-authorization-server",
62
- "https://login.vendor.test/tenant/.well-known/openid-configuration",
63
- "https://login.vendor.test/.well-known/openid-configuration",
64
- ]);
65
- });
66
-
67
- it("for a bare issuer tries RFC 8414 at the origin first, the document the reader before this one read", () => {
68
- expect(authorizationServerMetadataUrls(new URL("https://mcp.vendor.test"))).toEqual([
69
- "https://mcp.vendor.test/.well-known/oauth-authorization-server",
70
- "https://mcp.vendor.test/.well-known/openid-configuration",
71
- ]);
72
- });
73
- });
74
-
75
- describe("resolveAuthorizationServers", () => {
76
- it("prefers the challenge's pointer and reads authorization_servers from it", async () => {
77
- const { fetchImpl, requested } = serving({
78
- "https://mcp.vendor.test/.well-known/oauth-protected-resource/mcp": { resource: "https://mcp.vendor.test/mcp", authorization_servers: ["https://login.vendor.test"] },
79
- });
80
- const result = await resolveAuthorizationServers("https://mcp.vendor.test/mcp", "https://mcp.vendor.test/.well-known/oauth-protected-resource/mcp", { ...deps, fetchImpl });
81
- expect(result.issuers).toEqual(["https://login.vendor.test"]);
82
- expect(requested).toEqual(["https://mcp.vendor.test/.well-known/oauth-protected-resource/mcp"]);
83
- });
84
-
85
- it("without a pointer walks the well-known documents most specific first", async () => {
86
- const { fetchImpl, requested } = serving({
87
- "https://mcp.vendor.test/.well-known/oauth-protected-resource": { authorization_servers: ["https://login.vendor.test/tenant"] },
88
- });
89
- const result = await resolveAuthorizationServers("https://mcp.vendor.test/mcp", undefined, { ...deps, fetchImpl });
90
- expect(result.issuers).toEqual(["https://login.vendor.test/tenant"]);
91
- expect(requested).toEqual(["https://mcp.vendor.test/.well-known/oauth-protected-resource/mcp", "https://mcp.vendor.test/.well-known/oauth-protected-resource"]);
92
- expect(result.attempts).toEqual([
93
- { url: "https://mcp.vendor.test/.well-known/oauth-protected-resource/mcp", status: 404 },
94
- { url: "https://mcp.vendor.test/.well-known/oauth-protected-resource", status: 200 },
95
- ]);
96
- });
97
-
98
- it("answers no issuers when no document names any, recording every attempt", async () => {
99
- const { fetchImpl } = serving({});
100
- const result = await resolveAuthorizationServers("https://mcp.vendor.test/mcp", undefined, { ...deps, fetchImpl });
101
- expect(result.issuers).toEqual([]);
102
- expect(result.attempts).toHaveLength(2);
103
- });
104
-
105
- it("records a network failure as an attempt and moves on", async () => {
106
- const fetchImpl: OutboundFetch = async () => {
107
- throw new Error("connect ECONNREFUSED");
108
- };
109
- const result = await resolveAuthorizationServers("https://mcp.vendor.test/", undefined, { ...deps, fetchImpl });
110
- expect(result.issuers).toEqual([]);
111
- expect(result.attempts).toEqual([{ url: "https://mcp.vendor.test/.well-known/oauth-protected-resource", error: "connect ECONNREFUSED" }]);
112
- });
113
- });
114
-
115
- describe("readAuthorizationServerMetadata", () => {
116
- it("reads a path-bearing issuer through the inserted well-known segment", async () => {
117
- const { fetchImpl, requested } = serving({
118
- "https://login.vendor.test/.well-known/oauth-authorization-server/tenant": ISSUER_DOCUMENT,
119
- });
120
- const read = await readAuthorizationServerMetadata("https://login.vendor.test/tenant", { ...deps, fetchImpl });
121
- expect(read.kind).toBe("found");
122
- if (read.kind === "found") {
123
- expect(read.metadata).toEqual({
124
- metadataUrl: "https://login.vendor.test/.well-known/oauth-authorization-server/tenant",
125
- issuer: "https://login.vendor.test",
126
- authorizationEndpoint: "https://login.vendor.test/authorize",
127
- tokenEndpoint: "https://login.vendor.test/token",
128
- registrationEndpoint: "https://login.vendor.test/register",
129
- scopesSupported: ["read"],
130
- codeChallengeMethodsSupported: ["S256"],
131
- });
132
- }
133
- expect(requested).toEqual(["https://login.vendor.test/.well-known/oauth-authorization-server/tenant"]);
134
- });
135
-
136
- it("falls back to OpenID's document and reads an absent registration_endpoint as empty", async () => {
137
- const { fetchImpl, requested } = serving({
138
- "https://login.vendor.test/.well-known/openid-configuration": { ...ISSUER_DOCUMENT, registration_endpoint: undefined, scopes_supported: undefined },
139
- });
140
- const read = await readAuthorizationServerMetadata("https://login.vendor.test", { ...deps, fetchImpl });
141
- expect(read.kind).toBe("found");
142
- if (read.kind === "found") {
143
- expect(read.metadata.registrationEndpoint).toBe("");
144
- expect(read.metadata.scopesSupported).toEqual([]);
145
- expect(read.metadata.metadataUrl).toBe("https://login.vendor.test/.well-known/openid-configuration");
146
- }
147
- expect(requested).toEqual(["https://login.vendor.test/.well-known/oauth-authorization-server", "https://login.vendor.test/.well-known/openid-configuration"]);
148
- });
149
-
150
- it("skips a document that lacks either endpoint and reports not-found with every attempt", async () => {
151
- const { fetchImpl } = serving({
152
- "https://login.vendor.test/.well-known/oauth-authorization-server": { issuer: "x", authorization_endpoint: "https://login.vendor.test/authorize" },
153
- "https://login.vendor.test/.well-known/openid-configuration": { status: 503 },
154
- });
155
- const read = await readAuthorizationServerMetadata("https://login.vendor.test", { ...deps, fetchImpl });
156
- expect(read).toEqual({
157
- kind: "not-found",
158
- attempts: [
159
- { url: "https://login.vendor.test/.well-known/oauth-authorization-server", status: 200, missing: "token_endpoint" },
160
- { url: "https://login.vendor.test/.well-known/openid-configuration", status: 503 },
161
- ],
162
- });
163
- });
164
-
165
- it("reports not-found for an unparseable issuer without dialling", async () => {
166
- const { fetchImpl, requested } = serving({});
167
- const read = await readAuthorizationServerMetadata("::::", { ...deps, fetchImpl });
168
- expect(read).toEqual({ kind: "not-found", attempts: [] });
169
- expect(requested).toEqual([]);
170
- });
171
- });
@@ -1,98 +0,0 @@
1
- /**
2
- * Pins the one-request probe: the complete `initialize` body (the shape
3
- * several hosted servers demand before they authenticate), the caller's
4
- * headers and name carried, the closed outcome vocabulary, the body
5
- * released unread, and a failing fetch answered as `unreachable`.
6
- */
7
- import { describe, expect, it } from "vitest";
8
-
9
- import type { OutboundFetch } from "../egress/fetch.js";
10
- import { probeEndpointAuth } from "../mcp-oauth/probe.js";
11
- import { MCP_PROTOCOL_VERSION } from "../mcp-oauth/request.js";
12
-
13
- const deps = { timeoutMs: 3_000, clientName: "stigmer-test" };
14
-
15
- function answering(status: number, headers: Record<string, string> = {}, body: string | null = null): { fetchImpl: OutboundFetch; calls: { url: string; init: RequestInit | undefined }[] } {
16
- const calls: { url: string; init: RequestInit | undefined }[] = [];
17
- const fetchImpl: OutboundFetch = async (url, init) => {
18
- calls.push({ url: String(url), init });
19
- return new Response(body, { status, headers });
20
- };
21
- return { fetchImpl, calls };
22
- }
23
-
24
- describe("probeEndpointAuth", () => {
25
- it("sends one complete initialize, naming the caller, with the endpoint's headers layered on", async () => {
26
- const { fetchImpl, calls } = answering(200, {}, "{}");
27
- await probeEndpointAuth("https://mcp.vendor.test/mcp", { "X-Vendor": "v" }, { ...deps, fetchImpl });
28
- expect(calls).toHaveLength(1);
29
- const init = calls[0]?.init;
30
- expect(init?.method).toBe("POST");
31
- const headers = init?.headers as Record<string, string>;
32
- expect(headers["Accept"]).toBe("application/json, text/event-stream");
33
- expect(headers["Content-Type"]).toBe("application/json");
34
- expect(headers["MCP-Protocol-Version"]).toBe(MCP_PROTOCOL_VERSION);
35
- expect(headers["X-Vendor"]).toBe("v");
36
- const body = JSON.parse(String(init?.body)) as { method: string; params: { protocolVersion: string; capabilities: object; clientInfo: { name: string } } };
37
- expect(body.method).toBe("initialize");
38
- expect(body.params.protocolVersion).toBe(MCP_PROTOCOL_VERSION);
39
- expect(body.params.capabilities).toEqual({});
40
- expect(body.params.clientInfo.name).toBe("stigmer-test");
41
- expect(init?.signal).toBeInstanceOf(AbortSignal);
42
- });
43
-
44
- it("reads a 401 OAuth challenge as oauth with its resource_metadata pointer", async () => {
45
- const { fetchImpl } = answering(401, { "www-authenticate": 'Bearer realm="OAuth", resource_metadata="https://mcp.vendor.test/.well-known/oauth-protected-resource"' });
46
- await expect(probeEndpointAuth("https://mcp.vendor.test/mcp", undefined, { ...deps, fetchImpl })).resolves.toEqual({
47
- kind: "oauth",
48
- challenge: 'Bearer realm="OAuth", resource_metadata="https://mcp.vendor.test/.well-known/oauth-protected-resource"',
49
- resourceMetadataUrl: "https://mcp.vendor.test/.well-known/oauth-protected-resource",
50
- });
51
- });
52
-
53
- it("reads a 401 without a pointer as oauth when the realm says OAuth", async () => {
54
- const { fetchImpl } = answering(401, { "www-authenticate": 'Bearer realm="OAuth"' });
55
- await expect(probeEndpointAuth("https://mcp.vendor.test/mcp", undefined, { ...deps, fetchImpl })).resolves.toEqual({
56
- kind: "oauth",
57
- challenge: 'Bearer realm="OAuth"',
58
- resourceMetadataUrl: undefined,
59
- });
60
- });
61
-
62
- it("reads a plain Bearer 401 as challenge-not-oauth", async () => {
63
- const { fetchImpl } = answering(401, { "www-authenticate": 'Bearer error="invalid_token"' });
64
- await expect(probeEndpointAuth("https://api.vendor.test/mcp", undefined, { ...deps, fetchImpl })).resolves.toEqual({
65
- kind: "challenge-not-oauth",
66
- challenge: 'Bearer error="invalid_token"',
67
- });
68
- });
69
-
70
- it("reads a 401 without a WWW-Authenticate header as challenge-not-oauth with an empty challenge", async () => {
71
- const { fetchImpl } = answering(401);
72
- await expect(probeEndpointAuth("https://api.vendor.test/mcp", undefined, { ...deps, fetchImpl })).resolves.toEqual({ kind: "challenge-not-oauth", challenge: "" });
73
- });
74
-
75
- it("reads a 2xx as accepted whatever the body says, and releases the body", async () => {
76
- let cancelled = false;
77
- const stream = new ReadableStream<Uint8Array>({
78
- cancel() {
79
- cancelled = true;
80
- },
81
- });
82
- const fetchImpl: OutboundFetch = async () => new Response(stream, { status: 200, headers: { "content-type": "text/event-stream" } });
83
- await expect(probeEndpointAuth("https://open.vendor.test/mcp", undefined, { ...deps, fetchImpl })).resolves.toEqual({ kind: "accepted", status: 200 });
84
- expect(cancelled).toBe(true);
85
- });
86
-
87
- it("reads any other status as http-other", async () => {
88
- const { fetchImpl } = answering(405);
89
- await expect(probeEndpointAuth("https://api.vendor.test/mcp", undefined, { ...deps, fetchImpl })).resolves.toEqual({ kind: "http-other", status: 405 });
90
- });
91
-
92
- it("never throws: a failing fetch is unreachable, naming the error", async () => {
93
- const fetchImpl: OutboundFetch = async () => {
94
- throw new Error("connect ECONNREFUSED");
95
- };
96
- await expect(probeEndpointAuth("http://127.0.0.1:9/mcp", undefined, { ...deps, fetchImpl })).resolves.toEqual({ kind: "unreachable", error: "Error: connect ECONNREFUSED" });
97
- });
98
- });