@wardby/cli 0.2.1 → 0.3.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 +34 -4
- package/README.md +41 -4
- package/dist/claude-coding-worker/driver.d.ts +6 -1
- package/dist/claude-coding-worker/driver.js +27 -1
- package/dist/claude-coding-worker/main.js +2 -0
- package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
- package/dist/claude-coding-worker/tool-socket.js +26 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +13 -4
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +219 -29
- package/dist/coding/collect-exclude.d.ts +25 -0
- package/dist/coding/collect-exclude.js +76 -0
- package/dist/coding/profile.d.ts +67 -22
- package/dist/coding/profile.js +58 -25
- package/dist/coding/protected-path-wording.d.ts +24 -0
- package/dist/coding/protected-path-wording.js +55 -0
- package/dist/coding/protected-paths.d.ts +31 -0
- package/dist/coding/protected-paths.js +48 -0
- package/dist/coding/protocol.d.ts +75 -4
- package/dist/coding/protocol.js +107 -7
- package/dist/coding/registry/adapters.d.ts +2 -0
- package/dist/coding/registry/adapters.js +9 -0
- package/dist/coding/registry/allowlist.d.ts +9 -0
- package/dist/coding/registry/allowlist.js +28 -0
- package/dist/coding/registry/json-scan.d.ts +55 -0
- package/dist/coding/registry/json-scan.js +191 -0
- package/dist/coding/registry/lockfiles.d.ts +6 -0
- package/dist/coding/registry/lockfiles.js +89 -0
- package/dist/coding/registry/npm-lockfile.d.ts +9 -0
- package/dist/coding/registry/npm-lockfile.js +73 -0
- package/dist/coding/registry/npm-plan.d.ts +29 -0
- package/dist/coding/registry/npm-plan.js +289 -0
- package/dist/coding/registry/npm.d.ts +7 -0
- package/dist/coding/registry/npm.js +252 -0
- package/dist/coding/registry/pypi.d.ts +4 -0
- package/dist/coding/registry/pypi.js +210 -0
- package/dist/coding/registry/report.d.ts +37 -0
- package/dist/coding/registry/report.js +31 -0
- package/dist/coding/registry/token.d.ts +4 -0
- package/dist/coding/registry/token.js +7 -0
- package/dist/coding/registry/types.d.ts +286 -0
- package/dist/coding/registry/types.js +19 -0
- package/dist/coding/registry/worker-config.d.ts +14 -0
- package/dist/coding/registry/worker-config.js +31 -0
- package/dist/coding/services/builtins.d.ts +22 -0
- package/dist/coding/services/builtins.js +85 -0
- package/dist/coding/services/catalog.d.ts +443 -0
- package/dist/coding/services/catalog.js +159 -0
- package/dist/coding/services/declaration.d.ts +11 -0
- package/dist/coding/services/declaration.js +114 -0
- package/dist/coding/services/note.d.ts +8 -0
- package/dist/coding/services/note.js +15 -0
- package/dist/coding/services/resolve.d.ts +25 -0
- package/dist/coding/services/resolve.js +50 -0
- package/dist/coding/services/wording.d.ts +25 -0
- package/dist/coding/services/wording.js +70 -0
- package/dist/coding-proxy/main.js +24 -4
- package/dist/coding-worker/artifact.d.ts +6 -0
- package/dist/coding-worker/debug-trace.d.ts +37 -0
- package/dist/coding-worker/debug-trace.js +117 -0
- package/dist/coding-worker/driver.d.ts +13 -1
- package/dist/coding-worker/driver.js +102 -13
- package/dist/coding-worker/errors.js +8 -0
- package/dist/coding-worker/main.js +10 -2
- package/dist/coding-worker/sdk.d.ts +2 -2
- package/dist/coding-worker/sdk.js +7 -2
- package/dist/coding-worker/types.d.ts +3 -0
- package/dist/config/providers.d.ts +41 -0
- package/dist/config/providers.js +66 -0
- package/dist/core/budget-groups.d.ts +108 -5
- package/dist/core/budget-groups.js +125 -19
- package/dist/core/budget-wording.d.ts +22 -0
- package/dist/core/budget-wording.js +55 -0
- package/dist/core/datastores.js +18 -2
- package/dist/core/db.d.ts +5 -1
- package/dist/core/db.js +8 -2
- package/dist/core/dispatch.d.ts +33 -6
- package/dist/core/dispatch.js +260 -43
- package/dist/core/engine-native.js +27 -10
- package/dist/core/grants.d.ts +86 -0
- package/dist/core/grants.js +126 -0
- package/dist/core/host-events.d.ts +49 -0
- package/dist/core/host-events.js +257 -0
- package/dist/core/host-identity-links.d.ts +54 -0
- package/dist/core/host-identity-links.js +189 -0
- package/dist/core/host-status.d.ts +61 -0
- package/dist/core/host-status.js +211 -0
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +38 -2
- package/dist/core/reconciler.js +86 -2
- package/dist/core/repo-access.d.ts +99 -0
- package/dist/core/repo-access.js +136 -0
- package/dist/core/review-host-checks.d.ts +11 -0
- package/dist/core/review-host-checks.js +41 -0
- package/dist/core/review-host-tools.d.ts +47 -0
- package/dist/core/review-host-tools.js +347 -0
- package/dist/core/run-heartbeat.d.ts +27 -0
- package/dist/core/run-heartbeat.js +54 -0
- package/dist/core/runner.d.ts +30 -8
- package/dist/core/runner.js +237 -40
- package/dist/core/secrets.d.ts +11 -2
- package/dist/core/secrets.js +25 -6
- package/dist/core/subagent-memory-tools.d.ts +1 -1
- package/dist/core/subagent-memory-tools.js +16 -3
- package/dist/core/tool-admin.d.ts +81 -0
- package/dist/core/tool-admin.js +129 -0
- package/dist/core/tool-names.d.ts +42 -0
- package/dist/core/tool-names.js +64 -0
- package/dist/core/untrusted-content.d.ts +32 -0
- package/dist/core/untrusted-content.js +72 -0
- package/dist/core/webhooks.d.ts +8 -1
- package/dist/core/webhooks.js +23 -2
- package/dist/generated/prisma/browser.d.ts +100 -0
- package/dist/generated/prisma/client.d.ts +100 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +30 -0
- package/dist/generated/prisma/enums.d.ts +6 -0
- package/dist/generated/prisma/enums.js +6 -1
- package/dist/generated/prisma/internal/class.d.ts +143 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1746 -577
- package/dist/generated/prisma/internal/prismaNamespace.js +179 -6
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +186 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +179 -6
- package/dist/generated/prisma/models/Agent.d.ts +294 -1
- package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
- package/dist/generated/prisma/models/AgentRepository.js +1 -0
- package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
- package/dist/generated/prisma/models/CodingProxySession.d.ts +123 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1276 -95
- package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
- package/dist/generated/prisma/models/CodingService.js +1 -0
- package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
- package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
- package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
- package/dist/generated/prisma/models/HostIdentity.js +1 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
- package/dist/generated/prisma/models/Principal.d.ts +455 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
- package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
- package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
- package/dist/generated/prisma/models/RegistryFetch.js +1 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
- package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
- package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
- package/dist/generated/prisma/models/ResourceGrant.js +1 -0
- package/dist/generated/prisma/models/Run.d.ts +389 -1
- package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
- package/dist/generated/prisma/models/RunHostCheck.js +1 -0
- package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
- package/dist/generated/prisma/models/RunHostStatus.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +15 -3
- package/dist/generated/prisma/models.d.ts +13 -0
- package/dist/help/build.d.ts +1 -0
- package/dist/help/build.js +9 -0
- package/dist/help/catalog.d.ts +24 -0
- package/dist/help/catalog.js +160 -0
- package/dist/help/cli.d.ts +2 -0
- package/dist/help/cli.js +65 -0
- package/dist/help/runtime.d.ts +3 -0
- package/dist/help/runtime.js +44 -0
- package/dist/help/search.d.ts +9 -0
- package/dist/help/search.js +104 -0
- package/dist/help-index.json +660 -0
- package/dist/import/cli-args.js +3 -2
- package/dist/import/create.d.ts +5 -0
- package/dist/import/create.js +67 -13
- package/dist/import/index.js +19 -9
- package/dist/import/neutral-schema.d.ts +11 -11
- package/dist/mcp/auth/access.d.ts +70 -0
- package/dist/mcp/auth/access.js +58 -0
- package/dist/mcp/auth/grants-cli.d.ts +149 -0
- package/dist/mcp/auth/grants-cli.js +518 -0
- package/dist/mcp/auth/host-account-cli.d.ts +2 -0
- package/dist/mcp/auth/host-account-cli.js +47 -0
- package/dist/mcp/auth/ownership.d.ts +26 -52
- package/dist/mcp/auth/ownership.js +19 -14
- package/dist/mcp/auth/repo-authorization.d.ts +22 -0
- package/dist/mcp/auth/repo-authorization.js +51 -0
- package/dist/mcp/auth/resource-server.d.ts +31 -2
- package/dist/mcp/auth/resource-server.js +84 -3
- package/dist/mcp/auth/self-hosted/browser.js +2 -2
- package/dist/mcp/auth/self-hosted/cli.js +47 -13
- package/dist/mcp/auth/self-hosted/credentials.d.ts +20 -2
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -1
- package/dist/mcp/context.d.ts +27 -1
- package/dist/mcp/errors.d.ts +25 -6
- package/dist/mcp/errors.js +98 -0
- package/dist/mcp/host-events/github-ingress.d.ts +36 -0
- package/dist/mcp/host-events/github-ingress.js +92 -0
- package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
- package/dist/mcp/host-events/github-user-callback.js +50 -0
- package/dist/mcp/index.d.ts +8 -1
- package/dist/mcp/index.js +106 -16
- package/dist/mcp/server.js +27 -9
- package/dist/mcp/tools/agents.js +446 -48
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/datastore.js +22 -15
- package/dist/mcp/tools/grants.d.ts +2 -0
- package/dist/mcp/tools/grants.js +239 -0
- package/dist/mcp/tools/help.d.ts +5 -0
- package/dist/mcp/tools/help.js +67 -0
- package/dist/mcp/tools/host-accounts.d.ts +2 -0
- package/dist/mcp/tools/host-accounts.js +114 -0
- package/dist/mcp/tools/memory.d.ts +7 -1
- package/dist/mcp/tools/memory.js +5 -5
- package/dist/mcp/tools/repositories.d.ts +2 -0
- package/dist/mcp/tools/repositories.js +181 -0
- package/dist/mcp/tools/runs.d.ts +6 -0
- package/dist/mcp/tools/runs.js +60 -6
- package/dist/mcp/tools/scheduling.js +3 -6
- package/dist/mcp/tools/secrets.js +18 -6
- package/dist/mcp/tools/services.d.ts +2 -0
- package/dist/mcp/tools/services.js +222 -0
- package/dist/mcp/tools/subagents.js +52 -16
- package/dist/mcp/tools/tools.d.ts +41 -0
- package/dist/mcp/tools/tools.js +201 -40
- package/dist/mcp/tools/trigger.js +36 -6
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +10 -0
- package/dist/mcp/transport/streamable-http.js +32 -2
- package/dist/providers/auth/delegating.d.ts +19 -0
- package/dist/providers/auth/delegating.js +71 -0
- package/dist/providers/auth/index.d.ts +2 -0
- package/dist/providers/auth/index.js +11 -0
- package/dist/providers/auth/self-hosted.d.ts +2 -1
- package/dist/providers/auth/self-hosted.js +16 -4
- package/dist/providers/auth/types.d.ts +6 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
- package/dist/providers/coding-proxy/memory-ledger.js +21 -2
- package/dist/providers/coding-proxy/metering.d.ts +4 -0
- package/dist/providers/coding-proxy/metering.js +28 -2
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
- package/dist/providers/coding-proxy/proxy.d.ts +13 -0
- package/dist/providers/coding-proxy/proxy.js +479 -18
- package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
- package/dist/providers/coding-proxy/registry/audit.js +380 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
- package/dist/providers/coding-proxy/registry/plan.js +304 -0
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
- package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
- package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
- package/dist/providers/coding-proxy/registry/service.js +1137 -0
- package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
- package/dist/providers/coding-proxy/registry/store.js +70 -0
- package/dist/providers/coding-proxy/runtime.d.ts +17 -0
- package/dist/providers/coding-proxy/runtime.js +63 -0
- package/dist/providers/coding-proxy/secure-fetch.js +0 -1
- package/dist/providers/coding-proxy/server.d.ts +11 -0
- package/dist/providers/coding-proxy/server.js +163 -0
- package/dist/providers/coding-proxy/types.d.ts +15 -0
- package/dist/providers/engine/types.d.ts +10 -0
- package/dist/providers/executor/build.d.ts +2 -2
- package/dist/providers/executor/composition.d.ts +3 -0
- package/dist/providers/executor/composition.js +19 -0
- package/dist/providers/executor/container.d.ts +105 -3
- package/dist/providers/executor/container.js +296 -20
- package/dist/providers/executor/dbos.d.ts +2 -3
- package/dist/providers/executor/in-process.d.ts +2 -3
- package/dist/providers/executor/routing.d.ts +7 -0
- package/dist/providers/executor/routing.js +13 -0
- package/dist/providers/executor/types.d.ts +22 -0
- package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
- package/dist/providers/jobs/claude-tool-setup.js +50 -0
- package/dist/providers/jobs/collect-prune.d.ts +7 -0
- package/dist/providers/jobs/collect-prune.js +27 -0
- package/dist/providers/jobs/docker-isolation.d.ts +48 -3
- package/dist/providers/jobs/docker-isolation.js +213 -22
- package/dist/providers/jobs/docker-services.d.ts +35 -0
- package/dist/providers/jobs/docker-services.js +191 -0
- package/dist/providers/jobs/docker.d.ts +49 -2
- package/dist/providers/jobs/docker.js +279 -32
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
- package/dist/providers/jobs/kubernetes-isolation.js +238 -57
- package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
- package/dist/providers/jobs/kubernetes-platform.js +11 -5
- package/dist/providers/jobs/kubernetes-preflight.js +3 -0
- package/dist/providers/jobs/kubernetes.d.ts +21 -2
- package/dist/providers/jobs/kubernetes.js +112 -21
- package/dist/providers/jobs/types.d.ts +18 -0
- package/dist/providers/llm/anthropic.js +6 -2
- package/dist/providers/llm/bedrock.js +2 -1
- package/dist/providers/llm/claude-messages.d.ts +5 -1
- package/dist/providers/llm/claude-messages.js +1 -0
- package/dist/providers/llm/claude-provider.d.ts +3 -1
- package/dist/providers/llm/claude-provider.js +5 -1
- package/dist/providers/llm/index.d.ts +1 -1
- package/dist/providers/llm/index.js +1 -1
- package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
- package/dist/providers/llm/pricing-anthropic.js +32 -14
- package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
- package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
- package/dist/providers/llm/routing.d.ts +10 -1
- package/dist/providers/llm/routing.js +18 -0
- package/dist/providers/llm/types.d.ts +12 -0
- package/dist/providers/llm/types.js +8 -1
- package/dist/providers/review-host/diff-lines.d.ts +16 -0
- package/dist/providers/review-host/diff-lines.js +59 -0
- package/dist/providers/review-host/github-events.d.ts +6 -0
- package/dist/providers/review-host/github-events.js +180 -0
- package/dist/providers/review-host/github-user-auth.d.ts +38 -0
- package/dist/providers/review-host/github-user-auth.js +128 -0
- package/dist/providers/review-host/github.d.ts +57 -0
- package/dist/providers/review-host/github.js +567 -0
- package/dist/providers/review-host/index.d.ts +12 -0
- package/dist/providers/review-host/index.js +30 -0
- package/dist/providers/review-host/review-format.d.ts +19 -0
- package/dist/providers/review-host/review-format.js +59 -0
- package/dist/providers/review-host/types.d.ts +284 -0
- package/dist/providers/review-host/types.js +24 -0
- package/dist/providers/vcs/git.d.ts +16 -6
- package/dist/providers/vcs/git.js +77 -13
- package/dist/providers/vcs/github.d.ts +74 -3
- package/dist/providers/vcs/github.js +195 -15
- package/dist/providers/vcs/types.d.ts +42 -4
- package/dist/quickstart/index.js +13 -2
- package/dist/sandbox/fetch-policy.d.ts +20 -2
- package/dist/sandbox/fetch-policy.js +64 -3
- package/dist/sandbox/host-functions.d.ts +9 -1
- package/dist/sandbox/host-functions.js +12 -5
- package/dist/serve.js +1 -1
- package/dist/wardby-bin.js +6 -0
- package/docs/README.md +30 -0
- package/docs/architecture-runtime.md +90 -0
- package/docs/assets/brand/wardby-icon-512.png +0 -0
- package/docs/assets/brand/wardby-icon.svg +16 -0
- package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
- package/docs/assets/brand/wardby-mascot.png +0 -0
- package/docs/assets/brand/wardby-mascot.svg +5 -0
- package/docs/assets/wardby-workflow.svg +106 -0
- package/docs/code-review-agents.md +481 -0
- package/docs/coding-agent-setup.md +172 -0
- package/docs/coding-packages.md +455 -0
- package/docs/coding-services.md +300 -0
- package/docs/coding-worker-byo-images.md +98 -0
- package/docs/coding-worker-isolation.md +1061 -0
- package/docs/getting-started-gke.md +615 -0
- package/docs/getting-started-identity-provider.md +308 -0
- package/docs/getting-started.md +133 -0
- package/docs/observability.md +53 -0
- package/docs/release-verification.md +66 -0
- package/docs/security-deployment.md +657 -0
- package/help/code-review-agents.md +31 -0
- package/help/coding-packages.md +31 -0
- package/help/coding-services.md +71 -0
- package/help/creating-agents.md +68 -0
- package/help/deploy-gke.md +39 -0
- package/help/deployment-targets.md +39 -0
- package/help/errors/budget-group-exhausted.md +25 -0
- package/help/errors/docker-isolation-unsupported.md +26 -0
- package/help/errors/protected-path.md +45 -0
- package/help/errors/repo-access.md +27 -0
- package/help/errors/service-declaration-invalid.md +27 -0
- package/help/errors/service-declaration-unavailable.md +25 -0
- package/help/errors/service-launcher-unsupported.md +30 -0
- package/help/errors/service-not-allowed.md +27 -0
- package/help/errors/service-unknown.md +23 -0
- package/help/errors/service-unready.md +49 -0
- package/help/getting-started.md +31 -0
- package/help/github.md +30 -0
- package/help/identity-and-access.md +39 -0
- package/help/mcp.md +30 -0
- package/help/native-capabilities.md +30 -0
- package/help/observability.md +41 -0
- package/help/operating-agents.md +30 -0
- package/help/security.md +27 -0
- package/help/troubleshooting/budgets.md +26 -0
- package/help/troubleshooting/coding-workers.md +47 -0
- package/help/troubleshooting/repository-access.md +27 -0
- package/package.json +12 -3
- package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
- package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
- package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
- package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
- package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
- package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
- package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
- package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
- package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
- package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
- package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
- package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
- package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
- package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
- package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
- package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
- package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
- package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
- package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
- package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
- package/prisma/schema.prisma +407 -21
package/dist/import/cli-args.js
CHANGED
|
@@ -21,9 +21,10 @@ export function parseImportArgs(args) {
|
|
|
21
21
|
throw new Error("Missing bundle directory positional argument");
|
|
22
22
|
}
|
|
23
23
|
const dir = positionals[0];
|
|
24
|
-
// Parse owner/public
|
|
24
|
+
// Parse owner/public: --public may be combined with --owner (the owner of
|
|
25
|
+
// the imported agents, which --public then shares with everyone).
|
|
25
26
|
const isPublic = values.public ?? false;
|
|
26
|
-
const owner =
|
|
27
|
+
const owner = values.owner ?? null;
|
|
27
28
|
// Validate on-conflict
|
|
28
29
|
const onConflict = (values["on-conflict"] ?? "fail");
|
|
29
30
|
if (!VALID_CONFLICT_POLICIES.includes(onConflict)) {
|
package/dist/import/create.d.ts
CHANGED
|
@@ -11,7 +11,12 @@ import type { SecretCipher } from "../providers/secrets/types.js";
|
|
|
11
11
|
export interface CreateOptions {
|
|
12
12
|
db: PrismaClient;
|
|
13
13
|
cipher: SecretCipher;
|
|
14
|
+
/** Owner of the imported tools, secrets, datastores, webhooks and budget groups; null in --public mode. */
|
|
14
15
|
ownerId: string | null;
|
|
16
|
+
/** Owner of the imported agents (defaults to ownerId): never null for a real import. */
|
|
17
|
+
agentOwnerId?: string | null;
|
|
18
|
+
/** --public: share each imported agent with everyone at execute. */
|
|
19
|
+
publicAgents?: boolean;
|
|
15
20
|
defaultBudget: string;
|
|
16
21
|
secretMode: "references" | "envelope";
|
|
17
22
|
transferPrivateKey?: KeyObject;
|
package/dist/import/create.js
CHANGED
|
@@ -8,12 +8,15 @@ import { createSecret, attachSecret } from "../core/secrets.js";
|
|
|
8
8
|
import { createDatastore, attachDatastore } from "../core/datastores.js";
|
|
9
9
|
import { createWebhook } from "../core/webhooks.js";
|
|
10
10
|
import { deriveJsonSchema } from "../sandbox/zod-params.js";
|
|
11
|
+
import { findSameNamedAttachedTool, reservedToolNameReason } from "../core/tool-names.js";
|
|
11
12
|
import { ToolCapabilitiesPatchSchema, FETCH_WILDCARD } from "../sandbox/tool-capabilities.js";
|
|
12
13
|
import { PostgresDatastore } from "../providers/datastore/postgres.js";
|
|
13
14
|
import { decryptTransferEnvelope } from "../providers/secrets/transfer-envelope.js";
|
|
14
15
|
import { mapBudget } from "./budgets.js";
|
|
16
|
+
import { EVERYONE_KEY, everyoneGrantData } from "../core/grants.js";
|
|
15
17
|
export async function createFromBundle(bundle, recon, opts) {
|
|
16
18
|
const { db, cipher, ownerId, secretMode, transferPrivateKey, allowOpenFetch } = opts;
|
|
19
|
+
const agentOwnerId = opts.agentOwnerId === undefined ? ownerId : opts.agentOwnerId;
|
|
17
20
|
const warnings = [];
|
|
18
21
|
const webhookSecrets = [];
|
|
19
22
|
const pendingSecretReentry = [];
|
|
@@ -37,28 +40,41 @@ export async function createFromBundle(bundle, recon, opts) {
|
|
|
37
40
|
for (const t of bundle.readTools()) {
|
|
38
41
|
if (toolRejected(t.name) || toolSkipped(t.name))
|
|
39
42
|
continue;
|
|
43
|
+
// A built-in dispatched before user tools would shadow it, so the tool
|
|
44
|
+
// could be created but never called (see core/tool-names.ts).
|
|
45
|
+
const reserved = reservedToolNameReason(eff(t.name));
|
|
46
|
+
if (reserved) {
|
|
47
|
+
warnings.push(`tool ${t.name}: skipped — ${reserved}`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
40
50
|
const schema = await deriveJsonSchema(t.paramsZod);
|
|
41
51
|
if (!schema.ok) {
|
|
42
52
|
warnings.push(`tool ${t.name}: failed to derive JSON schema, skipping`);
|
|
43
53
|
continue;
|
|
44
54
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
// Names are unique per owner: reuse the target owner's own same-named
|
|
56
|
+
// tool (what upsert-by-name used to do), never another owner's. A
|
|
57
|
+
// compound unique with a nullable column can't key an upsert, hence
|
|
58
|
+
// findFirst + create.
|
|
59
|
+
const tool = (await db.tool.findFirst({ where: { ownerId, name: eff(t.name) } })) ??
|
|
60
|
+
(await db.tool.create({
|
|
61
|
+
data: {
|
|
62
|
+
name: eff(t.name),
|
|
63
|
+
description: t.description,
|
|
64
|
+
paramsZod: t.paramsZod,
|
|
65
|
+
code: t.code,
|
|
66
|
+
jsonSchema: schema.value,
|
|
67
|
+
ownerId,
|
|
68
|
+
},
|
|
69
|
+
}));
|
|
57
70
|
toolIdMap.set(t.name, tool.id);
|
|
58
71
|
toolsCreated++;
|
|
59
72
|
}
|
|
60
73
|
// Step 2: Agents
|
|
61
74
|
const agentIdMap = new Map();
|
|
75
|
+
// Agents this import owns (created now, or already the import owner's):
|
|
76
|
+
// only their attachments are stamped with the owner's consent below.
|
|
77
|
+
const ownedAgentIds = new Set();
|
|
62
78
|
for (const a of bundle.readAgents()) {
|
|
63
79
|
if (agentSkipped(a.name))
|
|
64
80
|
continue;
|
|
@@ -74,11 +90,27 @@ export async function createFromBundle(bundle, recon, opts) {
|
|
|
74
90
|
timezone: a.timezone,
|
|
75
91
|
maxTurns: a.maxTurns,
|
|
76
92
|
scheduleEnabled,
|
|
77
|
-
ownerId,
|
|
93
|
+
ownerId: agentOwnerId,
|
|
78
94
|
},
|
|
79
95
|
update: {},
|
|
80
96
|
});
|
|
81
97
|
agentIdMap.set(a.name, agent.id);
|
|
98
|
+
if (agentOwnerId !== null && agent.ownerId === agentOwnerId) {
|
|
99
|
+
ownedAgentIds.add(agent.id);
|
|
100
|
+
if (opts.publicAgents) {
|
|
101
|
+
await db.resourceGrant.upsert({
|
|
102
|
+
where: {
|
|
103
|
+
resourceType_resourceId_granteeKey: {
|
|
104
|
+
resourceType: "agent",
|
|
105
|
+
resourceId: agent.id,
|
|
106
|
+
granteeKey: EVERYONE_KEY,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
create: everyoneGrantData("agent", agent.id, "execute", "import"),
|
|
110
|
+
update: {},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
82
114
|
agentsCreated++;
|
|
83
115
|
}
|
|
84
116
|
// Step 3: Attach tools
|
|
@@ -105,7 +137,26 @@ export async function createFromBundle(bundle, recon, opts) {
|
|
|
105
137
|
warnings.push(`agent-tool ${at.agentName}/${at.toolName}: invalid capabilities, skipping attachment`);
|
|
106
138
|
continue;
|
|
107
139
|
}
|
|
140
|
+
// Same guard as MCP attach_tool: an existing agent reused by name may
|
|
141
|
+
// already hold a different tool under this name (say a public one), and
|
|
142
|
+
// the runtime dispatches by name. Unlike attach_tool this check-then-
|
|
143
|
+
// upsert is not one Serializable transaction: the importer is an
|
|
144
|
+
// operator-only path, so a concurrent attach racing it is not defended
|
|
145
|
+
// against here (the runner's load-time duplicate check still is).
|
|
146
|
+
const clash = await findSameNamedAttachedTool(db, agentId, { id: toolId, name: eff(at.toolName) });
|
|
147
|
+
if (clash) {
|
|
148
|
+
warnings.push(`agent-tool ${at.agentName}/${at.toolName}: skipped — the agent already has a different tool with the same name (${clash.id})`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
108
151
|
const caps = capsPatch.data;
|
|
152
|
+
// The importing operator is trusted with the database, so on an agent
|
|
153
|
+
// this import owns it grants the bundle's capabilities in the owner's
|
|
154
|
+
// name (the runner honours them only with that stamp). An existing
|
|
155
|
+
// agent owned by someone else keeps an unstamped, inert attachment.
|
|
156
|
+
const consent = ownedAgentIds.has(agentId) ? agentOwnerId : null;
|
|
157
|
+
if (consent === null) {
|
|
158
|
+
warnings.push(`agent-tool ${at.agentName}/${at.toolName}: attached without capabilities in force — the agent belongs to another owner, who must re-grant them with attach_tool`);
|
|
159
|
+
}
|
|
109
160
|
await db.agentTool.upsert({
|
|
110
161
|
where: { agentId_toolId: { agentId, toolId } },
|
|
111
162
|
create: {
|
|
@@ -115,12 +166,15 @@ export async function createFromBundle(bundle, recon, opts) {
|
|
|
115
166
|
allowedDatastorePrefixes: caps.allowedDatastorePrefixes ?? [],
|
|
116
167
|
allowedHosts: caps.allowedHosts ?? [],
|
|
117
168
|
allowedSharedDatastorePrefixes: caps.allowedSharedDatastorePrefixes ?? {},
|
|
169
|
+
attachedById: agentOwnerId,
|
|
170
|
+
capabilitiesGrantedById: consent,
|
|
118
171
|
},
|
|
119
172
|
update: {
|
|
120
173
|
allowedSecrets: caps.allowedSecrets ?? [],
|
|
121
174
|
allowedDatastorePrefixes: caps.allowedDatastorePrefixes ?? [],
|
|
122
175
|
allowedHosts: caps.allowedHosts ?? [],
|
|
123
176
|
allowedSharedDatastorePrefixes: caps.allowedSharedDatastorePrefixes ?? {},
|
|
177
|
+
capabilitiesGrantedById: consent,
|
|
124
178
|
},
|
|
125
179
|
});
|
|
126
180
|
}
|
package/dist/import/index.js
CHANGED
|
@@ -10,19 +10,19 @@ import { supportedGlobalsFromPrelude } from "./tool-scan.js";
|
|
|
10
10
|
import { SANDBOX_PRELUDE } from "../sandbox/prelude.js";
|
|
11
11
|
import { resolveLlmRegistrations } from "../providers/llm/registration.js";
|
|
12
12
|
import { RoutingLlmProvider } from "../providers/llm/routing.js";
|
|
13
|
-
import { loadProviderConfig } from "../config/providers.js";
|
|
13
|
+
import { loadMcpConfig, loadProviderConfig } from "../config/providers.js";
|
|
14
14
|
import { buildSecretCipher } from "../providers/secrets/index.js";
|
|
15
15
|
import { resolvePrincipal } from "../mcp/auth/principal.js";
|
|
16
16
|
import { loadTransferPrivateKey, transferKeyIdOf } from "../providers/secrets/transfer-envelope.js";
|
|
17
17
|
import { readFileSync } from "node:fs";
|
|
18
18
|
export async function runImport(opts) {
|
|
19
19
|
const env = opts.env ?? process.env;
|
|
20
|
-
// Guard: owner
|
|
20
|
+
// Guard: --owner or --public (or both). --public no longer means
|
|
21
|
+
// owner-less: the imported agents are owned by --owner, or by the
|
|
22
|
+
// importing operator (LOCAL_PRINCIPAL), and shared with everyone at
|
|
23
|
+
// execute (resource-sharing grants spec §3.8).
|
|
21
24
|
if (opts.owner === null && !opts.isPublic) {
|
|
22
|
-
throw new Error("Must specify
|
|
23
|
-
}
|
|
24
|
-
if (opts.owner !== null && opts.isPublic) {
|
|
25
|
-
throw new Error("Cannot specify both --owner and --public");
|
|
25
|
+
throw new Error("Must specify --owner, --public, or both");
|
|
26
26
|
}
|
|
27
27
|
// Open bundle
|
|
28
28
|
const bundle = openBundle(opts.dir);
|
|
@@ -36,10 +36,13 @@ export async function runImport(opts) {
|
|
|
36
36
|
// Load existing names from db
|
|
37
37
|
const existingAgents = await opts.db.agent.findMany({ select: { name: true } });
|
|
38
38
|
const existingAgentNames = new Set(existingAgents.map((a) => a.name));
|
|
39
|
-
|
|
40
|
-
const existingToolNames = new Set(existingTools.map((t) => t.name));
|
|
41
|
-
// For owner-scoped entities (secrets, budgets), load only if we have an owner
|
|
39
|
+
// For owner-scoped entities (tools, secrets, budgets), load only if we have an owner
|
|
42
40
|
const ownerId = opts.owner !== null && !opts.isPublic ? (await resolvePrincipal(opts.owner, opts.db)).id : null;
|
|
41
|
+
// Tool names are unique per owner (null = the public namespace), so only
|
|
42
|
+
// the target owner's tools can collide; another owner's same-named tool
|
|
43
|
+
// is no conflict.
|
|
44
|
+
const existingTools = await opts.db.tool.findMany({ where: { ownerId }, select: { name: true } });
|
|
45
|
+
const existingToolNames = new Set(existingTools.map((t) => t.name));
|
|
43
46
|
// Tier-1 capabilities: "budgets" and "shared-datastores" are implemented
|
|
44
47
|
const capabilitiesSupported = new Set(["budgets", "shared-datastores"]);
|
|
45
48
|
// Run preflight reconciliation
|
|
@@ -84,11 +87,18 @@ export async function runImport(opts) {
|
|
|
84
87
|
// Build secret cipher
|
|
85
88
|
const providerConfig = loadProviderConfig(env);
|
|
86
89
|
const cipher = buildSecretCipher(providerConfig, env);
|
|
90
|
+
// The imported agents' owner: --owner, or in --public mode the importing
|
|
91
|
+
// operator. Resolved only for a real import (never on --dry-run).
|
|
92
|
+
const agentOwnerId = opts.isPublic
|
|
93
|
+
? (await resolvePrincipal(opts.owner ?? loadMcpConfig(env).localPrincipal, opts.db)).id
|
|
94
|
+
: ownerId;
|
|
87
95
|
// Run create
|
|
88
96
|
const result = await createFromBundle(bundle, recon, {
|
|
89
97
|
db: opts.db,
|
|
90
98
|
cipher,
|
|
91
99
|
ownerId,
|
|
100
|
+
agentOwnerId,
|
|
101
|
+
publicAgents: opts.isPublic,
|
|
92
102
|
defaultBudget: opts.defaultBudget ?? "10.00",
|
|
93
103
|
secretMode: effectiveSecretMode,
|
|
94
104
|
transferPrivateKey,
|
|
@@ -46,13 +46,13 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
46
46
|
capabilities: z.ZodArray<z.ZodString, "many">;
|
|
47
47
|
counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
48
48
|
}, "strip", z.ZodTypeAny, {
|
|
49
|
-
capabilities: string[];
|
|
50
|
-
bundleVersion: number;
|
|
51
49
|
source: {
|
|
52
50
|
product: string;
|
|
53
51
|
exporterVersion: string;
|
|
54
52
|
exportedAt: string;
|
|
55
53
|
};
|
|
54
|
+
capabilities: string[];
|
|
55
|
+
bundleVersion: number;
|
|
56
56
|
secretMode: "references" | "envelope";
|
|
57
57
|
transferKeyId: string | null;
|
|
58
58
|
contentWindowDays: number | null;
|
|
@@ -62,13 +62,13 @@ export declare const ManifestSchema: z.ZodObject<{
|
|
|
62
62
|
runAuditSince: string | null;
|
|
63
63
|
counts: Record<string, number>;
|
|
64
64
|
}, {
|
|
65
|
-
capabilities: string[];
|
|
66
|
-
bundleVersion: number;
|
|
67
65
|
source: {
|
|
68
66
|
product: string;
|
|
69
67
|
exporterVersion: string;
|
|
70
68
|
exportedAt: string;
|
|
71
69
|
};
|
|
70
|
+
capabilities: string[];
|
|
71
|
+
bundleVersion: number;
|
|
72
72
|
secretMode: "references" | "envelope";
|
|
73
73
|
counts: Record<string, number>;
|
|
74
74
|
transferKeyId?: string | null | undefined;
|
|
@@ -98,41 +98,41 @@ export declare const NeutralAgentSchema: z.ZodObject<{
|
|
|
98
98
|
slug: z.ZodOptional<z.ZodDefault<z.ZodNullable<z.ZodString>>>;
|
|
99
99
|
emailAllowlist: z.ZodOptional<z.ZodDefault<z.ZodNullable<z.ZodUnknown>>>;
|
|
100
100
|
}, "strip", z.ZodTypeAny, {
|
|
101
|
-
description?: string | null | undefined;
|
|
102
101
|
slug?: string | null | undefined;
|
|
102
|
+
description?: string | null | undefined;
|
|
103
103
|
emailAllowlist?: unknown;
|
|
104
104
|
}, {
|
|
105
|
-
description?: string | null | undefined;
|
|
106
105
|
slug?: string | null | undefined;
|
|
106
|
+
description?: string | null | undefined;
|
|
107
107
|
emailAllowlist?: unknown;
|
|
108
108
|
}>>;
|
|
109
109
|
}, "strip", z.ZodTypeAny, {
|
|
110
110
|
name: string;
|
|
111
111
|
model: string;
|
|
112
112
|
budgetUsd: string;
|
|
113
|
-
systemPrompt: string;
|
|
114
113
|
kind: "native";
|
|
114
|
+
provider: "openai" | "bedrock";
|
|
115
|
+
systemPrompt: string;
|
|
115
116
|
schedule: string | null;
|
|
116
117
|
timezone: string;
|
|
117
118
|
scheduleEnabled: boolean;
|
|
118
119
|
maxTurns: number;
|
|
119
120
|
memoryEnabled: boolean;
|
|
120
|
-
provider: "openai" | "bedrock";
|
|
121
121
|
region: string | null;
|
|
122
122
|
ownerEmail: string | null;
|
|
123
123
|
unmodeled: {
|
|
124
|
-
description?: string | null | undefined;
|
|
125
124
|
slug?: string | null | undefined;
|
|
125
|
+
description?: string | null | undefined;
|
|
126
126
|
emailAllowlist?: unknown;
|
|
127
127
|
};
|
|
128
128
|
}, {
|
|
129
129
|
name: string;
|
|
130
130
|
model: string;
|
|
131
131
|
budgetUsd: string;
|
|
132
|
+
provider: "openai" | "bedrock";
|
|
132
133
|
systemPrompt: string;
|
|
133
134
|
scheduleEnabled: boolean;
|
|
134
135
|
maxTurns: number;
|
|
135
|
-
provider: "openai" | "bedrock";
|
|
136
136
|
kind?: "native" | undefined;
|
|
137
137
|
schedule?: string | null | undefined;
|
|
138
138
|
timezone?: string | undefined;
|
|
@@ -140,8 +140,8 @@ export declare const NeutralAgentSchema: z.ZodObject<{
|
|
|
140
140
|
region?: string | null | undefined;
|
|
141
141
|
ownerEmail?: string | null | undefined;
|
|
142
142
|
unmodeled?: {
|
|
143
|
-
description?: string | null | undefined;
|
|
144
143
|
slug?: string | null | undefined;
|
|
144
|
+
description?: string | null | undefined;
|
|
145
145
|
emailAllowlist?: unknown;
|
|
146
146
|
} | undefined;
|
|
147
147
|
}>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MCP seam for agent access (resource-sharing grants spec §3.3). Every
|
|
3
|
+
* agent tool routes through here instead of ownership.ts's owner-or-public
|
|
4
|
+
* rule, which no longer applies to agents: an owner-less agent is reachable
|
|
5
|
+
* only through its grants (the migration gives everyone execute).
|
|
6
|
+
*
|
|
7
|
+
* - Below read: 404 with the same text as a missing row, so existence never
|
|
8
|
+
* leaks. At read or above but below the level required: 403 naming both.
|
|
9
|
+
* - The helpers take a `db` argument so a Serializable transaction reads the
|
|
10
|
+
* grant rows through `tx`; a concurrent revoke then conflicts instead of
|
|
11
|
+
* racing.
|
|
12
|
+
* - `ctx.operator` (stdio's local operator, never an HTTP principal) is
|
|
13
|
+
* owner of every agent for access checks and sees every agent in
|
|
14
|
+
* listings, but does NOT bypass requireBindingOwner: one owner's secrets,
|
|
15
|
+
* datastores and repositories never reach another owner's agent.
|
|
16
|
+
*/
|
|
17
|
+
import type { Prisma, PrismaClient } from "#prisma";
|
|
18
|
+
import { type Access, type Level } from "../../core/grants.js";
|
|
19
|
+
import type { McpRequestContext } from "../context.js";
|
|
20
|
+
import { McpError } from "../errors.js";
|
|
21
|
+
export type AgentLevel = Level<"agent">;
|
|
22
|
+
export type AgentAccess = Access<"agent">;
|
|
23
|
+
type AgentRef = {
|
|
24
|
+
id: string;
|
|
25
|
+
ownerId: string | null;
|
|
26
|
+
};
|
|
27
|
+
type GrantDb = Pick<PrismaClient, "resourceGrant">;
|
|
28
|
+
export declare function agentNotFound(id: string): McpError;
|
|
29
|
+
export declare function insufficientAgentAccess(id: string, required: AgentLevel | "owner", held: AgentAccess): McpError;
|
|
30
|
+
/** The caller's access to an agent row already read. */
|
|
31
|
+
export declare function agentAccess(ctx: McpRequestContext, agent: AgentRef, db?: GrantDb): Promise<AgentAccess>;
|
|
32
|
+
/** For a row already read (inside a transaction, or with includes): 404 below read, 403 below `required`. */
|
|
33
|
+
export declare function assertAgentAccess<A extends AgentRef>(ctx: McpRequestContext, agent: A | null, id: string, required: AgentLevel | "owner", db?: GrantDb): Promise<{
|
|
34
|
+
agent: A;
|
|
35
|
+
access: AgentAccess;
|
|
36
|
+
}>;
|
|
37
|
+
/** 404 if missing or access < read; 403 if read <= access < required. Returns row + access. */
|
|
38
|
+
export declare function requireAgentAccess(ctx: McpRequestContext, id: string, required: AgentLevel | "owner", db?: Pick<PrismaClient, "agent" | "resourceGrant">): Promise<{
|
|
39
|
+
agent: {
|
|
40
|
+
name: string;
|
|
41
|
+
model: string;
|
|
42
|
+
budgetUsd: import("@prisma/client-runtime-utils").Decimal;
|
|
43
|
+
kind: import("#prisma").AgentKind;
|
|
44
|
+
id: string;
|
|
45
|
+
ownerId: string | null;
|
|
46
|
+
createdAt: Date;
|
|
47
|
+
updatedAt: Date;
|
|
48
|
+
systemPrompt: string;
|
|
49
|
+
schedule: string | null;
|
|
50
|
+
timezone: string;
|
|
51
|
+
scheduleEnabled: boolean;
|
|
52
|
+
lastScheduledAt: Date | null;
|
|
53
|
+
maxTurns: number;
|
|
54
|
+
budgetGroupId: string | null;
|
|
55
|
+
memoryEnabled: boolean;
|
|
56
|
+
effort: string | null;
|
|
57
|
+
};
|
|
58
|
+
access: AgentAccess;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Bindings (secrets, datastores, repositories, capability grants): strict
|
|
62
|
+
* ownership, whatever the grants. The stdio operator does NOT bypass this:
|
|
63
|
+
* it can adopt the agent first (make_owner / grants adopt-public).
|
|
64
|
+
*/
|
|
65
|
+
export declare function requireBindingOwner(ctx: McpRequestContext, agent: AgentRef): void;
|
|
66
|
+
/** Prisma where for agent listings: own rows plus rows granted >= read; the operator sees all. */
|
|
67
|
+
export declare function readableAgentsWhere(ctx: McpRequestContext, db?: GrantDb): Promise<Prisma.AgentWhereInput>;
|
|
68
|
+
/** One grant lookup for a whole listing: returns agent -> the caller's access. */
|
|
69
|
+
export declare function agentAccessResolver(ctx: McpRequestContext, db?: GrantDb): Promise<(agent: AgentRef) => AgentAccess>;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { atLeast, effectiveAccess, grantedAccessMap, grantedIds } from "../../core/grants.js";
|
|
2
|
+
import { McpError } from "../errors.js";
|
|
3
|
+
export function agentNotFound(id) {
|
|
4
|
+
return new McpError(404, `Agent "${id}" not found.`);
|
|
5
|
+
}
|
|
6
|
+
function describeLevel(level) {
|
|
7
|
+
return level === "owner" ? "the agent's owner" : `${level} access`;
|
|
8
|
+
}
|
|
9
|
+
export function insufficientAgentAccess(id, required, held) {
|
|
10
|
+
return new McpError(403, `Agent "${id}": this needs ${describeLevel(required)}; you have ${held === "owner" ? "owner" : held} access.`);
|
|
11
|
+
}
|
|
12
|
+
/** The caller's access to an agent row already read. */
|
|
13
|
+
export function agentAccess(ctx, agent, db = ctx.db) {
|
|
14
|
+
return effectiveAccess(db, "agent", agent, ctx.principal.id, { operator: ctx.operator === true });
|
|
15
|
+
}
|
|
16
|
+
/** For a row already read (inside a transaction, or with includes): 404 below read, 403 below `required`. */
|
|
17
|
+
export async function assertAgentAccess(ctx, agent, id, required, db = ctx.db) {
|
|
18
|
+
if (!agent)
|
|
19
|
+
throw agentNotFound(id);
|
|
20
|
+
const access = await agentAccess(ctx, agent, db);
|
|
21
|
+
if (!atLeast("agent", access, "read"))
|
|
22
|
+
throw agentNotFound(id);
|
|
23
|
+
if (!atLeast("agent", access, required))
|
|
24
|
+
throw insufficientAgentAccess(id, required, access);
|
|
25
|
+
return { agent, access };
|
|
26
|
+
}
|
|
27
|
+
/** 404 if missing or access < read; 403 if read <= access < required. Returns row + access. */
|
|
28
|
+
export async function requireAgentAccess(ctx, id, required, db = ctx.db) {
|
|
29
|
+
const agent = await db.agent.findUnique({ where: { id } });
|
|
30
|
+
return assertAgentAccess(ctx, agent, id, required, db);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Bindings (secrets, datastores, repositories, capability grants): strict
|
|
34
|
+
* ownership, whatever the grants. The stdio operator does NOT bypass this:
|
|
35
|
+
* it can adopt the agent first (make_owner / grants adopt-public).
|
|
36
|
+
*/
|
|
37
|
+
export function requireBindingOwner(ctx, agent) {
|
|
38
|
+
if (agent.ownerId === null) {
|
|
39
|
+
throw new McpError(403, `Agent "${agent.id}" has no owner, so nothing can be bound to it; an admin can assign one with make_owner.`);
|
|
40
|
+
}
|
|
41
|
+
if (agent.ownerId !== ctx.principal.id) {
|
|
42
|
+
throw new McpError(403, `Only the owner of agent "${agent.id}" can change its bindings.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Prisma where for agent listings: own rows plus rows granted >= read; the operator sees all. */
|
|
46
|
+
export async function readableAgentsWhere(ctx, db = ctx.db) {
|
|
47
|
+
if (ctx.operator)
|
|
48
|
+
return {};
|
|
49
|
+
const ids = await grantedIds(db, "agent", ctx.principal.id, "read");
|
|
50
|
+
return { OR: [{ ownerId: ctx.principal.id }, { id: { in: ids } }] };
|
|
51
|
+
}
|
|
52
|
+
/** One grant lookup for a whole listing: returns agent -> the caller's access. */
|
|
53
|
+
export async function agentAccessResolver(ctx, db = ctx.db) {
|
|
54
|
+
if (ctx.operator)
|
|
55
|
+
return () => "owner";
|
|
56
|
+
const granted = await grantedAccessMap(db, "agent", ctx.principal.id);
|
|
57
|
+
return (agent) => agent.ownerId !== null && agent.ownerId === ctx.principal.id ? "owner" : (granted.get(agent.id) ?? "none");
|
|
58
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { type PrismaClient } from "#prisma";
|
|
2
|
+
/** The report needs only raw queries, so it can run on a schema the generated client doesn't match. */
|
|
3
|
+
export interface ReportDb {
|
|
4
|
+
$queryRaw<T = unknown>(query: TemplateStringsArray, ...values: unknown[]): PromiseLike<T>;
|
|
5
|
+
}
|
|
6
|
+
export declare const BEHAVIOUR_CHANGES: string[];
|
|
7
|
+
export interface MigrationReport {
|
|
8
|
+
grantsTable: boolean;
|
|
9
|
+
ownerlessAgents: {
|
|
10
|
+
agentId: string;
|
|
11
|
+
name: string;
|
|
12
|
+
everyoneGrant: string | null;
|
|
13
|
+
/** What adopting the agent as each principal would bring back into force (review I3). */
|
|
14
|
+
revivedByAdopter: {
|
|
15
|
+
principalId: string;
|
|
16
|
+
subject: string;
|
|
17
|
+
secrets: string[];
|
|
18
|
+
datastores: string[];
|
|
19
|
+
toolCapabilities: string[];
|
|
20
|
+
}[];
|
|
21
|
+
}[];
|
|
22
|
+
inertBindings: {
|
|
23
|
+
kind: "secret" | "datastore";
|
|
24
|
+
agentId: string;
|
|
25
|
+
agentName: string;
|
|
26
|
+
agentOwnerId: string | null;
|
|
27
|
+
boundName: string;
|
|
28
|
+
resourceId: string;
|
|
29
|
+
resourceOwnerId: string | null;
|
|
30
|
+
/** Removed by prune-bindings (owned agent); on an owner-less agent adopt-public decides. */
|
|
31
|
+
prunable: boolean;
|
|
32
|
+
}[];
|
|
33
|
+
suspendedCapabilities: {
|
|
34
|
+
agentId: string;
|
|
35
|
+
agentName: string;
|
|
36
|
+
toolId: string;
|
|
37
|
+
toolName: string;
|
|
38
|
+
regrant: string;
|
|
39
|
+
}[];
|
|
40
|
+
/**
|
|
41
|
+
* Capabilities the migration stamps with the current owner on owner-less
|
|
42
|
+
* tools: a previous owner may have set them before a make_owner (review
|
|
43
|
+
* M2). They stay in force; the owner should review them.
|
|
44
|
+
*/
|
|
45
|
+
reviewCapabilities: {
|
|
46
|
+
agentId: string;
|
|
47
|
+
agentName: string;
|
|
48
|
+
toolId: string;
|
|
49
|
+
toolName: string;
|
|
50
|
+
regrant: string;
|
|
51
|
+
}[];
|
|
52
|
+
failingEdges: {
|
|
53
|
+
parentAgentId: string;
|
|
54
|
+
parentOwnerId: string | null;
|
|
55
|
+
childAgentId: string;
|
|
56
|
+
childOwnerId: string | null;
|
|
57
|
+
boundName: string;
|
|
58
|
+
}[];
|
|
59
|
+
webhooks: {
|
|
60
|
+
onOwnerlessAgents: {
|
|
61
|
+
id: string;
|
|
62
|
+
agentId: string;
|
|
63
|
+
createdBy: string | null;
|
|
64
|
+
}[];
|
|
65
|
+
creatorLacksExecute: {
|
|
66
|
+
id: string;
|
|
67
|
+
agentId: string;
|
|
68
|
+
createdBy: string | null;
|
|
69
|
+
}[];
|
|
70
|
+
};
|
|
71
|
+
behaviourChanges: string[];
|
|
72
|
+
orphanGrants: {
|
|
73
|
+
id: string;
|
|
74
|
+
resourceType: string;
|
|
75
|
+
resourceId: string;
|
|
76
|
+
}[] | null;
|
|
77
|
+
}
|
|
78
|
+
export declare function migrationReport(db: ReportDb): Promise<MigrationReport>;
|
|
79
|
+
export declare function formatMigrationReport(report: MigrationReport): string;
|
|
80
|
+
export interface AdoptedAgent {
|
|
81
|
+
agentId: string;
|
|
82
|
+
name: string;
|
|
83
|
+
bindingsRemoved: {
|
|
84
|
+
kind: "secret" | "datastore";
|
|
85
|
+
boundName: string;
|
|
86
|
+
resourceId: string;
|
|
87
|
+
}[];
|
|
88
|
+
bindingsKept: {
|
|
89
|
+
kind: "secret" | "datastore";
|
|
90
|
+
boundName: string;
|
|
91
|
+
}[];
|
|
92
|
+
capabilitiesStamped: string[];
|
|
93
|
+
/** Every attached tool the new owner doesn't own (review M7); `regrant` only when it had capabilities. */
|
|
94
|
+
foreignTools: {
|
|
95
|
+
toolId: string;
|
|
96
|
+
toolName: string;
|
|
97
|
+
toolOwnerId: string | null;
|
|
98
|
+
regrant: string | null;
|
|
99
|
+
}[];
|
|
100
|
+
failingEdges: {
|
|
101
|
+
parentAgentId: string;
|
|
102
|
+
childAgentId: string;
|
|
103
|
+
boundName: string;
|
|
104
|
+
}[];
|
|
105
|
+
/** The everyone grant before and after adoption (null = none). */
|
|
106
|
+
everyoneGrant: {
|
|
107
|
+
before: string | null;
|
|
108
|
+
after: string | null;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export interface AdoptResult {
|
|
112
|
+
owner: {
|
|
113
|
+
id: string;
|
|
114
|
+
subject: string;
|
|
115
|
+
};
|
|
116
|
+
dryRun: boolean;
|
|
117
|
+
agents: AdoptedAgent[];
|
|
118
|
+
}
|
|
119
|
+
/** Gives every owner-less agent `ownerSubject` as its owner. See the module header. */
|
|
120
|
+
export declare function adoptPublic(db: PrismaClient, opts: {
|
|
121
|
+
ownerSubject: string;
|
|
122
|
+
dryRun: boolean;
|
|
123
|
+
keepEveryoneExecute?: boolean;
|
|
124
|
+
}): Promise<AdoptResult>;
|
|
125
|
+
export declare function formatAdoptResult(result: AdoptResult): string;
|
|
126
|
+
export interface PruneResult {
|
|
127
|
+
dryRun: boolean;
|
|
128
|
+
removed: {
|
|
129
|
+
kind: "secret" | "datastore";
|
|
130
|
+
agentId: string;
|
|
131
|
+
agentName: string;
|
|
132
|
+
boundName: string;
|
|
133
|
+
resourceId: string;
|
|
134
|
+
resourceOwnerId: string | null;
|
|
135
|
+
}[];
|
|
136
|
+
}
|
|
137
|
+
/** Deletes cross-owner secret/datastore bindings on owned agents, in one transaction. */
|
|
138
|
+
export declare function pruneBindings(db: PrismaClient, opts: {
|
|
139
|
+
dryRun: boolean;
|
|
140
|
+
}): Promise<PruneResult>;
|
|
141
|
+
export declare function formatPruneResult(result: PruneResult): string;
|
|
142
|
+
/**
|
|
143
|
+
* The owner of an agent made with `wardby agent create` (resource-sharing
|
|
144
|
+
* grants spec §3.8): `--owner <subject>` must already exist (a typo never
|
|
145
|
+
* mints a principal), otherwise the local operator (LOCAL_PRINCIPAL),
|
|
146
|
+
* found or created exactly as stdio does.
|
|
147
|
+
*/
|
|
148
|
+
export declare function resolveCliAgentOwner(db: PrismaClient, ownerSubject: string | undefined, localPrincipal: string): Promise<string>;
|
|
149
|
+
export declare function grantsCommand(args: string[], db: PrismaClient, output?: (value: string) => void): Promise<void>;
|