stitchkit 0.93.0 → 0.94.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/CHANGELOG.md +198 -0
- package/README.md +5 -2
- package/dist/agent-runtime/children-control.d.ts +6 -0
- package/dist/agent-runtime/children-control.d.ts.map +1 -0
- package/dist/agent-runtime/children-spawn.d.ts +6 -0
- package/dist/agent-runtime/children-spawn.d.ts.map +1 -0
- package/dist/agent-runtime/children-state.d.ts +46 -0
- package/dist/agent-runtime/children-state.d.ts.map +1 -0
- package/dist/agent-runtime/children-usage.d.ts +8 -0
- package/dist/agent-runtime/children-usage.d.ts.map +1 -0
- package/dist/agent-runtime/children.d.ts +11 -14
- package/dist/agent-runtime/children.d.ts.map +1 -1
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-contract.d.ts +2 -1
- package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/contained-darwin.d.ts +38 -0
- package/dist/agent-runtime/contained-darwin.d.ts.map +1 -0
- package/dist/agent-runtime/contained-files.d.ts +11 -26
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/contained-scan.d.ts +21 -0
- package/dist/agent-runtime/contained-scan.d.ts.map +1 -0
- package/dist/agent-runtime/contained-write.d.ts +9 -0
- package/dist/agent-runtime/contained-write.d.ts.map +1 -0
- package/dist/agent-runtime/deferred-tool-types.d.ts +4 -3
- package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
- package/dist/agent-runtime/events.d.ts +1 -1
- package/dist/agent-runtime/events.d.ts.map +1 -1
- package/dist/agent-runtime/harness-control.d.ts +0 -1
- package/dist/agent-runtime/harness-control.d.ts.map +1 -1
- package/dist/agent-runtime/harness.d.ts +0 -5
- package/dist/agent-runtime/harness.d.ts.map +1 -1
- package/dist/agent-runtime/managed-tools.d.ts +3 -2
- package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
- package/dist/agent-runtime/observability.d.ts +1 -1
- package/dist/agent-runtime/observability.d.ts.map +1 -1
- package/dist/agent-runtime/openrouter.d.ts +29 -0
- package/dist/agent-runtime/openrouter.d.ts.map +1 -0
- package/dist/agent-runtime/projections.d.ts +1 -1
- package/dist/agent-runtime/projections.d.ts.map +1 -1
- package/dist/agent-runtime/run-acquisition.d.ts +17 -0
- package/dist/agent-runtime/run-acquisition.d.ts.map +1 -0
- package/dist/agent-runtime/run-execution-state.d.ts +133 -0
- package/dist/agent-runtime/run-execution-state.d.ts.map +1 -0
- package/dist/agent-runtime/run-execution.d.ts +17 -33
- package/dist/agent-runtime/run-execution.d.ts.map +1 -1
- package/dist/agent-runtime/run-failure.d.ts +18 -0
- package/dist/agent-runtime/run-failure.d.ts.map +1 -0
- package/dist/agent-runtime/run-model-attempts.d.ts +6 -0
- package/dist/agent-runtime/run-model-attempts.d.ts.map +1 -0
- package/dist/agent-runtime/run-prompt-history.d.ts +58 -0
- package/dist/agent-runtime/run-prompt-history.d.ts.map +1 -0
- package/dist/agent-runtime/run-provider-ledger.d.ts +26 -0
- package/dist/agent-runtime/run-provider-ledger.d.ts.map +1 -0
- package/dist/agent-runtime/run-stream-parts.d.ts +17 -0
- package/dist/agent-runtime/run-stream-parts.d.ts.map +1 -0
- package/dist/agent-runtime/run-terminal.d.ts +11 -0
- package/dist/agent-runtime/run-terminal.d.ts.map +1 -0
- package/dist/agent-runtime/run-turn-preparation.d.ts +22 -0
- package/dist/agent-runtime/run-turn-preparation.d.ts.map +1 -0
- package/dist/agent-runtime/runtime-admission-gate.d.ts +29 -0
- package/dist/agent-runtime/runtime-admission-gate.d.ts.map +1 -0
- package/dist/agent-runtime/runtime-control.d.ts +9 -0
- package/dist/agent-runtime/runtime-control.d.ts.map +1 -0
- package/dist/agent-runtime/runtime-recovery.d.ts +10 -0
- package/dist/agent-runtime/runtime-recovery.d.ts.map +1 -0
- package/dist/agent-runtime/runtime-state.d.ts +36 -0
- package/dist/agent-runtime/runtime-state.d.ts.map +1 -0
- package/dist/agent-runtime/runtime-submit.d.ts +5 -0
- package/dist/agent-runtime/runtime-submit.d.ts.map +1 -0
- package/dist/agent-runtime/runtime.d.ts +10 -5
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/schedule-records.d.ts +34 -0
- package/dist/agent-runtime/schedule-records.d.ts.map +1 -0
- package/dist/agent-runtime/schedules.d.ts +34 -0
- package/dist/agent-runtime/schedules.d.ts.map +1 -1
- package/dist/agent-runtime/sqlite-bun.d.ts +12 -0
- package/dist/agent-runtime/sqlite-bun.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-events.d.ts +5 -0
- package/dist/agent-runtime/sqlite-events.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-history.d.ts +7 -0
- package/dist/agent-runtime/sqlite-history.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-ledger.d.ts +7 -0
- package/dist/agent-runtime/sqlite-ledger.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-node.d.ts +12 -0
- package/dist/agent-runtime/sqlite-node.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-reads.d.ts +14 -0
- package/dist/agent-runtime/sqlite-reads.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-rows.d.ts +178 -0
- package/dist/agent-runtime/sqlite-rows.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-schema.d.ts +7 -0
- package/dist/agent-runtime/sqlite-schema.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite-transactions.d.ts +25 -0
- package/dist/agent-runtime/sqlite-transactions.d.ts.map +1 -0
- package/dist/agent-runtime/sqlite.d.ts +10 -6
- package/dist/agent-runtime/sqlite.d.ts.map +1 -1
- package/dist/agent-runtime/store-archive.d.ts +16 -0
- package/dist/agent-runtime/store-archive.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts +434 -0
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts +18 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-support.d.ts +130 -0
- package/dist/agent-runtime/store-conformance-support.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts +12 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance.d.ts +40 -0
- package/dist/agent-runtime/store-conformance.d.ts.map +1 -0
- package/dist/agent-runtime/store-create.d.ts +11 -0
- package/dist/agent-runtime/store-create.d.ts.map +1 -0
- package/dist/agent-runtime/store-driver-contract.d.ts +814 -0
- package/dist/agent-runtime/store-driver-contract.d.ts.map +1 -0
- package/dist/agent-runtime/store-events.d.ts +7 -89
- package/dist/agent-runtime/store-events.d.ts.map +1 -1
- package/dist/agent-runtime/store-memory.d.ts +4 -0
- package/dist/agent-runtime/store-memory.d.ts.map +1 -0
- package/dist/agent-runtime/store-mutate.d.ts +13 -0
- package/dist/agent-runtime/store-mutate.d.ts.map +1 -0
- package/dist/agent-runtime/store-purge.d.ts +1 -1
- package/dist/agent-runtime/store-purge.d.ts.map +1 -1
- package/dist/agent-runtime/store-reads.d.ts +29 -0
- package/dist/agent-runtime/store-reads.d.ts.map +1 -0
- package/dist/agent-runtime/store-reduce-history.d.ts +10 -0
- package/dist/agent-runtime/store-reduce-history.d.ts.map +1 -0
- package/dist/agent-runtime/store-reduce-run.d.ts +14 -0
- package/dist/agent-runtime/store-reduce-run.d.ts.map +1 -0
- package/dist/agent-runtime/store-reduce-shared.d.ts +76 -0
- package/dist/agent-runtime/store-reduce-shared.d.ts.map +1 -0
- package/dist/agent-runtime/store-reduce-terminal.d.ts +6 -0
- package/dist/agent-runtime/store-reduce-terminal.d.ts.map +1 -0
- package/dist/agent-runtime/store-reducer.d.ts +24 -0
- package/dist/agent-runtime/store-reducer.d.ts.map +1 -0
- package/dist/agent-runtime/store-snapshot.d.ts +19 -0
- package/dist/agent-runtime/store-snapshot.d.ts.map +1 -0
- package/dist/agent-runtime/store.d.ts +1 -1
- package/dist/agent-runtime/store.d.ts.map +1 -1
- package/dist/application/admission-rate.d.ts +21 -0
- package/dist/application/admission-rate.d.ts.map +1 -0
- package/dist/application/admission-run.d.ts +8 -0
- package/dist/application/admission-run.d.ts.map +1 -0
- package/dist/application/admission.d.ts +1 -1
- package/dist/application/admission.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-lock.d.ts +9 -34
- package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
- package/dist/application/events.d.ts +1 -1
- package/dist/application/events.d.ts.map +1 -1
- package/dist/application/file-state-store.d.ts +23 -0
- package/dist/application/file-state-store.d.ts.map +1 -0
- package/dist/application/health.d.ts +1 -1
- package/dist/application/health.d.ts.map +1 -1
- package/dist/application/kernel-admission.d.ts +8 -0
- package/dist/application/kernel-admission.d.ts.map +1 -0
- package/dist/application/kernel-contract.d.ts +142 -0
- package/dist/application/kernel-contract.d.ts.map +1 -0
- package/dist/application/kernel-resource-context.d.ts +24 -0
- package/dist/application/kernel-resource-context.d.ts.map +1 -0
- package/dist/application/kernel-restart.d.ts +5 -0
- package/dist/application/kernel-restart.d.ts.map +1 -0
- package/dist/application/kernel-rollback.d.ts +4 -0
- package/dist/application/kernel-rollback.d.ts.map +1 -0
- package/dist/application/kernel-shutdown.d.ts +6 -0
- package/dist/application/kernel-shutdown.d.ts.map +1 -0
- package/dist/application/kernel-start.d.ts +20 -0
- package/dist/application/kernel-start.d.ts.map +1 -0
- package/dist/application/kernel-state.d.ts +116 -0
- package/dist/application/kernel-state.d.ts.map +1 -0
- package/dist/application/kernel.d.ts +9 -140
- package/dist/application/kernel.d.ts.map +1 -1
- package/dist/application/latest-sink.d.ts +1 -1
- package/dist/application/latest-sink.d.ts.map +1 -1
- package/dist/application/notification-outbox.d.ts.map +1 -1
- package/dist/application/opentelemetry.d.ts +1 -1
- package/dist/application/opentelemetry.d.ts.map +1 -1
- package/dist/application/schedule.d.ts +0 -1
- package/dist/application/schedule.d.ts.map +1 -1
- package/dist/application/watch-hub-core.d.ts +122 -0
- package/dist/application/watch-hub-core.d.ts.map +1 -0
- package/dist/application/watch-hub.d.ts +3 -3
- package/dist/application/watch-hub.d.ts.map +1 -1
- package/dist/browser/client-executors.d.ts +14 -0
- package/dist/browser/client-executors.d.ts.map +1 -0
- package/dist/browser/client-multipart.d.ts +1 -1
- package/dist/browser/client-multipart.d.ts.map +1 -1
- package/dist/browser/client-url.d.ts +1 -1
- package/dist/browser/client-url.d.ts.map +1 -1
- package/dist/browser/client.d.ts +3 -2
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/contract-stream.d.ts +1 -1
- package/dist/browser/contract-stream.d.ts.map +1 -1
- package/dist/browser/http-fetch.d.ts +22 -0
- package/dist/browser/http-fetch.d.ts.map +1 -0
- package/dist/browser/http.d.ts +2 -4
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/live-state-core.d.ts +63 -0
- package/dist/browser/live-state-core.d.ts.map +1 -0
- package/dist/browser/live-state.d.ts.map +1 -1
- package/dist/browser/realtime-client.d.ts +26 -0
- package/dist/browser/realtime-client.d.ts.map +1 -0
- package/dist/browser/resumable.d.ts +1 -28
- package/dist/browser/resumable.d.ts.map +1 -1
- package/dist/browser/retained.d.ts.map +1 -0
- package/dist/browser/socket-io-connection.d.ts +82 -0
- package/dist/browser/socket-io-connection.d.ts.map +1 -0
- package/dist/browser/socket-io-peer.d.ts +20 -0
- package/dist/browser/socket-io-peer.d.ts.map +1 -0
- package/dist/browser/socket-io-trace.d.ts +31 -0
- package/dist/browser/socket-io-trace.d.ts.map +1 -0
- package/dist/browser/socket-io.d.ts +24 -18
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/browser/stream.d.ts +14 -2
- package/dist/browser/stream.d.ts.map +1 -1
- package/dist/contract/client-types.d.ts +134 -0
- package/dist/contract/client-types.d.ts.map +1 -0
- package/dist/contract/define-validation.d.ts +30 -0
- package/dist/contract/define-validation.d.ts.map +1 -0
- package/dist/contract/define.d.ts +47 -394
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/normalize.d.ts +56 -0
- package/dist/contract/normalize.d.ts.map +1 -0
- package/dist/contract/runtime-context.d.ts +131 -0
- package/dist/contract/runtime-context.d.ts.map +1 -0
- package/dist/contract/tool-options.d.ts +105 -0
- package/dist/contract/tool-options.d.ts.map +1 -0
- package/dist/contract/tool-view.d.ts +148 -0
- package/dist/contract/tool-view.d.ts.map +1 -0
- package/dist/declaration/declaration.d.ts.map +1 -0
- package/dist/durability/contract.d.ts +259 -0
- package/dist/durability/contract.d.ts.map +1 -0
- package/dist/durability/effect.d.ts +24 -0
- package/dist/durability/effect.d.ts.map +1 -0
- package/dist/durability/engine.d.ts +14 -0
- package/dist/durability/engine.d.ts.map +1 -0
- package/dist/durability/events.d.ts +103 -0
- package/dist/durability/events.d.ts.map +1 -0
- package/dist/durability/json.d.ts +3 -0
- package/dist/durability/json.d.ts.map +1 -0
- package/dist/durability/ledger.d.ts +27 -0
- package/dist/durability/ledger.d.ts.map +1 -0
- package/dist/durability/parks.d.ts +22 -0
- package/dist/durability/parks.d.ts.map +1 -0
- package/dist/durability/scheduler.d.ts +30 -0
- package/dist/durability/scheduler.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/browser.d.ts +5 -0
- package/dist/entrypoints/agent-runtime/browser.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/browser.js +124 -0
- package/dist/entrypoints/agent-runtime/coding-tools.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/coding-tools.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/coding-tools.js +22 -0
- package/dist/entrypoints/agent-runtime/harness.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/harness.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/harness.js +739 -0
- package/dist/entrypoints/agent-runtime/openrouter.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/openrouter.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/openrouter.js +270 -0
- package/dist/entrypoints/agent-runtime/sandbox.d.ts +5 -0
- package/dist/entrypoints/agent-runtime/sandbox.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/sandbox.js +797 -0
- package/dist/entrypoints/agent-runtime/sqlite/bun.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/sqlite/bun.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +44 -0
- package/dist/entrypoints/agent-runtime/sqlite/node.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/sqlite/node.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/sqlite/node.js +46 -0
- package/dist/entrypoints/agent-runtime/testing.d.ts +4 -0
- package/dist/entrypoints/agent-runtime/testing.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/testing.js +1116 -0
- package/dist/entrypoints/agent-runtime.d.ts +42 -0
- package/dist/entrypoints/agent-runtime.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime.js +2670 -0
- package/dist/entrypoints/application/diagnostic-journal.d.ts +21 -0
- package/dist/entrypoints/application/diagnostic-journal.d.ts.map +1 -0
- package/dist/entrypoints/application/diagnostic-journal.js +492 -0
- package/dist/entrypoints/application/grammy.d.ts +2 -0
- package/dist/entrypoints/application/grammy.d.ts.map +1 -0
- package/dist/entrypoints/application/grammy.js +169 -0
- package/dist/entrypoints/application/opentelemetry.d.ts +2 -0
- package/dist/entrypoints/application/opentelemetry.d.ts.map +1 -0
- package/dist/entrypoints/application/opentelemetry.js +250 -0
- package/dist/entrypoints/application/schemas.d.ts +15 -0
- package/dist/entrypoints/application/schemas.d.ts.map +1 -0
- package/dist/entrypoints/application/schemas.js +27 -0
- package/dist/entrypoints/application.d.ts +23 -0
- package/dist/entrypoints/application.d.ts.map +1 -0
- package/dist/entrypoints/application.js +2016 -0
- package/dist/entrypoints/bin/upgrade-cli.d.ts.map +1 -0
- package/dist/entrypoints/bin/upgrade-cli.js +177 -0
- package/dist/entrypoints/cli.d.ts +44 -0
- package/dist/entrypoints/cli.d.ts.map +1 -0
- package/dist/entrypoints/cli.js +773 -0
- package/dist/entrypoints/contract.d.ts +12 -0
- package/dist/entrypoints/contract.d.ts.map +1 -0
- package/dist/entrypoints/contract.js +64 -0
- package/dist/entrypoints/declaration.d.ts +2 -0
- package/dist/entrypoints/declaration.d.ts.map +1 -0
- package/dist/entrypoints/declaration.js +183 -0
- package/dist/entrypoints/files.d.ts +5 -0
- package/dist/entrypoints/files.d.ts.map +1 -0
- package/dist/entrypoints/files.js +111 -0
- package/dist/entrypoints/geo.d.ts +3 -0
- package/dist/entrypoints/geo.d.ts.map +1 -0
- package/dist/entrypoints/geo.js +245 -0
- package/dist/entrypoints/google.d.ts +2 -0
- package/dist/entrypoints/google.d.ts.map +1 -0
- package/dist/entrypoints/google.js +175 -0
- package/dist/entrypoints/index.d.ts +17 -0
- package/dist/entrypoints/index.d.ts.map +1 -0
- package/dist/entrypoints/index.js +764 -0
- package/dist/entrypoints/live.d.ts +19 -0
- package/dist/entrypoints/live.d.ts.map +1 -0
- package/dist/entrypoints/live.js +302 -0
- package/dist/entrypoints/node.d.ts +19 -0
- package/dist/entrypoints/node.d.ts.map +1 -0
- package/dist/entrypoints/node.js +308 -0
- package/dist/entrypoints/oauth.d.ts +2 -0
- package/dist/entrypoints/oauth.d.ts.map +1 -0
- package/dist/entrypoints/oauth.js +170 -0
- package/dist/entrypoints/observability.d.ts +19 -0
- package/dist/entrypoints/observability.d.ts.map +1 -0
- package/dist/entrypoints/observability.js +567 -0
- package/dist/entrypoints/primitives.d.ts +3 -0
- package/dist/entrypoints/primitives.d.ts.map +1 -0
- package/dist/entrypoints/primitives.js +749 -0
- package/dist/entrypoints/react.d.ts +5 -0
- package/dist/entrypoints/react.d.ts.map +1 -0
- package/dist/entrypoints/react.js +403 -0
- package/dist/entrypoints/release.d.ts +15 -0
- package/dist/entrypoints/release.d.ts.map +1 -0
- package/dist/entrypoints/release.js +196 -0
- package/dist/entrypoints/remote.d.ts +9 -0
- package/dist/entrypoints/remote.d.ts.map +1 -0
- package/dist/entrypoints/remote.js +66 -0
- package/dist/entrypoints/server.d.ts +39 -0
- package/dist/entrypoints/server.d.ts.map +1 -0
- package/dist/entrypoints/server.js +2009 -0
- package/dist/entrypoints/telegram.d.ts +3 -0
- package/dist/entrypoints/telegram.d.ts.map +1 -0
- package/dist/entrypoints/telegram.js +224 -0
- package/dist/entrypoints/testing.d.ts +10 -0
- package/dist/entrypoints/testing.d.ts.map +1 -0
- package/dist/entrypoints/testing.js +1377 -0
- package/dist/entrypoints/tools/connections.d.ts +19 -0
- package/dist/entrypoints/tools/connections.d.ts.map +1 -0
- package/dist/entrypoints/tools/connections.js +1110 -0
- package/dist/entrypoints/tools/contract.d.ts +29 -0
- package/dist/entrypoints/tools/contract.d.ts.map +1 -0
- package/dist/entrypoints/tools/contract.js +24 -0
- package/dist/entrypoints/tools/invoker.d.ts +9 -0
- package/dist/entrypoints/tools/invoker.d.ts.map +1 -0
- package/dist/entrypoints/tools/invoker.js +20 -0
- package/dist/entrypoints/tools.d.ts +54 -0
- package/dist/entrypoints/tools.d.ts.map +1 -0
- package/dist/entrypoints/tools.js +3009 -0
- package/dist/entrypoints/tracking/server.d.ts +15 -0
- package/dist/entrypoints/tracking/server.d.ts.map +1 -0
- package/dist/entrypoints/tracking.d.ts +24 -0
- package/dist/entrypoints/tracking.d.ts.map +1 -0
- package/dist/entrypoints/tracking.js +1140 -0
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files/file-io.d.ts +14 -0
- package/dist/files/file-io.d.ts.map +1 -0
- package/dist/google/google.d.ts.map +1 -0
- package/dist/index-0b1ess5e.js +38 -0
- package/dist/index-1j8pm5t0.js +412 -0
- package/dist/index-1zbbzgfh.js +89 -0
- package/dist/index-2bxbyab0.js +47 -0
- package/dist/index-2gxzjvyr.js +266 -0
- package/dist/index-35mh5bhj.js +177 -0
- package/dist/index-48ffdxgk.js +6 -0
- package/dist/index-4gcnakhx.js +82 -0
- package/dist/index-55hkhm67.js +343 -0
- package/dist/index-79z7m7dt.js +675 -0
- package/dist/index-7f68ghdn.js +3618 -0
- package/dist/index-7p1f0vp2.js +154 -0
- package/dist/index-83bdg97s.js +16 -0
- package/dist/index-863ea9jb.js +154 -0
- package/dist/index-8p52kd5p.js +242 -0
- package/dist/index-d9pk3td4.js +326 -0
- package/dist/index-dce5wxcq.js +63 -0
- package/dist/index-e01r054k.js +105 -0
- package/dist/index-ensd0r74.js +595 -0
- package/dist/index-eqqvgdb3.js +46 -0
- package/dist/index-gxrt5h6v.js +341 -0
- package/dist/index-h6eeys1v.js +211 -0
- package/dist/index-ham5sz8m.js +734 -0
- package/dist/index-het2he5g.js +1387 -0
- package/dist/index-hffjpmq9.js +30 -0
- package/dist/index-hmp4800j.js +51 -0
- package/dist/index-k30h66yd.js +317 -0
- package/dist/index-k5hsfc3j.js +31 -0
- package/dist/index-khtgb21r.js +92 -0
- package/dist/index-m9zn6cpq.js +51 -0
- package/dist/index-ndddxtyx.js +324 -0
- package/dist/index-ngfhvfpd.js +30 -0
- package/dist/index-np4m8hd3.js +1205 -0
- package/dist/index-p3vsv1fb.js +3493 -0
- package/dist/index-p5r7qpdd.js +85 -0
- package/dist/index-p9e0w8hs.js +1084 -0
- package/dist/index-p9sh0xx4.js +64 -0
- package/dist/index-paz6sgdp.js +371 -0
- package/dist/index-px2gm2jp.js +448 -0
- package/dist/index-qwhynv6x.js +103 -0
- package/dist/index-s812ycat.js +65 -0
- package/dist/index-sp1tzwnb.js +281 -0
- package/dist/index-t9rhjr9f.js +2306 -0
- package/dist/index-v260df89.js +342 -0
- package/dist/index-w906953s.js +946 -0
- package/dist/index-wdkt63w3.js +214 -0
- package/dist/index-wqgjfstn.js +18 -0
- package/dist/index-wsm5w4ee.js +1023 -0
- package/dist/index-xw3s75nj.js +100 -0
- package/dist/index-yw4fzmdz.js +268 -0
- package/dist/index-zfrhfn82.js +85 -0
- package/dist/index-znfs20ss.js +98 -0
- package/dist/internal/atomic-file.d.ts +23 -2
- package/dist/internal/atomic-file.d.ts.map +1 -1
- package/dist/internal/backoff.d.ts +29 -0
- package/dist/internal/backoff.d.ts.map +1 -0
- package/dist/internal/canonical-json.d.ts +21 -11
- package/dist/internal/canonical-json.d.ts.map +1 -1
- package/dist/internal/channel.d.ts.map +1 -0
- package/dist/internal/exclusive-lock.d.ts +51 -0
- package/dist/internal/exclusive-lock.d.ts.map +1 -0
- package/dist/internal/logger.d.ts.map +1 -0
- package/dist/internal/process-identity.d.ts +47 -0
- package/dist/internal/process-identity.d.ts.map +1 -0
- package/dist/internal/request.d.ts.map +1 -0
- package/dist/internal/stable-digest.d.ts +0 -43
- package/dist/internal/stable-digest.d.ts.map +1 -1
- package/dist/internal/typed.d.ts +0 -8
- package/dist/internal/typed.d.ts.map +1 -1
- package/dist/internal/with-exclusive-lock.d.ts +67 -0
- package/dist/internal/with-exclusive-lock.d.ts.map +1 -0
- package/dist/internal/zod-issues.d.ts +38 -0
- package/dist/internal/zod-issues.d.ts.map +1 -0
- package/dist/json-schema/dialect.d.ts +17 -0
- package/dist/json-schema/dialect.d.ts.map +1 -0
- package/dist/json-schema/json-schema.d.ts.map +1 -0
- package/dist/live/watch-client.d.ts.map +1 -1
- package/dist/live/watch-delta.d.ts.map +1 -1
- package/dist/oauth/authorization-code.d.ts +57 -0
- package/dist/oauth/authorization-code.d.ts.map +1 -0
- package/dist/observability/audit.d.ts +3 -3
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/bounded-logger.d.ts +1 -1
- package/dist/observability/bounded-logger.d.ts.map +1 -1
- package/dist/observability/bounded-sink.d.ts +81 -0
- package/dist/observability/bounded-sink.d.ts.map +1 -0
- package/dist/observability/context.d.ts +1 -1
- package/dist/observability/context.d.ts.map +1 -1
- package/dist/observability/event.d.ts +2 -1
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/observability/work.d.ts +1 -1
- package/dist/observability/work.d.ts.map +1 -1
- package/dist/primitives/audit.d.ts +1 -1
- package/dist/primitives/audit.d.ts.map +1 -1
- package/dist/primitives/export-operation.d.ts +4 -2
- package/dist/primitives/export-operation.d.ts.map +1 -1
- package/dist/realtime/registry.d.ts +0 -5
- package/dist/realtime/registry.d.ts.map +1 -1
- package/dist/realtime/socket.d.ts +1 -1
- package/dist/realtime/socket.d.ts.map +1 -1
- package/dist/server/bun.d.ts +0 -1
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/context-contribution.d.ts +1 -1
- package/dist/server/context-contribution.d.ts.map +1 -1
- package/dist/server/context.d.ts +2 -2
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/contract-method.d.ts +15 -0
- package/dist/server/contract-method.d.ts.map +1 -0
- package/dist/server/contract-stream.d.ts +1 -1
- package/dist/server/contract-stream.d.ts.map +1 -1
- package/dist/server/create.d.ts +8 -0
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/endpoint-dispatch.d.ts +10 -0
- package/dist/server/endpoint-dispatch.d.ts.map +1 -0
- package/dist/server/endpoint-response.d.ts +19 -0
- package/dist/server/endpoint-response.d.ts.map +1 -0
- package/dist/server/error-dispatch.d.ts +17 -1
- package/dist/server/error-dispatch.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +2 -2
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/handler-state.d.ts +44 -0
- package/dist/server/handler-state.d.ts.map +1 -0
- package/dist/server/implement-registry.d.ts +54 -0
- package/dist/server/implement-registry.d.ts.map +1 -0
- package/dist/server/implement.d.ts +9 -55
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/middleware/auth.d.ts +1 -31
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/cors.d.ts +17 -0
- package/dist/server/middleware/cors.d.ts.map +1 -1
- package/dist/server/middleware/jwt.d.ts +31 -0
- package/dist/server/middleware/jwt.d.ts.map +1 -0
- package/dist/server/middleware/trust-fence.d.ts +1 -1
- package/dist/server/middleware/trust-fence.d.ts.map +1 -1
- package/dist/server/multipart-reader.d.ts +22 -0
- package/dist/server/multipart-reader.d.ts.map +1 -0
- package/dist/server/multipart.d.ts +1 -1
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/oauth/cimd.d.ts +88 -0
- package/dist/server/oauth/cimd.d.ts.map +1 -0
- package/dist/server/oauth/endpoints.d.ts +39 -0
- package/dist/server/oauth/endpoints.d.ts.map +1 -0
- package/dist/server/oauth/metadata.d.ts +28 -0
- package/dist/server/oauth/metadata.d.ts.map +1 -0
- package/dist/server/oauth/provider.d.ts +117 -0
- package/dist/server/oauth/provider.d.ts.map +1 -0
- package/dist/server/realtime.d.ts +1 -1
- package/dist/server/realtime.d.ts.map +1 -1
- package/dist/server/request-completion.d.ts +16 -0
- package/dist/server/request-completion.d.ts.map +1 -0
- package/dist/server/response-metadata.d.ts +1 -1
- package/dist/server/response-metadata.d.ts.map +1 -1
- package/dist/server/route-table.d.ts +9 -0
- package/dist/server/route-table.d.ts.map +1 -0
- package/dist/server/stream.d.ts +0 -13
- package/dist/server/stream.d.ts.map +1 -1
- package/dist/server/streaming-pump.d.ts +66 -0
- package/dist/server/streaming-pump.d.ts.map +1 -0
- package/dist/server/streaming-route.d.ts +12 -5
- package/dist/server/streaming-route.d.ts.map +1 -1
- package/dist/server/types.d.ts +10 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/unix-client-bun.d.ts.map +1 -1
- package/dist/server/unix-client-http1.d.ts +76 -0
- package/dist/server/unix-client-http1.d.ts.map +1 -0
- package/dist/server/unix-client.d.ts.map +1 -1
- package/dist/testing/handler-clients.d.ts +32 -0
- package/dist/testing/handler-clients.d.ts.map +1 -0
- package/dist/testing/managed-resource-conformance-scenarios.d.ts.map +1 -1
- package/dist/testing/realtime-probe.d.ts +33 -0
- package/dist/testing/realtime-probe.d.ts.map +1 -0
- package/dist/testing/surface-conformance.d.ts +2 -32
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing/surface-manifest-digest.d.ts +44 -0
- package/dist/testing/surface-manifest-digest.d.ts.map +1 -0
- package/dist/testing/surface-manifest.d.ts +30 -4
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/tools/agent.d.ts +1 -1
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli/args-fields.d.ts +31 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -0
- package/dist/tools/cli/args-route.d.ts +42 -0
- package/dist/tools/cli/args-route.d.ts.map +1 -0
- package/dist/tools/cli/args-view.d.ts +32 -0
- package/dist/tools/cli/args-view.d.ts.map +1 -0
- package/dist/tools/cli/args.d.ts +80 -0
- package/dist/tools/cli/args.d.ts.map +1 -0
- package/dist/tools/cli/argument-error.d.ts +5 -0
- package/dist/tools/cli/argument-error.d.ts.map +1 -0
- package/dist/tools/cli/checkpoint.d.ts +24 -0
- package/dist/tools/cli/checkpoint.d.ts.map +1 -0
- package/dist/tools/cli/command.d.ts +70 -0
- package/dist/tools/cli/command.d.ts.map +1 -0
- package/dist/tools/cli/config.d.ts +90 -0
- package/dist/tools/cli/config.d.ts.map +1 -0
- package/dist/tools/cli/create-cli.d.ts +36 -0
- package/dist/tools/cli/create-cli.d.ts.map +1 -0
- package/dist/tools/cli/download.d.ts +8 -0
- package/dist/tools/cli/download.d.ts.map +1 -0
- package/dist/tools/cli/format.d.ts +50 -0
- package/dist/tools/cli/format.d.ts.map +1 -0
- package/dist/tools/cli/help.d.ts +24 -0
- package/dist/tools/cli/help.d.ts.map +1 -0
- package/dist/tools/cli/installer.d.ts +34 -0
- package/dist/tools/cli/installer.d.ts.map +1 -0
- package/dist/tools/cli/invoke.d.ts +144 -0
- package/dist/tools/cli/invoke.d.ts.map +1 -0
- package/dist/tools/cli/io.d.ts +10 -0
- package/dist/tools/cli/io.d.ts.map +1 -0
- package/dist/tools/cli/managed-surface.d.ts +30 -0
- package/dist/tools/cli/managed-surface.d.ts.map +1 -0
- package/dist/tools/cli/manifest.d.ts +80 -0
- package/dist/tools/cli/manifest.d.ts.map +1 -0
- package/dist/tools/cli/policy.d.ts +27 -0
- package/dist/tools/cli/policy.d.ts.map +1 -0
- package/dist/tools/cli/prepare.d.ts +14 -0
- package/dist/tools/cli/prepare.d.ts.map +1 -0
- package/dist/tools/cli/profile.d.ts +40 -0
- package/dist/tools/cli/profile.d.ts.map +1 -0
- package/dist/tools/cli/run-managed.d.ts +5 -0
- package/dist/tools/cli/run-managed.d.ts.map +1 -0
- package/dist/tools/cli/run-native.d.ts +9 -0
- package/dist/tools/cli/run-native.d.ts.map +1 -0
- package/dist/tools/cli/session.d.ts +40 -0
- package/dist/tools/cli/session.d.ts.map +1 -0
- package/dist/tools/cli/signature.d.ts +81 -0
- package/dist/tools/cli/signature.d.ts.map +1 -0
- package/dist/tools/cli/stream.d.ts +93 -0
- package/dist/tools/cli/stream.d.ts.map +1 -0
- package/dist/tools/cli/update.d.ts +145 -0
- package/dist/tools/cli/update.d.ts.map +1 -0
- package/dist/tools/cli/view.d.ts +12 -0
- package/dist/tools/cli/view.d.ts.map +1 -0
- package/dist/tools/cli/wait.d.ts +54 -0
- package/dist/tools/cli/wait.d.ts.map +1 -0
- package/dist/tools/connections/runtime.d.ts +1 -1
- package/dist/tools/connections/runtime.d.ts.map +1 -1
- package/dist/tools/connections/types.d.ts +3 -3
- package/dist/tools/connections/types.d.ts.map +1 -1
- package/dist/tools/durability-context.d.ts +1 -1
- package/dist/tools/durability-context.d.ts.map +1 -1
- package/dist/tools/execute-args.d.ts +23 -0
- package/dist/tools/execute-args.d.ts.map +1 -0
- package/dist/tools/execute-hooks.d.ts +146 -0
- package/dist/tools/execute-hooks.d.ts.map +1 -0
- package/dist/tools/execute-result.d.ts +40 -0
- package/dist/tools/execute-result.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +31 -193
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/internal/surface-projector.d.ts +9 -6
- package/dist/tools/internal/surface-projector.d.ts.map +1 -1
- package/dist/tools/internal/tool-view.d.ts +41 -0
- package/dist/tools/internal/tool-view.d.ts.map +1 -0
- package/dist/tools/invoker.d.ts +13 -4
- package/dist/tools/invoker.d.ts.map +1 -1
- package/dist/tools/lifecycle.d.ts +1 -1
- package/dist/tools/lifecycle.d.ts.map +1 -1
- package/dist/tools/list-names.d.ts +3 -3
- package/dist/tools/list-names.d.ts.map +1 -1
- package/dist/tools/manifest.d.ts +2 -2
- package/dist/tools/manifest.d.ts.map +1 -1
- package/dist/tools/mcp/app.d.ts +62 -0
- package/dist/tools/mcp/app.d.ts.map +1 -0
- package/dist/tools/mcp/catalog.d.ts +68 -0
- package/dist/tools/mcp/catalog.d.ts.map +1 -0
- package/dist/tools/mcp/handler.d.ts +46 -0
- package/dist/tools/mcp/handler.d.ts.map +1 -0
- package/dist/tools/mcp/mount.d.ts +152 -0
- package/dist/tools/mcp/mount.d.ts.map +1 -0
- package/dist/tools/mcp/prepare.d.ts +76 -0
- package/dist/tools/mcp/prepare.d.ts.map +1 -0
- package/dist/tools/mcp/progress.d.ts +46 -0
- package/dist/tools/mcp/progress.d.ts.map +1 -0
- package/dist/tools/mcp/register.d.ts +36 -0
- package/dist/tools/mcp/register.d.ts.map +1 -0
- package/dist/tools/mcp/round-context.d.ts +38 -0
- package/dist/tools/mcp/round-context.d.ts.map +1 -0
- package/dist/tools/mcp/round-policy.d.ts +33 -0
- package/dist/tools/mcp/round-policy.d.ts.map +1 -0
- package/dist/tools/mcp/round.d.ts +53 -0
- package/dist/tools/mcp/round.d.ts.map +1 -0
- package/dist/tools/mcp/runtime-tools.d.ts +25 -0
- package/dist/tools/mcp/runtime-tools.d.ts.map +1 -0
- package/dist/tools/mcp/stdio-signals.d.ts +33 -0
- package/dist/tools/mcp/stdio-signals.d.ts.map +1 -0
- package/dist/tools/mcp/stdio.d.ts +20 -0
- package/dist/tools/mcp/stdio.d.ts.map +1 -0
- package/dist/tools/mcp/trace.d.ts +12 -0
- package/dist/tools/mcp/trace.d.ts.map +1 -0
- package/dist/tools/mount.d.ts +14 -7
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/native-definition.d.ts +4 -3
- package/dist/tools/native-definition.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-binding-types.d.ts +127 -0
- package/dist/tools/operations/async-operation-binding-types.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-binding.d.ts +28 -0
- package/dist/tools/operations/async-operation-binding.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-canonical-types.d.ts +110 -0
- package/dist/tools/operations/async-operation-canonical-types.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-canonical.d.ts +7 -0
- package/dist/tools/operations/async-operation-canonical.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-contract.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-id.d.ts +23 -0
- package/dist/tools/operations/async-operation-id.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-runtime-tools.d.ts +41 -0
- package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-runtime-types.d.ts +69 -0
- package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -0
- package/dist/tools/operations/async-operation-runtime.d.ts +5 -0
- package/dist/tools/operations/async-operation-runtime.d.ts.map +1 -0
- package/dist/tools/operations/define-wait-tool.d.ts +22 -0
- package/dist/tools/operations/define-wait-tool.d.ts.map +1 -0
- package/dist/tools/operations/mount-wait.d.ts.map +1 -0
- package/dist/tools/operations/wait-core.d.ts.map +1 -0
- package/dist/tools/remote.d.ts +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +13 -4
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/schema/coerce.d.ts.map +1 -0
- package/dist/tools/schema/flatten-join.d.ts.map +1 -0
- package/dist/tools/schema/flatten.d.ts.map +1 -0
- package/dist/tools/schema/portable-formats.d.ts.map +1 -0
- package/dist/tools/schema/presentation.d.ts +24 -0
- package/dist/tools/schema/presentation.d.ts.map +1 -0
- package/dist/tools/schema/schema.d.ts.map +1 -0
- package/dist/tools/schema/untyped-properties.d.ts.map +1 -0
- package/dist/tools/surface.d.ts +2 -3
- package/dist/tools/surface.d.ts.map +1 -1
- package/dist/tools/tool-logger.d.ts +1 -1
- package/dist/tools/tool-logger.d.ts.map +1 -1
- package/dist/tools/toolkit.d.ts +4 -4
- package/dist/tools/toolkit.d.ts.map +1 -1
- package/dist/tools/transfer/define-download-tool.d.ts +18 -0
- package/dist/tools/transfer/define-download-tool.d.ts.map +1 -0
- package/dist/tools/transfer/define-upload-tool.d.ts +16 -0
- package/dist/tools/transfer/define-upload-tool.d.ts.map +1 -0
- package/dist/tools/transfer/define-view-file-tool.d.ts +10 -0
- package/dist/tools/transfer/define-view-file-tool.d.ts.map +1 -0
- package/dist/tools/transfer/download-core.d.ts +20 -0
- package/dist/tools/transfer/download-core.d.ts.map +1 -0
- package/dist/tools/transfer/managed-file-error.d.ts +6 -0
- package/dist/tools/transfer/managed-file-error.d.ts.map +1 -0
- package/dist/tools/transfer/mount-download.d.ts +41 -0
- package/dist/tools/transfer/mount-download.d.ts.map +1 -0
- package/dist/tools/transfer/mount-upload.d.ts +21 -0
- package/dist/tools/transfer/mount-upload.d.ts.map +1 -0
- package/dist/tools/transfer/native-result.d.ts.map +1 -0
- package/dist/tools/transfer/upload-core.d.ts +4 -0
- package/dist/tools/transfer/upload-core.d.ts.map +1 -0
- package/dist/tools/transfer/view-file-contract.d.ts.map +1 -0
- package/dist/tools/transfer/view-file.d.ts +62 -0
- package/dist/tools/transfer/view-file.d.ts.map +1 -0
- package/dist/tools/transports.d.ts +1 -1
- package/dist/tools/transports.d.ts.map +1 -1
- package/dist/tracking/client-listeners.d.ts +30 -0
- package/dist/tracking/client-listeners.d.ts.map +1 -0
- package/dist/tracking/client-visit.d.ts +61 -0
- package/dist/tracking/client-visit.d.ts.map +1 -0
- package/dist/tracking/client.d.ts +3 -2
- package/dist/tracking/client.d.ts.map +1 -1
- package/dist/tracking/contract.d.ts +1 -1
- package/dist/tracking/contract.d.ts.map +1 -1
- package/llms/agent-runtime-browser.txt +33 -0
- package/llms/agent-runtime-coding-tools.txt +58 -0
- package/llms/agent-runtime-harness.txt +45 -0
- package/llms/agent-runtime-openrouter.txt +22 -0
- package/llms/agent-runtime-sandbox.txt +159 -0
- package/llms/agent-runtime-sqlite-bun.txt +29 -0
- package/llms/agent-runtime-sqlite-node.txt +26 -0
- package/llms/agent-runtime-testing.txt +30 -0
- package/llms/agent-runtime.2.txt +550 -0
- package/llms/agent-runtime.3.txt +311 -0
- package/llms/agent-runtime.txt +893 -0
- package/llms/application-diagnostic-journal.txt +30 -0
- package/llms/application-grammy.txt +27 -0
- package/llms/application-opentelemetry.txt +27 -0
- package/llms/application-schemas.txt +42 -0
- package/llms/application.2.txt +487 -0
- package/llms/application.txt +886 -0
- package/llms/cli.2.txt +80 -0
- package/llms/cli.txt +948 -0
- package/llms/contract.txt +606 -0
- package/llms/declaration.txt +286 -0
- package/llms/files.txt +33 -0
- package/llms/geo.txt +114 -0
- package/llms/google.txt +27 -0
- package/llms/live.txt +471 -0
- package/llms/node.txt +43 -0
- package/llms/oauth.txt +136 -0
- package/llms/observability.txt +893 -0
- package/llms/primitives.txt +158 -0
- package/llms/react.txt +184 -0
- package/llms/release.txt +176 -0
- package/llms/remote.txt +25 -0
- package/llms/server.2.txt +361 -0
- package/llms/server.3.txt +1031 -0
- package/llms/server.4.txt +905 -0
- package/llms/server.5.txt +250 -0
- package/llms/server.txt +996 -0
- package/llms/stitchkit.2.txt +836 -0
- package/llms/stitchkit.3.txt +147 -0
- package/llms/stitchkit.txt +260 -0
- package/llms/telegram.txt +30 -0
- package/llms/testing.txt +676 -0
- package/llms/tools-connections.txt +45 -0
- package/llms/tools-contract.txt +9 -0
- package/llms/tools-invoker.txt +9 -0
- package/llms/tools.2.txt +647 -0
- package/llms/tools.3.txt +288 -0
- package/llms/tools.txt +966 -0
- package/llms/tracking-server.txt +32 -0
- package/llms/tracking.txt +263 -0
- package/llms/upgrading-0.37.0-0.50.0.txt +947 -0
- package/llms/upgrading-0.53.0-0.67.0.txt +1174 -0
- package/llms/upgrading-0.68.0-0.94.0.txt +1159 -0
- package/llms/upgrading.txt +215 -0
- package/llms-full.txt +312 -77
- package/llms.txt +54 -5
- package/package.json +84 -83
- package/dist/agent-runtime/durability-contract.d.ts +0 -176
- package/dist/agent-runtime/durability-contract.d.ts.map +0 -1
- package/dist/agent-runtime/durability-json.d.ts +0 -3
- package/dist/agent-runtime/durability-json.d.ts.map +0 -1
- package/dist/agent-runtime/durability-ledger.d.ts +0 -16
- package/dist/agent-runtime/durability-ledger.d.ts.map +0 -1
- package/dist/agent-runtime/durability-scheduler.d.ts +0 -29
- package/dist/agent-runtime/durability-scheduler.d.ts.map +0 -1
- package/dist/agent-runtime/durability.d.ts +0 -14
- package/dist/agent-runtime/durability.d.ts.map +0 -1
- package/dist/agent-runtime/store-driver.d.ts +0 -814
- package/dist/agent-runtime/store-driver.d.ts.map +0 -1
- package/dist/agent-runtime-browser.d.ts +0 -5
- package/dist/agent-runtime-browser.d.ts.map +0 -1
- package/dist/agent-runtime-browser.js +0 -124
- package/dist/agent-runtime-coding-tools.d.ts +0 -2
- package/dist/agent-runtime-coding-tools.d.ts.map +0 -1
- package/dist/agent-runtime-coding-tools.js +0 -23
- package/dist/agent-runtime-harness.d.ts +0 -2
- package/dist/agent-runtime-harness.d.ts.map +0 -1
- package/dist/agent-runtime-harness.js +0 -729
- package/dist/agent-runtime-openrouter.d.ts +0 -29
- package/dist/agent-runtime-openrouter.d.ts.map +0 -1
- package/dist/agent-runtime-openrouter.js +0 -270
- package/dist/agent-runtime-sandbox.d.ts +0 -5
- package/dist/agent-runtime-sandbox.d.ts.map +0 -1
- package/dist/agent-runtime-sandbox.js +0 -798
- package/dist/agent-runtime-sqlite-bun.d.ts +0 -11
- package/dist/agent-runtime-sqlite-bun.d.ts.map +0 -1
- package/dist/agent-runtime-sqlite-bun.js +0 -42
- package/dist/agent-runtime-sqlite-node.d.ts +0 -11
- package/dist/agent-runtime-sqlite-node.d.ts.map +0 -1
- package/dist/agent-runtime-sqlite-node.js +0 -44
- package/dist/agent-runtime-testing.d.ts +0 -3
- package/dist/agent-runtime-testing.d.ts.map +0 -1
- package/dist/agent-runtime-testing.js +0 -156
- package/dist/agent-runtime.d.ts +0 -38
- package/dist/agent-runtime.d.ts.map +0 -1
- package/dist/agent-runtime.js +0 -2607
- package/dist/application/channel.d.ts.map +0 -1
- package/dist/application-diagnostic-journal.d.ts +0 -21
- package/dist/application-diagnostic-journal.d.ts.map +0 -1
- package/dist/application-diagnostic-journal.js +0 -632
- package/dist/application-grammy.d.ts +0 -2
- package/dist/application-grammy.d.ts.map +0 -1
- package/dist/application-grammy.js +0 -169
- package/dist/application-opentelemetry.d.ts +0 -2
- package/dist/application-opentelemetry.d.ts.map +0 -1
- package/dist/application-opentelemetry.js +0 -250
- package/dist/application-schemas.d.ts +0 -15
- package/dist/application-schemas.d.ts.map +0 -1
- package/dist/application-schemas.js +0 -27
- package/dist/application.d.ts +0 -22
- package/dist/application.d.ts.map +0 -1
- package/dist/application.js +0 -1977
- package/dist/cli.d.ts +0 -41
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -753
- package/dist/contract/index.d.ts +0 -8
- package/dist/contract/index.d.ts.map +0 -1
- package/dist/contract/index.js +0 -55
- package/dist/declaration.d.ts.map +0 -1
- package/dist/declaration.js +0 -183
- package/dist/files.d.ts +0 -3
- package/dist/files.d.ts.map +0 -1
- package/dist/files.js +0 -15
- package/dist/geo.d.ts +0 -3
- package/dist/geo.d.ts.map +0 -1
- package/dist/geo.js +0 -245
- package/dist/google.d.ts.map +0 -1
- package/dist/google.js +0 -175
- package/dist/index-0a349c33.js +0 -470
- package/dist/index-0j3vcp5m.js +0 -28
- package/dist/index-2c2bjw3s.js +0 -51
- package/dist/index-2na0qrfn.js +0 -214
- package/dist/index-2qzskm8h.js +0 -63
- package/dist/index-3bmnp41g.js +0 -2169
- package/dist/index-3xwxfj4z.js +0 -334
- package/dist/index-4fpa9dy2.js +0 -51
- package/dist/index-6kyksz9y.js +0 -268
- package/dist/index-77fekveh.js +0 -44
- package/dist/index-7gnkny4z.js +0 -326
- package/dist/index-7zbps32p.js +0 -89
- package/dist/index-9f8ztey6.js +0 -588
- package/dist/index-a11g2kry.js +0 -866
- package/dist/index-a916km3r.js +0 -45
- package/dist/index-actkayzn.js +0 -367
- package/dist/index-bn2cjajt.js +0 -524
- package/dist/index-bx75zwt7.js +0 -63
- package/dist/index-cby4ar3v.js +0 -46
- package/dist/index-cnyk6te3.js +0 -77
- package/dist/index-cxqhvq21.js +0 -413
- package/dist/index-e0znv5gn.js +0 -176
- package/dist/index-e42wzzz5.js +0 -154
- package/dist/index-f477k430.js +0 -324
- package/dist/index-f9mb610r.js +0 -177
- package/dist/index-fadnxwna.js +0 -1046
- package/dist/index-fq77yfzc.js +0 -1303
- package/dist/index-h9etkkyk.js +0 -1126
- package/dist/index-hrbajay7.js +0 -1196
- package/dist/index-kw9t5ayn.js +0 -507
- package/dist/index-mzvgxp0n.js +0 -80
- package/dist/index-n0f51dfn.js +0 -3170
- package/dist/index-p13mwz16.js +0 -16
- package/dist/index-s8cnx02s.js +0 -90
- package/dist/index-sr93cwf9.js +0 -325
- package/dist/index-tmwcrptx.js +0 -85
- package/dist/index-v5573g1k.js +0 -142
- package/dist/index-vjpvjqpn.js +0 -86
- package/dist/index-vk3kq9sb.js +0 -3344
- package/dist/index-wc4x00bn.js +0 -103
- package/dist/index-wnfk50r0.js +0 -211
- package/dist/index-yewwh1w4.js +0 -647
- package/dist/index-yn8remb1.js +0 -290
- package/dist/index-ywd0y6m1.js +0 -394
- package/dist/index-zwkgfq1s.js +0 -345
- package/dist/index.d.ts +0 -14
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -632
- package/dist/internal/errors.d.ts +0 -92
- package/dist/internal/errors.d.ts.map +0 -1
- package/dist/internal/observability-sink.d.ts +0 -81
- package/dist/internal/observability-sink.d.ts.map +0 -1
- package/dist/live.d.ts +0 -19
- package/dist/live.d.ts.map +0 -1
- package/dist/live.js +0 -282
- package/dist/logger.d.ts.map +0 -1
- package/dist/node.d.ts +0 -18
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js +0 -303
- package/dist/oauth.d.ts +0 -57
- package/dist/oauth.d.ts.map +0 -1
- package/dist/oauth.js +0 -170
- package/dist/observability/index.d.ts +0 -19
- package/dist/observability/index.d.ts.map +0 -1
- package/dist/observability/index.js +0 -569
- package/dist/primitives.d.ts +0 -3
- package/dist/primitives.d.ts.map +0 -1
- package/dist/primitives.js +0 -754
- package/dist/react.d.ts +0 -5
- package/dist/react.d.ts.map +0 -1
- package/dist/react.js +0 -403
- package/dist/release.d.ts +0 -15
- package/dist/release.d.ts.map +0 -1
- package/dist/release.js +0 -196
- package/dist/remote.d.ts +0 -9
- package/dist/remote.d.ts.map +0 -1
- package/dist/remote.js +0 -88
- package/dist/retained.d.ts.map +0 -1
- package/dist/server/file-state-store.d.ts +0 -23
- package/dist/server/file-state-store.d.ts.map +0 -1
- package/dist/server/index.d.ts +0 -36
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -1745
- package/dist/server/request.d.ts.map +0 -1
- package/dist/telegram.d.ts +0 -3
- package/dist/telegram.d.ts.map +0 -1
- package/dist/telegram.js +0 -224
- package/dist/testing/agent-store-conformance.d.ts +0 -40
- package/dist/testing/agent-store-conformance.d.ts.map +0 -1
- package/dist/testing.d.ts +0 -39
- package/dist/testing.d.ts.map +0 -1
- package/dist/testing.js +0 -2209
- package/dist/tool-invoker.d.ts +0 -9
- package/dist/tool-invoker.d.ts.map +0 -1
- package/dist/tool-invoker.js +0 -21
- package/dist/tools/async-operation-contract.d.ts.map +0 -1
- package/dist/tools/async-operation.d.ts +0 -332
- package/dist/tools/async-operation.d.ts.map +0 -1
- package/dist/tools/cli-args.d.ts +0 -143
- package/dist/tools/cli-args.d.ts.map +0 -1
- package/dist/tools/cli-checkpoint.d.ts +0 -24
- package/dist/tools/cli-checkpoint.d.ts.map +0 -1
- package/dist/tools/cli-command.d.ts +0 -70
- package/dist/tools/cli-command.d.ts.map +0 -1
- package/dist/tools/cli-format.d.ts +0 -49
- package/dist/tools/cli-format.d.ts.map +0 -1
- package/dist/tools/cli-installer.d.ts +0 -34
- package/dist/tools/cli-installer.d.ts.map +0 -1
- package/dist/tools/cli-invoke.d.ts +0 -143
- package/dist/tools/cli-invoke.d.ts.map +0 -1
- package/dist/tools/cli-manifest.d.ts +0 -80
- package/dist/tools/cli-manifest.d.ts.map +0 -1
- package/dist/tools/cli-policy.d.ts +0 -27
- package/dist/tools/cli-policy.d.ts.map +0 -1
- package/dist/tools/cli-profile.d.ts +0 -40
- package/dist/tools/cli-profile.d.ts.map +0 -1
- package/dist/tools/cli-signature.d.ts +0 -81
- package/dist/tools/cli-signature.d.ts.map +0 -1
- package/dist/tools/cli-stream.d.ts +0 -93
- package/dist/tools/cli-stream.d.ts.map +0 -1
- package/dist/tools/cli-update.d.ts +0 -126
- package/dist/tools/cli-update.d.ts.map +0 -1
- package/dist/tools/cli-view.d.ts +0 -12
- package/dist/tools/cli-view.d.ts.map +0 -1
- package/dist/tools/cli-wait.d.ts +0 -54
- package/dist/tools/cli-wait.d.ts.map +0 -1
- package/dist/tools/cli.d.ts +0 -94
- package/dist/tools/cli.d.ts.map +0 -1
- package/dist/tools/coerce.d.ts.map +0 -1
- package/dist/tools/connections/index.d.ts +0 -20
- package/dist/tools/connections/index.d.ts.map +0 -1
- package/dist/tools/connections/index.js +0 -1107
- package/dist/tools/define-download-tool.d.ts +0 -18
- package/dist/tools/define-download-tool.d.ts.map +0 -1
- package/dist/tools/define-upload-tool.d.ts +0 -16
- package/dist/tools/define-upload-tool.d.ts.map +0 -1
- package/dist/tools/define-view-file-tool.d.ts +0 -10
- package/dist/tools/define-view-file-tool.d.ts.map +0 -1
- package/dist/tools/define-wait-tool.d.ts +0 -22
- package/dist/tools/define-wait-tool.d.ts.map +0 -1
- package/dist/tools/download-core.d.ts +0 -20
- package/dist/tools/download-core.d.ts.map +0 -1
- package/dist/tools/flatten-join.d.ts.map +0 -1
- package/dist/tools/flatten.d.ts.map +0 -1
- package/dist/tools/json-schema-dialect.d.ts +0 -17
- package/dist/tools/json-schema-dialect.d.ts.map +0 -1
- package/dist/tools/json-schema.d.ts.map +0 -1
- package/dist/tools/managed-file-error.d.ts +0 -6
- package/dist/tools/managed-file-error.d.ts.map +0 -1
- package/dist/tools/mcp-app.d.ts +0 -62
- package/dist/tools/mcp-app.d.ts.map +0 -1
- package/dist/tools/mcp-catalog.d.ts +0 -68
- package/dist/tools/mcp-catalog.d.ts.map +0 -1
- package/dist/tools/mcp-handler.d.ts +0 -46
- package/dist/tools/mcp-handler.d.ts.map +0 -1
- package/dist/tools/mcp-prepare.d.ts +0 -75
- package/dist/tools/mcp-prepare.d.ts.map +0 -1
- package/dist/tools/mcp-progress.d.ts +0 -46
- package/dist/tools/mcp-progress.d.ts.map +0 -1
- package/dist/tools/mcp-round-policy.d.ts +0 -33
- package/dist/tools/mcp-round-policy.d.ts.map +0 -1
- package/dist/tools/mcp-round.d.ts +0 -61
- package/dist/tools/mcp-round.d.ts.map +0 -1
- package/dist/tools/mcp-stdio-signals.d.ts +0 -33
- package/dist/tools/mcp-stdio-signals.d.ts.map +0 -1
- package/dist/tools/mcp-stdio.d.ts +0 -20
- package/dist/tools/mcp-stdio.d.ts.map +0 -1
- package/dist/tools/mcp-trace.d.ts +0 -12
- package/dist/tools/mcp-trace.d.ts.map +0 -1
- package/dist/tools/mcp.d.ts +0 -152
- package/dist/tools/mcp.d.ts.map +0 -1
- package/dist/tools/mount-download.d.ts +0 -41
- package/dist/tools/mount-download.d.ts.map +0 -1
- package/dist/tools/mount-upload.d.ts +0 -21
- package/dist/tools/mount-upload.d.ts.map +0 -1
- package/dist/tools/mount-wait.d.ts.map +0 -1
- package/dist/tools/native-mcp.d.ts +0 -20
- package/dist/tools/native-mcp.d.ts.map +0 -1
- package/dist/tools/native-result.d.ts.map +0 -1
- package/dist/tools/oauth-metadata.d.ts +0 -28
- package/dist/tools/oauth-metadata.d.ts.map +0 -1
- package/dist/tools/oauth-provider.d.ts +0 -184
- package/dist/tools/oauth-provider.d.ts.map +0 -1
- package/dist/tools/portable-formats.d.ts.map +0 -1
- package/dist/tools/presentation.d.ts +0 -22
- package/dist/tools/presentation.d.ts.map +0 -1
- package/dist/tools/schema.d.ts.map +0 -1
- package/dist/tools/untyped-properties.d.ts.map +0 -1
- package/dist/tools/upload-core.d.ts +0 -4
- package/dist/tools/upload-core.d.ts.map +0 -1
- package/dist/tools/view-file-contract.d.ts.map +0 -1
- package/dist/tools/view-file.d.ts +0 -62
- package/dist/tools/view-file.d.ts.map +0 -1
- package/dist/tools/wait-core.d.ts.map +0 -1
- package/dist/tools-contract.d.ts +0 -29
- package/dist/tools-contract.d.ts.map +0 -1
- package/dist/tools-contract.js +0 -24
- package/dist/tools.d.ts +0 -50
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -2930
- package/dist/tracking-server.d.ts +0 -15
- package/dist/tracking-server.d.ts.map +0 -1
- package/dist/tracking.d.ts +0 -24
- package/dist/tracking.d.ts.map +0 -1
- package/dist/tracking.js +0 -1092
- package/dist/upgrade-cli.d.ts.map +0 -1
- package/dist/upgrade-cli.js +0 -177
- /package/dist/{retained.d.ts → browser/retained.d.ts} +0 -0
- /package/dist/{declaration.d.ts → declaration/declaration.d.ts} +0 -0
- /package/dist/{upgrade-cli.d.ts → entrypoints/bin/upgrade-cli.d.ts} +0 -0
- /package/dist/{tracking-server.js → entrypoints/tracking/server.js} +0 -0
- /package/dist/{google.d.ts → google/google.d.ts} +0 -0
- /package/dist/{index-pq95qkbf.js → index-5jm36zv1.js} +0 -0
- /package/dist/{application → internal}/channel.d.ts +0 -0
- /package/dist/{logger.d.ts → internal/logger.d.ts} +0 -0
- /package/dist/{server → internal}/request.d.ts +0 -0
- /package/dist/{tools → json-schema}/json-schema.d.ts +0 -0
- /package/dist/tools/{async-operation-contract.d.ts → operations/async-operation-contract.d.ts} +0 -0
- /package/dist/tools/{mount-wait.d.ts → operations/mount-wait.d.ts} +0 -0
- /package/dist/tools/{wait-core.d.ts → operations/wait-core.d.ts} +0 -0
- /package/dist/tools/{coerce.d.ts → schema/coerce.d.ts} +0 -0
- /package/dist/tools/{flatten-join.d.ts → schema/flatten-join.d.ts} +0 -0
- /package/dist/tools/{flatten.d.ts → schema/flatten.d.ts} +0 -0
- /package/dist/tools/{portable-formats.d.ts → schema/portable-formats.d.ts} +0 -0
- /package/dist/tools/{schema.d.ts → schema/schema.d.ts} +0 -0
- /package/dist/tools/{untyped-properties.d.ts → schema/untyped-properties.d.ts} +0 -0
- /package/dist/tools/{native-result.d.ts → transfer/native-result.d.ts} +0 -0
- /package/dist/tools/{view-file-contract.d.ts → transfer/view-file-contract.d.ts} +0 -0
|
@@ -0,0 +1,905 @@
|
|
|
1
|
+
# stitchkit/server — stitchkit docs slice, part 4 of 5
|
|
2
|
+
|
|
3
|
+
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
|
+
> `llms.txt` in this package.
|
|
5
|
+
> Continues in `llms/server.5.txt`.
|
|
6
|
+
|
|
7
|
+
Parts of this slice:
|
|
8
|
+
- `llms/server.txt`: Guide: HTTP server (docs/guide/server.md)
|
|
9
|
+
- `llms/server.2.txt`: Guide: HTTP server (docs/guide/server.md)
|
|
10
|
+
- `llms/server.3.txt`: Guide: Realtime (docs/guide/realtime.md)
|
|
11
|
+
- `llms/server.4.txt`: Guide: Auth & errors (docs/guide/auth-and-errors.md) · Guide: Multi-tenant (docs/guide/multi-tenant.md)
|
|
12
|
+
- `llms/server.5.txt`: API reference: `stitchkit/server` (docs/api/reference.md)
|
|
13
|
+
|
|
14
|
+
Also read:
|
|
15
|
+
- see `llms/testing.txt` for the Testing & deployment guide
|
|
16
|
+
|
|
17
|
+
==============================================================================
|
|
18
|
+
# Guide: Auth & errors (docs/guide/auth-and-errors.md)
|
|
19
|
+
==============================================================================
|
|
20
|
+
|
|
21
|
+
# Auth & errors
|
|
22
|
+
|
|
23
|
+
Client-side login/session operations may legitimately answer `401`. Declare
|
|
24
|
+
that policy with contract-owned matchers instead of path strings:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const http = createHttpClient({
|
|
28
|
+
baseUrl,
|
|
29
|
+
suppressUnauthorizedFor: contractEndpointMatchers(publicAuth, ['login', 'verify']),
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Only the selected operations suppress the global `unauthorized` event; a 401
|
|
34
|
+
from any neighbouring protected route still signals session expiry.
|
|
35
|
+
|
|
36
|
+
stitchkit carries no domain model — it does not know what a user is. What it
|
|
37
|
+
provides is the *control flow*: a scope on every endpoint, one hook that
|
|
38
|
+
enforces it, and one error model shared by every transport. The identity and
|
|
39
|
+
the scope vocabulary are yours.
|
|
40
|
+
|
|
41
|
+
## Scopes
|
|
42
|
+
|
|
43
|
+
An endpoint declares a `scope` — a free string. The contract `meta.scope` is the
|
|
44
|
+
default for endpoints that declare none. (Authored through
|
|
45
|
+
[`createContractFactory<Scope>()`](./contracts.md#scope), both the contract's
|
|
46
|
+
scope and any endpoint override are held to your own union instead.)
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
export const posts = defineContract({ prefix: 'posts', scope: 'user' }, {
|
|
50
|
+
list: { method: 'GET', path: '/', desc: 'List posts', scope: 'public', output: /* … */ },
|
|
51
|
+
create: { method: 'POST', path: '/', desc: 'Create', /* inherits 'user' */ },
|
|
52
|
+
remove: { method: 'DELETE', path: '/:id', desc: 'Delete', scope: 'admin' },
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The framework attaches no meaning to the strings — `'public'`, `'user'`,
|
|
57
|
+
`'admin'` mean whatever your auth hook decides.
|
|
58
|
+
|
|
59
|
+
## `createAuthHook`
|
|
60
|
+
|
|
61
|
+
`createAuthHook` builds one scope gate that can run in both HTTP and tool
|
|
62
|
+
lifecycles. On HTTP it belongs in `hooks.authorize`: Stitchkit validates path
|
|
63
|
+
params, resolves identity and scope, and rejects `401`/`403` **before reading a
|
|
64
|
+
JSON or multipart body**. On MCP, agent and CLI surfaces it belongs in
|
|
65
|
+
`lifecycle.beforeHandle`, because those transports have already received their
|
|
66
|
+
arguments before the common tool runner starts.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createAuthHook, createServer } from 'stitchkit/server'
|
|
70
|
+
|
|
71
|
+
const authHook = createAuthHook<User>({
|
|
72
|
+
resolve: (ctx) => resolveSession(ctx), // → a User, or null
|
|
73
|
+
rules: {
|
|
74
|
+
public: 'public', // always pass
|
|
75
|
+
user: 'authenticated', // any resolved identity passes
|
|
76
|
+
admin: (user) => user.isAdmin, // custom predicate
|
|
77
|
+
},
|
|
78
|
+
inject: (ctx, user) => { ctx.user = user },
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
createServer({ services, hooks: { authorize: authHook } })
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `AuthRule`
|
|
85
|
+
|
|
86
|
+
The value of each `rules` entry, keyed by scope:
|
|
87
|
+
|
|
88
|
+
- **`'public'`** — always passes; the identity is attached if present.
|
|
89
|
+
- **`'authenticated'`** — any resolved identity passes; no identity ⇒ 401.
|
|
90
|
+
- **a function** `(identity, ctx) => boolean | contribution`, sync or async — a custom
|
|
91
|
+
check. It receives request metadata and validated path params, so a
|
|
92
|
+
resource-scoped rule can do a DB lookup. It cannot read `input` or files: the
|
|
93
|
+
body has deliberately not been consumed yet. `false` denies, `true` passes,
|
|
94
|
+
and a returned plain object passes and contributes inferred handler fields.
|
|
95
|
+
|
|
96
|
+
#### Resource-scoped rule — reading a path/prefix param
|
|
97
|
+
|
|
98
|
+
For a multi-tenant API (`pathPrefix: '/tenants/:tenantId'`, see
|
|
99
|
+
[Route groups → param prefixes](./server.md#param-prefixes-resource-scoped-paths)),
|
|
100
|
+
the rule gates access to the tenant in the path. A `:param` from the group prefix
|
|
101
|
+
or the endpoint is on the **context root** as `ctx.<name>` (a raw `string`):
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
const authHook = createAuthHook<User>({
|
|
105
|
+
resolve: sessionResolver,
|
|
106
|
+
rules: {
|
|
107
|
+
public: 'public',
|
|
108
|
+
// gate the tenant in the path — ctx.tenantId comes from the group prefix
|
|
109
|
+
tenant: async (user, ctx) => userCanAccessTenant(user.id, String(ctx.tenantId)),
|
|
110
|
+
} satisfies Record<Scope, AuthRule<User>>,
|
|
111
|
+
// derive per-request facts onto ctx for handlers (role within this tenant, …)
|
|
112
|
+
inject: async (ctx, user) => {
|
|
113
|
+
ctx.user = user
|
|
114
|
+
if (user) ctx.tenantRole = await roleInTenant(user.id, String(ctx.tenantId))
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`inject` runs on every request (identity may be `null`) — use it to put the
|
|
120
|
+
identity *and* any derived values (role, parent-id) on `ctx` for handlers. Read
|
|
121
|
+
them back as `ctx.tenantRole` (typed `unknown` — narrow at the read site). The
|
|
122
|
+
endpoints under the group declare `scope: 'tenant'`.
|
|
123
|
+
|
|
124
|
+
When the async authorization lookup already produced handler data, return it
|
|
125
|
+
instead of repeating the lookup in `inject` and a handwritten scope map:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const auth = createAuthHook({
|
|
129
|
+
resolve: sessionResolver,
|
|
130
|
+
rules: {
|
|
131
|
+
project: async (user, ctx) => {
|
|
132
|
+
const membership = await findMembership(user.id, String(ctx.projectId))
|
|
133
|
+
return membership
|
|
134
|
+
? { userId: user.id, projectId: membership.projectId, role: membership.role }
|
|
135
|
+
: false
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
const implementFor = createScopedImplement<AuthScopes<typeof auth>>()
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Contributions are merged only after full validation. Runtime-owned context keys,
|
|
144
|
+
arrays, class instances, accessors, symbols, unsafe prototypes and partial proxy
|
|
145
|
+
reads fail without mutating context. `false | object` contributes required
|
|
146
|
+
fields; `true | object` correctly makes them optional.
|
|
147
|
+
|
|
148
|
+
### `AuthHookConfig`
|
|
149
|
+
|
|
150
|
+
| Field | Purpose |
|
|
151
|
+
|-------|---------|
|
|
152
|
+
| `resolve` | `(ctx) => identity \| null` — HTTP identity from `ctx.req` (cookie / bearer + lookup) |
|
|
153
|
+
| `resolveFromContext` | `(ctx) => identity \| null` — identity on a tool call (no `req`) |
|
|
154
|
+
| `rules` | access rule per scope; `endpoint.scope` is the key |
|
|
155
|
+
| `defaultScope` | scope applied when an endpoint declares none |
|
|
156
|
+
| `inject` | write the resolved identity onto `ctx` for handlers |
|
|
157
|
+
| `onAnonymous` | thrown when a scope needs an identity and there is none (default 401) |
|
|
158
|
+
| `onForbidden` | thrown when an identity is present but the rule rejects it (default 403) |
|
|
159
|
+
|
|
160
|
+
Annotate `rules` with `satisfies Record<MyScope, AuthRule<User>>` so the compiler
|
|
161
|
+
catches a scope you forgot to cover. With the scoped rule objects below, widen
|
|
162
|
+
the annotation to
|
|
163
|
+
`satisfies Record<MyScope, AuthRule<User> | ScopedAuthRule<User, AuthRuleContribution>>`
|
|
164
|
+
— it keeps the coverage check and does not disturb the derivation. (When every
|
|
165
|
+
scope comes from the derived map, the check is already implicit: a scope missing
|
|
166
|
+
from `rules` is no key of the map, and a contract using it fails to compile.)
|
|
167
|
+
|
|
168
|
+
### Scoped rules — the map `createScopedImplement` consumes
|
|
169
|
+
|
|
170
|
+
A rule may take an object form, `{ rule, inject }`, where `inject` **returns**
|
|
171
|
+
the fields this scope contributes. That return type is a declaration the hook
|
|
172
|
+
derives a scope→context map from — feed it to
|
|
173
|
+
[`createScopedImplement`](./server.md#per-scope-handler-context--createscopedimplement)
|
|
174
|
+
and the map can never drift from the hook, because it is computed from it:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const authHook = createAuthHook({
|
|
178
|
+
resolve: sessionResolver, // no explicit generic — let it infer
|
|
179
|
+
rules: {
|
|
180
|
+
public: { rule: 'public', inject: (user) => ({ userId: user.id }) },
|
|
181
|
+
user: { rule: 'authenticated', inject: (user) => ({ userId: user.id }) },
|
|
182
|
+
admin: {
|
|
183
|
+
rule: (user) => user.admin,
|
|
184
|
+
inject: (user) => ({ userId: user.id, isAdmin: user.admin }),
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
export const implementFor = createScopedImplement<AuthScopes<typeof authHook>>()
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- A `'public'` rule's fields come out **optional**: public admits the anonymous
|
|
193
|
+
caller, it does not refuse to know the logged-in one — `resolve` and `inject`
|
|
194
|
+
still run, so a public `me` / `logout` handler reads `ctx.userId` as
|
|
195
|
+
`string | undefined` and narrows, instead of being pushed toward a cast by a
|
|
196
|
+
`public: object` map.
|
|
197
|
+
- Any other rule's fields are required — the rule rejected the request before
|
|
198
|
+
the handler if no identity resolved.
|
|
199
|
+
- A scope with no rule is no key of the derived map, so a contract using it
|
|
200
|
+
fails to compile — the type-level mirror of the hook's fail-closed
|
|
201
|
+
`no rule for scope` throw.
|
|
202
|
+
|
|
203
|
+
The per-rule `inject` runs after the shared one, only when an identity
|
|
204
|
+
resolved, and **before** the rule check — it may run for an identity the rule
|
|
205
|
+
then rejects, so keep it pure and synchronous (an async `inject` is a compile
|
|
206
|
+
error, and a runtime one for untyped callers: merging a Promise would merge
|
|
207
|
+
nothing). Write rule objects inline in `rules` — a hoisted, annotated rule
|
|
208
|
+
widens its inject and degrades that scope's fields to `object`.
|
|
209
|
+
|
|
210
|
+
Derivation needs the identity generic to be **inferred** (write no explicit
|
|
211
|
+
`createAuthHook<User>` — TypeScript has no partial inference); with an explicit
|
|
212
|
+
generic, or fields injected outside the hook, keep the hand-written map.
|
|
213
|
+
→ ADR 0078
|
|
214
|
+
|
|
215
|
+
### Multiple auth domains — `composeAuthHooks`
|
|
216
|
+
|
|
217
|
+
Independent identity domains should keep separate resolvers and rules. Compose
|
|
218
|
+
their canonical hooks and derive one handler context without a manual dispatcher
|
|
219
|
+
or scope-map intersection:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
const userAuth = createAuthHook({
|
|
223
|
+
resolve: resolveUser,
|
|
224
|
+
resolveFromContext: resolveToolUser,
|
|
225
|
+
rules: {
|
|
226
|
+
user: (user) => ({ userId: user.id }),
|
|
227
|
+
workspace: (user) => ({ userId: user.id }),
|
|
228
|
+
},
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
const workspaceAuth = createAuthHook({
|
|
232
|
+
resolve: resolveMembership,
|
|
233
|
+
resolveFromContext: resolveToolMembership,
|
|
234
|
+
rules: {
|
|
235
|
+
workspace: (membership) => ({ workspaceId: membership.workspaceId }),
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
export const auth = composeAuthHooks({
|
|
240
|
+
hooks: [userAuth, workspaceAuth],
|
|
241
|
+
defaultScope: 'user',
|
|
242
|
+
})
|
|
243
|
+
export const implementFor = createScopedImplement<AuthScopes<typeof auth>>()
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Only hooks that declare the selected scope run. An unknown scope fails closed;
|
|
247
|
+
when several hooks own one scope, every owner must pass in declaration order.
|
|
248
|
+
Each owner evaluates on an isolated shadow context. Stitchkit validates all
|
|
249
|
+
changed fields, rejects reserved/unsafe fields and cross-owner key collisions,
|
|
250
|
+
then commits the combined contribution once. A rejected or cancelled composite
|
|
251
|
+
therefore exposes no partial fields to the handler.
|
|
252
|
+
|
|
253
|
+
Isolation is per-key, not deep: a contribution is the set of context keys whose
|
|
254
|
+
descriptor changed. Mutating an existing value **in place**
|
|
255
|
+
(`ctx.user.role = 'admin'`) edits the object every owner already shares, so it
|
|
256
|
+
is neither reported as a contribution nor checked for collisions — contribute
|
|
257
|
+
new fields instead of editing another owner's object. External side effects
|
|
258
|
+
likewise remain consumer-owned and are not rolled back.
|
|
259
|
+
|
|
260
|
+
The composite's `defaultScope` is the only implicit scope. A child hook's own
|
|
261
|
+
default must be absent or equal to it, so reordering hooks cannot change which
|
|
262
|
+
scope protects an endpoint.
|
|
263
|
+
|
|
264
|
+
### Auth on the tool surface — `resolveFromContext`
|
|
265
|
+
|
|
266
|
+
The same hook guards every transport, but the lifecycle slot and identity
|
|
267
|
+
source differ:
|
|
268
|
+
|
|
269
|
+
- **HTTP** — `hooks.authorize` calls `resolve(ctx)` from `ctx.req` (a cookie or
|
|
270
|
+
bearer token) before body parsing.
|
|
271
|
+
- **Tool calls (MCP / agent)** — there is no `req`. The transport authenticated
|
|
272
|
+
the caller (an MCP API key) and `buildMcpServer`'s `context` injected the
|
|
273
|
+
identity into `ctx`. `lifecycle.beforeHandle` calls
|
|
274
|
+
`resolveFromContext(ctx)` to locate it.
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
const authHook = createAuthHook<User>({
|
|
278
|
+
resolve: (ctx) => resolveSession(ctx), // HTTP — from ctx.req
|
|
279
|
+
resolveFromContext: (ctx) => ctx.user ?? null, // tool — from injected ctx
|
|
280
|
+
rules: { public: 'public', user: 'authenticated', admin: (u) => u.isAdmin },
|
|
281
|
+
})
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
The **scope check is identical** on both surfaces — only identity resolution
|
|
285
|
+
differs. If you omit `resolveFromContext`, a scoped tool call has no identity
|
|
286
|
+
and **fails closed** (rejected by `onAnonymous`) — the hook never silently
|
|
287
|
+
passes a tool call it cannot authenticate. → [ADR 0014](../decisions/0014-tool-http-parity.md)
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
createServer({ services, hooks: { authorize: authHook } })
|
|
291
|
+
createMcpHandler({ services, lifecycle: { beforeHandle: authHook } })
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## `createBearerResolver`
|
|
295
|
+
|
|
296
|
+
For API-key or bearer-token auth (the usual MCP case), `createBearerResolver`
|
|
297
|
+
strips `Authorization: Bearer <token>` and hands the raw token to your lookup:
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import { createBearerResolver } from 'stitchkit/server'
|
|
301
|
+
|
|
302
|
+
const resolve = createBearerResolver<User>({
|
|
303
|
+
lookup: (token, req) => db.apiKeys.resolve(token), // → User, or null
|
|
304
|
+
})
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Use it as `createMcpHandler`'s `auth`, or inside `createAuthHook`'s `resolve`.
|
|
308
|
+
|
|
309
|
+
## JWT
|
|
310
|
+
|
|
311
|
+
`verifyJwt(token, secret)` verifies an HS256 JWT and returns its payload, or
|
|
312
|
+
throws `unauthorized`. It pins the algorithm (the token's own `alg` can never
|
|
313
|
+
pick the scheme), and checks `exp` and `nbf`.
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
import { verifyJwt, extractToken } from 'stitchkit/server'
|
|
317
|
+
import { env } from './env'
|
|
318
|
+
|
|
319
|
+
const token = extractToken(req) // from Authorization, or a cookie name
|
|
320
|
+
if (!token) throw unauthorized('Bearer token is required')
|
|
321
|
+
const payload = await verifyJwt(token, env.JWT_SECRET)
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
`extractToken(req, cookieName?)` reads a bearer token from the `Authorization`
|
|
325
|
+
header, or from the named cookie.
|
|
326
|
+
|
|
327
|
+
## Telegram Mini Apps
|
|
328
|
+
|
|
329
|
+
A Mini App hands its backend an `initData` query string that Telegram signed
|
|
330
|
+
with a key derived from the bot token. `verifyTelegramInitData` checks that
|
|
331
|
+
signature and reports what the string says — and refuses with a **reason**,
|
|
332
|
+
because an application answers a stale string differently from a forged one.
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
import { verifyTelegramInitData } from 'stitchkit/telegram'
|
|
336
|
+
import { unauthorized } from 'stitchkit/contract'
|
|
337
|
+
import { env } from './env'
|
|
338
|
+
|
|
339
|
+
const result = await verifyTelegramInitData({
|
|
340
|
+
initData,
|
|
341
|
+
botToken: env.BOT_TOKEN,
|
|
342
|
+
maxAgeSeconds: 3600, // a signed string is otherwise valid forever
|
|
343
|
+
})
|
|
344
|
+
if (!result.valid) {
|
|
345
|
+
// 'missing-hash' | 'signature-mismatch' | 'malformed' | 'expired'
|
|
346
|
+
throw unauthorized(result.reason === 'expired' ? 'Reopen the app' : 'Invalid session')
|
|
347
|
+
}
|
|
348
|
+
const telegramId = result.data.user?.id
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Three things it does that a hand-written check usually does not:
|
|
352
|
+
|
|
353
|
+
- the **signature is checked first**, before `auth_date` or anything else is
|
|
354
|
+
read — an expiry inside an unverified payload is a number the sender chose;
|
|
355
|
+
- digests are compared **without an early exit**, so the time a rejection takes
|
|
356
|
+
is not a measurement of how much of the digest was right;
|
|
357
|
+
- `raw` keeps every signed pair, so a field Telegram adds after this release
|
|
358
|
+
does not need a release to reach.
|
|
359
|
+
|
|
360
|
+
`maxAgeSeconds` is optional and there is no default: only the application knows
|
|
361
|
+
how long its own session is worth. Omitting it means the string never expires,
|
|
362
|
+
which is a decision rather than an oversight.
|
|
363
|
+
|
|
364
|
+
The module is server-only and pulls in no bot library — the token never belongs
|
|
365
|
+
in a browser bundle. `stitchkit/application/grammy` remains the lifecycle
|
|
366
|
+
adapter for an injected grammY bot. Its companion,
|
|
367
|
+
`classifyTelegramSendFailure`, names why a send was refused and separates *retry
|
|
368
|
+
this send* from *stop addressing this recipient*:
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
import { classifyTelegramSendFailure } from 'stitchkit/telegram'
|
|
372
|
+
|
|
373
|
+
try {
|
|
374
|
+
await bot.api.sendMessage(chatId, text)
|
|
375
|
+
} catch (error) {
|
|
376
|
+
const failure = classifyTelegramSendFailure(error)
|
|
377
|
+
if (failure.recipientUnreachable) await markUnreachable(chatId, failure.reason)
|
|
378
|
+
else if (failure.retryable) await requeue(chatId, failure.retryAfterSeconds)
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
The two flags are separate because one answer cannot serve both. A rate limit is
|
|
383
|
+
retryable and implicates nobody; a blocked user is unreachable and no retry
|
|
384
|
+
helps; a message Telegram could not parse is *neither* — the recipient is fine
|
|
385
|
+
and our payload is wrong, which is the case a list of substrings quietly counts
|
|
386
|
+
against the user. An unrecognised refusal leaves the recipient reachable: losing
|
|
387
|
+
a working subscriber forever costs more than one wasted send.
|
|
388
|
+
|
|
389
|
+
## Cookies
|
|
390
|
+
|
|
391
|
+
```ts
|
|
392
|
+
import { defineCookie } from 'stitchkit/server'
|
|
393
|
+
|
|
394
|
+
const session = defineCookie({ name: 'sid', httpOnly: true, secure: true, sameSite: 'Lax', path: '/' })
|
|
395
|
+
|
|
396
|
+
session.get(req) // string | undefined
|
|
397
|
+
session.set('abc123') // → a Set-Cookie header value
|
|
398
|
+
session.clear() // → a Set-Cookie value that expires it
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
`defineCookie` bundles a cookie's name and options into a typed handle, so the
|
|
402
|
+
config is not repeated at every call site. `parseCookies(header)`,
|
|
403
|
+
`parseCookieHeader(header)` and `serializeCookie(name, value, opts)` are the
|
|
404
|
+
lower-level primitives.
|
|
405
|
+
|
|
406
|
+
**Two cookies, one name.** A browser sends every cookie whose domain and path
|
|
407
|
+
match, so a `sid` on `.example.com` and a `sid` on `app.example.com` both arrive
|
|
408
|
+
— in an order the browser chooses (RFC 6265 §5.4) and a server should not rely
|
|
409
|
+
on (§4.2.2). `get` returns the **last** one by default, which is a fact of the
|
|
410
|
+
header order, not a rule: the same session then validates in one browser and
|
|
411
|
+
not in another. Name the behaviour you rely on, or refuse to guess:
|
|
412
|
+
|
|
413
|
+
```ts
|
|
414
|
+
const session = defineCookie({ name: 'sid', domain: '.example.com', duplicates: 'reject' })
|
|
415
|
+
|
|
416
|
+
session.get(req) // undefined when two *different* values arrive; the one value when they agree
|
|
417
|
+
session.getAll(req) // every candidate, in header order — validate each, clear the loser
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
`duplicates: 'reject'` turns the lottery into "no session", which a login page
|
|
421
|
+
handles; `'first'` and `'last'` exist so an application can state which coin it
|
|
422
|
+
flips. For a session cookie on a parent domain the durable fix is `getAll`:
|
|
423
|
+
validate each candidate and answer with `clear()` for the one that lost, so the
|
|
424
|
+
next request carries one.
|
|
425
|
+
|
|
426
|
+
To set a cookie from a schema-validated JSON endpoint without losing its typed
|
|
427
|
+
client result, declare [`responseMeta`](./server.md#typed-json-response-metadata)
|
|
428
|
+
and append the generated value:
|
|
429
|
+
|
|
430
|
+
```ts
|
|
431
|
+
complete: async ({ response }) => {
|
|
432
|
+
response.headers.append('Set-Cookie', session.set('abc123'))
|
|
433
|
+
return authenticatedUser
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Append once per cookie; Stitchkit preserves separate `Set-Cookie` fields through
|
|
438
|
+
both Bun and Node. Cookie/session policy remains application logic.
|
|
439
|
+
|
|
440
|
+
## The error model
|
|
441
|
+
|
|
442
|
+
One error type, `AppError`, is shared by the contract, the server and the
|
|
443
|
+
client. It carries a stable `code`, an HTTP `status`, and optional structured
|
|
444
|
+
`details` and a `hint`.
|
|
445
|
+
|
|
446
|
+
### Throwing errors
|
|
447
|
+
|
|
448
|
+
Throw `AppError` directly, or use a typed helper — the idiomatic path:
|
|
449
|
+
|
|
450
|
+
| Helper | Status | Code |
|
|
451
|
+
|--------|--------|------|
|
|
452
|
+
| `notFound(message?)` | 404 | `NOT_FOUND` |
|
|
453
|
+
| `badRequest(message, details?)` | 400 | `BAD_REQUEST` |
|
|
454
|
+
| `unauthorized(message?)` | 401 | `UNAUTHORIZED` |
|
|
455
|
+
| `forbidden(message?)` | 403 | `FORBIDDEN` |
|
|
456
|
+
| `conflict(message?, details?)` | 409 | `CONFLICT` |
|
|
457
|
+
| `rateLimited(message?)` | 429 | `RATE_LIMITED` |
|
|
458
|
+
| `appError(code, message?, details?)` | mapped, else 500 | any `code` |
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
import { notFound, badRequest } from 'stitchkit/server'
|
|
462
|
+
|
|
463
|
+
const note = db.get(ctx.params.id)
|
|
464
|
+
if (!note) notFound('Note not found')
|
|
465
|
+
if (ctx.input.title.length > 200) badRequest('Title too long', { max: 200 })
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Each helper has a `never` return type — TypeScript knows execution stops, so the
|
|
469
|
+
code after it is correctly narrowed.
|
|
470
|
+
|
|
471
|
+
You can subclass `AppError` for a domain error model (`class FeatureLocked extends
|
|
472
|
+
AppError`). `AppError.is(err)` identifies any instance — a direct one, a subclass,
|
|
473
|
+
even a copy from another bundle chunk or realm — by a global brand rather than
|
|
474
|
+
`instanceof`, so a domain error keeps its `code` / `details` / `hint` on every
|
|
475
|
+
transport (HTTP, MCP, agent). → ADR 0032.
|
|
476
|
+
|
|
477
|
+
### The error envelope
|
|
478
|
+
|
|
479
|
+
`AppError.toJSON()` renders the public envelope every transport returns:
|
|
480
|
+
|
|
481
|
+
```json
|
|
482
|
+
{ "error": { "code": "NOT_FOUND", "message": "Note not found" } }
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
`details` and `hint` are included when present. On HTTP this is the response
|
|
486
|
+
body with the matching status; for an MCP or agent call the same `code` and
|
|
487
|
+
`details` come back as a tool error. A schema-validation failure on the request
|
|
488
|
+
is turned into a `400 VALIDATION_ERROR` automatically — and it carries the
|
|
489
|
+
offending fields as structured `details.issues`, so a machine client matches on
|
|
490
|
+
them instead of parsing the text `message`:
|
|
491
|
+
|
|
492
|
+
`path` and `code` are the framework's. **`message` is not** — it is `issue.message`
|
|
493
|
+
as Zod produced it, so for a `.refine()` it is whatever the schema's author wrote.
|
|
494
|
+
The framework never puts a submitted value into it, and its own messages describe
|
|
495
|
+
types rather than values (`expected string, received undefined`, `Invalid UUID`),
|
|
496
|
+
but that is a property of today's messages, not a guarantee anyone is in a
|
|
497
|
+
position to make: the text belongs to whoever declared the schema. Forward `path`
|
|
498
|
+
and `code` to an end user freely; treat `message` as internal unless you wrote
|
|
499
|
+
every refine in the contract.
|
|
500
|
+
|
|
501
|
+
```json
|
|
502
|
+
{
|
|
503
|
+
"error": {
|
|
504
|
+
"code": "VALIDATION_ERROR",
|
|
505
|
+
"message": "name: Invalid input\nage: Invalid input",
|
|
506
|
+
"details": {
|
|
507
|
+
"issues": [
|
|
508
|
+
{ "path": "name", "code": "invalid_type", "message": "Invalid input" },
|
|
509
|
+
{ "path": "age", "code": "invalid_type", "message": "Invalid input" }
|
|
510
|
+
]
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Use the exported `zodIssues(error)` to build the same structured list from a
|
|
517
|
+
`ZodError` in your own hook.
|
|
518
|
+
|
|
519
|
+
### On the client
|
|
520
|
+
|
|
521
|
+
The client parses that envelope back into an `ApiError` with the same `code`,
|
|
522
|
+
`status`, `details` and `hint`, plus the response `x-request-id` as optional
|
|
523
|
+
readonly `traceId` — see [Typed client → ApiError](./client.md#apierror). The
|
|
524
|
+
error round-trips without adding correlation data to the response body.
|
|
525
|
+
|
|
526
|
+
### Stitch codes vs your codes
|
|
527
|
+
|
|
528
|
+
A `code` is a free string — your app codes (`BOT_NOT_FOUND`, …) are yours and the
|
|
529
|
+
core never models them (ADR 0002). But stitchkit itself emits a set of its own:
|
|
530
|
+
`BAD_REQUEST`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `METHOD_NOT_ALLOWED`,
|
|
531
|
+
`CONFLICT`, `RATE_LIMITED`, `VALIDATION_ERROR`, `FILE_INVALID_PATH`,
|
|
532
|
+
`FILE_OUTSIDE_ROOT`, `FILE_NOT_FOUND`, `FILE_NOT_REGULAR`,
|
|
533
|
+
`FILE_INSPECTION_REJECTED`, `FILE_TOO_LARGE`, `FILE_EXISTS`,
|
|
534
|
+
`REALTIME_CONTRACT_VIOLATION`, `APPLICATION_NOT_ACCEPTING`, `NOT_IMPLEMENTED`,
|
|
535
|
+
`WAIT_TIMEOUT`,
|
|
536
|
+
`WAIT_FAILED`, `DOWNLOAD_NOT_FOUND`, `VIEW_HTTP_ERROR`,
|
|
537
|
+
`OPERATION_NOT_SUCCEEDED`, `STREAM_ITEM_INVALID`, `STREAM_FRAME_TOO_LARGE`,
|
|
538
|
+
`STREAM_TERMINAL_MISSING`, `STREAM_LIFETIME_EXCEEDED`,
|
|
539
|
+
`GRAMMY_WEBHOOK_NOT_ACCEPTING`, `SANDBOX_UNAVAILABLE`, `SANDBOX_INSUFFICIENT`,
|
|
540
|
+
`SPILL_REFERENCE_UNKNOWN`, `INTERNAL_SERVER_ERROR` — a set that grows in
|
|
541
|
+
ordinary releases, each addition named in the changelog. They are
|
|
542
|
+
published as **`STITCH_ERROR_STATUS`** (the `code → status` map) and
|
|
543
|
+
**`StitchErrorCode`** (its `keyof`), with **`isStitchErrorCode()`** (→ ADR 0026).
|
|
544
|
+
|
|
545
|
+
> This list is enumerated here for reading, and the enumeration is what goes
|
|
546
|
+
> stale — it once dropped `APPLICATION_NOT_ACCEPTING`, which made the map below
|
|
547
|
+
> stop compiling. `Object.keys(STITCH_ERROR_STATUS)` is the answer that cannot;
|
|
548
|
+
> `packages/core/tests/error-registry-completeness.test.ts` keeps the registry
|
|
549
|
+
> itself complete against the source.
|
|
550
|
+
|
|
551
|
+
If you translate stitch's framework errors into your own wire codes in an
|
|
552
|
+
`onError` hook, you choose how the set's growth reaches you. Keying the map by
|
|
553
|
+
`StitchErrorCode` makes it exhaustive, so a code stitch adds or renames becomes
|
|
554
|
+
a compile error rather than an unfamiliar code on your wire — worth it when the
|
|
555
|
+
envelope is a published contract, at the cost of an edit on those releases:
|
|
556
|
+
|
|
557
|
+
```ts
|
|
558
|
+
// Exhaustive on purpose: the annotation is what turns a new stitch code into a
|
|
559
|
+
// compile error here. Drop it (or use `satisfies` on a partial map) to let an
|
|
560
|
+
// unmapped code travel as itself instead.
|
|
561
|
+
// `Partial`, not an exhaustive `Record`: the set grows in ordinary releases, and
|
|
562
|
+
// a map written exhaustively stops compiling on every addition. Codes you leave
|
|
563
|
+
// out fall through to `unmappedCode`.
|
|
564
|
+
const STITCH_TO_APP: Partial<Record<StitchErrorCode, AppCode>> = {
|
|
565
|
+
NOT_FOUND: 'NOT_FOUND', METHOD_NOT_ALLOWED: 'METHOD_NOT_ALLOWED',
|
|
566
|
+
BAD_REQUEST: 'VALIDATION_ERROR', VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
567
|
+
UNAUTHORIZED: 'UNAUTHORIZED', FORBIDDEN: 'FORBIDDEN', CONFLICT: 'CONFLICT',
|
|
568
|
+
RATE_LIMITED: 'RATE_LIMITED', INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',
|
|
569
|
+
REALTIME_CONTRACT_VIOLATION: 'INTERNAL_SERVER_ERROR',
|
|
570
|
+
FILE_INVALID_PATH: 'VALIDATION_ERROR', FILE_OUTSIDE_ROOT: 'VALIDATION_ERROR',
|
|
571
|
+
FILE_NOT_FOUND: 'NOT_FOUND', FILE_NOT_REGULAR: 'VALIDATION_ERROR',
|
|
572
|
+
FILE_INSPECTION_REJECTED: 'VALIDATION_ERROR', FILE_TOO_LARGE: 'VALIDATION_ERROR',
|
|
573
|
+
FILE_EXISTS: 'CONFLICT',
|
|
574
|
+
}
|
|
575
|
+
onError: (ctx, err) => {
|
|
576
|
+
if (AppError.is(err) && isStitchErrorCode(err.code)) {
|
|
577
|
+
return jsonError(STITCH_TO_APP[err.code], err.status) // keep stitch's status
|
|
578
|
+
}
|
|
579
|
+
// … your own AppError / normalizeError path
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
## One application vocabulary and one wire map
|
|
584
|
+
|
|
585
|
+
`defineErrors` can also resolve Stitchkit's framework codes into the same
|
|
586
|
+
application vocabulary. A status fallback is explicit because several
|
|
587
|
+
application codes may legally share one HTTP status:
|
|
588
|
+
|
|
589
|
+
```ts
|
|
590
|
+
const vocabulary = defineErrors(
|
|
591
|
+
{
|
|
592
|
+
VALIDATION_ERROR: { status: 400, message: 'Invalid request' },
|
|
593
|
+
INTERNAL_ERROR: { status: 500, message: 'Internal error' },
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
fallback: { 400: 'VALIDATION_ERROR', 500: 'INTERNAL_ERROR' },
|
|
597
|
+
map: { FILE_TOO_LARGE: 'VALIDATION_ERROR' },
|
|
598
|
+
},
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
const onError = createErrorHook({ vocabulary })
|
|
602
|
+
// `vocabulary` *is* the wire map: `codeMap` and `unmappedCode` cannot sit
|
|
603
|
+
// beside it — the type forbids the combination and the runtime refuses it.
|
|
604
|
+
// A `map` target must be declared under the framework code's own status
|
|
605
|
+
// (`NOT_FOUND` → a 404 code, never a 410 one): the wire keeps the framework
|
|
606
|
+
// status and carries your code, so `defineErrors` refuses the mismatch where
|
|
607
|
+
// it already refuses a `fallback` under the wrong status.
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
An explicit per-code `map` wins over a status fallback. With
|
|
611
|
+
`exhaustive: true`, `map` must be a complete `Record<StitchErrorCode, AppCode>`
|
|
612
|
+
at compile time. Transport boundaries identify errors with `AppError.is`, not
|
|
613
|
+
`instanceof`, so two bundled copies still agree.
|
|
614
|
+
|
|
615
|
+
## Domain errors — `defineErrors`
|
|
616
|
+
|
|
617
|
+
Declare each domain code, HTTP status, default message and optional
|
|
618
|
+
structured-details schema in one immutable registry. The generated functions
|
|
619
|
+
construct typed branded `AppError` instances; ordinary `throw` remains explicit
|
|
620
|
+
at the call site:
|
|
621
|
+
|
|
622
|
+
```ts
|
|
623
|
+
import { z } from 'zod'
|
|
624
|
+
|
|
625
|
+
export const { errors, codes, definitions, isCode } = defineErrors({
|
|
626
|
+
SESSION_NOT_FOUND: { status: 404, message: 'No such session' },
|
|
627
|
+
QUOTA_EXCEEDED: {
|
|
628
|
+
status: 429,
|
|
629
|
+
message: 'Monthly quota exhausted',
|
|
630
|
+
details: z.object({ retryAfterSeconds: z.number().int().positive() }),
|
|
631
|
+
},
|
|
632
|
+
})
|
|
633
|
+
|
|
634
|
+
throw errors.SESSION_NOT_FOUND() // uses the declared message
|
|
635
|
+
throw errors.QUOTA_EXCEEDED({
|
|
636
|
+
message: 'Try later', // overrides it here only
|
|
637
|
+
details: { retryAfterSeconds: 30 },
|
|
638
|
+
hint: 'Wait for the current window to expire',
|
|
639
|
+
})
|
|
640
|
+
|
|
641
|
+
// Construction without throwing is useful for composition or inspection.
|
|
642
|
+
const error = errors.QUOTA_EXCEEDED({ details: { retryAfterSeconds: 30 } })
|
|
643
|
+
definitions.QUOTA_EXCEEDED.status // 429 — same source, no copied status map
|
|
644
|
+
definitions[code].message // the declared text, by a `code` variable
|
|
645
|
+
|
|
646
|
+
// client — match the code, never a magic string
|
|
647
|
+
if (err instanceof ApiError && err.code === codes.SESSION_NOT_FOUND) { … }
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
`message` is optional: declare it once instead of repeating the sentence at every
|
|
651
|
+
`throw`, and a per-call `message` still wins. A code without one keeps the
|
|
652
|
+
existing fallback — `AppError.message` is the code itself. An empty declared
|
|
653
|
+
message is rejected when the registry is declared, not when the error is thrown.
|
|
654
|
+
|
|
655
|
+
**The tool envelope has no `message` field**, and what the model sees depends on
|
|
656
|
+
whether the code declares `details`:
|
|
657
|
+
|
|
658
|
+
| | HTTP / typed client | MCP / agent / CLI |
|
|
659
|
+
|---|---|---|
|
|
660
|
+
| code **with** a `details` schema | the declared message | no text at all — only `details` and `hint` |
|
|
661
|
+
| code **without** one | the declared message | the same text, delivered as `details.message` |
|
|
662
|
+
|
|
663
|
+
The model-facing envelope is `{ error, retryable, details?, _hint? }`; for a code with no
|
|
664
|
+
details schema the framework fills `details` with `{ message }`, so declaring a
|
|
665
|
+
message changes what the model reads there — it used to be the code itself. Put
|
|
666
|
+
anything the model must reliably read in `details` or `hint`, not in `message`.
|
|
667
|
+
|
|
668
|
+
With no `details` schema, the options object forbids `details`. A required
|
|
669
|
+
`z.object` makes `details` required; `z.object(...).optional()` makes it
|
|
670
|
+
optional. Supplied details are parsed when the error is constructed, before any
|
|
671
|
+
transport sees them. `code` remains literal and the parsed details type is
|
|
672
|
+
retained on the returned `AppError`.
|
|
673
|
+
|
|
674
|
+
HTTP renders the complete code/status/message/details/hint. Tool transports keep
|
|
675
|
+
their established model-facing projection (code/details/hint, without HTTP
|
|
676
|
+
status), while `invokeOrThrow` recovers the exact normalized `AppError`. The
|
|
677
|
+
codes and schemas remain application-owned; Stitchkit stays domain-free.
|
|
678
|
+
|
|
679
|
+
## `createErrorHook`
|
|
680
|
+
|
|
681
|
+
`createErrorHook` is the code-map above, packaged — you supply a `codeMap` and
|
|
682
|
+
the envelope shape, it does the normalisation (including the
|
|
683
|
+
never-leak-an-internal-message rule for a raw throw):
|
|
684
|
+
|
|
685
|
+
```ts
|
|
686
|
+
const onError = createErrorHook({
|
|
687
|
+
// Map the codes you have an opinion about.
|
|
688
|
+
codeMap: {
|
|
689
|
+
BAD_REQUEST: 'bad_request', VALIDATION_ERROR: 'bad_request',
|
|
690
|
+
UNAUTHORIZED: 'unauthenticated', FORBIDDEN: 'forbidden',
|
|
691
|
+
NOT_FOUND: 'not_found', METHOD_NOT_ALLOWED: 'not_found',
|
|
692
|
+
CONFLICT: 'conflict', RATE_LIMITED: 'rate_limited',
|
|
693
|
+
INTERNAL_SERVER_ERROR: 'internal',
|
|
694
|
+
},
|
|
695
|
+
// Optional: one public vocabulary entry for every other stitchkit code.
|
|
696
|
+
// A resolver `(code) => ...` is also accepted for grouping code families.
|
|
697
|
+
unmappedCode: 'framework_error',
|
|
698
|
+
// `ctx` is the request's RuntimeContext — read `ctx.traceId` for a
|
|
699
|
+
// correlation id in the envelope. Declaring it is optional.
|
|
700
|
+
render: (info, ctx) => ({
|
|
701
|
+
ok: false,
|
|
702
|
+
error: { code: info.code, message: info.message },
|
|
703
|
+
traceId: ctx.traceId,
|
|
704
|
+
}),
|
|
705
|
+
})
|
|
706
|
+
|
|
707
|
+
createServer({ services, hooks: { onError } })
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
`codeMap` is partial: map the codes you have an opinion about. By default a
|
|
711
|
+
stitchkit code you did not list travels as itself. Set `unmappedCode` to one
|
|
712
|
+
wire-code when your public vocabulary has a catch-all, or to a function such as
|
|
713
|
+
`(code) => code.startsWith('FILE_') ? 'storage_error' : 'framework_error'` when
|
|
714
|
+
framework code families need different buckets. An explicit `codeMap` entry
|
|
715
|
+
always wins. Codes your project throws itself do not belong to Stitchkit's
|
|
716
|
+
vocabulary, so they never pass through this fallback and remain unchanged.
|
|
717
|
+
|
|
718
|
+
One `satisfies` is the **opt-in** to the stricter deal:
|
|
719
|
+
|
|
720
|
+
```ts
|
|
721
|
+
codeMap: { /* … every code … */ } satisfies Record<StitchErrorCode, string>,
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
That makes the map exhaustive on your side, so a release that adds a code stops
|
|
725
|
+
your build until you decide what the new code is called on your wire. Take it
|
|
726
|
+
when your envelope is a published contract and a code surfacing in stitchkit's
|
|
727
|
+
spelling would violate it; leave it off when passing one through is fine.
|
|
728
|
+
Neither choice is silent — the changelog names every added code.
|
|
729
|
+
|
|
730
|
+
Both `onError` and `render` may be asynchronous and receive the matched endpoint
|
|
731
|
+
as their final argument. The observer is awaited before rendering, so it can
|
|
732
|
+
resolve identity or enrich the request context even for failures raised before
|
|
733
|
+
`beforeHandle`:
|
|
734
|
+
|
|
735
|
+
```ts
|
|
736
|
+
const onError = createErrorHook({
|
|
737
|
+
onError: async (_error, _info, ctx, endpoint) => {
|
|
738
|
+
await attributeFailedRequest(ctx, endpoint)
|
|
739
|
+
},
|
|
740
|
+
render: (info, ctx) => ({
|
|
741
|
+
error: { code: info.code },
|
|
742
|
+
actorId: ctx.actorId,
|
|
743
|
+
}),
|
|
744
|
+
})
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
`endpoint` is `undefined` when the failure happened before route resolution.
|
|
748
|
+
Synchronous callbacks and renderers that declare fewer parameters continue to
|
|
749
|
+
work normally.
|
|
750
|
+
|
|
751
|
+
Invalid input (a `ZodError`) is classified as `VALIDATION_ERROR` 400 before it
|
|
752
|
+
reaches `render` — a client fault is an honest 400, not a 500 — and the
|
|
753
|
+
offending fields arrive as structured `info.details.issues`, so your `render`
|
|
754
|
+
can surface them to a machine client without parsing the message.
|
|
755
|
+
|
|
756
|
+
If you write a **bespoke** `onError` instead of using `createErrorHook`, run the
|
|
757
|
+
thrown value through the exported `normalizeError` to get the same classification
|
|
758
|
+
(a raw `ZodError` reaches your hook untouched, so the framework can inspect it —
|
|
759
|
+
call `zodIssues(err)` yourself if you want the structured fields):
|
|
760
|
+
|
|
761
|
+
```ts
|
|
762
|
+
import { normalizeError } from 'stitchkit/server'
|
|
763
|
+
|
|
764
|
+
onError: (ctx, err) => {
|
|
765
|
+
const e = normalizeError(err) // ZodError → VALIDATION_ERROR 400, else generic 500
|
|
766
|
+
return jsonError(e.code, e.status, e.message)
|
|
767
|
+
}
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
==============================================================================
|
|
771
|
+
# Guide: Multi-tenant (docs/guide/multi-tenant.md)
|
|
772
|
+
==============================================================================
|
|
773
|
+
|
|
774
|
+
# Multi-tenant / resource-scoped paths
|
|
775
|
+
|
|
776
|
+
A walkthrough of one mainstream scenario end-to-end: a SaaS API scoped by a path
|
|
777
|
+
segment — `/tenants/:tenantId/widgets/...` — where the same `tenantId` gates
|
|
778
|
+
access in auth and is injected into tool calls (one API key → many tenants).
|
|
779
|
+
|
|
780
|
+
Every piece below already exists; this recipe wires them into one flow. Each step
|
|
781
|
+
links to its reference section.
|
|
782
|
+
|
|
783
|
+
## 1. The contract — tenant-agnostic
|
|
784
|
+
|
|
785
|
+
Endpoints know nothing about the tenant; the path segment lives on the group, not
|
|
786
|
+
the endpoint:
|
|
787
|
+
|
|
788
|
+
```ts
|
|
789
|
+
export const widgets = defineContract(
|
|
790
|
+
{ prefix: 'widgets', scope: 'tenant' },
|
|
791
|
+
{
|
|
792
|
+
list: { method: 'GET', path: '/', desc: 'List widgets', output: WidgetList },
|
|
793
|
+
create: { method: 'POST', path: '/', desc: 'Create a widget', input: NewWidget, output: Widget },
|
|
794
|
+
},
|
|
795
|
+
)
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
## 2. The server — a param prefix
|
|
799
|
+
|
|
800
|
+
Mount the service under a group whose `pathPrefix` carries `:tenantId`. The
|
|
801
|
+
matched value is on the context root as `ctx.tenantId`
|
|
802
|
+
([details](./server.md#param-prefixes-resource-scoped-paths)):
|
|
803
|
+
|
|
804
|
+
```ts
|
|
805
|
+
createServer({
|
|
806
|
+
groups: [
|
|
807
|
+
{ pathPrefix: '/tenants/:tenantId', services: [widgetsService], hooks: { authorize: authHook } },
|
|
808
|
+
],
|
|
809
|
+
})
|
|
810
|
+
// → /tenants/:tenantId/widgets
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
With more than one scope, let **`scopePrefixes`** map `scope → prefix` and mount
|
|
814
|
+
the flat `services` list — no hand-partitioning, the mapping lives in one place
|
|
815
|
+
([details](./server.md#scope-driven-mounting-scopeprefixes), → ADR 0024):
|
|
816
|
+
|
|
817
|
+
```ts
|
|
818
|
+
createServer({
|
|
819
|
+
services, // mixed scopes, listed once
|
|
820
|
+
scopePrefixes: { tenant: 'tenants/:tenantId', project: 'projects/:projectId' },
|
|
821
|
+
hooks: { authorize: authHook },
|
|
822
|
+
})
|
|
823
|
+
// `tenant`-scoped → /tenants/:tenantId/..., `project` → /projects/:projectId/..., the rest flat
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
Handlers read `ctx.tenantId` (a raw `string` — narrow it). To get it typed inside
|
|
827
|
+
`ctx.params`, add `tenantId` to the endpoint's `params` schema (a `z.strictObject`
|
|
828
|
+
that omits it will reject the request). When each scope guarantees different
|
|
829
|
+
injected fields, declare the scope map once with
|
|
830
|
+
[`createScopedImplement`](./server.md#per-scope-handler-context--createscopedimplement):
|
|
831
|
+
|
|
832
|
+
```ts
|
|
833
|
+
export const implementFor = createScopedImplement<{
|
|
834
|
+
public: object
|
|
835
|
+
tenant: { tenantId: string; userId: string }
|
|
836
|
+
project: { projectId: string; userId: string }
|
|
837
|
+
}>()
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
Each handler is then typed by its endpoint's effective scope — no superset
|
|
841
|
+
context that promises a `tenantId` a `public` handler never receives. A contract
|
|
842
|
+
that mixes scopes across its endpoints needs no splitting.
|
|
843
|
+
|
|
844
|
+
## 3. Auth — gate the tenant in the path
|
|
845
|
+
|
|
846
|
+
The `tenant` scope rule reads the prefix param and checks access; `inject` puts
|
|
847
|
+
the identity and derived facts on `ctx`
|
|
848
|
+
([details](./auth-and-errors.md#resource-scoped-rule--reading-a-pathprefix-param)):
|
|
849
|
+
|
|
850
|
+
```ts
|
|
851
|
+
const authHook = createAuthHook<User>({
|
|
852
|
+
resolve: sessionResolver,
|
|
853
|
+
rules: {
|
|
854
|
+
public: 'public',
|
|
855
|
+
tenant: (user, ctx) => userCanAccessTenant(user.id, String(ctx.tenantId)),
|
|
856
|
+
} satisfies Record<Scope, AuthRule<User>>,
|
|
857
|
+
inject: (ctx, user) => { ctx.user = user },
|
|
858
|
+
})
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
## 4. The client — a per-tenant `pathPrefix`
|
|
862
|
+
|
|
863
|
+
`createClient`'s third argument prepends the tenant segment; `stripPrefixKeys`
|
|
864
|
+
keeps `tenantId` out of the body/query
|
|
865
|
+
([details](./client.md#contractclientconfig--per-tenant--resource-scoped-clients)):
|
|
866
|
+
|
|
867
|
+
```ts
|
|
868
|
+
const widgetsApi = createClient(widgets, http, {
|
|
869
|
+
pathPrefix: ({ tenantId }) => `tenants/${tenantId}/`,
|
|
870
|
+
stripPrefixKeys: ['tenantId'],
|
|
871
|
+
})
|
|
872
|
+
|
|
873
|
+
widgetsApi.list({ tenantId: 't_123' }) // GET /tenants/t_123/widgets
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
`stripPrefixKeys` (a `const` tuple) also makes the consumed keys **typed,
|
|
877
|
+
required args** on every method — `tenantId` above is type-checked, not a runtime
|
|
878
|
+
surprise — so no hand-written scoped-client wrapper is needed (→ ADR 0025).
|
|
879
|
+
|
|
880
|
+
## 5. The AI surface — `extend` injects the tenant
|
|
881
|
+
|
|
882
|
+
One API key serves every tenant: the model passes `tenantId` per call, `resolve`
|
|
883
|
+
validates it and puts it on `ctx` — so the *same* handler that reads `ctx.tenantId`
|
|
884
|
+
over HTTP serves the tool call
|
|
885
|
+
([details](./mcp-and-agents.md#adding-tool-only-args--extend)):
|
|
886
|
+
|
|
887
|
+
```ts
|
|
888
|
+
createMcpHandler({
|
|
889
|
+
serverInfo, auth,
|
|
890
|
+
services: [widgetsService],
|
|
891
|
+
lifecycle: { beforeHandle: authHook },
|
|
892
|
+
extend: {
|
|
893
|
+
schema: { tenantId: z.string().describe('Tenant to act on') },
|
|
894
|
+
resolve: async ({ tenantId }) => ({ tenantId: String(tenantId) }),
|
|
895
|
+
filter: (_s, m) => m.scope === 'tenant',
|
|
896
|
+
},
|
|
897
|
+
})
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
## The through-line
|
|
901
|
+
|
|
902
|
+
`ctx.tenantId` is the single join point: the **prefix param** puts it there on
|
|
903
|
+
HTTP, `extend`'s **resolve** puts it there on a tool call. Handlers and the auth
|
|
904
|
+
rule read it the same way on both surfaces — one contract, every surface, no
|
|
905
|
+
per-transport tenant plumbing.
|