stitchkit 0.90.5 → 0.90.6

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 (41) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +2 -0
  3. package/dist/agent-runtime-coding-tools.js +2 -1
  4. package/dist/agent-runtime-harness.js +2 -1
  5. package/dist/agent-runtime-sandbox.js +2 -1
  6. package/dist/agent-runtime.js +2 -1
  7. package/dist/application/grammy.d.ts.map +1 -1
  8. package/dist/application-grammy.js +4 -1
  9. package/dist/cli.js +2 -1
  10. package/dist/contract/index.js +2 -1
  11. package/dist/google.d.ts +56 -0
  12. package/dist/google.d.ts.map +1 -0
  13. package/dist/google.js +175 -0
  14. package/dist/{index-ra6txecz.js → index-640tz39q.js} +2 -2
  15. package/dist/{index-z78bjcxj.js → index-aj9geeez.js} +1 -1
  16. package/dist/{index-bg8ypxzn.js → index-bva395we.js} +6 -7
  17. package/dist/index-hr4tzbwq.js +11 -0
  18. package/dist/{index-kazec06k.js → index-nrqg8tks.js} +5 -19
  19. package/dist/index-rxfy4cq7.js +17 -0
  20. package/dist/{index-6q3zjwaz.js → index-vy2nxwg8.js} +1 -1
  21. package/dist/index.js +3 -2
  22. package/dist/internal/pkce.d.ts +3 -0
  23. package/dist/internal/pkce.d.ts.map +1 -0
  24. package/dist/node.js +4 -3
  25. package/dist/oauth.d.ts +57 -0
  26. package/dist/oauth.d.ts.map +1 -0
  27. package/dist/oauth.js +170 -0
  28. package/dist/observability/index.js +2 -1
  29. package/dist/primitives.js +2 -1
  30. package/dist/remote.js +3 -2
  31. package/dist/server/bun.d.ts.map +1 -1
  32. package/dist/server/index.js +9 -6
  33. package/dist/server/middleware/pkce.d.ts +1 -2
  34. package/dist/server/middleware/pkce.d.ts.map +1 -1
  35. package/dist/testing.js +3 -2
  36. package/dist/tool-invoker.js +2 -1
  37. package/dist/tools.js +5 -3
  38. package/dist/tracking.js +2 -1
  39. package/llms-full.txt +146 -0
  40. package/llms.txt +1 -0
  41. package/package.json +36 -22
package/CHANGELOG.md CHANGED
@@ -15,6 +15,40 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.90.6] — 2026-09-20
19
+
20
+ ### Added
21
+
22
+ - **Browser Authorization Code + PKCE transactions in `stitchkit/oauth`.** The new
23
+ browser-safe entrypoint creates authorization URLs, stores one-time state and
24
+ verifier records, and consumes callbacks with bounded expiry, replay protection,
25
+ safe return paths and provider errors that do not expose credentials.
26
+ - **A Google OpenID Connect server adapter in `stitchkit/google`.** It exchanges an
27
+ authorization code through the official optional `google-auth-library` peer,
28
+ requires an exact redirect allowlist, validates issuer, audience, expiry and nonce,
29
+ and returns a small stable identity without leaking tokens into application state.
30
+
31
+ ### Fixed
32
+
33
+ - **Unix-socket servers no longer forward Bun's TCP-only `http2` option.** The Unix
34
+ variant now strips it beside the other transport-specific settings.
35
+ - **grammY startup accepts the native application abort signal on its Node typing
36
+ boundary.** Runtime cancellation was already compatible; the adapter now makes that
37
+ compatibility explicit instead of failing consumer type-checks.
38
+ - **The lane temporary-directory test is isolated from concurrent lanes.** Its real
39
+ default-path proof runs in a child process with a private system temp root, removing
40
+ the full-suite timeout caused by scanning unrelated live descriptors.
41
+ - **Concurrent packed lanes serialize the shared core build.** Two release lanes can no
42
+ longer clean `dist` underneath each other's `prepack`, which previously produced a
43
+ JavaScript-only tarball during a parallel full gate.
44
+
45
+ ### Changed
46
+
47
+ - **Supported dependencies and consumer fixtures track current stable releases.** The
48
+ MCP Apps peer accepts both the existing 1.x line and current 2.x, while development
49
+ and optional-peer lanes exercise 2.x; the `srvx` peer likewise keeps its supported
50
+ 0.12 line while adding 1.x.
51
+
18
52
  ## [0.90.5] — 2026-09-16
