@wardby/cli 0.6.0 → 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/deploy/local/docker-compose.quickstart-coding.yml +13 -0
- package/dist/claude-coding-worker/driver.d.ts +21 -3
- package/dist/claude-coding-worker/driver.js +125 -17
- package/dist/claude-coding-worker/main.js +34 -6
- package/dist/claude-coding-worker/sdk.js +12 -1
- 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 +1 -0
- package/dist/cli.js +24 -10
- 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 +46 -126
- package/dist/coding/profile.js +45 -4
- package/dist/coding/protected-path-wording.d.ts +8 -0
- package/dist/coding/protected-path-wording.js +1 -1
- package/dist/coding/protocol.d.ts +264 -346
- package/dist/coding/protocol.js +235 -12
- 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 +8 -3
- package/dist/coding-worker/artifact.js +3 -1
- 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 +116 -38
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -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 +11 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/providers.d.ts +12 -3
- package/dist/config/providers.js +55 -5
- 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/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 +42 -0
- package/dist/core/dispatch.js +131 -56
- package/dist/core/engine-native.js +1 -1
- 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 +18 -2
- package/dist/core/host-events.js +284 -24
- 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 +124 -33
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +4 -10
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +54 -26
- 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 +2 -1
- package/dist/core/merge-order-check.js +8 -1
- package/dist/core/notification-templates.d.ts +1 -7
- package/dist/core/notification-templates.js +36 -2
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +4 -3
- package/dist/core/reconciler.js +8 -1
- package/dist/core/related-pull-requests.d.ts +11 -3
- package/dist/core/related-pull-requests.js +27 -14
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/review-fix.d.ts +1 -1
- package/dist/core/review-fix.js +2 -1
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +3 -0
- package/dist/core/review-host-tools.js +99 -13
- 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 +80 -34
- package/dist/core/runner.js +439 -144
- 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 +10 -74
- 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/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/workflow-events.d.ts +14 -2
- package/dist/core/workflow-events.js +4 -0
- package/dist/core/workflow-run-events.d.ts +5 -3
- package/dist/core/workflow-run-events.js +43 -8
- 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 +34 -3
- package/dist/generated/prisma/client.d.ts +34 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +220 -60
- package/dist/generated/prisma/enums.d.ts +10 -0
- package/dist/generated/prisma/enums.js +8 -0
- package/dist/generated/prisma/internal/class.d.ts +44 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +428 -9
- package/dist/generated/prisma/internal/prismaNamespace.js +92 -1
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +95 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +92 -1
- package/dist/generated/prisma/models/Agent.d.ts +106 -8
- package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +229 -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 +1637 -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 +39 -1
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
- 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 +738 -2
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models.d.ts +4 -0
- package/dist/help-index.json +1320 -69
- package/dist/import/create.js +32 -3
- package/dist/import/neutral-schema.d.ts +50 -281
- package/dist/import/neutral-schema.js +5 -4
- package/dist/knowledge/check.d.ts +1 -1
- package/dist/knowledge/cli.d.ts +11 -1
- package/dist/knowledge/cli.js +37 -4
- package/dist/knowledge/concept.d.ts +3 -19
- package/dist/knowledge/location.d.ts +31 -0
- package/dist/knowledge/location.js +78 -0
- package/dist/mcp/auth/access.d.ts +10 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/ownership.d.ts +7 -7
- 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/host-events/github-ingress.d.ts +2 -0
- package/dist/mcp/host-events/github-ingress.js +2 -1
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +58 -10
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +33 -14
- package/dist/mcp/tools/agents.d.ts +4 -0
- package/dist/mcp/tools/agents.js +198 -16
- 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.js +2 -2
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/repositories.js +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.js +34 -12
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-elicitation-form.js +5 -0
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -61
- package/dist/mcp/tools/secrets.js +2 -2
- 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 +1 -1
- package/dist/mcp/tools/tools.js +25 -9
- 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/docker-launcher.d.ts +38 -2
- package/dist/native-worker/docker-launcher.js +65 -5
- package/dist/native-worker/gateway-server.d.ts +41 -3
- package/dist/native-worker/gateway-server.js +124 -27
- package/dist/native-worker/gateway.d.ts +27 -1
- package/dist/native-worker/gateway.js +70 -4
- package/dist/native-worker/http-server.d.ts +3 -1
- package/dist/native-worker/http-server.js +11 -7
- package/dist/native-worker/http-transport.js +1 -1
- package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
- package/dist/native-worker/kubernetes-launcher.js +43 -3
- package/dist/native-worker/launch.d.ts +18 -1
- package/dist/native-worker/launch.js +6 -1
- package/dist/native-worker/ledger.d.ts +18 -2
- package/dist/native-worker/ledger.js +57 -4
- package/dist/native-worker/loopback.js +3 -8
- package/dist/native-worker/main.d.ts +2 -1
- package/dist/native-worker/main.js +14 -3
- package/dist/native-worker/protocol.d.ts +129 -577
- package/dist/native-worker/protocol.js +47 -1
- package/dist/native-worker/sandbox-executor.d.ts +17 -2
- package/dist/native-worker/sandbox-executor.js +78 -4
- package/dist/native-worker/stderr-redaction.d.ts +77 -0
- package/dist/native-worker/stderr-redaction.js +237 -0
- package/dist/native-worker/stdio.d.ts +1 -1
- package/dist/native-worker/stdio.js +6 -5
- package/dist/native-worker/warm-pool.d.ts +2 -2
- package/dist/native-worker/warm-pool.js +4 -4
- package/dist/native-worker/worker.js +28 -2
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/self-hosted.d.ts +1 -1
- package/dist/providers/coding-proxy/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 +17 -2
- package/dist/providers/engine/types.js +17 -0
- package/dist/providers/executor/composition.d.ts +10 -3
- package/dist/providers/executor/composition.js +47 -7
- package/dist/providers/executor/container.d.ts +361 -8
- package/dist/providers/executor/container.js +1136 -91
- package/dist/providers/executor/dbos-status.d.ts +31 -0
- package/dist/providers/executor/dbos-status.js +64 -0
- package/dist/providers/executor/dbos.d.ts +50 -1
- package/dist/providers/executor/dbos.js +207 -20
- package/dist/providers/executor/deferred.d.ts +12 -24
- package/dist/providers/executor/deferred.js +10 -29
- package/dist/providers/executor/in-process.d.ts +9 -1
- package/dist/providers/executor/in-process.js +14 -4
- package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
- package/dist/providers/executor/linked-issue-reader.js +30 -0
- package/dist/providers/executor/routing.d.ts +2 -0
- package/dist/providers/executor/routing.js +4 -0
- package/dist/providers/executor/types.d.ts +13 -0
- package/dist/providers/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 +27 -2
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
- package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
- package/dist/providers/jobs/kubernetes-api.js +10 -0
- package/dist/providers/jobs/kubernetes-client.js +10 -1
- package/dist/providers/jobs/kubernetes-isolation.d.ts +2 -0
- package/dist/providers/jobs/kubernetes-isolation.js +17 -1
- package/dist/providers/jobs/kubernetes.d.ts +6 -1
- package/dist/providers/jobs/kubernetes.js +105 -16
- package/dist/providers/jobs/types.d.ts +33 -0
- package/dist/providers/jobs/types.js +13 -1
- package/dist/providers/llm/anthropic.js +5 -1
- package/dist/providers/llm/bedrock.d.ts +0 -12
- package/dist/providers/llm/bedrock.js +4 -0
- package/dist/providers/llm/claude-messages.d.ts +3 -1
- package/dist/providers/llm/claude-messages.js +4 -1
- package/dist/providers/llm/claude-provider.d.ts +2 -2
- package/dist/providers/llm/claude-provider.js +2 -2
- package/dist/providers/llm/openai.d.ts +2 -2
- package/dist/providers/llm/openai.js +6 -2
- package/dist/providers/llm/routing.d.ts +2 -2
- package/dist/providers/llm/routing.js +2 -2
- package/dist/providers/llm/types.d.ts +12 -2
- package/dist/providers/review-host/github-events.d.ts +9 -1
- package/dist/providers/review-host/github-events.js +34 -12
- package/dist/providers/review-host/github.d.ts +29 -2
- package/dist/providers/review-host/github.js +224 -29
- package/dist/providers/review-host/local.d.ts +8 -4
- package/dist/providers/review-host/local.js +49 -31
- package/dist/providers/review-host/patch-pages.d.ts +41 -0
- package/dist/providers/review-host/patch-pages.js +176 -0
- package/dist/providers/review-host/review-format.d.ts +19 -1
- package/dist/providers/review-host/review-format.js +38 -7
- package/dist/providers/review-host/types.d.ts +134 -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 +214 -6
- package/dist/providers/vcs/github.js +447 -45
- 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 +14 -3
- package/dist/quickstart/coding-seed.js +213 -4
- 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/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +1 -0
- package/dist/sandbox/host-functions.js +6 -11
- package/dist/sandbox/secret-broker.js +3 -4
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +8 -1
- package/dist/viewer/api-schema.d.ts +349 -2627
- package/dist/viewer/api-schema.js +7 -0
- package/dist/viewer/build-schemas.js +6 -2
- package/dist/viewer/openapi.js +2 -4
- package/dist/wardby-bin.js +10 -0
- package/docs/agent-recipes.md +58 -20
- package/docs/code-review-agents.md +551 -41
- package/docs/coding-agent-setup.md +489 -7
- package/docs/coding-packages.md +1033 -90
- package/docs/coding-services.md +27 -12
- package/docs/coding-worker-byo-images.md +20 -0
- package/docs/coding-worker-isolation.md +105 -30
- package/docs/getting-started-gke.md +124 -137
- package/docs/getting-started-identity-provider.md +10 -1
- package/docs/getting-started.md +9 -0
- package/docs/jira-agents.md +17 -8
- package/docs/knowledge/blob-not-found-semantics.md +41 -0
- package/docs/knowledge/bounded-file-descriptor.md +52 -0
- package/docs/knowledge/delegation-admission-slots.md +52 -0
- package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
- package/docs/knowledge/import-rename-target.md +52 -0
- package/docs/knowledge/index.md +57 -0
- package/docs/knowledge/log.md +9 -0
- package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
- package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
- package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
- package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
- package/docs/knowledge/overview-cli.md +74 -0
- package/docs/knowledge/overview-coding-proxy.md +72 -0
- package/docs/knowledge/overview-coding.md +72 -0
- package/docs/knowledge/overview-config.md +60 -0
- package/docs/knowledge/overview-core.md +72 -0
- package/docs/knowledge/overview-deploy.md +83 -0
- package/docs/knowledge/overview-mcp.md +61 -0
- package/docs/knowledge/overview-prisma.md +72 -0
- package/docs/knowledge/overview-providers.md +89 -0
- package/docs/knowledge/overview-sandbox.md +83 -0
- package/docs/knowledge/overview-surfaces.md +83 -0
- package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
- package/docs/knowledge/proxy-settlement-projections.md +41 -0
- package/docs/knowledge/run-pricing-first-writer.md +43 -0
- package/docs/knowledge/schedule-claim-transaction.md +41 -0
- package/docs/knowledge/secret-entry-replica-contract.md +52 -0
- package/docs/knowledge/terminal-run-first-writer.md +41 -0
- package/docs/knowledge/transactional-agent-authorization.md +52 -0
- package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
- package/docs/knowledge/warm-input-publication.md +30 -0
- package/docs/knowledge/workspace-staging-failure.md +54 -0
- package/docs/knowledge.md +54 -14
- package/docs/native-sandbox.md +119 -23
- package/docs/observability.md +4 -0
- package/docs/security-deployment.md +33 -2
- package/docs/slack-notifications.md +35 -19
- package/docs/tool-secrets.md +42 -10
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +24 -2
- package/help/architecture-agent.md +11 -6
- package/help/build-worker-image.md +3 -1
- package/help/builder-agent.md +19 -6
- package/help/code-review-agents.md +177 -6
- package/help/coding-packages.md +156 -6
- package/help/cost-attribution.md +9 -5
- package/help/creating-agents.md +14 -1
- package/help/dependency-cache.md +143 -0
- package/help/deploy-gke.md +15 -8
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-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/delegation-conflict.md +24 -0
- package/help/errors/file-list-truncated.md +45 -0
- package/help/errors/full-read-required.md +49 -0
- package/help/errors/github-account-not-allowed.md +4 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-worker-exited.md +3 -2
- 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-in-value.md +69 -0
- package/help/errors/target-merge.md +40 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/github-app-setup.md +132 -0
- package/help/github.md +22 -0
- package/help/identity-and-access.md +2 -0
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +1 -1
- package/help/low-power-mode.md +7 -1
- package/help/merge-order-check.md +5 -0
- package/help/native-capabilities.md +29 -1
- package/help/native-sandbox.md +15 -1
- package/help/operating-agents.md +5 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +10 -7
- package/help/resume-runs-locally.md +131 -0
- package/help/review-fix-rounds.md +33 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +19 -5
- package/help/status-comments.md +31 -0
- package/help/stop-run.md +58 -0
- package/help/troubleshooting/budgets.md +28 -0
- package/help/troubleshooting/coding-workers.md +78 -7
- package/package.json +17 -10
- package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
- package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
- package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
- package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
- package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
- package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
- package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
- package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
- package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
- package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
- package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
- package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
- package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
- package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
- package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
- package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
- package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
- package/prisma/schema.prisma +311 -97
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs inside a worker thread spawned by lockfile-parse.ts: parses one
|
|
3
|
+
* lockfile with the ecosystem's own parser, off the proxy's event loop, and
|
|
4
|
+
* posts back a plain, structured-cloneable form of the result (entries,
|
|
5
|
+
* projects, and the edge table `resolve` answers from). `parentPort` is
|
|
6
|
+
* null when this file is merely imported, so nothing runs then.
|
|
7
|
+
*/
|
|
8
|
+
import { parentPort } from "node:worker_threads";
|
|
9
|
+
import { REGISTRY_ADAPTERS } from "../../../coding/registry/adapters.js";
|
|
10
|
+
import { RegistryError } from "../../../coding/registry/types.js";
|
|
11
|
+
/** At most this many edges per entry are shipped (far above any real
|
|
12
|
+
* package's dependency count), so a crafted entry with a huge dependency
|
|
13
|
+
* map can't make the main thread deserialize millions of them. */
|
|
14
|
+
const MAX_EDGES_PER_ENTRY = 2000;
|
|
15
|
+
export function parseAndShip(request) {
|
|
16
|
+
const support = REGISTRY_ADAPTERS.get(request.ecosystem)?.lockfilePlan;
|
|
17
|
+
if (!support)
|
|
18
|
+
throw new RegistryError(404, "wardby_plan_unsupported", `no lockfile plans for ${request.ecosystem}`);
|
|
19
|
+
const parsed = support.parse(request.body, {
|
|
20
|
+
maxEntries: request.maxEntries,
|
|
21
|
+
proxyRegistryUrl: request.proxyRegistryUrl,
|
|
22
|
+
});
|
|
23
|
+
if (!parsed.dependencyKeys)
|
|
24
|
+
throw new Error("this lockfile format cannot be parsed off the event loop");
|
|
25
|
+
const index = new Map(parsed.entries.map((entry, at) => [entry, at]));
|
|
26
|
+
const edgesOf = (path, what) => {
|
|
27
|
+
let keys = parsed.dependencyKeys(path);
|
|
28
|
+
// A project's edges only label audited packages top-level (best effort):
|
|
29
|
+
// past the bound they are cut, never a reason to refuse the plan.
|
|
30
|
+
if (what === "project")
|
|
31
|
+
keys = keys.slice(0, MAX_EDGES_PER_ENTRY);
|
|
32
|
+
if (keys.length > MAX_EDGES_PER_ENTRY)
|
|
33
|
+
throw new RegistryError(413, "wardby_lockfile_too_large", `lockfile ${what} "${path}" lists ${keys.length} dependencies; at most ${MAX_EDGES_PER_ENTRY} are read`);
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const key of keys) {
|
|
36
|
+
const target = parsed.resolve(path, key);
|
|
37
|
+
const at = target && index.get(target);
|
|
38
|
+
if (at !== undefined && at !== null)
|
|
39
|
+
out.push([key, at]);
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
entries: parsed.entries,
|
|
45
|
+
projects: parsed.projects,
|
|
46
|
+
...(parsed.integrity ? { integrity: parsed.integrity } : {}),
|
|
47
|
+
edges: parsed.entries.map((entry) => edgesOf(entry.path, "entry")),
|
|
48
|
+
projectEdges: parsed.projects.map((project) => edgesOf(project.path, "project")),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** The answer for one parse: the lockfile, the parser's refusal, or (a bug,
|
|
52
|
+
* not a verdict about the lockfile) the unexpected error's message, which
|
|
53
|
+
* the main thread logs. */
|
|
54
|
+
export function responseFor(parse) {
|
|
55
|
+
try {
|
|
56
|
+
return { ok: true, lockfile: parse() };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof RegistryError)
|
|
60
|
+
return { ok: false, status: error.status, code: error.code, message: error.message };
|
|
61
|
+
return { ok: false, unexpected: true, message: error instanceof Error ? String(error) : "unknown error" };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (parentPort) {
|
|
65
|
+
const port = parentPort;
|
|
66
|
+
port.on("message", (request) => port.postMessage(responseFor(() => parseAndShip(request))));
|
|
67
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ParsedLockfile } from "../../../coding/registry/types.js";
|
|
2
|
+
/** Time one off-thread lockfile parse may take. Real lockfiles at the
|
|
3
|
+
* entry bound parse in well under a second. */
|
|
4
|
+
export declare const DEFAULT_LOCKFILE_PARSE_TIMEOUT_MS = 15000;
|
|
5
|
+
export declare function parseWorkerHeapMb(maxEntries: number): number;
|
|
6
|
+
export declare function parseLockfileOffThread(ecosystem: string, body: string, options: {
|
|
7
|
+
maxEntries: number;
|
|
8
|
+
proxyRegistryUrl: string;
|
|
9
|
+
}, limits?: {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
/** Heap bound for the worker (default parseWorkerHeapMb(maxEntries)). */
|
|
13
|
+
maxOldGenerationSizeMb?: number;
|
|
14
|
+
/** Tests only: the worker script to run. */
|
|
15
|
+
workerUrl?: URL;
|
|
16
|
+
}): Promise<ParsedLockfile>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a lockfile in a disposable worker thread with a hard time bound,
|
|
3
|
+
* for the formats that are costly to read (pnpm's and yarn's: YAML, or
|
|
4
|
+
* yarn classic's own format). A lockfile is attacker-controlled up to the
|
|
5
|
+
* 20 MiB plan cap, and a synchronous parse can't be interrupted, so on the
|
|
6
|
+
* event loop a crafted one could stall every request the proxy serves (model
|
|
7
|
+
* traffic included) for seconds. A worker's terminate() can stop it; the
|
|
8
|
+
* event loop only deserializes the bounded result (entries and their edges).
|
|
9
|
+
*
|
|
10
|
+
* One worker per parse, never reused (the same choice as the sandbox's
|
|
11
|
+
* parser pool): plans already run at most `planConcurrency` at once.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync } from "node:fs";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { Worker } from "node:worker_threads";
|
|
16
|
+
import { RegistryError } from "../../../coding/registry/types.js";
|
|
17
|
+
/** Time one off-thread lockfile parse may take. Real lockfiles at the
|
|
18
|
+
* entry bound parse in well under a second. */
|
|
19
|
+
export const DEFAULT_LOCKFILE_PARSE_TIMEOUT_MS = 15_000;
|
|
20
|
+
/** Heap one parse worker may use before it is stopped, per 5000 entries
|
|
21
|
+
* the plan may have (REGISTRY_PLAN_MAX_ENTRIES, at least the default's
|
|
22
|
+
* share). A realistic 5000-entry pnpm-lock.yaml (3.4 MiB: peers, engines,
|
|
23
|
+
* six dependencies a snapshot) needs 129 to 160 MiB of it, so 384 MiB is
|
|
24
|
+
* about 2.5 times that; a crafted lockfile that expands further is
|
|
25
|
+
* stopped there and refused as too large. */
|
|
26
|
+
const PARSE_WORKER_HEAP_MB_PER_5000_ENTRIES = 384;
|
|
27
|
+
export function parseWorkerHeapMb(maxEntries) {
|
|
28
|
+
return Math.ceil((PARSE_WORKER_HEAP_MB_PER_5000_ENTRIES * Math.max(maxEntries, 5000)) / 5000);
|
|
29
|
+
}
|
|
30
|
+
const compiledWorker = new URL("./lockfile-parse-worker.js", import.meta.url);
|
|
31
|
+
// Under tsx/vitest only the .ts source exists, and a worker gets no TS
|
|
32
|
+
// loader by inheritance (see src/sandbox/parser-worker/pool.ts).
|
|
33
|
+
const WORKER_URL = existsSync(fileURLToPath(compiledWorker))
|
|
34
|
+
? compiledWorker
|
|
35
|
+
: new URL("./lockfile-parse-worker.ts", import.meta.url);
|
|
36
|
+
function incomplete(message) {
|
|
37
|
+
return new RegistryError(503, "wardby_plan_incomplete", message);
|
|
38
|
+
}
|
|
39
|
+
/** The ParsedLockfile a worker shipped back, with `resolve` answering from
|
|
40
|
+
* its edge table. */
|
|
41
|
+
function rebuild(shipped) {
|
|
42
|
+
const byPath = new Map();
|
|
43
|
+
shipped.entries.forEach((entry, at) => {
|
|
44
|
+
byPath.set(entry.path, new Map(shipped.edges[at].map(([key, target]) => [key, shipped.entries[target]])));
|
|
45
|
+
});
|
|
46
|
+
// A project's own dependencies (what package audit mode labels top-level);
|
|
47
|
+
// a path an entry also uses keeps the entry's, as the parser's resolve does.
|
|
48
|
+
shipped.projects.forEach((project, at) => {
|
|
49
|
+
if (byPath.has(project.path))
|
|
50
|
+
return;
|
|
51
|
+
byPath.set(project.path, new Map(shipped.projectEdges[at].map(([key, target]) => [key, shipped.entries[target]])));
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
entries: shipped.entries,
|
|
55
|
+
projects: shipped.projects,
|
|
56
|
+
...(shipped.integrity ? { integrity: shipped.integrity } : {}),
|
|
57
|
+
resolve: (fromPath, key) => byPath.get(fromPath)?.get(key),
|
|
58
|
+
dependencyKeys: (path) => [...(byPath.get(path)?.keys() ?? [])],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export async function parseLockfileOffThread(ecosystem, body, options, limits = {}) {
|
|
62
|
+
const timeoutMs = limits.timeoutMs ?? DEFAULT_LOCKFILE_PARSE_TIMEOUT_MS;
|
|
63
|
+
if (limits.signal?.aborted)
|
|
64
|
+
throw incomplete("the client went away before the lockfile was read");
|
|
65
|
+
const workerUrl = limits.workerUrl ?? WORKER_URL;
|
|
66
|
+
const worker = new Worker(workerUrl, {
|
|
67
|
+
resourceLimits: { maxOldGenerationSizeMb: limits.maxOldGenerationSizeMb ?? parseWorkerHeapMb(options.maxEntries) },
|
|
68
|
+
execArgv: workerUrl.pathname.endsWith(".ts") ? ["--import", "tsx/esm"] : [],
|
|
69
|
+
});
|
|
70
|
+
try {
|
|
71
|
+
const response = await new Promise((resolve, reject) => {
|
|
72
|
+
const timer = setTimeout(() => reject(incomplete(`the lockfile was not read within ${Math.round(timeoutMs / 1000)} s`)), timeoutMs);
|
|
73
|
+
const onAbort = () => reject(incomplete("the client went away before the lockfile was read"));
|
|
74
|
+
limits.signal?.addEventListener("abort", onAbort, { once: true });
|
|
75
|
+
const settle = () => {
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
limits.signal?.removeEventListener("abort", onAbort);
|
|
78
|
+
};
|
|
79
|
+
worker.once("message", (message) => {
|
|
80
|
+
settle();
|
|
81
|
+
resolve(message);
|
|
82
|
+
});
|
|
83
|
+
worker.once("error", (error) => {
|
|
84
|
+
settle();
|
|
85
|
+
// Out of heap: the lockfile expanded too far, a verdict about it.
|
|
86
|
+
// Anything else (the worker failed to load, crashed) is the proxy's
|
|
87
|
+
// own failure: a plain error, which the plan route logs and answers
|
|
88
|
+
// as a failure to verify, never as a refusal of the lockfile.
|
|
89
|
+
reject(error.code === "ERR_WORKER_OUT_OF_MEMORY"
|
|
90
|
+
? new RegistryError(413, "wardby_lockfile_too_large", "the lockfile needs too much memory to read")
|
|
91
|
+
: new Error(`the lockfile reader failed: ${error.message}`, { cause: error }));
|
|
92
|
+
});
|
|
93
|
+
worker.once("exit", (code) => {
|
|
94
|
+
settle();
|
|
95
|
+
reject(new Error(`the lockfile reader stopped (exit code ${code})`));
|
|
96
|
+
});
|
|
97
|
+
const request = { ecosystem, body, ...options };
|
|
98
|
+
worker.postMessage(request);
|
|
99
|
+
});
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
if ("unexpected" in response)
|
|
102
|
+
throw new Error(`the lockfile reader failed: ${response.message}`);
|
|
103
|
+
throw new RegistryError(response.status, response.code, response.message);
|
|
104
|
+
}
|
|
105
|
+
return rebuild(response.lockfile);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await worker.terminate().catch(() => undefined);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PackageAuditMode } from "../../../coding/registry/audit-mode.js";
|
|
1
2
|
import { type AllowlistEntry, type LockfilePlanSupport, type ParsedLockfile, type RegistryAdapter, type UpstreamFetch } from "../../../coding/registry/types.js";
|
|
2
3
|
import { type AuditedVersion, type WithheldVersions } from "./audit.js";
|
|
3
4
|
import type { ApprovedVersion, StoredVersionFact } from "./store.js";
|
|
@@ -28,6 +29,8 @@ export interface PlanRefusal {
|
|
|
28
29
|
export interface PlanResult {
|
|
29
30
|
approved: ApprovedVersion[];
|
|
30
31
|
refused: PlanRefusal[];
|
|
32
|
+
/** Approvals carrying an audit verdict (package audit mode only; 0 otherwise). */
|
|
33
|
+
audited: number;
|
|
31
34
|
}
|
|
32
35
|
export interface PlanFacts {
|
|
33
36
|
getVersionFacts(versions: readonly {
|
|
@@ -49,6 +52,12 @@ export interface PlanInput {
|
|
|
49
52
|
/** Unbuffered fetch for streamed package documents. */
|
|
50
53
|
streamUpstream: UpstreamFetch;
|
|
51
54
|
audit(versions: readonly AuditedVersion[], signal: AbortSignal): Promise<WithheldVersions>;
|
|
55
|
+
/** The run's accepted advisory ids (packagePolicy.acceptedAdvisories):
|
|
56
|
+
* blocking advisories they waive do not refuse a version (see
|
|
57
|
+
* `isWaived`; malware is never waived). Absent or empty waives nothing. */
|
|
58
|
+
accepted?: ReadonlySet<string>;
|
|
59
|
+
/** The run's package audit mode (CodingRun.packageAuditMode); absent or null = normal enforcement. */
|
|
60
|
+
auditMode?: PackageAuditMode | null;
|
|
52
61
|
hostAllowed(url: string): boolean;
|
|
53
62
|
signal: AbortSignal;
|
|
54
63
|
factConcurrency?: number;
|
|
@@ -4,24 +4,38 @@
|
|
|
4
4
|
* lockfile claims is trusted:
|
|
5
5
|
*
|
|
6
6
|
* - every entry's integrity must equal the registry's own for that exact
|
|
7
|
-
* version (a per-version fact read from the registry, stored forever)
|
|
7
|
+
* version (a per-version fact read from the registry, stored forever),
|
|
8
|
+
* unless the format records no npm integrity at all (yarn Berry): then
|
|
9
|
+
* the approval is the exact name@version, and the download is checked
|
|
10
|
+
* against the registry's integrity alone;
|
|
8
11
|
* - edges come from the registry too: a parent version's declared
|
|
9
12
|
* dependencies, resolved to lockfile entries by the client's own rule
|
|
10
13
|
* (npm: nearest ancestor node_modules), and kept only when the entry is
|
|
11
14
|
* the declared package at a version inside the declared range;
|
|
12
|
-
* - reachability starts at
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
+
* - reachability starts at every lockfile entry that is an allowlist root
|
|
16
|
+
* (at a version inside the root's range), wherever it sits and whether or
|
|
17
|
+
* not a project declares it, and follows only verified
|
|
18
|
+
* edges, through versions old enough and without a HIGH/CRITICAL advisory
|
|
19
|
+
* (one the run's accepted set waives does not count; malware always does).
|
|
20
|
+
*
|
|
21
|
+
* PyPI dependency lines may be gated on extras: an entry is expanded with the
|
|
22
|
+
* extras it is installed with (a start's allowlist entry's, then those its
|
|
23
|
+
* parents' lines ask of it), and a plain install follows none.
|
|
15
24
|
*
|
|
16
25
|
* A refused entry refuses itself and whatever is reachable only through it;
|
|
17
|
-
* everything else is approved, as exact name@version pairs
|
|
26
|
+
* everything else is approved, as exact name@version pairs (an ecosystem
|
|
27
|
+
* that `approves: "names"` turns them into name allowances). In package
|
|
28
|
+
* audit mode every registry entry is a start as well: one the allowlist does
|
|
29
|
+
* not reach is approved when it passes every other check, marked with its
|
|
30
|
+
* audit verdict (and, in `full`, a version kept only past non-malware
|
|
31
|
+
* blocking advisories is approved and marked too). The work is
|
|
18
32
|
* bounded: facts are fetched only for entries reached (so a lockfile of
|
|
19
33
|
* unrelated packages costs nothing upstream), with bounded concurrency and a
|
|
20
34
|
* deadline.
|
|
21
35
|
*/
|
|
22
36
|
import { matchRoot } from "../../../coding/registry/allowlist.js";
|
|
23
37
|
import { RegistryError, } from "../../../coding/registry/types.js";
|
|
24
|
-
import { versionKey } from "./audit.js";
|
|
38
|
+
import { auditAdvisoryOf, splitWaived, versionKey } from "./audit.js";
|
|
25
39
|
export const DEFAULT_PLAN_MAX_ENTRIES = 5000;
|
|
26
40
|
export const DEFAULT_PLAN_TIMEOUT_MS = 120_000;
|
|
27
41
|
/** Per-version documents fetched at once (each is a few KB). */
|
|
@@ -61,21 +75,29 @@ export async function verifyLockfilePlan(input) {
|
|
|
61
75
|
reason: entry.unsupportedReason ?? "cannot be verified against the registry",
|
|
62
76
|
});
|
|
63
77
|
}
|
|
64
|
-
// Starting points:
|
|
65
|
-
//
|
|
78
|
+
// Starting points: every registry entry that is an allowlist root at a
|
|
79
|
+
// version inside the root's range, wherever it sits in the lockfile and
|
|
80
|
+
// whether or not a project declares it. An allowlisted name may be
|
|
81
|
+
// installed by name anyway (the download path allows the same name@version:
|
|
82
|
+
// `authorize` matches the name with `matchRoot`, and `keptVersions`
|
|
83
|
+
// applies the root's range, release age and advisories), so an `overrides`-forced version of it, which no parent's
|
|
84
|
+
// declared range reaches, is a start in its own right. Every start still
|
|
85
|
+
// passes the fact checks below (integrity, release age, advisories), and
|
|
86
|
+
// edges are still followed only inside declared ranges.
|
|
66
87
|
const starts = new Set();
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
// The extras each reached entry is installed with (PyPI): a start's are its
|
|
89
|
+
// allowlist entry's, a child's those its parents' lines ask of it.
|
|
90
|
+
const extrasOf = new Map();
|
|
91
|
+
for (const entry of lockfile.entries) {
|
|
92
|
+
if (entry.kind !== "registry")
|
|
93
|
+
continue;
|
|
94
|
+
const root = matchRoot(input.roots, adapter.normalizeName(entry.name));
|
|
95
|
+
if (!root)
|
|
96
|
+
continue;
|
|
97
|
+
if (root.range && !safeSatisfies(adapter, entry.version, root.range))
|
|
98
|
+
continue;
|
|
99
|
+
starts.add(entry);
|
|
100
|
+
extrasOf.set(entry, new Set(root.extras ?? []));
|
|
79
101
|
}
|
|
80
102
|
// Breadth first over verified edges, fetching facts one layer at a time
|
|
81
103
|
// (only for entries actually reached).
|
|
@@ -83,11 +105,28 @@ export async function verifyLockfilePlan(input) {
|
|
|
83
105
|
const edges = new Map();
|
|
84
106
|
const candidates = new Set();
|
|
85
107
|
const visited = new Set(starts);
|
|
108
|
+
// Package audit mode: every other registry entry starts too, except an
|
|
109
|
+
// allowlisted name outside its entry's own range (an owner's explicit
|
|
110
|
+
// restriction, never widened by audit mode). Visited after the roots'
|
|
111
|
+
// graph, so facts load in the same bounded layers.
|
|
112
|
+
const auditStarts = input.auditMode
|
|
113
|
+
? lockfile.entries.filter((entry) => entry.kind === "registry" &&
|
|
114
|
+
!starts.has(entry) &&
|
|
115
|
+
!outsideRootRange(input, adapter.normalizeName(entry.name), entry.version))
|
|
116
|
+
: [];
|
|
86
117
|
let layer = [...starts];
|
|
87
|
-
|
|
118
|
+
let auditSeeded = false;
|
|
119
|
+
while (layer.length > 0 || (!auditSeeded && auditStarts.length > 0)) {
|
|
120
|
+
if (layer.length === 0) {
|
|
121
|
+
auditSeeded = true;
|
|
122
|
+
layer = auditStarts.filter((entry) => !visited.has(entry));
|
|
123
|
+
for (const entry of layer)
|
|
124
|
+
visited.add(entry);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
88
127
|
signal.throwIfAborted();
|
|
89
128
|
await loadFacts(input, layer, outcomes);
|
|
90
|
-
const next =
|
|
129
|
+
const next = new Set();
|
|
91
130
|
for (const entry of layer) {
|
|
92
131
|
const outcome = outcomes.get(versionKey(entry.name, entry.version));
|
|
93
132
|
if ("refusal" in outcome) {
|
|
@@ -95,7 +134,8 @@ export async function verifyLockfilePlan(input) {
|
|
|
95
134
|
continue;
|
|
96
135
|
}
|
|
97
136
|
const { fact } = outcome;
|
|
98
|
-
if (
|
|
137
|
+
if (lockfile.integrity !== "registry" &&
|
|
138
|
+
(entry.integrity === null || entry.integrity.trim() !== fact.integrity)) {
|
|
99
139
|
refusals.set(entry, {
|
|
100
140
|
code: "wardby_lockfile_integrity_mismatch",
|
|
101
141
|
reason: `the lockfile's integrity is not the registry's for ${entry.name}@${entry.version}`,
|
|
@@ -113,34 +153,63 @@ export async function verifyLockfilePlan(input) {
|
|
|
113
153
|
}
|
|
114
154
|
candidates.add(entry);
|
|
115
155
|
const children = [];
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
156
|
+
const dependencies = support.dependenciesOf
|
|
157
|
+
? support.dependenciesOf(fact, [...(extrasOf.get(entry) ?? [])].sort())
|
|
158
|
+
: fact.dependencies;
|
|
159
|
+
for (const dependency of dependencies) {
|
|
160
|
+
const resolved = lockfile.resolveAll
|
|
161
|
+
? lockfile.resolveAll(entry.path, dependency.key)
|
|
162
|
+
: [lockfile.resolve(entry.path, dependency.key)];
|
|
163
|
+
for (const child of resolved) {
|
|
164
|
+
if (!child || child.kind !== "registry" || child.name !== dependency.name)
|
|
165
|
+
continue;
|
|
166
|
+
if (!support.edgeSatisfies(child.version, dependency.range))
|
|
167
|
+
continue;
|
|
168
|
+
children.push(child);
|
|
169
|
+
const asked = dependency.extras ?? [];
|
|
170
|
+
if (!visited.has(child)) {
|
|
171
|
+
visited.add(child);
|
|
172
|
+
extrasOf.set(child, new Set(asked));
|
|
173
|
+
next.add(child);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
// Reached again with extras it lacked: expanded again, now with them
|
|
177
|
+
// (extras only grow, so this ends).
|
|
178
|
+
const known = extrasOf.get(child) ?? new Set();
|
|
179
|
+
if (asked.some((extra) => !known.has(extra))) {
|
|
180
|
+
for (const extra of asked)
|
|
181
|
+
known.add(extra);
|
|
182
|
+
extrasOf.set(child, known);
|
|
183
|
+
next.add(child);
|
|
184
|
+
}
|
|
126
185
|
}
|
|
127
186
|
}
|
|
128
187
|
edges.set(entry, children);
|
|
129
188
|
}
|
|
130
|
-
layer = next;
|
|
189
|
+
layer = [...next];
|
|
131
190
|
}
|
|
132
191
|
// One advisory lookup for every candidate version.
|
|
133
192
|
const withheld = await input.audit([...new Map([...candidates].map((entry) => [versionKey(entry.name, entry.version), entry])).values()].map(({ name, version }) => ({ name, version })), signal);
|
|
193
|
+
// Advisories the run's accepted set waived, per approved name@version,
|
|
194
|
+
// and (full mode) the blocking ones served past.
|
|
195
|
+
const waivers = new Map();
|
|
196
|
+
const auditAdvisories = new Map();
|
|
134
197
|
for (const entry of candidates) {
|
|
135
|
-
const
|
|
136
|
-
|
|
198
|
+
const key = versionKey(entry.name, entry.version);
|
|
199
|
+
const split = splitWaived(withheld.get(key) ?? [], input.accepted, { auditAll: input.auditMode === "full" });
|
|
200
|
+
if (split.audited.length > 0)
|
|
201
|
+
auditAdvisories.set(key, split.audited.map(auditAdvisoryOf));
|
|
202
|
+
if (split.withheld.length > 0) {
|
|
137
203
|
candidates.delete(entry);
|
|
138
204
|
refusals.set(entry, {
|
|
139
205
|
code: "wardby_version_filtered",
|
|
140
|
-
reason: `withheld by advisory ${
|
|
206
|
+
reason: `withheld by advisory ${split.withheld.map(({ id }) => id).join(", ")} (high severity or malware)`,
|
|
141
207
|
intrinsic: true,
|
|
142
208
|
});
|
|
143
209
|
}
|
|
210
|
+
else if (split.waived.length > 0) {
|
|
211
|
+
waivers.set(key, split.waived.map(({ id }) => id));
|
|
212
|
+
}
|
|
144
213
|
}
|
|
145
214
|
// Reachability again, now only through entries that passed every check:
|
|
146
215
|
// a refused entry refuses whatever is reachable only through it.
|
|
@@ -157,16 +226,38 @@ export async function verifyLockfilePlan(input) {
|
|
|
157
226
|
queue.push(child);
|
|
158
227
|
}
|
|
159
228
|
}
|
|
229
|
+
// Package audit mode: every other entry that passed every check is
|
|
230
|
+
// approved too, marked with how it reached the lockfile.
|
|
231
|
+
const relations = input.auditMode
|
|
232
|
+
? auditRelations(input, approvedEntries, candidates, edges)
|
|
233
|
+
: new Map();
|
|
160
234
|
const approved = new Map();
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
235
|
+
const approve = (entry, relation) => {
|
|
236
|
+
const key = versionKey(entry.name, entry.version);
|
|
237
|
+
const outcome = outcomes.get(key);
|
|
238
|
+
if (!outcome || !("fact" in outcome) || approved.has(key))
|
|
239
|
+
return;
|
|
240
|
+
const acceptedAdvisories = waivers.get(key);
|
|
241
|
+
const advisories = auditAdvisories.get(key);
|
|
242
|
+
const audit = relation
|
|
243
|
+
? { ...relation, ...(advisories ? { advisories } : {}) }
|
|
244
|
+
: advisories
|
|
245
|
+
? { relation: "allowed", advisories }
|
|
246
|
+
: undefined;
|
|
247
|
+
approved.set(key, {
|
|
248
|
+
name: entry.name,
|
|
249
|
+
version: entry.version,
|
|
250
|
+
integrity: outcome.fact.integrity,
|
|
251
|
+
...(acceptedAdvisories ? { acceptedAdvisories } : {}),
|
|
252
|
+
...(audit ? { audit } : {}),
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
// Approvals through the allowlist first: an exact version approved both
|
|
256
|
+
// ways is not audited.
|
|
257
|
+
for (const entry of approvedEntries)
|
|
258
|
+
approve(entry, undefined);
|
|
259
|
+
for (const [entry, relation] of relations)
|
|
260
|
+
approve(entry, relation);
|
|
170
261
|
const refused = new Map();
|
|
171
262
|
for (const entry of lockfile.entries) {
|
|
172
263
|
if (entry.kind === "bundled")
|
|
@@ -182,7 +273,59 @@ export async function verifyLockfilePlan(input) {
|
|
|
182
273
|
}
|
|
183
274
|
// An entry refused at one place in the tree but approved at another (the
|
|
184
275
|
// same name@version) is approved: approvals are per exact version.
|
|
185
|
-
|
|
276
|
+
const approvals = [...approved.values()];
|
|
277
|
+
return {
|
|
278
|
+
approved: approvals,
|
|
279
|
+
refused: [...refused.values()],
|
|
280
|
+
audited: approvals.filter((approval) => approval.audit).length,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/** Whether `name@version` is an allowlisted name at a version its entry's range excludes. */
|
|
284
|
+
function outsideRootRange(input, name, version) {
|
|
285
|
+
const root = matchRoot(input.roots, name);
|
|
286
|
+
return !!root?.range && !safeSatisfies(input.adapter, version, root.range);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* How each candidate the allowlist does not reach came into the lockfile
|
|
290
|
+
* (package audit mode): `top-level` when a lockfile project declares it,
|
|
291
|
+
* `transitive` when an audited top-level entry reaches it over verified
|
|
292
|
+
* edges (`via` its nearest such ancestor, breadth first), otherwise
|
|
293
|
+
* `unknown`. Best effort: it decides only what a reviewer is shown.
|
|
294
|
+
*/
|
|
295
|
+
function auditRelations(input, approvedEntries, candidates, edges) {
|
|
296
|
+
const { lockfile } = input;
|
|
297
|
+
// An allowlisted name outside its entry's range is never audited in,
|
|
298
|
+
// even when an audited package declares it.
|
|
299
|
+
const audited = new Set([...candidates].filter((entry) => !approvedEntries.has(entry) && !outsideRootRange(input, input.adapter.normalizeName(entry.name), entry.version)));
|
|
300
|
+
const relations = new Map();
|
|
301
|
+
const declared = new Set();
|
|
302
|
+
for (const project of lockfile.projects)
|
|
303
|
+
for (const dependency of project.dependencies) {
|
|
304
|
+
const entry = lockfile.resolve(project.path, dependency.key);
|
|
305
|
+
if (entry)
|
|
306
|
+
declared.add(entry);
|
|
307
|
+
}
|
|
308
|
+
const queue = [];
|
|
309
|
+
for (const entry of audited)
|
|
310
|
+
if (declared.has(entry)) {
|
|
311
|
+
relations.set(entry, { relation: "top-level" });
|
|
312
|
+
queue.push(entry);
|
|
313
|
+
}
|
|
314
|
+
const via = new Map(queue.map((entry) => [entry, entry.name]));
|
|
315
|
+
while (queue.length > 0) {
|
|
316
|
+
const entry = queue.shift();
|
|
317
|
+
for (const child of edges.get(entry) ?? []) {
|
|
318
|
+
if (via.has(child) || !audited.has(child))
|
|
319
|
+
continue;
|
|
320
|
+
via.set(child, via.get(entry));
|
|
321
|
+
relations.set(child, { relation: "transitive", via: via.get(entry) });
|
|
322
|
+
queue.push(child);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
for (const entry of audited)
|
|
326
|
+
if (!relations.has(entry))
|
|
327
|
+
relations.set(entry, { relation: "unknown" });
|
|
328
|
+
return relations;
|
|
186
329
|
}
|
|
187
330
|
function safeSatisfies(adapter, version, range) {
|
|
188
331
|
try {
|
|
@@ -213,6 +356,7 @@ async function loadFacts(input, layer, outcomes) {
|
|
|
213
356
|
if (missing.length === 0)
|
|
214
357
|
return;
|
|
215
358
|
const fresh = new Map();
|
|
359
|
+
const complete = [];
|
|
216
360
|
await eachLimited(missing, input.factConcurrency ?? DEFAULT_PLAN_FACT_CONCURRENCY, async ({ name, version }) => {
|
|
217
361
|
const key = versionKey(name, version);
|
|
218
362
|
try {
|
|
@@ -227,6 +371,13 @@ async function loadFacts(input, layer, outcomes) {
|
|
|
227
371
|
});
|
|
228
372
|
return;
|
|
229
373
|
}
|
|
374
|
+
// A registry that gives the publish time with the version (PyPI) needs no second read.
|
|
375
|
+
if (fact.publishedAt) {
|
|
376
|
+
const stored = { ...fact, publishedAt: fact.publishedAt };
|
|
377
|
+
complete.push(stored);
|
|
378
|
+
outcomes.set(key, checkedFact(input, stored));
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
230
381
|
fresh.set(key, fact);
|
|
231
382
|
}
|
|
232
383
|
catch (error) {
|
|
@@ -239,7 +390,6 @@ async function loadFacts(input, layer, outcomes) {
|
|
|
239
390
|
const byName = new Map();
|
|
240
391
|
for (const fact of fresh.values())
|
|
241
392
|
byName.set(fact.name, [...(byName.get(fact.name) ?? []), fact.version]);
|
|
242
|
-
const complete = [];
|
|
243
393
|
await eachLimited([...byName.entries()], input.timeConcurrency ?? DEFAULT_PLAN_TIME_CONCURRENCY, async ([name, versions]) => {
|
|
244
394
|
let times;
|
|
245
395
|
try {
|
|
@@ -300,5 +450,8 @@ function upstreamRefusal(error) {
|
|
|
300
450
|
return { code: "wardby_metadata_too_large", reason: error.message };
|
|
301
451
|
if (error instanceof RegistryError && error.code === "wardby_package_not_found")
|
|
302
452
|
return { code: "wardby_package_not_found", reason: error.message };
|
|
453
|
+
// A release with nothing the registry may serve (PyPI: no wheel) stays so.
|
|
454
|
+
if (error instanceof RegistryError && error.code === "wardby_file_not_allowed")
|
|
455
|
+
return { code: "wardby_file_not_allowed", reason: error.message, intrinsic: true };
|
|
303
456
|
return { code: "wardby_upstream_error", reason: "the registry could not be read for it; try again" };
|
|
304
457
|
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { PrismaClient } from "#prisma";
|
|
2
2
|
import type { FileDependency } from "../../../coding/registry/types.js";
|
|
3
|
-
import type { ApprovedVersion, PlanRefusedVersion, RegistryFetchRecord, RegistryRunContext, RegistryStore, StoredVersionFact } from "./store.js";
|
|
3
|
+
import type { ApprovedDownload, ApprovedVersion, PlanRefusedVersion, RegistryAuditInsert, RegistryFetchRecord, RegistryRunContext, RegistryStore, StoredVersionFact } from "./store.js";
|
|
4
4
|
export declare class PrismaRegistryStore implements RegistryStore {
|
|
5
5
|
private readonly db;
|
|
6
6
|
constructor(db: PrismaClient);
|
|
7
7
|
findRunByRegistryTokenHash(hash: string, now: Date): Promise<RegistryRunContext | null>;
|
|
8
8
|
isAllowedDependency(runId: string, ecosystem: string, name: string): Promise<boolean>;
|
|
9
|
+
findAllowance(runId: string, ecosystem: string, name: string): Promise<{
|
|
10
|
+
auditedVia: string | null;
|
|
11
|
+
} | null>;
|
|
9
12
|
addAllowances(runId: string, ecosystem: string, names: readonly string[]): Promise<void>;
|
|
13
|
+
addAuditedAllowances(runId: string, ecosystem: string, names: readonly string[], auditedVia: string): Promise<void>;
|
|
14
|
+
recordAudit(record: RegistryAuditInsert): Promise<void>;
|
|
10
15
|
allowedExtras(runId: string, ecosystem: string, name: string): Promise<string[]>;
|
|
11
16
|
addExtraAllowances(runId: string, ecosystem: string, dependencies: readonly FileDependency[]): Promise<void>;
|
|
12
17
|
recordFetch(record: RegistryFetchRecord): Promise<void>;
|
|
@@ -18,20 +23,21 @@ export declare class PrismaRegistryStore implements RegistryStore {
|
|
|
18
23
|
listFetches(runId: string): Promise<(RegistryFetchRecord & {
|
|
19
24
|
createdAt: Date;
|
|
20
25
|
})[]>;
|
|
26
|
+
listRecentRefusals(runId: string, since: Date, limit: number): Promise<(RegistryFetchRecord & {
|
|
27
|
+
createdAt: Date;
|
|
28
|
+
})[]>;
|
|
21
29
|
getVersionFacts(ecosystem: string, versions: readonly {
|
|
22
30
|
name: string;
|
|
23
31
|
version: string;
|
|
24
32
|
}[]): Promise<StoredVersionFact[]>;
|
|
25
33
|
putVersionFacts(ecosystem: string, facts: readonly StoredVersionFact[]): Promise<void>;
|
|
26
34
|
approveVersions(runId: string, ecosystem: string, versions: readonly ApprovedVersion[]): Promise<void>;
|
|
27
|
-
findApprovedVersion(runId: string, ecosystem: string, name: string, version: string): Promise<
|
|
28
|
-
integrity: string;
|
|
29
|
-
downloadUrl: string;
|
|
30
|
-
} | null>;
|
|
35
|
+
findApprovedVersion(runId: string, ecosystem: string, name: string, version: string): Promise<ApprovedDownload | null>;
|
|
31
36
|
refusePlanVersions(runId: string, ecosystem: string, versions: readonly PlanRefusedVersion[]): Promise<void>;
|
|
32
37
|
findPlanRefusal(runId: string, ecosystem: string, name: string, version: string): Promise<{
|
|
33
38
|
code: string;
|
|
34
39
|
reason: string;
|
|
35
40
|
publishedAt: Date | null;
|
|
36
41
|
} | null>;
|
|
42
|
+
recordDependencyCacheLockHash(runId: string, lockHash: string, max: number): Promise<void>;
|
|
37
43
|
}
|