@wardby/cli 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +5 -5
- package/README.md +6 -1
- package/deploy/local/docker-compose.quickstart-coding.yml +19 -0
- package/dist/claude-coding-worker/driver.d.ts +33 -3
- package/dist/claude-coding-worker/driver.js +151 -21
- package/dist/claude-coding-worker/main.js +38 -6
- package/dist/claude-coding-worker/sdk.js +29 -2
- package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
- package/dist/claude-coding-worker/tool-socket.js +111 -0
- package/dist/claude-coding-worker/transcript.d.ts +18 -0
- package/dist/claude-coding-worker/transcript.js +77 -0
- package/dist/claude-plugin/command.d.ts +61 -0
- package/dist/claude-plugin/command.js +376 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +3 -1
- package/dist/cli.js +71 -13
- package/dist/coding/code-host.d.ts +16 -0
- package/dist/coding/code-host.js +60 -0
- package/dist/coding/continuation-wording.d.ts +35 -0
- package/dist/coding/continuation-wording.js +73 -0
- package/dist/coding/linked-issue-note.d.ts +23 -0
- package/dist/coding/linked-issue-note.js +47 -0
- package/dist/coding/mcp-token.d.ts +12 -0
- package/dist/coding/mcp-token.js +26 -0
- package/dist/coding/merge-wording.d.ts +28 -0
- package/dist/coding/merge-wording.js +78 -0
- package/dist/coding/pr-description-note.d.ts +9 -0
- package/dist/coding/pr-description-note.js +32 -0
- package/dist/coding/profile.d.ts +46 -126
- package/dist/coding/profile.js +45 -4
- package/dist/coding/protected-path-wording.d.ts +8 -0
- package/dist/coding/protected-path-wording.js +1 -1
- package/dist/coding/protocol.d.ts +264 -346
- package/dist/coding/protocol.js +237 -12
- package/dist/coding/redact.d.ts +3 -0
- package/dist/coding/redact.js +17 -0
- package/dist/coding/registry/allowlist.d.ts +12 -0
- package/dist/coding/registry/allowlist.js +14 -1
- package/dist/coding/registry/audit-mode.d.ts +153 -0
- package/dist/coding/registry/audit-mode.js +304 -0
- package/dist/coding/registry/lockfile-shared.d.ts +36 -0
- package/dist/coding/registry/lockfile-shared.js +128 -0
- package/dist/coding/registry/lockfiles.js +1 -1
- package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
- package/dist/coding/registry/npm-lockfile-formats.js +41 -0
- package/dist/coding/registry/npm-lockfile.d.ts +8 -4
- package/dist/coding/registry/npm-lockfile.js +4 -6
- package/dist/coding/registry/npm.js +78 -8
- package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
- package/dist/coding/registry/pnpm-lockfile.js +189 -0
- package/dist/coding/registry/pypi-plan.d.ts +50 -0
- package/dist/coding/registry/pypi-plan.js +406 -0
- package/dist/coding/registry/pypi-requirements.d.ts +58 -0
- package/dist/coding/registry/pypi-requirements.js +155 -0
- package/dist/coding/registry/pypi.d.ts +3 -27
- package/dist/coding/registry/pypi.js +40 -154
- package/dist/coding/registry/refusal-hints.d.ts +20 -0
- package/dist/coding/registry/refusal-hints.js +61 -0
- package/dist/coding/registry/refusal-wording.d.ts +11 -0
- package/dist/coding/registry/refusal-wording.js +56 -0
- package/dist/coding/registry/report.d.ts +70 -8
- package/dist/coding/registry/report.js +112 -5
- package/dist/coding/registry/types.d.ts +58 -8
- package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
- package/dist/coding/registry/yarn-lockfile.js +367 -0
- package/dist/coding/services/catalog.d.ts +37 -351
- package/dist/coding/transcript/claude-code.d.ts +13 -0
- package/dist/coding/transcript/claude-code.js +273 -0
- package/dist/coding/transcript/download-protocol.d.ts +30 -0
- package/dist/coding/transcript/download-protocol.js +18 -0
- package/dist/coding/transcript/format.d.ts +20 -0
- package/dist/coding/transcript/format.js +32 -0
- package/dist/coding/transcript/recorder.d.ts +52 -0
- package/dist/coding/transcript/recorder.js +225 -0
- package/dist/coding/transcript/resume/checkout.d.ts +31 -0
- package/dist/coding/transcript/resume/checkout.js +203 -0
- package/dist/coding/transcript/resume/command.d.ts +17 -0
- package/dist/coding/transcript/resume/command.js +176 -0
- package/dist/coding/transcript/resume/download.d.ts +20 -0
- package/dist/coding/transcript/resume/download.js +153 -0
- package/dist/coding/transcript/resume/launch.d.ts +38 -0
- package/dist/coding/transcript/resume/launch.js +128 -0
- package/dist/coding/transcript/resume/session-file.d.ts +13 -0
- package/dist/coding/transcript/resume/session-file.js +79 -0
- package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
- package/dist/coding/transcript/resume/stand-in.js +49 -0
- package/dist/coding-worker/artifact.d.ts +8 -3
- package/dist/coding-worker/artifact.js +3 -1
- package/dist/coding-worker/debug-trace.d.ts +9 -6
- package/dist/coding-worker/debug-trace.js +16 -19
- package/dist/coding-worker/dependency-cache.d.mts +229 -0
- package/dist/coding-worker/dependency-cache.mjs +2123 -0
- package/dist/coding-worker/driver.d.ts +4 -3
- package/dist/coding-worker/driver.js +124 -39
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- package/dist/coding-worker/main.js +5 -1
- package/dist/coding-worker/mcp-config.d.ts +27 -0
- package/dist/coding-worker/mcp-config.js +32 -0
- package/dist/coding-worker/sdk.d.ts +36 -0
- package/dist/coding-worker/sdk.js +28 -1
- package/dist/coding-worker/task-note.d.ts +11 -0
- package/dist/coding-worker/task-note.js +13 -0
- package/dist/coding-worker/types.d.ts +15 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/mcp-call-limit.d.ts +8 -0
- package/dist/config/mcp-call-limit.js +18 -0
- package/dist/config/mcp-servers.d.ts +8 -0
- package/dist/config/mcp-servers.js +12 -0
- package/dist/config/providers.d.ts +12 -3
- package/dist/config/providers.js +55 -5
- package/dist/config/test-simulators.d.ts +92 -0
- package/dist/config/test-simulators.js +333 -0
- package/dist/config/tool-timeout.d.ts +1 -0
- package/dist/config/tool-timeout.js +18 -0
- package/dist/core/async-context.d.ts +2 -0
- package/dist/core/async-context.js +12 -0
- package/dist/core/budget-events.d.ts +108 -0
- package/dist/core/budget-events.js +346 -0
- package/dist/core/budget-groups.d.ts +50 -1
- package/dist/core/budget-groups.js +236 -27
- package/dist/core/budget-stopped-head.d.ts +46 -0
- package/dist/core/budget-stopped-head.js +81 -0
- package/dist/core/budget-topup.d.ts +51 -0
- package/dist/core/budget-topup.js +156 -0
- package/dist/core/budget-wording.d.ts +16 -2
- package/dist/core/budget-wording.js +40 -2
- package/dist/core/coding-mcp.d.ts +36 -0
- package/dist/core/coding-mcp.js +253 -0
- package/dist/core/coding-queue.d.ts +2 -1
- package/dist/core/coding-queue.js +7 -0
- package/dist/core/coding-repository.d.ts +46 -0
- package/dist/core/coding-repository.js +92 -0
- package/dist/core/cron.d.ts +19 -1
- package/dist/core/cron.js +17 -0
- package/dist/core/datastores.js +1 -1
- package/dist/core/deferred-coding.d.ts +14 -0
- package/dist/core/deferred-coding.js +62 -0
- package/dist/core/delegation-child.d.ts +25 -0
- package/dist/core/delegation-child.js +37 -0
- package/dist/core/delegation-slots.d.ts +27 -0
- package/dist/core/delegation-slots.js +44 -0
- package/dist/core/dispatch.d.ts +48 -2
- package/dist/core/dispatch.js +166 -66
- package/dist/core/engine-native.js +1 -1
- package/dist/core/error-code.d.ts +38 -0
- package/dist/core/error-code.js +169 -0
- package/dist/core/grants.d.ts +46 -8
- package/dist/core/grants.js +99 -8
- package/dist/core/host-events.d.ts +18 -2
- package/dist/core/host-events.js +291 -27
- package/dist/core/host-status.d.ts +85 -3
- package/dist/core/host-status.js +300 -22
- package/dist/core/issue-bridge.d.ts +50 -6
- package/dist/core/issue-bridge.js +124 -33
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +4 -10
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +58 -29
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/logger.js +14 -1
- package/dist/core/lost-run-children.d.ts +6 -0
- package/dist/core/lost-run-children.js +32 -0
- package/dist/core/mark-ready.d.ts +34 -0
- package/dist/core/mark-ready.js +152 -0
- package/dist/core/markdown-code.d.ts +8 -0
- package/dist/core/markdown-code.js +107 -0
- package/dist/core/mcp-client/client.d.ts +47 -0
- package/dist/core/mcp-client/client.js +141 -0
- package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
- package/dist/core/mcp-client/jsonrpc.js +54 -0
- package/dist/core/mcp-client/results.d.ts +13 -0
- package/dist/core/mcp-client/results.js +42 -0
- package/dist/core/mcp-servers.d.ts +90 -0
- package/dist/core/mcp-servers.js +230 -0
- package/dist/core/mcp-tools.d.ts +108 -0
- package/dist/core/mcp-tools.js +287 -0
- package/dist/core/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +2 -1
- package/dist/core/merge-order-check.js +44 -18
- package/dist/core/notification-dispatcher.js +2 -1
- package/dist/core/notification-templates.d.ts +1 -7
- package/dist/core/notification-templates.js +36 -2
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +4 -3
- package/dist/core/reconciler.js +8 -1
- package/dist/core/related-pull-requests.d.ts +11 -3
- package/dist/core/related-pull-requests.js +49 -20
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/review-fix.d.ts +1 -1
- package/dist/core/review-fix.js +4 -3
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +3 -0
- package/dist/core/review-host-tools.js +102 -14
- package/dist/core/review-reads.d.ts +55 -0
- package/dist/core/review-reads.js +233 -0
- package/dist/core/run-status.d.ts +12 -0
- package/dist/core/run-status.js +12 -0
- package/dist/core/runner.d.ts +145 -49
- package/dist/core/runner.js +719 -216
- package/dist/core/schedule-start.d.ts +12 -0
- package/dist/core/schedule-start.js +14 -0
- package/dist/core/secret-broker-config.d.ts +12 -74
- package/dist/core/secret-broker-config.js +1 -1
- package/dist/core/secret-guard.d.ts +49 -0
- package/dist/core/secret-guard.js +119 -0
- package/dist/core/secret-guarded-stores.d.ts +12 -0
- package/dist/core/secret-guarded-stores.js +41 -0
- package/dist/core/secret-spans.d.ts +50 -0
- package/dist/core/secret-spans.js +94 -0
- package/dist/core/secrets.d.ts +11 -1
- package/dist/core/secrets.js +27 -1
- package/dist/core/serializable-retry.d.ts +18 -0
- package/dist/core/serializable-retry.js +43 -0
- package/dist/core/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/tool-admin.d.ts +5 -1
- package/dist/core/tool-admin.js +7 -2
- package/dist/core/tool-names.d.ts +13 -0
- package/dist/core/tool-names.js +20 -0
- package/dist/core/webhooks.d.ts +4 -0
- package/dist/core/webhooks.js +68 -49
- package/dist/core/workflow-events.d.ts +14 -2
- package/dist/core/workflow-events.js +4 -0
- package/dist/core/workflow-run-events.d.ts +5 -3
- package/dist/core/workflow-run-events.js +45 -9
- package/dist/core/zod-json-schema.d.ts +4 -0
- package/dist/core/zod-json-schema.js +39 -0
- package/dist/core/zod3-window.d.ts +35 -0
- package/dist/core/zod3-window.js +124 -0
- package/dist/generated/prisma/browser.d.ts +65 -3
- package/dist/generated/prisma/client.d.ts +65 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +266 -106
- package/dist/generated/prisma/enums.d.ts +10 -0
- package/dist/generated/prisma/enums.js +8 -0
- package/dist/generated/prisma/internal/class.d.ts +110 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +957 -9
- package/dist/generated/prisma/internal/prismaNamespace.js +166 -2
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +174 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +166 -2
- package/dist/generated/prisma/models/Agent.d.ts +377 -8
- package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
- package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
- package/dist/generated/prisma/models/AgentRepository.d.ts +81 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +228 -7
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
- package/dist/generated/prisma/models/CodingProxySession.d.ts +232 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1712 -1
- package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
- package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
- package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
- package/dist/generated/prisma/models/HostProvider.js +1 -0
- package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
- package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
- package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
- package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
- package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
- package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
- package/dist/generated/prisma/models/McpServer.js +1 -0
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +77 -1
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
- package/dist/generated/prisma/models/Principal.d.ts +167 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
- package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
- package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
- package/dist/generated/prisma/models/Run.d.ts +738 -2
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +387 -0
- package/dist/generated/prisma/models/Tool.d.ts +223 -1
- package/dist/generated/prisma/models.d.ts +10 -0
- package/dist/help/search.js +12 -3
- package/dist/help-index.json +2033 -110
- package/dist/import/create.js +48 -4
- package/dist/import/neutral-schema.d.ts +51 -281
- package/dist/import/neutral-schema.js +7 -4
- package/dist/knowledge/check.d.ts +1 -1
- package/dist/knowledge/cli.d.ts +11 -1
- package/dist/knowledge/cli.js +37 -4
- package/dist/knowledge/concept.d.ts +3 -19
- package/dist/knowledge/location.d.ts +31 -0
- package/dist/knowledge/location.js +78 -0
- package/dist/mcp/auth/access.d.ts +10 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/grants-cli.d.ts +6 -4
- package/dist/mcp/auth/grants-cli.js +42 -3
- package/dist/mcp/auth/ownership.d.ts +7 -7
- package/dist/mcp/auth/resource-server.d.ts +3 -1
- package/dist/mcp/auth/resource-server.js +17 -2
- package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
- package/dist/mcp/context.d.ts +3 -0
- package/dist/mcp/host-events/github-ingress.d.ts +2 -0
- package/dist/mcp/host-events/github-ingress.js +2 -1
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +69 -10
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +33 -14
- package/dist/mcp/tools/agents.d.ts +4 -0
- package/dist/mcp/tools/agents.js +295 -28
- package/dist/mcp/tools/datastore.js +17 -8
- package/dist/mcp/tools/grants.js +73 -29
- package/dist/mcp/tools/host-providers.d.ts +2 -0
- package/dist/mcp/tools/host-providers.js +215 -0
- package/dist/mcp/tools/mcp-servers.d.ts +26 -0
- package/dist/mcp/tools/mcp-servers.js +481 -0
- package/dist/mcp/tools/memory.js +11 -1
- package/dist/mcp/tools/notification-channels.js +2 -2
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/repositories.js +65 -12
- package/dist/mcp/tools/run-access.d.ts +16 -0
- package/dist/mcp/tools/run-access.js +25 -0
- package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
- package/dist/mcp/tools/run-transcript-download.js +129 -0
- package/dist/mcp/tools/run-transcript.d.ts +19 -0
- package/dist/mcp/tools/run-transcript.js +70 -0
- package/dist/mcp/tools/runs.js +209 -27
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-elicitation-form.js +5 -0
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -61
- package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
- package/dist/mcp/tools/secret-elicitation.js +25 -2
- package/dist/mcp/tools/secrets.js +40 -6
- package/dist/mcp/tools/stop-run.d.ts +2 -0
- package/dist/mcp/tools/stop-run.js +82 -0
- package/dist/mcp/tools/subagents.js +2 -2
- package/dist/mcp/tools/tools.d.ts +7 -5
- package/dist/mcp/tools/tools.js +64 -16
- package/dist/mcp/tools/trigger.js +28 -6
- package/dist/mcp/transport/http-limits.d.ts +2 -0
- package/dist/mcp/transport/http-limits.js +6 -2
- package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
- package/dist/mcp/transport/stdio-link-host.js +67 -0
- package/dist/mcp/transport/streamable-http.d.ts +13 -0
- package/dist/mcp/transport/streamable-http.js +41 -1
- package/dist/mcp/webhooks/ingress.js +10 -0
- package/dist/native-worker/docker-launcher.d.ts +38 -2
- package/dist/native-worker/docker-launcher.js +65 -5
- package/dist/native-worker/gateway-server.d.ts +55 -3
- package/dist/native-worker/gateway-server.js +152 -34
- package/dist/native-worker/gateway.d.ts +29 -1
- package/dist/native-worker/gateway.js +74 -4
- package/dist/native-worker/http-server.d.ts +7 -1
- package/dist/native-worker/http-server.js +62 -7
- package/dist/native-worker/http-transport.js +1 -1
- package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
- package/dist/native-worker/kubernetes-launcher.js +43 -3
- package/dist/native-worker/launch.d.ts +18 -1
- package/dist/native-worker/launch.js +6 -1
- package/dist/native-worker/ledger.d.ts +24 -4
- package/dist/native-worker/ledger.js +62 -8
- package/dist/native-worker/loopback.js +3 -8
- package/dist/native-worker/main.d.ts +2 -1
- package/dist/native-worker/main.js +14 -3
- package/dist/native-worker/protocol.d.ts +130 -577
- package/dist/native-worker/protocol.js +51 -2
- package/dist/native-worker/sandbox-executor.d.ts +17 -2
- package/dist/native-worker/sandbox-executor.js +78 -4
- package/dist/native-worker/stderr-redaction.d.ts +77 -0
- package/dist/native-worker/stderr-redaction.js +237 -0
- package/dist/native-worker/stdio.d.ts +1 -1
- package/dist/native-worker/stdio.js +6 -5
- package/dist/native-worker/warm-pool.d.ts +2 -2
- package/dist/native-worker/warm-pool.js +4 -4
- package/dist/native-worker/worker.js +28 -2
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/self-hosted.d.ts +1 -1
- package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
- package/dist/providers/coding-proxy/capability-hash.js +5 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
- package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
- package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
- package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
- package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
- package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
- package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
- package/dist/providers/coding-proxy/hold.d.ts +32 -0
- package/dist/providers/coding-proxy/hold.js +86 -0
- package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
- package/dist/providers/coding-proxy/interrupted.js +104 -0
- package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
- package/dist/providers/coding-proxy/mcp-route.js +166 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -2
- package/dist/providers/coding-proxy/memory-ledger.js +99 -8
- package/dist/providers/coding-proxy/metering.d.ts +16 -0
- package/dist/providers/coding-proxy/metering.js +27 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +16 -2
- package/dist/providers/coding-proxy/prisma-ledger.js +209 -69
- package/dist/providers/coding-proxy/proxy.d.ts +21 -2
- package/dist/providers/coding-proxy/proxy.js +300 -48
- package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
- package/dist/providers/coding-proxy/registry/audit.js +94 -17
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
- package/dist/providers/coding-proxy/registry/plan.js +201 -48
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
- package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
- package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
- package/dist/providers/coding-proxy/registry/service.js +579 -112
- package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
- package/dist/providers/coding-proxy/registry/store.js +54 -1
- package/dist/providers/coding-proxy/runtime.d.ts +10 -0
- package/dist/providers/coding-proxy/runtime.js +109 -16
- package/dist/providers/coding-proxy/server.d.ts +9 -1
- package/dist/providers/coding-proxy/server.js +55 -1
- package/dist/providers/coding-proxy/types.d.ts +78 -1
- package/dist/providers/datastore/types.d.ts +5 -0
- package/dist/providers/engine/types.d.ts +17 -2
- package/dist/providers/engine/types.js +17 -0
- package/dist/providers/executor/composition.d.ts +10 -3
- package/dist/providers/executor/composition.js +52 -7
- package/dist/providers/executor/container.d.ts +394 -9
- package/dist/providers/executor/container.js +1210 -96
- package/dist/providers/executor/dbos-status.d.ts +31 -0
- package/dist/providers/executor/dbos-status.js +64 -0
- package/dist/providers/executor/dbos.d.ts +50 -1
- package/dist/providers/executor/dbos.js +207 -20
- package/dist/providers/executor/deferred.d.ts +12 -24
- package/dist/providers/executor/deferred.js +10 -29
- package/dist/providers/executor/in-process.d.ts +9 -1
- package/dist/providers/executor/in-process.js +14 -4
- package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
- package/dist/providers/executor/linked-issue-reader.js +30 -0
- package/dist/providers/executor/routing.d.ts +2 -0
- package/dist/providers/executor/routing.js +4 -0
- package/dist/providers/executor/types.d.ts +13 -0
- package/dist/providers/host-tools/invoke.d.ts +37 -0
- package/dist/providers/host-tools/invoke.js +117 -0
- package/dist/providers/host-tools/operations.d.ts +65 -0
- package/dist/providers/host-tools/operations.js +149 -0
- package/dist/providers/host-tools/registry.d.ts +79 -0
- package/dist/providers/host-tools/registry.js +362 -0
- package/dist/providers/host-tools/request-guard.d.ts +17 -0
- package/dist/providers/host-tools/request-guard.js +99 -0
- package/dist/providers/host-tools/self-test.d.ts +64 -0
- package/dist/providers/host-tools/self-test.js +142 -0
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/issue-tracker/types.d.ts +17 -0
- package/dist/providers/issue-tracker/types.js +39 -1
- package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
- package/dist/providers/jobs/claude-tool-setup.js +5 -2
- package/dist/providers/jobs/docker-isolation.d.ts +10 -2
- package/dist/providers/jobs/docker-isolation.js +47 -8
- package/dist/providers/jobs/docker.d.ts +9 -0
- package/dist/providers/jobs/docker.js +60 -11
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
- package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
- package/dist/providers/jobs/kubernetes-api.js +10 -0
- package/dist/providers/jobs/kubernetes-client.js +10 -1
- package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
- package/dist/providers/jobs/kubernetes-isolation.js +32 -3
- package/dist/providers/jobs/kubernetes.d.ts +11 -1
- package/dist/providers/jobs/kubernetes.js +111 -17
- package/dist/providers/jobs/types.d.ts +39 -0
- package/dist/providers/jobs/types.js +13 -1
- package/dist/providers/llm/anthropic.js +5 -1
- package/dist/providers/llm/bedrock.d.ts +0 -12
- package/dist/providers/llm/bedrock.js +4 -0
- package/dist/providers/llm/claude-messages.d.ts +3 -1
- package/dist/providers/llm/claude-messages.js +4 -1
- package/dist/providers/llm/claude-provider.d.ts +2 -2
- package/dist/providers/llm/claude-provider.js +2 -2
- package/dist/providers/llm/openai.d.ts +2 -2
- package/dist/providers/llm/openai.js +6 -2
- package/dist/providers/llm/routing.d.ts +2 -2
- package/dist/providers/llm/routing.js +2 -2
- package/dist/providers/llm/types.d.ts +12 -2
- package/dist/providers/review-host/github-events.d.ts +9 -1
- package/dist/providers/review-host/github-events.js +34 -12
- package/dist/providers/review-host/github.d.ts +29 -2
- package/dist/providers/review-host/github.js +224 -29
- package/dist/providers/review-host/local.d.ts +8 -4
- package/dist/providers/review-host/local.js +49 -31
- package/dist/providers/review-host/patch-pages.d.ts +41 -0
- package/dist/providers/review-host/patch-pages.js +176 -0
- package/dist/providers/review-host/review-format.d.ts +19 -1
- package/dist/providers/review-host/review-format.js +38 -7
- package/dist/providers/review-host/types.d.ts +140 -6
- package/dist/providers/review-host/types.js +9 -1
- package/dist/providers/storage/gcs.d.ts +63 -0
- package/dist/providers/storage/gcs.js +69 -0
- package/dist/providers/storage/index.d.ts +15 -0
- package/dist/providers/storage/index.js +14 -0
- package/dist/providers/storage/local.d.ts +24 -0
- package/dist/providers/storage/local.js +92 -0
- package/dist/providers/storage/meter.d.ts +14 -0
- package/dist/providers/storage/meter.js +34 -0
- package/dist/providers/storage/s3.d.ts +41 -0
- package/dist/providers/storage/s3.js +107 -0
- package/dist/providers/storage/types.d.ts +37 -3
- package/dist/providers/storage/types.js +21 -4
- package/dist/providers/vcs/git.d.ts +39 -4
- package/dist/providers/vcs/git.js +339 -26
- package/dist/providers/vcs/github-remote.d.ts +26 -3
- package/dist/providers/vcs/github-remote.js +124 -14
- package/dist/providers/vcs/github.d.ts +183 -44
- package/dist/providers/vcs/github.js +455 -56
- package/dist/providers/vcs/index.d.ts +1 -1
- package/dist/providers/vcs/index.js +9 -2
- package/dist/providers/vcs/pr-description.d.ts +127 -0
- package/dist/providers/vcs/pr-description.js +270 -0
- package/dist/providers/vcs/remote.d.ts +37 -1
- package/dist/providers/vcs/remote.js +7 -1
- package/dist/providers/vcs/routing.d.ts +16 -8
- package/dist/providers/vcs/routing.js +27 -6
- package/dist/providers/vcs/types.d.ts +150 -5
- package/dist/quickstart/coding-seed.d.ts +14 -3
- package/dist/quickstart/coding-seed.js +213 -4
- package/dist/quickstart/index.d.ts +5 -0
- package/dist/quickstart/index.js +21 -0
- package/dist/quickstart/reviewer-prompt.d.ts +1 -1
- package/dist/quickstart/reviewer-prompt.js +6 -6
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/eval-core.d.ts +12 -2
- package/dist/sandbox/eval-core.js +20 -4
- package/dist/sandbox/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +5 -0
- package/dist/sandbox/host-functions.js +13 -13
- package/dist/sandbox/limits.d.ts +4 -1
- package/dist/sandbox/limits.js +4 -1
- package/dist/sandbox/run-in-sandbox.d.ts +6 -0
- package/dist/sandbox/run-in-sandbox.js +14 -2
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +1 -1
- package/dist/sandbox/secret-broker.d.ts +1 -0
- package/dist/sandbox/secret-broker.js +4 -5
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/tool-timeout.d.ts +32 -0
- package/dist/sandbox/tool-timeout.js +52 -0
- package/dist/sandbox/user-tool.d.ts +8 -1
- package/dist/sandbox/user-tool.js +9 -3
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +8 -1
- package/dist/viewer/api-schema.d.ts +349 -2627
- package/dist/viewer/api-schema.js +7 -0
- package/dist/viewer/build-schemas.js +6 -2
- package/dist/viewer/graph.js +2 -1
- package/dist/viewer/openapi.js +2 -4
- package/dist/wardby-bin.js +15 -0
- package/docs/README.md +11 -1
- package/docs/agent-recipes.md +95 -24
- package/docs/architecture-runtime.md +1 -1
- package/docs/claude-code-plugin.md +164 -0
- package/docs/code-review-agents.md +557 -41
- package/docs/coding-agent-setup.md +566 -8
- package/docs/coding-packages.md +1033 -90
- package/docs/coding-services.md +27 -12
- package/docs/coding-worker-byo-images.md +24 -2
- package/docs/coding-worker-isolation.md +183 -37
- package/docs/debugging-agent-runs.md +242 -0
- package/docs/getting-started-gke.md +129 -141
- package/docs/getting-started-identity-provider.md +53 -38
- package/docs/getting-started.md +17 -0
- package/docs/host-providers.md +294 -0
- package/docs/jira-agents.md +17 -8
- package/docs/knowledge/blob-not-found-semantics.md +41 -0
- package/docs/knowledge/bounded-file-descriptor.md +52 -0
- package/docs/knowledge/delegation-admission-slots.md +52 -0
- package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
- package/docs/knowledge/import-rename-target.md +52 -0
- package/docs/knowledge/index.md +57 -0
- package/docs/knowledge/log.md +9 -0
- package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
- package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
- package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
- package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
- package/docs/knowledge/overview-cli.md +74 -0
- package/docs/knowledge/overview-coding-proxy.md +72 -0
- package/docs/knowledge/overview-coding.md +72 -0
- package/docs/knowledge/overview-config.md +60 -0
- package/docs/knowledge/overview-core.md +72 -0
- package/docs/knowledge/overview-deploy.md +83 -0
- package/docs/knowledge/overview-mcp.md +61 -0
- package/docs/knowledge/overview-prisma.md +72 -0
- package/docs/knowledge/overview-providers.md +89 -0
- package/docs/knowledge/overview-sandbox.md +83 -0
- package/docs/knowledge/overview-surfaces.md +83 -0
- package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
- package/docs/knowledge/proxy-settlement-projections.md +41 -0
- package/docs/knowledge/run-pricing-first-writer.md +43 -0
- package/docs/knowledge/schedule-claim-transaction.md +41 -0
- package/docs/knowledge/secret-entry-replica-contract.md +52 -0
- package/docs/knowledge/terminal-run-first-writer.md +41 -0
- package/docs/knowledge/transactional-agent-authorization.md +52 -0
- package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
- package/docs/knowledge/warm-input-publication.md +30 -0
- package/docs/knowledge/workspace-staging-failure.md +54 -0
- package/docs/knowledge.md +54 -14
- package/docs/mcp-servers.md +254 -0
- package/docs/native-sandbox.md +143 -31
- package/docs/observability.md +4 -0
- package/docs/security-deployment.md +139 -29
- package/docs/slack-notifications.md +35 -19
- package/docs/tool-secrets.md +45 -10
- package/docs/viewer-api.md +6 -0
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +28 -2
- package/help/agent-recipes.md +33 -2
- package/help/architecture-agent.md +11 -6
- package/help/brokered-secrets.md +3 -0
- package/help/build-claude-code-image.md +1 -1
- package/help/build-worker-image.md +3 -1
- package/help/builder-agent.md +19 -6
- package/help/claude-code-run-pane.md +40 -0
- package/help/code-review-agents.md +177 -6
- package/help/coding-packages.md +156 -6
- package/help/cost-attribution.md +9 -5
- package/help/creating-agents.md +14 -1
- package/help/dependency-cache.md +143 -0
- package/help/deploy-gke.md +15 -8
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-mcp-pins-unavailable.md +35 -0
- package/help/errors/coding-stream-quota-exceeded.md +33 -0
- package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
- package/help/errors/continuation-closed.md +9 -12
- package/help/errors/database-auth-invalid.md +1 -1
- package/help/errors/delegation-conflict.md +24 -0
- package/help/errors/file-list-truncated.md +45 -0
- package/help/errors/full-read-required.md +49 -0
- package/help/errors/github-account-not-allowed.md +4 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/host-provider-error.md +40 -0
- package/help/errors/host-tool-failed.md +36 -0
- package/help/errors/mcp-call-limit.md +22 -0
- package/help/errors/mcp-call-timeout.md +22 -0
- package/help/errors/mcp-server-auth-failed.md +22 -0
- package/help/errors/mcp-server-credentials-unavailable.md +45 -0
- package/help/errors/mcp-server-error.md +28 -0
- package/help/errors/mcp-server-unreachable.md +22 -0
- package/help/errors/mcp-servers-off.md +21 -0
- package/help/errors/mcp-tool-not-allowed.md +26 -0
- package/help/errors/mcp-tool-removed.md +22 -0
- package/help/errors/mcp-unavailable.md +25 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/native-sandbox-capacity.md +1 -1
- package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
- package/help/errors/native-sandbox-docker-failed.md +1 -1
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
- package/help/errors/native-sandbox-image-not-pinned.md +1 -1
- package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-network-unenforced.md +1 -1
- package/help/errors/native-sandbox-requires-catalog.md +1 -1
- package/help/errors/native-sandbox-unavailable.md +1 -1
- package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
- package/help/errors/native-sandbox-worker-exited.md +4 -3
- package/help/errors/native-sandbox-worker-lost.md +1 -1
- package/help/errors/native-sandbox-worker-unready.md +1 -1
- package/help/errors/package-not-allowed-pending.md +52 -0
- package/help/errors/package-not-allowed.md +51 -0
- package/help/errors/package-refusals.md +43 -0
- package/help/errors/patch-cursor-malformed.md +31 -0
- package/help/errors/repository-not-listed.md +36 -0
- package/help/errors/repository-required.md +36 -0
- package/help/errors/run-lost.md +39 -0
- package/help/errors/run-transcript-download.md +44 -0
- package/help/errors/secret-in-value.md +69 -0
- package/help/errors/target-merge.md +40 -0
- package/help/errors/tool-timeout.md +38 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/github-app-setup.md +132 -0
- package/help/github.md +22 -0
- package/help/host-providers.md +40 -0
- package/help/identity-and-access.md +6 -1
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +1 -1
- package/help/low-power-mode.md +7 -1
- package/help/mcp-servers.md +73 -0
- package/help/mcp.md +7 -2
- package/help/merge-order-check.md +5 -0
- package/help/native-capabilities.md +55 -1
- package/help/native-sandbox.md +16 -2
- package/help/operating-agents.md +21 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +17 -10
- package/help/repo-instructions-and-skills.md +3 -1
- package/help/resume-runs-locally.md +134 -0
- package/help/review-fix-rounds.md +33 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +19 -5
- package/help/status-comments.md +31 -0
- package/help/stop-run.md +58 -0
- package/help/troubleshooting/budgets.md +28 -0
- package/help/troubleshooting/coding-workers.md +86 -7
- package/help/troubleshooting/debugging-agent-runs.md +29 -0
- package/package.json +18 -10
- package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
- package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
- package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
- package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
- package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
- package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
- package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
- package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
- package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
- package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
- package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
- package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
- package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
- package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
- package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
- package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
- package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
- package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
- package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
- package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
- package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
- package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
- package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
- package/prisma/schema.prisma +468 -109
- package/scripts/git-askpass.sh +1 -1
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PrismaClient } from "#prisma";
|
|
2
|
+
import { type ScheduleState } from "./cron.js";
|
|
3
|
+
/**
|
|
4
|
+
* The `lastScheduledAt` to write with a schedule change: the database's
|
|
5
|
+
* clock when the change starts the schedule (see startsSchedule), nothing
|
|
6
|
+
* otherwise. The database's clock, not this process's, because the CLI and
|
|
7
|
+
* import can run on an operator's machine: a clock running ahead there would
|
|
8
|
+
* record a start after a window the scheduler has yet to fire, and skip it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function scheduleStartFields(db: Pick<PrismaClient, "$queryRaw">, before: ScheduleState | null, after: ScheduleState): Promise<{
|
|
11
|
+
lastScheduledAt: Date;
|
|
12
|
+
} | Record<string, never>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { startsSchedule } from "./cron.js";
|
|
2
|
+
/**
|
|
3
|
+
* The `lastScheduledAt` to write with a schedule change: the database's
|
|
4
|
+
* clock when the change starts the schedule (see startsSchedule), nothing
|
|
5
|
+
* otherwise. The database's clock, not this process's, because the CLI and
|
|
6
|
+
* import can run on an operator's machine: a clock running ahead there would
|
|
7
|
+
* record a start after a window the scheduler has yet to fire, and skip it.
|
|
8
|
+
*/
|
|
9
|
+
export async function scheduleStartFields(db, before, after) {
|
|
10
|
+
if (!startsSchedule(before, after))
|
|
11
|
+
return {};
|
|
12
|
+
const [{ now }] = await db.$queryRaw `SELECT now() AS now`;
|
|
13
|
+
return { lastScheduledAt: now };
|
|
14
|
+
}
|
|
@@ -1,88 +1,26 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const MIN_BROKERED_VALUE_LENGTH = 6;
|
|
3
|
+
/** False for a name a resolver could read as an IPv4 address ("127.1", "0x7f.0.0.1") or with a label ending in "-". */
|
|
4
|
+
export declare function isExactHostname(h: string): boolean;
|
|
3
5
|
export declare const SecretBrokerConfigSchema: z.ZodObject<{
|
|
4
|
-
hosts: z.ZodArray<z.
|
|
5
|
-
pathPrefixes: z.ZodOptional<z.ZodArray<z.
|
|
6
|
-
placement: z.ZodDiscriminatedUnion<
|
|
6
|
+
hosts: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
7
|
+
pathPrefixes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
8
|
+
placement: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
7
9
|
kind: z.ZodLiteral<"header">;
|
|
8
|
-
name: z.
|
|
9
|
-
format: z.
|
|
10
|
-
},
|
|
11
|
-
name: string;
|
|
12
|
-
kind: "header";
|
|
13
|
-
format: string;
|
|
14
|
-
}, {
|
|
15
|
-
name: string;
|
|
16
|
-
kind: "header";
|
|
17
|
-
format: string;
|
|
18
|
-
}>, z.ZodObject<{
|
|
10
|
+
name: z.ZodString;
|
|
11
|
+
format: z.ZodString;
|
|
12
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
19
13
|
kind: z.ZodLiteral<"query">;
|
|
20
14
|
name: z.ZodString;
|
|
21
|
-
},
|
|
22
|
-
name: string;
|
|
23
|
-
kind: "query";
|
|
24
|
-
}, {
|
|
25
|
-
name: string;
|
|
26
|
-
kind: "query";
|
|
27
|
-
}>, z.ZodObject<{
|
|
15
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
28
16
|
kind: z.ZodLiteral<"body">;
|
|
29
17
|
field: z.ZodString;
|
|
30
|
-
},
|
|
31
|
-
kind: "body";
|
|
32
|
-
field: string;
|
|
33
|
-
}, {
|
|
34
|
-
kind: "body";
|
|
35
|
-
field: string;
|
|
36
|
-
}>, z.ZodObject<{
|
|
18
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
37
19
|
kind: z.ZodLiteral<"aws-sigv4">;
|
|
38
20
|
region: z.ZodString;
|
|
39
21
|
service: z.ZodString;
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
service: string;
|
|
43
|
-
region: string;
|
|
44
|
-
}, {
|
|
45
|
-
kind: "aws-sigv4";
|
|
46
|
-
service: string;
|
|
47
|
-
region: string;
|
|
48
|
-
}>]>;
|
|
49
|
-
}, "strict", z.ZodTypeAny, {
|
|
50
|
-
hosts: string[];
|
|
51
|
-
placement: {
|
|
52
|
-
name: string;
|
|
53
|
-
kind: "header";
|
|
54
|
-
format: string;
|
|
55
|
-
} | {
|
|
56
|
-
name: string;
|
|
57
|
-
kind: "query";
|
|
58
|
-
} | {
|
|
59
|
-
kind: "body";
|
|
60
|
-
field: string;
|
|
61
|
-
} | {
|
|
62
|
-
kind: "aws-sigv4";
|
|
63
|
-
service: string;
|
|
64
|
-
region: string;
|
|
65
|
-
};
|
|
66
|
-
pathPrefixes?: string[] | undefined;
|
|
67
|
-
}, {
|
|
68
|
-
hosts: string[];
|
|
69
|
-
placement: {
|
|
70
|
-
name: string;
|
|
71
|
-
kind: "header";
|
|
72
|
-
format: string;
|
|
73
|
-
} | {
|
|
74
|
-
name: string;
|
|
75
|
-
kind: "query";
|
|
76
|
-
} | {
|
|
77
|
-
kind: "body";
|
|
78
|
-
field: string;
|
|
79
|
-
} | {
|
|
80
|
-
kind: "aws-sigv4";
|
|
81
|
-
service: string;
|
|
82
|
-
region: string;
|
|
83
|
-
};
|
|
84
|
-
pathPrefixes?: string[] | undefined;
|
|
85
|
-
}>;
|
|
22
|
+
}, z.core.$strict>], "kind">;
|
|
23
|
+
}, z.core.$strict>;
|
|
86
24
|
export type SecretBrokerConfig = z.infer<typeof SecretBrokerConfigSchema>;
|
|
87
25
|
export type SecretBrokerPlacement = SecretBrokerConfig["placement"];
|
|
88
26
|
export declare function parseSecretBrokerConfig(input: unknown): SecretBrokerConfig;
|
|
@@ -11,7 +11,7 @@ const TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,128}$/;
|
|
|
11
11
|
const HOSTNAME = /^(?=.{1,253}$)(?!-)[a-z0-9-]{1,63}(?:\.(?!-)[a-z0-9-]{1,63})+$/;
|
|
12
12
|
const IPV4 = /^\d{1,3}(?:\.\d{1,3}){3}$/;
|
|
13
13
|
/** False for a name a resolver could read as an IPv4 address ("127.1", "0x7f.0.0.1") or with a label ending in "-". */
|
|
14
|
-
function isExactHostname(h) {
|
|
14
|
+
export function isExactHostname(h) {
|
|
15
15
|
if (!HOSTNAME.test(h) || IPV4.test(h))
|
|
16
16
|
return false;
|
|
17
17
|
const labels = h.split(".");
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { PrismaClient } from "#prisma";
|
|
2
|
+
import { buildSecretsAccessor } from "./secrets.js";
|
|
3
|
+
export interface NamedSecretValues {
|
|
4
|
+
name: string;
|
|
5
|
+
values: string[];
|
|
6
|
+
}
|
|
7
|
+
type SecretGuardCipher = Parameters<typeof buildSecretsAccessor>[1];
|
|
8
|
+
type SecretGuardDb = Parameters<typeof buildSecretsAccessor>[2] & Pick<PrismaClient, "agentSecret" | "agentMcpServer" | "secret">;
|
|
9
|
+
/**
|
|
10
|
+
* Every secret attached to the agent (readable and brokered), and every secret of an MCP server
|
|
11
|
+
* attached to it (named `mcp:<server>/<secret>`), with every form to look for. Rejects if any read fails.
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadAgentSecretValues(db: SecretGuardDb, cipher: SecretGuardCipher, agentId: string): Promise<NamedSecretValues[]>;
|
|
14
|
+
/** The sorted, unique names of the secrets whose value occurs anywhere in `value`. */
|
|
15
|
+
export declare function secretNamesIn(value: unknown, named: readonly NamedSecretValues[]): string[];
|
|
16
|
+
/** The agent-visible refusal: names the secrets, never a value. At most 1000 characters. */
|
|
17
|
+
export declare function secretInValueMessage(names: readonly string[]): string;
|
|
18
|
+
export declare const SECRET_CHECK_UNAVAILABLE_MESSAGE = "secret_check_unavailable: not stored. The agent's secrets could not be read to check this value; try again.";
|
|
19
|
+
export declare const WITHHELD_TEXT_NOTICE = "[withheld: this text could not be checked for secret values]";
|
|
20
|
+
export declare class SecretInValueError extends Error {
|
|
21
|
+
readonly code = "secret_in_value";
|
|
22
|
+
readonly secretNames: string[];
|
|
23
|
+
constructor(names: readonly string[]);
|
|
24
|
+
}
|
|
25
|
+
export declare class SecretCheckUnavailableError extends Error {
|
|
26
|
+
readonly code = "secret_check_unavailable";
|
|
27
|
+
constructor();
|
|
28
|
+
}
|
|
29
|
+
/** `text` with every value of every named secret masked. */
|
|
30
|
+
export declare function maskNamedSecrets(text: string, named: readonly NamedSecretValues[]): string;
|
|
31
|
+
export interface SecretWriteGuard {
|
|
32
|
+
assertNoSecrets(agentId: string, value: unknown): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/** Refuses a value holding an attached secret's value; fails closed when the secrets cannot be read. */
|
|
35
|
+
export declare function createSecretWriteGuard(source: {
|
|
36
|
+
load(agentId: string): Promise<NamedSecretValues[]>;
|
|
37
|
+
}): SecretWriteGuard;
|
|
38
|
+
export declare function createDbSecretWriteGuard(db: SecretGuardDb, cipher: SecretGuardCipher): SecretWriteGuard;
|
|
39
|
+
/**
|
|
40
|
+
* Built-in tools whose arguments become text on a host, so their arguments are masked before
|
|
41
|
+
* the call. Review host: repo_publish_review (summary, body, inline comment bodies), repo_comment
|
|
42
|
+
* (body). Jira: jira_comment and jira_edit_own_comment (body), jira_update_fields (labels,
|
|
43
|
+
* components, priority, custom fields), jira_create_issue (summary, description, labels,
|
|
44
|
+
* components, custom fields, fingerprint), jira_set_property (a stored value), jira_transition
|
|
45
|
+
* (toStatus, which Jira may echo in an error). Read tools and jira_link_issues (a link type name
|
|
46
|
+
* checked against an allowlist) are left out.
|
|
47
|
+
*/
|
|
48
|
+
export declare const POSTING_TOOL_NAMES: ReadonlySet<string>;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { MIN_REDACTABLE_SECRET_LENGTH, redactExactSecretValues, withEscapedForms } from "./secret-spans.js";
|
|
2
|
+
import { buildSecretsAccessor } from "./secrets.js";
|
|
3
|
+
import { consoleRedactionValues } from "../sandbox/secret-broker.js";
|
|
4
|
+
import { mcpNamedSecretValues } from "./mcp-tools.js";
|
|
5
|
+
/**
|
|
6
|
+
* Every secret attached to the agent (readable and brokered), and every secret of an MCP server
|
|
7
|
+
* attached to it (named `mcp:<server>/<secret>`), with every form to look for. Rejects if any read fails.
|
|
8
|
+
*/
|
|
9
|
+
export async function loadAgentSecretValues(db, cipher, agentId) {
|
|
10
|
+
const [rows, mcp] = await Promise.all([
|
|
11
|
+
db.agentSecret.findMany({ where: { agentId }, select: { boundName: true } }),
|
|
12
|
+
mcpNamedSecretValues(db, cipher, agentId),
|
|
13
|
+
]);
|
|
14
|
+
const accessor = buildSecretsAccessor(agentId, cipher, db);
|
|
15
|
+
const own = await Promise.all(rows.map(async ({ boundName }) => {
|
|
16
|
+
const entry = await accessor.resolve(boundName);
|
|
17
|
+
return { name: boundName, values: entry ? withEscapedForms(consoleRedactionValues(entry)) : [] };
|
|
18
|
+
}));
|
|
19
|
+
return [...own, ...mcp];
|
|
20
|
+
}
|
|
21
|
+
function textOf(value) {
|
|
22
|
+
return typeof value === "string" ? value : (JSON.stringify(value) ?? "");
|
|
23
|
+
}
|
|
24
|
+
/** The sorted, unique names of the secrets whose value occurs anywhere in `value`. */
|
|
25
|
+
export function secretNamesIn(value, named) {
|
|
26
|
+
const text = textOf(value);
|
|
27
|
+
const hits = new Set();
|
|
28
|
+
for (const { name, values } of named) {
|
|
29
|
+
if (values.some((v) => v.length >= MIN_REDACTABLE_SECRET_LENGTH && text.includes(v)))
|
|
30
|
+
hits.add(name);
|
|
31
|
+
}
|
|
32
|
+
return [...hits].sort();
|
|
33
|
+
}
|
|
34
|
+
const MAX_MESSAGE_LENGTH = 1000;
|
|
35
|
+
const MCP_SECRET_PREFIX = "mcp:";
|
|
36
|
+
function refusal(names, listed) {
|
|
37
|
+
const shown = names.slice(0, listed).map((n) => JSON.stringify(n));
|
|
38
|
+
const more = names.length - listed;
|
|
39
|
+
const list = shown.join(", ") + (more > 0 ? `, and ${more} more` : "");
|
|
40
|
+
const noun = names.length > 1 ? "secrets" : "secret";
|
|
41
|
+
const head = `secret_in_value: not stored. The value contains the value of ${noun} ${list} attached to this agent, and secret values are never stored.`;
|
|
42
|
+
// An MCP server's secret (`mcp:<server>/<secret>`) is not readable by the agent, so it gets no secrets.get hint.
|
|
43
|
+
const readable = names.find((n) => !n.startsWith(MCP_SECRET_PREFIX));
|
|
44
|
+
const mcpNote = names.some((n) => n.startsWith(MCP_SECRET_PREFIX))
|
|
45
|
+
? " A name starting with mcp: is an MCP server's secret: it is used only by that server's tools and can't be stored or read."
|
|
46
|
+
: "";
|
|
47
|
+
if (readable === undefined)
|
|
48
|
+
return head + mcpNote;
|
|
49
|
+
const first = JSON.stringify(readable);
|
|
50
|
+
return `${head} Store the secret's name instead and read it when you need it: secrets.get(${first}), or fetch(url, { secrets: [${first}] }) if it is brokered.${mcpNote}`;
|
|
51
|
+
}
|
|
52
|
+
/** The agent-visible refusal: names the secrets, never a value. At most 1000 characters. */
|
|
53
|
+
export function secretInValueMessage(names) {
|
|
54
|
+
let listed = names.length;
|
|
55
|
+
while (listed > 1 && refusal(names, listed).length > MAX_MESSAGE_LENGTH)
|
|
56
|
+
listed--;
|
|
57
|
+
return refusal(names, listed);
|
|
58
|
+
}
|
|
59
|
+
export const SECRET_CHECK_UNAVAILABLE_MESSAGE = "secret_check_unavailable: not stored. The agent's secrets could not be read to check this value; try again.";
|
|
60
|
+
export const WITHHELD_TEXT_NOTICE = "[withheld: this text could not be checked for secret values]";
|
|
61
|
+
export class SecretInValueError extends Error {
|
|
62
|
+
code = "secret_in_value";
|
|
63
|
+
secretNames;
|
|
64
|
+
constructor(names) {
|
|
65
|
+
super(secretInValueMessage(names));
|
|
66
|
+
this.name = "SecretInValueError";
|
|
67
|
+
this.secretNames = [...names];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export class SecretCheckUnavailableError extends Error {
|
|
71
|
+
code = "secret_check_unavailable";
|
|
72
|
+
constructor() {
|
|
73
|
+
super(SECRET_CHECK_UNAVAILABLE_MESSAGE);
|
|
74
|
+
this.name = "SecretCheckUnavailableError";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** `text` with every value of every named secret masked. */
|
|
78
|
+
export function maskNamedSecrets(text, named) {
|
|
79
|
+
return redactExactSecretValues(text, named.flatMap((n) => n.values));
|
|
80
|
+
}
|
|
81
|
+
/** Refuses a value holding an attached secret's value; fails closed when the secrets cannot be read. */
|
|
82
|
+
export function createSecretWriteGuard(source) {
|
|
83
|
+
return {
|
|
84
|
+
async assertNoSecrets(agentId, value) {
|
|
85
|
+
let named;
|
|
86
|
+
try {
|
|
87
|
+
named = await source.load(agentId);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
throw new SecretCheckUnavailableError();
|
|
91
|
+
}
|
|
92
|
+
const names = secretNamesIn(value, named);
|
|
93
|
+
if (names.length > 0)
|
|
94
|
+
throw new SecretInValueError(names);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function createDbSecretWriteGuard(db, cipher) {
|
|
99
|
+
return createSecretWriteGuard({ load: (id) => loadAgentSecretValues(db, cipher, id) });
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Built-in tools whose arguments become text on a host, so their arguments are masked before
|
|
103
|
+
* the call. Review host: repo_publish_review (summary, body, inline comment bodies), repo_comment
|
|
104
|
+
* (body). Jira: jira_comment and jira_edit_own_comment (body), jira_update_fields (labels,
|
|
105
|
+
* components, priority, custom fields), jira_create_issue (summary, description, labels,
|
|
106
|
+
* components, custom fields, fingerprint), jira_set_property (a stored value), jira_transition
|
|
107
|
+
* (toStatus, which Jira may echo in an error). Read tools and jira_link_issues (a link type name
|
|
108
|
+
* checked against an allowlist) are left out.
|
|
109
|
+
*/
|
|
110
|
+
export const POSTING_TOOL_NAMES = new Set([
|
|
111
|
+
"repo_publish_review",
|
|
112
|
+
"repo_comment",
|
|
113
|
+
"jira_comment",
|
|
114
|
+
"jira_edit_own_comment",
|
|
115
|
+
"jira_update_fields",
|
|
116
|
+
"jira_create_issue",
|
|
117
|
+
"jira_set_property",
|
|
118
|
+
"jira_transition",
|
|
119
|
+
]);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Datastore } from "../providers/datastore/types.js";
|
|
2
|
+
import type { AgentMemoryStore } from "../providers/memory/types.js";
|
|
3
|
+
import { type SecretWriteGuard } from "./secret-guard.js";
|
|
4
|
+
/**
|
|
5
|
+
* Datastore that refuses a key or value holding an attached secret's value. Shared
|
|
6
|
+
* writes are checked against `opts.writerAgentId`; without it the writer is
|
|
7
|
+
* unknown, so the write is refused (fail closed). `writerAgentId` is stripped
|
|
8
|
+
* before the inner store sees it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function guardDatastore(inner: Datastore, guard: SecretWriteGuard): Datastore;
|
|
11
|
+
/** Agent memory that refuses a key or content holding an attached secret's value. */
|
|
12
|
+
export declare function guardAgentMemory(inner: AgentMemoryStore, guard: SecretWriteGuard): AgentMemoryStore;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { SecretCheckUnavailableError } from "./secret-guard.js";
|
|
2
|
+
/**
|
|
3
|
+
* Datastore that refuses a key or value holding an attached secret's value. Shared
|
|
4
|
+
* writes are checked against `opts.writerAgentId`; without it the writer is
|
|
5
|
+
* unknown, so the write is refused (fail closed). `writerAgentId` is stripped
|
|
6
|
+
* before the inner store sees it.
|
|
7
|
+
*/
|
|
8
|
+
export function guardDatastore(inner, guard) {
|
|
9
|
+
return {
|
|
10
|
+
get: (agentId, key) => inner.get(agentId, key),
|
|
11
|
+
async set(agentId, key, value, opts) {
|
|
12
|
+
await guard.assertNoSecrets(agentId, [key, value]);
|
|
13
|
+
return inner.set(agentId, key, value, opts);
|
|
14
|
+
},
|
|
15
|
+
delete: (agentId, key) => inner.delete(agentId, key),
|
|
16
|
+
list: (agentId, prefix) => inner.list(agentId, prefix),
|
|
17
|
+
getShared: (datastoreId, key) => inner.getShared(datastoreId, key),
|
|
18
|
+
async setShared(datastoreId, key, value, opts) {
|
|
19
|
+
const { writerAgentId, ...rest } = opts ?? {};
|
|
20
|
+
if (!writerAgentId)
|
|
21
|
+
throw new SecretCheckUnavailableError();
|
|
22
|
+
await guard.assertNoSecrets(writerAgentId, [key, value]);
|
|
23
|
+
return inner.setShared(datastoreId, key, value, rest);
|
|
24
|
+
},
|
|
25
|
+
deleteShared: (datastoreId, key) => inner.deleteShared(datastoreId, key),
|
|
26
|
+
listShared: (datastoreId, prefix) => inner.listShared(datastoreId, prefix),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Agent memory that refuses a key or content holding an attached secret's value. */
|
|
30
|
+
export function guardAgentMemory(inner, guard) {
|
|
31
|
+
return {
|
|
32
|
+
get: (agentId, key) => inner.get(agentId, key),
|
|
33
|
+
async set(agentId, key, content) {
|
|
34
|
+
await guard.assertNoSecrets(agentId, [key, content]);
|
|
35
|
+
return inner.set(agentId, key, content);
|
|
36
|
+
},
|
|
37
|
+
list: (agentId) => inner.list(agentId),
|
|
38
|
+
search: (agentId, query, limit) => inner.search(agentId, query, limit),
|
|
39
|
+
delete: (agentId, key) => inner.delete(agentId, key),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one redactor for exact secret values: every site that masks values it knows (the sandbox
|
|
3
|
+
* console bridge, the native gateway's log, the native worker's stderr, a brokered response, a
|
|
4
|
+
* coding worker's debug trace, git output) goes through these functions. It masks the union of
|
|
5
|
+
* every occurrence of every value, overlapping occurrences included, so no character of any
|
|
6
|
+
* occurrence survives however occurrences overlap (a value such as `abcabcabc` in `abc` x 5).
|
|
7
|
+
*
|
|
8
|
+
* No imports: every worker image (native sandbox, coding driver, Claude coding worker) ships this
|
|
9
|
+
* file next to its callers.
|
|
10
|
+
*/
|
|
11
|
+
/** Below this length a "secret" is too likely to coincidentally match ordinary log text — not worth the false-positive risk of redacting it. */
|
|
12
|
+
export declare const MIN_REDACTABLE_SECRET_LENGTH = 6;
|
|
13
|
+
/** The marker that stands in for each masked span, unless a site passes its own. */
|
|
14
|
+
export declare const REDACTED_MARKER = "[REDACTED]";
|
|
15
|
+
export interface RedactOptions {
|
|
16
|
+
/** Replaces each merged span (default REDACTED_MARKER). */
|
|
17
|
+
marker?: string;
|
|
18
|
+
/** Values shorter than this are left alone (default MIN_REDACTABLE_SECRET_LENGTH; an empty value never matches). */
|
|
19
|
+
minLength?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Each value plus its JSON-escaped forms, deduplicated: escaped once (`JSON.stringify(v).slice(1, -1)`)
|
|
23
|
+
* and twice. A value holding a quote, a backslash, a newline or a control character appears escaped
|
|
24
|
+
* once inside JSON text (a console line, a log line), and twice when that JSON text is itself
|
|
25
|
+
* logged as a string (`console.log(JSON.stringify({ key: value }))` through the console bridge, or
|
|
26
|
+
* a logger field that already holds JSON). The one expansion every redaction list goes through.
|
|
27
|
+
*/
|
|
28
|
+
export declare function withEscapedForms(values: Iterable<string>): string[];
|
|
29
|
+
/**
|
|
30
|
+
* The merged, sorted [start, end) spans of `text` covered by any occurrence of any value, overlapping
|
|
31
|
+
* occurrences included (the search advances by one character, not by the value's length), so a
|
|
32
|
+
* self-overlapping value is covered wherever any occurrence of it lies. Values shorter than
|
|
33
|
+
* `minLength` are ignored. Overlapping or adjacent spans merge.
|
|
34
|
+
*/
|
|
35
|
+
export declare function secretSpans(text: string, values: Iterable<string>, minLength?: number): Array<[number, number]>;
|
|
36
|
+
/** `spans` sorted and merged, overlapping or adjacent ones joined. */
|
|
37
|
+
export declare function mergeSpans(spans: ReadonlyArray<readonly [number, number]>): Array<[number, number]>;
|
|
38
|
+
/** `text` with each of the merged, sorted `spans` replaced by one `marker`. */
|
|
39
|
+
export declare function maskSpans(text: string, spans: ReadonlyArray<readonly [number, number]>, marker?: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* `text` with the union of every occurrence of each value (secretSpans) replaced by the marker;
|
|
42
|
+
* values shorter than the minimum length are left alone.
|
|
43
|
+
*/
|
|
44
|
+
export declare function redactExactSecretValues(text: string, values: Iterable<string>, options?: RedactOptions): string;
|
|
45
|
+
/**
|
|
46
|
+
* Whether `text` equals, contains, or is contained in any of `values`, under the same minimum
|
|
47
|
+
* length as redactExactSecretValues. For a short field that is sent whole or not at all (a native
|
|
48
|
+
* gateway error's cause code), where redacting part of it would still leave part of a value.
|
|
49
|
+
*/
|
|
50
|
+
export declare function overlapsSecretValue(text: string, values: Iterable<string>): boolean;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one redactor for exact secret values: every site that masks values it knows (the sandbox
|
|
3
|
+
* console bridge, the native gateway's log, the native worker's stderr, a brokered response, a
|
|
4
|
+
* coding worker's debug trace, git output) goes through these functions. It masks the union of
|
|
5
|
+
* every occurrence of every value, overlapping occurrences included, so no character of any
|
|
6
|
+
* occurrence survives however occurrences overlap (a value such as `abcabcabc` in `abc` x 5).
|
|
7
|
+
*
|
|
8
|
+
* No imports: every worker image (native sandbox, coding driver, Claude coding worker) ships this
|
|
9
|
+
* file next to its callers.
|
|
10
|
+
*/
|
|
11
|
+
/** Below this length a "secret" is too likely to coincidentally match ordinary log text — not worth the false-positive risk of redacting it. */
|
|
12
|
+
export const MIN_REDACTABLE_SECRET_LENGTH = 6;
|
|
13
|
+
/** The marker that stands in for each masked span, unless a site passes its own. */
|
|
14
|
+
export const REDACTED_MARKER = "[REDACTED]";
|
|
15
|
+
/** `text` as it appears inside a JSON string literal (JSON.stringify without the quotes). */
|
|
16
|
+
const jsonEscaped = (text) => JSON.stringify(text).slice(1, -1);
|
|
17
|
+
/**
|
|
18
|
+
* Each value plus its JSON-escaped forms, deduplicated: escaped once (`JSON.stringify(v).slice(1, -1)`)
|
|
19
|
+
* and twice. A value holding a quote, a backslash, a newline or a control character appears escaped
|
|
20
|
+
* once inside JSON text (a console line, a log line), and twice when that JSON text is itself
|
|
21
|
+
* logged as a string (`console.log(JSON.stringify({ key: value }))` through the console bridge, or
|
|
22
|
+
* a logger field that already holds JSON). The one expansion every redaction list goes through.
|
|
23
|
+
*/
|
|
24
|
+
export function withEscapedForms(values) {
|
|
25
|
+
const out = new Set();
|
|
26
|
+
for (const value of values) {
|
|
27
|
+
const once = jsonEscaped(value);
|
|
28
|
+
out.add(value);
|
|
29
|
+
out.add(once);
|
|
30
|
+
out.add(jsonEscaped(once));
|
|
31
|
+
}
|
|
32
|
+
return [...out];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The merged, sorted [start, end) spans of `text` covered by any occurrence of any value, overlapping
|
|
36
|
+
* occurrences included (the search advances by one character, not by the value's length), so a
|
|
37
|
+
* self-overlapping value is covered wherever any occurrence of it lies. Values shorter than
|
|
38
|
+
* `minLength` are ignored. Overlapping or adjacent spans merge.
|
|
39
|
+
*/
|
|
40
|
+
export function secretSpans(text, values, minLength = MIN_REDACTABLE_SECRET_LENGTH) {
|
|
41
|
+
const spans = [];
|
|
42
|
+
const shortest = Math.max(1, minLength);
|
|
43
|
+
for (const value of new Set(values)) {
|
|
44
|
+
if (value.length < shortest)
|
|
45
|
+
continue;
|
|
46
|
+
for (let at = text.indexOf(value); at >= 0; at = text.indexOf(value, at + 1))
|
|
47
|
+
spans.push([at, at + value.length]);
|
|
48
|
+
}
|
|
49
|
+
return mergeSpans(spans);
|
|
50
|
+
}
|
|
51
|
+
/** `spans` sorted and merged, overlapping or adjacent ones joined. */
|
|
52
|
+
export function mergeSpans(spans) {
|
|
53
|
+
const sorted = spans.filter(([start, end]) => end > start).sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
54
|
+
const merged = [];
|
|
55
|
+
for (const [start, end] of sorted) {
|
|
56
|
+
const last = merged[merged.length - 1];
|
|
57
|
+
if (last && start <= last[1])
|
|
58
|
+
last[1] = Math.max(last[1], end);
|
|
59
|
+
else
|
|
60
|
+
merged.push([start, end]);
|
|
61
|
+
}
|
|
62
|
+
return merged;
|
|
63
|
+
}
|
|
64
|
+
/** `text` with each of the merged, sorted `spans` replaced by one `marker`. */
|
|
65
|
+
export function maskSpans(text, spans, marker = REDACTED_MARKER) {
|
|
66
|
+
let out = "";
|
|
67
|
+
let from = 0;
|
|
68
|
+
for (const [start, end] of spans) {
|
|
69
|
+
out += `${text.slice(from, start)}${marker}`;
|
|
70
|
+
from = end;
|
|
71
|
+
}
|
|
72
|
+
return out + text.slice(from);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* `text` with the union of every occurrence of each value (secretSpans) replaced by the marker;
|
|
76
|
+
* values shorter than the minimum length are left alone.
|
|
77
|
+
*/
|
|
78
|
+
export function redactExactSecretValues(text, values, options = {}) {
|
|
79
|
+
return maskSpans(text, secretSpans(text, values, options.minLength), options.marker);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Whether `text` equals, contains, or is contained in any of `values`, under the same minimum
|
|
83
|
+
* length as redactExactSecretValues. For a short field that is sent whole or not at all (a native
|
|
84
|
+
* gateway error's cause code), where redacting part of it would still leave part of a value.
|
|
85
|
+
*/
|
|
86
|
+
export function overlapsSecretValue(text, values) {
|
|
87
|
+
for (const value of values) {
|
|
88
|
+
if (value.length < MIN_REDACTABLE_SECRET_LENGTH)
|
|
89
|
+
continue;
|
|
90
|
+
if (text.includes(value) || value.includes(text))
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
package/dist/core/secrets.d.ts
CHANGED
|
@@ -23,6 +23,15 @@ export interface SecretsAccessor {
|
|
|
23
23
|
/** Host-internal: value and broker config, brokered or not. Never exposed to tool code. */
|
|
24
24
|
resolve?(name: string): Promise<SecretEntry | undefined>;
|
|
25
25
|
}
|
|
26
|
+
/** A webhook secret signs what a host sends us, so a short one is refused at registration and at rotation. */
|
|
27
|
+
export declare const MIN_WEBHOOK_SECRET_LENGTH = 16;
|
|
28
|
+
export declare const WEBHOOK_SECRET_SHORT = "host_provider_webhook_secret_short: a host provider's webhook secret needs at least 16 characters";
|
|
29
|
+
export declare const WEBHOOK_SECRET_ATTACHED = "host_provider_webhook_secret_attached: this secret is a host provider's webhook secret and can't be attached to an agent";
|
|
30
|
+
/** The host providers using a secret, by name, and whether it's the webhook secret of any. */
|
|
31
|
+
export declare function hostProvidersUsingSecret(db: Pick<PrismaClient, "hostProvider" | "hostProviderCredential">, secretId: string): Promise<{
|
|
32
|
+
providers: string[];
|
|
33
|
+
webhook: boolean;
|
|
34
|
+
}>;
|
|
26
35
|
/**
|
|
27
36
|
* Encrypts and stores a secret value. Upserts on (ownerId, name) — calling
|
|
28
37
|
* this again for a name the owner already has rotates its value in place
|
|
@@ -56,7 +65,8 @@ export declare function setSecretBroker(db: PrismaClient, cipher: SecretCipher,
|
|
|
56
65
|
export declare function listSecrets(ownerId: string, db: PrismaClient): Promise<SecretMetadata[]>;
|
|
57
66
|
/** Attaches one of the owner's own secrets (by canonical name) to an agent,
|
|
58
67
|
* under `boundName` — the point-of-use name the agent's tools resolve
|
|
59
|
-
* (`secrets.get(boundName)`). Defaults to the secret's own name.
|
|
68
|
+
* (`secrets.get(boundName)`). Defaults to the secret's own name. A host
|
|
69
|
+
* provider's webhook secret is kept off every agent, so no tool can read it. */
|
|
60
70
|
export declare function attachSecret(agentId: string, name: string, ownerId: string, db: PrismaClient, boundName?: string): Promise<void>;
|
|
61
71
|
/** Detaches by point-of-use name — the pair (agentId, boundName) uniquely
|
|
62
72
|
* identifies the edge — falling back to the secret's own name when no edge
|
package/dist/core/secrets.js
CHANGED
|
@@ -13,6 +13,22 @@ function brokerOf(secret) {
|
|
|
13
13
|
return secret.broker === null || secret.broker === undefined ? null : parseSecretBrokerConfig(secret.broker);
|
|
14
14
|
}
|
|
15
15
|
const BROKERED_GET_MESSAGE = 'secret_brokered: this secret is brokered; send it with fetch(url, { secrets: ["NAME"] }) instead of reading it';
|
|
16
|
+
/** A webhook secret signs what a host sends us, so a short one is refused at registration and at rotation. */
|
|
17
|
+
export const MIN_WEBHOOK_SECRET_LENGTH = 16;
|
|
18
|
+
export const WEBHOOK_SECRET_SHORT = `host_provider_webhook_secret_short: a host provider's webhook secret needs at least ${MIN_WEBHOOK_SECRET_LENGTH} characters`;
|
|
19
|
+
export const WEBHOOK_SECRET_ATTACHED = "host_provider_webhook_secret_attached: this secret is a host provider's webhook secret and can't be attached to an agent";
|
|
20
|
+
/** The host providers using a secret, by name, and whether it's the webhook secret of any. */
|
|
21
|
+
export async function hostProvidersUsingSecret(db, secretId) {
|
|
22
|
+
const credentials = await db.hostProviderCredential.findMany({ where: { secretId }, select: { provider: true } });
|
|
23
|
+
const rows = await db.hostProvider.findMany({
|
|
24
|
+
where: { OR: [{ webhookSecretId: secretId }, { permissionSecretId: secretId }] },
|
|
25
|
+
select: { name: true, webhookSecretId: true },
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
providers: [...new Set([...credentials.map((c) => c.provider), ...rows.map((r) => r.name)])].sort(),
|
|
29
|
+
webhook: rows.some((r) => r.webhookSecretId === secretId),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
16
32
|
/**
|
|
17
33
|
* Encrypts and stores a secret value. Upserts on (ownerId, name) — calling
|
|
18
34
|
* this again for a name the owner already has rotates its value in place
|
|
@@ -23,6 +39,12 @@ const BROKERED_GET_MESSAGE = 'secret_brokered: this secret is brokered; send it
|
|
|
23
39
|
export async function createSecret(name, value, ownerId, cipher, db, options = {}) {
|
|
24
40
|
boundedString(name, 1024);
|
|
25
41
|
boundedString(value, 65_536);
|
|
42
|
+
if (value.length < MIN_WEBHOOK_SECRET_LENGTH) {
|
|
43
|
+
const current = await db.secret.findUnique({ where: { ownerId_name: { ownerId, name } }, select: { id: true } });
|
|
44
|
+
if (current && (await db.hostProvider.count({ where: { webhookSecretId: current.id } })) > 0) {
|
|
45
|
+
throw new Error(WEBHOOK_SECRET_SHORT);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
26
48
|
const broker = options.broker ? parseSecretBrokerConfig(options.broker) : undefined;
|
|
27
49
|
if (broker)
|
|
28
50
|
assertBrokerableValue(broker, value);
|
|
@@ -122,11 +144,15 @@ async function findOwnedSecretByName(db, ownerId, name) {
|
|
|
122
144
|
}
|
|
123
145
|
/** Attaches one of the owner's own secrets (by canonical name) to an agent,
|
|
124
146
|
* under `boundName` — the point-of-use name the agent's tools resolve
|
|
125
|
-
* (`secrets.get(boundName)`). Defaults to the secret's own name.
|
|
147
|
+
* (`secrets.get(boundName)`). Defaults to the secret's own name. A host
|
|
148
|
+
* provider's webhook secret is kept off every agent, so no tool can read it. */
|
|
126
149
|
export async function attachSecret(agentId, name, ownerId, db, boundName = name) {
|
|
127
150
|
const secret = await findOwnedSecretByName(db, ownerId, name);
|
|
128
151
|
if (!secret)
|
|
129
152
|
throw new Error(`No secret named "${name}" owned by this caller.`);
|
|
153
|
+
if ((await db.hostProvider.count({ where: { webhookSecretId: secret.id } })) > 0) {
|
|
154
|
+
throw new Error(WEBHOOK_SECRET_ATTACHED);
|
|
155
|
+
}
|
|
130
156
|
await db.agentSecret.create({ data: { agentId, secretId: secret.id, boundName } });
|
|
131
157
|
}
|
|
132
158
|
/** Detaches by point-of-use name — the pair (agentId, boundName) uniquely
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run first inside each of those transactions (make_owner, attach_mcp_server, grant/revoke). Postgres's Serializable mode takes a predicate (SIREAD)
|
|
3
|
+
* lock on everything a statement reads, and a sequential scan locks the whole relation and checks every
|
|
4
|
+
* row in it for conflicts. On small tables (a fresh deployment, or a test database) the planner picks a
|
|
5
|
+
* sequential scan even for a primary-key lookup, so two admin actions on unrelated agents read each
|
|
6
|
+
* other's rows and abort one another, retry after retry, while either keeps running. The Postgres manual
|
|
7
|
+
* ("Serializable Isolation Level") recommends steering these transactions to index scans; their queries
|
|
8
|
+
* are keyed by indexed agent, server or resource ids, so turning sequential scans off for this
|
|
9
|
+
* transaction only (SET LOCAL) narrows the locks to the rows and index pages actually read. It changes
|
|
10
|
+
* plans, never results: a query with no usable index still scans.
|
|
11
|
+
*/
|
|
12
|
+
export declare function preferIndexScans(tx: {
|
|
13
|
+
$executeRawUnsafe(query: string): Promise<number>;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
export declare function withSerializableRetry<T>(fn: () => Promise<T>, options?: {
|
|
16
|
+
attempts?: number;
|
|
17
|
+
sleep?: (ms: number) => Promise<void>;
|
|
18
|
+
}): Promise<T>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bounded retry for short Serializable transactions on admin and owner actions (make_owner,
|
|
3
|
+
* attach_mcp_server, grant/revoke that prune attachments). Postgres aborts one side of a conflicting
|
|
4
|
+
* pair; nothing of the aborted attempt was committed, so running it again is safe. Only serialization
|
|
5
|
+
* conflicts (isSerializationConflict: P2034, a raw-statement 40001/40P01, or one at COMMIT) are
|
|
6
|
+
* retried; anything else, and the last attempt's conflict, is rethrown for mapPrismaError (409).
|
|
7
|
+
*/
|
|
8
|
+
import { isSerializationConflict } from "./dispatch.js";
|
|
9
|
+
const BASE_DELAY_MS = 20;
|
|
10
|
+
const MAX_DELAY_MS = 250;
|
|
11
|
+
/** Jittered exponential backoff: half the ceiling plus up to half again. */
|
|
12
|
+
function delayMs(attempt) {
|
|
13
|
+
const ceiling = Math.min(MAX_DELAY_MS, BASE_DELAY_MS * 2 ** attempt);
|
|
14
|
+
return Math.floor(ceiling / 2 + Math.random() * (ceiling / 2));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Run first inside each of those transactions (make_owner, attach_mcp_server, grant/revoke). Postgres's Serializable mode takes a predicate (SIREAD)
|
|
18
|
+
* lock on everything a statement reads, and a sequential scan locks the whole relation and checks every
|
|
19
|
+
* row in it for conflicts. On small tables (a fresh deployment, or a test database) the planner picks a
|
|
20
|
+
* sequential scan even for a primary-key lookup, so two admin actions on unrelated agents read each
|
|
21
|
+
* other's rows and abort one another, retry after retry, while either keeps running. The Postgres manual
|
|
22
|
+
* ("Serializable Isolation Level") recommends steering these transactions to index scans; their queries
|
|
23
|
+
* are keyed by indexed agent, server or resource ids, so turning sequential scans off for this
|
|
24
|
+
* transaction only (SET LOCAL) narrows the locks to the rows and index pages actually read. It changes
|
|
25
|
+
* plans, never results: a query with no usable index still scans.
|
|
26
|
+
*/
|
|
27
|
+
export async function preferIndexScans(tx) {
|
|
28
|
+
await tx.$executeRawUnsafe("SET LOCAL enable_seqscan = off");
|
|
29
|
+
}
|
|
30
|
+
export async function withSerializableRetry(fn, options = {}) {
|
|
31
|
+
const attempts = Math.max(1, options.attempts ?? 3);
|
|
32
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
33
|
+
for (let attempt = 0;; attempt += 1) {
|
|
34
|
+
try {
|
|
35
|
+
return await fn();
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (!isSerializationConflict(err) || attempt >= attempts - 1)
|
|
39
|
+
throw err;
|
|
40
|
+
await sleep(delayMs(attempt));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|