19
53
 
20
54
  Three gaps a consuming project found on the first live surface after adopting
package/README.md CHANGED
@@ -78,6 +78,7 @@ import { createSocketIOClient } from 'stitchkit'
78
78
  import { createCursorQuery, createCacheBridge } from 'stitchkit/react'
79
79
  import { AgentRunSchema, AgentRuntimeEventSchema } from 'stitchkit/agent-runtime/browser'
80
80
  import { parseSSE } from 'stitchkit'
81
+ import { createAuthorizationCodeClient } from 'stitchkit/oauth'
81
82
  ```
82
83
 
83
84
  Server code imports server entrypoints:
@@ -90,6 +91,7 @@ import { createAgentRuntime, defineAgentProtocol } from 'stitchkit/agent-runtime
90
91
  import { createBunSqliteAgentRuntimeStore } from 'stitchkit/agent-runtime/sqlite/bun'
91
92
  import { createApplication, defineManagedResource } from 'stitchkit/application'
92
93
  import { implementRemote } from 'stitchkit/remote'
94
+ import { createGoogleOidcClient } from 'stitchkit/google'
93
95
  ```
94
96
 
95
97
  The root `stitchkit` entrypoint is browser-safe. Server, tool, optional managed
@@ -6,7 +6,8 @@ import {
6
6
  } from "./index-3yqgj323.js";
7
7
  import"./index-bn2cjajt.js";
8
8
  import"./index-gte38nbm.js";
9
- import"./index-kazec06k.js";
9
+ import"./index-nrqg8tks.js";
10
+ import"./index-rxfy4cq7.js";
10
11
  import"./index-6k1937bx.js";
11
12
  import"./index-8z9we758.js";
12
13
  import"./index-fenaekmk.js";
@@ -23,7 +23,8 @@ import"./index-8pjqv3zh.js";
23
23
  import"./index-vsbzgd7b.js";
24
24
  import"./index-f9mb610r.js";
25
25
  import"./index-2hryh65w.js";
26
- import"./index-kazec06k.js";
26
+ import"./index-nrqg8tks.js";
27
+ import"./index-rxfy4cq7.js";
27
28
  import"./index-6k1937bx.js";
28
29
  import"./index-zcgf3gqf.js";
29
30
  import"./index-7zbps32p.js";
@@ -7,7 +7,8 @@ import {
7
7
  missingSandboxRestrictions,
8
8
  probeAgentProcessSandbox
9
9
  } from "./index-gte38nbm.js";
10
- import"./index-kazec06k.js";
10
+ import"./index-nrqg8tks.js";
11
+ import"./index-rxfy4cq7.js";
11
12
  import"./index-6k1937bx.js";
12
13
  import"./index-8z9we758.js";
13
14
  import"./index-fenaekmk.js";
@@ -177,7 +177,8 @@ import"./index-8pjqv3zh.js";
177
177
  import"./index-vsbzgd7b.js";
178
178
  import"./index-f9mb610r.js";
179
179
  import"./index-2hryh65w.js";
180
- import"./index-kazec06k.js";
180
+ import"./index-nrqg8tks.js";
181
+ import"./index-rxfy4cq7.js";
181
182
  import"./index-6k1937bx.js";
182
183
  import {
183
184
  childSpan,
@@ -1 +1 @@
1
- {"version":3,"file":"grammy.d.ts","sourceRoot":"","sources":["../../src/application/grammy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAMzE,MAAM,WAAW,2BAA2B,CAAC,CAAC,SAAS,OAAO;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAcD,iEAAiE;AACjE,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,OAAO,EACrD,MAAM,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACrC,eAAe,CAiEjB;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9F,MAAM,WAAW,2BAA2B,CAAC,CAAC,SAAS,OAAO;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,OAAO;IACtD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,YAAY,CACV,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,oBAAoB,CAAC,EAAE,oBAAoB,GAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,6BAA8B,SAAQ,QAAQ,CAAC,8BAA8B,CAAC;IACzF,cAOC;CACF;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,OAAO,EAC3D,MAAM,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACrC,qBAAqB,CAAC,CAAC,CAAC,CAiE1B"}
1
+ {"version":3,"file":"grammy.d.ts","sourceRoot":"","sources":["../../src/application/grammy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAMzE,MAAM,WAAW,2BAA2B,CAAC,CAAC,SAAS,OAAO;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAcD,iEAAiE;AACjE,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,OAAO,EACrD,MAAM,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACrC,eAAe,CAiEjB;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9F,MAAM,WAAW,2BAA2B,CAAC,CAAC,SAAS,OAAO;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,OAAO;IACtD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,YAAY,CACV,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,oBAAoB,CAAC,EAAE,oBAAoB,GAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAaD;;;;;;;;;;;GAWG;AACH,qBAAa,6BAA8B,SAAQ,QAAQ,CAAC,8BAA8B,CAAC;IACzF,cAOC;CACF;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,OAAO,EAC3D,MAAM,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACrC,qBAAqB,CAAC,CAAC,CAAC,CAiE1B"}
@@ -86,6 +86,9 @@ function grammyPollingResource(config) {
86
86
  }
87
87
  });
88
88
  }
