@query-farm/vgi-rpc 0.6.4 → 0.7.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 (177) hide show
  1. package/dist/access-log.d.ts +55 -0
  2. package/dist/access-log.d.ts.map +1 -0
  3. package/dist/arrow/impl-arrowjs/index.d.ts +96 -0
  4. package/dist/arrow/impl-arrowjs/index.d.ts.map +1 -0
  5. package/dist/arrow/impl-flechette/index.d.ts +102 -0
  6. package/dist/arrow/impl-flechette/index.d.ts.map +1 -0
  7. package/dist/arrow/impl-flechette/message-meta.d.ts +11 -0
  8. package/dist/arrow/impl-flechette/message-meta.d.ts.map +1 -0
  9. package/dist/arrow/index.d.ts +4 -0
  10. package/dist/arrow/index.d.ts.map +1 -0
  11. package/dist/arrow/predicates.d.ts +44 -0
  12. package/dist/arrow/predicates.d.ts.map +1 -0
  13. package/dist/arrow/types.d.ts +62 -0
  14. package/dist/arrow/types.d.ts.map +1 -0
  15. package/dist/auth.d.ts +5 -0
  16. package/dist/auth.d.ts.map +1 -1
  17. package/dist/client/capabilities.d.ts +25 -0
  18. package/dist/client/capabilities.d.ts.map +1 -0
  19. package/dist/client/connect.d.ts +10 -0
  20. package/dist/client/connect.d.ts.map +1 -1
  21. package/dist/client/introspect.d.ts +21 -0
  22. package/dist/client/introspect.d.ts.map +1 -1
  23. package/dist/client/ipc.d.ts +8 -2
  24. package/dist/client/ipc.d.ts.map +1 -1
  25. package/dist/client/oauth.d.ts +9 -0
  26. package/dist/client/oauth.d.ts.map +1 -1
  27. package/dist/client/pipe.d.ts +24 -0
  28. package/dist/client/pipe.d.ts.map +1 -1
  29. package/dist/client/stream.d.ts +19 -2
  30. package/dist/client/stream.d.ts.map +1 -1
  31. package/dist/client/types.d.ts +23 -0
  32. package/dist/client/types.d.ts.map +1 -1
  33. package/dist/client/uploadUrl.d.ts +25 -0
  34. package/dist/client/uploadUrl.d.ts.map +1 -0
  35. package/dist/constants.d.ts +30 -2
  36. package/dist/constants.d.ts.map +1 -1
  37. package/dist/crypto.d.ts +22 -0
  38. package/dist/crypto.d.ts.map +1 -0
  39. package/dist/dispatch/describe.d.ts +10 -6
  40. package/dist/dispatch/describe.d.ts.map +1 -1
  41. package/dist/dispatch/stream.d.ts +2 -2
  42. package/dist/dispatch/stream.d.ts.map +1 -1
  43. package/dist/dispatch/unary.d.ts +2 -2
  44. package/dist/dispatch/unary.d.ts.map +1 -1
  45. package/dist/errors.d.ts +64 -1
  46. package/dist/errors.d.ts.map +1 -1
  47. package/dist/external.d.ts +27 -5
  48. package/dist/external.d.ts.map +1 -1
  49. package/dist/http/auth.d.ts +13 -0
  50. package/dist/http/auth.d.ts.map +1 -1
  51. package/dist/http/bearer.d.ts.map +1 -1
  52. package/dist/http/common.d.ts +43 -7
  53. package/dist/http/common.d.ts.map +1 -1
  54. package/dist/http/dispatch.d.ts +20 -2
  55. package/dist/http/dispatch.d.ts.map +1 -1
  56. package/dist/http/handler.d.ts.map +1 -1
  57. package/dist/http/index.d.ts +1 -0
  58. package/dist/http/index.d.ts.map +1 -1
  59. package/dist/http/jwt.d.ts +1 -0
  60. package/dist/http/jwt.d.ts.map +1 -1
  61. package/dist/http/mtls.d.ts +9 -1
  62. package/dist/http/mtls.d.ts.map +1 -1
  63. package/dist/http/oauth-pkce.d.ts +141 -0
  64. package/dist/http/oauth-pkce.d.ts.map +1 -0
  65. package/dist/http/pages.d.ts +3 -0
  66. package/dist/http/pages.d.ts.map +1 -1
  67. package/dist/http/sticky.d.ts +124 -0
  68. package/dist/http/sticky.d.ts.map +1 -0
  69. package/dist/http/token.d.ts +43 -12
  70. package/dist/http/token.d.ts.map +1 -1
  71. package/dist/http/types.d.ts +68 -5
  72. package/dist/http/types.d.ts.map +1 -1
  73. package/dist/index.d.ts +6 -4
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +1275 -3511
  76. package/dist/index.js.map +20 -38
  77. package/dist/launcher/hash.d.ts +22 -0
  78. package/dist/launcher/hash.d.ts.map +1 -0
  79. package/dist/launcher/index.d.ts +23 -0
  80. package/dist/launcher/index.d.ts.map +1 -0
  81. package/dist/launcher/launch.d.ts +27 -0
  82. package/dist/launcher/launch.d.ts.map +1 -0
  83. package/dist/launcher/lock.d.ts +19 -0
  84. package/dist/launcher/lock.d.ts.map +1 -0
  85. package/dist/launcher/serve-unix.d.ts +55 -0
  86. package/dist/launcher/serve-unix.d.ts.map +1 -0
  87. package/dist/launcher/state.d.ts +71 -0
  88. package/dist/launcher/state.d.ts.map +1 -0
  89. package/dist/otel.d.ts.map +1 -1
  90. package/dist/protocol.d.ts +19 -2
  91. package/dist/protocol.d.ts.map +1 -1
  92. package/dist/schema.d.ts +45 -18
  93. package/dist/schema.d.ts.map +1 -1
  94. package/dist/server.d.ts +23 -2
  95. package/dist/server.d.ts.map +1 -1
  96. package/dist/types.d.ts +270 -12
  97. package/dist/types.d.ts.map +1 -1
  98. package/dist/util/gzip.d.ts +10 -0
  99. package/dist/util/gzip.d.ts.map +1 -0
  100. package/dist/util/schema.d.ts +3 -15
  101. package/dist/util/schema.d.ts.map +1 -1
  102. package/dist/util/web-crypto.d.ts +22 -0
  103. package/dist/util/web-crypto.d.ts.map +1 -0
  104. package/dist/util/zstd.d.ts +26 -3
  105. package/dist/util/zstd.d.ts.map +1 -1
  106. package/dist/wire/opaque.d.ts +11 -0
  107. package/dist/wire/opaque.d.ts.map +1 -0
  108. package/dist/wire/reader.d.ts +5 -5
  109. package/dist/wire/reader.d.ts.map +1 -1
  110. package/dist/wire/request.d.ts +11 -3
  111. package/dist/wire/request.d.ts.map +1 -1
  112. package/dist/wire/response.d.ts +6 -6
  113. package/dist/wire/response.d.ts.map +1 -1
  114. package/dist/wire/writer.d.ts +49 -39
  115. package/dist/wire/writer.d.ts.map +1 -1
  116. package/package.json +35 -21
  117. package/src/access-log.ts +200 -0
  118. package/src/arrow/impl-arrowjs/index.ts +433 -0
  119. package/src/arrow/impl-flechette/index.ts +414 -0
  120. package/src/arrow/impl-flechette/message-meta.ts +174 -0
  121. package/src/arrow/index.ts +89 -0
  122. package/src/arrow/predicates.ts +56 -0
  123. package/src/arrow/types.ts +73 -0
  124. package/src/auth.ts +5 -0
  125. package/src/client/capabilities.ts +84 -0
  126. package/src/client/connect.ts +113 -26
  127. package/src/client/introspect.ts +74 -38
  128. package/src/client/ipc.ts +37 -27
  129. package/src/client/oauth.ts +9 -0
  130. package/src/client/pipe.ts +36 -9
  131. package/src/client/stream.ts +43 -20
  132. package/src/client/types.ts +23 -0
  133. package/src/client/uploadUrl.ts +169 -0
  134. package/src/constants.ts +34 -2
  135. package/src/crypto.ts +95 -0
  136. package/src/dispatch/describe.ts +146 -107
  137. package/src/dispatch/stream.ts +53 -24
  138. package/src/dispatch/unary.ts +5 -4
  139. package/src/errors.ts +87 -0
  140. package/src/external.ts +49 -30
  141. package/src/http/auth.ts +13 -0
  142. package/src/http/bearer.ts +2 -5
  143. package/src/http/common.ts +91 -23
  144. package/src/http/dispatch.ts +373 -46
  145. package/src/http/handler.ts +790 -68
  146. package/src/http/index.ts +1 -0
  147. package/src/http/jwt.ts +1 -0
  148. package/src/http/mtls.ts +25 -3
  149. package/src/http/oauth-pkce.ts +1035 -0
  150. package/src/http/pages.ts +30 -15
  151. package/src/http/sticky.ts +429 -0
  152. package/src/http/token.ts +170 -75
  153. package/src/http/types.ts +69 -5
  154. package/src/index.ts +40 -1
  155. package/src/launcher/hash.ts +104 -0
  156. package/src/launcher/index.ts +35 -0
  157. package/src/launcher/launch.ts +284 -0
  158. package/src/launcher/lock.ts +171 -0
  159. package/src/launcher/serve-unix.ts +386 -0
  160. package/src/launcher/state.ts +257 -0
  161. package/src/otel.ts +39 -33
  162. package/src/protocol.ts +30 -3
  163. package/src/schema.ts +107 -56
  164. package/src/server.ts +196 -20
  165. package/src/types.ts +376 -18
  166. package/src/util/gzip.ts +63 -0
  167. package/src/util/schema.ts +4 -22
  168. package/src/util/web-crypto.ts +98 -0
  169. package/src/util/zstd.ts +133 -14
  170. package/src/wire/opaque.ts +37 -0
  171. package/src/wire/reader.ts +5 -4
  172. package/src/wire/request.ts +67 -8
  173. package/src/wire/response.ts +51 -85
  174. package/src/wire/writer.ts +165 -69
  175. package/dist/util/conform.d.ts +0 -18
  176. package/dist/util/conform.d.ts.map +0 -1
  177. package/src/util/conform.ts +0 -94
