@try-works/dsh-tool-mode 0.0.0-stage → 0.5.44
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/README.md +299 -2
- package/bin/dsh-tool-mode-credentials.mjs +20 -0
- package/bin/dsh-tool-mode-mcp-stdio.mjs +80 -0
- package/bin/dsh-tool-mode.mjs +211 -0
- package/builtins.lock.json +26 -0
- package/catalog/desert-ant-models.json +693 -0
- package/catalog/playbooks.json +531 -0
- package/client/client.model-tools.js +1910 -0
- package/client/index.js +4039 -0
- package/cordis.patch.yml +39 -0
- package/lib/adapters/index.d.ts +61 -0
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +82 -0
- package/lib/adapters/types.d.ts +106 -0
- package/lib/adapters/types.d.ts.map +1 -0
- package/lib/adapters/types.js +85 -0
- package/lib/approval.d.ts +189 -0
- package/lib/approval.d.ts.map +1 -0
- package/lib/approval.js +510 -0
- package/lib/asset-acquisition.d.ts +149 -0
- package/lib/asset-acquisition.d.ts.map +1 -0
- package/lib/asset-acquisition.js +175 -0
- package/lib/authority.d.ts +185 -0
- package/lib/authority.d.ts.map +1 -0
- package/lib/authority.js +223 -0
- package/lib/bindings.d.ts +144 -0
- package/lib/bindings.d.ts.map +1 -0
- package/lib/bindings.js +314 -0
- package/lib/builtins.d.ts +27 -0
- package/lib/builtins.d.ts.map +1 -0
- package/lib/builtins.js +37 -0
- package/lib/capability.d.ts +58 -0
- package/lib/capability.d.ts.map +1 -0
- package/lib/capability.js +192 -0
- package/lib/capture-path.d.ts +97 -0
- package/lib/capture-path.d.ts.map +1 -0
- package/lib/capture-path.js +152 -0
- package/lib/catalog.d.ts +37 -0
- package/lib/catalog.d.ts.map +1 -0
- package/lib/catalog.js +274 -0
- package/lib/contract-payload.d.ts +39 -0
- package/lib/contract-payload.d.ts.map +1 -0
- package/lib/contract-payload.js +56 -0
- package/lib/custom-tools/compile.d.ts +25 -0
- package/lib/custom-tools/compile.d.ts.map +1 -0
- package/lib/custom-tools/compile.js +61 -0
- package/lib/custom-tools/composite-executor.d.ts +42 -0
- package/lib/custom-tools/composite-executor.d.ts.map +1 -0
- package/lib/custom-tools/composite-executor.js +113 -0
- package/lib/custom-tools/dispatch.d.ts +28 -0
- package/lib/custom-tools/dispatch.d.ts.map +1 -0
- package/lib/custom-tools/dispatch.js +34 -0
- package/lib/custom-tools/http-executor.d.ts +48 -0
- package/lib/custom-tools/http-executor.d.ts.map +1 -0
- package/lib/custom-tools/http-executor.js +241 -0
- package/lib/custom-tools/index.d.ts +12 -0
- package/lib/custom-tools/index.d.ts.map +1 -0
- package/lib/custom-tools/index.js +12 -0
- package/lib/custom-tools/mcp-surface.d.ts +14 -0
- package/lib/custom-tools/mcp-surface.d.ts.map +1 -0
- package/lib/custom-tools/mcp-surface.js +41 -0
- package/lib/custom-tools/prompt-executor.d.ts +39 -0
- package/lib/custom-tools/prompt-executor.d.ts.map +1 -0
- package/lib/custom-tools/prompt-executor.js +59 -0
- package/lib/custom-tools/registry.d.ts +69 -0
- package/lib/custom-tools/registry.d.ts.map +1 -0
- package/lib/custom-tools/registry.js +130 -0
- package/lib/custom-tools/schema.d.ts +26 -0
- package/lib/custom-tools/schema.d.ts.map +1 -0
- package/lib/custom-tools/schema.js +375 -0
- package/lib/custom-tools/service.d.ts +90 -0
- package/lib/custom-tools/service.d.ts.map +1 -0
- package/lib/custom-tools/service.js +203 -0
- package/lib/custom-tools/store.d.ts +61 -0
- package/lib/custom-tools/store.d.ts.map +1 -0
- package/lib/custom-tools/store.js +240 -0
- package/lib/custom-tools/types.d.ts +131 -0
- package/lib/custom-tools/types.d.ts.map +1 -0
- package/lib/custom-tools/types.js +11 -0
- package/lib/decision-combine.d.ts +113 -0
- package/lib/decision-combine.d.ts.map +1 -0
- package/lib/decision-combine.js +156 -0
- package/lib/decision-evaluate.d.ts +185 -0
- package/lib/decision-evaluate.d.ts.map +1 -0
- package/lib/decision-evaluate.js +227 -0
- package/lib/deployment-coordinator.d.ts +213 -0
- package/lib/deployment-coordinator.d.ts.map +1 -0
- package/lib/deployment-coordinator.js +274 -0
- package/lib/diagnostics.d.ts +169 -0
- package/lib/diagnostics.d.ts.map +1 -0
- package/lib/diagnostics.js +136 -0
- package/lib/discovery-contracts.d.ts +14 -0
- package/lib/discovery-contracts.d.ts.map +1 -0
- package/lib/discovery-contracts.js +90 -0
- package/lib/discovery-describe.d.ts +35 -0
- package/lib/discovery-describe.d.ts.map +1 -0
- package/lib/discovery-describe.js +99 -0
- package/lib/embedding-index.d.ts +55 -0
- package/lib/embedding-index.d.ts.map +1 -0
- package/lib/embedding-index.js +126 -0
- package/lib/extension-dependencies.d.ts +355 -0
- package/lib/extension-dependencies.d.ts.map +1 -0
- package/lib/extension-dependencies.js +987 -0
- package/lib/extension-dispatch.d.ts +150 -0
- package/lib/extension-dispatch.d.ts.map +1 -0
- package/lib/extension-dispatch.js +178 -0
- package/lib/extension-page-state.d.ts +69 -0
- package/lib/extension-page-state.d.ts.map +1 -0
- package/lib/extension-page-state.js +82 -0
- package/lib/extension-registrar.d.ts +116 -0
- package/lib/extension-registrar.d.ts.map +1 -0
- package/lib/extension-registrar.js +144 -0
- package/lib/extensions-api.d.ts +346 -0
- package/lib/extensions-api.d.ts.map +1 -0
- package/lib/extensions-api.js +17 -0
- package/lib/extensions-remote.d.ts +57 -0
- package/lib/extensions-remote.d.ts.map +1 -0
- package/lib/extensions-remote.js +69 -0
- package/lib/extensions-service.d.ts +568 -0
- package/lib/extensions-service.d.ts.map +1 -0
- package/lib/extensions-service.js +2507 -0
- package/lib/harness-budgets.d.ts +158 -0
- package/lib/harness-budgets.d.ts.map +1 -0
- package/lib/harness-budgets.js +152 -0
- package/lib/harness-llm.d.ts +138 -0
- package/lib/harness-llm.d.ts.map +1 -0
- package/lib/harness-llm.js +218 -0
- package/lib/harness-serving.d.ts +115 -0
- package/lib/harness-serving.d.ts.map +1 -0
- package/lib/harness-serving.js +176 -0
- package/lib/headless.d.ts +97 -0
- package/lib/headless.d.ts.map +1 -0
- package/lib/headless.js +407 -0
- package/lib/http-acquisition.d.ts +27 -0
- package/lib/http-acquisition.d.ts.map +1 -0
- package/lib/http-acquisition.js +140 -0
- package/lib/index.d.ts +546 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +5197 -0
- package/lib/invocation-accounting.d.ts +169 -0
- package/lib/invocation-accounting.d.ts.map +1 -0
- package/lib/invocation-accounting.js +148 -0
- package/lib/jev.d.ts +218 -0
- package/lib/jev.d.ts.map +1 -0
- package/lib/jev.js +366 -0
- package/lib/legacy-migration.d.ts +95 -0
- package/lib/legacy-migration.d.ts.map +1 -0
- package/lib/legacy-migration.js +429 -0
- package/lib/license-basis.d.ts +29 -0
- package/lib/license-basis.d.ts.map +1 -0
- package/lib/license-basis.js +58 -0
- package/lib/managed-workers.d.ts +158 -0
- package/lib/managed-workers.d.ts.map +1 -0
- package/lib/managed-workers.js +269 -0
- package/lib/mcp/auth-selection.d.ts +35 -0
- package/lib/mcp/auth-selection.d.ts.map +1 -0
- package/lib/mcp/auth-selection.js +64 -0
- package/lib/mcp/client-grant.d.ts +89 -0
- package/lib/mcp/client-grant.d.ts.map +1 -0
- package/lib/mcp/client-grant.js +63 -0
- package/lib/mcp/credential-cli.d.ts +38 -0
- package/lib/mcp/credential-cli.d.ts.map +1 -0
- package/lib/mcp/credential-cli.js +148 -0
- package/lib/mcp/credential-store.d.ts +143 -0
- package/lib/mcp/credential-store.d.ts.map +1 -0
- package/lib/mcp/credential-store.js +461 -0
- package/lib/mcp/export-policy.d.ts +25 -0
- package/lib/mcp/export-policy.d.ts.map +1 -0
- package/lib/mcp/export-policy.js +31 -0
- package/lib/mcp/host-binding.d.ts +144 -0
- package/lib/mcp/host-binding.d.ts.map +1 -0
- package/lib/mcp/host-binding.js +280 -0
- package/lib/mcp/http.d.ts +180 -0
- package/lib/mcp/http.d.ts.map +1 -0
- package/lib/mcp/http.js +602 -0
- package/lib/mcp/oauth.d.ts +149 -0
- package/lib/mcp/oauth.d.ts.map +1 -0
- package/lib/mcp/oauth.js +396 -0
- package/lib/mcp/protocol.d.ts +329 -0
- package/lib/mcp/protocol.d.ts.map +1 -0
- package/lib/mcp/protocol.js +459 -0
- package/lib/mcp/rate-limit.d.ts +68 -0
- package/lib/mcp/rate-limit.d.ts.map +1 -0
- package/lib/mcp/rate-limit.js +114 -0
- package/lib/mcp/sdk-v2.d.ts +17 -0
- package/lib/mcp/sdk-v2.d.ts.map +1 -0
- package/lib/mcp/sdk-v2.js +204 -0
- package/lib/mcp/server.d.ts +149 -0
- package/lib/mcp/server.d.ts.map +1 -0
- package/lib/mcp/server.js +302 -0
- package/lib/mcp/stdio.d.ts +80 -0
- package/lib/mcp/stdio.d.ts.map +1 -0
- package/lib/mcp/stdio.js +184 -0
- package/lib/mcp/subscriptions.d.ts +177 -0
- package/lib/mcp/subscriptions.d.ts.map +1 -0
- package/lib/mcp/subscriptions.js +288 -0
- package/lib/mcp-status.d.ts +96 -0
- package/lib/mcp-status.d.ts.map +1 -0
- package/lib/mcp-status.js +70 -0
- package/lib/mcp-usage.d.ts +110 -0
- package/lib/mcp-usage.d.ts.map +1 -0
- package/lib/mcp-usage.js +189 -0
- package/lib/model-qualification.d.ts +192 -0
- package/lib/model-qualification.d.ts.map +1 -0
- package/lib/model-qualification.js +178 -0
- package/lib/planning.d.ts +256 -0
- package/lib/planning.d.ts.map +1 -0
- package/lib/planning.js +471 -0
- package/lib/playbook.d.ts +42 -0
- package/lib/playbook.d.ts.map +1 -0
- package/lib/playbook.js +65 -0
- package/lib/prepared-assets.d.ts +269 -0
- package/lib/prepared-assets.d.ts.map +1 -0
- package/lib/prepared-assets.js +471 -0
- package/lib/provider-bridge.d.ts +107 -0
- package/lib/provider-bridge.d.ts.map +1 -0
- package/lib/provider-bridge.js +423 -0
- package/lib/ptc-authority.d.ts +154 -0
- package/lib/ptc-authority.d.ts.map +1 -0
- package/lib/ptc-authority.js +242 -0
- package/lib/ptc-confinement.d.ts +60 -0
- package/lib/ptc-confinement.d.ts.map +1 -0
- package/lib/ptc-confinement.js +212 -0
- package/lib/ptc-runtime.d.ts +166 -0
- package/lib/ptc-runtime.d.ts.map +1 -0
- package/lib/ptc-runtime.js +231 -0
- package/lib/publication.d.ts +161 -0
- package/lib/publication.d.ts.map +1 -0
- package/lib/publication.js +181 -0
- package/lib/receipt-store.d.ts +57 -0
- package/lib/receipt-store.d.ts.map +1 -0
- package/lib/receipt-store.js +143 -0
- package/lib/receipt.d.ts +231 -0
- package/lib/receipt.d.ts.map +1 -0
- package/lib/receipt.js +165 -0
- package/lib/registrar.d.ts +75 -0
- package/lib/registrar.d.ts.map +1 -0
- package/lib/registrar.js +152 -0
- package/lib/resource-governance.d.ts +204 -0
- package/lib/resource-governance.d.ts.map +1 -0
- package/lib/resource-governance.js +213 -0
- package/lib/server-lifecycle.d.ts +175 -0
- package/lib/server-lifecycle.d.ts.map +1 -0
- package/lib/server-lifecycle.js +269 -0
- package/lib/skills.d.ts +31 -0
- package/lib/skills.d.ts.map +1 -0
- package/lib/skills.js +170 -0
- package/lib/speech-bridge.d.ts +74 -0
- package/lib/speech-bridge.d.ts.map +1 -0
- package/lib/speech-bridge.js +115 -0
- package/lib/state.d.ts +100 -0
- package/lib/state.d.ts.map +1 -0
- package/lib/state.js +160 -0
- package/lib/title-proposal.d.ts +194 -0
- package/lib/title-proposal.d.ts.map +1 -0
- package/lib/title-proposal.js +244 -0
- package/lib/tool-inventory.d.ts +90 -0
- package/lib/tool-inventory.d.ts.map +1 -0
- package/lib/tool-inventory.js +102 -0
- package/lib/tool-mode-run.d.ts +310 -0
- package/lib/tool-mode-run.d.ts.map +1 -0
- package/lib/tool-mode-run.js +411 -0
- package/lib/tool-sources.d.ts +80 -0
- package/lib/tool-sources.d.ts.map +1 -0
- package/lib/tool-sources.js +123 -0
- package/lib/tool-usage-projection.d.ts +390 -0
- package/lib/tool-usage-projection.d.ts.map +1 -0
- package/lib/tool-usage-projection.js +1038 -0
- package/lib/tool-usage-report.d.ts +153 -0
- package/lib/tool-usage-report.d.ts.map +1 -0
- package/lib/tool-usage-report.js +274 -0
- package/lib/transport.d.ts +158 -0
- package/lib/transport.d.ts.map +1 -0
- package/lib/transport.js +332 -0
- package/lib/types.d.ts +134 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +8 -0
- package/lib/update-surface.d.ts +79 -0
- package/lib/update-surface.d.ts.map +1 -0
- package/lib/update-surface.js +224 -0
- package/lib/version.d.ts +3 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +27 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.d.ts +13 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contract-metadata.js +85 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts +16 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.js +87 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts +38 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.js +445 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts +20 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.js +112 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts +14 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.js +63 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts +14 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.js +76 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts +82 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +274 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +26 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/index.js +53 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts +133 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/meta.js +64 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +121 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +246 -0
- package/node_modules/@try-works/tool-mode-contracts/package.json +35 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/bin/dsh-tool-mode.mjs +20 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts +80 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.js +533 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts +86 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.js +145 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts +70 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.js +201 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts +57 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.js +83 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts +33 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.js +33 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts +86 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.js +191 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts +137 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.js +349 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts +274 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.js +932 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts +210 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.js +368 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts +63 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.js +149 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts +35 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.js +179 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts +179 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.js +299 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +395 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +839 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts +44 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.js +255 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts +185 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.d.ts +221 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/licensing.js +188 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +128 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.d.ts +41 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/test-host.js +52 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +157 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +688 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/package.json +54 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
- package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +460 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +647 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +61 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +1106 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +205 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +119 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/images.js +201 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +345 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1465 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +231 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +435 -0
- package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
- package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
- package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
- package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
- package/package.json +127 -4
- package/remote/spec.mjs +993 -0
- package/remote/typert.host.mjs +14 -0
- package/remote/typert.remote-client.mjs +16 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The embedded LOCAL OAuth 2.1 authorization server + resource-server verifier
|
|
3
|
+
* (P26-15).
|
|
4
|
+
*
|
|
5
|
+
* P26-15 permits exactly two implementations: a tested authorization-server
|
|
6
|
+
* integration, or a properly implemented embedded/local server — and forbids
|
|
7
|
+
* inventing token cryptography. This module is the second: the signing and
|
|
8
|
+
* verification primitives are Node's OWN WebCrypto (`crypto.subtle` HMAC-SHA256),
|
|
9
|
+
* and only the JWT envelope around them is assembled here. No cipher, mode or
|
|
10
|
+
* hash is hand-rolled.
|
|
11
|
+
*
|
|
12
|
+
* The shape follows the parts of RFC 6749/6750/8414/9728 a resource server and a
|
|
13
|
+
* local issuer need:
|
|
14
|
+
*
|
|
15
|
+
* - HS256-signed JWTs with `iss`, `sub` (client id), `aud`, `scope`, `iat`, `exp`
|
|
16
|
+
* and a unique `jti`;
|
|
17
|
+
* - RFC 6750 challenges: `WWW-Authenticate: Bearer error="invalid_token"|...`
|
|
18
|
+
* with `scope="..."` on insufficient_scope;
|
|
19
|
+
* - per-client credentials with INDEPENDENT revocation (a revoked client's tokens
|
|
20
|
+
* fail while every other client keeps working);
|
|
21
|
+
* - RFC 8414 authorization-server metadata and RFC 9728 protected-resource
|
|
22
|
+
* metadata, so a client can discover issuer/audience/token endpoint.
|
|
23
|
+
*
|
|
24
|
+
* The static-token mode remains available as CUSTOM authentication and still
|
|
25
|
+
* claims nothing; this module is what a deployment turns on when it wants the
|
|
26
|
+
* OAuth profile, and `authProfile()` reports which mode is live.
|
|
27
|
+
*
|
|
28
|
+
* @module @try-works/dsh-tool-mode/mcp/oauth
|
|
29
|
+
*/
|
|
30
|
+
import type { ClientCredentialStore } from './credential-store.ts';
|
|
31
|
+
/** One registered client of the local authorization server. */
|
|
32
|
+
export interface OAuthClient {
|
|
33
|
+
/** The client's identity, recorded in the token's `sub` and in receipts. */
|
|
34
|
+
readonly clientId: string;
|
|
35
|
+
/** The client's secret, the shared symmetric key for HS256. */
|
|
36
|
+
readonly secret: string;
|
|
37
|
+
/** The scope this client may be granted. */
|
|
38
|
+
readonly scope: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
/** Configuration for the embedded authorization server. */
|
|
41
|
+
export interface LocalOAuthServerConfig {
|
|
42
|
+
/** The issuer URI, stamped into every token's `iss`. */
|
|
43
|
+
readonly issuer: string;
|
|
44
|
+
/** The resource the tokens target, stamped into `aud`. */
|
|
45
|
+
readonly audience: string;
|
|
46
|
+
/** Token lifetime in seconds. */
|
|
47
|
+
readonly tokenLifetimeSeconds?: number;
|
|
48
|
+
/** Clock skew tolerated on verification, in seconds. */
|
|
49
|
+
readonly leewaySeconds?: number;
|
|
50
|
+
/**
|
|
51
|
+
* The durable credential store (SEC-01).
|
|
52
|
+
*
|
|
53
|
+
* When present, generated and operator-provisioned clients are PERSISTED
|
|
54
|
+
* owner-only, revocation survives restarts, and the server hydrates its
|
|
55
|
+
* registry from the store at construction. A generation that cannot be
|
|
56
|
+
* persisted registers nothing (fail-closed). Absent keeps the earlier
|
|
57
|
+
* in-memory behavior.
|
|
58
|
+
*/
|
|
59
|
+
readonly store?: ClientCredentialStore;
|
|
60
|
+
}
|
|
61
|
+
/** A generated credential, with the secret returned exactly once. */
|
|
62
|
+
export interface GeneratedClientCredential {
|
|
63
|
+
readonly clientId: string;
|
|
64
|
+
/** Crypto-random, shown once here and never re-echoed (SEC-01). */
|
|
65
|
+
readonly secret: string;
|
|
66
|
+
}
|
|
67
|
+
/** Why verification failed, in RFC 6750 error-code vocabulary. */
|
|
68
|
+
export type OAuthTokenError = {
|
|
69
|
+
readonly code: 'invalid_request';
|
|
70
|
+
readonly description: string;
|
|
71
|
+
} | {
|
|
72
|
+
readonly code: 'invalid_token';
|
|
73
|
+
readonly description: string;
|
|
74
|
+
} | {
|
|
75
|
+
readonly code: 'insufficient_scope';
|
|
76
|
+
readonly description: string;
|
|
77
|
+
readonly scope: string;
|
|
78
|
+
};
|
|
79
|
+
/** A verified token's claims. */
|
|
80
|
+
export interface VerifiedToken {
|
|
81
|
+
readonly clientId: string;
|
|
82
|
+
readonly scope: readonly string[];
|
|
83
|
+
readonly audience: string;
|
|
84
|
+
readonly jti: string;
|
|
85
|
+
}
|
|
86
|
+
/** The embedded local authorization server. */
|
|
87
|
+
export interface LocalOAuthServer {
|
|
88
|
+
/** Register or replace a client credential. */
|
|
89
|
+
upsertClient(client: OAuthClient): void;
|
|
90
|
+
/**
|
|
91
|
+
* GENERATE a fresh client credential with a crypto-random secret (SEC-01).
|
|
92
|
+
*
|
|
93
|
+
* The secret is returned EXACTLY ONCE, in the returned object; every later surface
|
|
94
|
+
* names only the clientId. The generation is fail-closed: when the durable store is
|
|
95
|
+
* present and the credential cannot be persisted, nothing is registered and the
|
|
96
|
+
* call throws — a credential that a restart would forget must never appear usable.
|
|
97
|
+
*/
|
|
98
|
+
generateClient(options: {
|
|
99
|
+
readonly clientId: string;
|
|
100
|
+
readonly scope?: readonly string[];
|
|
101
|
+
}): GeneratedClientCredential;
|
|
102
|
+
/** Revoke ONE client; its tokens fail, every other client is untouched. */
|
|
103
|
+
revokeClient(clientId: string): void;
|
|
104
|
+
/** Issue an access token for a client, or undefined for an unknown/revoked client. */
|
|
105
|
+
issueAccessToken(clientId: string, scope?: readonly string[]): Promise<string>;
|
|
106
|
+
/**
|
|
107
|
+
* Verify a presented bearer token: signature, issuer, audience, expiry and
|
|
108
|
+
* scope, against the live client registry and revocation set.
|
|
109
|
+
*/
|
|
110
|
+
verify(token: string, requiredScope?: readonly string[]): Promise<{
|
|
111
|
+
readonly ok: true;
|
|
112
|
+
readonly token: VerifiedToken;
|
|
113
|
+
} | {
|
|
114
|
+
readonly ok: false;
|
|
115
|
+
readonly error: OAuthTokenError;
|
|
116
|
+
}>;
|
|
117
|
+
/** RFC 8414 authorization-server metadata. */
|
|
118
|
+
authorizationServerMetadata(): Record<string, unknown>;
|
|
119
|
+
/** RFC 9728 protected-resource metadata. */
|
|
120
|
+
protectedResourceMetadata(): Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create the embedded local authorization server.
|
|
124
|
+
*
|
|
125
|
+
* The signing key is DERIVED per client from its secret (SHA-256), so each
|
|
126
|
+
* client's tokens are signed with a key only that client's secret can produce —
|
|
127
|
+
* and revoking a client is removing its secret from the registry, which is the
|
|
128
|
+
* one-sided operation a resource server can perform without consulting the
|
|
129
|
+
* authorization server.
|
|
130
|
+
* @param config - issuer, audience and lifetimes.
|
|
131
|
+
* @returns the server.
|
|
132
|
+
*/
|
|
133
|
+
export declare function createLocalOAuthServer(config: LocalOAuthServerConfig): LocalOAuthServer;
|
|
134
|
+
/** Build the RFC 6750 challenge header for a verification failure. */
|
|
135
|
+
export declare function oauthChallenge(error: OAuthTokenError, realm?: string): string;
|
|
136
|
+
/**
|
|
137
|
+
* The HTTP status RFC 6750 §3.1 assigns to each token error.
|
|
138
|
+
*
|
|
139
|
+
* All three are 401-shaped failures, but the RFC distinguishes them so a client
|
|
140
|
+
* can tell "malformed request, fix it" (400) from "credential bad, re-auth"
|
|
141
|
+
* (401) from "credential fine, grant too small" (403). Flattening every
|
|
142
|
+
* challenge to 401 was the F4 gap: a client receiving 400 for a revoked token
|
|
143
|
+
* would re-send the same request, and one receiving 401 for insufficient scope
|
|
144
|
+
* would re-authenticate pointlessly instead of asking for the scope.
|
|
145
|
+
*/
|
|
146
|
+
export declare function oauthErrorStatus(error: OAuthTokenError): 400 | 401 | 403;
|
|
147
|
+
/** Extract the error code from a challenge, for tests and diagnostics. */
|
|
148
|
+
export declare function challengeErrorCode(challenge: string): string | undefined;
|
|
149
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/mcp/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAElE,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC;AAED,2DAA2D;AAC3D,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,iCAAiC;IACjC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IACtC,wDAAwD;IACxD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,qBAAqB,CAAA;CACvC;AAED,qEAAqE;AACrE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,kEAAkE;AAClE,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjG,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACvC;;;;;;;OAOG;IACH,cAAc,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,yBAAyB,CAAA;IACrH,2EAA2E;IAC3E,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,sFAAsF;IACtF,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9E;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAC7D;QAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;KAAE,GACpD;QAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;KAAE,CAC1D,CAAA;IACD,8CAA8C;IAC9C,2BAA2B,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtD,4CAA4C;IAC5C,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrD;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,CA8TvF;AAED,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,SAAc,GAAG,MAAM,CAQlF;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAMxE;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE"}
|
package/lib/mcp/oauth.js
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The embedded LOCAL OAuth 2.1 authorization server + resource-server verifier
|
|
3
|
+
* (P26-15).
|
|
4
|
+
*
|
|
5
|
+
* P26-15 permits exactly two implementations: a tested authorization-server
|
|
6
|
+
* integration, or a properly implemented embedded/local server — and forbids
|
|
7
|
+
* inventing token cryptography. This module is the second: the signing and
|
|
8
|
+
* verification primitives are Node's OWN WebCrypto (`crypto.subtle` HMAC-SHA256),
|
|
9
|
+
* and only the JWT envelope around them is assembled here. No cipher, mode or
|
|
10
|
+
* hash is hand-rolled.
|
|
11
|
+
*
|
|
12
|
+
* The shape follows the parts of RFC 6749/6750/8414/9728 a resource server and a
|
|
13
|
+
* local issuer need:
|
|
14
|
+
*
|
|
15
|
+
* - HS256-signed JWTs with `iss`, `sub` (client id), `aud`, `scope`, `iat`, `exp`
|
|
16
|
+
* and a unique `jti`;
|
|
17
|
+
* - RFC 6750 challenges: `WWW-Authenticate: Bearer error="invalid_token"|...`
|
|
18
|
+
* with `scope="..."` on insufficient_scope;
|
|
19
|
+
* - per-client credentials with INDEPENDENT revocation (a revoked client's tokens
|
|
20
|
+
* fail while every other client keeps working);
|
|
21
|
+
* - RFC 8414 authorization-server metadata and RFC 9728 protected-resource
|
|
22
|
+
* metadata, so a client can discover issuer/audience/token endpoint.
|
|
23
|
+
*
|
|
24
|
+
* The static-token mode remains available as CUSTOM authentication and still
|
|
25
|
+
* claims nothing; this module is what a deployment turns on when it wants the
|
|
26
|
+
* OAuth profile, and `authProfile()` reports which mode is live.
|
|
27
|
+
*
|
|
28
|
+
* @module @try-works/dsh-tool-mode/mcp/oauth
|
|
29
|
+
*/
|
|
30
|
+
import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
31
|
+
const ENCODER = new TextEncoder();
|
|
32
|
+
/** Base64url without padding, the JWT alphabet. */
|
|
33
|
+
function b64url(bytes) {
|
|
34
|
+
return Buffer.from(bytes).toString('base64url');
|
|
35
|
+
}
|
|
36
|
+
/** Decode one base64url JWT part to its JSON value. */
|
|
37
|
+
function decodePart(part) {
|
|
38
|
+
if (part === undefined || part.length === 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(Buffer.from(part, 'base64url').toString('utf8'));
|
|
42
|
+
return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)
|
|
43
|
+
? parsed
|
|
44
|
+
: undefined;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create the embedded local authorization server.
|
|
52
|
+
*
|
|
53
|
+
* The signing key is DERIVED per client from its secret (SHA-256), so each
|
|
54
|
+
* client's tokens are signed with a key only that client's secret can produce —
|
|
55
|
+
* and revoking a client is removing its secret from the registry, which is the
|
|
56
|
+
* one-sided operation a resource server can perform without consulting the
|
|
57
|
+
* authorization server.
|
|
58
|
+
* @param config - issuer, audience and lifetimes.
|
|
59
|
+
* @returns the server.
|
|
60
|
+
*/
|
|
61
|
+
export function createLocalOAuthServer(config) {
|
|
62
|
+
const lifetime = config.tokenLifetimeSeconds ?? 900;
|
|
63
|
+
const leeway = config.leewaySeconds ?? 30;
|
|
64
|
+
const clients = new Map();
|
|
65
|
+
const revoked = new Map(); // clientId -> secret hash, so a re-registration restores access
|
|
66
|
+
// SEC-01: hydrate the registry from the durable store, so generated credentials
|
|
67
|
+
// survive a restart. Revoked clients are ABSENT from the store (revocation deletes),
|
|
68
|
+
// so everything listed is live.
|
|
69
|
+
for (const stored of config.store?.list() ?? []) {
|
|
70
|
+
if (stored.scheme !== 'oauth-resource-server')
|
|
71
|
+
continue;
|
|
72
|
+
clients.set(stored.clientId, { clientId: stored.clientId, secret: stored.secret, scope: stored.scope });
|
|
73
|
+
}
|
|
74
|
+
// The key type is inferred: naming `CryptoKey` here collides with the DOM value
|
|
75
|
+
// of the same name in the Node type surface.
|
|
76
|
+
const keyFor = (secret) => {
|
|
77
|
+
const digest = createHash('sha256').update(secret).digest();
|
|
78
|
+
return crypto.subtle.importKey('raw', digest, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign', 'verify']);
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* The LIVE registry entry for one client id.
|
|
82
|
+
*
|
|
83
|
+
* When the durable store exists it is the SOLE authority: the store row is
|
|
84
|
+
* read fresh on every issue and verify, and there is NO fallback to the
|
|
85
|
+
* construction-time hydration —
|
|
86
|
+
*
|
|
87
|
+
* - a row ABSENT from the store is an unknown/revoked client, even if this
|
|
88
|
+
* process hydrated the id earlier (delete-then-recreate invalidates old
|
|
89
|
+
* tokens; deletion through any surface takes effect on the next call);
|
|
90
|
+
* - a row with the WRONG SCHEME (static-token where an OAuth row was
|
|
91
|
+
* hydrated) is REJECTED as an OAuth client — scheme confusion must not
|
|
92
|
+
* resurrect a hydrated entry;
|
|
93
|
+
* - a credential generated after this server was constructed ISSUES
|
|
94
|
+
* immediately (the earlier design answered "unknown client" until
|
|
95
|
+
* restart).
|
|
96
|
+
*
|
|
97
|
+
* The in-memory map serves ONLY the store-less mode.
|
|
98
|
+
*/
|
|
99
|
+
const liveClient = (clientId) => {
|
|
100
|
+
if (config.store !== undefined) {
|
|
101
|
+
const stored = config.store.get(clientId);
|
|
102
|
+
if (stored === undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
if (stored.scheme !== 'oauth-resource-server')
|
|
105
|
+
return undefined;
|
|
106
|
+
return { clientId: stored.clientId, secret: stored.secret, scope: stored.scope };
|
|
107
|
+
}
|
|
108
|
+
return clients.get(clientId);
|
|
109
|
+
};
|
|
110
|
+
/** Validate scope names once, so a bad name is refused at registration. */
|
|
111
|
+
const assertScopeNames = (scope) => {
|
|
112
|
+
// Scope names are RFC 6749 scope-tokens: no whitespace. A name containing a
|
|
113
|
+
// space can never be satisfied (issue joins with ' ', verify splits), so
|
|
114
|
+
// registering one is a configuration error and is refused here rather than
|
|
115
|
+
// silently issuing credentials that can never authorize (review F-g).
|
|
116
|
+
for (const name of scope) {
|
|
117
|
+
if (!/^[A-Za-z0-9._:\/-]+$/.test(name)) {
|
|
118
|
+
throw new Error(`scope name ${JSON.stringify(name)} is not an RFC 6749 scope-token`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const register = (client) => {
|
|
123
|
+
assertScopeNames(client.scope);
|
|
124
|
+
// SEC-01 FAIL-CLOSED: persist FIRST, register only when the credential is durable —
|
|
125
|
+
// a generation that a restart would forget must never appear usable.
|
|
126
|
+
if (config.store !== undefined) {
|
|
127
|
+
config.store.upsert({
|
|
128
|
+
clientId: client.clientId,
|
|
129
|
+
secret: client.secret,
|
|
130
|
+
scheme: 'oauth-resource-server',
|
|
131
|
+
scope: client.scope,
|
|
132
|
+
createdAt: new Date().toISOString(),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
clients.set(client.clientId, client);
|
|
136
|
+
revoked.delete(client.clientId);
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
upsertClient(client) {
|
|
140
|
+
register(client);
|
|
141
|
+
},
|
|
142
|
+
generateClient(options) {
|
|
143
|
+
if (typeof options.clientId !== 'string' || options.clientId.length === 0 || options.clientId.length > 64) {
|
|
144
|
+
throw new Error('clientId must be a non-empty string of at most 64 characters');
|
|
145
|
+
}
|
|
146
|
+
if (clients.has(options.clientId) || config.store?.get(options.clientId) !== undefined) {
|
|
147
|
+
throw new Error(`a credential for ${JSON.stringify(options.clientId)} already exists; revoke it first`);
|
|
148
|
+
}
|
|
149
|
+
// SEC-01: high entropy — 32 crypto-random bytes, base64url-encoded. The secret
|
|
150
|
+
// is generated SERVER-SIDE and returned exactly once from this function.
|
|
151
|
+
const secret = randomBytes(32).toString('base64url');
|
|
152
|
+
register({ clientId: options.clientId, secret, scope: options.scope ?? ['mcp:call'] });
|
|
153
|
+
return { clientId: options.clientId, secret };
|
|
154
|
+
},
|
|
155
|
+
revokeClient(clientId) {
|
|
156
|
+
/**
|
|
157
|
+
* Revocation is decided by the LIVE authority, never by the hydrated map:
|
|
158
|
+
* a client generated AFTER this server was constructed (a "late client")
|
|
159
|
+
* exists only in the durable store, and revoking it must delete the
|
|
160
|
+
* durable record just like any other. The revocation FINGERPRINT is the
|
|
161
|
+
* hash of the client's own SECRET — scoped to the credential, not the id —
|
|
162
|
+
* so a legitimate re-generation of the same id with a fresh secret is
|
|
163
|
+
* never blocked by an old revocation.
|
|
164
|
+
*/
|
|
165
|
+
const client = liveClient(clientId);
|
|
166
|
+
if (client !== undefined) {
|
|
167
|
+
revoked.set(clientId, createHash('sha256').update(client.secret).digest('hex'));
|
|
168
|
+
// Durable revocation: the store entry is DELETED, so the credential does not
|
|
169
|
+
// resurrect on the next boot. A persistence failure surfaces to the caller;
|
|
170
|
+
// the in-memory revocation still stands for this process.
|
|
171
|
+
config.store?.delete(clientId);
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
async issueAccessToken(clientId, scope) {
|
|
175
|
+
const client = liveClient(clientId);
|
|
176
|
+
if (client === undefined)
|
|
177
|
+
return undefined;
|
|
178
|
+
// SECRET-SCOPED revocation: the fingerprint is the hash of the revoked
|
|
179
|
+
// secret itself, so re-generating the same id with a FRESH secret issues
|
|
180
|
+
// again, while a revoked secret never does.
|
|
181
|
+
const revokedHash = revoked.get(clientId);
|
|
182
|
+
if (revokedHash !== undefined && revokedHash === createHash('sha256').update(client.secret).digest('hex')) {
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
const grantedScope = scope === undefined || scope.length === 0
|
|
186
|
+
? [...client.scope]
|
|
187
|
+
: [...new Set(scope.filter(name => client.scope.includes(name)))];
|
|
188
|
+
const now = Math.floor(Date.now() / 1000);
|
|
189
|
+
const header = b64url(ENCODER.encode(JSON.stringify({ alg: 'HS256', typ: 'JWT' })));
|
|
190
|
+
const payload = b64url(ENCODER.encode(JSON.stringify({
|
|
191
|
+
iss: config.issuer,
|
|
192
|
+
sub: client.clientId,
|
|
193
|
+
aud: config.audience,
|
|
194
|
+
scope: grantedScope.join(' '),
|
|
195
|
+
iat: now,
|
|
196
|
+
exp: now + lifetime,
|
|
197
|
+
jti: `jti_${now.toString(36)}_${Math.random().toString(36).slice(2, 10)}`,
|
|
198
|
+
})));
|
|
199
|
+
const signingInput = `${header}.${payload}`;
|
|
200
|
+
const signature = await crypto.subtle.sign('HMAC', await keyFor(client.secret), ENCODER.encode(signingInput));
|
|
201
|
+
return `${signingInput}.${b64url(new Uint8Array(signature))}`;
|
|
202
|
+
},
|
|
203
|
+
async verify(token, requiredScope) {
|
|
204
|
+
const parts = token.split('.');
|
|
205
|
+
if (parts.length !== 3) {
|
|
206
|
+
return {
|
|
207
|
+
ok: false,
|
|
208
|
+
error: { code: 'invalid_request', description: 'the credential is not a JWT with three parts' },
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const header = decodePart(parts[0]);
|
|
212
|
+
const payload = decodePart(parts[1]);
|
|
213
|
+
if (header?.alg !== 'HS256' || payload === undefined) {
|
|
214
|
+
return {
|
|
215
|
+
ok: false,
|
|
216
|
+
error: { code: 'invalid_request', description: 'the credential is not an HS256 JWT with a JSON payload' },
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const clientId = payload.sub;
|
|
220
|
+
if (typeof clientId !== 'string') {
|
|
221
|
+
return {
|
|
222
|
+
ok: false,
|
|
223
|
+
error: { code: 'invalid_request', description: 'the credential carries no subject' },
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
// The LIVE registry entry: the durable store first, so a rotated or
|
|
227
|
+
// deleted credential is judged by the CURRENT secret and scope, never by
|
|
228
|
+
// the construction-time snapshot.
|
|
229
|
+
const client = liveClient(clientId);
|
|
230
|
+
if (client === undefined) {
|
|
231
|
+
return {
|
|
232
|
+
ok: false,
|
|
233
|
+
error: { code: 'invalid_token', description: 'the credential is from an unknown client' },
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
// SIGNATURE FIRST: only a credential signed with the client's own key may
|
|
237
|
+
// present claims about that client, so nothing below reads an unsigned claim
|
|
238
|
+
// — including the revocation state, which a forged credential must not be
|
|
239
|
+
// able to probe (F2: the revoked check sat here before and answered an
|
|
240
|
+
// unsigned token claiming sub=X, revealing whether X is revoked).
|
|
241
|
+
const signingInput = `${parts[0]}.${parts[1]}`;
|
|
242
|
+
const signaturePart = parts[2];
|
|
243
|
+
const presented = Buffer.from(signaturePart, 'base64url');
|
|
244
|
+
const expected = new Uint8Array(await crypto.subtle.sign('HMAC', await keyFor(client.secret), ENCODER.encode(signingInput)));
|
|
245
|
+
const matches = presented.length === expected.length && timingSafeEqual(presented, expected);
|
|
246
|
+
if (!matches) {
|
|
247
|
+
return {
|
|
248
|
+
ok: false,
|
|
249
|
+
error: { code: 'invalid_token', description: 'the credential signature does not verify' },
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const revokedHash = revoked.get(clientId);
|
|
253
|
+
if (revokedHash !== undefined && revokedHash === createHash('sha256').update(client.secret).digest('hex')) {
|
|
254
|
+
return {
|
|
255
|
+
ok: false,
|
|
256
|
+
error: { code: 'invalid_token', description: 'the credential is revoked' },
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
// SEC-01: a client deleted from the durable store by ANY surface — the local
|
|
260
|
+
// revokeClient, the host's management action, or another process — is revoked
|
|
261
|
+
// for this process too, on the very next verification. The live lookup above
|
|
262
|
+
// consults the store; this is the in-memory fallback check.
|
|
263
|
+
if (config.store !== undefined && config.store.get(clientId) === undefined) {
|
|
264
|
+
return {
|
|
265
|
+
ok: false,
|
|
266
|
+
error: { code: 'invalid_token', description: 'the credential is revoked' },
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
// Issuer and audience are validated AFTER the signature: only then are they
|
|
270
|
+
// facts the issuer asserted rather than text an attacker wrote.
|
|
271
|
+
if (payload.iss !== config.issuer) {
|
|
272
|
+
return {
|
|
273
|
+
ok: false,
|
|
274
|
+
error: { code: 'invalid_token', description: 'the credential was issued by a different authorization server' },
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
const audience = payload.aud;
|
|
278
|
+
const audiences = Array.isArray(audience) ? audience : [audience];
|
|
279
|
+
if (!audiences.includes(config.audience)) {
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
error: { code: 'invalid_token', description: `the credential audience does not include ${config.audience}` },
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const exp = payload.exp;
|
|
286
|
+
const now = Math.floor(Date.now() / 1000);
|
|
287
|
+
if (typeof exp !== 'number' || now > exp + leeway) {
|
|
288
|
+
return {
|
|
289
|
+
ok: false,
|
|
290
|
+
error: { code: 'invalid_token', description: 'the credential has expired' },
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
const iat = payload.iat;
|
|
294
|
+
if (typeof iat === 'number' && iat > now + leeway) {
|
|
295
|
+
return {
|
|
296
|
+
ok: false,
|
|
297
|
+
error: { code: 'invalid_token', description: 'the credential is not yet valid' },
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
const scope = typeof payload.scope === 'string'
|
|
301
|
+
? payload.scope.split(' ').filter(Boolean)
|
|
302
|
+
: [];
|
|
303
|
+
/**
|
|
304
|
+
* F1 FIX (review): the presented scope is CAPPED at the client's registered
|
|
305
|
+
* grant. Issuance already caps it, but with symmetric keys a client can
|
|
306
|
+
* self-mint a token claiming ANY scope — verification is therefore the only
|
|
307
|
+
* place the per-client grant can be enforced, and it was not. A claim the
|
|
308
|
+
* registry does not admit is refused here, never trusted.
|
|
309
|
+
*/
|
|
310
|
+
const overGrant = scope.filter(name => !client.scope.includes(name));
|
|
311
|
+
if (overGrant.length > 0) {
|
|
312
|
+
return {
|
|
313
|
+
ok: false,
|
|
314
|
+
error: {
|
|
315
|
+
code: 'invalid_token',
|
|
316
|
+
description: `the credential claims scope beyond this client's grant: ${overGrant.join(', ')}`,
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
const required = requiredScope ?? [];
|
|
321
|
+
const missing = required.filter(name => !scope.includes(name));
|
|
322
|
+
if (missing.length > 0) {
|
|
323
|
+
return {
|
|
324
|
+
ok: false,
|
|
325
|
+
error: {
|
|
326
|
+
code: 'insufficient_scope',
|
|
327
|
+
description: `the credential lacks required scope: ${missing.join(', ')}`,
|
|
328
|
+
scope: required.join(' '),
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
ok: true,
|
|
334
|
+
token: {
|
|
335
|
+
clientId,
|
|
336
|
+
scope,
|
|
337
|
+
audience: config.audience,
|
|
338
|
+
jti: typeof payload.jti === 'string' ? payload.jti : '',
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
},
|
|
342
|
+
authorizationServerMetadata() {
|
|
343
|
+
return {
|
|
344
|
+
issuer: config.issuer,
|
|
345
|
+
// NO token_endpoint (F3, review): issuance is programmatic-only here, so
|
|
346
|
+
// advertising an endpoint the transport never serves would be an RFC 8414
|
|
347
|
+
// lie. A client that finds this issuer knows credentials come from the
|
|
348
|
+
// operator's configuration, not from a token request.
|
|
349
|
+
response_types_supported: ['token'],
|
|
350
|
+
token_endpoint_auth_methods_supported: ['client_secret_post'],
|
|
351
|
+
grant_types_supported: ['client_credentials'],
|
|
352
|
+
};
|
|
353
|
+
},
|
|
354
|
+
protectedResourceMetadata() {
|
|
355
|
+
return {
|
|
356
|
+
resource: config.audience,
|
|
357
|
+
authorization_servers: [config.issuer],
|
|
358
|
+
bearer_methods_supported: ['header'],
|
|
359
|
+
scopes_supported: [...new Set([...clients.values()].flatMap(client => client.scope))],
|
|
360
|
+
};
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
/** Build the RFC 6750 challenge header for a verification failure. */
|
|
365
|
+
export function oauthChallenge(error, realm = 'tool-mode') {
|
|
366
|
+
const params = [
|
|
367
|
+
`realm="${realm}"`,
|
|
368
|
+
`error="${error.code}"`,
|
|
369
|
+
`error_description="${error.description.replaceAll('"', "'")}"`,
|
|
370
|
+
];
|
|
371
|
+
if (error.code === 'insufficient_scope')
|
|
372
|
+
params.push(`scope="${error.scope}"`);
|
|
373
|
+
return `Bearer ${params.join(', ')}`;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* The HTTP status RFC 6750 §3.1 assigns to each token error.
|
|
377
|
+
*
|
|
378
|
+
* All three are 401-shaped failures, but the RFC distinguishes them so a client
|
|
379
|
+
* can tell "malformed request, fix it" (400) from "credential bad, re-auth"
|
|
380
|
+
* (401) from "credential fine, grant too small" (403). Flattening every
|
|
381
|
+
* challenge to 401 was the F4 gap: a client receiving 400 for a revoked token
|
|
382
|
+
* would re-send the same request, and one receiving 401 for insufficient scope
|
|
383
|
+
* would re-authenticate pointlessly instead of asking for the scope.
|
|
384
|
+
*/
|
|
385
|
+
export function oauthErrorStatus(error) {
|
|
386
|
+
switch (error.code) {
|
|
387
|
+
case 'invalid_request': return 400;
|
|
388
|
+
case 'insufficient_scope': return 403;
|
|
389
|
+
case 'invalid_token': return 401;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/** Extract the error code from a challenge, for tests and diagnostics. */
|
|
393
|
+
export function challengeErrorCode(challenge) {
|
|
394
|
+
return /error="([^"]+)"/.exec(challenge)?.[1];
|
|
395
|
+
}
|
|
396
|
+
//# sourceMappingURL=oauth.js.map
|