89
+ function grammyNodeSignal(signal) {
90
+ return signal;
91
+ }
89
92
 
90
93
  class GrammyWebhookUnavailableError extends AppError {
91
94
  constructor() {
@@ -115,7 +118,7 @@ function createGrammyWebhookResource(config) {
115
118
  ...config.dependsOn && { dependsOn: config.dependsOn },
116
119
  ...config.required !== undefined && { required: config.required },
117
120
  async start(context) {
118
- await config.bot.init(context.signal);
121
+ await config.bot.init(grammyNodeSignal(context.signal));
119
122
  },
120
123
  activate() {
121
124
  accepting = true;
package/dist/cli.js CHANGED
@@ -19,7 +19,8 @@ import"./index-8pjqv3zh.js";
19
19
  import"./index-vsbzgd7b.js";
20
20
  import"./index-f9mb610r.js";
21
21
  import"./index-2hryh65w.js";
22
- import"./index-kazec06k.js";
22
+ import"./index-nrqg8tks.js";
23
+ import"./index-rxfy4cq7.js";
23
24
  import"./index-6k1937bx.js";
24
25
  import"./index-zcgf3gqf.js";
25
26
  import {
@@ -8,7 +8,8 @@ import {
8
8
  defineErrors,
9
9
  encodeCursor,
10
10
  paginatedSchema
11
- } from "../index-kazec06k.js";
11
+ } from "../index-nrqg8tks.js";
12
+ import"../index-rxfy4cq7.js";
12
13
  import {
13
14
  ManagedFilePathSchema,
14
15
  ManagedFileRefSchema
@@ -0,0 +1,56 @@
1
+ export type GoogleOidcErrorCode = 'MISCONFIGURED' | 'INVALID_CREDENTIAL' | 'UPSTREAM_UNAVAILABLE';
2
+ export declare class GoogleOidcError extends Error {
3
+ readonly code: GoogleOidcErrorCode;
4
+ readonly retryable: boolean;
5
+ constructor(code: GoogleOidcErrorCode, options?: ErrorOptions);
6
+ }
7
+ export interface GoogleOidcIdentity {
8
+ subject: string;
9
+ email: string;
10
+ name?: string;
11
+ picture?: string;
12
+ }
13
+ export interface GoogleOidcClaims {
14
+ sub?: string;
15
+ email?: string;
16
+ emailVerified?: boolean;
17
+ nonce?: string;
18
+ name?: string;
19
+ picture?: string;
20
+ }
21
+ export interface GoogleOidcExchangeInput {
22
+ code: string;
23
+ codeVerifier: string;
24
+ redirectUri: string;
25
+ clientId: string;
26
+ clientSecret: string;
27
+ tokenEndpoint: string;
28
+ signal: AbortSignal;
29
+ }
30
+ export type GoogleOidcTokenTransport = (input: GoogleOidcExchangeInput) => Promise<{
31
+ idToken: string;
32
+ }>;
33
+ export type GoogleOidcIdTokenVerifier = (input: {
34
+ idToken: string;
35
+ audience: string;
36
+ }) => Promise<GoogleOidcClaims>;
37
+ export interface GoogleOidcClientConfig {
38
+ clientId: string;
39
+ clientSecret: string;
40
+ allowedRedirectUris: readonly string[];
41
+ timeoutMs?: number;
42
+ fetch?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
43
+ tokenTransport?: GoogleOidcTokenTransport;
44
+ idTokenVerifier?: GoogleOidcIdTokenVerifier;
45
+ }
46
+ export interface ExchangeGoogleAuthorizationCodeInput {
47
+ code: string;
48
+ codeVerifier: string;
49
+ redirectUri: string;
50
+ nonce: string;
51
+ }
52
+ export interface GoogleOidcClient {
53
+ exchangeAuthorizationCode(input: ExchangeGoogleAuthorizationCodeInput): Promise<GoogleOidcIdentity>;
54
+ }
55
+ export declare function createGoogleOidcClient(config: GoogleOidcClientConfig): GoogleOidcClient;
56
+ //# sourceMappingURL=google.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../src/google.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,oBAAoB,GACpB,sBAAsB,CAAC;AAQ3B,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B,YAAY,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,YAAY,EAK5D;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,MAAM,wBAAwB,GAAG,CACrC,KAAK,EAAE,uBAAuB,KAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAElC,MAAM,MAAM,yBAAyB,GAAG,CAAC,KAAK,EAAE;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAEhC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjF,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,eAAe,CAAC,EAAE,yBAAyB,CAAC;CAC7C;AAED,MAAM,WAAW,oCAAoC;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB,CACvB,KAAK,EAAE,oCAAoC,GAC1C,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAChC;AAqGD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,CAmFvF"}
package/dist/google.js ADDED
@@ -0,0 +1,175 @@
1
+ // src/google.ts
2
+ import { OAuth2Client } from "google-auth-library";
3
+ import { z } from "zod";
4
+ var DEFAULT_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token";
5
+ var DEFAULT_TIMEOUT_MS = 1e4;
6
+ var ERROR_MESSAGES = {
7
+ MISCONFIGURED: "Google OIDC is not configured correctly.",
8
+ INVALID_CREDENTIAL: "The Google credential is invalid.",
9
+ UPSTREAM_UNAVAILABLE: "Google identity verification is temporarily unavailable."
10
+ };
11
+
12
+ class GoogleOidcError extends Error {
13
+ code;
14
+ retryable;
15
+ constructor(code, options) {
16
+ super(ERROR_MESSAGES[code], options);
17
+ this.name = "GoogleOidcError";
18
+ this.code = code;
19
+ this.retryable = code === "UPSTREAM_UNAVAILABLE";
20
+ }
21
+ }
22
+ function recordOf(value) {
23
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? Object.fromEntries(Object.entries(value)) : null;
24
+ }
25
+ function statusOf(error) {
26
+ const record = recordOf(error);
27
+ const response = recordOf(record?.response);
28
+ return typeof response?.status === "number" ? response.status : null;
29
+ }
30
+ function codeOf(error) {
31
+ const record = recordOf(error);
32
+ return typeof record?.code === "string" ? record.code : null;
33
+ }
34
+ function upstreamVerifierFailure(error) {
35
+ const status = statusOf(error);
36
+ if (status !== null && (status === 429 || status >= 500))
37
+ return true;
38
+ return ["ECONNRESET", "ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND", "EAI_AGAIN"].includes(codeOf(error) ?? "");
39
+ }
40
+ function constantTimeEqual(left, right) {
41
+ const leftBytes = new TextEncoder().encode(left);
42
+ const rightBytes = new TextEncoder().encode(right);
43
+ if (leftBytes.length !== rightBytes.length)
44
+ return false;
45
+ let difference = 0;
46
+ for (let index = 0;index < leftBytes.length; index += 1) {
47
+ difference |= (leftBytes[index] ?? 0) ^ (rightBytes[index] ?? 0);
48
+ }
49
+ return difference === 0;
50
+ }
51
+ function defaultTokenTransport(fetcher) {
52
+ return async (input) => {
53
+ let response;
54
+ try {
55
+ response = await fetcher(input.tokenEndpoint, {
56
+ method: "POST",
57
+ headers: { "content-type": "application/x-www-form-urlencoded" },
58
+ body: new URLSearchParams({
59
+ grant_type: "authorization_code",
60
+ code: input.code,
61
+ code_verifier: input.codeVerifier,
62
+ redirect_uri: input.redirectUri,
63
+ client_id: input.clientId,
64
+ client_secret: input.clientSecret
65
+ }),
66
+ signal: input.signal
67
+ });
68
+ } catch {
69
+ throw new GoogleOidcError("UPSTREAM_UNAVAILABLE");
70
+ }
71
+ if (!response.ok) {
72
+ throw new GoogleOidcError(response.status === 429 || response.status >= 500 ? "UPSTREAM_UNAVAILABLE" : "INVALID_CREDENTIAL");
73
+ }
74
+ let body;
75
+ try {
76
+ body = await response.json();
77
+ } catch {
78
+ throw new GoogleOidcError("UPSTREAM_UNAVAILABLE");
79
+ }
80
+ const idToken = recordOf(body)?.id_token;
81
+ if (typeof idToken !== "string" || !idToken) {
82
+ throw new GoogleOidcError("INVALID_CREDENTIAL");
83
+ }
84
+ return { idToken };
85
+ };
86
+ }
87
+ function defaultIdTokenVerifier(clientId, clientSecret) {
88
+ const client = new OAuth2Client(clientId, clientSecret);
89
+ return async ({ idToken, audience }) => {
90
+ const ticket = await client.verifyIdToken({ idToken, audience });
91
+ const payload = ticket.getPayload();
92
+ if (!payload)
93
+ throw new GoogleOidcError("INVALID_CREDENTIAL");
94
+ return {
95
+ sub: payload.sub,
96
+ email: payload.email,
97
+ emailVerified: payload.email_verified,
98
+ nonce: payload.nonce,
99
+ name: payload.name,
100
+ picture: payload.picture
101
+ };
102
+ };
103
+ }
104
+ function createGoogleOidcClient(config) {
105
+ const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
106
+ if (!config.clientId || !config.clientSecret || config.allowedRedirectUris.length === 0 || config.allowedRedirectUris.some((uri) => !uri) || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
107
+ throw new GoogleOidcError("MISCONFIGURED");
108
+ }
109
+ const allowedRedirectUris = new Set(config.allowedRedirectUris);
110
+ const transport = config.tokenTransport ?? defaultTokenTransport(config.fetch ?? globalThis.fetch);
111
+ const verify = config.idTokenVerifier ?? defaultIdTokenVerifier(config.clientId, config.clientSecret);
112
+ return {
113
+ async exchangeAuthorizationCode(input) {
114
+ if (!allowedRedirectUris.has(input.redirectUri)) {
115
+ throw new GoogleOidcError("INVALID_CREDENTIAL");
116
+ }
117
+ if (!input.code || !input.codeVerifier || !input.nonce) {
118
+ throw new GoogleOidcError("INVALID_CREDENTIAL");
119
+ }
120
+ const controller = new AbortController;
121
+ let timer;
122
+ const deadline = new Promise((_, reject) => {
123
+ timer = setTimeout(() => {
124
+ controller.abort();
125
+ reject(new GoogleOidcError("UPSTREAM_UNAVAILABLE"));
126
+ }, timeoutMs);
127
+ });
128
+ let exchanged;
129
+ try {
130
+ exchanged = await Promise.race([
131
+ transport({
132
+ code: input.code,
133
+ codeVerifier: input.codeVerifier,
134
+ redirectUri: input.redirectUri,
135
+ clientId: config.clientId,
136
+ clientSecret: config.clientSecret,
137
+ tokenEndpoint: DEFAULT_TOKEN_ENDPOINT,
138
+ signal: controller.signal
139
+ }),
140
+ deadline
141
+ ]);
142
+ } catch (cause) {
143
+ if (cause instanceof GoogleOidcError)
144
+ throw cause;
145
+ throw new GoogleOidcError("UPSTREAM_UNAVAILABLE");
146
+ } finally {
147
+ if (timer)
148
+ clearTimeout(timer);
149
+ }
150
+ if (!exchanged.idToken)
151
+ throw new GoogleOidcError("INVALID_CREDENTIAL");
152
+ let claims;
153
+ try {
154
+ claims = await verify({ idToken: exchanged.idToken, audience: config.clientId });
155
+ } catch (cause) {
156
+ if (cause instanceof GoogleOidcError)
157
+ throw cause;
158
+ throw new GoogleOidcError(upstreamVerifierFailure(cause) ? "UPSTREAM_UNAVAILABLE" : "INVALID_CREDENTIAL");
159
+ }
160
+ if (!claims.sub || !claims.email || claims.emailVerified !== true || !claims.nonce || !constantTimeEqual(claims.nonce, input.nonce) || !z.email().safeParse(claims.email).success) {
161
+ throw new GoogleOidcError("INVALID_CREDENTIAL");
162
+ }
163
+ return {
164
+ subject: claims.sub,
165
+ email: claims.email,
166
+ ...claims.name ? { name: claims.name } : {},
167
+ ...claims.picture ? { picture: claims.picture } : {}
168
+ };
169
+ }
170
+ };
171
+ }
172
+ export {
173
+ createGoogleOidcClient,
174
+ GoogleOidcError
175
+ };
@@ -22,7 +22,7 @@ import {
22
22
  isOriginAllowed,
23
23
  mediaTypeEssence,
24
24
  reportSignalError
25
- } from "./index-z78bjcxj.js";
25
+ } from "./index-aj9geeez.js";
26
26
  import {
27
27
  getRequestContext,
28
28
  runWithRequestContext,
@@ -46,7 +46,7 @@ import {
46
46
  DEFAULT_CONTRACT_STREAM_FRAME_BYTES,
47
47
  joinRoutePath,
48
48
  parseTrailingWildcard
49
- } from "./index-kazec06k.js";
49
+ } from "./index-nrqg8tks.js";
50
50
  import {
51
51
  resolveTraceContext
52
52
  } from "./index-zcgf3gqf.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  mergeMeta,
3
3
  resolveRouteParamsSchema
4
- } from "./index-kazec06k.js";
4
+ } from "./index-nrqg8tks.js";
5
5
  import {
6
6
  isUnsafeKey
7
7
  } from "./index-kzfs85xp.js";
@@ -1,12 +1,15 @@
1
+ import {
2
+ deriveCodeChallenge
3
+ } from "./index-hr4tzbwq.js";
1
4
  import {
2
5
  contextContributionDelta,
3
6
  mergeContextContribution,
4
7
  prepareContextContribution
5
- } from "./index-z78bjcxj.js";
8
+ } from "./index-aj9geeez.js";
6
9
  import {
7
10
  base64UrlToBytes,
8
11
  bytesToBase64Url
9
- } from "./index-kazec06k.js";
12
+ } from "./index-rxfy4cq7.js";
10
13
  import {
11
14
  forbidden,
12
15
  unauthorized
@@ -312,10 +315,6 @@ function createBearerResolver(config) {
312
315
  }
313
316
 
314
317
  // src/server/middleware/pkce.ts
315
- async function deriveCodeChallenge(verifier) {
316
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
317
- return bytesToBase64Url(new Uint8Array(digest));
318
- }
319
318
  async function verifyPkce(verifier, challenge) {
320
319
  if (!verifier || !challenge)
321
320
  return false;
@@ -323,4 +322,4 @@ async function verifyPkce(verifier, challenge) {
323
322
  return derived === challenge;
324
323
  }
325
324
 
326
- export { parseCookieHeader, parseCookies, serializeCookie, defineCookie, verifyJwt, signJwt, extractToken, createAuthHook, composeAuthHooks, createBearerResolver, deriveCodeChallenge, verifyPkce };
325
+ export { parseCookieHeader, parseCookies, serializeCookie, defineCookie, verifyJwt, signJwt, extractToken, createAuthHook, composeAuthHooks, createBearerResolver, verifyPkce };
@@ -0,0 +1,11 @@
1
+ import {
2
+ bytesToBase64Url
3
+ } from "./index-rxfy4cq7.js";
4
+
5
+ // src/internal/pkce.ts
6
+ async function deriveCodeChallenge(verifier, subtle = globalThis.crypto.subtle) {
7
+ const digest = await subtle.digest("SHA-256", new TextEncoder().encode(verifier));
8
+ return bytesToBase64Url(new Uint8Array(digest));
9
+ }
10
+
11
+ export { deriveCodeChallenge };
@@ -1,3 +1,7 @@
1
+ import {
2
+ base64UrlToBytes,
3
+ bytesToBase64Url
4
+ } from "./index-rxfy4cq7.js";
1
5
  import {
2
6
  AppError,
3
7
  STITCH_ERROR_STATUS,
@@ -422,24 +426,6 @@ function createContractFactory(config) {
422
426
  }
423
427
  // src/contract/pagination.ts
424
428
  import { z as z3 } from "zod";
425
-
426
- // src/internal/base64url.ts
427
- function bytesToBase64Url(bytes) {
428
- let binary = "";
429
- for (const byte of bytes)
430
- binary += String.fromCharCode(byte);
431
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
432
- }
433
- function base64UrlToBytes(segment) {
434
- if (!/^[A-Za-z0-9_-]*$/.test(segment) || segment.length % 4 === 1) {
435
- throw new Error("invalid base64url segment");
436
- }
437
- const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
438
- const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
439
- return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
440
- }
441
-
442
- // src/contract/pagination.ts
443
429
  function paginatedSchema(itemSchema) {
444
430
  return z3.object({
445
431
  items: z3.array(itemSchema),
@@ -481,4 +467,4 @@ var ContractStreamFrameSchema = z4.discriminatedUnion("type", [
481
467
  }).strict(),
482
468
  z4.object({ type: z4.literal("end") }).strict()
483
469
  ]);
484
- export { joinRoutePath, resolveRouteParamsSchema, parseTrailingWildcard, ALL_TRANSPORTS, defineContract, mergeMeta, defineErrors, createContractFactory, bytesToBase64Url, base64UrlToBytes, paginatedSchema, encodeCursor, decodeCursor, DEFAULT_CONTRACT_STREAM_FRAME_BYTES, ContractStreamFrameSchema };
470
+ export { joinRoutePath, resolveRouteParamsSchema, parseTrailingWildcard, ALL_TRANSPORTS, defineContract, mergeMeta, defineErrors, createContractFactory, paginatedSchema, encodeCursor, decodeCursor, DEFAULT_CONTRACT_STREAM_FRAME_BYTES, ContractStreamFrameSchema };
@@ -0,0 +1,17 @@
1
+ // src/internal/base64url.ts
2
+ function bytesToBase64Url(bytes) {
3
+ let binary = "";
4
+ for (const byte of bytes)
5
+ binary += String.fromCharCode(byte);
6
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
7
+ }
8
+ function base64UrlToBytes(segment) {
9
+ if (!/^[A-Za-z0-9_-]*$/.test(segment) || segment.length % 4 === 1) {
10
+ throw new Error("invalid base64url segment");
11
+ }
12
+ const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
13
+ const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
14
+ return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
15
+ }
16
+
17
+ export { bytesToBase64Url, base64UrlToBytes };
@@ -16,7 +16,7 @@ import {
16
16
  ContractStreamFrameSchema,
17
17
  DEFAULT_CONTRACT_STREAM_FRAME_BYTES,
18
18
  parseTrailingWildcard
19
- } from "./index-kazec06k.js";
19
+ } from "./index-nrqg8tks.js";
20
20
  import {
21
21
  isRecord,
22
22
  mapObject,
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  createUrlBuilder,
16
16
  createUrlBuilders,
17
17
  parseNDJSON
18
- } from "./index-6q3zjwaz.js";
18
+ } from "./index-vy2nxwg8.js";
19
19
  import {
20
20
  REALTIME_REJECTION_KEY,
21
21
  asRealtimeRejection,
@@ -60,7 +60,8 @@ import {
60
60
  defineErrors,
61
61
  encodeCursor,
62
62
  paginatedSchema
63
- } from "./index-kazec06k.js";
63
+ } from "./index-nrqg8tks.js";
64
+ import"./index-rxfy4cq7.js";
64
65
  import {
65
66
  ManagedFilePathSchema,
66
67
  ManagedFileRefSchema
@@ -0,0 +1,3 @@
1
+ /** Derive the RFC 7636 S256 challenge with the caller's Web Crypto implementation. */
2
+ export declare function deriveCodeChallenge(verifier: string, subtle?: Pick<SubtleCrypto, 'digest'>): Promise<string>;
3
+ //# sourceMappingURL=pkce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../src/internal/pkce.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAA4B,GAC9D,OAAO,CAAC,MAAM,CAAC,CAGjB"}
package/dist/node.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  createHandler,
6
6
  createSocketIOServer,
7
7
  createUnixClientTransport
8
- } from "./index-ra6txecz.js";
8
+ } from "./index-640tz39q.js";
9
9
  import"./index-y91ry9h2.js";
10
10
  import {
11
11
  ShutdownOptionsSchema,
@@ -24,11 +24,12 @@ import {
24
24
  createScopedImplementRegistry,
25
25
  implement,
26
26
  implementRegistry
27
- } from "./index-z78bjcxj.js";
27
+ } from "./index-aj9geeez.js";
28
28
  import"./index-vsbzgd7b.js";
29
29
  import"./index-f9mb610r.js";
30
30
  import"./index-2hryh65w.js";
31
- import"./index-kazec06k.js";
31
+ import"./index-nrqg8tks.js";
32
+ import"./index-rxfy4cq7.js";
32
33
  import"./index-6k1937bx.js";
33
34
  import"./index-zcgf3gqf.js";
34
35
  import {
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Browser-safe OAuth Authorization Code + PKCE mechanics.
3
+ *
4
+ * The application owns navigation, token exchange, identity, persistence,
5
+ * sessions, roles and account policy. This module owns one pending browser
6
+ * transaction and consumes it exactly once.
7
+ */
8
+ import type { z } from 'zod';
9
+ export type AuthorizationCodeClientErrorCode = 'INVALID_CONFIGURATION' | 'RESERVED_PARAMETER' | 'INVALID_CONTEXT' | 'STORAGE_FAILURE' | 'MISSING_TRANSACTION' | 'MALFORMED_TRANSACTION' | 'UNSUPPORTED_TRANSACTION_VERSION' | 'STATE_MISMATCH';
10
+ export declare class AuthorizationCodeClientError extends Error {
11
+ readonly code: AuthorizationCodeClientErrorCode;
12
+ constructor(code: AuthorizationCodeClientErrorCode, options?: ErrorOptions);
13
+ }
14
+ export interface AuthorizationCodeStorage {
15
+ getItem(key: string): string | null;
16
+ setItem(key: string, value: string): void;
17
+ removeItem(key: string): void;
18
+ }
19
+ export interface AuthorizationCodeCrypto {
20
+ getRandomValues(bytes: Uint8Array): Uint8Array;
21
+ subtle: Pick<SubtleCrypto, 'digest'>;
22
+ }
23
+ export interface AuthorizationCodeClientConfig<TContext> {
24
+ authorizationEndpoint: string;
25
+ clientId: string;
26
+ redirectUri: string;
27
+ scopes: readonly string[];
28
+ storage: AuthorizationCodeStorage;
29
+ storageKey: string;
30
+ contextSchema: z.ZodType<TContext>;
31
+ authorizationParameters?: Readonly<Record<string, string>>;
32
+ /** Web Crypto seam for deterministic tests. Defaults at call time, never module load. */
33
+ crypto?: AuthorizationCodeCrypto;
34
+ }
35
+ export interface BeginAuthorizationCodeInput<TContext> {
36
+ context: TContext;
37
+ }
38
+ export interface BeginAuthorizationCodeResult {
39
+ authorizationUrl: string;
40
+ }
41
+ export interface ConsumeAuthorizationCodeInput {
42
+ state: string;
43
+ }
44
+ export interface ConsumedAuthorizationCode<TContext> {
45
+ codeVerifier: string;
46
+ nonce: string;
47
+ redirectUri: string;
48
+ context: TContext;
49
+ }
50
+ export interface AuthorizationCodeClient<TContext> {
51
+ begin(input: BeginAuthorizationCodeInput<TContext>): Promise<BeginAuthorizationCodeResult>;
52
+ consume(input: ConsumeAuthorizationCodeInput): ConsumedAuthorizationCode<TContext>;
53
+ }
54
+ export declare function createAuthorizationCodeClient<TContext>(config: AuthorizationCodeClientConfig<TContext>): AuthorizationCodeClient<TContext>;
55
+ /** Keep a return target on the current origin, or use the caller's trusted fallback. */
56
+ export declare function safeInternalReturnPath(candidate: string | null | undefined, fallback: string): string;
57
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgB7B,MAAM,MAAM,gCAAgC,GACxC,uBAAuB,GACvB,oBAAoB,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,qBAAqB,GACrB,uBAAuB,GACvB,iCAAiC,GACjC,gBAAgB,CAAC;AAarB,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,EAAE,gCAAgC,CAAC;IAEhD,YAAY,IAAI,EAAE,gCAAgC,EAAE,OAAO,CAAC,EAAE,YAAY,EAIzE;CACF;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAAC;IAC/C,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,6BAA6B,CAAC,QAAQ;IACrD,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE,wBAAwB,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,uBAAuB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,yFAAyF;IACzF,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAED,MAAM,WAAW,2BAA2B,CAAC,QAAQ;IACnD,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB,CAAC,QAAQ;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB,CAAC,QAAQ;IAC/C,KAAK,CAAC,KAAK,EAAE,2BAA2B,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC3F,OAAO,CAAC,KAAK,EAAE,6BAA6B,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC;CACpF;AAmED,wBAAgB,6BAA6B,CAAC,QAAQ,EACpD,MAAM,EAAE,6BAA6B,CAAC,QAAQ,CAAC,GAC9C,uBAAuB,CAAC,QAAQ,CAAC,CAgFnC;AAED,wFAAwF;AACxF,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,QAAQ,EAAE,MAAM,GACf,MAAM,CAcR"}