@@ -1,16 +1,52 @@
1
- import { type RecordBatch, type Schema } from "@query-farm/apache-arrow";
1
+ import { type VgiBatch, type VgiSchema } from "../arrow/index.js";
2
+ import type { CookieSpec } from "../types.js";
3
+ /** MIME type for Arrow IPC stream request and response bodies. */
2
4
  export declare const ARROW_CONTENT_TYPE = "application/vnd.apache.arrow.stream";
5
+ export declare const SESSION_HEADER = "VGI-Session";
6
+ export declare const SESSION_ACCEPT_HEADER = "VGI-Session-Accept";
7
+ export declare const SESSION_CLOSE_HEADER = "VGI-Session-Close";
8
+ export declare const STICKY_ENABLED_HEADER = "VGI-Sticky-Enabled";
9
+ export declare const STICKY_DEFAULT_TTL_HEADER = "VGI-Sticky-Default-TTL";
10
+ export declare const STICKY_ECHO_HEADERS_HEADER = "VGI-Sticky-Echo-Headers";
11
+ /** Prefix the server uses to tell the client "echo this header on subsequent
12
+ * requests in this session". Clients capture and replay
13
+ * `VGI-Echo-<name>: <value>` as plain `<name>: <value>` for the session
14
+ * lifetime — used for client-driven routing (e.g. `fly-force-instance-id`). */
15
+ export declare const ECHO_HEADER_PREFIX = "VGI-Echo-";
16
+ /** Framework-managed sticky session teardown endpoint path component.
17
+ * `DELETE {prefix}/__session__` idempotently closes the session referenced
18
+ * by the request's `VGI-Session` header. */
19
+ export declare const SESSION_ENDPOINT = "__session__";
20
+ /** Serialize a CookieSpec into a Set-Cookie header value. */
21
+ export declare function formatSetCookieHeader(c: CookieSpec): string;
22
+ /** Append Set-Cookie headers for each queued CookieSpec onto an existing Headers object. */
23
+ export declare function appendCookieHeaders(headers: Headers, cookies: readonly CookieSpec[]): void;
3
24
  export declare class HttpRpcError extends Error {
4
25
  readonly statusCode: number;
5
26
  constructor(message: string, statusCode: number);
6
27
  }
