@wardby/cli 0.2.0 → 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 +183 -71
- package/dist/claude-coding-worker/driver.d.ts +7 -1
- package/dist/claude-coding-worker/driver.js +31 -2
- package/dist/claude-coding-worker/main.js +5 -2
- 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 +99 -3
- package/dist/coding/protocol.js +155 -4
- 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 +18 -0
- package/dist/coding-worker/artifact.js +48 -6
- 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 +14 -1
- package/dist/coding-worker/driver.js +106 -14
- package/dist/coding-worker/errors.d.ts +7 -0
- package/dist/coding-worker/errors.js +26 -0
- package/dist/coding-worker/main.js +13 -4
- 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 +109 -6
- 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/coding-queue.d.ts +1 -1
- package/dist/core/datastores.d.ts +1 -1
- package/dist/core/datastores.js +18 -2
- package/dist/core/db.d.ts +40 -2
- package/dist/core/db.js +75 -2
- package/dist/core/dispatch.d.ts +49 -7
- package/dist/core/dispatch.js +290 -45
- 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/http-runtime.js +3 -4
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/lease.d.ts +1 -1
- package/dist/core/private-directory.d.ts +20 -0
- package/dist/core/private-directory.js +36 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +39 -3
- 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 +31 -9
- package/dist/core/runner.js +237 -40
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/secrets.d.ts +12 -3
- package/dist/core/secrets.js +25 -6
- package/dist/core/subagent-memory-tools.d.ts +2 -2
- 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 +9 -2
- package/dist/core/webhooks.js +23 -2
- package/dist/generated/prisma/browser.d.ts +328 -0
- package/dist/generated/prisma/browser.js +17 -0
- package/dist/generated/prisma/client.d.ts +347 -0
- package/dist/generated/prisma/client.js +34 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +839 -0
- package/dist/generated/prisma/commonInputTypes.js +10 -0
- package/dist/generated/prisma/enums.d.ts +59 -0
- package/dist/generated/prisma/enums.js +59 -0
- package/dist/generated/prisma/internal/class.d.ts +605 -0
- package/dist/generated/prisma/internal/class.js +49 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +4494 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +628 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +635 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +599 -0
- package/dist/generated/prisma/models/Agent.d.ts +3560 -0
- package/dist/generated/prisma/models/Agent.js +1 -0
- package/dist/generated/prisma/models/AgentDatastore.d.ts +1210 -0
- package/dist/generated/prisma/models/AgentDatastore.js +1 -0
- package/dist/generated/prisma/models/AgentMemory.d.ts +986 -0
- package/dist/generated/prisma/models/AgentMemory.js +1 -0
- package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
- package/dist/generated/prisma/models/AgentRepository.js +1 -0
- package/dist/generated/prisma/models/AgentSecret.d.ts +1212 -0
- package/dist/generated/prisma/models/AgentSecret.js +1 -0
- package/dist/generated/prisma/models/AgentSubAgent.d.ts +1217 -0
- package/dist/generated/prisma/models/AgentSubAgent.js +1 -0
- package/dist/generated/prisma/models/AgentTool.d.ts +1403 -0
- package/dist/generated/prisma/models/AgentTool.js +1 -0
- package/dist/generated/prisma/models/AuthFormChallenge.d.ts +1298 -0
- package/dist/generated/prisma/models/AuthFormChallenge.js +1 -0
- package/dist/generated/prisma/models/AuthLoginKey.d.ts +1245 -0
- package/dist/generated/prisma/models/AuthLoginKey.js +1 -0
- package/dist/generated/prisma/models/AuthRateLimit.d.ts +979 -0
- package/dist/generated/prisma/models/AuthRateLimit.js +1 -0
- package/dist/generated/prisma/models/AuthSession.d.ts +1376 -0
- package/dist/generated/prisma/models/AuthSession.js +1 -0
- package/dist/generated/prisma/models/AuthUser.d.ts +1700 -0
- package/dist/generated/prisma/models/AuthUser.js +1 -0
- package/dist/generated/prisma/models/BudgetGroup.d.ts +1548 -0
- package/dist/generated/prisma/models/BudgetGroup.js +1 -0
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +1681 -0
- package/dist/generated/prisma/models/CodingAgentProfile.js +1 -0
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +1749 -0
- package/dist/generated/prisma/models/CodingProxyRequest.js +1 -0
- package/dist/generated/prisma/models/CodingProxySession.d.ts +1626 -0
- package/dist/generated/prisma/models/CodingProxySession.js +1 -0
- package/dist/generated/prisma/models/CodingRun.d.ts +3583 -0
- package/dist/generated/prisma/models/CodingRun.js +1 -0
- package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
- package/dist/generated/prisma/models/CodingService.js +1 -0
- package/dist/generated/prisma/models/Datastore.d.ts +1434 -0
- package/dist/generated/prisma/models/Datastore.js +1 -0
- package/dist/generated/prisma/models/DatastoreEntry.d.ts +1314 -0
- package/dist/generated/prisma/models/DatastoreEntry.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/OAuthAuthorizationCode.d.ts +1526 -0
- package/dist/generated/prisma/models/OAuthAuthorizationCode.js +1 -0
- package/dist/generated/prisma/models/OAuthAuthorizationRequest.d.ts +1350 -0
- package/dist/generated/prisma/models/OAuthAuthorizationRequest.js +1 -0
- package/dist/generated/prisma/models/OAuthClient.d.ts +1289 -0
- package/dist/generated/prisma/models/OAuthClient.js +1 -0
- package/dist/generated/prisma/models/OAuthFamily.d.ts +1540 -0
- package/dist/generated/prisma/models/OAuthFamily.js +1 -0
- package/dist/generated/prisma/models/OAuthGrant.d.ts +1280 -0
- package/dist/generated/prisma/models/OAuthGrant.js +1 -0
- package/dist/generated/prisma/models/Principal.d.ts +2245 -0
- package/dist/generated/prisma/models/Principal.js +1 -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 +2669 -0
- package/dist/generated/prisma/models/Run.js +1 -0
- 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/SchedulerLease.d.ts +970 -0
- package/dist/generated/prisma/models/SchedulerLease.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +1399 -0
- package/dist/generated/prisma/models/Secret.js +1 -0
- package/dist/generated/prisma/models/SecretElicitationOutcome.d.ts +973 -0
- package/dist/generated/prisma/models/SecretElicitationOutcome.js +1 -0
- package/dist/generated/prisma/models/Task.d.ts +1176 -0
- package/dist/generated/prisma/models/Task.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +1490 -0
- package/dist/generated/prisma/models/Tool.js +1 -0
- package/dist/generated/prisma/models/Webhook.d.ts +1386 -0
- package/dist/generated/prisma/models/Webhook.js +1 -0
- package/dist/generated/prisma/models.d.ts +45 -0
- package/dist/generated/prisma/models.js +1 -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 +6 -1
- package/dist/import/create.js +68 -14
- package/dist/import/index.d.ts +1 -1
- 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 +37 -63
- package/dist/mcp/auth/ownership.js +19 -14
- package/dist/mcp/auth/principal.d.ts +1 -1
- 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 +32 -3
- package/dist/mcp/auth/resource-server.js +84 -3
- package/dist/mcp/auth/self-hosted/browser.js +22 -8
- package/dist/mcp/auth/self-hosted/cli.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/cli.js +47 -13
- package/dist/mcp/auth/self-hosted/credentials.d.ts +21 -3
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/rate-limit.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/session.d.ts +3 -2
- package/dist/mcp/context.d.ts +28 -2
- 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.d.ts +1 -1
- package/dist/mcp/server.js +27 -9
- package/dist/mcp/shared/page-style.d.ts +16 -0
- package/dist/mcp/shared/page-style.js +129 -0
- package/dist/mcp/tasks/manager.d.ts +1 -1
- package/dist/mcp/tools/agents.js +447 -49
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/datastore.js +23 -16
- 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 +4 -7
- package/dist/mcp/tools/secret-elicitation-form.d.ts +1 -1
- package/dist/mcp/tools/secret-elicitation-form.js +10 -28
- package/dist/mcp/tools/secret-elicitation.d.ts +1 -1
- 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 +53 -17
- package/dist/mcp/tools/tools.d.ts +41 -0
- package/dist/mcp/tools/tools.js +202 -41
- package/dist/mcp/tools/trigger.js +36 -6
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +11 -1
- package/dist/mcp/transport/streamable-http.js +32 -2
- package/dist/mcp/unattended-schedules.d.ts +1 -1
- package/dist/mcp/webhooks/ingress.d.ts +1 -1
- package/dist/providers/auth/delegating.d.ts +19 -0
- package/dist/providers/auth/delegating.js +71 -0
- package/dist/providers/auth/index.d.ts +3 -1
- package/dist/providers/auth/index.js +11 -0
- package/dist/providers/auth/self-hosted.d.ts +4 -3
- 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 +18 -1
- 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 +18 -1
- 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/datastore/postgres.d.ts +1 -1
- package/dist/providers/engine/types.d.ts +10 -0
- package/dist/providers/executor/build.d.ts +3 -3
- package/dist/providers/executor/composition.d.ts +4 -1
- package/dist/providers/executor/composition.js +19 -0
- package/dist/providers/executor/container.d.ts +106 -4
- package/dist/providers/executor/container.js +305 -22
- package/dist/providers/executor/dbos.d.ts +3 -4
- 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 +60 -2
- package/dist/providers/jobs/docker.js +313 -50
- 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 +117 -31
- package/dist/providers/jobs/types.d.ts +20 -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/memory/postgres.d.ts +1 -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 +79 -14
- 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 +34 -32
- package/dist/quickstart/migrate.d.ts +23 -0
- package/dist/quickstart/migrate.js +125 -0
- 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 +30 -11
- package/prisma/migrate.config.mjs +20 -0
- 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 +417 -23
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# Services for coding runs
|
|
2
|
+
|
|
3
|
+
A coding run can have the services its project's tests need — a PostgreSQL
|
|
4
|
+
database, a Redis cache — next to it for the length of the run. The repository
|
|
5
|
+
says which services it needs; wardby's service catalog says what each one is;
|
|
6
|
+
the agent's owner says which ones the agent may use. Every run gets its own
|
|
7
|
+
fresh, empty instance, and the run's sandbox and network policy do not change.
|
|
8
|
+
|
|
9
|
+
Services work on the Kubernetes job launcher (`JOB_LAUNCHER=kubernetes`,
|
|
10
|
+
running Kubernetes 1.29 or later, which its native sidecars need) and on the
|
|
11
|
+
Docker job launcher (`JOB_LAUNCHER=docker`), for Codex and Claude Code agents
|
|
12
|
+
on both; see [coding-worker-isolation.md](coding-worker-isolation.md). A run
|
|
13
|
+
whose agent allows at least one service is refused if its repository declares
|
|
14
|
+
one and the deployment can't start services (for example
|
|
15
|
+
`JOB_LAUNCHER=local`) — an agent that allows none never reads the declaration
|
|
16
|
+
in the first place (see "Allowing services for an agent" below), so its runs
|
|
17
|
+
are unaffected by this and start normally on any launcher.
|
|
18
|
+
|
|
19
|
+
## How it works
|
|
20
|
+
|
|
21
|
+
1. The repository declares its services in `.wardby/services.yaml` on its base
|
|
22
|
+
branch.
|
|
23
|
+
2. When a coding run is dispatched, wardby reads that file from the run's base
|
|
24
|
+
branch through the GitHub App (never from the run's own branch), checks each
|
|
25
|
+
entry against the service catalog and the agent's allowed services, and
|
|
26
|
+
either refuses the run or records the resolved services on it.
|
|
27
|
+
3. The run starts each service before anything else in the run. On
|
|
28
|
+
Kubernetes each is a native sidecar in the run's pod (an init container
|
|
29
|
+
with `restartPolicy: Always`, which needs Kubernetes 1.29 or later). On
|
|
30
|
+
Docker each is its own container sharing the run's network namespace. The
|
|
31
|
+
coding agent does not start until every service reports ready.
|
|
32
|
+
4. The agent's shells receive each service's variables (such as
|
|
33
|
+
`DATABASE_URL`), and its instructions gain a short note listing the services,
|
|
34
|
+
their variables, and that they start empty. Claude Code runs work the same
|
|
35
|
+
way on both launchers: its tool runner, which actually runs shell commands
|
|
36
|
+
in the repository, reaches every service on `127.0.0.1` with the same
|
|
37
|
+
variables. On Kubernetes the tool runner starts before the service
|
|
38
|
+
sidecars, and the keeper and the agent wait for every service to be ready;
|
|
39
|
+
on Docker the tool runner and the agent are created only after every
|
|
40
|
+
service is ready.
|
|
41
|
+
5. When the run ends, its pod (Kubernetes) or its containers (Docker) are
|
|
42
|
+
deleted, and each service and its data go with them.
|
|
43
|
+
|
|
44
|
+
`get_run` lists a run's services, for example `"services": ["postgres 16"]`.
|
|
45
|
+
|
|
46
|
+
## Declaring services in a repository
|
|
47
|
+
|
|
48
|
+
Commit `.wardby/services.yaml` at the repository root:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
# Services wardby starts next to coding runs for this repository.
|
|
52
|
+
services:
|
|
53
|
+
postgres: "16"
|
|
54
|
+
redis: "7"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- `services` is the only key. Each entry is a catalog name and a version.
|
|
58
|
+
Names are lowercase letters, digits and hyphens; versions are short strings
|
|
59
|
+
(quote them, so `"8.0"` stays `8.0`).
|
|
60
|
+
- At most five services; the file must be under 8 KiB.
|
|
61
|
+
- The file names services only. Images, ports, commands, volumes and
|
|
62
|
+
environment come from the catalog, never from the repository.
|
|
63
|
+
- No file means no services.
|
|
64
|
+
|
|
65
|
+
The file is read from the run's base branch — the agent's `baseRef`, or a
|
|
66
|
+
`baseRef` given to `trigger_agent` for that run — never from the run's own
|
|
67
|
+
branch. So a builder agent's edit to the declaration in its own pull request
|
|
68
|
+
takes effect once that pull request is merged into the base branch, not
|
|
69
|
+
before. A coding agent may propose a change in a pull request (see "Letting a
|
|
70
|
+
coding agent change the declaration" below).
|
|
71
|
+
|
|
72
|
+
### Telling your tests where the services are
|
|
73
|
+
|
|
74
|
+
Tests should read the variables rather than hard-code connection details. A
|
|
75
|
+
short note in the repository's `AGENTS.md` helps coding agents and people alike:
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
## Tests
|
|
79
|
+
|
|
80
|
+
Integration tests need PostgreSQL. They read `DATABASE_URL`
|
|
81
|
+
(for example `postgres://test:test@127.0.0.1:5432/test`). In wardby coding
|
|
82
|
+
runs it is set for you; locally, start a database and export it yourself.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## The service catalog
|
|
86
|
+
|
|
87
|
+
Anyone with the `agents:read` scope can read the catalog, so an agent's owner
|
|
88
|
+
can see which services exist and what variables they provide. Changing it needs
|
|
89
|
+
the `services:manage` scope plus a Wardby role that grants it — `service-manager`,
|
|
90
|
+
or `admin` (see [roles and privileged operations](security-deployment.md#roles-and-privileged-operations)) —
|
|
91
|
+
and every change is written to the control-plane log
|
|
92
|
+
(`event: coding.service_catalog.create|update|delete`, with the entry and the
|
|
93
|
+
caller's principal id).
|
|
94
|
+
|
|
95
|
+
| Tool | What it does |
|
|
96
|
+
| ------------------------------------ | ----------------------------------------------------------------------------------------- |
|
|
97
|
+
| `list_services` (`agents:read`) | Every entry: name, version, image, whether it is built in. |
|
|
98
|
+
| `get_service` (`agents:read`) | One entry in full, including `testEnv`, the variables a run's shells receive. |
|
|
99
|
+
| `create_service` (`services:manage`) | Adds an entry. The image must be pinned by digest (`repo@sha256:...`). |
|
|
100
|
+
| `update_service` (`services:manage`) | Changes an entry that is not built in. Runs already dispatched keep what they began with. |
|
|
101
|
+
| `delete_service` (`services:manage`) | Removes an entry that is not built in. |
|
|
102
|
+
|
|
103
|
+
An entry has:
|
|
104
|
+
|
|
105
|
+
| Field | Meaning |
|
|
106
|
+
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
107
|
+
| `name`, `version` | What a repository declares. Unique together. |
|
|
108
|
+
| `kind` | `sidecar`: a fresh instance next to each run. |
|
|
109
|
+
| `image` | The image, pinned by digest. |
|
|
110
|
+
| `port` | The port it listens on. |
|
|
111
|
+
| `serviceEnv` | Environment for the service container. Per-run throwaway values only; never put a secret here. |
|
|
112
|
+
| `testEnv` | Variables the agent's shells receive. Upper-case names; names wardby uses itself (`PATH`, `HOME`, `PIP_*`, `WARDBY_*`, proxy settings, ...) are refused. |
|
|
113
|
+
| `readiness` | A command in the image that succeeds once the service accepts connections on `127.0.0.1`, with its period, timeout and failure threshold. |
|
|
114
|
+
| `resources` | CPU (millicores), memory (MiB) and disk (MiB). Requests equal limits. |
|
|
115
|
+
| `dataPath` | The directory the service writes its data to; an empty volume in every run (memory-backed on Docker). |
|
|
116
|
+
| `writablePaths` | Other directories the image writes to (a socket directory, `/tmp`). The service's root filesystem is read-only. |
|
|
117
|
+
|
|
118
|
+
### Built-in services
|
|
119
|
+
|
|
120
|
+
wardby ships these entries, pinned to the official images by digest. They
|
|
121
|
+
change only with a wardby release and cannot be updated or deleted over MCP.
|
|
122
|
+
|
|
123
|
+
| Service | Variables the agent's shells receive |
|
|
124
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
125
|
+
| `postgres` `15`, `16`, `17` | `DATABASE_URL=postgres://test:test@127.0.0.1:5432/test`, `PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE` |
|
|
126
|
+
| `redis` `7` | `REDIS_URL=redis://127.0.0.1:6379/0`, `REDIS_HOST`, `REDIS_PORT` |
|
|
127
|
+
| `mysql` `8` | `DATABASE_URL=mysql://test:test@127.0.0.1:3306/test`, `MYSQL_HOST`, `MYSQL_TCP_PORT`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE` |
|
|
128
|
+
|
|
129
|
+
The credentials are fixed test values, visible to anyone who can read the
|
|
130
|
+
catalog: each instance exists only inside one run's pod and is reachable only
|
|
131
|
+
from it. Never put a real secret in `serviceEnv` or `testEnv`.
|
|
132
|
+
|
|
133
|
+
### Adding your own entry
|
|
134
|
+
|
|
135
|
+
Use `create_service` for another database version, an extension image, or an
|
|
136
|
+
image mirrored into your own registry (for example to avoid Docker Hub pull
|
|
137
|
+
limits):
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"name": "postgres-postgis",
|
|
142
|
+
"version": "16",
|
|
143
|
+
"image": "registry.example.com/mirror/postgis@sha256:<64 hex digits>",
|
|
144
|
+
"port": 5432,
|
|
145
|
+
"serviceEnv": {
|
|
146
|
+
"POSTGRES_USER": "test",
|
|
147
|
+
"POSTGRES_PASSWORD": "test",
|
|
148
|
+
"POSTGRES_DB": "test",
|
|
149
|
+
"PGDATA": "/var/lib/postgresql/data/pgdata"
|
|
150
|
+
},
|
|
151
|
+
"testEnv": { "DATABASE_URL": "postgres://test:test@127.0.0.1:5432/test" },
|
|
152
|
+
"readiness": {
|
|
153
|
+
"command": ["pg_isready", "-h", "127.0.0.1", "-p", "5432", "-U", "test", "-d", "test"],
|
|
154
|
+
"periodSeconds": 2,
|
|
155
|
+
"timeoutSeconds": 2,
|
|
156
|
+
"failureThreshold": 30
|
|
157
|
+
},
|
|
158
|
+
"resources": { "cpuMillicores": 500, "memoryMib": 512, "diskMib": 1024 },
|
|
159
|
+
"dataPath": "/var/lib/postgresql/data",
|
|
160
|
+
"writablePaths": ["/var/run/postgresql", "/tmp"]
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The image runs as the run pod's non-root user with a read-only root
|
|
165
|
+
filesystem and no Linux capabilities, so list every directory it writes to.
|
|
166
|
+
Probe the service over TCP on `127.0.0.1` rather than a Unix socket: database
|
|
167
|
+
images commonly start a temporary socket-only server while they initialize.
|
|
168
|
+
|
|
169
|
+
On the Docker launcher, every directory the image declares as a `VOLUME` must
|
|
170
|
+
be its `dataPath` or one of its `writablePaths`. Any other `VOLUME` would be an
|
|
171
|
+
unbounded volume on the host's disk, so the run fails its isolation check
|
|
172
|
+
instead.
|
|
173
|
+
|
|
174
|
+
## Allowing services for an agent
|
|
175
|
+
|
|
176
|
+
The agent's owner lists the catalog names its runs may use (any version the
|
|
177
|
+
catalog has):
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{ "id": "<agent id>", "codingProfile": { "services": ["postgres", "redis"] } }
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
sent with `update_agent` (or `create_agent`'s `codingProfile`). A name the
|
|
184
|
+
catalog doesn't have is refused. An empty list, the default, means no services.
|
|
185
|
+
|
|
186
|
+
An agent with an empty list never reads `.wardby/services.yaml` at all —
|
|
187
|
+
dispatch only looks at the file when the agent allows at least one service.
|
|
188
|
+
So an agent that allows no services just starts its runs without services,
|
|
189
|
+
whatever a repository declares; every refusal in "Errors" below applies only
|
|
190
|
+
to an agent that allows at least one service.
|
|
191
|
+
|
|
192
|
+
A [bring-your-own worker image](coding-worker-byo-images.md) must be built on
|
|
193
|
+
driver v11 or later to run with services; an agent whose `workerImageRef`
|
|
194
|
+
predates driver v11 rejects the run input once services are on it.
|
|
195
|
+
|
|
196
|
+
## Letting a coding agent change the declaration
|
|
197
|
+
|
|
198
|
+
Wardby always protects `.wardby/` in coding runs, except
|
|
199
|
+
`.wardby/services.yaml`: whatever an agent's own `protectedPaths` say, a coding
|
|
200
|
+
run may not change other files under `.wardby/`, and any coding agent may
|
|
201
|
+
propose a change to the declaration in its pull request. The change takes
|
|
202
|
+
effect only after a person merges it, because runs read the declaration from
|
|
203
|
+
the base branch. If a code-review agent reviews the repository's pull
|
|
204
|
+
requests, add a line to its instructions asking it to call out any change to
|
|
205
|
+
`.wardby/services.yaml`.
|
|
206
|
+
|
|
207
|
+
Protected-path entries also accept a leading `!` for your own exceptions:
|
|
208
|
+
`["docs/**", "!docs/changelog.md"]` protects `docs/` except the changelog.
|
|
209
|
+
|
|
210
|
+
- An exception is one literal file path: no `*`, `?`, `[ ]` or `{ }`. Entries
|
|
211
|
+
such as `!**` or `!.github/**` are refused, so an exception can never switch
|
|
212
|
+
off a whole protected tree.
|
|
213
|
+
- An exception wins over the agent's own patterns, whatever its position.
|
|
214
|
+
- Exceptions never apply to the `.wardby/` baseline: nothing under `.wardby/`
|
|
215
|
+
other than `services.yaml` can be unprotected, and `services.yaml` cannot be
|
|
216
|
+
protected again.
|
|
217
|
+
- A list must protect at least one path.
|
|
218
|
+
|
|
219
|
+
## Errors
|
|
220
|
+
|
|
221
|
+
| Problem | When | Run | What the requester sees |
|
|
222
|
+
| ---------------------------------------------- | -------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
223
|
+
| `services.yaml` is invalid | Dispatch | refused, `service_declaration_invalid` | "`.wardby/services.yaml` is invalid: <line and reason>." |
|
|
224
|
+
| The file couldn't be read | Dispatch | refused, `service_declaration_unavailable` | "wardby couldn't read `.wardby/services.yaml` from the base branch, so the run was not started. Try again." |
|
|
225
|
+
| A name and version the catalog doesn't have | Dispatch | refused, `service_unknown` | "This repository asks for `<name> <version>`, which wardby's service catalog doesn't have." |
|
|
226
|
+
| A service the agent isn't allowed | Dispatch | refused, `service_not_allowed` | "This repository asks for `<name>`, which this agent isn't allowed to use. An admin or the agent's owner can allow it." |
|
|
227
|
+
| Services on a deployment that can't start them | Dispatch | refused, `service_launcher_unsupported` | "This repository asks for services, which this wardby deployment can't start: services need the Kubernetes or Docker job launcher." |
|
|
228
|
+
| A service never became ready | Launch | failed, category `service_unready` | "The `<name>` service didn't become ready, so the run couldn't start." |
|
|
229
|
+
| The run's changes touched a protected path | Collect | failed, category `protected_path` | "its changes include `<path>`, which this agent may not edit, so none of its changes were kept. Ask again without changing that file, or have the repository owner make that change." |
|
|
230
|
+
|
|
231
|
+
A refused run's `error` (from `get_run`) is the code followed by that sentence.
|
|
232
|
+
The sentence reaches the requester on the run's status comment and, for a
|
|
233
|
+
coding run started by another agent, in that agent's tool result. A
|
|
234
|
+
`protected_path` failure is not a service error -- see
|
|
235
|
+
[Run changed a protected path](../help/errors/protected-path.md) -- but is
|
|
236
|
+
listed here because it uses the same category/sentence mechanism.
|
|
237
|
+
|
|
238
|
+
On Kubernetes, a service is "not ready" when its readiness command keeps
|
|
239
|
+
failing past its failure threshold (the sidecar restarts), its image can't be
|
|
240
|
+
pulled or started, or it has still not started when the launcher's pod-start
|
|
241
|
+
bound (`KUBERNETES_READY_TIMEOUT_MS`, default 120000) is reached. So an entry's
|
|
242
|
+
readiness is bounded by that timeout: a `failureThreshold` × `periodSeconds`
|
|
243
|
+
longer than it never takes effect. Pulling a service image adds to pod start
|
|
244
|
+
time; raise that bound if first pulls on new nodes are slow.
|
|
245
|
+
|
|
246
|
+
On Docker, the launcher starts the services one at a time and runs each
|
|
247
|
+
readiness command with `docker exec` every `periodSeconds`, each attempt
|
|
248
|
+
bounded by `timeoutSeconds`. A service is "not ready" after `failureThreshold`
|
|
249
|
+
consecutive failures, when its container can't be created or started or
|
|
250
|
+
exits, when its image can't be pulled within 5 minutes, or when the run's
|
|
251
|
+
services are still not all ready after 120 seconds. Unlike Kubernetes's
|
|
252
|
+
pod-start bound, that 120-second limit is fixed: it has no environment
|
|
253
|
+
variable, so raising it means switching to the Kubernetes launcher. It covers
|
|
254
|
+
creating, starting and probing every service of the run together, not image
|
|
255
|
+
pulls, and start-up never runs past the run's own timeout either. So an
|
|
256
|
+
entry's readiness settings apply within that limit: a `failureThreshold` ×
|
|
257
|
+
(`periodSeconds` + `timeoutSeconds`) longer than it never takes effect. The
|
|
258
|
+
launcher uses a local copy of the digest-pinned image when the Docker host
|
|
259
|
+
has one and otherwise pulls it without registry credentials. For a private
|
|
260
|
+
registry, or to avoid public pull limits, pull the image on the Docker host
|
|
261
|
+
beforehand (`docker pull <image>@sha256:<digest>`).
|
|
262
|
+
|
|
263
|
+
## Cost and capacity
|
|
264
|
+
|
|
265
|
+
Each service reserves its catalog resources for the whole run, on top of the
|
|
266
|
+
worker's: CPU and memory at their requests (equal to limits), and ephemeral
|
|
267
|
+
storage for its data volume plus 64 MiB for each writable path. They count
|
|
268
|
+
toward the namespace's ResourceQuota and, on GKE Autopilot, toward what you are
|
|
269
|
+
billed for the run's pod and its 10 GiB pod ephemeral-storage ceiling. A run
|
|
270
|
+
whose workspace and services together exceed that ceiling fails before its pod
|
|
271
|
+
is created.
|
|
272
|
+
|
|
273
|
+
On the Docker launcher everything a service stores is in memory: its data
|
|
274
|
+
path and each writable path are tmpfs mounts, so its memory limit is its
|
|
275
|
+
catalog memory plus its disk (its data volume and 64 MiB for each writable
|
|
276
|
+
path) plus 64 MiB of shared memory, with its catalog CPU and at most 512
|
|
277
|
+
processes. Size the Docker host's RAM for `CODING_MAX_CONCURRENT` runs with
|
|
278
|
+
their services. A service that exits during a run is not restarted on Docker;
|
|
279
|
+
the run's tests see it gone.
|
|
280
|
+
|
|
281
|
+
Unlike a managed Kubernetes tier such as GKE Autopilot, which checks a
|
|
282
|
+
resource ceiling per pod, the Docker launcher does not cap the combined memory
|
|
283
|
+
of a single run's services. Size a Docker host's RAM for the worker plus the
|
|
284
|
+
worst case a repository could declare in one run: up to five services, each
|
|
285
|
+
at its catalog entry's memory plus disk plus 64 MiB. A custom catalog entry's
|
|
286
|
+
`resources` (`create_service`/`update_service`) is what sets those numbers, so
|
|
287
|
+
review them before allowing a repository to declare more or larger services.
|
|
288
|
+
|
|
289
|
+
## Upgrading an existing deployment
|
|
290
|
+
|
|
291
|
+
`services:manage` is a new scope. If your deployment delegates to an
|
|
292
|
+
identity provider, define `services:manage` in the provider before you deploy
|
|
293
|
+
this release: clients that request every advertised scope otherwise fail with
|
|
294
|
+
`invalid_scope`. Map the `service-manager` role (or use `admin`) for the people
|
|
295
|
+
who maintain the catalog; see
|
|
296
|
+
[getting-started-identity-provider.md](getting-started-identity-provider.md#wardby-roles).
|
|
297
|
+
|
|
298
|
+
Existing agents are allowed no services until their owners add
|
|
299
|
+
`codingProfile.services`, and every existing agent gets the `.wardby/`
|
|
300
|
+
protected-path baseline without any change to its settings.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Bring-Your-Own Coding-Worker Images
|
|
2
|
+
|
|
3
|
+
wardby ships worker images for `node` and `node-python` toolchains
|
|
4
|
+
(`src/coding-worker/Dockerfile`, `Dockerfile.node-python`). For any other
|
|
5
|
+
language toolchain (Ruby, PHP, .NET, ...), build your own image on top of
|
|
6
|
+
wardby's published **driver base image** and point your agent's
|
|
7
|
+
`workerImageRef` at it, instead of waiting for wardby to hand-author a new
|
|
8
|
+
`Dockerfile.<toolchain>`.
|
|
9
|
+
|
|
10
|
+
## The driver image
|
|
11
|
+
|
|
12
|
+
`ghcr.io/wardby/wardby/wardby-coding-worker-driver` contains wardby's
|
|
13
|
+
compiled Node.js coding-worker driver, `git`, `ca-certificates`, and the
|
|
14
|
+
`wardby` user (uid/gid 10001) — nothing language-specific. It's built from
|
|
15
|
+
`src/coding-worker/Dockerfile.driver` and published on `driver-vN` git tags;
|
|
16
|
+
each release's GitHub Release notes carry the resolved
|
|
17
|
+
`@sha256:...` digest to pin.
|
|
18
|
+
|
|
19
|
+
The image deliberately stops before setting `USER`, `WORKDIR`, or
|
|
20
|
+
`ENTRYPOINT`, and before any of the hardened binary-absence checks wardby's
|
|
21
|
+
own images run. Those depend on what you install on top — some toolchains
|
|
22
|
+
(Ruby native gems, .NET native interop) legitimately need a compiler, so
|
|
23
|
+
there's no one-size-fits-all hardening rule. Your derived Dockerfile owns
|
|
24
|
+
that decision and must finish the job itself.
|
|
25
|
+
|
|
26
|
+
## Writing your Dockerfile
|
|
27
|
+
|
|
28
|
+
`src/coding-worker/Dockerfile.node-python` in this repo is the reference
|
|
29
|
+
example — it's a real, CI-built image built this same way. The shape is:
|
|
30
|
+
|
|
31
|
+
```dockerfile
|
|
32
|
+
FROM ghcr.io/wardby/wardby/wardby-coding-worker-driver@sha256:<pin the real digest from a driver-vN release>
|
|
33
|
+
RUN apt-get update \
|
|
34
|
+
&& apt-get install -y --no-install-recommends <your toolchain packages> \
|
|
35
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
36
|
+
# Assert the binaries your sandbox must not contain are absent. Adjust the
|
|
37
|
+
# list to what your toolchain actually needs — e.g. a native-extension
|
|
38
|
+
# ecosystem may need to keep a compiler and drop this line for it.
|
|
39
|
+
RUN test ! -e /usr/bin/docker \
|
|
40
|
+
&& test ! -e /usr/bin/ssh \
|
|
41
|
+
&& test ! -e /usr/bin/curl \
|
|
42
|
+
&& test ! -e /usr/bin/wget \
|
|
43
|
+
&& test ! -e /usr/bin/sudo
|
|
44
|
+
USER 10001:10001
|
|
45
|
+
ENV NODE_ENV=production HOME=/home/wardby
|
|
46
|
+
WORKDIR /workspace
|
|
47
|
+
ENTRYPOINT ["node", "/opt/wardby/coding-worker/main.js"]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Provide the command names your ecosystem's tooling and docs actually use.
|
|
51
|
+
A worker only has what you install: Debian's `python3` package ships no
|
|
52
|
+
`python`, so a task that runs `python -m pytest` — as most Python projects'
|
|
53
|
+
own READMEs tell it to — reports a failed command even when the suite is
|
|
54
|
+
green. `Dockerfile.node-python` symlinks `python` to `python3` for exactly
|
|
55
|
+
that reason, and asserts both work.
|
|
56
|
+
|
|
57
|
+
Build it, push it to your own registry, and note the resulting digest —
|
|
58
|
+
`docker inspect --format '{{index .RepoDigests 0}}' <your-tag>` after a push,
|
|
59
|
+
or read it straight from `docker buildx build --push`'s output.
|
|
60
|
+
|
|
61
|
+
## Pointing an agent at it
|
|
62
|
+
|
|
63
|
+
Set `CodingAgentProfile.workerImageRef` to your image's digest (a mutable
|
|
64
|
+
tag is rejected — see `isImmutableDockerImage` in
|
|
65
|
+
`src/providers/jobs/docker-isolation.ts`). Through the MCP API, that means
|
|
66
|
+
passing `workerImageRef` inside `codingProfile` on `create_agent` or
|
|
67
|
+
`update_agent`.
|
|
68
|
+
|
|
69
|
+
**This requires the `agents:admin` scope**, not just `agents:write` —
|
|
70
|
+
`workerImageRef` bypasses wardby's own curated toolchain matrix entirely, so
|
|
71
|
+
setting or changing it is gated the same way `make_owner` is: a caller with
|
|
72
|
+
only `agents:write` can still manage coding agents normally (including
|
|
73
|
+
picking `toolchain`/`toolchainVersion` from wardby's own images), but cannot
|
|
74
|
+
point one at an arbitrary image without the step-up scope. The scope alone
|
|
75
|
+
isn't enough: the caller must also hold the admin role (see
|
|
76
|
+
[roles and privileged operations](security-deployment.md#roles-and-privileged-operations)).
|
|
77
|
+
|
|
78
|
+
## Running services with a BYO image
|
|
79
|
+
|
|
80
|
+
An agent whose `codingProfile.services` allows a service ([coding
|
|
81
|
+
services](coding-services.md)) needs a worker image built on **driver v11 or
|
|
82
|
+
later**. The driver validates the run input it receives with a strict schema:
|
|
83
|
+
a worker built on an older driver base doesn't recognize the input's
|
|
84
|
+
`services` field and rejects the run outright, rather than silently starting
|
|
85
|
+
without them. Rebuild your image on a current `driver-vN` digest (see "The
|
|
86
|
+
driver image" above) before allowing any service on an agent that uses it.
|
|
87
|
+
|
|
88
|
+
## What this doesn't cover
|
|
89
|
+
|
|
90
|
+
wardby does not re-validate the contents of your built image beyond the
|
|
91
|
+
digest-pinning check above. The mitigant is architectural, not a scan: the
|
|
92
|
+
guardrails that actually matter for a sandboxed run — protected paths, the
|
|
93
|
+
single-commit-per-run invariant, branch/PR scoping, hardened git config —
|
|
94
|
+
live in wardby's own orchestration code (`src/providers/vcs/git.ts`,
|
|
95
|
+
`src/providers/executor/container.ts`), not inside the worker image. A
|
|
96
|
+
compromised or careless BYO image changes the blast radius of the one job
|
|
97
|
+
running inside it; it can't reach past those checks, since the image only
|
|
98
|
+
ever talks git through that code path.
|