stitchkit 0.110.5 → 0.111.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/dist/agent-runtime/branch-observations.d.ts +16 -16
- package/dist/agent-runtime/sandbox-broker.d.ts.map +1 -1
- package/dist/browser/stream.d.ts +3 -2
- package/dist/browser/stream.d.ts.map +1 -1
- package/dist/contract/runtime-context.d.ts +3 -1
- package/dist/contract/runtime-context.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/coding-tools.js +2 -2
- package/dist/entrypoints/agent-runtime/sandbox.js +15 -29
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +4 -4
- package/dist/entrypoints/agent-runtime/sqlite/node.js +4 -4
- package/dist/entrypoints/agent-runtime/testing.js +4 -4
- package/dist/entrypoints/agent-runtime.js +4 -4
- package/dist/entrypoints/bin/upgrade-cli.d.ts.map +1 -1
- package/dist/entrypoints/bin/upgrade-cli.js +123 -29
- package/dist/entrypoints/cli/publish.js +1 -1
- package/dist/entrypoints/cli.js +2 -2
- package/dist/entrypoints/http.d.ts +2 -0
- package/dist/entrypoints/http.d.ts.map +1 -1
- package/dist/entrypoints/http.js +5 -1
- package/dist/entrypoints/index.d.ts +1 -0
- package/dist/entrypoints/index.d.ts.map +1 -1
- package/dist/entrypoints/index.js +5 -1
- package/dist/entrypoints/node.d.ts +1 -0
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +3 -1
- package/dist/entrypoints/observability.js +24 -9
- package/dist/entrypoints/process.js +1 -1
- package/dist/entrypoints/remote.js +1 -1
- package/dist/entrypoints/server.d.ts +2 -0
- package/dist/entrypoints/server.d.ts.map +1 -1
- package/dist/entrypoints/server.js +79 -6
- package/dist/entrypoints/telegram.js +3 -3
- package/dist/entrypoints/testing.js +1 -1
- package/dist/entrypoints/tools/connections.js +16 -31
- package/dist/entrypoints/tools.js +39 -7
- package/dist/{index-mpg1t7nv.js → index-0z3kfphz.js} +1 -1
- package/dist/{index-jk44mbqb.js → index-1y0arq4z.js} +3 -57
- package/dist/{index-5pbtbce0.js → index-7c957abz.js} +1 -1
- package/dist/{index-e1sjcjfy.js → index-7r4knwf8.js} +94 -23
- package/dist/index-cjbn98zt.js +68 -0
- package/dist/{index-bm180f2d.js → index-ey15wx6j.js} +1 -1
- package/dist/{index-s0xbnpfh.js → index-kdnfe0sr.js} +1 -1
- package/dist/{index-s6d8zsha.js → index-krng2a5j.js} +64 -110
- package/dist/{index-9ket8wzx.js → index-mnk5vgdr.js} +1 -1
- package/dist/index-qndsr7f0.js +55 -0
- package/dist/{index-n7hrpngg.js → index-syzngt7v.js} +1 -1
- package/dist/{index-3h0ztg0z.js → index-t65erk4z.js} +5 -21
- package/dist/internal/bounded-body.d.ts +44 -0
- package/dist/internal/bounded-body.d.ts.map +1 -0
- package/dist/internal/bounded-lines.d.ts +1 -2
- package/dist/internal/bounded-lines.d.ts.map +1 -1
- package/dist/internal/secure-fetch.d.ts.map +1 -1
- package/dist/internal/stream-chunks.d.ts +13 -0
- package/dist/internal/stream-chunks.d.ts.map +1 -0
- package/dist/internal/upgrade-affects.d.ts +5 -0
- package/dist/internal/upgrade-affects.d.ts.map +1 -1
- package/dist/internal/upgrade-plan.d.ts +18 -3
- package/dist/internal/upgrade-plan.d.ts.map +1 -1
- package/dist/internal/upgrade-usage.d.ts +21 -5
- package/dist/internal/upgrade-usage.d.ts.map +1 -1
- package/dist/observability/audit.d.ts +10 -0
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/event.d.ts +5 -0
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/process/group-diagnostics.d.ts +20 -0
- package/dist/process/group-diagnostics.d.ts.map +1 -0
- package/dist/process/group-settlement.d.ts +1 -1
- package/dist/process/group-settlement.d.ts.map +1 -1
- package/dist/process/group.d.ts.map +1 -1
- package/dist/server/bun.d.ts +9 -0
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/oauth/endpoints.d.ts.map +1 -1
- package/dist/server/oauth/provider.d.ts +5 -0
- package/dist/server/oauth/provider.d.ts.map +1 -1
- package/dist/server/proxy-origin.d.ts +12 -0
- package/dist/server/proxy-origin.d.ts.map +1 -0
- package/dist/server/raw.d.ts +6 -3
- package/dist/server/raw.d.ts.map +1 -1
- package/dist/server/request-body.d.ts.map +1 -1
- package/dist/server/request-completion.d.ts.map +1 -1
- package/dist/server/request-ingress.d.ts +31 -0
- package/dist/server/request-ingress.d.ts.map +1 -0
- package/dist/server/unix-client-body.d.ts.map +1 -1
- package/dist/tools/connections/limits.d.ts.map +1 -1
- package/llms/http.txt +3 -0
- package/llms/observability.txt +19 -2
- package/llms/server.2.txt +135 -0
- package/llms/server.5.txt +3 -1
- package/llms/server.txt +97 -131
- package/llms/stitchkit.2.txt +28 -0
- package/llms/stitchkit.txt +3 -3
- package/llms/tools.3.txt +1 -1
- package/llms/tools.txt +4 -0
- package/llms/{upgrading-0.101.0-0.110.0.txt → upgrading-0.101.0-0.111.0.txt} +29 -3
- package/llms/upgrading.txt +8 -2
- package/llms-full.txt +192 -8
- package/llms.txt +6 -6
- package/package.json +1 -1
package/llms-full.txt
CHANGED
|
@@ -77,12 +77,12 @@ own, recorded as an ADR.
|
|
|
77
77
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
78
78
|
| `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
|
|
79
79
|
| `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
|
|
80
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the
|
|
80
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the 56 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
81
81
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, the managed-resource conformance kit and manual time for schedules and retries |
|
|
82
82
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
83
83
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
84
84
|
| `stitchkit/react/keyboard` | browser | evolving | which part of a screen gets a key — ordered layers, one Escape per level, list zones with real focus; see [keyboard guide](keyboard.md) |
|
|
85
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 23 of the
|
|
85
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 23 of the 56 minors since 0.56.2, most recently 0.105.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
86
86
|
| `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
|
|
87
87
|
| `stitchkit/agent-runtime/testing` | tests on Bun or Node | evolving | credential-free replay, scripted provider faults, deterministic race controls and the agent-store conformance kit |
|
|
88
88
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
@@ -94,7 +94,7 @@ own, recorded as an ADR.
|
|
|
94
94
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
95
95
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
96
96
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
97
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 14 of the
|
|
97
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 14 of the 56 minors since 0.56.2, most recently 0.110.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
98
98
|
| `stitchkit/application/grammy` | server | evolving | a grammY bot as application resources — configuration, then polling with updates admitted by batch — and the webhook adapter |
|
|
99
99
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
100
100
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
|
@@ -1162,6 +1162,48 @@ Every handler receives one `ctx` argument:
|
|
|
1162
1162
|
The same handler runs for HTTP, MCP and agent calls — `ctx.source` tells you
|
|
1163
1163
|
which. Anything an auth hook attaches (e.g. the resolved user) is also on `ctx`.
|
|
1164
1164
|
|
|
1165
|
+
### Request attributes from the ingress
|
|
1166
|
+
|
|
1167
|
+
When your own code builds the `Request` — a local socket ingress, a relay, a test harness —
|
|
1168
|
+
and calls the fetch handler of the core, it often knows something an endpoint needs and the
|
|
1169
|
+
request cannot be allowed to say for itself: which authenticated peer sent it. A header can be
|
|
1170
|
+
forged by any client. `defineRequestIngress` is the channel the request cannot carry:
|
|
1171
|
+
|
|
1172
|
+
```ts
|
|
1173
|
+
import { createHandler, defineRequestIngress, implement } from 'stitchkit/server'
|
|
1174
|
+
|
|
1175
|
+
interface Peer {
|
|
1176
|
+
node: string
|
|
1177
|
+
}
|
|
1178
|
+
export const peer = defineRequestIngress<Peer>('peer')
|
|
1179
|
+
|
|
1180
|
+
// The ingress, after it has authenticated the peer and built the request:
|
|
1181
|
+
peer.attach(request, { node: 'node-7' })
|
|
1182
|
+
const response = await handler(request)
|
|
1183
|
+
|
|
1184
|
+
// An endpoint, `authorize`, `beforeHandle` or `onError` — `ctx` is the source:
|
|
1185
|
+
implement(contract, {
|
|
1186
|
+
place: (ctx) => ({ node: peer.from(ctx)?.node ?? null }),
|
|
1187
|
+
})
|
|
1188
|
+
```
|
|
1189
|
+
|
|
1190
|
+
- The value belongs to the key. A header, a body, `request.clone()` and `new Request(request)`
|
|
1191
|
+
carry nothing; a request from another ingress has no value, and `from` answers `undefined`.
|
|
1192
|
+
Two keys never meet, even under one name, and a second `attach` of the same key to the same
|
|
1193
|
+
request is an error.
|
|
1194
|
+
- `ctx.req` is the `Request` the fetch handler of the core received, on every HTTP context: an
|
|
1195
|
+
endpoint, `authorize`, `beforeHandle`, and the `onError` context of a validation failure, an
|
|
1196
|
+
unknown path, a refused method or an `onRequest` that threw. That is the guarantee the lookup
|
|
1197
|
+
stands on, and the ingress tests hold it.
|
|
1198
|
+
- A raw route, `streamingRoute` and `onRequest` receive the request without a context: read with
|
|
1199
|
+
`peer.from({ req })`. The MCP, agent and CLI lanes carry no `Request`, so there is nothing to
|
|
1200
|
+
read.
|
|
1201
|
+
- With `proxyOrigin` configured, the request is replaced before `wrapFetch`: attach in
|
|
1202
|
+
`wrapFetch` or later, to the request you are handed.
|
|
1203
|
+
- A Socket.IO handshake is routed before `wrapFetch` on Bun and rebuilt as a new `Request` on
|
|
1204
|
+
Node: it never carries an attached value.
|
|
1205
|
+
- `stitchkit/node` exports the same names.
|
|
1206
|
+
|
|
1165
1207
|
### `createImplement` — a fixed context type
|
|
1166
1208
|
|
|
1167
1209
|
To type `ctx` with your app's extras (the user an auth hook injects), fix the
|
|
@@ -1369,6 +1411,7 @@ server. See [Testing & deployment](./testing-and-deployment.md).
|
|
|
1369
1411
|
| `logging` | `true` for built-in request logs, or a `LoggingConfig` (see below) |
|
|
1370
1412
|
| `traceId` | override per-request trace-id resolution — may return `undefined` to fall back |
|
|
1371
1413
|
| `wrapFetch` | compose wrappers around the finished handler (request context, audit) |
|
|
1414
|
+
| `proxyOrigin` | Bun TCP ingress policy: `{ trustedPeer(socketIp) }` restores the external scheme before all composition; independent of client-IP `trustProxy` |
|
|
1372
1415
|
| `socket` | full Stitchkit Socket.IO handle; route, default WebSocket handler and shutdown are mounted once |
|
|
1373
1416
|
| `websocket` | custom Bun WebSocket handler; with `socket`, this is the explicit composed handler |
|
|
1374
1417
|
| `development` / `bun` | passthrough to `Bun.serve` |
|
|
@@ -1377,6 +1420,60 @@ Native Bun `routes` are intentionally not accepted: Bun matches them before
|
|
|
1377
1420
|
`fetch`, so they could bypass shutdown admission. Use `rawRoutes`; they retain
|
|
1378
1421
|
the Fetch `Request → Response` model and participate in lifecycle tracking.
|
|
1379
1422
|
|
|
1423
|
+
### External origin behind a trusted proxy
|
|
1424
|
+
|
|
1425
|
+
An HTTPS ingress often forwards plain HTTP to Bun. `trustProxy` trusts client-IP
|
|
1426
|
+
headers only; it does not change `Request.url`. Opt into the separate URL policy:
|
|
1427
|
+
|
|
1428
|
+
```ts
|
|
1429
|
+
import { createServer, isLoopbackAddress } from 'stitchkit/server'
|
|
1430
|
+
|
|
1431
|
+
const server = createServer({
|
|
1432
|
+
hostname: '127.0.0.1',
|
|
1433
|
+
port: 3000,
|
|
1434
|
+
proxyOrigin: { trustedPeer: isLoopbackAddress },
|
|
1435
|
+
services,
|
|
1436
|
+
})
|
|
1437
|
+
```
|
|
1438
|
+
|
|
1439
|
+
The predicate receives the **real TCP peer**, never `X-Forwarded-For` or
|
|
1440
|
+
`X-Real-IP`. Match only the ingress you control. Loopback is appropriate only
|
|
1441
|
+
when other local processes are trusted. Unmatched peers, missing peer metadata
|
|
1442
|
+
and the default configuration ignore URL forwarding headers. Unix listeners have
|
|
1443
|
+
no TCP peer and do not use this policy. This option belongs to Bun `createServer`,
|
|
1444
|
+
not the Fetch-clean `createHandler` or Node `serveNode`.
|
|
1445
|
+
|
|
1446
|
+
The trusted ingress must overwrite `Host` with the external authority and
|
|
1447
|
+
`X-Forwarded-Proto` with exactly `http` or `https`. It must remove `Forwarded`,
|
|
1448
|
+
`X-Forwarded-Host` and `X-Forwarded-Port`; their presence, a missing/invalid
|
|
1449
|
+
proto, a list of values or a malformed Host returns HTTP 400 before application
|
|
1450
|
+
code. Header names are case-insensitive; proto values are lowercase. Multiple
|
|
1451
|
+
ingress chains require a single sanitizing ingress at this boundary.
|
|
1452
|
+
|
|
1453
|
+
For an nginx HTTPS terminator, the relevant forwarding settings are:
|
|
1454
|
+
|
|
1455
|
+
```nginx
|
|
1456
|
+
proxy_set_header Host $http_host;
|
|
1457
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
1458
|
+
proxy_set_header Forwarded "";
|
|
1459
|
+
proxy_set_header X-Forwarded-Host "";
|
|
1460
|
+
proxy_set_header X-Forwarded-Port "";
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
The normalized `Request.url` reaches `wrapFetch`, hooks, contracts, raw routes,
|
|
1464
|
+
and the managed Socket.IO route. It preserves the path/query, wire authority
|
|
1465
|
+
(including explicit ports), method, body, headers and linked cancellation signal.
|
|
1466
|
+
Request cloning uses the normalized URL. The same runtime handle resolves
|
|
1467
|
+
`requestIP`, `timeout` and `upgrade` against the original native request, retaining
|
|
1468
|
+
WebSocket and shutdown behavior.
|
|
1469
|
+
|
|
1470
|
+
This is a scheme normalization policy, **not host authorization**. Applications
|
|
1471
|
+
must retain their hostname/tenant allowlist and exact same-origin checks for
|
|
1472
|
+
Origin and Referer. The TLS terminator must reject SNI/Host mismatches before
|
|
1473
|
+
forwarding; a plain-HTTP Bun listener cannot observe the TLS SNI. The normalizer
|
|
1474
|
+
does not accept `X-Forwarded-Host`, authorize a foreign Host, or treat HTTP and
|
|
1475
|
+
HTTPS as aliases.
|
|
1476
|
+
|
|
1380
1477
|
### Local daemon over a unix socket
|
|
1381
1478
|
|
|
1382
1479
|
A local daemon whose door is a socket file needs no TCP port at all:
|
|
@@ -2032,6 +2129,10 @@ handler: async (req) => {
|
|
|
2032
2129
|
}
|
|
2033
2130
|
```
|
|
2034
2131
|
|
|
2132
|
+
`parseBody` reads the body up to `{ maxBytes }` — 1 MiB when you pass none, as the third
|
|
2133
|
+
argument — and returns `null` for a larger one without reading further, so a raw route
|
|
2134
|
+
never holds an unbounded body in memory.
|
|
2135
|
+
|
|
2035
2136
|
The error helpers (`badRequest`, `notFound`, …) **throw** an `AppError`, so raise
|
|
2036
2137
|
them inside the `try` and let `errorResponse(err)` render it — that runs any
|
|
2037
2138
|
thrown value through the framework's `normalizeError`, so a raw route returns the
|
|
@@ -3454,6 +3555,33 @@ that ends inside a line throws `StreamTruncatedLineError` (`lineBytes`) instead
|
|
|
3454
3555
|
fragment as a value — the right policy for a socket or a child process, where a missing newline
|
|
3455
3556
|
means the writer died. Both errors extend the `RangeError` / `SyntaxError` they replace.
|
|
3456
3557
|
|
|
3558
|
+
## Reading a body up to a byte limit
|
|
3559
|
+
|
|
3560
|
+
`readBoundedBody` (from `stitchkit` or `stitchkit/http`) reads a request or response body, a
|
|
3561
|
+
`ReadableStream<Uint8Array>` or any `AsyncIterable<Uint8Array>`, and never reads past
|
|
3562
|
+
`maxBytes` plus one chunk. Whoever owns the boundary picks the two errors, so a body that is too
|
|
3563
|
+
large and a read that was cancelled stay different outcomes:
|
|
3564
|
+
|
|
3565
|
+
```ts
|
|
3566
|
+
import { readBoundedBody } from 'stitchkit'
|
|
3567
|
+
|
|
3568
|
+
const bytes = await readBoundedBody(request.body, {
|
|
3569
|
+
maxBytes: 64 * 1024,
|
|
3570
|
+
signal: request.signal,
|
|
3571
|
+
limitError: (observedBytes) => new PayloadTooLarge(observedBytes),
|
|
3572
|
+
abortError: (reason) => new ClientGone({ cause: reason }),
|
|
3573
|
+
})
|
|
3574
|
+
```
|
|
3575
|
+
|
|
3576
|
+
- The source is cancelled when the limit is crossed and when `signal` aborts. A read that never
|
|
3577
|
+
settles does not hold the call after an abort, and an abort is honoured before the first read
|
|
3578
|
+
(even for a `null` body).
|
|
3579
|
+
- A body of exactly `maxBytes` is read; one more byte calls `limitError` with the bytes seen so far
|
|
3580
|
+
(the chunk that crossed the limit included).
|
|
3581
|
+
- A `null` body, such as a request without one, is an empty result.
|
|
3582
|
+
- Without `abortError` the signal's own reason is thrown.
|
|
3583
|
+
- `maxBytes` is a positive safe integer.
|
|
3584
|
+
|
|
3457
3585
|
## Resumable streams
|
|
3458
3586
|
|
|
3459
3587
|
A stream that survives a dropped connection needs four things beyond opening it:
|
|
@@ -4456,6 +4584,10 @@ default; DCR is off unless `clientRegistration.dcr` supplies both `register` and
|
|
|
4456
4584
|
exactly equals its URL, explicit redirect URIs and
|
|
4457
4585
|
`token_endpoint_auth_method: 'none'`.
|
|
4458
4586
|
|
|
4587
|
+
The token endpoint and `/register` read at most 64 KiB of a request body, or
|
|
4588
|
+
`maxRequestBodyBytes` when you set it; a larger one is answered `413` with
|
|
4589
|
+
`invalid_request` and the rest is not read.
|
|
4590
|
+
|
|
4459
4591
|
The production fetcher rejects credentials, fragments, non-HTTPS URLs and
|
|
4460
4592
|
private/reserved targets. Every redirect is DNS-resolved and IP-pinned again;
|
|
4461
4593
|
timeouts, redirect count and body size are bounded. Its bounded cache respects
|
|
@@ -13372,7 +13504,7 @@ queryable across all three:
|
|
|
13372
13504
|
| `ok` / `statusCode` | legacy success bit plus real HTTP status, or `200`/`400` for a tool; an opted-in cancellation is `false` / `499`. `statusCode` is **absent** on a job — it had no transport to have a status on, and inventing one would be the same defect as the `method: 'AGENT'` this replaced. A job's outcome is `ok`, plus `errorCode` when it failed |
|
|
13373
13505
|
| `durationMs` / `startedAt` | timing |
|
|
13374
13506
|
| `errorCode` / `errorMessage` / `errorDetail` | failures only — `errorDetail` carries the structure the message flattens (e.g. Zod issues) |
|
|
13375
|
-
| `payload` | sanitised tool arguments; HTTP is `null` unless request `includePayload` is enabled |
|
|
13507
|
+
| `payload` | sanitised tool arguments; HTTP is `null` unless request `includePayload` is enabled, or when the body was larger than `payloadMaxBytes` (then `payloadTruncated: true`) |
|
|
13376
13508
|
| `resultSize` / `responseBytes` | result item count + serialised size |
|
|
13377
13509
|
| `userId` / `ipAddress` / `userAgent` | identity |
|
|
13378
13510
|
|
|
@@ -13744,6 +13876,23 @@ createObservability({
|
|
|
13744
13876
|
`redact`, `truncatePreview` and `measureSize` are exported on their own if you
|
|
13745
13877
|
need to sanitise something outside the audit path.
|
|
13746
13878
|
|
|
13879
|
+
### How much of a body the audit row reads
|
|
13880
|
+
|
|
13881
|
+
With `includePayload: true` the row reads a clone of the request body, and it reads at most
|
|
13882
|
+
`payloadMaxBytes` of it. Unset, the limit is the handler's `maxJsonBodyBytes`, or 1 MiB when the
|
|
13883
|
+
handler has none, so one number bounds both. The clone is taken when the request opens, before
|
|
13884
|
+
a route is matched, so an endpoint's own `maxJsonBodyBytes` is not known to it: set
|
|
13885
|
+
`payloadMaxBytes` when endpoints accept more than the handler default. A body that is larger
|
|
13886
|
+
is cancelled at the limit, its `payload` is `null`, and the row carries `payloadTruncated: true` — a `null` payload with that flag
|
|
13887
|
+
means "too large to record", not "no body". Set `payloadMaxBytes` (a positive integer) to record
|
|
13888
|
+
more or less than the handler accepts:
|
|
13889
|
+
|
|
13890
|
+
```ts
|
|
13891
|
+
createObservability({
|
|
13892
|
+
request: { write, includePayload: true, payloadMaxBytes: 256 * 1024 },
|
|
13893
|
+
})
|
|
13894
|
+
```
|
|
13895
|
+
|
|
13747
13896
|
## The raw hooks
|
|
13748
13897
|
|
|
13749
13898
|
Tool observability is built on hooks you can also use directly — for a one-off
|
|
@@ -15998,6 +16147,32 @@ analytics policy belong to the application.
|
|
|
15998
16147
|
|
|
15999
16148
|
# Upgrading stitchkit
|
|
16000
16149
|
|
|
16150
|
+
## Released migration: 0.111.0
|
|
16151
|
+
|
|
16152
|
+
**Who must act:** applications whose raw routes call `parseBody` on JSON larger than 1 MiB, and applications whose OAuth clients send `/register` or `/token` bodies larger than 64 KiB.
|
|
16153
|
+
|
|
16154
|
+
### Bounded raw and OAuth bodies
|
|
16155
|
+
|
|
16156
|
+
`parseBody` reads at most 1 MiB and returns `null` for a larger body, where it used to read any size. A route that takes larger JSON states its limit:
|
|
16157
|
+
|
|
16158
|
+
```ts
|
|
16159
|
+
// before
|
|
16160
|
+
const body = await parseBody(req, Schema)
|
|
16161
|
+
// after
|
|
16162
|
+
const body = await parseBody(req, Schema, { maxBytes: 8 * 1024 * 1024 })
|
|
16163
|
+
```
|
|
16164
|
+
|
|
16165
|
+
`mountOAuthProvider` reads at most 64 KiB of a `/token` or `/register` body and answers `413` with `invalid_request` for a larger one. A deployment whose clients register larger metadata raises the limit:
|
|
16166
|
+
|
|
16167
|
+
```ts
|
|
16168
|
+
// before
|
|
16169
|
+
mountOAuthProvider({ issuer, signingSecret, resource, codes, authorizeUser })
|
|
16170
|
+
// after
|
|
16171
|
+
mountOAuthProvider({ issuer, signingSecret, resource, codes, authorizeUser, maxRequestBodyBytes: 256 * 1024 })
|
|
16172
|
+
```
|
|
16173
|
+
|
|
16174
|
+
Both limits must be a positive safe integer; anything else is refused when the route is built or called.
|
|
16175
|
+
|
|
16001
16176
|
## Released migration: 0.110.0
|
|
16002
16177
|
|
|
16003
16178
|
### Interrupted process drains
|
|
@@ -17375,7 +17550,7 @@ Run it inside the project that depends on stitchkit. It reads your installed
|
|
|
17375
17550
|
version out of `node_modules`, reads the changelog **shipped inside the
|
|
17376
17551
|
package**, and prints every breaking section your range crosses, oldest first,
|
|
17377
17552
|
each with its **Who must act** line — the list this guide's migrations expand
|
|
17378
|
-
on. Nothing to clone, nothing to be told: `--from` / `--to` override either end
|
|
17553
|
+
on — and then the fixes of that range that name what they touch. Nothing to clone, nothing to be told: `--from` / `--to` override either end
|
|
17379
17554
|
of the range if you want a different one.
|
|
17380
17555
|
|
|
17381
17556
|
So upgrading is: read the `### ⚠️ Breaking changes` of every version *above* your
|
|
@@ -17406,6 +17581,12 @@ beside a `package.json`, which is build output) and gives each item one verdict:
|
|
|
17406
17581
|
- **not declared — check by hand** — an item from before the line existed, with the files that
|
|
17407
17582
|
import the entrypoints it leads with.
|
|
17408
17583
|
|
|
17584
|
+
A fix that names what it touches gets the same verdicts. Since 0.110.7 every `### Fixed` item that
|
|
17585
|
+
leads with an entrypoint carries the `**Affects:**` line, and `upgrade` prints them in a second
|
|
17586
|
+
section, **Fixes that touch this project** (`fixes` in `--json`): a fix to `runNativeCommand` is
|
|
17587
|
+
listed with the `path:line` that imports it, or as *not used here*. Fixes of earlier releases that
|
|
17588
|
+
carry no line are not judged; one line counts them (`fixesWithoutAffects` in `--json`).
|
|
17589
|
+
|
|
17409
17590
|
`--json` prints the same verdicts per item for a CI step. The scan reads static `import` and
|
|
17410
17591
|
`export … from` declarations, bare imports and `import()` / `require()` of a literal specifier; a
|
|
17411
17592
|
specifier built at run time is invisible to it, and so is a file of another kind (`.astro`,
|
|
@@ -20903,6 +21084,7 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
20903
21084
|
| `parseSSE` | function | parse SSE from a `Response`, a web stream or an async byte iterable into an async generator — [guide](../guide/client.md#sse) |
|
|
20904
21085
|
| `parseNDJSON` | function | parse bounded fatal-UTF-8 NDJSON from a `Response`, a `ReadableStream<Uint8Array>` or an `AsyncIterable<Uint8Array>` (a child's stdout); blank keep-alives are skipped, `finalLine: 'require-newline'` makes the delimiter mandatory and `signal` cancels the source — [guide](../guide/client.md#any-byte-source) |
|
|
20905
21086
|
| `createNDJSONDecoder` / `NDJSONDecoder` | function / _type_ | the same bounded NDJSON reading driven by `push(chunk)` / `end()`, for a socket `data` callback |
|
|
21087
|
+
| `readBoundedBody` / `BoundedBodyOptions` | function / _type_ | the whole body of a `ReadableStream<Uint8Array>` or async byte iterable as bytes, never reading past `maxBytes` plus one chunk; `limitError(observedBytes)` and `abortError(reason)` choose the two errors, the source is cancelled on both, a `null` body is empty — [guide](../guide/client.md#reading-a-body-up-to-a-byte-limit) |
|
|
20906
21088
|
| `StreamByteSource` | _type_ | `Response \| ReadableStream<Uint8Array> \| AsyncIterable<Uint8Array>`, what the NDJSON and SSE readers accept |
|
|
20907
21089
|
| `StreamLineLimitError` / `StreamTruncatedLineError` | class | a line past `maxLineBytes` (`limitBytes`, `lineBytes`; a `RangeError`) and a source ended inside a line under `require-newline` (`lineBytes`; a `SyntaxError`) |
|
|
20908
21090
|
| `resumableIterator` | function | re-open a long-lived stream from the last delivered cursor, with jittered backoff, a caller-owned terminal item and prompt abort — [guide](../guide/client.md#resumable-streams) |
|
|
@@ -21242,9 +21424,11 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
21242
21424
|
| `formatZodError` | function | a `ZodError` → a readable, field-summarised string |
|
|
21243
21425
|
| `zodIssues` | function | a `ZodError` → structured `{ path, code, message }[]` — the machine-readable sibling of `formatZodError` |
|
|
21244
21426
|
| `ZodIssueSummary` | _type_ | one structured validation issue (`{ path, code, message }`) |
|
|
21245
|
-
| `parseBody` | function | parse + Zod-validate a JSON body → `data` or `null` (no throw) |
|
|
21427
|
+
| `parseBody` | function | parse + Zod-validate a JSON body → `data` or `null` (no throw); reads at most `options.maxBytes` (1 MiB by default) and is `null` for a larger body |
|
|
21246
21428
|
| `HandlerConfig` | _type_ | config for `createHandler`, including optional `maxJsonBodyBytes`; bound to `BunServer` on this entrypoint |
|
|
21247
21429
|
| `BunServerConfig` | _type_ | config for `createServer` (Bun); `unix` listens on a unix domain socket (mutually exclusive with `port`/`hostname`) — [details](../guide/server.md#local-daemon-over-a-unix-socket) |
|
|
21430
|
+
| `defineRequestIngress` / `RequestIngress` / `RequestIngressSource` | function / _type_ | a typed key the code that builds a `Request` attaches a value to (`attach(request, value)`) and an endpoint, `authorize`, `beforeHandle` or `onError` reads from its `ctx` (`from(ctx)`); a header, `clone()` and `new Request(request)` carry nothing, a second `attach` is refused, and `ctx.req` is the very request the handler received — [guide](../guide/server.md#request-attributes-from-the-ingress) |
|
|
21431
|
+
| `ProxyOriginConfig` | _type_ | explicit real-peer trust for Bun `createServer({ proxyOrigin })`; strict external-scheme normalization before composition — [details](../guide/server.md#external-origin-behind-a-trusted-proxy) |
|
|
21248
21432
|
| `UnixListenConfig` | _type_ | unix listener — a socket path, or `{ path, mode }` to tighten the file mode after listen |
|
|
21249
21433
|
| `BunServerHandle` | _type_ | managed Bun handle (`url`, `port`, `runtime`, `status`, `shutdown`) |
|
|
21250
21434
|
| `ManagedServerHandle` | _type_ | shared lifecycle shape generic over the runtime escape hatch |
|
|
@@ -22333,7 +22517,7 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
22333
22517
|
| `ObservabilityDrainReport` | _type_ | final closed/drained snapshot, `durationMs` (the shared drain's age, not this call's wait), and `drained` — read from the counters, `false` only when `total.pending + total.preparing` is nonzero |
|
|
22334
22518
|
| `ObservabilitySinkStatusSchema` / `ObservabilityStatusSchema` / `ObservabilityDrainReportSchema` | schema | runtime schemas for status/report integration boundaries |
|
|
22335
22519
|
| `RequestEventSinkConfig` | _type_ | `write`, filter/sanitisation, `maxPending`, `onSinkError` and `onDrop` |
|
|
22336
|
-
| `RequestObservabilityConfig` | _type_ | request sink plus opt-in payload capture and default-off `includeCancelled` rows |
|
|
22520
|
+
| `RequestObservabilityConfig` | _type_ | request sink plus opt-in payload capture (`payloadMaxBytes` bounds the body read, `payloadTruncated` marks a cut one) and default-off `includeCancelled` rows |
|
|
22337
22521
|
| `SinkDropReason` | _type_ | `'capacity' \| 'closed'` |
|
|
22338
22522
|
| `SinkError` | _type_ | isolated sink/projection failure and optional event |
|
|
22339
22523
|
| `SinkDrop` | _type_ | rejected event, reason and current pending count |
|
|
@@ -22578,7 +22762,7 @@ A native remote-connector auth surface for MCP — [guide](../guide/mcp-and-agen
|
|
|
22578
22762
|
| `protectedResourceMetadataUrl` | function | build the metadata URL for a resource |
|
|
22579
22763
|
| `wwwAuthenticateHeader` | function | build the `WWW-Authenticate` challenge header |
|
|
22580
22764
|
| `PROTECTED_RESOURCE_PATH` | const | the well-known metadata path |
|
|
22581
|
-
| `OAuthProviderConfig` | _type_ | config for `mountOAuthProvider` |
|
|
22765
|
+
| `OAuthProviderConfig` | _type_ | config for `mountOAuthProvider`; `maxRequestBodyBytes` bounds the `/token` and `/register` bodies (64 KiB by default) |
|
|
22582
22766
|
| `ProtectedResourceConfig` | _type_ | config for `oauthProtectedResourceRoute` |
|
|
22583
22767
|
| `ApplicationType` | _type_ | DCR `application_type` — `'native'` (loopback allowed) \| `'web'` (https only) |
|
|
22584
22768
|
| `AuthCodeData` | _type_ | a stored authorization-code record |
|
package/llms.txt
CHANGED
|
@@ -9,11 +9,11 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
|
|
|
9
9
|
Load the slice for each entrypoint your code imports — `import … from 'stitchkit/server'` → `llms/server.txt`; the root `stitchkit` import → `llms/stitchkit.txt`. A slice holds that entrypoint's API reference section and the guide pages whose home it is; every guide lives in exactly one slice, and a slice that needs another's guide names it under "Also read". Each file is at most 50.0 KB; a longer one continues in numbered parts, each naming the next at its top. Moving across versions: load `llms/upgrading.txt` and the range slices it lists between your version and the target. `llms-full.txt` inlines everything; it is far larger than a context window, so do not read it whole.
|
|
10
10
|
|
|
11
11
|
## Entrypoint slices
|
|
12
|
-
- **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 47.5 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt)
|
|
12
|
+
- **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 47.5 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 38.1 KB
|
|
13
13
|
- **stitchkit/live**: [llms/live.txt](llms/live.txt) 21.2 KB
|
|
14
14
|
- **stitchkit/react**: [llms/react.txt](llms/react.txt) 8.6 KB
|
|
15
15
|
- **stitchkit/react/keyboard**: [llms/react-keyboard.txt](llms/react-keyboard.txt) 9.2 KB
|
|
16
|
-
- **stitchkit/tools**: [llms/tools.txt](llms/tools.txt) 46.
|
|
16
|
+
- **stitchkit/tools**: [llms/tools.txt](llms/tools.txt) 46.4 KB → [llms/tools.2.txt](llms/tools.2.txt) 30.4 KB → [llms/tools.3.txt](llms/tools.3.txt) 26.3 KB
|
|
17
17
|
- **stitchkit/tools/mcp**: [llms/tools-mcp.txt](llms/tools-mcp.txt) 1.8 KB
|
|
18
18
|
- **stitchkit/tools/contract**: [llms/tools-contract.txt](llms/tools-contract.txt) 0.2 KB
|
|
19
19
|
- **stitchkit/tools/invoker**: [llms/tools-invoker.txt](llms/tools-invoker.txt) 0.2 KB
|
|
@@ -23,8 +23,8 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
|
|
|
23
23
|
- **stitchkit/remote**: [llms/remote.txt](llms/remote.txt) 1.0 KB
|
|
24
24
|
- **stitchkit/contract**: [llms/contract.txt](llms/contract.txt) 31.9 KB
|
|
25
25
|
- **stitchkit/primitives**: [llms/primitives.txt](llms/primitives.txt) 11.7 KB
|
|
26
|
-
- **stitchkit/server**: [llms/server.txt](llms/server.txt)
|
|
27
|
-
- **stitchkit/observability**: [llms/observability.txt](llms/observability.txt)
|
|
26
|
+
- **stitchkit/server**: [llms/server.txt](llms/server.txt) 44.2 KB → [llms/server.2.txt](llms/server.2.txt) 20.5 KB → [llms/server.3.txt](llms/server.3.txt) 45.6 KB → [llms/server.4.txt](llms/server.4.txt) 38.3 KB → [llms/server.5.txt](llms/server.5.txt) 22.9 KB
|
|
27
|
+
- **stitchkit/observability**: [llms/observability.txt](llms/observability.txt) 46.9 KB
|
|
28
28
|
- **stitchkit/agent-runtime**: [llms/agent-runtime.txt](llms/agent-runtime.txt) 42.7 KB → [llms/agent-runtime.2.txt](llms/agent-runtime.2.txt) 46.7 KB → [llms/agent-runtime.3.txt](llms/agent-runtime.3.txt) 35.6 KB
|
|
29
29
|
- **stitchkit/agent-runtime/testing**: [llms/agent-runtime-testing.txt](llms/agent-runtime-testing.txt) 2.6 KB
|
|
30
30
|
- **stitchkit/agent-runtime/harness**: [llms/agent-runtime-harness.txt](llms/agent-runtime-harness.txt) 11.0 KB
|
|
@@ -63,8 +63,8 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
|
|
|
63
63
|
- **stitchkit/realtime**: [llms/realtime.txt](llms/realtime.txt) 1.4 KB
|
|
64
64
|
|
|
65
65
|
## Upgrading slices
|
|
66
|
-
- **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 12.
|
|
67
|
-
- **Upgrading 0.101.0 → 0.
|
|
66
|
+
- **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 12.7 KB
|
|
67
|
+
- **Upgrading 0.101.0 → 0.111.0**: [llms/upgrading-0.101.0-0.111.0.txt](llms/upgrading-0.101.0-0.111.0.txt) 46.9 KB
|
|
68
68
|
- **Upgrading 0.74.0 → 0.100.0**: [llms/upgrading-0.74.0-0.100.0.txt](llms/upgrading-0.74.0-0.100.0.txt) 45.1 KB
|
|
69
69
|
- **Upgrading 0.61.0 → 0.73.0**: [llms/upgrading-0.61.0-0.73.0.txt](llms/upgrading-0.61.0-0.73.0.txt) 41.2 KB
|
|
70
70
|
- **Upgrading 0.44.0 → 0.60.0**: [llms/upgrading-0.44.0-0.60.0.txt](llms/upgrading-0.44.0-0.60.0.txt) 43.9 KB
|
package/package.json
CHANGED