7
- /** Serialize a schema + batches into a complete IPC stream as Uint8Array. */
8
- export declare function serializeIpcStream(schema: Schema, batches: RecordBatch[]): Uint8Array;
9
- /** Create a Response with Arrow IPC content type. Casts Uint8Array for TS lib compat. */
28
+ /**
29
+ * Serialize a schema + batches into a complete IPC stream as Uint8Array.
30
+ *
31
+ * A single IPC stream is `[schema_msg, batch_msg, batch_msg, ..., EOS]`.
32
+ * Each backend implements `serializeBatches` to write that atomically —
33
+ * arrow-js via `RecordBatchStreamWriter`, flechette via `tablesToIPC`
34
+ * (added in our flechette fork). Naive concatenation of per-batch streams
35
+ * produces multiple EOS markers and breaks readers.
36
+ */
37
+ export declare function serializeIpcStream(schema: VgiSchema, batches: VgiBatch[]): Uint8Array;
38
+ /**
39
+ * Create a Response with Arrow IPC content type.
40
+ *
41
+ * Server errors (status 500) are translated to HTTP 200 with an
42
+ * ``X-VGI-RPC-Error: true`` header so that clients which discard
43
+ * response bodies on 5xx still receive the Arrow IPC error metadata.
44
+ * Client errors (400, 401, 404, 415) are passed through unchanged.
45
+ */
10
46
  export declare function arrowResponse(body: Uint8Array, status?: number, extraHeaders?: Headers): Response;
11
- /** Read schema + first batch from an IPC stream body. */
47
+ /** Read schema + first batch from an IPC stream body via the facade. */
12
48
  export declare function readRequestFromBody(body: Uint8Array): Promise<{
13
- schema: Schema;
14
- batch: RecordBatch;
49
+ schema: VgiSchema;
50
+ batch: VgiBatch;
15
51
  }>;
16
52
  //# sourceMappingURL=common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/http/common.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAA8C,KAAK,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGrH,eAAO,MAAM,kBAAkB,wCAAwC,CAAC;AAExE,qBAAa,YAAa,SAAQ,KAAK;aAGnB,UAAU,EAAE,MAAM;gBADlC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM;CAKrC;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,UAAU,CAQrF;AAED,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,SAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAI9F;AAED,yDAAyD;AACzD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC,CAY3G"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/http/common.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,QAAQ,EACb,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,kEAAkE;AAClE,eAAO,MAAM,kBAAkB,wCAAwC,CAAC;AAKxE,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAC5C,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAC1D,eAAO,MAAM,oBAAoB,sBAAsB,CAAC;AACxD,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAC1D,eAAO,MAAM,yBAAyB,2BAA2B,CAAC;AAClE,eAAO,MAAM,0BAA0B,4BAA4B,CAAC;AAEpE;;;gFAGgF;AAChF,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAE9C;;6CAE6C;AAC7C,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C,6DAA6D;AAC7D,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAiB3D;AAED,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAI1F;AAED,qBAAa,YAAa,SAAQ,KAAK;aAGnB,UAAU,EAAE,MAAM;gBADlC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM;CAKrC;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,UAAU,CAGrF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,SAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAQ9F;AAED,wEAAwE;AACxE,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC,CAU3G"}
@@ -1,18 +1,36 @@
1
1
  import type { AuthContext } from "../auth.js";
2
2
  import { type ExternalLocationConfig } from "../external.js";
3
3
  import type { MethodDefinition } from "../types.js";
4
+ import { TransportKind } from "../types.js";
4
5
  import type { StateSerializer } from "./types.js";
5
6
  export interface DispatchContext {
6
- signingKey: Uint8Array;
7
+ tokenKey: Uint8Array;
7
8
  tokenTtl: number;
8
9
  serverId: string;
10
+ /** Producer-only soft wire-cap (deprecated alias for the producer-loop
11
+ * byte budget). Unary/exchange ignore this. */
9
12
  maxStreamResponseBytes?: number;
13
+ /** Soft wire-cap for producer streams; hard wire-cap for unary/exchange.
14
+ * Externalised payloads do not count toward this. */
15
+ maxResponseBytes?: number;
16
+ /** Hard cap on bytes uploaded to external storage during one HTTP response. */
17
+ maxExternalizedResponseBytes?: number;
10
18
  stateSerializer: StateSerializer;
11
19
  authContext?: AuthContext;
12
20
  externalLocation?: ExternalLocationConfig;
21
+ /** Incoming HTTP request cookies. Empty/absent on non-HTTP paths. */
22
+ cookies?: ReadonlyMap<string, string>;
23
+ /** Transport identifier surfaced to handlers via CallContext.kind.
24
+ * Defaults to HTTP when unset (the only caller that overrides it is
25
+ * the AF_UNIX launcher path). */
26
+ kind?: TransportKind;
27
+ /** Per-request sticky-session sink. Installed by the handler when sticky
28
+ * is enabled and the dispatcher attaches it to the OutputCollector so
29
+ * `ctx.session` / `ctx.openSession` / `ctx.closeSession` work. */
30
+ stickyContext?: import("../types.js").StickyContext;
13
31
  }
14
32
  /** Dispatch a __describe__ request. */
15
- export declare function httpDispatchDescribe(protocolName: string, methods: Map<string, MethodDefinition>, serverId: string): Response;
33
+ export declare function httpDispatchDescribe(protocolName: string, methods: Map<string, MethodDefinition>, serverId: string, protocolVersion?: string): Promise<Response>;
16
34
  /** Dispatch a unary HTTP request. */
17
35
  export declare function httpDispatchUnary(method: MethodDefinition, body: Uint8Array, ctx: DispatchContext): Promise<Response>;
