stitchkit 0.55.0 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/socket-io.d.ts +14 -6
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/cli.js +4 -4
- package/dist/contract/errors.d.ts +7 -0
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/index.js +1 -1
- package/dist/files/boundary.d.ts +8 -5
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files.js +1 -1
- package/dist/{index-rgd18hx3.js → index-28cqssm3.js} +7 -0
- package/dist/index-557by2db.js +34 -0
- package/dist/index-5r13htq1.js +283 -0
- package/dist/index-6y759j86.js +1031 -0
- package/dist/{index-npye5kt7.js → index-75njxz7p.js} +69 -7
- package/dist/{index-1k16zv57.js → index-bfcpjw20.js} +125 -31
- package/dist/{index-0gv7k0ra.js → index-escqg10p.js} +73 -666
- package/dist/{index-v4bbq3p4.js → index-j3dem06f.js} +1 -1
- package/dist/{index-qx84bqzk.js → index-jcc611vh.js} +1 -1
- package/dist/{index-pzc32v75.js → index-sm2tjx06.js} +41 -4
- package/dist/{index-js7yexng.js → index-xy8fmh6w.js} +83 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -6
- package/dist/node.js +5 -4
- package/dist/observability/audit.d.ts +4 -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/observability/index.js +17 -11
- package/dist/remote.js +1 -1
- package/dist/server/context-contribution.d.ts +8 -0
- package/dist/server/context-contribution.d.ts.map +1 -1
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +1 -1
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +10 -6
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware/auth.d.ts +29 -2
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/request-body.d.ts.map +1 -1
- package/dist/testing/surface-conformance.d.ts +143 -10
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing/surface-manifest.d.ts +132 -33
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +470 -122
- package/dist/tools/async-operation.d.ts +210 -18
- package/dist/tools/async-operation.d.ts.map +1 -1
- package/dist/tools/define-download-tool.d.ts.map +1 -1
- package/dist/tools/define-upload-tool.d.ts.map +1 -1
- package/dist/tools/internal/surface-projector.d.ts +101 -0
- package/dist/tools/internal/surface-projector.d.ts.map +1 -0
- package/dist/tools/managed-file-error.d.ts +6 -0
- package/dist/tools/managed-file-error.d.ts.map +1 -0
- package/dist/tools/mcp-prepare.d.ts +3 -21
- package/dist/tools/mcp-prepare.d.ts.map +1 -1
- package/dist/tools/mcp-round-policy.d.ts +9 -0
- package/dist/tools/mcp-round-policy.d.ts.map +1 -0
- package/dist/tools/mcp-round.d.ts +0 -4
- package/dist/tools/mcp-round.d.ts.map +1 -1
- package/dist/tools/mount-download.d.ts.map +1 -1
- package/dist/tools/mount-upload.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +5 -9
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/surface.d.ts +7 -0
- package/dist/tools/surface.d.ts.map +1 -1
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +348 -383
- package/llms-full.txt +425 -66
- package/package.json +1 -1
- package/dist/index-h60df7rj.js +0 -110
- package/dist/index-k4dftwf7.js +0 -66
package/llms-full.txt
CHANGED
|
@@ -989,6 +989,18 @@ createServer({
|
|
|
989
989
|
| `'pretty'` | two coloured lines per request — `→` on arrival, `←` on completion | no — a line sized for a terminal is not a record |
|
|
990
990
|
| `'json'` | one structured line per completed request | yes |
|
|
991
991
|
|
|
992
|
+
Status `499` has one framework-wide meaning: the client closed the request. It
|
|
993
|
+
is logged at `info`, not under the ordinary `4xx → warn` rule. A confirmed
|
|
994
|
+
disconnect is not sent through project `onError`, `normalizeError` or the
|
|
995
|
+
request-error recorder; an `AbortError` while the request signal is still active
|
|
996
|
+
remains an internal failure. A runtime abort reason may be preserved by identity
|
|
997
|
+
through at most eight cycle-safe standard `cause` links; error messages and codes
|
|
998
|
+
are never classifiers. The same rule applies when the disconnect happens while
|
|
999
|
+
Stitchkit is reading a JSON upload body: bounded reads race every pending stream
|
|
1000
|
+
read against the request signal and never parse a cancelled partial body. `499`
|
|
1001
|
+
is transport telemetry, not a response declared in the contract or generated
|
|
1002
|
+
OpenAPI document.
|
|
1003
|
+
|
|
992
1004
|
Unset, `format` follows `NODE_ENV`: `json` under `production`, `pretty`
|
|
993
1005
|
otherwise. That default is read **per request** — not at import, not when this
|
|
994
1006
|
package was built — so it reflects the environment your app actually runs in.
|
|
@@ -1159,7 +1171,9 @@ createServer({
|
|
|
1159
1171
|
- **`afterHandle`** — receives the handler result; return a replacement to
|
|
1160
1172
|
transform it.
|
|
1161
1173
|
- **`onError`** — receives any thrown error; return a `Response` to customise
|
|
1162
|
-
the error body. Without it, errors render through the standard envelope.
|
|
1174
|
+
the error body. Without it, errors render through the standard envelope. A
|
|
1175
|
+
confirmed client disconnect is a transport cancellation rather than an
|
|
1176
|
+
application error and deliberately bypasses this hook.
|
|
1163
1177
|
|
|
1164
1178
|
Hooks see `RuntimeContext` (loose types); handlers see `HandlerContext` (typed).
|
|
1165
1179
|
That split is deliberate — see [ADR 0003](../decisions/0003-two-context-types.md).
|
|
@@ -3024,7 +3038,13 @@ import {
|
|
|
3024
3038
|
import { createManagedFileBoundary } from 'stitchkit/files'
|
|
3025
3039
|
import { z } from 'zod'
|
|
3026
3040
|
|
|
3027
|
-
const files = await createManagedFileBoundary({
|
|
3041
|
+
const files = await createManagedFileBoundary({
|
|
3042
|
+
root: '/srv/job-media',
|
|
3043
|
+
createRoot: true, // creates only this final directory; /srv must already be trusted
|
|
3044
|
+
inspectionTimeoutMs: 15_000,
|
|
3045
|
+
inspect: ({ prefix, name, declaredMediaType, signal }) =>
|
|
3046
|
+
inspectFile(prefix, { name, declaredMediaType, signal }),
|
|
3047
|
+
})
|
|
3028
3048
|
|
|
3029
3049
|
const waitForJob = defineWaitTool({
|
|
3030
3050
|
name: 'wait_for_job',
|
|
@@ -3131,16 +3151,14 @@ const runtimeTools = exportOperation.runtimeTools
|
|
|
3131
3151
|
```
|
|
3132
3152
|
|
|
3133
3153
|
Every follow-up repeats `authorize`; an opaque id is never authority. Aborting
|
|
3134
|
-
`wait` only stops waiting and never calls optional domain `cancel`.
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
id and snapshot Zod instances; declare each once and reuse it:
|
|
3154
|
+
`wait` only stops waiting and never calls optional domain `cancel`.
|
|
3155
|
+
|
|
3156
|
+
For a new HTTP surface, derive the canonical capability contract once. The
|
|
3157
|
+
factory defines schemas and routes only; the application still supplies normal
|
|
3158
|
+
handlers to `implement` and owns the job:
|
|
3140
3159
|
|
|
3141
3160
|
```ts
|
|
3142
|
-
import {
|
|
3143
|
-
import { bindContractAsyncOperation } from 'stitchkit/tools'
|
|
3161
|
+
import { defineAsyncOperationContract } from 'stitchkit/tools'
|
|
3144
3162
|
import { z } from 'zod'
|
|
3145
3163
|
|
|
3146
3164
|
const operationId = z.object({ id: z.string() })
|
|
@@ -3148,38 +3166,82 @@ const operationSnapshot = z.object({
|
|
|
3148
3166
|
phase: z.enum(['pending', 'running', 'succeeded', 'failed', 'cancelled']),
|
|
3149
3167
|
})
|
|
3150
3168
|
|
|
3151
|
-
const operations =
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3169
|
+
const operations = defineAsyncOperationContract({
|
|
3170
|
+
prefix: 'exports',
|
|
3171
|
+
scope: 'user',
|
|
3172
|
+
description: 'Export project data',
|
|
3173
|
+
startInput: z.object({ projectId: z.string() }),
|
|
3174
|
+
id: operationId,
|
|
3175
|
+
snapshot: operationSnapshot,
|
|
3176
|
+
cancel: true,
|
|
3177
|
+
result: z.object({ downloadUrl: z.url() }),
|
|
3178
|
+
})
|
|
3179
|
+
|
|
3180
|
+
// Pass operations.contract and ordinary handlers to implement(...).
|
|
3181
|
+
// operations.capabilities/schemas/adapters are the canonical protocol metadata.
|
|
3182
|
+
```
|
|
3183
|
+
|
|
3184
|
+
If an existing dedicated contract has a different wire shape — for example
|
|
3185
|
+
`start` returns a snapshot while follow-ups accept separate envelopes — bind it
|
|
3186
|
+
without casts or duplicate endpoints. Inline callbacks are contextually typed;
|
|
3187
|
+
every returned id/input is parsed by the destination schema:
|
|
3188
|
+
|
|
3189
|
+
```ts
|
|
3190
|
+
import { defineContract } from 'stitchkit/contract'
|
|
3191
|
+
import { bindContractAsyncOperation } from 'stitchkit/tools'
|
|
3192
|
+
|
|
3193
|
+
const startOutput = z.object({ operation: operationId, acceptedAt: z.string() })
|
|
3194
|
+
const statusInput = z.object({ operationId: z.string() })
|
|
3195
|
+
const waitInput = z.object({ lookup: operationId })
|
|
3196
|
+
|
|
3197
|
+
const existing = defineContract({ prefix: 'exports' }, {
|
|
3198
|
+
start: {
|
|
3199
|
+
method: 'POST', path: '/', desc: 'Start export',
|
|
3200
|
+
input: z.object({ projectId: z.string() }), output: startOutput,
|
|
3166
3201
|
},
|
|
3167
|
-
|
|
3202
|
+
status: {
|
|
3203
|
+
method: 'POST', path: '/status', desc: 'Read export status',
|
|
3204
|
+
input: statusInput, output: operationSnapshot,
|
|
3205
|
+
},
|
|
3206
|
+
wait: {
|
|
3207
|
+
method: 'POST', path: '/wait', desc: 'Wait for export',
|
|
3208
|
+
input: waitInput, output: operationSnapshot,
|
|
3209
|
+
},
|
|
3210
|
+
})
|
|
3168
3211
|
|
|
3169
3212
|
const operationHandlers = {
|
|
3170
|
-
start: () => ({ id: 'example' }),
|
|
3213
|
+
start: () => ({ operation: { id: 'example' }, acceptedAt: new Date().toISOString() }),
|
|
3171
3214
|
status: (): z.output<typeof operationSnapshot> => ({ phase: 'pending' }),
|
|
3172
3215
|
wait: (): z.output<typeof operationSnapshot> => ({ phase: 'succeeded' }),
|
|
3173
3216
|
}
|
|
3174
3217
|
|
|
3175
3218
|
const bound = bindContractAsyncOperation({
|
|
3176
3219
|
mode: 'contract-backed',
|
|
3177
|
-
|
|
3220
|
+
binding: 'adapted',
|
|
3221
|
+
contract: existing,
|
|
3222
|
+
id: operationId,
|
|
3178
3223
|
capabilities: { start: 'start', status: 'status', wait: 'wait' },
|
|
3224
|
+
adapters: {
|
|
3225
|
+
idFromStart: (output) => output.operation,
|
|
3226
|
+
inputFor: {
|
|
3227
|
+
status: (id) => ({ operationId: id.id }),
|
|
3228
|
+
wait: (id) => ({ lookup: id }),
|
|
3229
|
+
},
|
|
3230
|
+
},
|
|
3179
3231
|
handlers: operationHandlers,
|
|
3180
3232
|
})
|
|
3181
3233
|
```
|
|
3182
3234
|
|
|
3235
|
+
Direct binding remains the short form when start already returns the id and
|
|
3236
|
+
every follow-up reuses that exact schema instance. Its ID schema must be
|
|
3237
|
+
wire-stable: input and output types match and parsing has no transform,
|
|
3238
|
+
coercion, default or overwrite. This also excludes same-type transforms because
|
|
3239
|
+
the direct adapters would parse an already parsed ID again. Use adapted binding
|
|
3240
|
+
and explicitly project the parsed ID back into each follow-up input. In both
|
|
3241
|
+
modes the binder creates no router;
|
|
3242
|
+
it returns the existing contract, handlers and protocol metadata for
|
|
3243
|
+
application composition.
|
|
3244
|
+
|
|
3183
3245
|
### Explicit raw SDK registration
|
|
3184
3246
|
|
|
3185
3247
|
`rawTools` is deliberately named as an escape hatch. A tool registered there
|
|
@@ -3758,6 +3820,24 @@ socket.on('note:created', (note) => { /* typed note */ })
|
|
|
3758
3820
|
socket.emit('room:join', 'general', ({ joined }) => { /* typed + validated */ })
|
|
3759
3821
|
```
|
|
3760
3822
|
|
|
3823
|
+
When an application already owns the low-level Stitchkit transport, bind the
|
|
3824
|
+
contract without opening a second connection:
|
|
3825
|
+
|
|
3826
|
+
```ts
|
|
3827
|
+
import { bindRealtimeClient, createSocketIOClient } from 'stitchkit'
|
|
3828
|
+
|
|
3829
|
+
const transport = createSocketIOClient({ url: 'https://api.example.com' })
|
|
3830
|
+
const events = bindRealtimeClient(realtimeContract, transport, { onRejected })
|
|
3831
|
+
|
|
3832
|
+
transport.connect() // lifecycle stays with the transport owner
|
|
3833
|
+
events.on('note:created', handleNote)
|
|
3834
|
+
await events.request('room:join', 'general', { timeoutMs: 5_000 })
|
|
3835
|
+
```
|
|
3836
|
+
|
|
3837
|
+
The bound handle intentionally has no `connect()` or `disconnect()`. Its
|
|
3838
|
+
`on`/`emit`/`request`, rejection and timeout semantics are exactly the path used
|
|
3839
|
+
by `createRealtimeClient`; only transport construction/lifecycle differs.
|
|
3840
|
+
|
|
3761
3841
|
### Request-response over realtime
|
|
3762
3842
|
|
|
3763
3843
|
For an event with an `ack` schema, `request()` is the Promise form of the same
|
|
@@ -3792,6 +3872,7 @@ transport.
|
|
|
3792
3872
|
`createSocketIOClient` remains the low-level Socket.IO transport wrapper for
|
|
3793
3873
|
schema-agnostic infrastructure. Application wire events should use
|
|
3794
3874
|
`createRealtimeClient`; it adds the shared contract without replacing Socket.IO.
|
|
3875
|
+
Use `bindRealtimeClient` when that low-level transport already exists.
|
|
3795
3876
|
|
|
3796
3877
|
### Durable subscriptions
|
|
3797
3878
|
|
|
@@ -4344,10 +4425,10 @@ fields; `true | object` correctly makes them optional.
|
|
|
4344
4425
|
Annotate `rules` with `satisfies Record<MyScope, AuthRule<User>>` so the compiler
|
|
4345
4426
|
catches a scope you forgot to cover. With the scoped rule objects below, widen
|
|
4346
4427
|
the annotation to
|
|
4347
|
-
`satisfies Record<MyScope, AuthRule<User> | ScopedAuthRule<User,
|
|
4348
|
-
keeps the coverage check and does not disturb the derivation. (When every
|
|
4349
|
-
comes from the derived map, the check is already implicit: a scope missing
|
|
4350
|
-
`rules` is no key of the map, and a contract using it fails to compile.)
|
|
4428
|
+
`satisfies Record<MyScope, AuthRule<User> | ScopedAuthRule<User, AuthRuleContribution>>`
|
|
4429
|
+
— it keeps the coverage check and does not disturb the derivation. (When every
|
|
4430
|
+
scope comes from the derived map, the check is already implicit: a scope missing
|
|
4431
|
+
from `rules` is no key of the map, and a contract using it fails to compile.)
|
|
4351
4432
|
|
|
4352
4433
|
### Scoped rules — the map `createScopedImplement` consumes
|
|
4353
4434
|
|
|
@@ -4393,11 +4474,58 @@ widens its inject and degrades that scope's fields to `object`.
|
|
|
4393
4474
|
|
|
4394
4475
|
Derivation needs the identity generic to be **inferred** (write no explicit
|
|
4395
4476
|
`createAuthHook<User>` — TypeScript has no partial inference); with an explicit
|
|
4396
|
-
generic, or fields injected outside the hook, keep the hand-written map.
|
|
4397
|
-
hooks guarding different scopes compose by intersection:
|
|
4398
|
-
`createScopedImplement<AuthScopes<typeof userHook> & AuthScopes<typeof botHook>>()`.
|
|
4477
|
+
generic, or fields injected outside the hook, keep the hand-written map.
|
|
4399
4478
|
→ ADR 0078
|
|
4400
4479
|
|
|
4480
|
+
### Multiple auth domains — `composeAuthHooks`
|
|
4481
|
+
|
|
4482
|
+
Independent identity domains should keep separate resolvers and rules. Compose
|
|
4483
|
+
their canonical hooks and derive one handler context without a manual dispatcher
|
|
4484
|
+
or scope-map intersection:
|
|
4485
|
+
|
|
4486
|
+
```ts
|
|
4487
|
+
const userAuth = createAuthHook({
|
|
4488
|
+
resolve: resolveUser,
|
|
4489
|
+
resolveFromContext: resolveToolUser,
|
|
4490
|
+
rules: {
|
|
4491
|
+
user: (user) => ({ userId: user.id }),
|
|
4492
|
+
workspace: (user) => ({ userId: user.id }),
|
|
4493
|
+
},
|
|
4494
|
+
})
|
|
4495
|
+
|
|
4496
|
+
const workspaceAuth = createAuthHook({
|
|
4497
|
+
resolve: resolveMembership,
|
|
4498
|
+
resolveFromContext: resolveToolMembership,
|
|
4499
|
+
rules: {
|
|
4500
|
+
workspace: (membership) => ({ workspaceId: membership.workspaceId }),
|
|
4501
|
+
},
|
|
4502
|
+
})
|
|
4503
|
+
|
|
4504
|
+
export const auth = composeAuthHooks({
|
|
4505
|
+
hooks: [userAuth, workspaceAuth],
|
|
4506
|
+
defaultScope: 'user',
|
|
4507
|
+
})
|
|
4508
|
+
export const implementFor = createScopedImplement<AuthScopes<typeof auth>>()
|
|
4509
|
+
```
|
|
4510
|
+
|
|
4511
|
+
Only hooks that declare the selected scope run. An unknown scope fails closed;
|
|
4512
|
+
when several hooks own one scope, every owner must pass in declaration order.
|
|
4513
|
+
Each owner evaluates on an isolated shadow context. Stitchkit validates all
|
|
4514
|
+
changed fields, rejects reserved/unsafe fields and cross-owner key collisions,
|
|
4515
|
+
then commits the combined contribution once. A rejected or cancelled composite
|
|
4516
|
+
therefore exposes no partial fields to the handler.
|
|
4517
|
+
|
|
4518
|
+
Isolation is per-key, not deep: a contribution is the set of context keys whose
|
|
4519
|
+
descriptor changed. Mutating an existing value **in place**
|
|
4520
|
+
(`ctx.user.role = 'admin'`) edits the object every owner already shares, so it
|
|
4521
|
+
is neither reported as a contribution nor checked for collisions — contribute
|
|
4522
|
+
new fields instead of editing another owner's object. External side effects
|
|
4523
|
+
likewise remain consumer-owned and are not rolled back.
|
|
4524
|
+
|
|
4525
|
+
The composite's `defaultScope` is the only implicit scope. A child hook's own
|
|
4526
|
+
default must be absent or equal to it, so reordering hooks cannot change which
|
|
4527
|
+
scope protects an endpoint.
|
|
4528
|
+
|
|
4401
4529
|
### Auth on the tool surface — `resolveFromContext`
|
|
4402
4530
|
|
|
4403
4531
|
The same hook guards every transport, but the lifecycle slot and identity
|
|
@@ -4764,9 +4892,11 @@ a request context, and event projections — and you usually touch only the last
|
|
|
4764
4892
|
### createObservability
|
|
4765
4893
|
|
|
4766
4894
|
`createObservability` configures request and tool projections independently.
|
|
4767
|
-
Every completed call is normalised into one `RequestEvent`; HTTP
|
|
4768
|
-
owned directly by `createHandler`, while MCP/Agent completion uses
|
|
4769
|
-
`ToolCallHooks` runner.
|
|
4895
|
+
Every completed application call is normalised into one `RequestEvent`; HTTP
|
|
4896
|
+
completion is owned directly by `createHandler`, while MCP/Agent completion uses
|
|
4897
|
+
the canonical `ToolCallHooks` runner. Confirmed HTTP client cancellation stays
|
|
4898
|
+
in the access log by default and becomes a structured event only when the
|
|
4899
|
+
request sink opts in. There is no nested HTTP audit wrapper.
|
|
4770
4900
|
|
|
4771
4901
|
```ts
|
|
4772
4902
|
import { createObservability } from 'stitchkit/observability'
|
|
@@ -4787,6 +4917,7 @@ export const observability = createObservability({
|
|
|
4787
4917
|
request: {
|
|
4788
4918
|
write,
|
|
4789
4919
|
includePayload: false, // default: no Request.clone(), payload is null
|
|
4920
|
+
includeCancelled: false, // default: keep client closes in access logs only
|
|
4790
4921
|
filter: (event) => event.method !== 'GET',
|
|
4791
4922
|
},
|
|
4792
4923
|
tools: {
|
|
@@ -4809,6 +4940,40 @@ Each sink runs fire-and-forget and fails independently: a slow or broken request
|
|
|
4809
4940
|
sink cannot block the response, suppress operational logging or break the tool
|
|
4810
4941
|
sink.
|
|
4811
4942
|
|
|
4943
|
+
#### Client cancellation
|
|
4944
|
+
|
|
4945
|
+
A physical client close is classified only when the request's own signal is
|
|
4946
|
+
aborted and the thrown value is either an `AbortError` or contains the exact
|
|
4947
|
+
`request.signal.reason` by identity at the top level or within at most eight
|
|
4948
|
+
standard `cause` links. Cause traversal is cycle-safe. No message or error-code
|
|
4949
|
+
matching is used; active requests and unrelated/deeper causes remain application
|
|
4950
|
+
failures. The access completion is always `499/info`, without application error
|
|
4951
|
+
fields or project `onError`.
|
|
4952
|
+
|
|
4953
|
+
Structured request sinks are default-preserving: existing sinks receive no row
|
|
4954
|
+
for this outcome. Opt in when cancellation frequency belongs in the durable
|
|
4955
|
+
stream:
|
|
4956
|
+
|
|
4957
|
+
```ts
|
|
4958
|
+
const observability = createObservability({
|
|
4959
|
+
request: {
|
|
4960
|
+
includeCancelled: true,
|
|
4961
|
+
write: (event) => {
|
|
4962
|
+
if (event.outcome === 'cancelled') return recordClientClose(event)
|
|
4963
|
+
return recordApplicationRequest(event)
|
|
4964
|
+
},
|
|
4965
|
+
},
|
|
4966
|
+
})
|
|
4967
|
+
```
|
|
4968
|
+
|
|
4969
|
+
An opted-in row has `outcome: 'cancelled'`, `ok: false`, `statusCode: 499`, the
|
|
4970
|
+
ordinary identity/trace/timing fields and no `errorCode`, `errorMessage` or
|
|
4971
|
+
`errorDetail`. `ok` remains the legacy success bit: branch on `outcome` first.
|
|
4972
|
+
Cancellation rows use the same filter, capacity, diagnostics, ordering,
|
|
4973
|
+
`flush()` and `close()` machinery as every request event. MCP protocol
|
|
4974
|
+
cancellation remains represented by `event.mcp.outcome`; Agent and CLI have no
|
|
4975
|
+
generic client-disconnect signal and are not inferred from error text.
|
|
4976
|
+
|
|
4812
4977
|
The fire-and-forget work has an explicit bounded lifecycle:
|
|
4813
4978
|
|
|
4814
4979
|
```ts
|
|
@@ -4889,7 +5054,8 @@ queryable across all three:
|
|
|
4889
5054
|
| `httpMethod` | the contract verb on **tool** events (their `method` is `TOOL`) — filter reads vs writes across both surfaces with `(event.httpMethod ?? event.method) !== 'GET'` |
|
|
4890
5055
|
| `dimensions` | app-defined domain dimensions (tenant / project / entity id) — see [request context](#request-context) |
|
|
4891
5056
|
| `traceId` / `spanId` / `parentSpanId` | [W3C trace context](#trace-context) |
|
|
4892
|
-
| `
|
|
5057
|
+
| `outcome` | optional `'cancelled'` on explicitly enabled HTTP client-close rows; ordinary rows omit it |
|
|
5058
|
+
| `ok` / `statusCode` | legacy success bit plus real HTTP status, or `200`/`400` for a tool; an opted-in cancellation is `false` / `499` |
|
|
4893
5059
|
| `durationMs` / `startedAt` | timing |
|
|
4894
5060
|
| `errorCode` / `errorMessage` / `errorDetail` | failures only — `errorDetail` carries the structure the message flattens (e.g. Zod issues) |
|
|
4895
5061
|
| `payload` | sanitised tool arguments; HTTP is `null` unless request `includePayload` is enabled |
|
|
@@ -5139,6 +5305,10 @@ success and error alike — carrying the tool name, the arguments, the result, t
|
|
|
5139
5305
|
duration, the call context, the endpoint identity, and (only when the call failed
|
|
5140
5306
|
by throwing) the raw thrown value.
|
|
5141
5307
|
|
|
5308
|
+
A confirmed HTTP client disconnect is the exception to the raw-hook table: it
|
|
5309
|
+
is transport cancellation, so neither `afterHandle` nor project `onError` runs.
|
|
5310
|
+
Use the `499/info` access completion or opt-in request cancellation event above.
|
|
5311
|
+
|
|
5142
5312
|
```ts
|
|
5143
5313
|
createMcpHandler({
|
|
5144
5314
|
serverInfo, auth, services,
|
|
@@ -5332,35 +5502,98 @@ exercise the same framework pipeline.
|
|
|
5332
5502
|
|
|
5333
5503
|
### Transport conformance
|
|
5334
5504
|
|
|
5335
|
-
`buildSurfaceManifest` snapshots
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5505
|
+
`buildSurfaceManifest` v2 snapshots canonical operations separately from actual
|
|
5506
|
+
HTTP topology and mounted MCP/Agent/CLI projections. Named MCP surfaces keep
|
|
5507
|
+
their own advertised input digests (including `extend`, flattening and schema
|
|
5508
|
+
policy), and named realtime contracts keep directional argument/ack input and
|
|
5509
|
+
output digests. Compare only discovery you actually observed, then run explicit
|
|
5510
|
+
drivers for the transports you provide:
|
|
5339
5511
|
|
|
5340
5512
|
```ts
|
|
5513
|
+
import { bindRealtimeClient } from 'stitchkit'
|
|
5341
5514
|
import {
|
|
5342
5515
|
assertSurfaceDiscovery,
|
|
5343
5516
|
buildSurfaceManifest,
|
|
5517
|
+
createRealtimeProbeDriver,
|
|
5518
|
+
defineRealtimeProbe,
|
|
5344
5519
|
runSurfaceProbes,
|
|
5345
5520
|
} from 'stitchkit/testing'
|
|
5346
5521
|
|
|
5347
|
-
const manifest = buildSurfaceManifest({
|
|
5522
|
+
const manifest = buildSurfaceManifest({
|
|
5523
|
+
groups: [{ pathPrefix: '/api', services: httpServices }],
|
|
5524
|
+
mcpPreparation: { extend, schemaValidation, multiRound },
|
|
5525
|
+
mcpSurfaces: {
|
|
5526
|
+
member: { services: memberServices, runtimeTools },
|
|
5527
|
+
admin: { services: adminServices, runtimeTools },
|
|
5528
|
+
},
|
|
5529
|
+
toolSurfaces: {
|
|
5530
|
+
AGENT: { services: agentServices, runtimeTools },
|
|
5531
|
+
CLI: { services: cliServices, runtimeTools: cliRuntimeTools },
|
|
5532
|
+
},
|
|
5533
|
+
realtime: { primary: realtimeContract },
|
|
5534
|
+
cliCommands,
|
|
5535
|
+
})
|
|
5348
5536
|
assertSurfaceDiscovery(manifest, {
|
|
5349
5537
|
openApi,
|
|
5350
|
-
|
|
5538
|
+
toolSurfaces: [{
|
|
5539
|
+
transport: 'MCP',
|
|
5540
|
+
surface: 'member',
|
|
5541
|
+
names: (await mcpClient.listTools()).tools.map((tool) => tool.name),
|
|
5542
|
+
}],
|
|
5351
5543
|
AGENT: Object.keys(agentTools),
|
|
5352
5544
|
CLI: cliHelpNames,
|
|
5545
|
+
realtime: {
|
|
5546
|
+
primary: { serverToClient: observedServerEvents, clientToServer: observedClientEvents },
|
|
5547
|
+
},
|
|
5548
|
+
})
|
|
5549
|
+
|
|
5550
|
+
const invalidInbound = defineRealtimeProbe({
|
|
5551
|
+
name: 'invalid inbound payload',
|
|
5552
|
+
scenario: 'invalid_arguments',
|
|
5553
|
+
fixture: invalidPayloadFixture,
|
|
5554
|
+
expected: {
|
|
5555
|
+
outcome: 'realtime_rejected',
|
|
5556
|
+
code: 'REALTIME_CONTRACT_VIOLATION',
|
|
5557
|
+
rejection: {
|
|
5558
|
+
direction: 'server-inbound', phase: 'arguments',
|
|
5559
|
+
reason: 'invalid-arguments', fault: 'peer',
|
|
5560
|
+
},
|
|
5561
|
+
handlerCalls: 0,
|
|
5562
|
+
},
|
|
5563
|
+
})
|
|
5564
|
+
|
|
5565
|
+
const realtimeDriver = createRealtimeProbeDriver({
|
|
5566
|
+
bind: (onRejected, fixture) => {
|
|
5567
|
+
const client = bindRealtimeClient(realtimeContract, existingTransport, { onRejected })
|
|
5568
|
+
const scenario = bindApplicationRealtimeScenario(client, fixture)
|
|
5569
|
+
return {
|
|
5570
|
+
connected: () => client.connected,
|
|
5571
|
+
invoke: scenario.invoke,
|
|
5572
|
+
dispose: scenario.dispose, // subscriptions only; never disconnect the transport
|
|
5573
|
+
}
|
|
5574
|
+
},
|
|
5575
|
+
handlerCalls: () => applicationRealtimeHandlerCalls,
|
|
5353
5576
|
})
|
|
5354
5577
|
|
|
5355
5578
|
await runSurfaceProbes({
|
|
5356
|
-
probes,
|
|
5357
|
-
drivers: {
|
|
5579
|
+
probes: [invalidInbound],
|
|
5580
|
+
drivers: { REALTIME: realtimeDriver },
|
|
5358
5581
|
})
|
|
5359
5582
|
```
|
|
5360
5583
|
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5584
|
+
MCP preparation is global because the real MCP mount has one preparation
|
|
5585
|
+
policy; named surfaces select tools, while `extend.filter` decides which
|
|
5586
|
+
selected operations receive extra fields. CLI selection is deliberately plain,
|
|
5587
|
+
and Agent owns its own reachable presentation shaping.
|
|
5588
|
+
|
|
5589
|
+
The kit never starts a server, discovers Socket.IO topology remotely, invents
|
|
5590
|
+
credentials or synthesises invalid Zod values. Fixtures and observations come
|
|
5591
|
+
from the application. The realtime driver creates a rejection channel per
|
|
5592
|
+
scenario, observes connection state before invocation, and disposes only
|
|
5593
|
+
probe-owned subscriptions. Each scenario has one absolute deadline shared by
|
|
5594
|
+
signalled setup, invocation and teardown. An outer timeout stops waiting; it
|
|
5595
|
+
does not disconnect a foreign transport or retract an already emitted packet.
|
|
5596
|
+
A missing driver is unsupported, not silently marked conformant.
|
|
5364
5597
|
|
|
5365
5598
|
### Test handlers with raw Requests
|
|
5366
5599
|
|
|
@@ -5921,7 +6154,95 @@ current one *up to* your target, and apply each snippet.
|
|
|
5921
6154
|
runtime): bootstrap the server, one HTTP request, and any feature you rely on
|
|
5922
6155
|
(Socket.IO connect, an MCP tool call, a multipart upload, …).
|
|
5923
6156
|
|
|
5924
|
-
##
|
|
6157
|
+
## Released migration: 0.56.0
|
|
6158
|
+
|
|
6159
|
+
### Surface manifests are version 2
|
|
6160
|
+
|
|
6161
|
+
`operation.tools` could not describe a role-selected MCP surface, a different
|
|
6162
|
+
Agent or CLI selection, or an advertised `extend` schema, so projections moved
|
|
6163
|
+
out of the canonical operation:
|
|
6164
|
+
|
|
6165
|
+
```ts
|
|
6166
|
+
// before
|
|
6167
|
+
manifest.operations[0].tools.MCP
|
|
6168
|
+
// after
|
|
6169
|
+
manifest.toolSurfaces.find((s) => s.transport === 'MCP' && s.surface === null)?.tools
|
|
6170
|
+
|
|
6171
|
+
// before
|
|
6172
|
+
buildSurfaceManifest({ mcpSurfaces: { admin: { services, extend } } })
|
|
6173
|
+
// after
|
|
6174
|
+
buildSurfaceManifest({ mcpSurfaces: { admin: { services } }, mcpPreparation: { extend } })
|
|
6175
|
+
```
|
|
6176
|
+
|
|
6177
|
+
A committed snapshot is regenerated once, deliberately: `manifestVersion` is
|
|
6178
|
+
`2`, and `ConformanceTransport` gained `REALTIME`, so any exhaustive
|
|
6179
|
+
`Record<ConformanceTransport, …>` must handle it.
|
|
6180
|
+
|
|
6181
|
+
### `FILE_*` codes joined the error registry
|
|
6182
|
+
|
|
6183
|
+
`StitchErrorCode` gained `FILE_INVALID_PATH`, `FILE_OUTSIDE_ROOT`,
|
|
6184
|
+
`FILE_NOT_FOUND`, `FILE_NOT_REGULAR`, `FILE_INSPECTION_REJECTED`,
|
|
6185
|
+
`FILE_TOO_LARGE` and `FILE_EXISTS`. Only exhaustive maps break:
|
|
6186
|
+
|
|
6187
|
+
```ts
|
|
6188
|
+
// before — compiled while the registry had no file codes
|
|
6189
|
+
const copy: Record<StitchErrorCode, string> = { …, RATE_LIMITED: '…' }
|
|
6190
|
+
// after — add the seven managed-file codes (or use Partial<Record<…>>)
|
|
6191
|
+
```
|
|
6192
|
+
|
|
6193
|
+
Unexpected IO stays scrubbed as `INTERNAL_SERVER_ERROR`: the new codes are the
|
|
6194
|
+
caller-safe ones only.
|
|
6195
|
+
|
|
6196
|
+
### `ScopedAuthHook` is nominal
|
|
6197
|
+
|
|
6198
|
+
A hand-written function shaped like an auth hook is no longer assignable —
|
|
6199
|
+
identity now comes from the factory, so scope ownership and the inferred
|
|
6200
|
+
context cannot drift apart:
|
|
6201
|
+
|
|
6202
|
+
```ts
|
|
6203
|
+
// before — a structural stand-in
|
|
6204
|
+
const auth: ScopedAuthHook<Scopes> = async (ctx, endpoint) => { … }
|
|
6205
|
+
// after — create it, then compose domains
|
|
6206
|
+
const auth = createAuthHook({ resolve, rules })
|
|
6207
|
+
const composed = composeAuthHooks({ hooks: [auth, billingAuth], defaultScope: 'public' })
|
|
6208
|
+
```
|
|
6209
|
+
|
|
6210
|
+
### Managed-file inspectors also run on reads
|
|
6211
|
+
|
|
6212
|
+
An inspector is no longer write-only, and it has a finite default deadline
|
|
6213
|
+
(15 s). Make it read-aware and idempotent — a read carries no
|
|
6214
|
+
`declaredMediaType`:
|
|
6215
|
+
|
|
6216
|
+
```ts
|
|
6217
|
+
// before
|
|
6218
|
+
inspect: ({ declaredMediaType }) => inspectDeclaredType(declaredMediaType!)
|
|
6219
|
+
// after
|
|
6220
|
+
inspect: ({ prefix, declaredMediaType, signal }) =>
|
|
6221
|
+
inspectBytes(prefix, { declaredMediaType, signal })
|
|
6222
|
+
```
|
|
6223
|
+
|
|
6224
|
+
Set `inspectionTimeoutMs` explicitly when 15 seconds is the wrong budget.
|
|
6225
|
+
|
|
6226
|
+
### Direct async-operation binding needs a wire-stable ID
|
|
6227
|
+
|
|
6228
|
+
A direct binding reuses the start output as the follow-up wire input, so the ID
|
|
6229
|
+
schema must parse to itself (`z.input` equals `z.output`, no transform,
|
|
6230
|
+
coercion, default or overwrite). Anything else is parsed twice:
|
|
6231
|
+
|
|
6232
|
+
```ts
|
|
6233
|
+
// before — a transform silently ran on start and again on every follow-up
|
|
6234
|
+
defineAsyncOperationContract({ binding: 'direct', id: z.string().transform(Number) })
|
|
6235
|
+
// after — keep the wire shape, adapt explicitly
|
|
6236
|
+
defineAsyncOperationContract({
|
|
6237
|
+
binding: 'adapted',
|
|
6238
|
+
id,
|
|
6239
|
+
adapters: { idFromStart, inputFor },
|
|
6240
|
+
})
|
|
6241
|
+
```
|
|
6242
|
+
|
|
6243
|
+
## Released migration: 0.55.0
|
|
6244
|
+
|
|
6245
|
+
### Peer-free `implementRemote`
|
|
5925
6246
|
|
|
5926
6247
|
`implementRemote` now has one canonical, optional-peer-free owner. This keeps
|
|
5927
6248
|
MCP SDK and AI SDK modules out of CLI bundles that only proxy HTTP calls:
|
|
@@ -5933,7 +6254,7 @@ import { implementRemote } from 'stitchkit/tools'
|
|
|
5933
6254
|
import { implementRemote } from 'stitchkit/remote'
|
|
5934
6255
|
```
|
|
5935
6256
|
|
|
5936
|
-
|
|
6257
|
+
### Managed file boundary and strict auth returns
|
|
5937
6258
|
|
|
5938
6259
|
Create one boundary during application bootstrap and pass the capability, never
|
|
5939
6260
|
a per-call directory or host path:
|
|
@@ -6927,6 +7248,7 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
6927
7248
|
| `createSocketIOClient` | function | low-level typed Socket.IO transport primitive — [guide](../guide/realtime.md#low-level-transport) |
|
|
6928
7249
|
| `defineRealtimeContract` | function | Zod-first shared Socket.IO event contract — [guide](../guide/realtime.md#zod-first-event-contract) |
|
|
6929
7250
|
| `createRealtimeClient` | function | inferred, runtime-validated Socket.IO client — [guide](../guide/realtime.md#client--createrealtimeclient) |
|
|
7251
|
+
| `bindRealtimeClient` | function | bind contract validation and typed acknowledgements to an existing Stitchkit client transport without owning its lifecycle |
|
|
6930
7252
|
| `createRetainedTopics` | function | retained last-value store for sticky events — [guide](../guide/realtime.md#sticky-events) |
|
|
6931
7253
|
| `parseSSE` | function | parse an SSE `Response` into an async generator — [guide](../guide/client.md#sse) |
|
|
6932
7254
|
| `SocketIOClient` | _type_ | low-level client handle; `emit` reports disconnected drops and `emitWithAck` exposes the native Promise primitive used by validated `request()` |
|
|
@@ -6934,6 +7256,9 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
6934
7256
|
| `SocketEventMap` | _type_ | the shape of an event map |
|
|
6935
7257
|
| `RealtimeClient` | _type_ | validated client inferred from a realtime contract |
|
|
6936
7258
|
| `RealtimeClientOptions` | _type_ | transport options and the rejected-event hook for `createRealtimeClient` |
|
|
7259
|
+
| `BoundRealtimeClient` | _type_ | validated non-owning `on`/`emit`/`request` client with no `connect`/`disconnect` |
|
|
7260
|
+
| `RealtimeClientTransport` | _type_ | minimal existing transport capability accepted by `bindRealtimeClient` |
|
|
7261
|
+
| `BindRealtimeClientOptions` | _type_ | rejection/logger options for a bound existing transport |
|
|
6937
7262
|
| `RealtimeAcknowledgedEvent` | _type_ | event-name union restricted to definitions with an `ack` schema |
|
|
6938
7263
|
| `RealtimeAcknowledgement` | _type_ | validated acknowledgement output inferred from an event definition |
|
|
6939
7264
|
| `RealtimeRequestArguments` | _type_ | request arguments inferred from an acknowledged event tuple |
|
|
@@ -7140,6 +7465,7 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
7140
7465
|
| Export | Kind | Summary |
|
|
7141
7466
|
|--------|------|---------|
|
|
7142
7467
|
| `createAuthHook` | function | one scope gate for HTTP `authorize` and tool `beforeHandle` — [guide](../guide/auth-and-errors.md#createauthhook) |
|
|
7468
|
+
| `composeAuthHooks` | function | route multiple canonical auth domains by owned scope and atomically commit their typed contributions |
|
|
7143
7469
|
| `createErrorHook` | function | an async-capable, endpoint-aware `onError` hook from a code map + envelope renderer — [guide](../guide/auth-and-errors.md#createerrorhook) |
|
|
7144
7470
|
| `ErrorHookConfig` | _type_ | async observer/renderer config for `createErrorHook` |
|
|
7145
7471
|
| `ResolvedError` | _type_ | the normalised error handed to `createErrorHook`'s `render` |
|
|
@@ -7159,6 +7485,8 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
7159
7485
|
| `RuleScopes` | _type_ | scope→context map derived from a `rules` object; `'public'` fields become optional |
|
|
7160
7486
|
| `ScopedAuthHook` | _type_ | an auth hook carrying its derived scope map at the type level |
|
|
7161
7487
|
| `AuthScopes` | _type_ | recover the derived map — `createScopedImplement<AuthScopes<typeof hook>>()` |
|
|
7488
|
+
| `ComposeAuthHooksConfig` | _type_ | ordered canonical hooks plus the optional explicit composite default scope |
|
|
7489
|
+
| `ComposedAuthScopes` | _type_ | scope→context map derived from every owner in a composed auth hook |
|
|
7162
7490
|
| `BearerResolverConfig` | _type_ | config for `createBearerResolver` |
|
|
7163
7491
|
| `JwtPayload` | _type_ | a decoded JWT payload |
|
|
7164
7492
|
| `SignJwtOptions` | _type_ | options for `signJwt` (expiry, claims) |
|
|
@@ -7265,7 +7593,7 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
7265
7593
|
| Export | Kind | Summary |
|
|
7266
7594
|
|--------|------|---------|
|
|
7267
7595
|
| `createObservability` | function | configure framework-owned request completion and canonical tool event sinks — [guide](../guide/observability.md#createobservability) |
|
|
7268
|
-
| `RequestEvent` | _type_ | the normalised audit event handed to the sink |
|
|
7596
|
+
| `RequestEvent` | _type_ | the normalised audit event handed to the sink; opt-in HTTP cancellation rows carry `outcome: 'cancelled'` |
|
|
7269
7597
|
| `ObservabilityConfig` | _type_ | independent request and tool sink configuration |
|
|
7270
7598
|
| `Observability` | _type_ | `{ request?, toolCall, getStatus(), flush(), close() }` with bounded sink lifecycle |
|
|
7271
7599
|
| `ObservabilitySinkStatus` | _type_ | immutable counters for one bounded request/tool sink |
|
|
@@ -7273,11 +7601,11 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
7273
7601
|
| `ObservabilityDrainReport` | _type_ | final closed/drained snapshot plus duration |
|
|
7274
7602
|
| `ObservabilitySinkStatusSchema` / `ObservabilityStatusSchema` / `ObservabilityDrainReportSchema` | schema | runtime schemas for status/report integration boundaries |
|
|
7275
7603
|
| `RequestEventSinkConfig` | _type_ | `write`, filter/sanitisation, `maxPending`, `onSinkError` and `onDrop` |
|
|
7276
|
-
| `RequestObservabilityConfig` | _type_ | request sink plus opt-in payload capture |
|
|
7604
|
+
| `RequestObservabilityConfig` | _type_ | request sink plus opt-in payload capture and default-off `includeCancelled` rows |
|
|
7277
7605
|
| `SinkDropReason` | _type_ | `'capacity' \| 'closed'` |
|
|
7278
7606
|
| `SinkError` | _type_ | isolated sink/projection failure and optional event |
|
|
7279
7607
|
| `SinkDrop` | _type_ | rejected event, reason and current pending count |
|
|
7280
|
-
| `HttpRequestCompletion` | _type_ | the single framework-owned HTTP outcome projected to logging and request events |
|
|
7608
|
+
| `HttpRequestCompletion` | _type_ | the single framework-owned HTTP outcome, including optional neutral cancellation, projected to logging and request events |
|
|
7281
7609
|
| `HttpRequestObserver` | _type_ | server-facing projection consumed by `HandlerConfig.observability` |
|
|
7282
7610
|
|
|
7283
7611
|
### Request context
|
|
@@ -7477,6 +7805,7 @@ runtime-tool runner, plus deliberate raw MCP adapters over the same mechanics.
|
|
|
7477
7805
|
| `ManagedWaitRender` | _type_ | optional managed wait terminal text and failure classification |
|
|
7478
7806
|
| `UploadToolInputSchema` | constant | fixed `{ path: string }` input schema for `defineUploadTool` |
|
|
7479
7807
|
| `defineAsyncOperation` | function | runtime-only start/status/wait plus configured cancel/result/artifacts definitions |
|
|
7808
|
+
| `defineAsyncOperationContract` | function | define one canonical Zod-first HTTP contract for start/status/wait plus optional capabilities |
|
|
7480
7809
|
| `bindContractAsyncOperation` | function | bind literal methods from an existing contract without creating another HTTP surface |
|
|
7481
7810
|
| `createAsyncOperationSnapshotSchema` | function | canonical pending/running/succeeded/failed/cancelled Zod snapshot |
|
|
7482
7811
|
| `AsyncOperationCancelResultSchema` | constant | validated accepted/already_terminal/rejected cancellation result |
|
|
@@ -7488,9 +7817,18 @@ runtime-tool runner, plus deliberate raw MCP adapters over the same mechanics.
|
|
|
7488
7817
|
| `AsyncOperationOutputCapability` | _type_ | optional result/artifact schema plus handler |
|
|
7489
7818
|
| `RuntimeAsyncOperationConfig` | _type_ | runtime-only descriptor configuration |
|
|
7490
7819
|
| `RuntimeAsyncOperation` | _type_ | inferred generated definitions and schemas |
|
|
7820
|
+
| `AsyncOperationContractConfig` | _type_ | canonical contract config where start returns the operation id |
|
|
7821
|
+
| `AsyncOperationContractWithStartOutputConfig` | _type_ | canonical contract config with an application start envelope and typed id extractor |
|
|
7822
|
+
| `DefinedAsyncOperationContract` | _type_ | generated contract, capability keys, schemas and parsed adapters |
|
|
7491
7823
|
| `ContractAsyncOperationConfig` | _type_ | literal contract method binding and handlers |
|
|
7824
|
+
| `AdaptedContractAsyncOperationConfig` | _type_ | existing-contract binding with explicit id and per-capability input adapters |
|
|
7825
|
+
| `BoundAdaptedContractAsyncOperation` | _type_ | inferred adapted binding with parsed id/input projectors |
|
|
7826
|
+
| `AdaptedContractAsyncOperationStartKey` | _type_ | existing-contract keys with a declared start output |
|
|
7827
|
+
| `AdaptedContractAsyncOperationFollowKey` | _type_ | existing-contract keys with both input and output schemas |
|
|
7828
|
+
| `AdaptedContractAsyncOperationWaitKey` | _type_ | adapted follow-up keys whose output matches the selected status snapshot |
|
|
7829
|
+
| `ContractAsyncOperationInputAdapters` | _type_ | guaranteed direct-binding status/wait input adapters plus configured optional capabilities |
|
|
7492
7830
|
| `ContractAsyncOperationKeys` | _type_ | literal method-key union of a bound contract |
|
|
7493
|
-
| `ContractAsyncOperationStartKey` | _type_ |
|
|
7831
|
+
| `ContractAsyncOperationStartKey` | _type_ | direct-binding start keys whose declared ID schema has stable input/output |
|
|
7494
7832
|
| `ContractAsyncOperationFollowKey` | _type_ | contract keys whose input schema type matches the selected start output |
|
|
7495
7833
|
| `ContractAsyncOperationWaitKey` | _type_ | follow-up keys whose output schema type also matches the selected status output |
|
|
7496
7834
|
| `composeToolLifecycle` | function | ordered composition of tool before/after phases |
|
|
@@ -7573,21 +7911,42 @@ handler pipeline without opening a TCP port.
|
|
|
7573
7911
|
| `HandlerTestClientConfig` | _type_ | handler, contract, path prefix, scoped config and client request defaults |
|
|
7574
7912
|
| `HandlerTestClientsConfig` | _type_ | batch helper configuration |
|
|
7575
7913
|
| `HandlerTestTransportConfig` | _type_ | shared in-process handler, origin, prefix, client defaults and optional server handle |
|
|
7576
|
-
| `buildSurfaceManifest` | function | deterministic
|
|
7914
|
+
| `buildSurfaceManifest` | function | deterministic manifest v2 with HTTP topology, transport-specific tool projections, named MCP surfaces and realtime schema digests |
|
|
7577
7915
|
| `assertSurfaceManifestSnapshot` | function | bounded deterministic manifest drift assertion |
|
|
7578
|
-
| `assertSurfaceDiscovery` | function | compare real OpenAPI/
|
|
7579
|
-
| `runSurfaceProbes` | function | execute explicit transport drivers
|
|
7580
|
-
| `
|
|
7916
|
+
| `assertSurfaceDiscovery` | function | compare real OpenAPI/tool/realtime caller-observed discovery to the exact manifest projection |
|
|
7917
|
+
| `runSurfaceProbes` | function | execute explicit transport drivers under one per-scenario setup/invoke/teardown deadline |
|
|
7918
|
+
| `defineRealtimeProbe` | function | declare one canonical realtime scenario for a caller-supplied real transport driver |
|
|
7919
|
+
| `createRealtimeProbeDriver` | function | bind each scenario to a caller-owned transport and normalize actual event/ack/rejection/disconnect outcomes without lifecycle ownership |
|
|
7920
|
+
| `TransportObservationSchema` | constant | normalized HTTP/tool/realtime outcome including rejection fields and handler-call evidence |
|
|
7921
|
+
| `RealtimeRejectionObservationSchema` | constant | direction/phase/reason/fault observation for a rejected realtime event |
|
|
7922
|
+
| `RealtimeDisconnectObservationSchema` | constant | observed before-invoke versus in-flight disconnect phase |
|
|
7581
7923
|
| `ConformanceTransport` | _type_ | explicit probe transport union |
|
|
7582
7924
|
| `RunSurfaceProbesConfig` | _type_ | probes, drivers and diagnostic byte cap |
|
|
7583
7925
|
| `SurfaceDiscoveryObservation` | _type_ | real OpenAPI/tool/CLI/extension discovery values |
|
|
7926
|
+
| `SurfaceToolDiscoveryObservation` | _type_ | transport, optional named surface and caller-observed tool names |
|
|
7927
|
+
| `SurfaceRealtimeDiscoveryObservation` | _type_ | caller-observed server→client and client→server event names |
|
|
7584
7928
|
| `SurfaceProbe` / `SurfaceProbeDriver` | _type_ | one bounded scenario and its consumer-supplied runner |
|
|
7929
|
+
| `DefineRealtimeProbeConfig` | _type_ | name, canonical scenario, explicit fixture and expected realtime outcome |
|
|
7930
|
+
| `CreateRealtimeProbeDriverConfig` | _type_ | per-scenario foreign-transport binder and optional handler-call counter |
|
|
7931
|
+
| `RealtimeProbeAdapter` | _type_ | connected-state observation, scenario invocation and subscription-only cleanup |
|
|
7932
|
+
| `RealtimeProbeFixture` / `RealtimeProbeScenario` | _type_ | driver input and supported event/ack/invalid/disconnect/timeout scenario vocabulary |
|
|
7933
|
+
| `RealtimeRejectionObservation` | _type_ | parsed structured realtime rejection observation |
|
|
7934
|
+
| `RealtimeDisconnectObservation` | _type_ | normalized physical timing of a realtime disconnect |
|
|
7585
7935
|
| `TransportObservation` | _type_ | validated normalized driver result |
|
|
7586
7936
|
| `SurfaceManifest` / `SurfaceManifestConfig` | _type_ | deterministic surface snapshot and its inputs |
|
|
7587
7937
|
| `SurfaceManifestOperation` / `SurfaceManifestOperationSchema` | _type_ / schema | one contract or runtime operation row |
|
|
7938
|
+
| `SurfaceManifestTool` / `SurfaceManifestToolSchema` | _type_ / schema | one mounted tool row with advertised input digest |
|
|
7939
|
+
| `SurfaceManifestToolSurface` / `SurfaceManifestToolSurfaceSchema` | _type_ / schema | one static transport projection, optionally keyed for a finite MCP surface |
|
|
7940
|
+
| `SurfaceManifestRealtimeEvent` / `SurfaceManifestRealtimeEventSchema` | _type_ / schema | one named directional realtime event with input/output args and ack digests |
|
|
7588
7941
|
| `SurfaceManifestExtension` / `SurfaceManifestExtensionSchema` | _type_ / schema | declared transport extension row |
|
|
7589
7942
|
| `SurfaceManifestSchema` | schema | complete deterministic manifest schema |
|
|
7590
|
-
| `
|
|
7943
|
+
| `SurfaceToolDefinition` | _type_ | plain service/runtime selection used by CLI and finite named MCP surfaces |
|
|
7944
|
+
| `SurfaceAgentProjection` | _type_ | Agent selection plus its reachable extend/flatten presentation policy |
|
|
7945
|
+
| `SurfaceMcpPreparation` | _type_ | one global MCP extend/flatten/schema-validation/multi-round preparation policy |
|
|
7946
|
+
| `SurfaceRuntimeToolDefinition` | _type_ | peer-free non-executable runtime-operation descriptor for manifest projection |
|
|
7947
|
+
| `SurfaceToolExtension` | _type_ | canonical structural tool extension including schema, resolver and optional filter |
|
|
7948
|
+
| `McpSchemaValidationConfig` / `IncompatibleSchemaPolicy` | _type_ | canonical MCP schema-preparation policy used by real mounts and manifests |
|
|
7949
|
+
| `SurfaceRealtimeSchemaPairSchema` | schema | input/output digest pair for args or acknowledgements |
|
|
7591
7950
|
| `SurfaceSchemaDigestsSchema` | schema | params/input/output/multipart digest object |
|
|
7592
7951
|
| `serializeSurfaceValue` | function | canonical versioned serialization used for deterministic digests |
|
|
7593
7952
|
|
|
@@ -7600,16 +7959,16 @@ available from `stitchkit/contract`.
|
|
|
7600
7959
|
|
|
7601
7960
|
| Export | Kind | Summary |
|
|
7602
7961
|
|--------|------|---------|
|
|
7603
|
-
| `createManagedFileBoundary` | function | bind
|
|
7962
|
+
| `createManagedFileBoundary` | function | bind an application-owned root, optionally creating one final directory under a trusted existing parent |
|
|
7604
7963
|
| `ManagedFileBoundary` | _type_ | non-reopenable `read`/`write` capability over canonical relative paths |
|
|
7605
|
-
| `ManagedFileBoundaryConfig` | _type_ | bound root, finite limits, inspector and cleanup observer |
|
|
7964
|
+
| `ManagedFileBoundaryConfig` | _type_ | bound root, optional `createRoot`, finite read/write/inspection limits, inspector and cleanup observer |
|
|
7606
7965
|
| `ManagedFileRefSchema` / `ManagedFileRef` | schema / _type_ | transport-safe relative path, measured size and optional media metadata |
|
|
7607
7966
|
| `ManagedFilePathSchema` / `ManagedFilePath` | schema / _type_ | canonical POSIX relative managed-file path |
|
|
7608
7967
|
| `ManagedFileSource` | _type_ | bounded immutable bytes plus validated ref passed to upload callbacks |
|
|
7609
7968
|
| `ManagedFileReadOptions` / `ManagedFileWriteOptions` | _type_ | per-operation byte cap, signal and atomic write policy |
|
|
7610
|
-
| `ManagedFileError` / `ManagedFileErrorCode` | class / _type_ | stable caller-safe
|
|
7611
|
-
| `ManagedFileInspector` | _type_ | bounded-prefix
|
|
7612
|
-
| `ManagedFileInspectionInput` / `ManagedFileInspection` | _type_ | inspector input and
|
|
7969
|
+
| `ManagedFileError` / `ManagedFileErrorCode` | class / _type_ | stable boundary failures; registered `FILE_*` mistakes are caller-safe while `FILE_IO_ERROR` remains internal |
|
|
7970
|
+
| `ManagedFileInspector` | _type_ | bounded-prefix read/write inspection callback with a finite cancellation signal that cannot own path or size |
|
|
7971
|
+
| `ManagedFileInspectionInput` / `ManagedFileInspection` | _type_ | inspector prefix/name/declared media/signal input and validated metadata-only result |
|
|
7613
7972
|
|
|
7614
7973
|
---
|
|
7615
7974
|
|