stitchkit 0.90.4 → 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.
- package/CHANGELOG.md +102 -0
- package/README.md +2 -0
- package/dist/agent-runtime-coding-tools.js +5 -4
- package/dist/agent-runtime-harness.js +6 -5
- package/dist/agent-runtime-sandbox.js +5 -4
- package/dist/agent-runtime.js +9 -8
- package/dist/application/grammy.d.ts.map +1 -1
- package/dist/application-grammy.js +4 -1
- package/dist/cli.js +62 -18
- package/dist/contract/index.js +2 -1
- package/dist/google.d.ts +56 -0
- package/dist/google.d.ts.map +1 -0
- package/dist/google.js +175 -0
- package/dist/{index-32vjke6q.js → index-1bnkzq95.js} +1 -1
- package/dist/{index-db51n3xr.js → index-640tz39q.js} +5 -5
- package/dist/{index-19ryv24q.js → index-83fafqw8.js} +3 -3
- package/dist/{index-z78bjcxj.js → index-aj9geeez.js} +1 -1
- package/dist/{index-bg8ypxzn.js → index-bva395we.js} +6 -7
- package/dist/{index-y47z614h.js → index-fqg5mfk7.js} +145 -32
- package/dist/index-hr4tzbwq.js +11 -0
- package/dist/{index-kazec06k.js → index-nrqg8tks.js} +5 -19
- package/dist/index-rxfy4cq7.js +17 -0
- package/dist/{index-6atvfjc1.js → index-s208wab5.js} +1 -1
- package/dist/{index-7t0wq6j5.js → index-tgh3ksfh.js} +5 -5
- package/dist/{index-6q3zjwaz.js → index-vy2nxwg8.js} +1 -1
- package/dist/{index-kzxpsf8y.js → index-zsdgd1tz.js} +1 -1
- package/dist/index.js +10 -9
- package/dist/internal/pkce.d.ts +3 -0
- package/dist/internal/pkce.d.ts.map +1 -0
- package/dist/node.js +5 -4
- package/dist/oauth.d.ts +57 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +170 -0
- package/dist/observability/index.js +3 -2
- package/dist/primitives.js +2 -1
- package/dist/remote.js +4 -3
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/index.js +14 -11
- package/dist/server/middleware/pkce.d.ts +1 -2
- package/dist/server/middleware/pkce.d.ts.map +1 -1
- package/dist/testing.js +5 -4
- package/dist/tool-invoker.js +7 -6
- package/dist/tools/cli-args.d.ts +10 -8
- package/dist/tools/cli-args.d.ts.map +1 -1
- package/dist/tools/cli-installer.d.ts +7 -2
- package/dist/tools/cli-installer.d.ts.map +1 -1
- package/dist/tools/cli-view.d.ts.map +1 -1
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools/connections/index.js +37 -4
- package/dist/tools/connections/mcp-envelope.d.ts +44 -0
- package/dist/tools/connections/mcp-envelope.d.ts.map +1 -0
- package/dist/tools/connections/mcp.d.ts.map +1 -1
- package/dist/tools.js +16 -14
- package/dist/tracking.js +3 -2
- package/llms-full.txt +224 -8
- package/llms.txt +1 -0
- package/package.json +36 -22
- package/dist/{index-8crm1srv.js → index-3yqgj323.js} +3 -3
- package/dist/{index-vcnfwrtr.js → index-8pjqv3zh.js} +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-envelope.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mcp-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAaxD;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,QAAQ,CAa1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAIhF,OAAO,EACL,KAAK,0BAA0B,EAIhC,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAQlE,gEAAgE;AAChE,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,mBAAmB,EAC/B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,0BAA0B,GACpC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAqElC"}
|
package/dist/tools.js
CHANGED
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
signJwt,
|
|
6
6
|
verifyPkce
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-bva395we.js";
|
|
8
|
+
import"./index-hr4tzbwq.js";
|
|
8
9
|
import {
|
|
9
10
|
DEFAULT_CORS_ALLOW_HEADERS,
|
|
10
11
|
DEFAULT_PROCESS_SIGNALS,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
guardSignalCallback,
|
|
14
15
|
mediaTypeEssence,
|
|
15
16
|
reportSignalError
|
|
16
|
-
} from "./index-
|
|
17
|
+
} from "./index-aj9geeez.js";
|
|
17
18
|
import {
|
|
18
19
|
redact
|
|
19
20
|
} from "./index-xbppf54a.js";
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
buildToolManifest,
|
|
22
23
|
describeToolCatalog,
|
|
23
24
|
mountAgent
|
|
24
|
-
} from "./index-
|
|
25
|
+
} from "./index-83fafqw8.js";
|
|
25
26
|
import"./index-7rkhw9ec.js";
|
|
26
27
|
import {
|
|
27
28
|
argumentsDigest
|
|
@@ -37,7 +38,7 @@ import {
|
|
|
37
38
|
} from "./index-4fpa9dy2.js";
|
|
38
39
|
import {
|
|
39
40
|
createToolInvoker
|
|
40
|
-
} from "./index-
|
|
41
|
+
} from "./index-tgh3ksfh.js";
|
|
41
42
|
import {
|
|
42
43
|
WaitTimeoutError,
|
|
43
44
|
createCli,
|
|
@@ -46,22 +47,22 @@ import {
|
|
|
46
47
|
fetchPinnedDocument,
|
|
47
48
|
readCapped,
|
|
48
49
|
runWaitOperation
|
|
49
|
-
} from "./index-
|
|
50
|
+
} from "./index-fqg5mfk7.js";
|
|
50
51
|
import"./index-sbdmyz75.js";
|
|
51
52
|
import {
|
|
52
53
|
collectToolSurface
|
|
53
|
-
} from "./index-
|
|
54
|
+
} from "./index-zsdgd1tz.js";
|
|
54
55
|
import {
|
|
55
56
|
collectTools,
|
|
56
57
|
createToolRunner,
|
|
57
58
|
formatToolError
|
|
58
|
-
} from "./index-
|
|
59
|
+
} from "./index-1bnkzq95.js";
|
|
59
60
|
import {
|
|
60
61
|
ToolExecutionControlError,
|
|
61
62
|
executeToolMethod,
|
|
62
63
|
isToolExecutionControlError,
|
|
63
64
|
toolResultFromError
|
|
64
|
-
} from "./index-
|
|
65
|
+
} from "./index-8pjqv3zh.js";
|
|
65
66
|
import {
|
|
66
67
|
getRequestContext,
|
|
67
68
|
getTraceId,
|
|
@@ -73,22 +74,18 @@ import {
|
|
|
73
74
|
} from "./index-2hryh65w.js";
|
|
74
75
|
import {
|
|
75
76
|
defineContract
|
|
76
|
-
} from "./index-
|
|
77
|
+
} from "./index-nrqg8tks.js";
|
|
78
|
+
import"./index-rxfy4cq7.js";
|
|
77
79
|
import {
|
|
78
80
|
ManagedFilePathSchema,
|
|
79
81
|
ManagedFileRefSchema
|
|
80
82
|
} from "./index-6k1937bx.js";
|
|
81
|
-
import {
|
|
82
|
-
AppError,
|
|
83
|
-
STITCH_ERROR_STATUS
|
|
84
|
-
} from "./index-scs3f1eg.js";
|
|
85
83
|
import {
|
|
86
84
|
resolvePropagationContext
|
|
87
85
|
} from "./index-zcgf3gqf.js";
|
|
88
86
|
import {
|
|
89
87
|
coerceJsonArgs
|
|
90
88
|
} from "./index-7zbps32p.js";
|
|
91
|
-
import"./index-kzfs85xp.js";
|
|
92
89
|
import {
|
|
93
90
|
createRuntimeToolFactory,
|
|
94
91
|
defineRuntimeTool
|
|
@@ -105,6 +102,11 @@ import {
|
|
|
105
102
|
validateMcpRoundPolicy
|
|
106
103
|
} from "./index-fenaekmk.js";
|
|
107
104
|
import"./index-cby4ar3v.js";
|
|
105
|
+
import {
|
|
106
|
+
AppError,
|
|
107
|
+
STITCH_ERROR_STATUS
|
|
108
|
+
} from "./index-scs3f1eg.js";
|
|
109
|
+
import"./index-kzfs85xp.js";
|
|
108
110
|
import {
|
|
109
111
|
isRecord
|
|
110
112
|
} from "./index-77fekveh.js";
|
package/dist/tracking.js
CHANGED
|
@@ -3,10 +3,11 @@ import {
|
|
|
3
3
|
} from "./index-3xwxfj4z.js";
|
|
4
4
|
import {
|
|
5
5
|
defineContract
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-nrqg8tks.js";
|
|
7
|
+
import"./index-rxfy4cq7.js";
|
|
7
8
|
import"./index-6k1937bx.js";
|
|
8
|
-
import"./index-scs3f1eg.js";
|
|
9
9
|
import"./index-zcgf3gqf.js";
|
|
10
|
+
import"./index-scs3f1eg.js";
|
|
10
11
|
import"./index-kzfs85xp.js";
|
|
11
12
|
import"./index-77fekveh.js";
|
|
12
13
|
|
package/llms-full.txt
CHANGED
|
@@ -64,6 +64,8 @@ own, recorded as an ADR.
|
|
|
64
64
|
| `stitchkit/tracking/server` | server (Bun or Node) | evolving | the decisions a tracking backend makes — dispositions, visit lease over an application-owned store, active intervals, presence; no database |
|
|
65
65
|
| `stitchkit/release` | browser **and** server | evolving | a page follows the release it was built for — `createReleaseMarker` on the server, `createReleaseWatcher` in the browser, the `X-Build-Id` header and a socket event between them |
|
|
66
66
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
67
|
+
| `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
|
|
68
|
+
| `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
|
|
67
69
|
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the 35 minors since 0.56.2, most recently 0.83.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
68
70
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the store and managed-resource conformance kits |
|
|
69
71
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
@@ -190,6 +192,8 @@ map — feature → packages:
|
|
|
190
192
|
| MCP Apps UI widgets | `@modelcontextprotocol/ext-apps` |
|
|
191
193
|
| React data layer (`stitchkit/react`) | `@tanstack/react-query` `react-query-kit` |
|
|
192
194
|
| MaxMind GeoIP (`stitchkit/geo`) | `maxmind` |
|
|
195
|
+
| Browser OAuth client (`stitchkit/oauth`) | — |
|
|
196
|
+
| Google OIDC verifier (`stitchkit/google`) | `google-auth-library` |
|
|
193
197
|
| **Socket.IO server on Bun** | `socket.io` `@socket.io/bun-engine` |
|
|
194
198
|
| **Socket.IO server on Node** | `socket.io` |
|
|
195
199
|
| Socket.IO client | `socket.io-client` (runtime peer; unrelated root declarations remain peer-free) |
|
|
@@ -226,6 +230,7 @@ package. MCP hosts and client E2E additionally install
|
|
|
226
230
|
- [MCP & agents](./mcp-and-agents.md) — contracts as AI tools.
|
|
227
231
|
- [Realtime](./realtime.md) — Socket.IO and the cache bridge.
|
|
228
232
|
- [Auth & errors](./auth-and-errors.md) — scopes, auth hooks, the error model.
|
|
233
|
+
- [Browser OAuth and Google OIDC](./oauth.md) — PKCE transaction and verified provider identity.
|
|
229
234
|
- [Testing & deployment](./testing-and-deployment.md).
|
|
230
235
|
- [API reference](../api/reference.md) — every export, by entrypoint.
|
|
231
236
|
|
|
@@ -7489,9 +7494,12 @@ same Zod schema an HTTP or MCP call does.
|
|
|
7489
7494
|
| `--quiet` | Suppress non-essential stderr output |
|
|
7490
7495
|
| `--dry-run` | Print the resolved call without executing |
|
|
7491
7496
|
| `--help`, `-h` | Usage — top-level or per-command flag table |
|
|
7497
|
+
| `--help <text>` | List only the commands matching a substring |
|
|
7492
7498
|
| `--count-by <field>` | Count records per distinct value — see [Aggregate views](#aggregate-views) |
|
|
7493
7499
|
| `--sum <f> [--by <g>]`| Total a numeric field, optionally grouped |
|
|
7494
|
-
| `--
|
|
7500
|
+
| `--sort <field>` | Order records by a field, largest first |
|
|
7501
|
+
| `--ascending` | Flip `--sort` to smallest first |
|
|
7502
|
+
| `--top <n>` | Keep the n leading entries of the view asked for |
|
|
7495
7503
|
| `--table <a,b>` | Render named fields as an aligned table |
|
|
7496
7504
|
|
|
7497
7505
|
stdout carries the result; structured errors and progress go to stderr. With
|
|
@@ -7502,6 +7510,34 @@ diagnostics remain ordinary stderr text. This keeps stdout pipeable and
|
|
|
7502
7510
|
`VALIDATION_ERROR → 1`, `UNAUTHORIZED → 2`, `FORBIDDEN → 3`, `NOT_FOUND → 4`,
|
|
7503
7511
|
…) — override per app with `exitCodes`.
|
|
7504
7512
|
|
|
7513
|
+
### A narrower question than "all of them"
|
|
7514
|
+
|
|
7515
|
+
On a discovered surface `--help` is the only way to learn what exists, and that
|
|
7516
|
+
can be two hundred commands. At that size the list stops being an answer: it
|
|
7517
|
+
scrolls past a person and costs an agent the same context an unfiltered result
|
|
7518
|
+
would. So there is a question between "one command" and "all of them":
|
|
7519
|
+
|
|
7520
|
+
```bash
|
|
7521
|
+
myapp --help broadcast # also: -h broadcast · help broadcast · --help=broadcast
|
|
7522
|
+
```
|
|
7523
|
+
|
|
7524
|
+
```
|
|
7525
|
+
Commands matching "broadcast" (3 of 205):
|
|
7526
|
+
broadcast_send Send a broadcast to every subscriber
|
|
7527
|
+
broadcast_cancel Stop a running broadcast
|
|
7528
|
+
announce_publish Publish an announcement as a broadcast
|
|
7529
|
+
```
|
|
7530
|
+
|
|
7531
|
+
The description is searched as well as the name, because the word someone knows
|
|
7532
|
+
is often in the sentence rather than the name — `announce_publish` above is
|
|
7533
|
+
matched that way. The count says what was left out.
|
|
7534
|
+
|
|
7535
|
+
**No match is an exit code**, not an empty success: `0` over an empty list reads
|
|
7536
|
+
as "there are none", which is a different statement from "none of these". It
|
|
7537
|
+
exits with whatever `NOT_FOUND` maps to (`4` by default). Bare `--help` is
|
|
7538
|
+
unchanged, and `--help=false` still means what it always did — the reserved
|
|
7539
|
+
boolean's negation — so one value never carries two meanings.
|
|
7540
|
+
|
|
7505
7541
|
## Application global options
|
|
7506
7542
|
|
|
7507
7543
|
`--json` and friends above are the framework's. An application usually has
|
|
@@ -7632,9 +7668,20 @@ myapp item_list --top 5 --by status # same view, written the other way ro
|
|
|
7632
7668
|
myapp item_list --table id,status # the one human-facing shape
|
|
7633
7669
|
```
|
|
7634
7670
|
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7671
|
+
Two words, one each: **`--by` groups, `--sort` orders.** That leaves `--top` a
|
|
7672
|
+
single meaning everywhere — *the n leading entries of the view you asked for* —
|
|
7673
|
+
so the question a CLI actually gets asked composes out of the parts:
|
|
7674
|
+
|
|
7675
|
+
```bash
|
|
7676
|
+
myapp item_list --top 5 --sort messages --table id,messages # the five biggest, as a table
|
|
7677
|
+
myapp item_list --sort messages --top 5 --json # the same five, as records
|
|
7678
|
+
myapp item_list --sort name --ascending # ordered the other way
|
|
7679
|
+
```
|
|
7680
|
+
|
|
7681
|
+
Groups come back largest first for the same reason. A record that carries no
|
|
7682
|
+
value for the sort field sorts **last in both directions**: it is not the
|
|
7683
|
+
smallest, it is not on the scale at all, and letting it lead an ascending list
|
|
7684
|
+
would answer a question nobody asked.
|
|
7638
7685
|
|
|
7639
7686
|
Three rules worth knowing before you rely on them:
|
|
7640
7687
|
|
|
@@ -7646,6 +7693,8 @@ Three rules worth knowing before you rely on them:
|
|
|
7646
7693
|
over an object with two array fields, is refused rather than guessed.
|
|
7647
7694
|
- **Without a view flag the output is byte-for-byte what it was.** The flags are
|
|
7648
7695
|
reserved CLI behaviour like `--json`; they never reach a tool argument.
|
|
7696
|
+
- **Ordering and grouping do not mix.** `--sort` with `--by`, `--count-by` or
|
|
7697
|
+
`--sum` is refused rather than given a second meaning.
|
|
7649
7698
|
|
|
7650
7699
|
A failed call still reports its own error and exit code. An aggregate over an
|
|
7651
7700
|
error is not an answer to the question that was asked.
|
|
@@ -7725,8 +7774,12 @@ import {
|
|
|
7725
7774
|
// otherwise everyone who already installed it never receives the fix.
|
|
7726
7775
|
assertCliPublishable(previous, next)
|
|
7727
7776
|
|
|
7728
|
-
// Serving:
|
|
7729
|
-
|
|
7777
|
+
// Serving: omit `asset` and one script covers every published target, selecting
|
|
7778
|
+
// by uname at run time — otherwise that dispatch is the last hand-written piece
|
|
7779
|
+
// of the install path, and every publisher writes the same x86_64 → x64 table.
|
|
7780
|
+
renderCliInstaller({ manifest, binaryName: 'myapp' })
|
|
7781
|
+
// Or pin one target explicitly:
|
|
7782
|
+
renderCliInstaller({ manifest, asset: selectCliBuildAsset(manifest, target), binaryName: 'myapp' })
|
|
7730
7783
|
|
|
7731
7784
|
// Checking: bounded, at most once per interval, silent on any failure.
|
|
7732
7785
|
const check = await checkCliUpdate({ manifestUrl, currentVersion, lastCheckedAt })
|
|
@@ -7772,6 +7825,28 @@ One unconvertible schema no longer takes the connection down with it. The tool
|
|
|
7772
7825
|
is skipped and **named** (`onSkippedTool`, or a stderr line by default), so a
|
|
7773
7826
|
surface of two hundred tools is not lost to one.
|
|
7774
7827
|
|
|
7828
|
+
**A remote refusal keeps its code.** A failed `tools/call` used to become a
|
|
7829
|
+
one-sentence `Error` with the result discarded, which cost three things at once:
|
|
7830
|
+
the code (so `exitCodes` had nothing to map and every remote failure exited `1`),
|
|
7831
|
+
the message the operator needed, and the error's own class — a plain `Error` is
|
|
7832
|
+
an *unexpected* error to the runner, so it printed a code frame of the framework
|
|
7833
|
+
bundle before the JSON failure and was then scrubbed to `INTERNAL_SERVER_ERROR`.
|
|
7834
|
+
A structured `{ error, details }` body is now relayed as the contract error it
|
|
7835
|
+
is, on every transport; anything else fails as `UPSTREAM_TOOL_ERROR` carrying
|
|
7836
|
+
what the server did send. Not `INTERNAL_SERVER_ERROR`, because nothing of ours
|
|
7837
|
+
broke.
|
|
7838
|
+
|
|
7839
|
+
**On the CLI a discovered command prints the answer, not the envelope.**
|
|
7840
|
+
`tools/call` returns `{ content: [...], structuredContent? }`, and an agent mount
|
|
7841
|
+
needs exactly that — the parts are what a model is shown. The CLI is different in
|
|
7842
|
+
kind, because the handler's value is what gets printed, piped and aggregated:
|
|
7843
|
+
handed the envelope, `--count-by status` groups the *content parts* and answers
|
|
7844
|
+
`no record carries the field "status" — available: text, type`. So the CLI
|
|
7845
|
+
transport unwraps, and only it: `structuredContent` when the server sent one, a
|
|
7846
|
+
lone text part when it parses as JSON, its text when it does not. Several parts,
|
|
7847
|
+
an image or audio pass through whole — picking one of many would be inventing an
|
|
7848
|
+
answer.
|
|
7849
|
+
|
|
7775
7850
|
|
|
7776
7851
|
## Auth parity
|
|
7777
7852
|
|
|
@@ -10028,6 +10103,118 @@ onError: (ctx, err) => {
|
|
|
10028
10103
|
```
|
|
10029
10104
|
|
|
10030
10105
|
|
|
10106
|
+
==============================================================================
|
|
10107
|
+
# Guide: OAuth & OpenID Connect (docs/guide/oauth.md)
|
|
10108
|
+
==============================================================================
|
|
10109
|
+
|
|
10110
|
+
# Browser OAuth and Google OIDC
|
|
10111
|
+
|
|
10112
|
+
Stitchkit separates the browser's Authorization Code + PKCE transaction from the server's
|
|
10113
|
+
provider credential verification. The application still owns navigation, users, account matching
|
|
10114
|
+
and merge policy, persistence, sessions, roles, unlink policy and UI.
|
|
10115
|
+
|
|
10116
|
+
## Supported profile
|
|
10117
|
+
|
|
10118
|
+
The current Google adapter supports one explicit profile: **web OpenID Connect Authorization Code
|
|
10119
|
+
with PKCE**. A browser performs a top-level redirect, an application backend exchanges the
|
|
10120
|
+
one-time code, and Stitchkit returns a verified identity. It is the redirect-based sign-in path;
|
|
10121
|
+
it is not a generic name for every Google identity or authorization mechanism.
|
|
10122
|
+
|
|
10123
|
+
Keep adjacent Google capabilities separate because their credentials, lifecycle and trust
|
|
10124
|
+
boundaries differ:
|
|
10125
|
+
|
|
10126
|
+
| Capability | Credential/result | Stitchkit support |
|
|
10127
|
+
| --- | --- | --- |
|
|
10128
|
+
| Web OIDC Authorization Code + PKCE | verified user identity | `stitchkit/oauth` + `stitchkit/google` |
|
|
10129
|
+
| Google Identity Services button, One Tap or FedCM | browser-delivered ID credential | not implemented |
|
|
10130
|
+
| Incremental authorization for Drive, Calendar or other Google APIs | access/refresh tokens and granted scopes | not implemented |
|
|
10131
|
+
| Installed Android, iOS or desktop application | platform client and system-browser callback | not implemented |
|
|
10132
|
+
| Limited-input/device authorization | device/user codes and polling lifecycle | not implemented |
|
|
10133
|
+
| Service account or workload identity | application identity, possibly domain-wide delegation | not implemented |
|
|
10134
|
+
|
|
10135
|
+
Do not add these as mode flags to `GoogleOidcClient`. Each future capability gets its own adapter
|
|
10136
|
+
and result type, while the provider-neutral PKCE transaction can be reused where its protocol
|
|
10137
|
+
actually applies. In particular, authentication establishes the person; authorization to Google
|
|
10138
|
+
APIs is requested later, in product context, and owns refresh-token persistence and revocation.
|
|
10139
|
+
|
|
10140
|
+
## Browser transaction
|
|
10141
|
+
|
|
10142
|
+
`stitchkit/oauth` is browser-safe and provider-neutral. It creates independent 32-byte `state`,
|
|
10143
|
+
`nonce` and PKCE verifier values, writes one versioned transaction to caller-provided storage and
|
|
10144
|
+
returns the authorization URL without navigating:
|
|
10145
|
+
|
|
10146
|
+
```ts
|
|
10147
|
+
import { createAuthorizationCodeClient, safeInternalReturnPath } from 'stitchkit/oauth'
|
|
10148
|
+
import { z } from 'zod'
|
|
10149
|
+
|
|
10150
|
+
const oauth = createAuthorizationCodeClient({
|
|
10151
|
+
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
10152
|
+
clientId,
|
|
10153
|
+
redirectUri: `${window.location.origin}/auth/google/callback`,
|
|
10154
|
+
scopes: ['openid', 'email', 'profile'],
|
|
10155
|
+
storage: window.sessionStorage,
|
|
10156
|
+
storageKey: 'app:google:oauth',
|
|
10157
|
+
contextSchema: z.object({ mode: z.enum(['login', 'link']), returnTo: z.string() }),
|
|
10158
|
+
authorizationParameters: { prompt: 'select_account' },
|
|
10159
|
+
})
|
|
10160
|
+
|
|
10161
|
+
const { authorizationUrl } = await oauth.begin({
|
|
10162
|
+
context: { mode: 'login', returnTo: '/account' },
|
|
10163
|
+
})
|
|
10164
|
+
window.location.assign(authorizationUrl)
|
|
10165
|
+
|
|
10166
|
+
// In the callback route. Reading is one-shot even when validation fails.
|
|
10167
|
+
const pending = oauth.consume({ state: new URL(location.href).searchParams.get('state') ?? '' })
|
|
10168
|
+
const returnTo = safeInternalReturnPath(pending.context.returnTo, '/')
|
|
10169
|
+
```
|
|
10170
|
+
|
|
10171
|
+
Provider parameters cannot replace protocol-owned fields. `consume` removes the pending value
|
|
10172
|
+
before parsing, version checking, context validation or state comparison, so a malformed callback
|
|
10173
|
+
and a React Strict Mode replay cannot reuse it. Errors expose a stable
|
|
10174
|
+
`AuthorizationCodeClientError.code` and never include transaction contents.
|
|
10175
|
+
|
|
10176
|
+
Token exchange, ID-token verification, credential persistence and application identity do not
|
|
10177
|
+
belong to this browser entrypoint.
|
|
10178
|
+
|
|
10179
|
+
## Google server adapter
|
|
10180
|
+
|
|
10181
|
+
Install the optional peer only in an application that imports `stitchkit/google`:
|
|
10182
|
+
|
|
10183
|
+
```bash
|
|
10184
|
+
bun add google-auth-library
|
|
10185
|
+
```
|
|
10186
|
+
|
|
10187
|
+
```ts
|
|
10188
|
+
import { createGoogleOidcClient } from 'stitchkit/google'
|
|
10189
|
+
|
|
10190
|
+
const google = createGoogleOidcClient({
|
|
10191
|
+
clientId: env.GOOGLE_CLIENT_ID,
|
|
10192
|
+
clientSecret: env.GOOGLE_CLIENT_SECRET,
|
|
10193
|
+
allowedRedirectUris: [env.GOOGLE_WEB_CALLBACK, env.GOOGLE_LOOPBACK_CALLBACK],
|
|
10194
|
+
timeoutMs: 10_000,
|
|
10195
|
+
})
|
|
10196
|
+
|
|
10197
|
+
const identity = await google.exchangeAuthorizationCode({
|
|
10198
|
+
code,
|
|
10199
|
+
codeVerifier: pending.codeVerifier,
|
|
10200
|
+
redirectUri: pending.redirectUri,
|
|
10201
|
+
nonce: pending.nonce,
|
|
10202
|
+
})
|
|
10203
|
+
// { subject, email, name?, picture? }
|
|
10204
|
+
```
|
|
10205
|
+
|
|
10206
|
+
The redirect must match the immutable allowlist exactly before any outbound call. The token
|
|
10207
|
+
exchange is bounded by an abort deadline; `google-auth-library` verifies the ID-token signature,
|
|
10208
|
+
issuer, audience and expiry. Stitchkit additionally requires `sub`, a valid verified email and an
|
|
10209
|
+
exact nonce. Access, refresh and raw ID tokens never leave the adapter.
|
|
10210
|
+
|
|
10211
|
+
`GoogleOidcError.code` distinguishes `MISCONFIGURED`, `INVALID_CREDENTIAL` and
|
|
10212
|
+
`UPSTREAM_UNAVAILABLE` with fixed safe messages. Endpoints compose their own rate limiter and then
|
|
10213
|
+
map the verified identity into application-owned user/session policy. Offline access, Google API
|
|
10214
|
+
scopes, database writes, user lookup or merging, session rotation, roles and UI remain outside the
|
|
10215
|
+
adapter.
|
|
10216
|
+
|
|
10217
|
+
|
|
10031
10218
|
==============================================================================
|
|
10032
10219
|
# Guide: Observability (docs/guide/observability.md)
|
|
10033
10220
|
==============================================================================
|
|
@@ -17093,6 +17280,35 @@ adapter is used.
|
|
|
17093
17280
|
|
|
17094
17281
|
---
|
|
17095
17282
|
|
|
17283
|
+
## `stitchkit/oauth`
|
|
17284
|
+
|
|
17285
|
+
Browser-safe, provider-neutral Authorization Code + PKCE transaction mechanics. Navigation,
|
|
17286
|
+
token exchange, identity and sessions remain application-owned. See the [OAuth guide](../guide/oauth.md).
|
|
17287
|
+
|
|
17288
|
+
| Export | Kind | Summary |
|
|
17289
|
+
|--------|------|---------|
|
|
17290
|
+
| `createAuthorizationCodeClient` / `AuthorizationCodeClient` / `AuthorizationCodeClientConfig` | function / _type_ | begin one S256 authorization request and consume its versioned pending transaction exactly once |
|
|
17291
|
+
| `BeginAuthorizationCodeInput` / `BeginAuthorizationCodeResult` / `ConsumeAuthorizationCodeInput` / `ConsumedAuthorizationCode` | _type_ | inputs and safe protocol result around caller-validated context |
|
|
17292
|
+
| `AuthorizationCodeStorage` / `AuthorizationCodeCrypto` | _type_ | injected browser capabilities; neither is read at module initialisation |
|
|
17293
|
+
| `AuthorizationCodeClientError` / `AuthorizationCodeClientErrorCode` | class / _type_ | fixed safe failure codes for configuration, context, storage, transaction and state failures |
|
|
17294
|
+
| `safeInternalReturnPath` | function | accept only a single-slash current-origin path without backslashes or ASCII controls |
|
|
17295
|
+
|
|
17296
|
+
---
|
|
17297
|
+
|
|
17298
|
+
## `stitchkit/google`
|
|
17299
|
+
|
|
17300
|
+
Server-only Google code exchange and verified OIDC identity. This entry requires the optional
|
|
17301
|
+
`google-auth-library` peer. See the [OAuth guide](../guide/oauth.md).
|
|
17302
|
+
|
|
17303
|
+
| Export | Kind | Summary |
|
|
17304
|
+
|--------|------|---------|
|
|
17305
|
+
| `createGoogleOidcClient` / `GoogleOidcClient` / `GoogleOidcClientConfig` | function / _type_ | exact-redirect, deadline-bounded code exchange and verified identity projection |
|
|
17306
|
+
| `ExchangeGoogleAuthorizationCodeInput` / `GoogleOidcIdentity` / `GoogleOidcClaims` | _type_ | callback input, provider-neutral result and verifier seam claims |
|
|
17307
|
+
| `GoogleOidcExchangeInput` / `GoogleOidcTokenTransport` / `GoogleOidcIdTokenVerifier` | _type_ | injectable transport and verifier boundaries used by production and deterministic tests |
|
|
17308
|
+
| `GoogleOidcError` / `GoogleOidcErrorCode` | class / _type_ | safe `MISCONFIGURED`, `INVALID_CREDENTIAL` or retryable `UPSTREAM_UNAVAILABLE` failure |
|
|
17309
|
+
|
|
17310
|
+
---
|
|
17311
|
+
|
|
17096
17312
|
## `stitchkit/declaration`
|
|
17097
17313
|
|
|
17098
17314
|
Zod-only, dependency-free. The **project declaration**: the single
|
|
@@ -17224,11 +17440,11 @@ SDK nor the `ai` peer.
|
|
|
17224
17440
|
| `CliBuildAssetSchema` / `CliBuildAsset` | schema / _type_ | one download; `size` and `sha256` describe the **decompressed** bytes |
|
|
17225
17441
|
| `CliBuildTargetSchema` / `CliBuildTarget` | schema / _type_ | `{ platform, arch }` |
|
|
17226
17442
|
| `CliBuildStampSchema` / `CliBuildStamp` | schema / _type_ | the version/commit/build time carried inside a binary |
|
|
17227
|
-
| `CliInstallerConfig` | _type_ | manifest,
|
|
17443
|
+
| `CliInstallerConfig` | _type_ | manifest, binary name, default install directory, and an optional `asset` — omit it for one script that selects the target by `uname` |
|
|
17228
17444
|
| `CliUpdateCheckConfig` / `CliUpdateCheck` | _type_ | check inputs, and its four answers — `skipped`, `current`, `outdated`, `unknown` |
|
|
17229
17445
|
| `CliUpdateApplyConfig` / `AppliedCliUpdate` | _type_ | apply inputs and the replaced path, byte count and digest |
|
|
17230
17446
|
| `CliProfileStore` / `CliProfileStoreConfig` / `ResolvedCliProfile` | _type_ | the profile store, its directory/schema/hint config, and one resolution |
|
|
17231
|
-
| `CliResultView` | _type_ | the requested
|
|
17447
|
+
| `CliResultView` | _type_ | the requested view — `count`, `sum`, or `records` (ordered and/or table-rendered) |
|
|
17232
17448
|
| `CliViewOutput` | _type_ | a JSON value, or the one human-facing text shape |
|
|
17233
17449
|
| `CliGlobalOptionsParse` | _type_ | `{ argv, globals }` returned by `extractCliGlobalOptions` |
|
|
17234
17450
|
| `CliArgvRoute` | _type_ | `{ command, commandArgv, topLevelHelp, version, error? }` returned by `routeCliArgv` |
|
package/llms.txt
CHANGED
|
@@ -21,6 +21,7 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
|
|
|
21
21
|
- [Realtime](https://github.com/max-listov/stitchkit/blob/master/docs/guide/realtime.md): Socket.IO server/client wrappers, handshake auth, the cache bridge, a raw WebSocket lane
|
|
22
22
|
- [Live data](https://github.com/max-listov/stitchkit/blob/master/docs/guide/live.md): defineEvents beside the contract, watched reads shared by every subscriber, keyspaces with authoritative memory, and the trust fence
|
|
23
23
|
- [Auth & errors](https://github.com/max-listov/stitchkit/blob/master/docs/guide/auth-and-errors.md): scopes, createAuthHook, JWT/cookies, the AppError model, the stitch error-code registry
|
|
24
|
+
- [OAuth & OpenID Connect](https://github.com/max-listov/stitchkit/blob/master/docs/guide/oauth.md): browser Authorization Code + PKCE transactions and the optional Google OIDC server adapter
|
|
24
25
|
- [Observability](https://github.com/max-listov/stitchkit/blob/master/docs/guide/observability.md): request and tool-call observability, W3C trace context, createObservability
|
|
25
26
|
- [Testing & deployment](https://github.com/max-listov/stitchkit/blob/master/docs/guide/testing-and-deployment.md): in-process testing; deploying on Bun and on Node (serveNode)
|
|
26
27
|
- [Multi-tenant](https://github.com/max-listov/stitchkit/blob/master/docs/guide/multi-tenant.md): a /tenants/:id/… scenario end-to-end — scopePrefixes, scoped client, extend
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stitchkit",
|
|
3
|
-
"version": "0.90.
|
|
3
|
+
"version": "0.90.6",
|
|
4
4
|
"description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -185,6 +185,14 @@
|
|
|
185
185
|
"types": "./dist/geo.d.ts",
|
|
186
186
|
"import": "./dist/geo.js"
|
|
187
187
|
},
|
|
188
|
+
"./oauth": {
|
|
189
|
+
"types": "./dist/oauth.d.ts",
|
|
190
|
+
"import": "./dist/oauth.js"
|
|
191
|
+
},
|
|
192
|
+
"./google": {
|
|
193
|
+
"types": "./dist/google.d.ts",
|
|
194
|
+
"import": "./dist/google.js"
|
|
195
|
+
},
|
|
188
196
|
"./declaration": {
|
|
189
197
|
"types": "./dist/declaration.d.ts",
|
|
190
198
|
"import": "./dist/declaration.js"
|
|
@@ -202,7 +210,8 @@
|
|
|
202
210
|
"check": "bun x tsc --noEmit",
|
|
203
211
|
"build:js": "bun run build:entrypoints && bun scripts/preserve-webpack-ignore.mjs",
|
|
204
212
|
"build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly && bun scripts/rewrite-declaration-specifiers.mjs",
|
|
205
|
-
"build": "
|
|
213
|
+
"build": "bun ../../scripts/package-build-lock.ts -- bun run build:unlocked",
|
|
214
|
+
"build:unlocked": "rm -rf dist && cp ../../CHANGELOG.md ./CHANGELOG.md && bun run build:js && chmod +x dist/upgrade-cli.js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-browser-executes.mjs && bun scripts/check-env-live.mjs && bun scripts/check-public-types.mjs && bun scripts/check-declarations-strict.mjs",
|
|
206
215
|
"dev": "bun run build:entrypoints -- --watch",
|
|
207
216
|
"prepack": "cp ../../README.md ./README.md && bun ../../scripts/gen-llms.ts && bun run build",
|
|
208
217
|
"test": "bun test",
|
|
@@ -214,23 +223,24 @@
|
|
|
214
223
|
"build:entrypoints": "bun scripts/build-entrypoints.mjs"
|
|
215
224
|
},
|
|
216
225
|
"peerDependencies": {
|
|
217
|
-
"@modelcontextprotocol/ext-apps": "^1.7.2",
|
|
226
|
+
"@modelcontextprotocol/ext-apps": "^1.7.2 || ^2.0.0",
|
|
218
227
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
219
|
-
"@openrouter/ai-sdk-provider": "^3.
|
|
228
|
+
"@openrouter/ai-sdk-provider": "^3.1.0",
|
|
220
229
|
"@opentelemetry/api": "^1.9.0",
|
|
221
|
-
"@socket.io/bun-engine": "^0.1.
|
|
230
|
+
"@socket.io/bun-engine": "^0.1.2",
|
|
222
231
|
"@socket.io/component-emitter": "^3.1.2",
|
|
223
232
|
"@tanstack/react-query": ">=5",
|
|
224
|
-
"@types/bun": "^1.
|
|
225
|
-
"ai": "^7.0.
|
|
226
|
-
"grammy": "^1.
|
|
233
|
+
"@types/bun": "^1.4.2",
|
|
234
|
+
"ai": "^7.0.107",
|
|
235
|
+
"grammy": "^1.46.0",
|
|
236
|
+
"google-auth-library": "^11.1.0",
|
|
227
237
|
"maxmind": "^5.0.7",
|
|
228
238
|
"react": ">=18",
|
|
229
239
|
"react-query-kit": "^3.3.3",
|
|
230
240
|
"socket.io": "^4.8.3",
|
|
231
241
|
"socket.io-client": "^4.8.3",
|
|
232
|
-
"srvx": "^0.12.5",
|
|
233
|
-
"zod": "^4.
|
|
242
|
+
"srvx": "^0.12.5 || ^1.0.5",
|
|
243
|
+
"zod": "^4.6.5"
|
|
234
244
|
},
|
|
235
245
|
"peerDependenciesMeta": {
|
|
236
246
|
"@modelcontextprotocol/ext-apps": {
|
|
@@ -263,6 +273,9 @@
|
|
|
263
273
|
"grammy": {
|
|
264
274
|
"optional": true
|
|
265
275
|
},
|
|
276
|
+
"google-auth-library": {
|
|
277
|
+
"optional": true
|
|
278
|
+
},
|
|
266
279
|
"maxmind": {
|
|
267
280
|
"optional": true
|
|
268
281
|
},
|
|
@@ -283,30 +296,31 @@
|
|
|
283
296
|
}
|
|
284
297
|
},
|
|
285
298
|
"dependencies": {
|
|
286
|
-
"ky": "^2.0
|
|
299
|
+
"ky": "^2.1.0"
|
|
287
300
|
},
|
|
288
301
|
"devDependencies": {
|
|
289
302
|
"@modelcontextprotocol/client": "^2.0.0",
|
|
290
|
-
"@modelcontextprotocol/ext-apps": "^
|
|
303
|
+
"@modelcontextprotocol/ext-apps": "^2.0.0",
|
|
291
304
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
292
|
-
"@openrouter/ai-sdk-provider": "^3.
|
|
305
|
+
"@openrouter/ai-sdk-provider": "^3.1.0",
|
|
293
306
|
"@opentelemetry/api": "^1.9.0",
|
|
294
|
-
"@socket.io/bun-engine": "^0.1.
|
|
307
|
+
"@socket.io/bun-engine": "^0.1.2",
|
|
295
308
|
"@socket.io/component-emitter": "^3.1.2",
|
|
296
|
-
"@tanstack/react-query": "5.
|
|
297
|
-
"@types/bun": "^1.4.
|
|
309
|
+
"@tanstack/react-query": "5.103.1",
|
|
310
|
+
"@types/bun": "^1.4.2",
|
|
298
311
|
"@types/json-schema": "^7.0.15",
|
|
299
|
-
"@types/react": "^19.
|
|
312
|
+
"@types/react": "^19.3.0",
|
|
300
313
|
"@typescript/typescript6": "^6.0.2",
|
|
301
|
-
"ai": "^7.0.
|
|
314
|
+
"ai": "^7.0.107",
|
|
302
315
|
"fake-indexeddb": "^6.2.5",
|
|
303
|
-
"grammy": "^1.
|
|
304
|
-
"
|
|
316
|
+
"grammy": "^1.46.0",
|
|
317
|
+
"google-auth-library": "^11.1.0",
|
|
318
|
+
"react": "^19.3.0",
|
|
305
319
|
"react-query-kit": "^3.3.4",
|
|
306
320
|
"socket.io": "^4.8.3",
|
|
307
321
|
"socket.io-client": "^4.8.3",
|
|
308
|
-
"srvx": "^0.
|
|
322
|
+
"srvx": "^1.0.5",
|
|
309
323
|
"typescript": "^7.0.2",
|
|
310
|
-
"zod": "^4.
|
|
324
|
+
"zod": "^4.6.5"
|
|
311
325
|
}
|
|
312
326
|
}
|
|
@@ -18,13 +18,13 @@ import {
|
|
|
18
18
|
probeAgentProcessSandbox,
|
|
19
19
|
refuseMissingCodingPath
|
|
20
20
|
} from "./index-gte38nbm.js";
|
|
21
|
+
import {
|
|
22
|
+
defineRuntimeTool
|
|
23
|
+
} from "./index-8z9we758.js";
|
|
21
24
|
import {
|
|
22
25
|
conflict,
|
|
23
26
|
forbidden
|
|
24
27
|
} from "./index-scs3f1eg.js";
|
|
25
|
-
import {
|
|
26
|
-
defineRuntimeTool
|
|
27
|
-
} from "./index-8z9we758.js";
|
|
28
28
|
|
|
29
29
|
// src/agent-runtime/coding-tool-contract.ts
|
|
30
30
|
import { z } from "zod";
|
|
@@ -7,20 +7,20 @@ import {
|
|
|
7
7
|
normalizeError,
|
|
8
8
|
validateDeclaredOutput
|
|
9
9
|
} from "./index-2hryh65w.js";
|
|
10
|
+
import {
|
|
11
|
+
coerceJsonArgs
|
|
12
|
+
} from "./index-7zbps32p.js";
|
|
13
|
+
import {
|
|
14
|
+
objectShapeKeys
|
|
15
|
+
} from "./index-fenaekmk.js";
|
|
10
16
|
import {
|
|
11
17
|
AppError,
|
|
12
18
|
STITCH_ERROR_STATUS,
|
|
13
19
|
isStitchErrorCode
|
|
14
20
|
} from "./index-scs3f1eg.js";
|
|
15
|
-
import {
|
|
16
|
-
coerceJsonArgs
|
|
17
|
-
} from "./index-7zbps32p.js";
|
|
18
21
|
import {
|
|
19
22
|
isUnsafeKey
|
|
20
23
|
} from "./index-kzfs85xp.js";
|
|
21
|
-
import {
|
|
22
|
-
objectShapeKeys
|
|
23
|
-
} from "./index-fenaekmk.js";
|
|
24
24
|
import {
|
|
25
25
|
isRecord
|
|
26
26
|
} from "./index-77fekveh.js";
|