18
36
  /** Dispatch a stream init HTTP request (producer or exchange). */
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/http/dispatch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EAAE,KAAK,sBAAsB,EAAyB,MAAM,gBAAgB,CAAC;AACpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAUlD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;CAC3C;AAED,uCAAuC;AACvC,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACtC,QAAQ,EAAE,MAAM,GACf,QAAQ,CAIV;AAED,qCAAqC;AACrC,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,QAAQ,CAAC,CA0BnB;AAED,kEAAkE;AAClE,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,QAAQ,CAAC,CA2EnB;AAED,yFAAyF;AACzF,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,QAAQ,CAAC,CAqHnB"}
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/http/dispatch.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EACL,KAAK,sBAAsB,EAI5B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAM7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAQlD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,UAAU,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB;oDACgD;IAChD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;0DACsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAC1C,sEAAsE;IACtE,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC;;sCAEkC;IAClC,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;uEAEmE;IACnE,aAAa,CAAC,EAAE,OAAO,aAAa,EAAE,aAAa,CAAC;CACrD;AA2BD,uCAAuC;AACvC,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACtC,QAAQ,EAAE,MAAM,EAChB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,QAAQ,CAAC,CAInB;AAED,qCAAqC;AACrC,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,QAAQ,CAAC,CA+FnB;AAED,kEAAkE;AAClE,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,QAAQ,CAAC,CAmGnB;AAED,yFAAyF;AACzF,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,QAAQ,CAAC,CAqMnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/http/handler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAa/C,OAAO,EAAE,KAAK,kBAAkB,EAAuB,MAAM,YAAY,CAAC;AAI1E;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsSpD"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/http/handler.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAoD/C,OAAO,EAAE,KAAK,kBAAkB,EAAuB,MAAM,YAAY,CAAC;AAwB1E;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAo7BpD"}
@@ -8,6 +8,7 @@ export type { JwtAuthenticateOptions } from "./jwt.js";
8
8
  export { jwtAuthenticate } from "./jwt.js";
9
9
  export type { CertValidateFn, XfccElement, XfccValidateFn } from "./mtls.js";
10
10
  export { mtlsAuthenticate, mtlsAuthenticateFingerprint, mtlsAuthenticateSubject, mtlsAuthenticateXfcc, parseXfcc, } from "./mtls.js";
11
+ export { cookieAuthenticate } from "./oauth-pkce.js";
11
12
  export { type UnpackedToken, unpackStateToken } from "./token.js";
12
13
  export type { HttpHandlerOptions, StateSerializer } from "./types.js";
13
14
  export { jsonStateSerializer } from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,uBAAuB,EACvB,oBAAoB,EACpB,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,uBAAuB,EACvB,oBAAoB,EACpB,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { AuthenticateFn } from "./auth.js";
