@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,125 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
// The installed npm package does not carry the Prisma CLI (a devDependency:
|
|
4
|
+
// its tree pulled advisories into every consumer install), so quickstart and
|
|
5
|
+
// doctor first look for a `prisma` executable on PATH and use it only if it
|
|
6
|
+
// reports exactly this version; anything else -- wrong version, not on PATH,
|
|
7
|
+
// a spawn error, a non-zero exit, or a timeout -- falls back to running the
|
|
8
|
+
// pinned version through npx, with a config file shipped in the package.
|
|
9
|
+
// Keep this equal to package.json's devDependencies.prisma (migrate.test.ts
|
|
10
|
+
// enforces it).
|
|
11
|
+
//
|
|
12
|
+
// Not supported on Windows: npx is `npx.cmd` there (and a local install would
|
|
13
|
+
// be `prisma.cmd`), which spawnSync can only run through a shell, and
|
|
14
|
+
// quickstart has no win32 handling anywhere else (Docker Compose paths,
|
|
15
|
+
// POSIX file modes) either.
|
|
16
|
+
export const PRISMA_CLI_VERSION = "7.10.0";
|
|
17
|
+
export const FETCH_NOTICE = `Fetching the Prisma CLI (prisma@${PRISMA_CLI_VERSION})…`;
|
|
18
|
+
export const REGISTRY_FAILURE_MESSAGE = `Could not download the Prisma CLI (prisma@${PRISMA_CLI_VERSION}) from the npm registry. ` +
|
|
19
|
+
"quickstart and doctor fetch it on demand. Check your internet connection or npm registry settings " +
|
|
20
|
+
"(.npmrc, proxy), then retry. You can also install it yourself " +
|
|
21
|
+
`(\`npm i -g prisma@${PRISMA_CLI_VERSION}\`) and rerun quickstart -- doctor benefits too.`;
|
|
22
|
+
export const migrateConfigFile = fileURLToPath(new URL("../../prisma/migrate.config.mjs", import.meta.url));
|
|
23
|
+
// A short timeout so a wedged or misbehaving local binary can't stall
|
|
24
|
+
// quickstart/doctor -- any hang past this falls back to npx.
|
|
25
|
+
const LOCAL_PRISMA_PROBE_TIMEOUT_MS = 5000;
|
|
26
|
+
// `prisma --version` prints a fixed-label, padded-column report, e.g.:
|
|
27
|
+
// prisma : 7.10.0
|
|
28
|
+
// @prisma/client : 7.10.0
|
|
29
|
+
// Operating System : darwin
|
|
30
|
+
// ...
|
|
31
|
+
// Several other lines carry their own version-shaped numbers (Node.js,
|
|
32
|
+
// TypeScript, the schema engine hash), so key off the "prisma" label
|
|
33
|
+
// specifically -- not the first x.y.z token anywhere in the output.
|
|
34
|
+
const LOCAL_VERSION_LINE = /^prisma\s*:\s*(\S+)$/m;
|
|
35
|
+
export function parseLocalPrismaVersion(stdout) {
|
|
36
|
+
return LOCAL_VERSION_LINE.exec(stdout)?.[1];
|
|
37
|
+
}
|
|
38
|
+
// Runs a local `prisma --version` under the given env's PATH and returns the
|
|
39
|
+
// version it reports, or undefined for anything that isn't a clean match:
|
|
40
|
+
// not on PATH, a spawn error, a non-zero exit, a timeout, or unparseable
|
|
41
|
+
// output. Never throws.
|
|
42
|
+
export function probeLocalPrismaVersion(env) {
|
|
43
|
+
const result = spawnSync("prisma", ["--version"], {
|
|
44
|
+
env,
|
|
45
|
+
encoding: "utf8",
|
|
46
|
+
stdio: "pipe",
|
|
47
|
+
timeout: LOCAL_PRISMA_PROBE_TIMEOUT_MS,
|
|
48
|
+
});
|
|
49
|
+
if (result.error || result.status !== 0)
|
|
50
|
+
return undefined;
|
|
51
|
+
return parseLocalPrismaVersion(result.stdout ?? "");
|
|
52
|
+
}
|
|
53
|
+
// DATABASE_URL travels in the child's environment only -- never argv, where
|
|
54
|
+
// any local user could read it from the process table. `probe` is injectable
|
|
55
|
+
// so tests never depend on the developer's real PATH.
|
|
56
|
+
export function prismaMigrateInvocation(subcommand, env, probe = probeLocalPrismaVersion) {
|
|
57
|
+
const childEnv = {
|
|
58
|
+
...env,
|
|
59
|
+
PRISMA_HIDE_UPDATE_MESSAGE: "1",
|
|
60
|
+
npm_config_update_notifier: "false",
|
|
61
|
+
npm_config_fund: "false",
|
|
62
|
+
};
|
|
63
|
+
if (probe(childEnv) === PRISMA_CLI_VERSION) {
|
|
64
|
+
return {
|
|
65
|
+
command: "prisma",
|
|
66
|
+
args: ["migrate", subcommand, "--config", migrateConfigFile],
|
|
67
|
+
env: childEnv,
|
|
68
|
+
local: true,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
command: "npx",
|
|
73
|
+
args: ["--yes", `prisma@${PRISMA_CLI_VERSION}`, "migrate", subcommand, "--config", migrateConfigFile],
|
|
74
|
+
env: childEnv,
|
|
75
|
+
local: false,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// npm's own error lines when it cannot fetch a package (npm 7+ prints
|
|
79
|
+
// "npm error", older "npm ERR!"): network failures and registry HTTP / version
|
|
80
|
+
// errors. A failed migration is printed by Prisma itself and never carries
|
|
81
|
+
// these -- in particular a database ECONNREFUSED is Prisma's P1001, not an
|
|
82
|
+
// "npm error code" line.
|
|
83
|
+
const REGISTRY_ERROR = /^npm (?:error|ERR!) (?:code|errno) (?:ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ETARGET|E[45]\d\d)\b|^npm (?:error|ERR!) network /m;
|
|
84
|
+
// `local` marks that `result`/`spawnError` came from the locally installed
|
|
85
|
+
// binary rather than npx: nothing was fetched, so neither an npm-shaped
|
|
86
|
+
// error line nor a spawn error is a registry failure there -- a spawn error
|
|
87
|
+
// still gets a clear message (below), just not that one.
|
|
88
|
+
export function classifyMigrateResult(result, spawnError, local = false) {
|
|
89
|
+
if (spawnError) {
|
|
90
|
+
if (local)
|
|
91
|
+
return { ...result, status: 1, stderr: spawnError.message };
|
|
92
|
+
return { ...result, status: 1, stderr: spawnError.message, registryFailure: true };
|
|
93
|
+
}
|
|
94
|
+
if (!local && result.status !== 0 && REGISTRY_ERROR.test(result.stderr))
|
|
95
|
+
return { ...result, registryFailure: true };
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
// The one-line reason for a failed run: the registry message, or Prisma's own
|
|
99
|
+
// first error line (URLs masked, though Prisma prints host and database only).
|
|
100
|
+
export function migrateFailureReason(result) {
|
|
101
|
+
if (result.registryFailure)
|
|
102
|
+
return REGISTRY_FAILURE_MESSAGE;
|
|
103
|
+
const lines = `${result.stderr}\n${result.stdout}`
|
|
104
|
+
.split("\n")
|
|
105
|
+
.map((line) => line.trim())
|
|
106
|
+
.filter(Boolean);
|
|
107
|
+
// A line that starts with "Error", or that carries a Prisma error code anywhere.
|
|
108
|
+
const line = lines.find((candidate) => candidate.startsWith("Error") || /\bP\d{4}\b/.test(candidate)) ?? lines[0] ?? "no output";
|
|
109
|
+
return line.replace(/postgres(ql)?:\/\/[^\s`'"]+/gi, "<database url>");
|
|
110
|
+
}
|
|
111
|
+
// Runs an already-resolved invocation (from `prismaMigrateInvocation`). Split
|
|
112
|
+
// out so callers can decide whether to print `FETCH_NOTICE` -- which only
|
|
113
|
+
// applies to the npx path -- before running it.
|
|
114
|
+
export function runPrismaMigrateInvocation(invocation, cwd) {
|
|
115
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
116
|
+
cwd,
|
|
117
|
+
env: invocation.env,
|
|
118
|
+
encoding: "utf8",
|
|
119
|
+
stdio: "pipe",
|
|
120
|
+
});
|
|
121
|
+
return classifyMigrateResult({ status: result.status ?? 1, stdout: result.stdout ?? "", stderr: result.stderr ?? "" }, result.error, invocation.local);
|
|
122
|
+
}
|
|
123
|
+
export function runPrismaMigrate(subcommand, env, cwd, probe) {
|
|
124
|
+
return runPrismaMigrateInvocation(prismaMigrateInvocation(subcommand, env, probe), cwd);
|
|
125
|
+
}
|
|
@@ -4,15 +4,33 @@ export type ResolvedAddress = {
|
|
|
4
4
|
};
|
|
5
5
|
export type Resolver = (hostname: string) => Promise<ResolvedAddress[]>;
|
|
6
6
|
export interface FetchPolicyOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Egress allowlist, enforced only with `restrictToAllowedHosts`. It can only
|
|
9
|
+
* NARROW where fetch may go: a listed host must still resolve exclusively to
|
|
10
|
+
* global addresses. Tool-controlled lists belong here.
|
|
11
|
+
*/
|
|
7
12
|
allowedHosts?: string[];
|
|
8
|
-
allowPrivateHosts?: boolean;
|
|
9
|
-
resolve?: Resolver;
|
|
10
13
|
restrictToAllowedHosts?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Hosts that may resolve to a non-global (private/loopback/link-local)
|
|
16
|
+
* address. Operator-controlled ONLY (WARDBY_FETCH_ALLOWED_HOSTS) — never
|
|
17
|
+
* populate it from a tool's or caller's own capability list. Cloud metadata
|
|
18
|
+
* endpoints stay blocked even when listed here.
|
|
19
|
+
*/
|
|
20
|
+
privateHostAllowlist?: string[];
|
|
21
|
+
resolve?: Resolver;
|
|
11
22
|
}
|
|
12
23
|
export declare class FetchPolicyError extends Error {
|
|
13
24
|
constructor();
|
|
14
25
|
}
|
|
15
26
|
export declare function isGlobalAddress(address: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* True for a cloud metadata address, including IPv6 encodings of the IPv4
|
|
29
|
+
* ones: IPv4-mapped/-compatible (::ffff:0:0/96, ::/96), NAT64 well-known
|
|
30
|
+
* (64:ff9b::/96), RFC 8215 local-use NAT64 (64:ff9b:1::/48, /96 and RFC 6052
|
|
31
|
+
* /48 layouts) and 6to4 (2002::/16). A zone id is ignored for the comparison.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isCloudMetadataAddress(address: string): boolean;
|
|
16
34
|
export declare function normalizeHost(host: string): string;
|
|
17
35
|
export declare function parseAllowedHosts(value: string | undefined): string[];
|
|
18
36
|
export declare function resolveDestination(urlString: string, options?: FetchPolicyOptions): Promise<{
|
|
@@ -33,6 +33,9 @@ function v6(ip) {
|
|
|
33
33
|
return groups.reduce((n, g) => (n << 16n) + BigInt("0x" + g), 0n);
|
|
34
34
|
}
|
|
35
35
|
export function isGlobalAddress(address) {
|
|
36
|
+
// Zone-scoped (fe80::1%eth0) answers are link-local by nature; never global.
|
|
37
|
+
if (address.includes("%"))
|
|
38
|
+
return false;
|
|
36
39
|
if (isIP(address) === 4)
|
|
37
40
|
return !blockedV4.some(([net, prefix]) => v4(address) >>> (32 - prefix) === v4(net) >>> (32 - prefix));
|
|
38
41
|
if (isIP(address) !== 6)
|
|
@@ -51,9 +54,57 @@ export function isGlobalAddress(address) {
|
|
|
51
54
|
return n >> shift === v6(net) >> shift;
|
|
52
55
|
}));
|
|
53
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Cloud instance-metadata endpoints: GCP/AWS/Azure IMDS, GKE metadata proxy,
|
|
59
|
+
* ECS task credentials, EKS Pod Identity, Alibaba Cloud; plus the AWS, EKS and
|
|
60
|
+
* GCE IPv6 addresses.
|
|
61
|
+
*/
|
|
62
|
+
const METADATA_V4 = new Set([
|
|
63
|
+
"169.254.169.254",
|
|
64
|
+
"169.254.169.252",
|
|
65
|
+
"169.254.170.2",
|
|
66
|
+
"169.254.170.23",
|
|
67
|
+
"100.100.100.200",
|
|
68
|
+
]);
|
|
69
|
+
const METADATA_V6 = new Set(["fd00:ec2::254", "fd00:ec2::23", "fd20:ce::254"].map(v6));
|
|
70
|
+
const METADATA_HOSTNAMES = new Set(["metadata.google.internal", "metadata"]);
|
|
71
|
+
const NAT64_WELL_KNOWN = v6("64:ff9b::") >> 32n;
|
|
72
|
+
const NAT64_LOCAL_USE = v6("64:ff9b:1::") >> 80n;
|
|
73
|
+
const SIX_TO_FOUR = 0x2002n;
|
|
74
|
+
function v4FromBits(bits) {
|
|
75
|
+
const n = Number(bits & 0xffffffffn);
|
|
76
|
+
return [24, 16, 8, 0].map((shift) => (n >>> shift) & 0xff).join(".");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* True for a cloud metadata address, including IPv6 encodings of the IPv4
|
|
80
|
+
* ones: IPv4-mapped/-compatible (::ffff:0:0/96, ::/96), NAT64 well-known
|
|
81
|
+
* (64:ff9b::/96), RFC 8215 local-use NAT64 (64:ff9b:1::/48, /96 and RFC 6052
|
|
82
|
+
* /48 layouts) and 6to4 (2002::/16). A zone id is ignored for the comparison.
|
|
83
|
+
*/
|
|
84
|
+
export function isCloudMetadataAddress(address) {
|
|
85
|
+
const bare = address.split("%")[0];
|
|
86
|
+
if (isIP(bare) === 4)
|
|
87
|
+
return METADATA_V4.has(bare);
|
|
88
|
+
if (isIP(bare) !== 6)
|
|
89
|
+
return false;
|
|
90
|
+
const n = v6(new URL("http://[" + bare + "]").hostname.slice(1, -1));
|
|
91
|
+
if (METADATA_V6.has(n))
|
|
92
|
+
return true;
|
|
93
|
+
const embedded = [];
|
|
94
|
+
const high96 = n >> 32n;
|
|
95
|
+
if (high96 === 0n || high96 === 0xffffn || high96 === NAT64_WELL_KNOWN)
|
|
96
|
+
embedded.push(n);
|
|
97
|
+
if (n >> 80n === NAT64_LOCAL_USE)
|
|
98
|
+
embedded.push(n, (((n >> 64n) & 0xffffn) << 16n) | ((n >> 40n) & 0xffffn));
|
|
99
|
+
if (n >> 112n === SIX_TO_FOUR)
|
|
100
|
+
embedded.push(n >> 80n);
|
|
101
|
+
return embedded.some((bits) => METADATA_V4.has(v4FromBits(bits)));
|
|
102
|
+
}
|
|
54
103
|
export function normalizeHost(host) {
|
|
55
104
|
if (!host || /[\s*/@?#\\]/.test(host))
|
|
56
105
|
throw new FetchPolicyError();
|
|
106
|
+
if (host.startsWith("[") !== host.endsWith("]"))
|
|
107
|
+
throw new FetchPolicyError();
|
|
57
108
|
const value = host.startsWith("[") ? host.slice(1, -1) : host;
|
|
58
109
|
if (isIP(value))
|
|
59
110
|
return new URL(isIP(value) === 6 ? "http://[" + value + "]" : "http://" + value).hostname
|
|
@@ -61,7 +112,10 @@ export function normalizeHost(host) {
|
|
|
61
112
|
.toLowerCase();
|
|
62
113
|
if (host.includes(":"))
|
|
63
114
|
throw new FetchPolicyError();
|
|
64
|
-
|
|
115
|
+
const name = new URL("http://" + host).hostname.toLowerCase().replace(/\.+$/, "");
|
|
116
|
+
if (!name)
|
|
117
|
+
throw new FetchPolicyError();
|
|
118
|
+
return name;
|
|
65
119
|
}
|
|
66
120
|
export function parseAllowedHosts(value) {
|
|
67
121
|
return value === undefined || value === "" ? [] : value.split(",").map((host) => normalizeHost(host.trim()));
|
|
@@ -77,17 +131,24 @@ export async function resolveDestination(urlString, options = {}) {
|
|
|
77
131
|
if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || urlString.length > 8192)
|
|
78
132
|
throw new FetchPolicyError();
|
|
79
133
|
const hostname = normalizeHost(url.hostname);
|
|
134
|
+
if (METADATA_HOSTNAMES.has(hostname))
|
|
135
|
+
throw new FetchPolicyError();
|
|
80
136
|
const allowed = (options.allowedHosts ?? []).map(normalizeHost).includes(hostname);
|
|
81
137
|
if (options.restrictToAllowedHosts && !allowed)
|
|
82
138
|
throw new FetchPolicyError();
|
|
139
|
+
// Only the operator list may open a non-global destination; a restricted
|
|
140
|
+
// caller additionally needs the host in its own list (checked just above).
|
|
141
|
+
const privateAllowed = (options.privateHostAllowlist ?? []).map(normalizeHost).includes(hostname);
|
|
83
142
|
const version = isIP(hostname);
|
|
84
143
|
const addresses = version
|
|
85
144
|
? [{ address: hostname, family: version }]
|
|
86
145
|
: await (options.resolve ?? ((host) => lookup(host, { all: true })))(hostname);
|
|
87
146
|
if (!addresses.length ||
|
|
88
|
-
addresses.some((a) =>
|
|
147
|
+
addresses.some((a) => a.address.includes("%") ||
|
|
148
|
+
!isIP(a.address) ||
|
|
89
149
|
isIP(a.address) !== a.family ||
|
|
90
|
-
(
|
|
150
|
+
isCloudMetadataAddress(a.address) ||
|
|
151
|
+
(!isGlobalAddress(a.address) && !privateAllowed)))
|
|
91
152
|
throw new FetchPolicyError();
|
|
92
153
|
return { url, hostname, address: addresses[0].address, family: addresses[0].family };
|
|
93
154
|
}
|
|
@@ -8,8 +8,16 @@ import type { QuickJSContext, QuickJSRuntime } from "quickjs-emscripten";
|
|
|
8
8
|
import type { Datastore } from "../providers/datastore/types.js";
|
|
9
9
|
import type { SecretsAccessor } from "../core/secrets.js";
|
|
10
10
|
import type { SharedDatastoreAccessor } from "../core/datastores.js";
|
|
11
|
+
import { type FetchPolicyOptions } from "./fetch-policy.js";
|
|
11
12
|
import { type Logger } from "../core/logger.js";
|
|
12
13
|
import { type ParserWorkerPool } from "./parser-worker/pool.js";
|
|
14
|
+
/**
|
|
15
|
+
* Fetch policy for one tool invocation. The tool's own host list only narrows
|
|
16
|
+
* egress; private destinations open solely via the operator's
|
|
17
|
+
* WARDBY_FETCH_ALLOWED_HOSTS (and, for a non-wildcard tool, only when the tool
|
|
18
|
+
* also lists the host). Cloud metadata stays blocked either way (fetch-policy.ts).
|
|
19
|
+
*/
|
|
20
|
+
export declare function sandboxFetchPolicy(toolHosts: readonly string[], operatorHosts?: readonly string[]): FetchPolicyOptions;
|
|
13
21
|
export interface HostFunctionOptions {
|
|
14
22
|
signal?: AbortSignal;
|
|
15
23
|
agentId: string;
|
|
@@ -23,7 +31,7 @@ export interface HostFunctionOptions {
|
|
|
23
31
|
logger?: Logger;
|
|
24
32
|
/** Overrides the shared default parser-worker pool — mainly for tests. */
|
|
25
33
|
parserPool?: ParserWorkerPool;
|
|
26
|
-
/** Hosts this specific tool attachment may fetch. Omitted/empty = no outbound fetch at all; a literal "*" element lifts the restriction
|
|
34
|
+
/** Hosts this specific tool attachment may fetch. Omitted/empty = no outbound fetch at all; a literal "*" element lifts the restriction. Either way this list only narrows egress: private/link-local destinations need the operator's WARDBY_FETCH_ALLOWED_HOSTS, and cloud metadata is always blocked. */
|
|
27
35
|
allowedFetchHosts?: string[];
|
|
28
36
|
}
|
|
29
37
|
export declare function installHostFunctions(context: QuickJSContext, runtime: QuickJSRuntime, options: HostFunctionOptions): void;
|
|
@@ -19,6 +19,17 @@ import { redactPii } from "./pii-redaction.js";
|
|
|
19
19
|
const MIN_REDACTABLE_SECRET_LENGTH = 6;
|
|
20
20
|
const FETCH_ALLOWED_HOSTS = parseAllowedHosts(process.env.WARDBY_FETCH_ALLOWED_HOSTS);
|
|
21
21
|
let sharedParserPool;
|
|
22
|
+
/**
|
|
23
|
+
* Fetch policy for one tool invocation. The tool's own host list only narrows
|
|
24
|
+
* egress; private destinations open solely via the operator's
|
|
25
|
+
* WARDBY_FETCH_ALLOWED_HOSTS (and, for a non-wildcard tool, only when the tool
|
|
26
|
+
* also lists the host). Cloud metadata stays blocked either way (fetch-policy.ts).
|
|
27
|
+
*/
|
|
28
|
+
export function sandboxFetchPolicy(toolHosts, operatorHosts = FETCH_ALLOWED_HOSTS) {
|
|
29
|
+
if (toolHosts.includes(FETCH_WILDCARD))
|
|
30
|
+
return { privateHostAllowlist: [...operatorHosts] };
|
|
31
|
+
return { allowedHosts: [...toolHosts], restrictToAllowedHosts: true, privateHostAllowlist: [...operatorHosts] };
|
|
32
|
+
}
|
|
22
33
|
function args(argsJson) {
|
|
23
34
|
return JSON.parse(argsJson);
|
|
24
35
|
}
|
|
@@ -74,11 +85,7 @@ export function installHostFunctions(context, runtime, options) {
|
|
|
74
85
|
});
|
|
75
86
|
register("__bridge_fetch", async (argsJson) => {
|
|
76
87
|
const [url, init] = args(argsJson);
|
|
77
|
-
|
|
78
|
-
if (hosts.includes(FETCH_WILDCARD)) {
|
|
79
|
-
return safeFetch(url, init, { allowedHosts: FETCH_ALLOWED_HOSTS, signal });
|
|
80
|
-
}
|
|
81
|
-
return safeFetch(url, init, { allowedHosts: hosts, restrictToAllowedHosts: true, signal });
|
|
88
|
+
return safeFetch(url, init, { ...sandboxFetchPolicy(allowedFetchHosts ?? []), signal });
|
|
82
89
|
});
|
|
83
90
|
register("__bridge_datastoreGet", async (argsJson) => {
|
|
84
91
|
const [key] = args(argsJson);
|
package/dist/serve.js
CHANGED
|
@@ -33,7 +33,7 @@ export async function startServe(options = {}) {
|
|
|
33
33
|
const concurrency = loadCodingConcurrencyConfig();
|
|
34
34
|
const providers = options.providers ?? buildMcpProviders().providers;
|
|
35
35
|
const mcp = await startMcp({ providers, schedulerAttached: true });
|
|
36
|
-
const reconciler = startReconciler({ executor: providers.executor });
|
|
36
|
+
const reconciler = startReconciler({ executor: providers.executor, reviewHosts: providers.reviewHosts });
|
|
37
37
|
const scheduler = startScheduler({
|
|
38
38
|
executor: providers.executor,
|
|
39
39
|
scope: options.scope,
|
package/dist/wardby-bin.js
CHANGED
|
@@ -36,6 +36,12 @@ async function main() {
|
|
|
36
36
|
const { downCommand } = await import("./quickstart/index.js");
|
|
37
37
|
await downCommand(process.argv.slice(3));
|
|
38
38
|
}
|
|
39
|
+
else if (command === "help") {
|
|
40
|
+
// Help is bundled and offline: avoid loading the runtime environment,
|
|
41
|
+
// database client, or HTTP runtime just to search documentation.
|
|
42
|
+
const { helpCommand } = await import("./help/cli.js");
|
|
43
|
+
await helpCommand(process.argv.slice(3));
|
|
44
|
+
}
|
|
39
45
|
else {
|
|
40
46
|
await import("./cli.js");
|
|
41
47
|
}
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
- [Getting started](getting-started.md) runs Wardby locally from npm with
|
|
4
|
+
containerized PostgreSQL and a budgeted sample agent.
|
|
5
|
+
- [Getting started on GKE](getting-started-gke.md) covers the supported Google
|
|
6
|
+
Cloud deployment from project setup through verification and teardown.
|
|
7
|
+
- [Bring your own identity provider](getting-started-identity-provider.md)
|
|
8
|
+
configures an existing OAuth/OIDC provider to protect remote MCP access.
|
|
9
|
+
- [Runtime architecture](architecture-runtime.md) explains the control-plane,
|
|
10
|
+
provider, persistence, and execution boundaries.
|
|
11
|
+
- [Coding-agent setup](coding-agent-setup.md) configures the local trusted proxy
|
|
12
|
+
and isolated Codex or Claude Code workers.
|
|
13
|
+
- [Coding-worker isolation](coding-worker-isolation.md) documents the threat
|
|
14
|
+
model and enforced worker boundary.
|
|
15
|
+
- [Bring-your-own worker images](coding-worker-byo-images.md) explains how to
|
|
16
|
+
extend the reviewed worker image contract.
|
|
17
|
+
- [Installing packages in coding runs](coding-packages.md) covers the coding
|
|
18
|
+
package registry: allowlists, safeguards, limits, and error codes.
|
|
19
|
+
- [Services for coding runs](coding-services.md) gives coding runs fresh
|
|
20
|
+
PostgreSQL, Redis or MySQL instances declared in `.wardby/services.yaml`:
|
|
21
|
+
the catalog, per-agent permission, variables, and errors.
|
|
22
|
+
- [Observability](observability.md) covers Prometheus metrics, Grafana, cloud
|
|
23
|
+
collectors, retention, and production ownership.
|
|
24
|
+
- [Release verification](release-verification.md) lists the automated and live
|
|
25
|
+
checks for a release candidate.
|
|
26
|
+
- [Security deployment](security-deployment.md) covers authentication, secrets,
|
|
27
|
+
networking, migrations, recovery, and known limitations.
|
|
28
|
+
|
|
29
|
+
Historical implementation plans, dated evidence, and internal design records
|
|
30
|
+
are intentionally maintained outside the public repository.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Runtime architecture — GitHub trigger path + observability
|
|
2
|
+
|
|
3
|
+
Two independent subsystems currently run side by side on the same host and
|
|
4
|
+
share only Postgres and a Docker Compose network: the `wardby mcp` process
|
|
5
|
+
(agents/runs/webhooks/MCP tools) and the local observability stack
|
|
6
|
+
(coding-proxy metrics → Prometheus → Grafana). Neither depends on the other;
|
|
7
|
+
restarting one has no effect on the other.
|
|
8
|
+
|
|
9
|
+
```mermaid
|
|
10
|
+
flowchart TB
|
|
11
|
+
subgraph GH["GitHub — your-org/your-repo"]
|
|
12
|
+
Issue["Issue or comment that\nmentions your agent"]
|
|
13
|
+
Action["Actions workflow that\nPOSTs the task to wardby"]
|
|
14
|
+
PRout["Draft PR opened"]
|
|
15
|
+
Issue --> Action
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
Action -->|"POST /webhooks/:id\nx-webhook-secret"| Tunnel
|
|
19
|
+
|
|
20
|
+
subgraph Public["Public HTTPS"]
|
|
21
|
+
Tunnel["HTTPS tunnel (e.g. ngrok)\n<your-domain> -> :8080\n(TLS terminated here)"]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Tunnel --> MCP
|
|
25
|
+
|
|
26
|
+
subgraph Host["Your machine"]
|
|
27
|
+
subgraph MCPBox["wardby mcp (Node/tsx)\nMCP_TRANSPORT=http, self-hosted auth"]
|
|
28
|
+
MCP["/webhooks/:id - secret auth\n/mcp - OAuth auth (list_agents, trigger_agent, get_run, ...)\n/.well-known/oauth-protected-resource"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
MCP -->|"creates Run, dispatches via JobLauncher"| Worker
|
|
32
|
+
MCP <-->|"reads/writes"| PG[("local-postgres-1\nAgent, Run, Webhook,\nBudgetGroup, AgentMemory, Datastore")]
|
|
33
|
+
|
|
34
|
+
subgraph Docker["Docker"]
|
|
35
|
+
Worker["ephemeral coding worker\n(Codex / Claude Code)\none per Run"]
|
|
36
|
+
Proxy["wardby-coding-proxy\ncredential injection +\ntoken/cost metering\n:9464/metrics (private net only)"]
|
|
37
|
+
Worker -->|"OpenAI/Anthropic calls,\nproxied"| Proxy
|
|
38
|
+
Proxy -->|"usage/cost ledger"| PG
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Worker -->|"push branch"| PRout
|
|
42
|
+
|
|
43
|
+
Proxy -->|"scraped"| Prom["local-prometheus-1\n127.0.0.1:9090 (loopback)\n24h retention"]
|
|
44
|
+
Prom -->|"query"| Graf["local-grafana-1\n127.0.0.1:3000 (loopback)\ndashboards: wardby-coding-proxy,\nwardby-coding-budget"]
|
|
45
|
+
end
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Key boundaries
|
|
49
|
+
|
|
50
|
+
- **Only one thing is reachable from outside this machine:** the HTTPS
|
|
51
|
+
tunnel into `wardby mcp:8080`. Postgres, coding-proxy, Prometheus, and
|
|
52
|
+
Grafana are all either fully private-network-only (`coding-proxy:9464`
|
|
53
|
+
has no `ports:` mapping at all) or explicitly loopback-bound
|
|
54
|
+
(`127.0.0.1:9090`, `127.0.0.1:3000`) — Grafana/Prometheus are not exposed
|
|
55
|
+
through the tunnel.
|
|
56
|
+
- **The coding worker never sees real API credentials.** `wardby-coding-proxy`
|
|
57
|
+
sits between it and OpenAI/Anthropic, injecting credentials and metering
|
|
58
|
+
tokens/cost — this is also where `/metrics` lives.
|
|
59
|
+
- **Two write paths into Postgres:** `wardby mcp` owns the agent/run/webhook
|
|
60
|
+
config tables directly; `coding-proxy` writes its own usage/cost ledger
|
|
61
|
+
directly during a run, which `wardby mcp` reconciles back into the `Run`
|
|
62
|
+
row once the container finishes (the "cap at the boundary, reconcile
|
|
63
|
+
after" pattern for opaque agent runs).
|
|
64
|
+
- **`wardby mcp` restarts don't affect observability, and vice versa.** The
|
|
65
|
+
control plane and metrics stack can be deployed and restarted independently.
|
|
66
|
+
|
|
67
|
+
## Where the worker actually runs
|
|
68
|
+
|
|
69
|
+
The diagram above shows `JOB_LAUNCHER=docker`, which is what this host uses.
|
|
70
|
+
The worker's execution backend is a seam (`WorkspaceJobLauncher`), and the
|
|
71
|
+
choice does not change any boundary above — the worker still holds no
|
|
72
|
+
credentials, still reaches only the proxy, and the proxy still owns the ledger.
|
|
73
|
+
|
|
74
|
+
| `JOB_LAUNCHER` | Worker runs in | Isolation |
|
|
75
|
+
| -------------- | -------------------------------- | ---------------------------------------------------- |
|
|
76
|
+
| `local` | a child process on this host | development only, no isolation |
|
|
77
|
+
| `docker` | a container on a per-run network | the diagram above |
|
|
78
|
+
| `kubernetes` | a pod in a namespace | per-run NetworkPolicy, attested pod, optional gVisor |
|
|
79
|
+
|
|
80
|
+
Under `kubernetes` the shape is the same with different nouns: the per-run
|
|
81
|
+
Docker network becomes a NetworkPolicy, the keeper and worker share a pod
|
|
82
|
+
instead of a volume, and the proxy is a Service rather than a container name.
|
|
83
|
+
Two things have no Docker equivalent. The pod read back from the API server is
|
|
84
|
+
compared field by field against the pod wardby built, and any difference fails
|
|
85
|
+
the run; and before the worker is released, the launcher proves the network
|
|
86
|
+
policy is actually being enforced, because a cluster accepts a policy whether
|
|
87
|
+
or not anything enforces it. See
|
|
88
|
+
[coding-worker-isolation.md](coding-worker-isolation.md) for the mechanics and
|
|
89
|
+
the [Kubernetes deployment guide](../deploy/kind-coding/README.md) for the local
|
|
90
|
+
and GKE Autopilot overlays.
|
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">Wardby icon</title>
|
|
3
|
+
<desc id="desc">A friendly helmeted guardian carrying a budget shield.</desc>
|
|
4
|
+
|
|
5
|
+
<circle cx="64" cy="64" r="58" fill="#071d3b"/>
|
|
6
|
+
<path d="M20 55C20 25 40 12 64 12s44 13 44 43v35H20Z" fill="#fffaf0"/>
|
|
7
|
+
<rect x="30" y="43" width="68" height="45" rx="18" fill="#0a2850"/>
|
|
8
|
+
<path d="M27 48Q64 18 101 48" fill="none" stroke="#c8aa70" stroke-width="10" stroke-linecap="round"/>
|
|
9
|
+
<path d="M64 7V53" fill="none" stroke="#c8aa70" stroke-width="11" stroke-linecap="round"/>
|
|
10
|
+
<path d="M44 65q7 10 14 0M70 65q7 10 14 0" fill="none" stroke="#4be6b3" stroke-width="6" stroke-linecap="round"/>
|
|
11
|
+
|
|
12
|
+
<path d="M78 76 108 86v18c0 12-10 19-30 24-20-5-30-12-30-24V86Z" fill="#071d3b" stroke="#fffaf0" stroke-width="5" stroke-linejoin="round"/>
|
|
13
|
+
<g transform="translate(78 105) scale(.72) translate(-78 -105)">
|
|
14
|
+
<path d="M89 91c-3-4-7-6-12-6-7 0-12 4-12 9 0 6 5 8 13 10 8 2 13 5 13 11 0 7-5 11-13 11-7 0-13-3-17-8M78 82v46" fill="none" stroke="#4be6b3" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
15
|
+
</g>
|
|
16
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1254 1254" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">Wardby robot mascot</title>
|
|
3
|
+
<desc id="desc">A friendly helmeted robot carrying a shield marked with a dollar sign.</desc>
|
|
4
|
+
<image width="1254" height="1254" href="wardby-mascot.png" xlink:href="wardby-mascot.png" preserveAspectRatio="xMidYMid meet"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="430" viewBox="0 0 1280 430" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">Wardby agent workflow</title>
|
|
3
|
+
<desc id="desc">Five stages show a request moving from Claude or Codex through MCP, governed execution in Wardby, and an outcome controlled by review policy.</desc>
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="background" x1="0" y1="0" x2="1" y2="1">
|
|
6
|
+
<stop offset="0" stop-color="#f7faff"/>
|
|
7
|
+
<stop offset="1" stop-color="#edf8f7"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
<linearGradient id="primary" x1="0" y1="0" x2="1" y2="1">
|
|
10
|
+
<stop offset="0" stop-color="#0f6bff"/>
|
|
11
|
+
<stop offset="1" stop-color="#0756d8"/>
|
|
12
|
+
</linearGradient>
|
|
13
|
+
<linearGradient id="success" x1="0" y1="0" x2="1" y2="1">
|
|
14
|
+
<stop offset="0" stop-color="#2de3a6"/>
|
|
15
|
+
<stop offset="1" stop-color="#11b981"/>
|
|
16
|
+
</linearGradient>
|
|
17
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="160%">
|
|
18
|
+
<feDropShadow dx="0" dy="5" stdDeviation="7" flood-color="#082850" flood-opacity="0.10"/>
|
|
19
|
+
</filter>
|
|
20
|
+
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
21
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c93b3"/>
|
|
22
|
+
</marker>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<rect x="1" y="1" width="1278" height="428" rx="28" fill="url(#background)" stroke="#dbe7f5" stroke-width="2"/>
|
|
26
|
+
|
|
27
|
+
<text x="48" y="48" fill="#0f6bff" font-family="Arial, Helvetica, sans-serif" font-size="13" font-weight="700" letter-spacing="2">FULL AGENT LIFECYCLE</text>
|
|
28
|
+
<text x="48" y="76" fill="#082850" font-family="Arial, Helvetica, sans-serif" font-size="24" font-weight="700">From a conversation to a governed, reviewable outcome</text>
|
|
29
|
+
|
|
30
|
+
<g filter="url(#shadow)">
|
|
31
|
+
<rect x="45" y="112" width="210" height="172" rx="18" fill="#ffffff" stroke="#bcd4f7" stroke-width="2"/>
|
|
32
|
+
<circle cx="75" cy="142" r="17" fill="#e8f1ff"/>
|
|
33
|
+
<text x="75" y="148" text-anchor="middle" fill="#0f6bff" font-family="Arial, Helvetica, sans-serif" font-size="15" font-weight="700">1</text>
|
|
34
|
+
<text x="103" y="147" fill="#0f6bff" font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" letter-spacing="1.5">ASK</text>
|
|
35
|
+
<text x="70" y="190" fill="#082850" font-family="Arial, Helvetica, sans-serif" font-size="21" font-weight="700">Claude or Codex</text>
|
|
36
|
+
<text x="70" y="220" fill="#52677f" font-family="Arial, Helvetica, sans-serif" font-size="14">Describe the outcome</text>
|
|
37
|
+
<text x="70" y="243" fill="#52677f" font-family="Arial, Helvetica, sans-serif" font-size="14">in natural language</text>
|
|
38
|
+
</g>
|
|
39
|
+
|
|
40
|
+
<path d="M 263 198 H 284" fill="none" stroke="#7c93b3" stroke-width="3" marker-end="url(#arrow)"/>
|
|
41
|
+
<text x="273" y="184" text-anchor="middle" fill="#637b98" font-family="Arial, Helvetica, sans-serif" font-size="11" font-weight="700">MCP</text>
|
|
42
|
+
|
|
43
|
+
<g filter="url(#shadow)">
|
|
44
|
+
<rect x="295" y="112" width="210" height="172" rx="18" fill="#ffffff" stroke="#bcd4f7" stroke-width="2"/>
|
|
45
|
+
<circle cx="325" cy="142" r="17" fill="#e8f1ff"/>
|
|
46
|
+
<text x="325" y="148" text-anchor="middle" fill="#0f6bff" font-family="Arial, Helvetica, sans-serif" font-size="15" font-weight="700">2</text>
|
|
47
|
+
<text x="353" y="147" fill="#0f6bff" font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" letter-spacing="1.5">DEFINE</text>
|
|
48
|
+
<text x="320" y="190" fill="#082850" font-family="Arial, Helvetica, sans-serif" font-size="21" font-weight="700">Agent blueprint</text>
|
|
49
|
+
<text x="320" y="220" fill="#52677f" font-family="Arial, Helvetica, sans-serif" font-size="14">Model • tools • schedule</text>
|
|
50
|
+
<text x="320" y="243" fill="#52677f" font-family="Arial, Helvetica, sans-serif" font-size="14">Sub-agents • outcome</text>
|
|
51
|
+
</g>
|
|
52
|
+
|
|
53
|
+
<path d="M 513 198 H 534" fill="none" stroke="#7c93b3" stroke-width="3" marker-end="url(#arrow)"/>
|
|
54
|
+
<text x="523" y="184" text-anchor="middle" fill="#637b98" font-family="Arial, Helvetica, sans-serif" font-size="11" font-weight="700">POLICY</text>
|
|
55
|
+
|
|
56
|
+
<g filter="url(#shadow)">
|
|
57
|
+
<rect x="545" y="112" width="210" height="172" rx="18" fill="url(#primary)"/>
|
|
58
|
+
<circle cx="575" cy="142" r="17" fill="#ffffff" fill-opacity="0.20"/>
|
|
59
|
+
<text x="575" y="148" text-anchor="middle" fill="#ffffff" font-family="Arial, Helvetica, sans-serif" font-size="15" font-weight="700">3</text>
|
|
60
|
+
<text x="603" y="147" fill="#dceaff" font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" letter-spacing="1.5">GOVERN</text>
|
|
61
|
+
<text x="570" y="190" fill="#ffffff" font-family="Arial, Helvetica, sans-serif" font-size="21" font-weight="700">Wardby</text>
|
|
62
|
+
<text x="570" y="220" fill="#e7f0ff" font-family="Arial, Helvetica, sans-serif" font-size="14">Budget • secrets • owner</text>
|
|
63
|
+
<text x="570" y="243" fill="#e7f0ff" font-family="Arial, Helvetica, sans-serif" font-size="14">Audit • cancellation</text>
|
|
64
|
+
</g>
|
|
65
|
+
|
|
66
|
+
<path d="M 763 198 H 784" fill="none" stroke="#7c93b3" stroke-width="3" marker-end="url(#arrow)"/>
|
|
67
|
+
<text x="773" y="184" text-anchor="middle" fill="#637b98" font-family="Arial, Helvetica, sans-serif" font-size="11" font-weight="700">RUN</text>
|
|
68
|
+
|
|
69
|
+
<g filter="url(#shadow)">
|
|
70
|
+
<rect x="795" y="112" width="210" height="172" rx="18" fill="#ffffff" stroke="#bcd4f7" stroke-width="2"/>
|
|
71
|
+
<circle cx="825" cy="142" r="17" fill="#e8f1ff"/>
|
|
72
|
+
<text x="825" y="148" text-anchor="middle" fill="#0f6bff" font-family="Arial, Helvetica, sans-serif" font-size="15" font-weight="700">4</text>
|
|
73
|
+
<text x="853" y="147" fill="#0f6bff" font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" letter-spacing="1.5">EXECUTE</text>
|
|
74
|
+
<text x="820" y="190" fill="#082850" font-family="Arial, Helvetica, sans-serif" font-size="21" font-weight="700">Isolated workers</text>
|
|
75
|
+
<text x="820" y="220" fill="#52677f" font-family="Arial, Helvetica, sans-serif" font-size="14">Native • Codex • Claude</text>
|
|
76
|
+
<text x="820" y="243" fill="#52677f" font-family="Arial, Helvetica, sans-serif" font-size="14">Bounded tools and access</text>
|
|
77
|
+
</g>
|
|
78
|
+
|
|
79
|
+
<path d="M 1013 198 H 1034" fill="none" stroke="#7c93b3" stroke-width="3" marker-end="url(#arrow)"/>
|
|
80
|
+
<text x="1023" y="184" text-anchor="middle" fill="#637b98" font-family="Arial, Helvetica, sans-serif" font-size="11" font-weight="700">RESULT</text>
|
|
81
|
+
|
|
82
|
+
<g filter="url(#shadow)">
|
|
83
|
+
<rect x="1045" y="112" width="190" height="172" rx="18" fill="#ffffff" stroke="#22c995" stroke-width="2"/>
|
|
84
|
+
<circle cx="1075" cy="142" r="17" fill="url(#success)"/>
|
|
85
|
+
<text x="1075" y="148" text-anchor="middle" fill="#ffffff" font-family="Arial, Helvetica, sans-serif" font-size="15" font-weight="700">5</text>
|
|
86
|
+
<text x="1103" y="147" fill="#09845f" font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" letter-spacing="1.5">REVIEW</text>
|
|
87
|
+
<text x="1070" y="190" fill="#082850" font-family="Arial, Helvetica, sans-serif" font-size="21" font-weight="700">Review policy</text>
|
|
88
|
+
<text x="1070" y="220" fill="#52677f" font-family="Arial, Helvetica, sans-serif" font-size="14">Agent or human review</text>
|
|
89
|
+
<text x="1070" y="243" fill="#09845f" font-family="Arial, Helvetica, sans-serif" font-size="14" font-weight="700">Authority stays explicit</text>
|
|
90
|
+
</g>
|
|
91
|
+
|
|
92
|
+
<rect x="45" y="324" width="1190" height="70" rx="16" fill="#082850"/>
|
|
93
|
+
<text x="72" y="351" fill="#70edc2" font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" letter-spacing="1.5">RUNS IN YOUR INFRASTRUCTURE</text>
|
|
94
|
+
<text x="72" y="378" fill="#ffffff" font-family="Arial, Helvetica, sans-serif" font-size="17" font-weight="700">Your cloud • Your credentials • Your operating boundary</text>
|
|
95
|
+
|
|
96
|
+
<g font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" text-anchor="middle">
|
|
97
|
+
<rect x="605" y="343" width="140" height="32" rx="16" fill="#ffffff" fill-opacity="0.11"/>
|
|
98
|
+
<text x="675" y="364" fill="#ffffff">Budget enforced</text>
|
|
99
|
+
<rect x="757" y="343" width="168" height="32" rx="16" fill="#ffffff" fill-opacity="0.11"/>
|
|
100
|
+
<text x="841" y="364" fill="#ffffff">Credentials separated</text>
|
|
101
|
+
<rect x="937" y="343" width="135" height="32" rx="16" fill="#ffffff" fill-opacity="0.11"/>
|
|
102
|
+
<text x="1005" y="364" fill="#ffffff">Runs observable</text>
|
|
103
|
+
<rect x="1084" y="343" width="125" height="32" rx="16" fill="#ffffff" fill-opacity="0.11"/>
|
|
104
|
+
<text x="1147" y="364" fill="#ffffff">Action policy</text>
|
|
105
|
+
</g>
|
|
106
|
+
</svg>
|