@wardby/cli 0.5.3 → 0.7.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 +33 -0
- package/README.md +25 -14
- package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
- package/dist/claude-coding-worker/context.d.ts +22 -0
- package/dist/claude-coding-worker/context.js +92 -0
- package/dist/claude-coding-worker/driver.d.ts +27 -3
- package/dist/claude-coding-worker/driver.js +161 -20
- package/dist/claude-coding-worker/main.js +34 -6
- package/dist/claude-coding-worker/sdk.js +25 -5
- package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
- package/dist/claude-coding-worker/tool-socket.js +111 -0
- package/dist/claude-coding-worker/transcript.d.ts +18 -0
- package/dist/claude-coding-worker/transcript.js +77 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +6 -2
- package/dist/cli-native-mode.d.ts +9 -0
- package/dist/cli-native-mode.js +20 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +161 -11
- package/dist/coding/claude-context.d.ts +45 -0
- package/dist/coding/claude-context.js +434 -0
- package/dist/coding/continuation-wording.d.ts +35 -0
- package/dist/coding/continuation-wording.js +73 -0
- package/dist/coding/linked-issue-note.d.ts +23 -0
- package/dist/coding/linked-issue-note.js +47 -0
- package/dist/coding/merge-wording.d.ts +28 -0
- package/dist/coding/merge-wording.js +78 -0
- package/dist/coding/pr-description-note.d.ts +9 -0
- package/dist/coding/pr-description-note.js +32 -0
- package/dist/coding/profile.d.ts +50 -118
- package/dist/coding/profile.js +51 -4
- package/dist/coding/protected-path-wording.d.ts +8 -0
- package/dist/coding/protected-path-wording.js +1 -1
- package/dist/coding/protocol.d.ts +292 -270
- package/dist/coding/protocol.js +322 -15
- package/dist/coding/redact.d.ts +3 -0
- package/dist/coding/redact.js +12 -0
- package/dist/coding/registry/allowlist.d.ts +12 -0
- package/dist/coding/registry/allowlist.js +14 -1
- package/dist/coding/registry/audit-mode.d.ts +153 -0
- package/dist/coding/registry/audit-mode.js +304 -0
- package/dist/coding/registry/lockfile-shared.d.ts +36 -0
- package/dist/coding/registry/lockfile-shared.js +128 -0
- package/dist/coding/registry/lockfiles.js +1 -1
- package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
- package/dist/coding/registry/npm-lockfile-formats.js +41 -0
- package/dist/coding/registry/npm-lockfile.d.ts +8 -4
- package/dist/coding/registry/npm-lockfile.js +4 -6
- package/dist/coding/registry/npm.js +78 -8
- package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
- package/dist/coding/registry/pnpm-lockfile.js +189 -0
- package/dist/coding/registry/pypi-plan.d.ts +50 -0
- package/dist/coding/registry/pypi-plan.js +406 -0
- package/dist/coding/registry/pypi-requirements.d.ts +58 -0
- package/dist/coding/registry/pypi-requirements.js +155 -0
- package/dist/coding/registry/pypi.d.ts +3 -27
- package/dist/coding/registry/pypi.js +40 -154
- package/dist/coding/registry/refusal-hints.d.ts +20 -0
- package/dist/coding/registry/refusal-hints.js +61 -0
- package/dist/coding/registry/refusal-wording.d.ts +11 -0
- package/dist/coding/registry/refusal-wording.js +56 -0
- package/dist/coding/registry/report.d.ts +70 -8
- package/dist/coding/registry/report.js +112 -5
- package/dist/coding/registry/types.d.ts +58 -8
- package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
- package/dist/coding/registry/yarn-lockfile.js +367 -0
- package/dist/coding/services/catalog.d.ts +37 -351
- package/dist/coding/transcript/claude-code.d.ts +13 -0
- package/dist/coding/transcript/claude-code.js +273 -0
- package/dist/coding/transcript/download-protocol.d.ts +30 -0
- package/dist/coding/transcript/download-protocol.js +18 -0
- package/dist/coding/transcript/format.d.ts +20 -0
- package/dist/coding/transcript/format.js +32 -0
- package/dist/coding/transcript/recorder.d.ts +51 -0
- package/dist/coding/transcript/recorder.js +225 -0
- package/dist/coding/transcript/resume/checkout.d.ts +31 -0
- package/dist/coding/transcript/resume/checkout.js +203 -0
- package/dist/coding/transcript/resume/command.d.ts +17 -0
- package/dist/coding/transcript/resume/command.js +176 -0
- package/dist/coding/transcript/resume/download.d.ts +20 -0
- package/dist/coding/transcript/resume/download.js +153 -0
- package/dist/coding/transcript/resume/launch.d.ts +38 -0
- package/dist/coding/transcript/resume/launch.js +128 -0
- package/dist/coding/transcript/resume/session-file.d.ts +13 -0
- package/dist/coding/transcript/resume/session-file.js +79 -0
- package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
- package/dist/coding/transcript/resume/stand-in.js +49 -0
- package/dist/coding-worker/artifact.d.ts +16 -3
- package/dist/coding-worker/artifact.js +5 -3
- package/dist/coding-worker/debug-trace.d.ts +6 -5
- package/dist/coding-worker/debug-trace.js +13 -18
- package/dist/coding-worker/dependency-cache.d.mts +229 -0
- package/dist/coding-worker/dependency-cache.mjs +2123 -0
- package/dist/coding-worker/driver.d.ts +4 -3
- package/dist/coding-worker/driver.js +118 -38
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- package/dist/coding-worker/sdk.d.ts +6 -0
- package/dist/coding-worker/sdk.js +1 -0
- package/dist/coding-worker/skills.d.ts +23 -0
- package/dist/coding-worker/skills.js +117 -0
- package/dist/coding-worker/task-note.d.ts +11 -0
- package/dist/coding-worker/task-note.js +13 -0
- package/dist/coding-worker/types.d.ts +13 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/github-allowed-accounts.d.ts +15 -0
- package/dist/config/github-allowed-accounts.js +36 -0
- package/dist/config/low-power.d.ts +12 -0
- package/dist/config/low-power.js +18 -0
- package/dist/config/mobile.d.ts +12 -0
- package/dist/config/mobile.js +18 -0
- package/dist/config/providers.d.ts +65 -3
- package/dist/config/providers.js +147 -11
- package/dist/config/test-simulators.d.ts +82 -0
- package/dist/config/test-simulators.js +305 -0
- package/dist/core/async-context.d.ts +2 -0
- package/dist/core/async-context.js +12 -0
- package/dist/core/budget-events.d.ts +108 -0
- package/dist/core/budget-events.js +346 -0
- package/dist/core/budget-groups.d.ts +50 -1
- package/dist/core/budget-groups.js +236 -27
- package/dist/core/budget-stopped-head.d.ts +46 -0
- package/dist/core/budget-stopped-head.js +81 -0
- package/dist/core/budget-topup.d.ts +51 -0
- package/dist/core/budget-topup.js +156 -0
- package/dist/core/budget-wording.d.ts +16 -2
- package/dist/core/budget-wording.js +40 -2
- package/dist/core/coding-queue.d.ts +2 -1
- package/dist/core/coding-queue.js +7 -0
- package/dist/core/cron.d.ts +19 -1
- package/dist/core/cron.js +17 -0
- package/dist/core/datastores.js +1 -1
- package/dist/core/db.d.ts +16 -6
- package/dist/core/db.js +12 -10
- package/dist/core/deferred-coding.d.ts +14 -0
- package/dist/core/deferred-coding.js +62 -0
- package/dist/core/delegation-child.d.ts +25 -0
- package/dist/core/delegation-child.js +37 -0
- package/dist/core/dispatch.d.ts +53 -0
- package/dist/core/dispatch.js +167 -57
- package/dist/core/engine-native.js +10 -6
- package/dist/core/error-code.d.ts +38 -0
- package/dist/core/error-code.js +168 -0
- package/dist/core/grants.d.ts +19 -6
- package/dist/core/grants.js +55 -6
- package/dist/core/host-events.d.ts +67 -5
- package/dist/core/host-events.js +571 -37
- package/dist/core/host-status.d.ts +85 -3
- package/dist/core/host-status.js +298 -20
- package/dist/core/issue-bridge.d.ts +50 -6
- package/dist/core/issue-bridge.js +151 -20
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +16 -11
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +68 -29
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/logger.js +14 -1
- package/dist/core/lost-run-children.d.ts +6 -0
- package/dist/core/lost-run-children.js +32 -0
- package/dist/core/mark-ready.d.ts +34 -0
- package/dist/core/mark-ready.js +152 -0
- package/dist/core/markdown-code.d.ts +8 -0
- package/dist/core/markdown-code.js +107 -0
- package/dist/core/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +130 -0
- package/dist/core/merge-order-check.js +343 -0
- package/dist/core/notification-dispatcher.d.ts +70 -0
- package/dist/core/notification-dispatcher.js +368 -0
- package/dist/core/notification-templates.d.ts +19 -0
- package/dist/core/notification-templates.js +139 -0
- package/dist/core/notifications.d.ts +10 -0
- package/dist/core/notifications.js +38 -0
- package/dist/core/pg-auth.d.ts +22 -0
- package/dist/core/pg-auth.js +152 -0
- package/dist/core/power-composition.d.ts +16 -0
- package/dist/core/power-composition.js +37 -0
- package/dist/core/power-idle.d.ts +14 -0
- package/dist/core/power-idle.js +30 -0
- package/dist/core/power.d.ts +71 -0
- package/dist/core/power.js +202 -0
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +8 -5
- package/dist/core/reconciler.js +37 -6
- package/dist/core/related-pull-requests.d.ts +59 -7
- package/dist/core/related-pull-requests.js +140 -25
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/repo-access.d.ts +15 -0
- package/dist/core/repo-access.js +66 -0
- package/dist/core/review-fix.d.ts +38 -1
- package/dist/core/review-fix.js +209 -7
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +23 -0
- package/dist/core/review-host-tools.js +156 -14
- package/dist/core/review-reads.d.ts +55 -0
- package/dist/core/review-reads.js +233 -0
- package/dist/core/run-status.d.ts +12 -0
- package/dist/core/run-status.js +12 -0
- package/dist/core/runner.d.ts +384 -5
- package/dist/core/runner.js +1244 -372
- package/dist/core/schedule-start.d.ts +12 -0
- package/dist/core/schedule-start.js +14 -0
- package/dist/core/secret-broker-config.d.ts +39 -0
- package/dist/core/secret-broker-config.js +112 -0
- package/dist/core/secret-guard.d.ts +46 -0
- package/dist/core/secret-guard.js +104 -0
- package/dist/core/secret-guarded-stores.d.ts +12 -0
- package/dist/core/secret-guarded-stores.js +41 -0
- package/dist/core/secret-spans.d.ts +50 -0
- package/dist/core/secret-spans.js +94 -0
- package/dist/core/secrets.d.ts +39 -4
- package/dist/core/secrets.js +148 -40
- package/dist/core/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/workflow-event-recorder.d.ts +14 -0
- package/dist/core/workflow-event-recorder.js +120 -0
- package/dist/core/workflow-events.d.ts +94 -0
- package/dist/core/workflow-events.js +48 -0
- package/dist/core/workflow-run-events.d.ts +18 -0
- package/dist/core/workflow-run-events.js +75 -0
- package/dist/core/zod-json-schema.d.ts +4 -0
- package/dist/core/zod-json-schema.js +39 -0
- package/dist/core/zod3-window.d.ts +35 -0
- package/dist/core/zod3-window.js +124 -0
- package/dist/generated/prisma/browser.d.ts +92 -3
- package/dist/generated/prisma/client.d.ts +92 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +364 -54
- package/dist/generated/prisma/enums.d.ts +37 -0
- package/dist/generated/prisma/enums.js +31 -0
- package/dist/generated/prisma/internal/class.d.ts +132 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1332 -142
- package/dist/generated/prisma/internal/prismaNamespace.js +227 -5
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +234 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +227 -5
- package/dist/generated/prisma/models/Agent.d.ts +464 -7
- package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +301 -1
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
- package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
- package/dist/generated/prisma/models/CodingRun.d.ts +1841 -1
- package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
- package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
- package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
- package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1713 -0
- package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1551 -0
- package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
- package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
- package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
- package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
- package/dist/generated/prisma/models/NotificationChannel.js +1 -0
- package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
- package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
- package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
- package/dist/generated/prisma/models/NotificationThread.js +1 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
- package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
- package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
- package/dist/generated/prisma/models/Run.d.ts +1619 -58
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +37 -1
- package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
- package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
- package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
- package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
- package/dist/generated/prisma/models.d.ts +12 -0
- package/dist/help/build.js +4 -2
- package/dist/help/catalog.d.ts +1 -1
- package/dist/help/catalog.js +31 -6
- package/dist/help-index.json +2584 -146
- package/dist/import/create.js +49 -3
- package/dist/import/neutral-schema.d.ts +50 -277
- package/dist/import/neutral-schema.js +7 -4
- package/dist/knowledge/check.d.ts +1 -1
- package/dist/knowledge/cli.d.ts +11 -1
- package/dist/knowledge/cli.js +37 -4
- package/dist/knowledge/concept.d.ts +3 -19
- package/dist/knowledge/location.d.ts +31 -0
- package/dist/knowledge/location.js +78 -0
- package/dist/mcp/auth/access.d.ts +11 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/ownership.d.ts +7 -7
- package/dist/mcp/auth/repo-authorization.js +14 -0
- package/dist/mcp/auth/resource-server.d.ts +2 -1
- package/dist/mcp/auth/resource-server.js +7 -2
- package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/browser.js +19 -6
- package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
- package/dist/mcp/context.d.ts +6 -0
- package/dist/mcp/host-events/github-ingress.d.ts +25 -1
- package/dist/mcp/host-events/github-ingress.js +70 -1
- package/dist/mcp/index.d.ts +19 -0
- package/dist/mcp/index.js +117 -20
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +33 -14
- package/dist/mcp/tools/agents.d.ts +4 -0
- package/dist/mcp/tools/agents.js +277 -24
- package/dist/mcp/tools/datastore.js +17 -8
- package/dist/mcp/tools/grants.js +9 -3
- package/dist/mcp/tools/memory.js +11 -1
- package/dist/mcp/tools/notification-channels.d.ts +2 -0
- package/dist/mcp/tools/notification-channels.js +293 -0
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/power.d.ts +2 -0
- package/dist/mcp/tools/power.js +77 -0
- package/dist/mcp/tools/repositories.js +18 -5
- package/dist/mcp/tools/run-access.d.ts +16 -0
- package/dist/mcp/tools/run-access.js +25 -0
- package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
- package/dist/mcp/tools/run-transcript-download.js +129 -0
- package/dist/mcp/tools/run-transcript.d.ts +19 -0
- package/dist/mcp/tools/run-transcript.js +70 -0
- package/dist/mcp/tools/runs.d.ts +0 -6
- package/dist/mcp/tools/runs.js +41 -14
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
- package/dist/mcp/tools/secret-broker-compat.js +23 -0
- package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
- package/dist/mcp/tools/secret-elicitation-form.js +205 -10
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -54
- package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
- package/dist/mcp/tools/secret-elicitation.js +110 -12
- package/dist/mcp/tools/secrets.js +186 -9
- package/dist/mcp/tools/stop-run.d.ts +2 -0
- package/dist/mcp/tools/stop-run.js +82 -0
- package/dist/mcp/tools/subagents.js +2 -2
- package/dist/mcp/tools/tools.d.ts +2 -2
- package/dist/mcp/tools/tools.js +47 -11
- package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
- package/dist/mcp/transport/stdio-link-host.js +67 -0
- package/dist/mcp/transport/streamable-http.d.ts +13 -0
- package/dist/mcp/transport/streamable-http.js +41 -1
- package/dist/native-worker/composition.d.ts +23 -0
- package/dist/native-worker/composition.js +77 -0
- package/dist/native-worker/docker-isolation.d.ts +65 -0
- package/dist/native-worker/docker-isolation.js +183 -0
- package/dist/native-worker/docker-launcher.d.ts +110 -0
- package/dist/native-worker/docker-launcher.js +297 -0
- package/dist/native-worker/gateway-server.d.ts +77 -0
- package/dist/native-worker/gateway-server.js +412 -0
- package/dist/native-worker/gateway.d.ts +70 -0
- package/dist/native-worker/gateway.js +263 -0
- package/dist/native-worker/http-server.d.ts +24 -0
- package/dist/native-worker/http-server.js +113 -0
- package/dist/native-worker/http-transport.d.ts +17 -0
- package/dist/native-worker/http-transport.js +88 -0
- package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
- package/dist/native-worker/kubernetes-isolation.js +218 -0
- package/dist/native-worker/kubernetes-launcher.d.ts +106 -0
- package/dist/native-worker/kubernetes-launcher.js +375 -0
- package/dist/native-worker/launch.d.ts +62 -0
- package/dist/native-worker/launch.js +49 -0
- package/dist/native-worker/ledger.d.ts +125 -0
- package/dist/native-worker/ledger.js +245 -0
- package/dist/native-worker/loopback.d.ts +12 -0
- package/dist/native-worker/loopback.js +44 -0
- package/dist/native-worker/main.d.ts +8 -0
- package/dist/native-worker/main.js +85 -0
- package/dist/native-worker/protocol.d.ts +296 -0
- package/dist/native-worker/protocol.js +246 -0
- package/dist/native-worker/sandbox-executor.d.ts +83 -0
- package/dist/native-worker/sandbox-executor.js +284 -0
- package/dist/native-worker/stderr-redaction.d.ts +77 -0
- package/dist/native-worker/stderr-redaction.js +237 -0
- package/dist/native-worker/stdio.d.ts +29 -0
- package/dist/native-worker/stdio.js +189 -0
- package/dist/native-worker/warm-delivery.d.ts +16 -0
- package/dist/native-worker/warm-delivery.js +33 -0
- package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
- package/dist/native-worker/warm-pool-ledger.js +73 -0
- package/dist/native-worker/warm-pool.d.ts +107 -0
- package/dist/native-worker/warm-pool.js +283 -0
- package/dist/native-worker/worker.d.ts +17 -0
- package/dist/native-worker/worker.js +141 -0
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/authorization-server.d.ts +3 -0
- package/dist/providers/auth/index.js +2 -0
- package/dist/providers/auth/self-hosted.d.ts +14 -2
- package/dist/providers/auth/self-hosted.js +54 -4
- package/dist/providers/chat/fake.d.ts +46 -0
- package/dist/providers/chat/fake.js +39 -0
- package/dist/providers/chat/index.d.ts +4 -0
- package/dist/providers/chat/index.js +8 -0
- package/dist/providers/chat/slack.d.ts +37 -0
- package/dist/providers/chat/slack.js +105 -0
- package/dist/providers/chat/types.d.ts +42 -0
- package/dist/providers/chat/types.js +19 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
- package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
- package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
- package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
- package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
- package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
- package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
- package/dist/providers/coding-proxy/hold.d.ts +32 -0
- package/dist/providers/coding-proxy/hold.js +86 -0
- package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
- package/dist/providers/coding-proxy/interrupted.js +104 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +15 -2
- package/dist/providers/coding-proxy/memory-ledger.js +84 -8
- package/dist/providers/coding-proxy/metering.d.ts +16 -0
- package/dist/providers/coding-proxy/metering.js +27 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -2
- package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
- package/dist/providers/coding-proxy/proxy.d.ts +14 -1
- package/dist/providers/coding-proxy/proxy.js +166 -14
- package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
- package/dist/providers/coding-proxy/registry/audit.js +94 -17
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
- package/dist/providers/coding-proxy/registry/plan.js +201 -48
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
- package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
- package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
- package/dist/providers/coding-proxy/registry/service.js +579 -112
- package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
- package/dist/providers/coding-proxy/registry/store.js +54 -1
- package/dist/providers/coding-proxy/runtime.d.ts +4 -0
- package/dist/providers/coding-proxy/runtime.js +78 -16
- package/dist/providers/coding-proxy/server.d.ts +6 -1
- package/dist/providers/coding-proxy/server.js +45 -1
- package/dist/providers/coding-proxy/types.d.ts +65 -1
- package/dist/providers/datastore/types.d.ts +5 -0
- package/dist/providers/engine/types.d.ts +36 -2
- package/dist/providers/engine/types.js +39 -0
- package/dist/providers/executor/composition.d.ts +31 -1
- package/dist/providers/executor/composition.js +81 -8
- package/dist/providers/executor/container.d.ts +385 -9
- package/dist/providers/executor/container.js +1234 -99
- package/dist/providers/executor/dbos-status.d.ts +31 -0
- package/dist/providers/executor/dbos-status.js +64 -0
- package/dist/providers/executor/dbos.d.ts +91 -0
- package/dist/providers/executor/dbos.js +319 -26
- package/dist/providers/executor/deferred.d.ts +44 -0
- package/dist/providers/executor/deferred.js +100 -0
- package/dist/providers/executor/in-process.d.ts +9 -1
- package/dist/providers/executor/in-process.js +14 -4
- package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
- package/dist/providers/executor/linked-issue-reader.js +30 -0
- package/dist/providers/executor/routing.d.ts +39 -10
- package/dist/providers/executor/routing.js +77 -32
- package/dist/providers/executor/types.d.ts +25 -0
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/issue-tracker/types.d.ts +17 -0
- package/dist/providers/issue-tracker/types.js +39 -1
- package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
- package/dist/providers/jobs/claude-tool-setup.js +5 -2
- package/dist/providers/jobs/docker-isolation.d.ts +8 -0
- package/dist/providers/jobs/docker-isolation.js +17 -0
- package/dist/providers/jobs/docker.d.ts +1 -0
- package/dist/providers/jobs/docker.js +29 -4
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +23 -2
- package/dist/providers/jobs/fake-kubernetes-api.js +45 -1
- package/dist/providers/jobs/kubernetes-api.d.ts +25 -1
- package/dist/providers/jobs/kubernetes-api.js +17 -0
- package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
- package/dist/providers/jobs/kubernetes-client.js +61 -3
- package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
- package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
- package/dist/providers/jobs/kubernetes-isolation.js +23 -1
- package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
- package/dist/providers/jobs/kubernetes-platform.js +38 -1
- package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
- package/dist/providers/jobs/kubernetes-preflight.js +4 -2
- package/dist/providers/jobs/kubernetes.d.ts +42 -2
- package/dist/providers/jobs/kubernetes.js +178 -19
- package/dist/providers/jobs/metadata-probes.d.ts +11 -0
- package/dist/providers/jobs/metadata-probes.js +13 -0
- package/dist/providers/jobs/types.d.ts +42 -0
- package/dist/providers/jobs/types.js +13 -1
- package/dist/providers/llm/anthropic.js +5 -1
- package/dist/providers/llm/bedrock.d.ts +0 -12
- package/dist/providers/llm/bedrock.js +4 -0
- package/dist/providers/llm/claude-messages.d.ts +3 -1
- package/dist/providers/llm/claude-messages.js +4 -1
- package/dist/providers/llm/claude-provider.d.ts +2 -2
- package/dist/providers/llm/claude-provider.js +2 -2
- package/dist/providers/llm/openai.d.ts +2 -2
- package/dist/providers/llm/openai.js +6 -2
- package/dist/providers/llm/routing.d.ts +2 -2
- package/dist/providers/llm/routing.js +2 -2
- package/dist/providers/llm/types.d.ts +12 -2
- package/dist/providers/review-host/github-events.d.ts +9 -1
- package/dist/providers/review-host/github-events.js +34 -12
- package/dist/providers/review-host/github.d.ts +39 -2
- package/dist/providers/review-host/github.js +274 -29
- package/dist/providers/review-host/local.d.ts +8 -4
- package/dist/providers/review-host/local.js +49 -31
- package/dist/providers/review-host/patch-pages.d.ts +41 -0
- package/dist/providers/review-host/patch-pages.js +176 -0
- package/dist/providers/review-host/review-format.d.ts +19 -1
- package/dist/providers/review-host/review-format.js +38 -7
- package/dist/providers/review-host/types.d.ts +157 -2
- package/dist/providers/review-host/types.js +8 -0
- package/dist/providers/storage/gcs.d.ts +63 -0
- package/dist/providers/storage/gcs.js +69 -0
- package/dist/providers/storage/index.d.ts +15 -0
- package/dist/providers/storage/index.js +14 -0
- package/dist/providers/storage/local.d.ts +24 -0
- package/dist/providers/storage/local.js +92 -0
- package/dist/providers/storage/meter.d.ts +14 -0
- package/dist/providers/storage/meter.js +34 -0
- package/dist/providers/storage/s3.d.ts +41 -0
- package/dist/providers/storage/s3.js +107 -0
- package/dist/providers/storage/types.d.ts +37 -3
- package/dist/providers/storage/types.js +21 -4
- package/dist/providers/vcs/git.d.ts +33 -2
- package/dist/providers/vcs/git.js +324 -22
- package/dist/providers/vcs/github-remote.d.ts +26 -3
- package/dist/providers/vcs/github-remote.js +124 -14
- package/dist/providers/vcs/github.d.ts +246 -12
- package/dist/providers/vcs/github.js +521 -61
- package/dist/providers/vcs/index.js +8 -1
- package/dist/providers/vcs/pr-description.d.ts +127 -0
- package/dist/providers/vcs/pr-description.js +270 -0
- package/dist/providers/vcs/remote.d.ts +33 -1
- package/dist/providers/vcs/routing.d.ts +4 -2
- package/dist/providers/vcs/routing.js +6 -0
- package/dist/providers/vcs/types.d.ts +80 -3
- package/dist/quickstart/coding-seed.d.ts +21 -3
- package/dist/quickstart/coding-seed.js +283 -3
- package/dist/quickstart/images.d.ts +2 -0
- package/dist/quickstart/images.js +7 -1
- package/dist/quickstart/reviewer-prompt.d.ts +1 -1
- package/dist/quickstart/reviewer-prompt.js +6 -6
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/brokered-fetch.d.ts +23 -0
- package/dist/sandbox/brokered-fetch.js +37 -0
- package/dist/sandbox/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +35 -0
- package/dist/sandbox/host-functions.js +150 -91
- package/dist/sandbox/prelude.js +7 -1
- package/dist/sandbox/run-in-sandbox.d.ts +19 -0
- package/dist/sandbox/run-in-sandbox.js +28 -10
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +3 -1
- package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
- package/dist/sandbox/secret-broker-sigv4.js +49 -0
- package/dist/sandbox/secret-broker.d.ts +34 -0
- package/dist/sandbox/secret-broker.js +161 -0
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/user-tool.d.ts +14 -0
- package/dist/sandbox/user-tool.js +32 -0
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +25 -0
- package/dist/viewer/api-schema.d.ts +372 -2454
- package/dist/viewer/api-schema.js +29 -0
- package/dist/viewer/build-schemas.js +10 -3
- package/dist/viewer/event-bus.d.ts +6 -0
- package/dist/viewer/event-bus.js +16 -7
- package/dist/viewer/graph.d.ts +5 -2
- package/dist/viewer/graph.js +7 -2
- package/dist/viewer/http.d.ts +0 -1
- package/dist/viewer/http.js +2 -2
- package/dist/viewer/infra.js +25 -2
- package/dist/viewer/limits.d.ts +4 -0
- package/dist/viewer/limits.js +4 -0
- package/dist/viewer/openapi.d.ts +15 -0
- package/dist/viewer/openapi.js +170 -0
- package/dist/wardby-bin.js +10 -0
- package/docs/README.md +7 -0
- package/docs/agent-recipes.md +114 -27
- package/docs/architecture-runtime.md +16 -1
- package/docs/code-review-agents.md +689 -45
- package/docs/coding-agent-setup.md +602 -12
- package/docs/coding-packages.md +1037 -92
- package/docs/coding-services.md +30 -13
- package/docs/coding-worker-byo-images.md +218 -6
- package/docs/coding-worker-isolation.md +173 -44
- package/docs/getting-started-gke.md +332 -129
- package/docs/getting-started-identity-provider.md +31 -11
- package/docs/getting-started.md +14 -4
- package/docs/jira-agents.md +22 -9
- package/docs/knowledge/blob-not-found-semantics.md +41 -0
- package/docs/knowledge/bounded-file-descriptor.md +52 -0
- package/docs/knowledge/delegation-admission-slots.md +52 -0
- package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
- package/docs/knowledge/import-rename-target.md +52 -0
- package/docs/knowledge/index.md +57 -0
- package/docs/knowledge/log.md +9 -0
- package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
- package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
- package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
- package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
- package/docs/knowledge/overview-cli.md +74 -0
- package/docs/knowledge/overview-coding-proxy.md +72 -0
- package/docs/knowledge/overview-coding.md +72 -0
- package/docs/knowledge/overview-config.md +60 -0
- package/docs/knowledge/overview-core.md +72 -0
- package/docs/knowledge/overview-deploy.md +83 -0
- package/docs/knowledge/overview-mcp.md +61 -0
- package/docs/knowledge/overview-prisma.md +72 -0
- package/docs/knowledge/overview-providers.md +89 -0
- package/docs/knowledge/overview-sandbox.md +83 -0
- package/docs/knowledge/overview-surfaces.md +83 -0
- package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
- package/docs/knowledge/proxy-settlement-projections.md +41 -0
- package/docs/knowledge/run-pricing-first-writer.md +43 -0
- package/docs/knowledge/schedule-claim-transaction.md +41 -0
- package/docs/knowledge/secret-entry-replica-contract.md +52 -0
- package/docs/knowledge/terminal-run-first-writer.md +41 -0
- package/docs/knowledge/transactional-agent-authorization.md +52 -0
- package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
- package/docs/knowledge/warm-input-publication.md +30 -0
- package/docs/knowledge/workspace-staging-failure.md +54 -0
- package/docs/knowledge.md +54 -14
- package/docs/native-sandbox.md +731 -0
- package/docs/observability.md +4 -0
- package/docs/release-verification.md +9 -0
- package/docs/security-deployment.md +146 -14
- package/docs/slack-notifications.md +268 -0
- package/docs/tool-secrets.md +284 -0
- package/docs/viewer-api.md +46 -5
- package/docs/viewer-api.openapi.yml +1404 -0
- package/help/admin-viewer.md +29 -3
- package/help/agent-recipes.md +27 -0
- package/help/architecture-agent.md +11 -6
- package/help/brokered-secrets.md +79 -0
- package/help/build-claude-code-image.md +131 -0
- package/help/build-worker-image.md +6 -7
- package/help/builder-agent.md +19 -6
- package/help/code-review-agents.md +243 -10
- package/help/coding-packages.md +156 -6
- package/help/cost-attribution.md +9 -5
- package/help/creating-agents.md +14 -1
- package/help/dependency-cache.md +143 -0
- package/help/deploy-gke.md +23 -9
- package/help/deployment-targets.md +25 -14
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-provider-not-configured.md +2 -2
- package/help/errors/coding-stream-quota-exceeded.md +33 -0
- package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
- package/help/errors/continuation-closed.md +9 -12
- package/help/errors/database-auth-invalid.md +28 -0
- package/help/errors/delegation-conflict.md +24 -0
- package/help/errors/file-list-truncated.md +45 -0
- package/help/errors/full-read-required.md +49 -0
- package/help/errors/github-account-not-allowed.md +29 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/low-power-disabled.md +29 -0
- package/help/errors/low-power-scale-forbidden.md +35 -0
- package/help/errors/low-power-wake-timeout.md +30 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/mobile-disabled.md +31 -0
- package/help/errors/native-sandbox-capacity.md +22 -0
- package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
- package/help/errors/native-sandbox-docker-failed.md +20 -0
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
- package/help/errors/native-sandbox-image-not-pinned.md +19 -0
- package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-network-unenforced.md +22 -0
- package/help/errors/native-sandbox-requires-catalog.md +31 -0
- package/help/errors/native-sandbox-unavailable.md +19 -0
- package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
- package/help/errors/native-sandbox-worker-exited.md +21 -0
- package/help/errors/native-sandbox-worker-lost.md +20 -0
- package/help/errors/native-sandbox-worker-unready.md +22 -0
- package/help/errors/package-not-allowed-pending.md +52 -0
- package/help/errors/package-not-allowed.md +51 -0
- package/help/errors/package-refusals.md +43 -0
- package/help/errors/patch-cursor-malformed.md +31 -0
- package/help/errors/run-lost.md +39 -0
- package/help/errors/run-transcript-download.md +44 -0
- package/help/errors/secret-broker-body-invalid.md +26 -0
- package/help/errors/secret-broker-changed.md +20 -0
- package/help/errors/secret-broker-config-invalid.md +30 -0
- package/help/errors/secret-broker-conflict.md +27 -0
- package/help/errors/secret-broker-destination-denied.md +28 -0
- package/help/errors/secret-broker-value-invalid.md +28 -0
- package/help/errors/secret-brokered.md +24 -0
- package/help/errors/secret-in-value.md +69 -0
- package/help/errors/secret-not-brokered.md +25 -0
- package/help/errors/slack-auth-failed.md +48 -0
- package/help/errors/slack-channel-unreachable.md +39 -0
- package/help/errors/slack-not-configured.md +33 -0
- package/help/errors/target-merge.md +40 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/getting-started.md +4 -5
- package/help/github-app-setup.md +132 -0
- package/help/github.md +40 -1
- package/help/identity-and-access.md +7 -1
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +3 -4
- package/help/low-power-mode.md +131 -0
- package/help/merge-order-check.md +122 -0
- package/help/mobile-app.md +54 -0
- package/help/native-capabilities.md +29 -1
- package/help/native-sandbox.md +150 -0
- package/help/observability.md +8 -0
- package/help/operating-agents.md +5 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +80 -16
- package/help/repo-instructions-and-skills.md +91 -0
- package/help/resume-runs-locally.md +131 -0
- package/help/review-fix-rounds.md +43 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +76 -0
- package/help/status-comments.md +31 -0
- package/help/stop-run.md +58 -0
- package/help/troubleshooting/budgets.md +28 -0
- package/help/troubleshooting/coding-workers.md +99 -7
- package/package.json +27 -13
- package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
- package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
- package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
- package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
- package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
- package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
- package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
- package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
- package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
- package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
- package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
- package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
- package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
- package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
- package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
- package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
- package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
- package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
- package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
- package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
- package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
- package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
- package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
- package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
- package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
- package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
- package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
- package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
- package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
- package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
- package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
- package/prisma/schema.prisma +631 -146
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KubernetesAlreadyExistsError, KubernetesConflictError, KubernetesNotFoundError, } from "./kubernetes-api.js";
|
|
1
|
+
import { KubernetesAlreadyExistsError, KubernetesConflictError, KubernetesForbiddenError, KubernetesNotFoundError, } from "./kubernetes-api.js";
|
|
2
2
|
/** In-memory KubernetesApi for unit tests. Tests drive pod status and exec behavior directly. */
|
|
3
3
|
export class FakeKubernetesApi {
|
|
4
4
|
objects = new Map();
|
|
@@ -13,6 +13,15 @@ export class FakeKubernetesApi {
|
|
|
13
13
|
};
|
|
14
14
|
/** The admission chain a dry-run create runs through. Default: echo the pod back unchanged. */
|
|
15
15
|
onDryRunCreatePod = async (_namespace, body) => body;
|
|
16
|
+
/** Runs at the start of every pod create; tests throw KubernetesQuotaExceededError (or anything) from it. */
|
|
17
|
+
onCreatePod = async () => { };
|
|
18
|
+
deploymentPatches = [];
|
|
19
|
+
/** Deployment names whose patch throws KubernetesForbiddenError. */
|
|
20
|
+
forbidden = new Set();
|
|
21
|
+
/** "deployment/<name>" or "endpoints/<name>" keys whose read throws KubernetesForbiddenError. */
|
|
22
|
+
forbiddenReads = new Set();
|
|
23
|
+
/** "verb/resource/name" keys canI answers false for. */
|
|
24
|
+
accessDenied = new Set();
|
|
16
25
|
logs = new Map();
|
|
17
26
|
/** What readApiServerVersion reports; tests that care about provenance set it. */
|
|
18
27
|
apiServerVersion = "v1.33.0";
|
|
@@ -76,6 +85,7 @@ export class FakeKubernetesApi {
|
|
|
76
85
|
this.delete("secret", namespace, name);
|
|
77
86
|
}
|
|
78
87
|
async createPod(namespace, body) {
|
|
88
|
+
await this.onCreatePod(namespace, body);
|
|
79
89
|
return this.create("pod", namespace, body);
|
|
80
90
|
}
|
|
81
91
|
/**
|
|
@@ -95,6 +105,14 @@ export class FakeKubernetesApi {
|
|
|
95
105
|
async readPod(namespace, name) {
|
|
96
106
|
return this.read("pod", namespace, name);
|
|
97
107
|
}
|
|
108
|
+
/** Matches `key=value[,key=value]` selectors against stored pods' labels. */
|
|
109
|
+
async listPods(namespace, labelSelector) {
|
|
110
|
+
const wanted = labelSelector.split(",").map((pair) => pair.split("="));
|
|
111
|
+
return [...this.objects.entries()]
|
|
112
|
+
.filter(([key]) => key.startsWith(`pod/${namespace}/`))
|
|
113
|
+
.map(([, pod]) => structuredClone(pod))
|
|
114
|
+
.filter((pod) => wanted.every(([k, v]) => pod.metadata?.labels?.[k] === v));
|
|
115
|
+
}
|
|
98
116
|
async deletePod(namespace, name, gracePeriodSeconds) {
|
|
99
117
|
this.deletedPods.push({ name, gracePeriodSeconds });
|
|
100
118
|
this.delete("pod", namespace, name);
|
|
@@ -112,11 +130,37 @@ export class FakeKubernetesApi {
|
|
|
112
130
|
return this.read("service", namespace, name);
|
|
113
131
|
}
|
|
114
132
|
async readEndpoints(namespace, name) {
|
|
133
|
+
if (this.forbiddenReads.has(`endpoints/${name}`))
|
|
134
|
+
throw new KubernetesForbiddenError(this.key("endpoints", namespace, name));
|
|
115
135
|
return this.read("endpoints", namespace, name);
|
|
116
136
|
}
|
|
117
137
|
async readResourceQuota(namespace, name) {
|
|
118
138
|
return this.read("resourcequota", namespace, name);
|
|
119
139
|
}
|
|
140
|
+
async readDeployment(namespace, name) {
|
|
141
|
+
if (this.forbiddenReads.has(`deployment/${name}`))
|
|
142
|
+
throw new KubernetesForbiddenError(this.key("deployment", namespace, name));
|
|
143
|
+
return this.read("deployment", namespace, name);
|
|
144
|
+
}
|
|
145
|
+
async patchDeployment(namespace, name, patch) {
|
|
146
|
+
if (this.forbidden.has(name))
|
|
147
|
+
throw new KubernetesForbiddenError(this.key("deployment", namespace, name));
|
|
148
|
+
const key = this.key("deployment", namespace, name);
|
|
149
|
+
const current = this.objects.get(key);
|
|
150
|
+
if (!current)
|
|
151
|
+
throw new KubernetesNotFoundError(key);
|
|
152
|
+
const metadata = { ...current.metadata, resourceVersion: String(++this.version) };
|
|
153
|
+
if (patch.annotations)
|
|
154
|
+
metadata.annotations = { ...current.metadata?.annotations, ...patch.annotations };
|
|
155
|
+
const next = { ...current, metadata };
|
|
156
|
+
if (patch.replicas !== undefined)
|
|
157
|
+
next.spec = { selector: {}, template: {}, ...current.spec, replicas: patch.replicas };
|
|
158
|
+
this.objects.set(key, next);
|
|
159
|
+
this.deploymentPatches.push({ name, replicas: patch.replicas, annotations: patch.annotations });
|
|
160
|
+
}
|
|
161
|
+
async canI(_namespace, verb, _group, resource, name) {
|
|
162
|
+
return !this.accessDenied.has(`${verb}/${resource}/${name}`);
|
|
163
|
+
}
|
|
120
164
|
async readApiServerVersion() {
|
|
121
165
|
return this.apiServerVersion;
|
|
122
166
|
}
|
|
@@ -3,11 +3,23 @@
|
|
|
3
3
|
* so every launcher behavior is unit-tested against FakeKubernetesApi and
|
|
4
4
|
* re-proven against a real cluster by kubernetes.integration.test.ts.
|
|
5
5
|
*/
|
|
6
|
-
import type { V1ConfigMap, V1Endpoints, V1NetworkPolicy, V1Pod, V1ResourceQuota, V1Secret, V1Service } from "@kubernetes/client-node";
|
|
6
|
+
import type { V1ConfigMap, V1Deployment, V1Endpoints, V1NetworkPolicy, V1Pod, V1ResourceQuota, V1Secret, V1Service } from "@kubernetes/client-node";
|
|
7
7
|
import type { Readable, Writable } from "node:stream";
|
|
8
8
|
export declare class KubernetesNotFoundError extends Error {
|
|
9
9
|
constructor(message?: string);
|
|
10
10
|
}
|
|
11
|
+
/** The caller's identity lacks RBAC permission for the request (HTTP 403). */
|
|
12
|
+
export declare class KubernetesForbiddenError extends Error {
|
|
13
|
+
constructor(message?: string, options?: ErrorOptions);
|
|
14
|
+
}
|
|
15
|
+
/** A create the namespace ResourceQuota refused (HTTP 403 "exceeded quota"). */
|
|
16
|
+
export declare class KubernetesQuotaExceededError extends Error {
|
|
17
|
+
/** The refusing quota's name as the API server worded it; unvalidated, and nothing else of the refusal is kept. */
|
|
18
|
+
readonly quotaName?: string;
|
|
19
|
+
constructor(message?: string, options?: ErrorOptions & {
|
|
20
|
+
quotaName?: string;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
11
23
|
/** Stale resourceVersion on replace. */
|
|
12
24
|
export declare class KubernetesConflictError extends Error {
|
|
13
25
|
constructor(message?: string);
|
|
@@ -36,6 +48,8 @@ export interface KubernetesApi {
|
|
|
36
48
|
*/
|
|
37
49
|
dryRunCreatePod(namespace: string, body: V1Pod): Promise<V1Pod>;
|
|
38
50
|
readPod(namespace: string, name: string): Promise<V1Pod | undefined>;
|
|
51
|
+
/** Lists pods in one namespace matching a label selector (e.g. the native sandbox janitor's). */
|
|
52
|
+
listPods(namespace: string, labelSelector: string): Promise<V1Pod[]>;
|
|
39
53
|
deletePod(namespace: string, name: string, gracePeriodSeconds: number): Promise<void>;
|
|
40
54
|
createNetworkPolicy(namespace: string, body: V1NetworkPolicy): Promise<V1NetworkPolicy>;
|
|
41
55
|
readNetworkPolicy(namespace: string, name: string): Promise<V1NetworkPolicy | undefined>;
|
|
@@ -44,11 +58,21 @@ export interface KubernetesApi {
|
|
|
44
58
|
/**
|
|
45
59
|
* Reads a Service's Endpoints by name. EndpointSlice is the durable successor to this core/v1
|
|
46
60
|
* resource (migrating to it is a follow-up); Endpoints is read by name so RBAC stays one object wide.
|
|
61
|
+
* Undefined when missing; throws KubernetesForbiddenError on 403.
|
|
47
62
|
*/
|
|
48
63
|
readEndpoints(namespace: string, name: string): Promise<V1Endpoints | undefined>;
|
|
49
64
|
/** Reads one ResourceQuota by name (its status carries hard and used), for the launcher's capacity check. */
|
|
50
65
|
readResourceQuota(namespace: string, name: string): Promise<V1ResourceQuota | undefined>;
|
|
51
66
|
readNamespace(name: string): Promise<boolean>;
|
|
67
|
+
/** Undefined when missing; throws KubernetesForbiddenError on 403. */
|
|
68
|
+
readDeployment(namespace: string, name: string): Promise<V1Deployment | undefined>;
|
|
69
|
+
/** JSON merge patch of metadata.annotations and spec.replicas only. Throws KubernetesForbiddenError on 403. */
|
|
70
|
+
patchDeployment(namespace: string, name: string, patch: {
|
|
71
|
+
replicas?: number;
|
|
72
|
+
annotations?: Record<string, string>;
|
|
73
|
+
}): Promise<void>;
|
|
74
|
+
/** SelfSubjectAccessReview: may the current identity perform `verb` on this one named resource? */
|
|
75
|
+
canI(namespace: string, verb: string, group: string, resource: string, name: string): Promise<boolean>;
|
|
52
76
|
/** Runs a command in a container; resolves with its exit code. Never uses a shell. */
|
|
53
77
|
exec(namespace: string, pod: string, container: string, command: string[], options: KubernetesExecOptions): Promise<number>;
|
|
54
78
|
/**
|
|
@@ -4,6 +4,23 @@ export class KubernetesNotFoundError extends Error {
|
|
|
4
4
|
this.name = "KubernetesNotFoundError";
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
+
/** The caller's identity lacks RBAC permission for the request (HTTP 403). */
|
|
8
|
+
export class KubernetesForbiddenError extends Error {
|
|
9
|
+
constructor(message, options) {
|
|
10
|
+
super(message, options);
|
|
11
|
+
this.name = "KubernetesForbiddenError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** A create the namespace ResourceQuota refused (HTTP 403 "exceeded quota"). */
|
|
15
|
+
export class KubernetesQuotaExceededError extends Error {
|
|
16
|
+
/** The refusing quota's name as the API server worded it; unvalidated, and nothing else of the refusal is kept. */
|
|
17
|
+
quotaName;
|
|
18
|
+
constructor(message, options) {
|
|
19
|
+
super(message, options);
|
|
20
|
+
this.name = "KubernetesQuotaExceededError";
|
|
21
|
+
this.quotaName = options?.quotaName;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
7
24
|
/** Stale resourceVersion on replace. */
|
|
8
25
|
export class KubernetesConflictError extends Error {
|
|
9
26
|
constructor(message) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* method is one client call plus HTTP-status translation into the seam's
|
|
4
4
|
* error classes. Proven against a real cluster by kubernetes.integration.test.ts.
|
|
5
5
|
*/
|
|
6
|
-
import { type V1ConfigMap, type V1Endpoints, type V1ResourceQuota, type V1NetworkPolicy, type V1Pod, type V1Secret, type V1Service } from "@kubernetes/client-node";
|
|
6
|
+
import { type V1ConfigMap, type V1Deployment, type V1Endpoints, type V1ResourceQuota, type V1NetworkPolicy, type V1Pod, type V1Secret, type V1Service } from "@kubernetes/client-node";
|
|
7
7
|
import { type KubernetesApi, type KubernetesExecOptions } from "./kubernetes-api.js";
|
|
8
8
|
export interface ClientNodeKubernetesApiOptions {
|
|
9
9
|
/** kubeconfig context to use; defaults to the current context (or in-cluster credentials). */
|
|
@@ -13,6 +13,8 @@ export declare class ClientNodeKubernetesApi implements KubernetesApi {
|
|
|
13
13
|
private readonly config;
|
|
14
14
|
private readonly core;
|
|
15
15
|
private readonly networking;
|
|
16
|
+
private readonly apps;
|
|
17
|
+
private readonly authz;
|
|
16
18
|
private readonly version;
|
|
17
19
|
constructor(options?: ClientNodeKubernetesApiOptions);
|
|
18
20
|
createConfigMap(namespace: string, body: V1ConfigMap): Promise<V1ConfigMap>;
|
|
@@ -23,6 +25,7 @@ export declare class ClientNodeKubernetesApi implements KubernetesApi {
|
|
|
23
25
|
createPod(namespace: string, body: V1Pod): Promise<V1Pod>;
|
|
24
26
|
dryRunCreatePod(namespace: string, body: V1Pod): Promise<V1Pod>;
|
|
25
27
|
readPod(namespace: string, name: string): Promise<V1Pod | undefined>;
|
|
28
|
+
listPods(namespace: string, labelSelector: string): Promise<V1Pod[]>;
|
|
26
29
|
deletePod(namespace: string, name: string, gracePeriodSeconds: number): Promise<void>;
|
|
27
30
|
createNetworkPolicy(namespace: string, body: V1NetworkPolicy): Promise<V1NetworkPolicy>;
|
|
28
31
|
readNetworkPolicy(namespace: string, name: string): Promise<V1NetworkPolicy | undefined>;
|
|
@@ -32,6 +35,12 @@ export declare class ClientNodeKubernetesApi implements KubernetesApi {
|
|
|
32
35
|
readResourceQuota(namespace: string, name: string): Promise<V1ResourceQuota | undefined>;
|
|
33
36
|
readApiServerVersion(): Promise<string>;
|
|
34
37
|
readNamespace(name: string): Promise<boolean>;
|
|
38
|
+
readDeployment(namespace: string, name: string): Promise<V1Deployment | undefined>;
|
|
39
|
+
patchDeployment(namespace: string, name: string, patch: {
|
|
40
|
+
replicas?: number;
|
|
41
|
+
annotations?: Record<string, string>;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
canI(namespace: string, verb: string, group: string, resource: string, name: string): Promise<boolean>;
|
|
35
44
|
exec(namespace: string, pod: string, container: string, command: string[], options: KubernetesExecOptions): Promise<number>;
|
|
36
45
|
readLogTail(namespace: string, pod: string, container: string, tailLines: number, limitBytes: number): Promise<string>;
|
|
37
46
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* method is one client call plus HTTP-status translation into the seam's
|
|
4
4
|
* error classes. Proven against a real cluster by kubernetes.integration.test.ts.
|
|
5
5
|
*/
|
|
6
|
-
import { ApiException, CoreV1Api, Exec, KubeConfig, NetworkingV1Api, VersionApi, } from "@kubernetes/client-node";
|
|
6
|
+
import { ApiException, AppsV1Api, AuthorizationV1Api, CoreV1Api, Exec, KubeConfig, NetworkingV1Api, PatchStrategy, setHeaderOptions, VersionApi, } from "@kubernetes/client-node";
|
|
7
7
|
import { Writable } from "node:stream";
|
|
8
|
-
import { KubernetesAlreadyExistsError, KubernetesConflictError, KubernetesNotFoundError, } from "./kubernetes-api.js";
|
|
8
|
+
import { KubernetesAlreadyExistsError, KubernetesConflictError, KubernetesForbiddenError, KubernetesNotFoundError, KubernetesQuotaExceededError, } from "./kubernetes-api.js";
|
|
9
9
|
function statusCode(error) {
|
|
10
10
|
return error instanceof ApiException ? error.code : undefined;
|
|
11
11
|
}
|
|
@@ -20,6 +20,19 @@ async function readOrUndefined(read) {
|
|
|
20
20
|
throw error;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
/** Undefined for a 404; a 403 becomes KubernetesForbiddenError (cause kept); rethrows anything else. */
|
|
24
|
+
async function readOrForbidden(what, read) {
|
|
25
|
+
try {
|
|
26
|
+
return await read();
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (statusCode(error) === 404)
|
|
30
|
+
return undefined;
|
|
31
|
+
if (statusCode(error) === 403)
|
|
32
|
+
throw new KubernetesForbiddenError(`forbidden: get ${what}`, { cause: error });
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
23
36
|
/** Swallows a 404 so deletes are idempotent. */
|
|
24
37
|
async function deleteIgnoringMissing(remove) {
|
|
25
38
|
try {
|
|
@@ -31,6 +44,11 @@ async function deleteIgnoringMissing(remove) {
|
|
|
31
44
|
throw error;
|
|
32
45
|
}
|
|
33
46
|
}
|
|
47
|
+
/** The error's message plus its body as text, for matching only; never copied into a thrown message. */
|
|
48
|
+
function bodyText(error) {
|
|
49
|
+
const { body, message } = error;
|
|
50
|
+
return `${message}\n${typeof body === "string" ? body : JSON.stringify(body ?? "")}`;
|
|
51
|
+
}
|
|
34
52
|
async function create(what, write) {
|
|
35
53
|
try {
|
|
36
54
|
return await write();
|
|
@@ -41,6 +59,10 @@ async function create(what, write) {
|
|
|
41
59
|
throw new KubernetesAlreadyExistsError(what);
|
|
42
60
|
if (code === 404)
|
|
43
61
|
throw new KubernetesNotFoundError(what);
|
|
62
|
+
if (code === 403 && /exceeded quota/i.test(bodyText(error))) {
|
|
63
|
+
const quotaName = /exceeded quota: ([^\s,"\\]+)/i.exec(bodyText(error))?.[1];
|
|
64
|
+
throw new KubernetesQuotaExceededError(`exceeded quota: ${what}`, { cause: error, quotaName });
|
|
65
|
+
}
|
|
44
66
|
throw error;
|
|
45
67
|
}
|
|
46
68
|
}
|
|
@@ -69,6 +91,8 @@ export class ClientNodeKubernetesApi {
|
|
|
69
91
|
config;
|
|
70
92
|
core;
|
|
71
93
|
networking;
|
|
94
|
+
apps;
|
|
95
|
+
authz;
|
|
72
96
|
version;
|
|
73
97
|
constructor(options = {}) {
|
|
74
98
|
this.config = new KubeConfig();
|
|
@@ -77,6 +101,8 @@ export class ClientNodeKubernetesApi {
|
|
|
77
101
|
this.config.setCurrentContext(options.context);
|
|
78
102
|
this.core = this.config.makeApiClient(CoreV1Api);
|
|
79
103
|
this.networking = this.config.makeApiClient(NetworkingV1Api);
|
|
104
|
+
this.apps = this.config.makeApiClient(AppsV1Api);
|
|
105
|
+
this.authz = this.config.makeApiClient(AuthorizationV1Api);
|
|
80
106
|
this.version = this.config.makeApiClient(VersionApi);
|
|
81
107
|
}
|
|
82
108
|
createConfigMap(namespace, body) {
|
|
@@ -103,6 +129,9 @@ export class ClientNodeKubernetesApi {
|
|
|
103
129
|
readPod(namespace, name) {
|
|
104
130
|
return readOrUndefined(() => this.core.readNamespacedPod({ namespace, name }));
|
|
105
131
|
}
|
|
132
|
+
async listPods(namespace, labelSelector) {
|
|
133
|
+
return (await this.core.listNamespacedPod({ namespace, labelSelector })).items;
|
|
134
|
+
}
|
|
106
135
|
deletePod(namespace, name, gracePeriodSeconds) {
|
|
107
136
|
return deleteIgnoringMissing(() => this.core.deleteNamespacedPod({ namespace, name, gracePeriodSeconds }));
|
|
108
137
|
}
|
|
@@ -119,7 +148,7 @@ export class ClientNodeKubernetesApi {
|
|
|
119
148
|
return readOrUndefined(() => this.core.readNamespacedService({ namespace, name }));
|
|
120
149
|
}
|
|
121
150
|
readEndpoints(namespace, name) {
|
|
122
|
-
return
|
|
151
|
+
return readOrForbidden(`endpoints/${namespace}/${name}`, () => this.core.readNamespacedEndpoints({ namespace, name }));
|
|
123
152
|
}
|
|
124
153
|
readResourceQuota(namespace, name) {
|
|
125
154
|
return readOrUndefined(() => this.core.readNamespacedResourceQuota({ namespace, name }));
|
|
@@ -130,6 +159,35 @@ export class ClientNodeKubernetesApi {
|
|
|
130
159
|
async readNamespace(name) {
|
|
131
160
|
return (await readOrUndefined(() => this.core.readNamespace({ name }))) !== undefined;
|
|
132
161
|
}
|
|
162
|
+
readDeployment(namespace, name) {
|
|
163
|
+
return readOrForbidden(`deployments/${namespace}/${name}`, () => this.apps.readNamespacedDeployment({ namespace, name }));
|
|
164
|
+
}
|
|
165
|
+
async patchDeployment(namespace, name, patch) {
|
|
166
|
+
const body = {
|
|
167
|
+
...(patch.annotations ? { metadata: { annotations: patch.annotations } } : {}),
|
|
168
|
+
...(patch.replicas !== undefined ? { spec: { replicas: patch.replicas } } : {}),
|
|
169
|
+
};
|
|
170
|
+
try {
|
|
171
|
+
await this.apps.patchNamespacedDeployment({ namespace, name, body }, setHeaderOptions("Content-Type", PatchStrategy.MergePatch));
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (statusCode(error) === 403)
|
|
175
|
+
throw new KubernetesForbiddenError(`deployments/${namespace}/${name}`, { cause: error });
|
|
176
|
+
if (statusCode(error) === 404)
|
|
177
|
+
throw new KubernetesNotFoundError(`deployments/${namespace}/${name}`);
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async canI(namespace, verb, group, resource, name) {
|
|
182
|
+
const review = await this.authz.createSelfSubjectAccessReview({
|
|
183
|
+
body: {
|
|
184
|
+
apiVersion: "authorization.k8s.io/v1",
|
|
185
|
+
kind: "SelfSubjectAccessReview",
|
|
186
|
+
spec: { resourceAttributes: { namespace, verb, group, resource, name } },
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
return review.status?.allowed === true;
|
|
190
|
+
}
|
|
133
191
|
exec(namespace, pod, container, command, options) {
|
|
134
192
|
// stderr is requested but discarded so it never reaches wardby's logs.
|
|
135
193
|
const stderr = new Writable({
|
|
@@ -14,7 +14,11 @@ export interface DryRunFixture {
|
|
|
14
14
|
notes: string[];
|
|
15
15
|
mutations: PodMutation[];
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
declare const FIXTURE_URLS: {
|
|
18
|
+
readonly "gke-autopilot": import("url").URL;
|
|
19
|
+
readonly eks: import("url").URL;
|
|
20
|
+
};
|
|
21
|
+
export declare function loadDryRunFixture(platform?: keyof typeof FIXTURE_URLS): DryRunFixture;
|
|
18
22
|
/**
|
|
19
23
|
* Returns a copy of `document` with every mutation applied in order.
|
|
20
24
|
*
|
|
@@ -47,3 +51,4 @@ export declare function applyMutations<T>(document: T, mutations: readonly PodMu
|
|
|
47
51
|
* `/spec/Foo` and `/spec/foo` by tie-break rules that differ between hosts).
|
|
48
52
|
*/
|
|
49
53
|
export declare function diffMutations(before: unknown, after: unknown, prefix?: string): PodMutation[];
|
|
54
|
+
export {};
|
|
@@ -33,9 +33,12 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { readFileSync } from "node:fs";
|
|
35
35
|
import { canonical } from "./kubernetes-isolation.js";
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const FIXTURE_URLS = {
|
|
37
|
+
"gke-autopilot": new URL("./fixtures/gke-autopilot-dry-run.json", import.meta.url),
|
|
38
|
+
eks: new URL("./fixtures/eks-dry-run.json", import.meta.url),
|
|
39
|
+
};
|
|
40
|
+
export function loadDryRunFixture(platform = "gke-autopilot") {
|
|
41
|
+
return JSON.parse(readFileSync(FIXTURE_URLS[platform], "utf8"));
|
|
39
42
|
}
|
|
40
43
|
function segments(path) {
|
|
41
44
|
if (path === "" || !path.startsWith("/"))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { V1NetworkPolicy, V1Pod, V1Secret } from "@kubernetes/client-node";
|
|
1
|
+
import type { V1Container, V1NetworkPolicy, V1Pod, V1Secret } from "@kubernetes/client-node";
|
|
2
2
|
import { type ResolvedCodingService } from "../../coding/services/catalog.js";
|
|
3
3
|
import type { JobSpec } from "./types.js";
|
|
4
|
+
import { CLAUDE_CONFIG_PATH, CLAUDE_CONFIG_SCRATCH_MIB } from "./docker-isolation.js";
|
|
4
5
|
import { type KubernetesPlatform } from "./kubernetes-platform.js";
|
|
5
6
|
export declare const KUBERNETES_ISOLATION_ERROR = "kubernetes_isolation_unsupported";
|
|
6
7
|
/** Extra seconds past timeoutSec before Kubernetes kills the pod (keeper included). */
|
|
@@ -51,6 +52,7 @@ export declare const ENFORCEMENT_PROBE_PROXY_UNREACHABLE = 4;
|
|
|
51
52
|
* blocking the path — the port is reachable-but-unserved and witnesses nothing.
|
|
52
53
|
*/
|
|
53
54
|
export declare const ENFORCEMENT_PROBE_DENY_REFUSED = 5;
|
|
55
|
+
export { CLAUDE_CONFIG_PATH, CLAUDE_CONFIG_SCRATCH_MIB };
|
|
54
56
|
export interface KubernetesRunNames {
|
|
55
57
|
token: string;
|
|
56
58
|
runSha: string;
|
|
@@ -81,6 +83,8 @@ export interface RunPodOptions {
|
|
|
81
83
|
export declare function buildRunPod(spec: JobSpec, options: RunPodOptions): V1Pod;
|
|
82
84
|
export declare function buildRunNetworkPolicy(spec: JobSpec, namespace: string): V1NetworkPolicy;
|
|
83
85
|
export declare function buildCapabilitySecret(spec: JobSpec, namespace: string, capability: string, toolSetup?: string): V1Secret;
|
|
86
|
+
/** A copy of a container's resources with every quantity in one rendering ("1" and "1000m" alike); see normalizeResources. */
|
|
87
|
+
export declare function canonicalResources(r?: V1Container["resources"]): V1Container["resources"];
|
|
84
88
|
/**
|
|
85
89
|
* A copy of `pod` with ONLY the API server's own defaulting and aliasing undone
|
|
86
90
|
* — the same `normalizeSpec` pass `assertRunPodMatches` runs, and nothing else.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
8
|
import { isIP } from "node:net";
|
|
9
9
|
import { StoredCodingServicesSchema } from "../../coding/services/catalog.js";
|
|
10
|
-
import { CLAUDE_TOOL_SETUP_ENV, CODING_PROXY_ALIAS, CODING_PROXY_DENY_PORT, CODING_PROXY_PORT, CODING_WORKER_GID, CODING_WORKER_UID, WORKER_STOP_GRACE_SECONDS, claudeToolLimits, isRepositoryDigest, } from "./docker-isolation.js";
|
|
10
|
+
import { CLAUDE_CONFIG_PATH, CLAUDE_CONFIG_SCRATCH_MIB, CLAUDE_TOOL_SETUP_ENV, CODING_PROXY_ALIAS, CODING_PROXY_DENY_PORT, CODING_PROXY_PORT, CODING_WORKER_GID, CODING_WORKER_UID, WORKER_STOP_GRACE_SECONDS, claudeToolLimits, isRepositoryDigest, } from "./docker-isolation.js";
|
|
11
11
|
import { GVISOR_RUNTIME_CLASS, KubernetesPlatformError, STORAGE_INIT_EPHEMERAL_MIB, TOOL_RUNNER_EPHEMERAL_MIB, WORKER_EPHEMERAL_MIB, conformResources, describeMib, normalizePlatformMetadata, platformProfile, podEphemeralStorageMib, } from "./kubernetes-platform.js";
|
|
12
12
|
export const KUBERNETES_ISOLATION_ERROR = "kubernetes_isolation_unsupported";
|
|
13
13
|
/** Extra seconds past timeoutSec before Kubernetes kills the pod (keeper included). */
|
|
@@ -97,6 +97,9 @@ const STORAGE_DIRECTORIES = ["workspace", "input", "output"];
|
|
|
97
97
|
* sandbox (GKE Autopilot annotates it `share: pod`), so the agent's relay can connect.
|
|
98
98
|
*/
|
|
99
99
|
const TOOL_SOCKET_VOLUME = "tool-socket";
|
|
100
|
+
/** Session resume only: the Claude worker's SDK config dir (docker-isolation.ts CLAUDE_CONFIG_SCRATCH_MIB). */
|
|
101
|
+
const CLAUDE_CONFIG_VOLUME = "claude-config";
|
|
102
|
+
export { CLAUDE_CONFIG_PATH, CLAUDE_CONFIG_SCRATCH_MIB };
|
|
100
103
|
const TOOL_SOCKET_VOLUME_MIB = 1;
|
|
101
104
|
/**
|
|
102
105
|
* `reason` is a short, fixed code naming which check failed (never a value from the spec itself,
|
|
@@ -166,6 +169,9 @@ export function validateKubernetesSpec(spec) {
|
|
|
166
169
|
else if (spec.toolImage !== undefined) {
|
|
167
170
|
throw isolationError("tool-image-set");
|
|
168
171
|
}
|
|
172
|
+
if (spec.sessionResume !== undefined && (spec.sessionResume !== true || spec.provider !== "claude-code")) {
|
|
173
|
+
throw isolationError("session-resume-not-claude");
|
|
174
|
+
}
|
|
169
175
|
if (!isRegistryDigest(spec.image))
|
|
170
176
|
throw isolationError("image-not-registry-digest");
|
|
171
177
|
if (spec.services !== undefined) {
|
|
@@ -322,6 +328,8 @@ export function buildRunPod(spec, options) {
|
|
|
322
328
|
{ name: TOOL_SOCKET_VOLUME, mountPath: "/run/wardby/tool" },
|
|
323
329
|
{ name: "tmp", mountPath: "/tmp" },
|
|
324
330
|
{ name: "home", mountPath: "/home/wardby" },
|
|
331
|
+
// Session resume: the SDK's config dir, where the session file grows, off /tmp's budget.
|
|
332
|
+
...(spec.sessionResume ? [{ name: CLAUDE_CONFIG_VOLUME, mountPath: CLAUDE_CONFIG_PATH }] : []),
|
|
325
333
|
]
|
|
326
334
|
: [
|
|
327
335
|
{ name: "storage", mountPath: "/workspace", subPath: "workspace" },
|
|
@@ -414,6 +422,14 @@ export function buildRunPod(spec, options) {
|
|
|
414
422
|
{ name: TOOL_SOCKET_VOLUME, emptyDir: { medium: "Memory", sizeLimit: `${TOOL_SOCKET_VOLUME_MIB}Mi` } },
|
|
415
423
|
{ name: "tool-tmp", emptyDir: { medium: "Memory", sizeLimit: `${toolScratchMb}Mi` } },
|
|
416
424
|
{ name: "tool-home", emptyDir: { medium: "Memory", sizeLimit: `${toolScratchMb}Mi` } },
|
|
425
|
+
...(spec.sessionResume
|
|
426
|
+
? [
|
|
427
|
+
{
|
|
428
|
+
name: CLAUDE_CONFIG_VOLUME,
|
|
429
|
+
emptyDir: { medium: "Memory", sizeLimit: `${CLAUDE_CONFIG_SCRATCH_MIB}Mi` },
|
|
430
|
+
},
|
|
431
|
+
]
|
|
432
|
+
: []),
|
|
417
433
|
]
|
|
418
434
|
: []),
|
|
419
435
|
...serviceVolumes(services),
|
|
@@ -561,6 +577,12 @@ function normalizeResources(r) {
|
|
|
561
577
|
bag["ephemeral-storage"] = memoryBytes(bag["ephemeral-storage"]);
|
|
562
578
|
}
|
|
563
579
|
}
|
|
580
|
+
/** A copy of a container's resources with every quantity in one rendering ("1" and "1000m" alike); see normalizeResources. */
|
|
581
|
+
export function canonicalResources(r) {
|
|
582
|
+
const copy = r ? JSON.parse(JSON.stringify(r)) : undefined;
|
|
583
|
+
normalizeResources(copy);
|
|
584
|
+
return copy;
|
|
585
|
+
}
|
|
564
586
|
function normalizeProbe(p) {
|
|
565
587
|
if (!p)
|
|
566
588
|
return;
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* regresses to a documentation-only fixture again.
|
|
30
30
|
*/
|
|
31
31
|
import type { V1PodSpec, V1Toleration } from "@kubernetes/client-node";
|
|
32
|
-
export type KubernetesPlatform = "generic" | "gke-autopilot";
|
|
32
|
+
export type KubernetesPlatform = "generic" | "gke-autopilot" | "eks";
|
|
33
33
|
export declare const KUBERNETES_PLATFORMS: readonly KubernetesPlatform[];
|
|
34
34
|
export declare const KUBERNETES_PLATFORM_ERROR = "kubernetes_platform_unconformable";
|
|
35
35
|
/** A request the platform cannot legally run, refused here instead of being silently adjusted by the platform. */
|
|
@@ -84,6 +84,9 @@ export interface KubernetesPlatformProfile {
|
|
|
84
84
|
/** gVisor is mandatory: an unset or different runtime class is refused at startup, not warned about. */
|
|
85
85
|
requiresGvisor: boolean;
|
|
86
86
|
}
|
|
87
|
+
/** Node label and taint key of the EKS sandbox node group; deploy/aws and overlays/eks use the same strings. */
|
|
88
|
+
export declare const EKS_SANDBOX_NODE_LABEL = "wardby.dev/sandbox";
|
|
89
|
+
export declare const EKS_SANDBOX_TAINT_KEY = "sandbox";
|
|
87
90
|
export declare function platformProfile(name: KubernetesPlatform): KubernetesPlatformProfile;
|
|
88
91
|
export interface ContainerResourceRequest {
|
|
89
92
|
cpuMillicores: number;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
export const KUBERNETES_PLATFORMS = Object.freeze([
|
|
1
|
+
export const KUBERNETES_PLATFORMS = Object.freeze([
|
|
2
|
+
"generic",
|
|
3
|
+
"gke-autopilot",
|
|
4
|
+
"eks",
|
|
5
|
+
]);
|
|
2
6
|
export const KUBERNETES_PLATFORM_ERROR = "kubernetes_platform_unconformable";
|
|
3
7
|
/** A request the platform cannot legally run, refused here instead of being silently adjusted by the platform. */
|
|
4
8
|
export class KubernetesPlatformError extends Error {
|
|
@@ -109,9 +113,42 @@ const GKE_AUTOPILOT = {
|
|
|
109
113
|
},
|
|
110
114
|
requiresGvisor: true,
|
|
111
115
|
};
|
|
116
|
+
/** Node label and taint key of the EKS sandbox node group; deploy/aws and overlays/eks use the same strings. */
|
|
117
|
+
export const EKS_SANDBOX_NODE_LABEL = "wardby.dev/sandbox";
|
|
118
|
+
export const EKS_SANDBOX_TAINT_KEY = "sandbox";
|
|
119
|
+
/**
|
|
120
|
+
* Amazon EKS with a dedicated gVisor node group (deploy/aws). EKS has no managed sandbox runtime, so
|
|
121
|
+
* the node group's launch template installs runsc and the overlay's `gvisor` RuntimeClass schedules
|
|
122
|
+
* onto it: the RuntimeClass admission plugin merges its `scheduling` block into the pod, which is
|
|
123
|
+
* the toleration and nodeSelector below — wardby never sets either itself (see SYMMETRY CAVEAT).
|
|
124
|
+
*
|
|
125
|
+
* PROVISIONAL: written from the RuntimeClass spec, not yet a server-side dry-run capture. EKS has no
|
|
126
|
+
* Autopilot-style resource admission, so resources are the generic rules plus explicit ephemeral
|
|
127
|
+
* storage (kubelet eviction accounting on a shared sandbox node). Replace the fixture with a real
|
|
128
|
+
* capture before relying on the allowance list (fixtures/eks-dry-run.json).
|
|
129
|
+
*/
|
|
130
|
+
const EKS = {
|
|
131
|
+
name: "eks",
|
|
132
|
+
resources: {
|
|
133
|
+
cpuFloorMillicores: 0,
|
|
134
|
+
cpuIncrementMillicores: 1,
|
|
135
|
+
memoryPerCpuMinMib: 0,
|
|
136
|
+
memoryPerCpuMaxMib: Number.POSITIVE_INFINITY,
|
|
137
|
+
explicitEphemeralStorage: true,
|
|
138
|
+
},
|
|
139
|
+
metadata: {
|
|
140
|
+
podAnnotationKeyPrefixes: [],
|
|
141
|
+
podLabelKeyPrefixes: [],
|
|
142
|
+
tolerations: [{ key: EKS_SANDBOX_TAINT_KEY, operator: "Equal", value: GVISOR_RUNTIME_CLASS, effect: "NoSchedule" }],
|
|
143
|
+
nodeSelector: { [EKS_SANDBOX_NODE_LABEL]: GVISOR_RUNTIME_CLASS },
|
|
144
|
+
dropsPodSeccompProfile: false,
|
|
145
|
+
},
|
|
146
|
+
requiresGvisor: true,
|
|
147
|
+
};
|
|
112
148
|
const PROFILES = Object.freeze({
|
|
113
149
|
generic: freezeProfile(GENERIC),
|
|
114
150
|
"gke-autopilot": freezeProfile(GKE_AUTOPILOT),
|
|
151
|
+
eks: freezeProfile(EKS),
|
|
115
152
|
});
|
|
116
153
|
export function platformProfile(name) {
|
|
117
154
|
const profile = PROFILES[name];
|
|
@@ -40,7 +40,8 @@ export interface CanaryResult {
|
|
|
40
40
|
* probe (`enforcementProbeScript`), which had to make the same distinction after a live cluster
|
|
41
41
|
* with no NetworkPolicy at all passed a boolean version of this check; preflight and gate must
|
|
42
42
|
* agree on what counts as evidence, or one of them is vacuous. `internet`, `metadata` and `proxy`
|
|
43
|
-
* stay plain reachability, where "connected" is the only thing that matters
|
|
43
|
+
* stay plain reachability, where "connected" is the only thing that matters; `metadata` is true if
|
|
44
|
+
* **any** cloud metadata endpoint connects.
|
|
44
45
|
*
|
|
45
46
|
* CNIs program a new pod's policy a few seconds after it starts, so the script first waits (up to
|
|
46
47
|
* 20 s) for the deny-port connect to be *dropped*; if it never is, `proxyDeny` reports true.
|
|
@@ -11,6 +11,7 @@ import { randomBytes } from "node:crypto";
|
|
|
11
11
|
import { CODING_PROXY_DENY_PORT, CODING_PROXY_PORT } from "./docker-isolation.js";
|
|
12
12
|
import { KUBERNETES_ISOLATION_ERROR, WORKER_CONTAINER, buildRunNetworkPolicy, buildRunPod, isRegistryDigest, } from "./kubernetes-isolation.js";
|
|
13
13
|
import { KubernetesPlatformError, assertPlatformConfig, platformProfile } from "./kubernetes-platform.js";
|
|
14
|
+
import { CLOUD_METADATA_PROBES } from "./metadata-probes.js";
|
|
14
15
|
import { readProxyWitness } from "./kubernetes-witness.js";
|
|
15
16
|
/**
|
|
16
17
|
* The image the preflight canary runs (it only needs node): the Codex worker when configured,
|
|
@@ -40,7 +41,8 @@ const CANARY_KEYS = Object.keys(EXPECTED).sort();
|
|
|
40
41
|
* probe (`enforcementProbeScript`), which had to make the same distinction after a live cluster
|
|
41
42
|
* with no NetworkPolicy at all passed a boolean version of this check; preflight and gate must
|
|
42
43
|
* agree on what counts as evidence, or one of them is vacuous. `internet`, `metadata` and `proxy`
|
|
43
|
-
* stay plain reachability, where "connected" is the only thing that matters
|
|
44
|
+
* stay plain reachability, where "connected" is the only thing that matters; `metadata` is true if
|
|
45
|
+
* **any** cloud metadata endpoint connects.
|
|
44
46
|
*
|
|
45
47
|
* CNIs program a new pod's policy a few seconds after it starts, so the script first waits (up to
|
|
46
48
|
* 20 s) for the deny-port connect to be *dropped*; if it never is, `proxyDeny` reports true.
|
|
@@ -81,7 +83,7 @@ export const CANARY_SCRIPT = [
|
|
|
81
83
|
" ),",
|
|
82
84
|
` proxyDeny: !(await dropped(process.env.WARDBY_CANARY_PROXY_IP, ${CODING_PROXY_DENY_PORT})),`,
|
|
83
85
|
' internet: await reachable("1.1.1.1", 443),',
|
|
84
|
-
|
|
86
|
+
` metadata: (await Promise.all(${JSON.stringify(CLOUD_METADATA_PROBES.map((p) => [p.host, p.port]))}.map(([host, port]) => reachable(host, port)))).some(Boolean),`,
|
|
85
87
|
` proxy: await reachable(process.env.WARDBY_CANARY_PROXY_IP, ${CODING_PROXY_PORT}),`,
|
|
86
88
|
" };",
|
|
87
89
|
" console.log(JSON.stringify({ wardbyCanary }));",
|