2
+ /** Options for {@link jwtAuthenticate}, configuring JWT Bearer-token validation. */
2
3
  export interface JwtAuthenticateOptions {
3
4
  /** The expected `iss` claim (also used to discover AS metadata). */
4
5
  issuer: string;
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/http/jwt.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAqD/E"}
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/http/jwt.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAqD/E"}
@@ -1,13 +1,20 @@
1
- import { X509Certificate } from "node:crypto";
2
1
  import { AuthContext } from "../auth.js";
3
2
  import type { AuthenticateFn } from "./auth.js";
3
+ type X509Certificate = any;
4
4
  /** A single element from an `x-forwarded-client-cert` header. */
5
5
  export interface XfccElement {
6
+ /** Hex SHA-256 digest of the client certificate (`Hash` key). */
6
7
  hash: string | null;
8
+ /** URL-decoded PEM of the client certificate (`Cert` key), if the proxy
9
+ * forwarded it. */
7
10
  cert: string | null;
11
+ /** Certificate Subject DN (`Subject` key). */
8
12
  subject: string | null;
13
+ /** URL-decoded URI-type Subject Alternative Name (`URI` key). */
9
14
  uri: string | null;
15
+ /** DNS-type Subject Alternative Names (`DNS` keys); may repeat in the header. */
10
16
  dns: readonly string[];
17
+ /** URL-decoded URI of the proxy that presented the cert (`By` key). */
11
18
  by: string | null;
12
19
  }
13
20
  /** Receives a parsed XFCC element, returns an AuthContext on success. Must throw on failure. */
@@ -75,4 +82,5 @@ export declare function mtlsAuthenticateSubject(options?: {
75
82
  allowedSubjects?: ReadonlySet<string> | null;
76
83
  checkExpiry?: boolean;
77
84
  }): AuthenticateFn;
85
+ export {};
78
86
  //# sourceMappingURL=mtls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mtls.d.ts","sourceRoot":"","sources":["../../src/http/mtls.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAMhD,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACnB;AAED,gGAAgG;AAChG,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAE1F,mGAAmG;AACnG,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,eAAe,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AA2C3F;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,EAAE,CA0C5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAC7C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC,GAAG,cAAc,CA2BjB;AAkCD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,cAAc,CAUjB;AAID;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACnD,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,cAAc,CAkBjB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,cAAc,CAkCjB"}
1
+ {"version":3,"file":"mtls.d.ts","sourceRoot":"","sources":["../../src/http/mtls.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAMhD,KAAK,eAAe,GAAG,GAAG,CAAC;AAc3B,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;wBACoB;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iEAAiE;IACjE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,iFAAiF;IACjF,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB,uEAAuE;IACvE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACnB;AAED,gGAAgG;AAChG,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAE1F,mGAAmG;AACnG,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,eAAe,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AA2C3F;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,EAAE,CA0C5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAC7C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC,GAAG,cAAc,CA2BjB;AAmCD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,cAAc,CAUjB;AAID;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACnD,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,cAAc,CAmBjB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,cAAc,CAkCjB"}
@@ -0,0 +1,141 @@
1
+ import type { AuthenticateFn } from "./auth.js";
2
+ /** Generate a 43-character URL-safe random code verifier (RFC 7636 S4.1). */
3
+ export declare function generateCodeVerifier(): string;
4
+ /** Compute S256 code challenge from a code verifier (RFC 7636 S4.2). */
5
+ export declare function generateCodeChallenge(verifier: string): string;
6
+ /** Generate a random state nonce for CSRF protection. */
7
+ export declare function generateStateNonce(): string;
8
+ /** Derive a separate HMAC key for OAuth session cookies. */
9
+ export declare function deriveSessionKey(signingKey: Uint8Array): Uint8Array;
10
+ /**
11
+ * Pack PKCE session data into a signed, base64-encoded cookie value.
12
+ *
13
+ * Wire format v4:
14
+ * [1B version=4] [8B created_at uint64 LE]
15
+ * [2B cv_len uint16 LE] [cv_len bytes code_verifier]
16
+ * [2B state_len uint16 LE] [state_len bytes state_nonce]
17
+ * [2B url_len uint16 LE] [url_len bytes original_url]
18
+ * [2B rt_len uint16 LE] [rt_len bytes return_to]
19
+ * [32B HMAC-SHA256(session_key, all above)]
20
+ */
21
+ export declare function packOAuthCookie(codeVerifier: string, stateNonce: string, originalUrl: string, sessionKey: Uint8Array, createdAt?: number, returnTo?: string): string;
22
+ export interface UnpackedOAuthCookie {
23
+ codeVerifier: string;
24
+ stateNonce: string;
25
+ originalUrl: string;
26
+ returnTo: string;
27
+ }
28
+ /**
29
+ * Unpack and verify a signed OAuth session cookie.
30
+ *
31
+ * @throws Error on tampered, expired, or malformed cookies.
32
+ */
33
+ export declare function unpackOAuthCookie(cookieValue: string, sessionKey: Uint8Array, maxAge?: number): UnpackedOAuthCookie;
34
+ export interface OidcEndpoints {
35
+ authorizationEndpoint: string;
36
+ tokenEndpoint: string;
37
+ }
38
+ /**
39
+ * Create a lazy-cached OIDC discovery function.
40
+ *
41
+ * Caches the Promise; resets on rejection so a transient failure is retried.
42
+ */
43
+ export declare function createOidcDiscovery(issuer: string): () => Promise<OidcEndpoints | null>;
44
+ export interface TokenExchangeResult {
45
+ token: string;
46
+ maxAge: number;
47
+ refreshToken: string | null;
48
+ }
49
+ /** Exchange an authorization code for a token via the token endpoint. */
50
+ export declare function exchangeCodeForToken(tokenEndpoint: string, code: string, redirectUri: string, codeVerifier: string, clientId: string, clientSecret?: string, useIdToken?: boolean): Promise<TokenExchangeResult>;
51
+ /** Validate the original URL is relative and within the expected prefix. */
52
+ export declare function validateOriginalUrl(url: string, prefix: string): string;
53
+ /** Validate an external return-to URL against an origin allowlist. */
54
+ export declare function validateReturnTo(url: string, allowedOrigins?: ReadonlySet<string>): string;
55
+ /** Parse the Cookie header from a Request into a Map. */
56
+ export declare function parseCookies(request: Request): Map<string, string>;
57
+ interface SetCookieOptions {
58
+ maxAge?: number;
59
+ path?: string;
60
+ secure?: boolean;
61
+ httpOnly?: boolean;
62
+ sameSite?: "Strict" | "Lax" | "None";
63
+ }
64
+ /** Build a Set-Cookie header string. */
65
+ export declare function buildSetCookieHeader(name: string, value: string, options: SetCookieOptions): string;
66
+ /** Render a user-friendly OAuth error page. */
67
+ export declare function buildOAuthErrorPage(message: string, detail: string | null, retryUrl: string): string;
68
+ /** Return HTML snippet (style + div + script) for user info display. */
69
+ export declare function buildUserInfoHtml(prefix: string): string;
70
+ /**
71
+ * Create an authenticate callback that reads a bearer token from a cookie.
72
+ *
73
+ * Extracts the token from the named cookie and delegates validation to the
74
+ * `innerAuth` authenticator by creating a new Request with an Authorization header.
75
+ */
76
+ export declare function cookieAuthenticate(innerAuth: AuthenticateFn, cookieName?: string): AuthenticateFn;
77
+ /** Configuration object produced by configureOAuthPkce. */
78
+ export interface OAuthPkceConfig {
79
+ sessionKey: Uint8Array;
80
+ oidcDiscovery: () => Promise<OidcEndpoints | null>;
81
+ clientId: string;
82
+ clientSecret: string | undefined;
83
+ useIdToken: boolean;
84
+ prefix: string;
85
+ secureCookie: boolean;
86
+ redirectUri: string;
87
+ scope: string;
88
+ allowedReturnOrigins: ReadonlySet<string>;
89
+ cookieAuthenticate: AuthenticateFn;
90
+ userInfoHtml: string;
91
+ }
92
+ /** Options for configureOAuthPkce. */
93
+ export interface OAuthPkceOptions {
94
+ signingKey: Uint8Array;
95
+ issuer: string;
96
+ clientId: string;
97
+ clientSecret?: string;
98
+ useIdToken?: boolean;
99
+ prefix: string;
100
+ secureCookie: boolean;
101
+ redirectUri: string;
102
+ scope?: string;
103
+ allowedReturnOrigins?: ReadonlySet<string>;
104
+ }
105
+ /**
106
+ * Resolve the OAuth PKCE `scope` string from available sources.
107
+ *
108
+ * Precedence:
109
+ * 1. `scopesSupported` from OAuth resource metadata (space-joined), when non-empty.
110
+ * 2. Explicit `optionsScope` override (e.g. `HttpHandlerOptions.oauthPkceScope`).
111
+ * 3. `undefined`, which lets `configureOAuthPkce` apply its built-in default of
112
+ * `"openid email"`.
113
+ *
114
+ * Mirrors the Python reference behavior introduced in vgi-rpc v0.6.12: authorization
115
+ * requests should use the scopes the server publishes in its protected resource
116
+ * metadata, so clients ask for exactly what the resource advertises.
117
+ */
118
+ export declare function resolvePkceScope(scopesSupported: readonly string[] | undefined, optionsScope: string | undefined): string | undefined;
119
+ /** Factory function wiring all PKCE components. */
120
+ export declare function configureOAuthPkce(opts: OAuthPkceOptions, innerAuth: AuthenticateFn): OAuthPkceConfig;
121
+ /**
122
+ * Handle POST/OPTIONS {prefix}/_oauth/token — the PKCE token-exchange proxy.
123
+ *
124
+ * SPA PKCE clients cannot safely hold a client_secret, but some IdPs
125
+ * (notably Google) reject token-endpoint requests from "Web application"
126
+ * clients without one. This handler accepts authorization_code/refresh_token
127
+ * exchanges from a browser, injects the configured server-side
128
+ * client_secret, and forwards the request to the IdP's real token_endpoint.
129
+ * The IdP response is returned verbatim (status code + body).
130
+ */
131
+ export declare function handleOAuthTokenProxy(request: Request, config: OAuthPkceConfig): Promise<Response>;
132
+ /** Handle GET {prefix}/_oauth/callback — the redirect from the authorization server. */
133
+ export declare function handleOAuthCallback(request: Request, config: OAuthPkceConfig): Promise<Response>;
134
+ /** Handle GET {prefix}/_oauth/logout — clear auth cookie and redirect. */
135
+ export declare function handleOAuthLogout(_request: Request, config: OAuthPkceConfig): Response;
136
+ /** Redirect an unauthenticated browser GET to the OAuth authorization endpoint. Returns null if unable. */
137
+ export declare function handleBrowserGetRedirect(request: Request, config: OAuthPkceConfig): Promise<Response | null>;
138
+ /** If user is already authenticated and has _vgi_return_to, redirect immediately. Returns null otherwise. */
139
+ export declare function handleEarlyReturnTo(request: Request, config: OAuthPkceConfig): Response | null;
140
+ export {};
141
+ //# sourceMappingURL=oauth-pkce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-pkce.d.ts","sourceRoot":"","sources":["../../src/http/oauth-pkce.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,9 @@
3
3
  * Matches the styling of the Python and Go implementations.
4
4
  */
5
5
  import type { MethodDefinition } from "../types.js";
6
+ export declare const LOGO_URL = "https://vgi-rpc-python.query.farm/assets/logo-hero.png";
7
+ export declare const FONTS = "<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=JetBrains+Mono:wght@400;600&display=swap\" rel=\"stylesheet\">";
8
+ export declare const ERROR_PAGE_STYLE = "<style>\nbody { font-family: 'Inter', system-ui, -apple-system, sans-serif; max-width: 600px;\n margin: 0 auto; padding: 60px 20px 0; color: #2c2c1e; text-align: center;\n background: #faf8f0; }\n.logo { margin-bottom: 24px; }\n.logo img { width: 120px; height: 120px; border-radius: 50%;\n box-shadow: 0 4px 24px rgba(0,0,0,0.12); }\nh1 { color: #2d5016; margin-bottom: 8px; font-weight: 700; }\ncode { font-family: 'JetBrains Mono', monospace; background: #f0ece0;\n padding: 2px 6px; border-radius: 3px; font-size: 0.9em; color: #2c2c1e; }\na { color: #2d5016; text-decoration: none; }\na:hover { color: #4a7c23; }\np { line-height: 1.7; color: #6b6b5a; }\n.detail { margin-top: 12px; padding: 12px 16px; background: #f0ece0;\n border-radius: 6px; font-size: 0.9em; color: #6b6b5a; }\nfooter { margin-top: 48px; padding: 20px 0; border-top: 1px solid #f0ece0;\n color: #6b6b5a; font-size: 0.85em; line-height: 1.8; }\nfooter a { color: #2d5016; font-weight: 600; }\nfooter a:hover { color: #4a7c23; }\n</style>";
6
9
  export declare function buildLandingPage(protocolName: string, serverId: string, describePath: string | null, repoUrl: string | null): string;
7
10
  export declare function buildNotFoundPage(prefix: string, protocolName: string): string;
8
11
  export declare function buildDescribePage(protocolName: string, serverId: string, methods: Map<string, MethodDefinition>, repoUrl: string | null): string;
@@ -1 +1 @@
1
- {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/http/pages.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA8BpD,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,MAAM,CA2DR;AAMD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CA8B9E;AA4ED,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACtC,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,MAAM,CA8ER"}
1
+ {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/http/pages.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,eAAO,MAAM,QAAQ,2DAA2D,CAAC;AAEjF,eAAO,MAAM,KAAK,kSAE6H,CAAC;AAEhJ,eAAO,MAAM,gBAAgB,4iCAmBpB,CAAC;AAwBV,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,MAAM,CA2DR;AAMD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAwB9E;AA4ED,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACtC,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,MAAM,CA8ER"}
@@ -0,0 +1,124 @@
1
+ /** Seal a sticky-session token. Returns the base64url-encoded value for the
2
+ * `VGI-Session` header. */
3
+ export declare function sealSessionToken(serverId: string, sessionId: Uint8Array, expiresAt: number, tokenKey: Uint8Array, aad: Uint8Array, now?: number): string;
4
+ export interface OpenedSessionToken {
5
+ serverId: string;
6
+ sessionId: Uint8Array;
7
+ expiresAt: number;
8
+ }
9
+ /** Open a sticky-session token. Raises {@link SessionLostError} on any failure
10
+ * — wrong AAD (cross-principal replay) is indistinguishable from garbage. */
11
+ export declare function openSessionToken(token: string, tokenKey: Uint8Array, aad: Uint8Array): OpenedSessionToken;
12
+ /** Minimal promise-based mutex. The HTTP handler awaits `acquire()` before
13
+ * dispatching on a resumed session and calls the returned release in a
14
+ * `finally` so concurrent calls on the same session run sequentially. */
15
+ declare class AsyncMutex {
16
+ private locked;
17
+ private waiters;
18
+ acquire(): Promise<() => void>;
19
+ private release;
20
+ }
21
+ /** A live session in the per-worker registry. */
22
+ export interface SessionEntry {
23
+ state: unknown;
24
+ expiresAt: number;
25
+ principalKey: string;
26
+ lock: AsyncMutex;
27
+ }
28
+ /**
29
+ * Derive the registry partition key for a request principal.
30
+ *
31
+ * Both the dispatch path and the `DELETE /__session__` teardown path MUST
32
+ * compute this identically — otherwise a session opened on one path can't
33
+ * be looked up on the other. The NUL separator (rather than a space)
34
+ * keeps `{domain:"a", principal:"b "}` from colliding with
35
+ * `{domain:"a ", principal:"b"}`. Anonymous requests collapse to a
36
+ * single sentinel.
37
+ *
38
+ * `domain` / `principal` are the authenticated identity fields, or
39
+ * null/undefined for anonymous.
40
+ */
41
+ export declare function sessionPrincipalKey(authenticated: boolean, domain: string | null | undefined, principal: string | null | undefined): string;
42
+ /** Hex-encode a session_id Uint8Array (24-char lowercase hex). */
43
+ export declare function sessionIdHex(sessionId: Uint8Array): string;
44
+ /** Per-worker in-process map of live sticky sessions. */
45
+ export declare class SessionRegistry {
46
+ readonly defaultTtl: number;
47
+ private entries;
48
+ private _draining;
49
+ constructor(defaultTtl: number);
50
+ get draining(): boolean;
51
+ setDraining(value: boolean): void;
52
+ /** Register a session. Throws {@link ServerDrainingError} when draining. */
53
+ open(state: unknown, ttl: number | undefined, principalKey: string): {
54
+ sessionId: Uint8Array;
55
+ expiresAt: number;
56
+ };
57
+ /** Look up a session. Returns null on miss, expiry, or principal mismatch.
58
+ * Expired entries are evicted in-line (and `state.close?.()` invoked). */
59
+ get(sessionId: Uint8Array, principalKey: string): SessionEntry | null;
60
+ /** Remove a session and invoke `state.close?.()`. Returns true on hit. */
61
+ close(sessionId: Uint8Array): boolean;
62
+ /** Evict every entry past its TTL. Returns the eviction count. */
63
+ drainExpired(now?: number): number;
64
+ /** Invoke `state.close?.()` on every live session and clear the registry. */
65
+ shutdown(): void;
66
+ get size(): number;
67
+ }
68
+ /** Start a periodic reaper that evicts expired sessions. Returns a stop fn.
69
+ * Uses `setInterval().unref()` where available so the reaper does not keep
70
+ * the process alive. */
71
+ export declare function startSessionReaper(registry: SessionRegistry, tickMs?: number): () => void;
72
+ /** Per-request handle that the HTTP handler installs on the OutputCollector.
73
+ * `CallContext.openSession` / `closeSession` / `session` read and mutate
74
+ * this object; the handler then emits the resulting headers on the
75
+ * response. */
76
+ export interface StickySink {
77
+ /** True iff the request carried `VGI-Session-Accept: true`. */
78
+ acceptOpens: boolean;
79
+ /** Live session state (resumed or just-opened). Null until `openSession`
80
+ * or a successful resume populates it. */
81
+ state: unknown | null;
82
+ /** Hex session_id for the access log. Populated on resume + open;
83
+ * preserved across `closeSession` so close records still carry the id. */
84
+ sessionId: string | null;
85
+ /** Set by `openSession` so `process_response` emits `VGI-Session: <token>`. */
86
+ mintToken: string | null;
87
+ /** Set by `closeSession` so `process_response` emits `VGI-Session-Close: true`. */
88
+ closed: boolean;
89
+ /** Sticky-session lifecycle action observed during dispatch — one of
90
+ * "none" / "resume" / "open" / "close". Surfaced on the access log. */
91
+ action: "none" | "resume" | "open" | "close";
92
+ /** Bound by the handler: registers `state` in the registry, mints the
93
+ * AEAD-sealed token, and stamps `mintToken` + `sessionId`. */
94
+ _open(state: unknown, ttl: number | undefined): void;
95
+ /** Bound by the handler: removes the registry entry + invokes
96
+ * `state.close?.()`. Idempotent. */
97
+ _close(): void;
98
+ }
99
+ /** Build a `StickySink` for a request without sticky support — `_open` /
100
+ * `_close` throw the same RuntimeError shape as Python's implementation so
101
+ * call sites get a clear message. */
102
+ export declare function unavailableStickySink(): StickySink;
103
+ /** Operator-facing handle returned by `createHttpHandler` (when sticky is
104
+ * enabled) so SIGTERM hooks / worker-exit hooks can drain in-flight
105
+ * sessions cleanly. Mirrors Python's `DrainHandle`. */
106
+ export interface DrainHandle {
107
+ /** Flip the registry's drain flag — subsequent `ctx.openSession` raises
108
+ * {@link ServerDrainingError}. Existing sessions continue. */
109
+ drain(): void;
110
+ /** Invoke `state.close?.()` on every live session and clear the registry. */
111
+ shutdown(): void;
112
+ /** Return whether `drain()` has been invoked. */
113
+ isDraining(): boolean;
114
+ /** Test-only / advanced: flip the drain flag back. Production deployments
115
+ * only ever drain in one direction; conformance tests use this to clean
116
+ * up the fixture between tests. */
117
+ setDraining(value: boolean): void;
118
+ }
119
+ /** Build a {@link DrainHandle} for *registry*. `stopReaper`, when supplied,
120
+ * is invoked by `shutdown()` so the periodic reaper interval is cleared and
121
+ * the handle fully releases its resources. */
122
+ export declare function makeDrainHandle(registry: SessionRegistry, stopReaper?: () => void): DrainHandle;
123
+ export {};
124
+ //# sourceMappingURL=sticky.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sticky.d.ts","sourceRoot":"","sources":["../../src/http/sticky.ts"],"names":[],"mappings":"AAmEA;4BAC4B;AAC5B,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,UAAU,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,UAAU,EACpB,GAAG,EAAE,UAAU,EACf,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,CAsBR;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,kBAAkB,CAiCzG;AAMD;;0EAE0E;AAC1E,cAAM,UAAU;IACd,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAyB;IAElC,OAAO,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;IAUpC,OAAO,CAAC,OAAO;CAShB;AAMD,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,OAAO,EACtB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,MAAM,CAGR;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAI1D;AASD,yDAAyD;AACzD,qBAAa,eAAe;aAKE,UAAU,EAAE,MAAM;IAH9C,OAAO,CAAC,OAAO,CAA8D;IAC7E,OAAO,CAAC,SAAS,CAAS;gBAEE,UAAU,EAAE,MAAM;IAE9C,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAIjC,4EAA4E;IAC5E,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAejH;+EAC2E;IAC3E,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAerE,0EAA0E;IAC1E,KAAK,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO;IASrC,kEAAkE;IAClE,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM;IAalC,6EAA6E;IAC7E,QAAQ,IAAI,IAAI;IAMhB,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAgBD;;yBAEyB;AACzB,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,SAAO,GAAG,MAAM,IAAI,CAUvF;AAMD;;;gBAGgB;AAChB,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,WAAW,EAAE,OAAO,CAAC;IACrB;+CAC2C;IAC3C,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB;+EAC2E;IAC3E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mFAAmF;IACnF,MAAM,EAAE,OAAO,CAAC;IAChB;4EACwE;IACxE,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC7C;mEAC+D;IAC/D,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACrD;yCACqC;IACrC,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;sCAEsC;AACtC,wBAAgB,qBAAqB,IAAI,UAAU,CAelD;AAMD;;wDAEwD;AACxD,MAAM,WAAW,WAAW;IAC1B;mEAC+D;IAC/D,KAAK,IAAI,IAAI,CAAC;IACd,6EAA6E;IAC7E,QAAQ,IAAI,IAAI,CAAC;IACjB,iDAAiD;IACjD,UAAU,IAAI,OAAO,CAAC;IACtB;;wCAEoC;IACpC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACnC;AAED;;+CAE+C;AAC/C,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,MAAM,IAAI,GAAG,WAAW,CAU/F"}
@@ -1,24 +1,55 @@
1
1
  /**
2
- * Pack a state token matching the Python v2 wire format.
2
+ * Build the AEAD associated data that binds a state token to its issuing
3
+ * principal. Anonymous and authenticated tokens produce distinct AAD
4
+ * strings, so an anonymous token cannot be opened by a named identity
5
+ * (and vice versa).
6
+ */
7
+ export declare function computeAad(principal: string | null | undefined): Uint8Array;
8
+ export declare function bytesToBase64(bytes: Uint8Array): string;
9
+ export declare function base64ToBytes(b64: string): Uint8Array;
10
+ /**
11
+ * Seal a state token with XChaCha20-Poly1305 AEAD (v4 wire format).
12
+ *
13
+ * Layout (base64-encoded):
3
14
  *
4
- * Layout:
5
- * [1B version=2]
6
- * [8B created_at uint64 LE (seconds since epoch)]
7
- * [4B state_len uint32 LE] [state_len bytes]
8
- * [4B schema_len uint32 LE] [schema_len bytes]
9
- * [4B input_schema_len uint32 LE] [input_schema_len bytes]
10
- * [32B HMAC-SHA256(signing_key, all above bytes)]
15
+ * ```
16
+ * [1B version=4]
17
+ * [24B XChaCha20-Poly1305 nonce (random)]
18
+ * [.. ciphertext + 16B Poly1305 tag]
19
+ * plaintext:
20
+ * [8B created_at uint64 LE]
21
+ * [4B state_len uint32 LE] [state_len bytes]
22
+ * [4B schema_len uint32 LE] [schema_len bytes]
23
+ * [4B input_schema_len LE] [input_schema_len bytes]
24
+ * ```
25
+ *
26
+ * `created_at` lives inside the ciphertext so TTL enforcement runs after
27
+ * authenticity. The version byte is informational (a self-describing
28
+ * format marker); a tampered version byte still fails decryption because
29
+ * we use the matching algorithm for that version. `principal` is bound
30
+ * via AEAD associated data so a token minted for one identity fails
31
+ * decryption when presented by another.
11
32
  */
12
- export declare function packStateToken(stateBytes: Uint8Array, schemaBytes: Uint8Array, inputSchemaBytes: Uint8Array, signingKey: Uint8Array, createdAt?: number): string;
33
+ export declare function packStateToken(stateBytes: Uint8Array, schemaBytes: Uint8Array, inputSchemaBytes: Uint8Array, tokenKey: Uint8Array, principal: string | null | undefined, createdAt?: number): string;
34
+ /** Decrypted payload of a state token, as returned by {@link unpackStateToken}. */
13
35
  export interface UnpackedToken {
36
+ /** Serialized stream-state bytes carried by the token. */
14
37
  stateBytes: Uint8Array;
38
+ /** Serialized output-schema IPC bytes. */
15
39
  schemaBytes: Uint8Array;
40
+ /** Serialized input-schema IPC bytes (exchange streams). */
16
41
  inputSchemaBytes: Uint8Array;
42
+ /** Unix epoch seconds at which the token was minted (used for TTL checks). */
17
43
  createdAt: number;
18
44
  }
19
45
  /**
20
- * Unpack and verify a state token.
21
- * Throws on tampered, expired, or malformed tokens.
46
+ * Open and verify a state token. Decryption (which checks the Poly1305
47
+ * tag) authenticates the payload; any tampering, wrong key, or AAD
48
+ * mismatch (e.g. cross-principal replay) surfaces as a uniform
49
+ * "signature verification failed" error so callers cannot distinguish
50
+ * failure modes via timing or message content.
51
+ *
52
+ * Throws on tampered, expired, malformed, or unknown-version tokens.
22
53
  */
23
- export declare function unpackStateToken(tokenBase64: string, signingKey: Uint8Array, tokenTtl: number): UnpackedToken;
54
+ export declare function unpackStateToken(tokenBase64: string, tokenKey: Uint8Array, tokenTtl: number, principal: string | null | undefined): UnpackedToken;
24
55
  //# sourceMappingURL=token.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/http/token.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,UAAU,EACvB,gBAAgB,EAAE,UAAU,EAC5B,UAAU,EAAE,UAAU,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAsCR;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,UAAU,CAAC;IACxB,gBAAgB,EAAE,UAAU,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAiE7G"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/http/token.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,CAU3E;AAMD,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMvD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAKrD;AAiCD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,UAAU,EACvB,gBAAgB,EAAE,UAAU,EAC5B,QAAQ,EAAE,UAAU,EACpB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CA8BR;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,UAAU,EAAE,UAAU,CAAC;IACvB,0CAA0C;IAC1C,WAAW,EAAE,UAAU,CAAC;IACxB,4DAA4D;IAC5D,gBAAgB,EAAE,UAAU,CAAC;IAC7B,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,aAAa,CAuEf"}