@capybara-hq/kernel 0.0.0-stage → 0.1.0-rc.1
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/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +20 -2
- package/bootstrap.json +26 -0
- package/dist/admin/admin.controller.d.ts +139 -0
- package/dist/admin/admin.controller.js +238 -0
- package/dist/admin/extensions.controller.d.ts +100 -0
- package/dist/admin/extensions.controller.js +226 -0
- package/dist/admin/setup.controller.d.ts +36 -0
- package/dist/admin/setup.controller.js +106 -0
- package/dist/admin/setup.service.d.ts +47 -0
- package/dist/admin/setup.service.js +90 -0
- package/dist/agents/agents.controller.d.ts +205 -0
- package/dist/agents/agents.controller.js +144 -0
- package/dist/agents/agents.service.d.ts +177 -0
- package/dist/agents/agents.service.js +677 -0
- package/dist/agents/definition.d.ts +198 -0
- package/dist/agents/definition.js +152 -0
- package/dist/agents/models.controller.d.ts +13 -0
- package/dist/agents/models.controller.js +31 -0
- package/dist/agents/templates.controller.d.ts +15 -0
- package/dist/agents/templates.controller.js +37 -0
- package/dist/agents/templates.d.ts +83 -0
- package/dist/agents/templates.js +173 -0
- package/dist/catalog/admin-catalog.controller.d.ts +143 -0
- package/dist/catalog/admin-catalog.controller.js +245 -0
- package/dist/catalog/catalog.service.d.ts +430 -0
- package/dist/catalog/catalog.service.js +882 -0
- package/dist/catalog/claude/agents.d.ts +27 -0
- package/dist/catalog/claude/agents.js +270 -0
- package/dist/catalog/claude/commands.d.ts +50 -0
- package/dist/catalog/claude/commands.js +179 -0
- package/dist/catalog/claude/manifest.d.ts +69 -0
- package/dist/catalog/claude/manifest.js +134 -0
- package/dist/catalog/claude/marketplace.d.ts +35 -0
- package/dist/catalog/claude/marketplace.js +194 -0
- package/dist/catalog/claude/mcp.d.ts +33 -0
- package/dist/catalog/claude/mcp.js +226 -0
- package/dist/catalog/claude/report.d.ts +86 -0
- package/dist/catalog/claude/report.js +121 -0
- package/dist/catalog/claude/translate.d.ts +56 -0
- package/dist/catalog/claude/translate.js +857 -0
- package/dist/catalog/cli.d.ts +46 -0
- package/dist/catalog/cli.js +211 -0
- package/dist/catalog/git-source.d.ts +127 -0
- package/dist/catalog/git-source.js +520 -0
- package/dist/catalog/marketplace-fetch.d.ts +99 -0
- package/dist/catalog/marketplace-fetch.js +203 -0
- package/dist/catalog/marketplaces.controller.d.ts +97 -0
- package/dist/catalog/marketplaces.controller.js +197 -0
- package/dist/catalog/marketplaces.service.d.ts +340 -0
- package/dist/catalog/marketplaces.service.js +1217 -0
- package/dist/catalog/org-catalog.controller.d.ts +128 -0
- package/dist/catalog/org-catalog.controller.js +277 -0
- package/dist/catalog/org-catalog.service.d.ts +246 -0
- package/dist/catalog/org-catalog.service.js +625 -0
- package/dist/catalog/plugin-import.d.ts +436 -0
- package/dist/catalog/plugin-import.js +1069 -0
- package/dist/catalog/plugin-install.d.ts +447 -0
- package/dist/catalog/plugin-install.js +1333 -0
- package/dist/catalog/plugin-package.d.ts +143 -0
- package/dist/catalog/plugin-package.js +382 -0
- package/dist/catalog/plugin-upgrade.d.ts +222 -0
- package/dist/catalog/plugin-upgrade.js +1219 -0
- package/dist/catalog/requests.service.d.ts +162 -0
- package/dist/catalog/requests.service.js +504 -0
- package/dist/catalog/schema-path.d.ts +7 -0
- package/dist/catalog/schema-path.js +63 -0
- package/dist/catalog/upgrade-targets.d.ts +59 -0
- package/dist/catalog/upgrade-targets.js +90 -0
- package/dist/catalog/versions.d.ts +31 -0
- package/dist/catalog/versions.js +44 -0
- package/dist/channels/actions.d.ts +37 -0
- package/dist/channels/actions.js +121 -0
- package/dist/channels/cards.d.ts +44 -0
- package/dist/channels/cards.js +156 -0
- package/dist/channels/connections.controller.d.ts +59 -0
- package/dist/channels/connections.controller.js +115 -0
- package/dist/channels/connections.service.d.ts +187 -0
- package/dist/channels/connections.service.js +534 -0
- package/dist/channels/features.d.ts +12 -0
- package/dist/channels/features.js +22 -0
- package/dist/channels/inbound.d.ts +120 -0
- package/dist/channels/inbound.js +332 -0
- package/dist/channels/outbound.d.ts +140 -0
- package/dist/channels/outbound.js +1126 -0
- package/dist/channels/phrases.d.ts +100 -0
- package/dist/channels/phrases.js +81 -0
- package/dist/channels/supervisor.d.ts +182 -0
- package/dist/channels/supervisor.js +625 -0
- package/dist/channels/threads.d.ts +29 -0
- package/dist/channels/threads.js +104 -0
- package/dist/channels/webhook-url.d.ts +16 -0
- package/dist/channels/webhook-url.js +34 -0
- package/dist/channels/webhook.controller.d.ts +19 -0
- package/dist/channels/webhook.controller.js +72 -0
- package/dist/channels/webhook.d.ts +73 -0
- package/dist/channels/webhook.js +274 -0
- package/dist/config/docs.d.ts +9 -0
- package/dist/config/docs.js +85 -0
- package/dist/config/env.d.ts +6 -0
- package/dist/config/env.js +73 -0
- package/dist/config/fields.d.ts +42 -0
- package/dist/config/fields.js +214 -0
- package/dist/config/file-source.d.ts +3 -0
- package/dist/config/file-source.js +31 -0
- package/dist/config/load.d.ts +20 -0
- package/dist/config/load.js +98 -0
- package/dist/config/nacos-source.d.ts +31 -0
- package/dist/config/nacos-source.js +229 -0
- package/dist/config/schema.d.ts +237 -0
- package/dist/config/schema.js +1192 -0
- package/dist/config/sources.d.ts +18 -0
- package/dist/config/sources.js +59 -0
- package/dist/config/types.d.ts +9 -0
- package/dist/config/types.js +7 -0
- package/dist/conversations/artifacts.d.ts +52 -0
- package/dist/conversations/artifacts.js +137 -0
- package/dist/conversations/attachments.controller.d.ts +28 -0
- package/dist/conversations/attachments.controller.js +96 -0
- package/dist/conversations/attachments.service.d.ts +180 -0
- package/dist/conversations/attachments.service.js +578 -0
- package/dist/conversations/conversations.controller.d.ts +288 -0
- package/dist/conversations/conversations.controller.js +607 -0
- package/dist/conversations/conversations.service.d.ts +321 -0
- package/dist/conversations/conversations.service.js +754 -0
- package/dist/conversations/event-log.d.ts +122 -0
- package/dist/conversations/event-log.js +259 -0
- package/dist/conversations/events.d.ts +856 -0
- package/dist/conversations/events.js +639 -0
- package/dist/conversations/files.d.ts +92 -0
- package/dist/conversations/files.js +213 -0
- package/dist/conversations/outputs-read.d.ts +34 -0
- package/dist/conversations/outputs-read.js +37 -0
- package/dist/conversations/queue.d.ts +169 -0
- package/dist/conversations/queue.js +527 -0
- package/dist/conversations/sandbox-status.d.ts +21 -0
- package/dist/conversations/sandbox-status.js +24 -0
- package/dist/conversations/selection.d.ts +46 -0
- package/dist/conversations/selection.js +75 -0
- package/dist/conversations/titles.d.ts +93 -0
- package/dist/conversations/titles.js +423 -0
- package/dist/ctx/bus.d.ts +16 -0
- package/dist/ctx/bus.js +101 -0
- package/dist/ctx/create-ctx.d.ts +109 -0
- package/dist/ctx/create-ctx.js +592 -0
- package/dist/ctx/kv.d.ts +4 -0
- package/dist/ctx/kv.js +31 -0
- package/dist/ctx/lock.d.ts +4 -0
- package/dist/ctx/lock.js +39 -0
- package/dist/ctx/namespace.d.ts +6 -0
- package/dist/ctx/namespace.js +12 -0
- package/dist/ctx/queue.d.ts +25 -0
- package/dist/ctx/queue.js +151 -0
- package/dist/ctx/secrets.d.ts +45 -0
- package/dist/ctx/secrets.js +175 -0
- package/dist/db/kernel-schema.d.ts +1122 -0
- package/dist/db/kernel-schema.js +5 -0
- package/dist/db/migrator.d.ts +28 -0
- package/dist/db/migrator.js +140 -0
- package/dist/db/pool.d.ts +21 -0
- package/dist/db/pool.js +28 -0
- package/dist/db/sql-statements.d.ts +34 -0
- package/dist/db/sql-statements.js +168 -0
- package/dist/errors.d.ts +211 -0
- package/dist/errors.js +213 -0
- package/dist/evals/budget.d.ts +61 -0
- package/dist/evals/budget.js +181 -0
- package/dist/evals/diff.d.ts +55 -0
- package/dist/evals/diff.js +133 -0
- package/dist/evals/judge.d.ts +53 -0
- package/dist/evals/judge.js +149 -0
- package/dist/evals/plan.d.ts +47 -0
- package/dist/evals/plan.js +77 -0
- package/dist/evals/reconstruct.d.ts +137 -0
- package/dist/evals/reconstruct.js +322 -0
- package/dist/evals/recorded-tools.d.ts +54 -0
- package/dist/evals/recorded-tools.js +167 -0
- package/dist/evals/run-replay.d.ts +86 -0
- package/dist/evals/run-replay.js +502 -0
- package/dist/evals/runs.controller.d.ts +100 -0
- package/dist/evals/runs.controller.js +199 -0
- package/dist/evals/runs.service.d.ts +275 -0
- package/dist/evals/runs.service.js +836 -0
- package/dist/evals/sets.controller.d.ts +61 -0
- package/dist/evals/sets.controller.js +183 -0
- package/dist/evals/sets.service.d.ts +128 -0
- package/dist/evals/sets.service.js +558 -0
- package/dist/evals/snapshot.d.ts +76 -0
- package/dist/evals/snapshot.js +207 -0
- package/dist/evals/step-replay.d.ts +113 -0
- package/dist/evals/step-replay.js +181 -0
- package/dist/evals/trajectory.controller.d.ts +41 -0
- package/dist/evals/trajectory.controller.js +88 -0
- package/dist/evals/trajectory.d.ts +144 -0
- package/dist/evals/trajectory.js +338 -0
- package/dist/evals/trajectory.service.d.ts +108 -0
- package/dist/evals/trajectory.service.js +323 -0
- package/dist/evals/worker.d.ts +101 -0
- package/dist/evals/worker.js +790 -0
- package/dist/extensions/admin-ops.d.ts +105 -0
- package/dist/extensions/admin-ops.js +353 -0
- package/dist/extensions/admin-view.d.ts +79 -0
- package/dist/extensions/admin-view.js +327 -0
- package/dist/extensions/approvals.d.ts +119 -0
- package/dist/extensions/approvals.js +205 -0
- package/dist/extensions/blobs.d.ts +45 -0
- package/dist/extensions/blobs.js +160 -0
- package/dist/extensions/bootstrap.d.ts +176 -0
- package/dist/extensions/bootstrap.js +535 -0
- package/dist/extensions/cli.d.ts +61 -0
- package/dist/extensions/cli.js +165 -0
- package/dist/extensions/config-json-schema.d.ts +9 -0
- package/dist/extensions/config-json-schema.js +73 -0
- package/dist/extensions/deployment-config.d.ts +138 -0
- package/dist/extensions/deployment-config.js +394 -0
- package/dist/extensions/enabled.d.ts +31 -0
- package/dist/extensions/enabled.js +55 -0
- package/dist/extensions/hooks.d.ts +161 -0
- package/dist/extensions/hooks.js +425 -0
- package/dist/extensions/host.d.ts +577 -0
- package/dist/extensions/host.js +2071 -0
- package/dist/extensions/inflight.d.ts +69 -0
- package/dist/extensions/inflight.js +277 -0
- package/dist/extensions/installs.d.ts +166 -0
- package/dist/extensions/installs.js +253 -0
- package/dist/extensions/instance.d.ts +167 -0
- package/dist/extensions/instance.js +329 -0
- package/dist/extensions/ledger.d.ts +30 -0
- package/dist/extensions/ledger.js +50 -0
- package/dist/extensions/lifecycle.d.ts +80 -0
- package/dist/extensions/lifecycle.js +152 -0
- package/dist/extensions/migrate-lock.d.ts +51 -0
- package/dist/extensions/migrate-lock.js +100 -0
- package/dist/extensions/org-config.controller.d.ts +24 -0
- package/dist/extensions/org-config.controller.js +59 -0
- package/dist/extensions/org-config.d.ts +169 -0
- package/dist/extensions/org-config.js +520 -0
- package/dist/extensions/package.d.ts +115 -0
- package/dist/extensions/package.js +246 -0
- package/dist/extensions/permission-set.d.ts +117 -0
- package/dist/extensions/permission-set.js +184 -0
- package/dist/extensions/permission-view.d.ts +194 -0
- package/dist/extensions/permission-view.js +284 -0
- package/dist/extensions/registry.d.ts +24 -0
- package/dist/extensions/registry.js +56 -0
- package/dist/extensions/resolve.d.ts +12 -0
- package/dist/extensions/resolve.js +71 -0
- package/dist/extensions/sources.d.ts +69 -0
- package/dist/extensions/sources.js +120 -0
- package/dist/extensions/sync.d.ts +40 -0
- package/dist/extensions/sync.js +242 -0
- package/dist/files/previewers.controller.d.ts +46 -0
- package/dist/files/previewers.controller.js +105 -0
- package/dist/files/previewers.d.ts +100 -0
- package/dist/files/previewers.js +250 -0
- package/dist/http/api.module.d.ts +114 -0
- package/dist/http/api.module.js +448 -0
- package/dist/http/app.d.ts +77 -0
- package/dist/http/app.js +220 -0
- package/dist/http/error.filter.d.ts +21 -0
- package/dist/http/error.filter.js +85 -0
- package/dist/http/gateway.module.d.ts +15 -0
- package/dist/http/gateway.module.js +13 -0
- package/dist/http/health.controller.d.ts +26 -0
- package/dist/http/health.controller.js +79 -0
- package/dist/http/nest-logger.d.ts +20 -0
- package/dist/http/nest-logger.js +28 -0
- package/dist/http/plugin-dispatch.d.ts +68 -0
- package/dist/http/plugin-dispatch.js +200 -0
- package/dist/http/tokens.d.ts +131 -0
- package/dist/http/tokens.js +131 -0
- package/dist/http/zod.pipe.d.ts +8 -0
- package/dist/http/zod.pipe.js +14 -0
- package/dist/identity/accounts.d.ts +93 -0
- package/dist/identity/accounts.js +367 -0
- package/dist/identity/api-tokens.d.ts +73 -0
- package/dist/identity/api-tokens.js +197 -0
- package/dist/identity/audit.d.ts +23 -0
- package/dist/identity/audit.js +41 -0
- package/dist/identity/auth.controller.d.ts +40 -0
- package/dist/identity/auth.controller.js +130 -0
- package/dist/identity/auth.guard.d.ts +41 -0
- package/dist/identity/auth.guard.js +162 -0
- package/dist/identity/binding.d.ts +47 -0
- package/dist/identity/binding.js +84 -0
- package/dist/identity/cookies.d.ts +16 -0
- package/dist/identity/cookies.js +32 -0
- package/dist/identity/credential-check.d.ts +17 -0
- package/dist/identity/credential-check.js +24 -0
- package/dist/identity/enterprise-admin.d.ts +14 -0
- package/dist/identity/enterprise-admin.js +27 -0
- package/dist/identity/external.d.ts +106 -0
- package/dist/identity/external.js +337 -0
- package/dist/identity/hash.d.ts +2 -0
- package/dist/identity/hash.js +3 -0
- package/dist/identity/login.d.ts +6 -0
- package/dist/identity/login.js +20 -0
- package/dist/identity/me.controller.d.ts +61 -0
- package/dist/identity/me.controller.js +159 -0
- package/dist/identity/passwords.d.ts +6 -0
- package/dist/identity/passwords.js +37 -0
- package/dist/identity/principal.d.ts +56 -0
- package/dist/identity/principal.js +38 -0
- package/dist/identity/rate-limit.d.ts +55 -0
- package/dist/identity/rate-limit.js +121 -0
- package/dist/identity/sessions.d.ts +84 -0
- package/dist/identity/sessions.js +306 -0
- package/dist/identity/settings.d.ts +121 -0
- package/dist/identity/settings.js +248 -0
- package/dist/identity/sso.controller.d.ts +59 -0
- package/dist/identity/sso.controller.js +192 -0
- package/dist/identity/sso.d.ts +83 -0
- package/dist/identity/sso.js +202 -0
- package/dist/inbox/inbox.service.d.ts +43 -0
- package/dist/inbox/inbox.service.js +57 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +67 -0
- package/dist/kernel.d.ts +259 -0
- package/dist/kernel.js +1326 -0
- package/dist/log-config.d.ts +9 -0
- package/dist/log-config.js +27 -0
- package/dist/log-context.d.ts +32 -0
- package/dist/log-context.js +40 -0
- package/dist/log-loki.d.ts +34 -0
- package/dist/log-loki.js +145 -0
- package/dist/log.d.ts +79 -0
- package/dist/log.js +303 -0
- package/dist/models/prices.d.ts +53 -0
- package/dist/models/prices.js +121 -0
- package/dist/models/purposes.controller.d.ts +19 -0
- package/dist/models/purposes.controller.js +56 -0
- package/dist/models/purposes.d.ts +140 -0
- package/dist/models/purposes.js +267 -0
- package/dist/net/proxy.d.ts +44 -0
- package/dist/net/proxy.js +162 -0
- package/dist/net/public-address.d.ts +60 -0
- package/dist/net/public-address.js +272 -0
- package/dist/net/safe-fetch.d.ts +38 -0
- package/dist/net/safe-fetch.js +140 -0
- package/dist/orgs/directory-sync.controller.d.ts +14 -0
- package/dist/orgs/directory-sync.controller.js +40 -0
- package/dist/orgs/directory-sync.d.ts +166 -0
- package/dist/orgs/directory-sync.js +558 -0
- package/dist/orgs/invitations.controller.d.ts +58 -0
- package/dist/orgs/invitations.controller.js +137 -0
- package/dist/orgs/invitations.service.d.ts +80 -0
- package/dist/orgs/invitations.service.js +217 -0
- package/dist/orgs/members.service.d.ts +63 -0
- package/dist/orgs/members.service.js +234 -0
- package/dist/orgs/offboarding.d.ts +141 -0
- package/dist/orgs/offboarding.js +398 -0
- package/dist/orgs/org-lock.d.ts +32 -0
- package/dist/orgs/org-lock.js +46 -0
- package/dist/orgs/org.guard.d.ts +35 -0
- package/dist/orgs/org.guard.js +95 -0
- package/dist/orgs/orgs.controller.d.ts +78 -0
- package/dist/orgs/orgs.controller.js +192 -0
- package/dist/orgs/orgs.service.d.ts +61 -0
- package/dist/orgs/orgs.service.js +209 -0
- package/dist/orgs/roles.d.ts +13 -0
- package/dist/orgs/roles.js +58 -0
- package/dist/orgs/settings.controller.d.ts +20 -0
- package/dist/orgs/settings.controller.js +53 -0
- package/dist/orgs/settings.service.d.ts +120 -0
- package/dist/orgs/settings.service.js +178 -0
- package/dist/packages/npm.d.ts +50 -0
- package/dist/packages/npm.js +218 -0
- package/dist/packages/provenance.d.ts +47 -0
- package/dist/packages/provenance.js +147 -0
- package/dist/packages/tgz.d.ts +76 -0
- package/dist/packages/tgz.js +225 -0
- package/dist/runtime/abort.d.ts +32 -0
- package/dist/runtime/abort.js +71 -0
- package/dist/runtime/checkpointer.d.ts +32 -0
- package/dist/runtime/checkpointer.js +243 -0
- package/dist/runtime/context/build.d.ts +254 -0
- package/dist/runtime/context/build.js +693 -0
- package/dist/runtime/context/claude-tools.d.ts +11 -0
- package/dist/runtime/context/claude-tools.js +24 -0
- package/dist/runtime/context/compaction.d.ts +26 -0
- package/dist/runtime/context/compaction.js +195 -0
- package/dist/runtime/context/pairing.d.ts +11 -0
- package/dist/runtime/context/pairing.js +82 -0
- package/dist/runtime/context/reminders.d.ts +5 -0
- package/dist/runtime/context/reminders.js +11 -0
- package/dist/runtime/context/skills.d.ts +105 -0
- package/dist/runtime/context/skills.js +283 -0
- package/dist/runtime/context/tokens.d.ts +19 -0
- package/dist/runtime/context/tokens.js +104 -0
- package/dist/runtime/conversation-lock.d.ts +40 -0
- package/dist/runtime/conversation-lock.js +97 -0
- package/dist/runtime/hook-calls.d.ts +84 -0
- package/dist/runtime/hook-calls.js +136 -0
- package/dist/runtime/langgraph-loop.d.ts +52 -0
- package/dist/runtime/langgraph-loop.js +247 -0
- package/dist/runtime/loop.d.ts +93 -0
- package/dist/runtime/loop.js +7 -0
- package/dist/runtime/maintenance.d.ts +80 -0
- package/dist/runtime/maintenance.js +148 -0
- package/dist/runtime/media-cache.d.ts +21 -0
- package/dist/runtime/media-cache.js +51 -0
- package/dist/runtime/model-call.d.ts +176 -0
- package/dist/runtime/model-call.js +1049 -0
- package/dist/runtime/providers.d.ts +86 -0
- package/dist/runtime/providers.js +224 -0
- package/dist/runtime/quota.d.ts +29 -0
- package/dist/runtime/quota.js +70 -0
- package/dist/runtime/run-finish.d.ts +45 -0
- package/dist/runtime/run-finish.js +69 -0
- package/dist/runtime/run-queue.d.ts +121 -0
- package/dist/runtime/run-queue.js +493 -0
- package/dist/runtime/run-worker.d.ts +138 -0
- package/dist/runtime/run-worker.js +806 -0
- package/dist/runtime/stream.controller.d.ts +34 -0
- package/dist/runtime/stream.controller.js +122 -0
- package/dist/runtime/stream.d.ts +63 -0
- package/dist/runtime/stream.js +262 -0
- package/dist/runtime/subagents/child.d.ts +80 -0
- package/dist/runtime/subagents/child.js +225 -0
- package/dist/runtime/subagents/definition.d.ts +103 -0
- package/dist/runtime/subagents/definition.js +392 -0
- package/dist/runtime/subagents/dispatch.d.ts +69 -0
- package/dist/runtime/subagents/dispatch.js +502 -0
- package/dist/runtime/subagents/limits.d.ts +23 -0
- package/dist/runtime/subagents/limits.js +34 -0
- package/dist/runtime/subagents/org-agents.d.ts +50 -0
- package/dist/runtime/subagents/org-agents.js +70 -0
- package/dist/runtime/subagents/preamble.d.ts +7 -0
- package/dist/runtime/subagents/preamble.js +11 -0
- package/dist/runtime/subagents/progress.d.ts +26 -0
- package/dist/runtime/subagents/progress.js +36 -0
- package/dist/runtime/subagents/roster.d.ts +55 -0
- package/dist/runtime/subagents/roster.js +111 -0
- package/dist/runtime/subagents/skill-fork.d.ts +123 -0
- package/dist/runtime/subagents/skill-fork.js +259 -0
- package/dist/runtime/usage-report.d.ts +163 -0
- package/dist/runtime/usage-report.js +551 -0
- package/dist/runtime/waits.d.ts +233 -0
- package/dist/runtime/waits.js +883 -0
- package/dist/sandbox/leases.d.ts +169 -0
- package/dist/sandbox/leases.js +515 -0
- package/dist/sandbox/lifecycle.d.ts +21 -0
- package/dist/sandbox/lifecycle.js +68 -0
- package/dist/sandbox/sandbox.service.d.ts +249 -0
- package/dist/sandbox/sandbox.service.js +908 -0
- package/dist/skills/catalog.d.ts +149 -0
- package/dist/skills/catalog.js +405 -0
- package/dist/skills/changes.controller.d.ts +56 -0
- package/dist/skills/changes.controller.js +136 -0
- package/dist/skills/changes.service.d.ts +175 -0
- package/dist/skills/changes.service.js +805 -0
- package/dist/skills/invocable.controller.d.ts +23 -0
- package/dist/skills/invocable.controller.js +50 -0
- package/dist/skills/invocation-keys.d.ts +23 -0
- package/dist/skills/invocation-keys.js +44 -0
- package/dist/skills/invoke.d.ts +135 -0
- package/dist/skills/invoke.js +286 -0
- package/dist/skills/package.d.ts +87 -0
- package/dist/skills/package.js +227 -0
- package/dist/skills/skills.controller.d.ts +40 -0
- package/dist/skills/skills.controller.js +110 -0
- package/dist/skills/skills.service.d.ts +192 -0
- package/dist/skills/skills.service.js +567 -0
- package/dist/storage/prefix.d.ts +36 -0
- package/dist/storage/prefix.js +104 -0
- package/dist/storage/purge.d.ts +27 -0
- package/dist/storage/purge.js +75 -0
- package/dist/storage/storage.service.d.ts +44 -0
- package/dist/storage/storage.service.js +145 -0
- package/dist/text.d.ts +13 -0
- package/dist/text.js +13 -0
- package/dist/tools/approvals.controller.d.ts +53 -0
- package/dist/tools/approvals.controller.js +128 -0
- package/dist/tools/approvals.service.d.ts +172 -0
- package/dist/tools/approvals.service.js +568 -0
- package/dist/tools/breaker.d.ts +28 -0
- package/dist/tools/breaker.js +72 -0
- package/dist/tools/builtins/agent.d.ts +81 -0
- package/dist/tools/builtins/agent.js +223 -0
- package/dist/tools/builtins/ask-user.d.ts +28 -0
- package/dist/tools/builtins/ask-user.js +139 -0
- package/dist/tools/builtins/read-tool-output.d.ts +18 -0
- package/dist/tools/builtins/read-tool-output.js +108 -0
- package/dist/tools/builtins/sandbox/bash.d.ts +16 -0
- package/dist/tools/builtins/sandbox/bash.js +137 -0
- package/dist/tools/builtins/sandbox/common.d.ts +116 -0
- package/dist/tools/builtins/sandbox/common.js +306 -0
- package/dist/tools/builtins/sandbox/deliver.d.ts +5 -0
- package/dist/tools/builtins/sandbox/deliver.js +180 -0
- package/dist/tools/builtins/sandbox/edit.d.ts +4 -0
- package/dist/tools/builtins/sandbox/edit.js +98 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +25 -0
- package/dist/tools/builtins/sandbox/glob-match.js +240 -0
- package/dist/tools/builtins/sandbox/glob.d.ts +4 -0
- package/dist/tools/builtins/sandbox/glob.js +104 -0
- package/dist/tools/builtins/sandbox/grep.d.ts +9 -0
- package/dist/tools/builtins/sandbox/grep.js +133 -0
- package/dist/tools/builtins/sandbox/index.d.ts +12 -0
- package/dist/tools/builtins/sandbox/index.js +27 -0
- package/dist/tools/builtins/sandbox/names.d.ts +7 -0
- package/dist/tools/builtins/sandbox/names.js +20 -0
- package/dist/tools/builtins/sandbox/read.d.ts +8 -0
- package/dist/tools/builtins/sandbox/read.js +121 -0
- package/dist/tools/builtins/sandbox/write.d.ts +4 -0
- package/dist/tools/builtins/sandbox/write.js +88 -0
- package/dist/tools/builtins/skill-load.d.ts +53 -0
- package/dist/tools/builtins/skill-load.js +446 -0
- package/dist/tools/builtins/skill-write.d.ts +59 -0
- package/dist/tools/builtins/skill-write.js +244 -0
- package/dist/tools/builtins/tool-search.d.ts +31 -0
- package/dist/tools/builtins/tool-search.js +171 -0
- package/dist/tools/connector-content.controller.d.ts +34 -0
- package/dist/tools/connector-content.controller.js +78 -0
- package/dist/tools/connector-content.d.ts +104 -0
- package/dist/tools/connector-content.js +267 -0
- package/dist/tools/connectors.controller.d.ts +210 -0
- package/dist/tools/connectors.controller.js +234 -0
- package/dist/tools/connectors.service.d.ts +303 -0
- package/dist/tools/connectors.service.js +1102 -0
- package/dist/tools/credentials.d.ts +139 -0
- package/dist/tools/credentials.js +351 -0
- package/dist/tools/drift.d.ts +141 -0
- package/dist/tools/drift.js +539 -0
- package/dist/tools/elicitation.d.ts +81 -0
- package/dist/tools/elicitation.js +266 -0
- package/dist/tools/endpoint.d.ts +18 -0
- package/dist/tools/endpoint.js +115 -0
- package/dist/tools/info.d.ts +67 -0
- package/dist/tools/info.js +113 -0
- package/dist/tools/naming.d.ts +27 -0
- package/dist/tools/naming.js +47 -0
- package/dist/tools/oauth/discovery.d.ts +65 -0
- package/dist/tools/oauth/discovery.js +307 -0
- package/dist/tools/oauth/flow.d.ts +63 -0
- package/dist/tools/oauth/flow.js +237 -0
- package/dist/tools/oauth/oauth.controller.d.ts +31 -0
- package/dist/tools/oauth/oauth.controller.js +95 -0
- package/dist/tools/oauth/tokens.d.ts +111 -0
- package/dist/tools/oauth/tokens.js +258 -0
- package/dist/tools/outputs.d.ts +61 -0
- package/dist/tools/outputs.js +156 -0
- package/dist/tools/pipeline.d.ts +322 -0
- package/dist/tools/pipeline.js +1236 -0
- package/dist/tools/policy.d.ts +60 -0
- package/dist/tools/policy.js +236 -0
- package/dist/tools/questions.controller.d.ts +24 -0
- package/dist/tools/questions.controller.js +58 -0
- package/dist/tools/questions.service.d.ts +103 -0
- package/dist/tools/questions.service.js +295 -0
- package/dist/tools/redact.d.ts +20 -0
- package/dist/tools/redact.js +60 -0
- package/dist/tools/registry.d.ts +246 -0
- package/dist/tools/registry.js +481 -0
- package/dist/tools/resources.d.ts +16 -0
- package/dist/tools/resources.js +76 -0
- package/dist/tools/specs.d.ts +14 -0
- package/dist/tools/specs.js +31 -0
- package/dist/tools/validate.d.ts +20 -0
- package/dist/tools/validate.js +183 -0
- package/dist/tools/view.d.ts +43 -0
- package/dist/tools/view.js +225 -0
- package/dist/ui/embed-token.d.ts +31 -0
- package/dist/ui/embed-token.js +132 -0
- package/dist/ui/registry.d.ts +58 -0
- package/dist/ui/registry.js +90 -0
- package/dist/ui/ui-stream.d.ts +37 -0
- package/dist/ui/ui-stream.js +162 -0
- package/dist/ui/views.controller.d.ts +81 -0
- package/dist/ui/views.controller.js +261 -0
- package/dist/ui/views.d.ts +155 -0
- package/dist/ui/views.js +306 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.js +6 -0
- package/package.json +69 -3
- package/src/migrations/0001_init.sql +8 -0
- package/src/migrations/0002_secrets.sql +8 -0
- package/src/migrations/0003_identity.sql +117 -0
- package/src/migrations/0004_plugin_org_config_nullable.sql +3 -0
- package/src/migrations/0005_agents.sql +27 -0
- package/src/migrations/0006_conversations.sql +37 -0
- package/src/migrations/0007_checkpoints.sql +26 -0
- package/src/migrations/0008_runs_trigger_seq.sql +3 -0
- package/src/migrations/0009_runs_active_unique.sql +4 -0
- package/src/migrations/0010_tools.sql +125 -0
- package/src/migrations/0011_approvals_spec.sql +10 -0
- package/src/migrations/0012_run_waits.sql +24 -0
- package/src/migrations/0013_app_tools_source.sql +4 -0
- package/src/migrations/0014_tool_specs.sql +8 -0
- package/src/migrations/0015_tool_drift.sql +20 -0
- package/src/migrations/0016_plugin_permissions.sql +11 -0
- package/src/migrations/0017_identity_sources.sql +6 -0
- package/src/migrations/0018_channels.sql +74 -0
- package/src/migrations/0019_identity_trust.sql +17 -0
- package/src/migrations/0020_channel_card_lookup.sql +10 -0
- package/src/migrations/0021_org_storage_purge.sql +9 -0
- package/src/migrations/0022_attachments.sql +29 -0
- package/src/migrations/0023_sandboxes.sql +37 -0
- package/src/migrations/0024_skills.sql +46 -0
- package/src/migrations/0025_skills_catalog_idx.sql +6 -0
- package/src/migrations/0026_skill_changes.sql +34 -0
- package/src/migrations/0027_model_prices.sql +18 -0
- package/src/migrations/0028_evals.sql +105 -0
- package/src/migrations/0029_model_purposes.sql +18 -0
- package/src/migrations/0030_plugin_installs.sql +73 -0
- package/src/migrations/0031_plugin_snapshot_source.sql +6 -0
- package/src/migrations/0032_plugin_deployment_configs.sql +10 -0
- package/src/migrations/0033_rename_apps_to_connectors.sql +25 -0
- package/src/migrations/0034_directory.sql +49 -0
- package/src/migrations/0035_catalogs.sql +40 -0
- package/src/migrations/0036_app_import_staging.sql +17 -0
- package/src/migrations/0037_directory_installs.sql +92 -0
- package/src/migrations/0038_channel_inbound_mode.sql +6 -0
- package/src/migrations/0039_channel_card_pending.sql +8 -0
- package/src/migrations/0040_usage_report_sweep.sql +10 -0
- package/src/migrations/0041_rename_plugins_to_extensions.sql +38 -0
- package/src/migrations/0042_rename_directory_to_catalog.sql +80 -0
- package/src/migrations/0043_rename_app_installs_to_plugin_installs.sql +20 -0
- package/src/migrations/0044_catalog_one_kind.sql +90 -0
- package/src/migrations/0045_plugin_dependencies.sql +9 -0
- package/src/migrations/0046_git_sources.sql +25 -0
- package/src/migrations/0047_marketplace_entry_heads.sql +7 -0
- package/src/migrations/0048_marketplace_entry_trees.sql +8 -0
- package/src/migrations/0049_plugin_upgrades.sql +37 -0
- package/src/migrations/0050_bootstrap.sql +53 -0
- package/src/migrations/0051_claude_compat.sql +26 -0
- package/src/migrations/0052_conversations_account_agent_idx.sql +5 -0
- package/src/migrations/0053_subagents.sql +73 -0
- package/src/migrations/0054_subagent_wait_expiry.sql +7 -0
- package/src/migrations/0055_subagent_parent_indexes.sql +10 -0
- package/src/migrations/0056_approval_reason.sql +3 -0
- package/src/migrations/0057_conversation_titles.sql +11 -0
- package/src/migrations/0058_conversation_selection.sql +4 -0
- package/src/migrations/0059_conversation_queue.sql +22 -0
- package/src/migrations/0060_file_previewers.sql +10 -0
- package/src/migrations/0061_queue_selection.sql +5 -0
- package/src/migrations/0062_queued_skill.sql +8 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Agent } from "undici";
|
|
2
|
+
/**
|
|
3
|
+
* Tunneling untrusted downloads through an HTTP(S) egress proxy with `CONNECT` (`net.httpsProxy`).
|
|
4
|
+
*
|
|
5
|
+
* Behind a proxy the kernel does not resolve the target: the proxy does, and the kernel's own DNS
|
|
6
|
+
* may answer fake or internal addresses (e.g. a fake-IP resolver answering 198.18.0.0/15) that say
|
|
7
|
+
* nothing about where the proxy connects. `safeFetch` therefore checks only the hostname rules
|
|
8
|
+
* (IP-literal targets against the private ranges and `allowPrivateHosts`; `allowedHosts` is checked
|
|
9
|
+
* by the callers on the hostname) and leaves SSRF protection for resolved addresses to the proxy.
|
|
10
|
+
*
|
|
11
|
+
* The proxy URL may carry credentials (`http://user:pass@proxy:3128`, sent as Basic
|
|
12
|
+
* `Proxy-Authorization`); they never appear in errors or logs: messages name the proxy by host and
|
|
13
|
+
* port only ({@link proxyLabel}).
|
|
14
|
+
*/
|
|
15
|
+
/** The egress proxy part of a `NetPolicy`. */
|
|
16
|
+
export type NetProxy = {
|
|
17
|
+
/** `http://` or `https://` proxy URL, optionally with `user:password@`. */
|
|
18
|
+
url: string;
|
|
19
|
+
/** Hostnames that bypass the proxy (an entry also matches its subdomains). */
|
|
20
|
+
noProxy: string[];
|
|
21
|
+
};
|
|
22
|
+
/** Why a `net.httpsProxy` value is refused (English, never echoing the value), or undefined. */
|
|
23
|
+
export declare function proxyUrlProblem(value: string): string | undefined;
|
|
24
|
+
/** Why a `net.noProxy` entry is refused, or undefined: a hostname (optionally `.`-prefixed) or IP. */
|
|
25
|
+
export declare function noProxyEntryProblem(entry: string): string | undefined;
|
|
26
|
+
/** Whether `host` bypasses the proxy: equal to a `noProxy` entry or a subdomain of one. */
|
|
27
|
+
export declare function bypassesProxy(host: string, noProxy: readonly string[]): boolean;
|
|
28
|
+
/** The proxy as `host:port`, for messages: never its credentials. */
|
|
29
|
+
export declare function proxyLabel(proxy: URL): string;
|
|
30
|
+
/**
|
|
31
|
+
* TLS trust overrides (tests): `ca` for the target, `proxyCa` for an https proxy; and the tunnel
|
|
32
|
+
* deadline (tests; default 10 s).
|
|
33
|
+
*/
|
|
34
|
+
export type ProxyTls = {
|
|
35
|
+
ca?: string | string[];
|
|
36
|
+
proxyCa?: string | string[];
|
|
37
|
+
tunnelTimeoutMs?: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* An undici dispatcher that reaches every https origin through a `CONNECT` tunnel on `proxyUrl`,
|
|
41
|
+
* then speaks TLS to the target over it (SNI and certificate checks for the target's hostname).
|
|
42
|
+
* The target is never resolved locally. One agent per download, like `pinnedAgent`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function proxyAgent(proxyUrl: string, tls?: ProxyTls): Agent;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { Agent, buildConnector } from "undici";
|
|
3
|
+
import { NetDeniedError, normalizeHost } from "./public-address.js";
|
|
4
|
+
/**
|
|
5
|
+
* How long opening the tunnel may take in total: connecting to the proxy plus its whole `CONNECT`
|
|
6
|
+
* answer. One deadline, not an idle timeout, so a proxy trickling bytes cannot hold a download open.
|
|
7
|
+
*/
|
|
8
|
+
const TUNNEL_TIMEOUT_MS = 10_000;
|
|
9
|
+
/** The largest `CONNECT` response head accepted from the proxy. */
|
|
10
|
+
const MAX_RESPONSE_HEAD = 16 * 1024;
|
|
11
|
+
/** Why a `net.httpsProxy` value is refused (English, never echoing the value), or undefined. */
|
|
12
|
+
export function proxyUrlProblem(value) {
|
|
13
|
+
let u;
|
|
14
|
+
try {
|
|
15
|
+
u = new URL(value);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return "must be an http:// or https:// URL such as http://proxy.internal:3128";
|
|
19
|
+
}
|
|
20
|
+
if (u.protocol !== "http:" && u.protocol !== "https:") {
|
|
21
|
+
return "must be an http:// or https:// URL (other proxy protocols are not supported)";
|
|
22
|
+
}
|
|
23
|
+
if ((u.pathname !== "" && u.pathname !== "/") || u.search !== "" || u.hash !== "") {
|
|
24
|
+
return "must not have a path, query or fragment";
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
// proxyAgent decodes them for Basic auth; a bad escape (`%zz`) would throw on every download
|
|
28
|
+
decodeURIComponent(u.username);
|
|
29
|
+
decodeURIComponent(u.password);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return "the user name or password is not valid percent-encoding";
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
const HOSTNAME_RE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
|
37
|
+
/** Why a `net.noProxy` entry is refused, or undefined: a hostname (optionally `.`-prefixed) or IP. */
|
|
38
|
+
export function noProxyEntryProblem(entry) {
|
|
39
|
+
const e = entry.startsWith(".") ? entry.slice(1) : entry;
|
|
40
|
+
if (isIP(e) !== 0 || HOSTNAME_RE.test(e))
|
|
41
|
+
return undefined;
|
|
42
|
+
return `"${entry}" is not a hostname or an IP address (no scheme, port, path or wildcard)`;
|
|
43
|
+
}
|
|
44
|
+
/** Whether `host` bypasses the proxy: equal to a `noProxy` entry or a subdomain of one. */
|
|
45
|
+
export function bypassesProxy(host, noProxy) {
|
|
46
|
+
const h = normalizeHost(host);
|
|
47
|
+
return noProxy.some((entry) => {
|
|
48
|
+
const e = normalizeHost(entry.startsWith(".") ? entry.slice(1) : entry);
|
|
49
|
+
return e !== "" && (h === e || (isIP(h) === 0 && h.endsWith(`.${e}`)));
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/** The proxy as `host:port`, for messages: never its credentials. */
|
|
53
|
+
export function proxyLabel(proxy) {
|
|
54
|
+
return `${proxy.hostname}:${proxy.port || (proxy.protocol === "https:" ? "443" : "80")}`;
|
|
55
|
+
}
|
|
56
|
+
/** Reads the proxy's answer to `CONNECT` and resolves its status once the head is complete. */
|
|
57
|
+
function readConnectResponse(socket) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
let head = Buffer.alloc(0);
|
|
60
|
+
const done = (err, status) => {
|
|
61
|
+
socket.off("data", onData);
|
|
62
|
+
socket.off("error", onError);
|
|
63
|
+
socket.off("close", onClose);
|
|
64
|
+
if (err)
|
|
65
|
+
reject(err);
|
|
66
|
+
else
|
|
67
|
+
resolve(status);
|
|
68
|
+
};
|
|
69
|
+
const onData = (chunk) => {
|
|
70
|
+
head = Buffer.concat([head, chunk]);
|
|
71
|
+
// Checked before looking for the terminator, so a large chunk that holds it is refused too
|
|
72
|
+
if (head.length > MAX_RESPONSE_HEAD) {
|
|
73
|
+
done(new Error("the proxy response head is too large"));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const end = head.indexOf("\r\n\r\n");
|
|
77
|
+
if (end < 0)
|
|
78
|
+
return;
|
|
79
|
+
socket.pause();
|
|
80
|
+
const rest = head.subarray(end + 4);
|
|
81
|
+
// Bytes after the head belong to the TLS stream: the socket is paused, so tls.connect over
|
|
82
|
+
// it (targetConnect with httpSocket) reads them first
|
|
83
|
+
if (rest.length > 0)
|
|
84
|
+
socket.unshift(rest);
|
|
85
|
+
const m = /^HTTP\/1\.[01] (\d{3})/.exec(head.subarray(0, end).toString("latin1"));
|
|
86
|
+
if (!m)
|
|
87
|
+
done(new Error("the proxy sent an invalid response to CONNECT"));
|
|
88
|
+
else
|
|
89
|
+
done(null, Number(m[1]));
|
|
90
|
+
};
|
|
91
|
+
const onError = (e) => done(e);
|
|
92
|
+
const onClose = () => done(new Error("the proxy closed the connection during CONNECT"));
|
|
93
|
+
socket.on("data", onData);
|
|
94
|
+
socket.on("error", onError);
|
|
95
|
+
socket.on("close", onClose);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* An undici dispatcher that reaches every https origin through a `CONNECT` tunnel on `proxyUrl`,
|
|
100
|
+
* then speaks TLS to the target over it (SNI and certificate checks for the target's hostname).
|
|
101
|
+
* The target is never resolved locally. One agent per download, like `pinnedAgent`.
|
|
102
|
+
*/
|
|
103
|
+
export function proxyAgent(proxyUrl, tls = {}) {
|
|
104
|
+
const proxy = new URL(proxyUrl);
|
|
105
|
+
const label = proxyLabel(proxy);
|
|
106
|
+
const auth = proxy.username !== "" || proxy.password !== ""
|
|
107
|
+
? `Basic ${Buffer.from(`${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`).toString("base64")}`
|
|
108
|
+
: undefined;
|
|
109
|
+
const tunnelTimeoutMs = tls.tunnelTimeoutMs ?? TUNNEL_TIMEOUT_MS;
|
|
110
|
+
const proxyConnect = buildConnector({
|
|
111
|
+
timeout: tunnelTimeoutMs,
|
|
112
|
+
...(tls.proxyCa !== undefined && { ca: tls.proxyCa }),
|
|
113
|
+
});
|
|
114
|
+
const targetConnect = buildConnector({
|
|
115
|
+
...(tls.ca !== undefined && { ca: tls.ca }),
|
|
116
|
+
});
|
|
117
|
+
const proxyPort = proxy.port || (proxy.protocol === "https:" ? "443" : "80");
|
|
118
|
+
const proxyHost = normalizeHost(proxy.hostname);
|
|
119
|
+
const connect = (opts, callback) => {
|
|
120
|
+
const target = normalizeHost(opts.hostname);
|
|
121
|
+
const port = opts.port || "443";
|
|
122
|
+
const authority = `${isIP(target) === 6 ? `[${target}]` : target}:${port}`;
|
|
123
|
+
const fail = (e) => callback(e, null);
|
|
124
|
+
if (opts.protocol !== "https:") {
|
|
125
|
+
fail(new Error("only https targets are sent through the egress proxy"));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const deadline = Date.now() + tunnelTimeoutMs;
|
|
129
|
+
proxyConnect({
|
|
130
|
+
protocol: proxy.protocol,
|
|
131
|
+
hostname: proxyHost,
|
|
132
|
+
host: `${proxy.hostname}:${proxyPort}`,
|
|
133
|
+
port: proxyPort,
|
|
134
|
+
}, (err, socket) => {
|
|
135
|
+
if (err || socket === null) {
|
|
136
|
+
fail(new Error(`cannot connect to the egress proxy ${label}: ${err?.message ?? ""}`));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const s = socket;
|
|
140
|
+
// What is left of the one deadline that started before connecting to the proxy
|
|
141
|
+
const timer = setTimeout(() => s.destroy(new Error("the proxy did not answer CONNECT in time")), Math.max(0, deadline - Date.now()));
|
|
142
|
+
const lines = [`CONNECT ${authority} HTTP/1.1`, `Host: ${authority}`];
|
|
143
|
+
if (auth !== undefined)
|
|
144
|
+
lines.push(`Proxy-Authorization: ${auth}`);
|
|
145
|
+
s.write(`${lines.join("\r\n")}\r\n\r\n`);
|
|
146
|
+
readConnectResponse(s).then((status) => {
|
|
147
|
+
clearTimeout(timer);
|
|
148
|
+
if (status < 200 || status > 299) {
|
|
149
|
+
s.destroy();
|
|
150
|
+
fail(new NetDeniedError("net.proxy_refused", target, `The egress proxy ${label} refused the connection to ${authority} (HTTP ${status}).`));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
targetConnect({ ...opts, httpSocket: s }, callback);
|
|
154
|
+
}, (e) => {
|
|
155
|
+
clearTimeout(timer);
|
|
156
|
+
s.destroy();
|
|
157
|
+
fail(new Error(`egress proxy ${label}: ${e.message}`));
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
return new Agent({ connect: connect });
|
|
162
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Whether connecting to this (resolved) IP is forbidden: private, loopback, reserved, or unparseable. */
|
|
2
|
+
export declare function isForbiddenAddress(ip: string): boolean;
|
|
3
|
+
/** Link-local (incl. cloud metadata 169.254.169.254) or unparseable: forbidden whatever the exemptions. */
|
|
4
|
+
export declare function isLinkLocalAddress(ip: string): boolean;
|
|
5
|
+
/** A hostname normalized for comparison: lower case, no IPv6 brackets, no trailing dots. */
|
|
6
|
+
export declare function normalizeHost(host: string): string;
|
|
7
|
+
/** `localhost`, `127.0.0.0/8` or `::1` (as written in a URL). */
|
|
8
|
+
export declare function isLoopbackHost(host: string): boolean;
|
|
9
|
+
/** Where downloads may go besides public addresses. */
|
|
10
|
+
export type NetPolicy = {
|
|
11
|
+
/** Testing only: plain http and loopback addresses for loopback hosts. */
|
|
12
|
+
allowInsecureLoopback: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* `marketplaces.allowPrivateHosts`: a hostname entry (exact, case-insensitive) exempts that host's
|
|
15
|
+
* resolved addresses; an IP or CIDR entry exempts IP-literal URL hosts inside it only, never a DNS
|
|
16
|
+
* name that resolves there (an attacker's name could point into the range).
|
|
17
|
+
*/
|
|
18
|
+
allowPrivateHosts: string[];
|
|
19
|
+
/** Origins configured by the admin (the npm registry): their hosts may resolve to private addresses. */
|
|
20
|
+
trustedOrigins: string[];
|
|
21
|
+
/**
|
|
22
|
+
* `net.httpsProxy` / `net.noProxy`: https downloads tunnel through this proxy (see `proxy.ts`);
|
|
23
|
+
* the target is then resolved by the proxy, not checked here, except IP-literal hosts.
|
|
24
|
+
*/
|
|
25
|
+
proxy?: {
|
|
26
|
+
url: string;
|
|
27
|
+
noProxy: string[];
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export type LookupFn = (host: string) => Promise<{
|
|
31
|
+
address: string;
|
|
32
|
+
family: number;
|
|
33
|
+
}[]>;
|
|
34
|
+
export type NetDeniedCode = "net.private_address" | "net.dns_failed" | "net.redirect" | "net.insecure_url" | "net.proxy_refused";
|
|
35
|
+
/** A download refused by the network rules. English message, safe to show. */
|
|
36
|
+
export declare class NetDeniedError extends Error {
|
|
37
|
+
readonly code: NetDeniedCode;
|
|
38
|
+
readonly host: string;
|
|
39
|
+
constructor(code: NetDeniedCode, host: string, message: string);
|
|
40
|
+
}
|
|
41
|
+
/** The shortest prefix an `allowPrivateHosts` CIDR may have, per family. */
|
|
42
|
+
export declare const MIN_CIDR_PREFIX: {
|
|
43
|
+
readonly ipv4: 8;
|
|
44
|
+
readonly ipv6: 16;
|
|
45
|
+
};
|
|
46
|
+
/** A syntactically valid `addr/prefix` CIDR as [address, prefix, family], else undefined. */
|
|
47
|
+
export declare function parseCidr(s: string): [string, number, "ipv4" | "ipv6"] | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Why a `marketplaces.allowPrivateHosts` entry is invalid (English), or null when it is a hostname,
|
|
50
|
+
* an IP address or a CIDR no broader than /8 (IPv4) or /16 (IPv6).
|
|
51
|
+
*/
|
|
52
|
+
export declare function privateHostEntryProblem(entry: string): string | null;
|
|
53
|
+
/** A valid `marketplaces.allowPrivateHosts` entry (see {@link privateHostEntryProblem}). */
|
|
54
|
+
export declare function isPrivateHostEntry(entry: string): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Resolves `host` (an IP literal is taken as is) and returns every address, in resolution order,
|
|
57
|
+
* after checking that each is public or exempt by `policy`. Throws {@link NetDeniedError}
|
|
58
|
+
* `net.dns_failed` (no answer) or `net.private_address` (some address is private and not exempt).
|
|
59
|
+
*/
|
|
60
|
+
export declare function resolvePublic(host: string, policy: NetPolicy, lookup?: LookupFn): Promise<string[]>;
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { lookup as dnsLookup } from "node:dns/promises";
|
|
2
|
+
import { BlockList, isIP } from "node:net";
|
|
3
|
+
/**
|
|
4
|
+
* Public-address checks for downloads whose URL comes from a marketplace or an admin (spec §5.1).
|
|
5
|
+
* A host is resolved once, every resolved address must be public, and the caller connects to the
|
|
6
|
+
* checked addresses only (see `safe-fetch.ts`), so a DNS answer that changes between check and
|
|
7
|
+
* connect (DNS rebinding, e.g. `10.0.0.1.nip.io`) cannot reach a private address.
|
|
8
|
+
*
|
|
9
|
+
* The blocked ranges are those of the sandbox-docker plugin's egress proxy
|
|
10
|
+
* (`plugins/sandbox-docker/egress-proxy/proxy.mjs` in capybara-hq/plugins), ported here because the
|
|
11
|
+
* kernel must not import from a plugin. IPv6 addresses that embed an IPv4 address
|
|
12
|
+
* (v4-mapped `::ffff:0:0/96`, v4-compatible `::/96`, NAT64 `64:ff9b::/96`, 6to4 `2002::/16`) are
|
|
13
|
+
* judged by the embedded IPv4 address; anything unparseable is refused. One addition over proxy.mjs:
|
|
14
|
+
* SIIT IPv4-translated addresses (`::ffff:0:a.b.c.d`, `::ffff:0:0:0/96`, RFC 2765) are also judged by
|
|
15
|
+
* the embedded IPv4 address (proxy.mjs falls through to the IPv6 table, where they are not blocked);
|
|
16
|
+
* a host behind a SIIT translator could otherwise reach a private IPv4 address.
|
|
17
|
+
*
|
|
18
|
+
* Link-local addresses (`169.254.0.0/16`, including cloud metadata, and `fe80::/10`) stay forbidden
|
|
19
|
+
* whatever the exemptions: no internal mirror lives there.
|
|
20
|
+
*/
|
|
21
|
+
const BLOCKED_V4 = [
|
|
22
|
+
["0.0.0.0", 8], // unspecified / this network
|
|
23
|
+
["10.0.0.0", 8],
|
|
24
|
+
["100.64.0.0", 10], // CGNAT
|
|
25
|
+
["127.0.0.0", 8],
|
|
26
|
+
["169.254.0.0", 16], // link-local, including cloud metadata 169.254.169.254
|
|
27
|
+
["172.16.0.0", 12],
|
|
28
|
+
["192.0.0.0", 24],
|
|
29
|
+
["192.0.2.0", 24],
|
|
30
|
+
["192.88.99.0", 24],
|
|
31
|
+
["192.168.0.0", 16],
|
|
32
|
+
["198.18.0.0", 15],
|
|
33
|
+
["198.51.100.0", 24],
|
|
34
|
+
["203.0.113.0", 24],
|
|
35
|
+
["224.0.0.0", 4], // multicast
|
|
36
|
+
["240.0.0.0", 4], // reserved and broadcast
|
|
37
|
+
];
|
|
38
|
+
const BLOCKED_V6 = [
|
|
39
|
+
["::", 128],
|
|
40
|
+
["::1", 128],
|
|
41
|
+
["100::", 64],
|
|
42
|
+
["2001:db8::", 32],
|
|
43
|
+
["fc00::", 7], // ULA
|
|
44
|
+
["fe80::", 10], // link-local
|
|
45
|
+
["fec0::", 10],
|
|
46
|
+
["ff00::", 8], // multicast
|
|
47
|
+
];
|
|
48
|
+
// Read-only after construction: address tables, not shared mutable state.
|
|
49
|
+
const blocked = new BlockList();
|
|
50
|
+
for (const [a, p] of BLOCKED_V4)
|
|
51
|
+
blocked.addSubnet(a, p, "ipv4");
|
|
52
|
+
for (const [a, p] of BLOCKED_V6)
|
|
53
|
+
blocked.addSubnet(a, p, "ipv6");
|
|
54
|
+
const linkLocal = new BlockList();
|
|
55
|
+
linkLocal.addSubnet("169.254.0.0", 16, "ipv4");
|
|
56
|
+
linkLocal.addSubnet("fe80::", 10, "ipv6");
|
|
57
|
+
/** An IPv6 address as its 8 16-bit groups; null when it cannot be parsed. */
|
|
58
|
+
function v6Groups(ip) {
|
|
59
|
+
let s = ip.toLowerCase();
|
|
60
|
+
const zone = s.indexOf("%");
|
|
61
|
+
if (zone >= 0)
|
|
62
|
+
s = s.slice(0, zone);
|
|
63
|
+
// a trailing dotted IPv4 (::ffff:1.2.3.4)
|
|
64
|
+
const m = /^(.*:)(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(s);
|
|
65
|
+
if (m) {
|
|
66
|
+
const [a = 0, b = 0, c = 0, d = 0] = m.slice(2).map(Number);
|
|
67
|
+
if ([a, b, c, d].some((x) => x > 255))
|
|
68
|
+
return null;
|
|
69
|
+
s = `${m[1]}${((a << 8) | b).toString(16)}:${((c << 8) | d).toString(16)}`;
|
|
70
|
+
}
|
|
71
|
+
const halves = s.split("::");
|
|
72
|
+
if (halves.length > 2)
|
|
73
|
+
return null;
|
|
74
|
+
const head = halves[0] ? halves[0].split(":") : [];
|
|
75
|
+
const tail = halves.length === 2 && halves[1] ? halves[1].split(":") : [];
|
|
76
|
+
const fill = halves.length === 2 ? 8 - head.length - tail.length : 0;
|
|
77
|
+
if (fill < 0)
|
|
78
|
+
return null;
|
|
79
|
+
const parts = [...head, ...Array(fill).fill("0"), ...tail];
|
|
80
|
+
if (!parts.every((g) => /^[0-9a-f]{1,4}$/.test(g)))
|
|
81
|
+
return null;
|
|
82
|
+
const groups = parts.map((g) => Number.parseInt(g, 16));
|
|
83
|
+
return groups.length === 8 ? groups : null;
|
|
84
|
+
}
|
|
85
|
+
const v4Of = (hi, lo) => `${hi >> 8}.${hi & 0xff}.${lo >> 8}.${lo & 0xff}`;
|
|
86
|
+
/**
|
|
87
|
+
* Whether `ip` falls in `table`, judging an IPv6 address that embeds an IPv4 address by the
|
|
88
|
+
* embedded one. Anything unparseable (including an IPv4 address with a `%` zone) counts as inside.
|
|
89
|
+
*/
|
|
90
|
+
function inTable(ip, table) {
|
|
91
|
+
if (isIP(ip) === 4)
|
|
92
|
+
return table.check(ip, "ipv4");
|
|
93
|
+
if (isIP(ip.split("%")[0] ?? "") !== 6)
|
|
94
|
+
return true;
|
|
95
|
+
const g = v6Groups(ip);
|
|
96
|
+
if (g === null)
|
|
97
|
+
return true;
|
|
98
|
+
const zeros = (from, to) => g.slice(from, to).every((x) => x === 0);
|
|
99
|
+
const [g0, g1, g2, , g4, g5, g6 = 0, g7 = 0] = g;
|
|
100
|
+
// v4-mapped ::ffff:a.b.c.d
|
|
101
|
+
if (zeros(0, 5) && g5 === 0xffff)
|
|
102
|
+
return inTable(v4Of(g6, g7), table);
|
|
103
|
+
// SIIT ::ffff:0:a.b.c.d (not unwrapped by proxy.mjs; see the file header)
|
|
104
|
+
if (zeros(0, 4) && g4 === 0xffff && g5 === 0)
|
|
105
|
+
return inTable(v4Of(g6, g7), table);
|
|
106
|
+
// v4-compatible ::a.b.c.d (:: and ::1 are left to the IPv6 table)
|
|
107
|
+
if (zeros(0, 6) && (g6 !== 0 || g7 > 1))
|
|
108
|
+
return inTable(v4Of(g6, g7), table);
|
|
109
|
+
// NAT64 64:ff9b::a.b.c.d
|
|
110
|
+
if (g0 === 0x64 && g1 === 0xff9b)
|
|
111
|
+
return inTable(v4Of(g6, g7), table);
|
|
112
|
+
// 6to4 2002:AABB:CCDD::
|
|
113
|
+
if (g0 === 0x2002)
|
|
114
|
+
return inTable(v4Of(g1 ?? 0, g2 ?? 0), table);
|
|
115
|
+
return table.check(g.map((x) => x.toString(16)).join(":"), "ipv6");
|
|
116
|
+
}
|
|
117
|
+
/** Whether connecting to this (resolved) IP is forbidden: private, loopback, reserved, or unparseable. */
|
|
118
|
+
export function isForbiddenAddress(ip) {
|
|
119
|
+
return inTable(ip, blocked);
|
|
120
|
+
}
|
|
121
|
+
/** Link-local (incl. cloud metadata 169.254.169.254) or unparseable: forbidden whatever the exemptions. */
|
|
122
|
+
export function isLinkLocalAddress(ip) {
|
|
123
|
+
return inTable(ip, linkLocal);
|
|
124
|
+
}
|
|
125
|
+
/** A hostname normalized for comparison: lower case, no IPv6 brackets, no trailing dots. */
|
|
126
|
+
export function normalizeHost(host) {
|
|
127
|
+
let h = host.trim().toLowerCase();
|
|
128
|
+
if (h.startsWith("[") && h.endsWith("]"))
|
|
129
|
+
h = h.slice(1, -1);
|
|
130
|
+
while (h.endsWith("."))
|
|
131
|
+
h = h.slice(0, -1);
|
|
132
|
+
return h;
|
|
133
|
+
}
|
|
134
|
+
/** `localhost`, `127.0.0.0/8` or `::1` (as written in a URL). */
|
|
135
|
+
export function isLoopbackHost(host) {
|
|
136
|
+
const h = normalizeHost(host);
|
|
137
|
+
return h === "localhost" || h === "::1" || (isIP(h) === 4 && h.startsWith("127."));
|
|
138
|
+
}
|
|
139
|
+
/** A download refused by the network rules. English message, safe to show. */
|
|
140
|
+
export class NetDeniedError extends Error {
|
|
141
|
+
code;
|
|
142
|
+
host;
|
|
143
|
+
constructor(code, host, message) {
|
|
144
|
+
super(message);
|
|
145
|
+
this.code = code;
|
|
146
|
+
this.host = host;
|
|
147
|
+
this.name = "NetDeniedError";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const defaultLookup = (host) => dnsLookup(host, { all: true, verbatim: true });
|
|
151
|
+
/** The shortest prefix an `allowPrivateHosts` CIDR may have, per family. */
|
|
152
|
+
export const MIN_CIDR_PREFIX = { ipv4: 8, ipv6: 16 };
|
|
153
|
+
/** A syntactically valid `addr/prefix` CIDR as [address, prefix, family], else undefined. */
|
|
154
|
+
export function parseCidr(s) {
|
|
155
|
+
const m = /^([^/]+)\/(\d{1,3})$/.exec(s.trim());
|
|
156
|
+
if (!m)
|
|
157
|
+
return undefined;
|
|
158
|
+
const addr = m[1].toLowerCase();
|
|
159
|
+
const prefix = Number(m[2]);
|
|
160
|
+
const family = isIP(addr);
|
|
161
|
+
if (family === 4 && prefix <= 32)
|
|
162
|
+
return [addr, prefix, "ipv4"];
|
|
163
|
+
if (family === 6 && prefix <= 128)
|
|
164
|
+
return [addr, prefix, "ipv6"];
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
const HOSTNAME = /^(?=.{1,253}$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/;
|
|
168
|
+
/**
|
|
169
|
+
* Why a `marketplaces.allowPrivateHosts` entry is invalid (English), or null when it is a hostname,
|
|
170
|
+
* an IP address or a CIDR no broader than /8 (IPv4) or /16 (IPv6).
|
|
171
|
+
*/
|
|
172
|
+
export function privateHostEntryProblem(entry) {
|
|
173
|
+
const cidr = parseCidr(entry);
|
|
174
|
+
if (cidr) {
|
|
175
|
+
const [, prefix, family] = cidr;
|
|
176
|
+
const min = MIN_CIDR_PREFIX[family];
|
|
177
|
+
return prefix < min
|
|
178
|
+
? `the CIDR ${entry.trim()} is too broad: use a prefix of at least /${min} for ${family === "ipv4" ? "IPv4" : "IPv6"}`
|
|
179
|
+
: null;
|
|
180
|
+
}
|
|
181
|
+
const h = normalizeHost(entry);
|
|
182
|
+
if (isIP(h) !== 0 || HOSTNAME.test(h))
|
|
183
|
+
return null;
|
|
184
|
+
return "must be a hostname, an IP address or a CIDR such as 10.1.0.0/16";
|
|
185
|
+
}
|
|
186
|
+
/** A valid `marketplaces.allowPrivateHosts` entry (see {@link privateHostEntryProblem}). */
|
|
187
|
+
export function isPrivateHostEntry(entry) {
|
|
188
|
+
return privateHostEntryProblem(entry) === null;
|
|
189
|
+
}
|
|
190
|
+
function exemptions(host, policy) {
|
|
191
|
+
const cidrs = new BlockList();
|
|
192
|
+
let all = false;
|
|
193
|
+
const literal = isIP(host) !== 0;
|
|
194
|
+
// a loopback host under allowInsecureLoopback may resolve to loopback addresses only
|
|
195
|
+
if (policy.allowInsecureLoopback && isLoopbackHost(host)) {
|
|
196
|
+
cidrs.addSubnet("127.0.0.0", 8, "ipv4");
|
|
197
|
+
cidrs.addAddress("::1", "ipv6");
|
|
198
|
+
}
|
|
199
|
+
for (const entry of policy.allowPrivateHosts) {
|
|
200
|
+
if (!isPrivateHostEntry(entry))
|
|
201
|
+
continue;
|
|
202
|
+
const cidr = parseCidr(entry);
|
|
203
|
+
const name = normalizeHost(entry);
|
|
204
|
+
if (cidr) {
|
|
205
|
+
// IP and CIDR entries match IP-literal hosts only
|
|
206
|
+
if (literal)
|
|
207
|
+
cidrs.addSubnet(...cidr);
|
|
208
|
+
}
|
|
209
|
+
else if (isIP(name) !== 0) {
|
|
210
|
+
if (literal)
|
|
211
|
+
cidrs.addAddress(name, isIP(name) === 4 ? "ipv4" : "ipv6");
|
|
212
|
+
}
|
|
213
|
+
else if (name === host) {
|
|
214
|
+
all = true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
for (const origin of policy.trustedOrigins) {
|
|
218
|
+
try {
|
|
219
|
+
if (normalizeHost(new URL(origin).hostname) === host)
|
|
220
|
+
all = true;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// an unparseable origin trusts nothing
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return { all, cidrs };
|
|
227
|
+
}
|
|
228
|
+
function allowedBy(cidrs, ip) {
|
|
229
|
+
const family = isIP(ip);
|
|
230
|
+
if (family === 4)
|
|
231
|
+
return cidrs.check(ip, "ipv4");
|
|
232
|
+
if (family === 6) {
|
|
233
|
+
if (cidrs.check(ip, "ipv6"))
|
|
234
|
+
return true;
|
|
235
|
+
// a v4-mapped answer also matches an IPv4 CIDR
|
|
236
|
+
const g = v6Groups(ip);
|
|
237
|
+
if (g?.slice(0, 5).every((x) => x === 0) && g[5] === 0xffff) {
|
|
238
|
+
return cidrs.check(v4Of(g[6] ?? 0, g[7] ?? 0), "ipv4");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Resolves `host` (an IP literal is taken as is) and returns every address, in resolution order,
|
|
245
|
+
* after checking that each is public or exempt by `policy`. Throws {@link NetDeniedError}
|
|
246
|
+
* `net.dns_failed` (no answer) or `net.private_address` (some address is private and not exempt).
|
|
247
|
+
*/
|
|
248
|
+
export async function resolvePublic(host, policy, lookup = defaultLookup) {
|
|
249
|
+
const h = normalizeHost(host);
|
|
250
|
+
let addrs;
|
|
251
|
+
if (isIP(h) !== 0) {
|
|
252
|
+
addrs = [h];
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
try {
|
|
256
|
+
addrs = (await lookup(h)).map((a) => a.address);
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
throw new NetDeniedError("net.dns_failed", h, `Cannot resolve ${h}.`);
|
|
260
|
+
}
|
|
261
|
+
if (addrs.length === 0)
|
|
262
|
+
throw new NetDeniedError("net.dns_failed", h, `Cannot resolve ${h}.`);
|
|
263
|
+
}
|
|
264
|
+
const ex = exemptions(h, policy);
|
|
265
|
+
const refused = (a) => isForbiddenAddress(a) && (isLinkLocalAddress(a) || (!ex.all && !allowedBy(ex.cidrs, a)));
|
|
266
|
+
if (addrs.some(refused)) {
|
|
267
|
+
throw new NetDeniedError("net.private_address", h, addrs.some(isLinkLocalAddress)
|
|
268
|
+
? `Access to ${h} is refused: it resolves to a link-local address, which is never allowed.`
|
|
269
|
+
: `Access to ${h} is refused: it resolves to a private or reserved address (add the hostname to marketplaces.allowPrivateHosts to allow an internal host).`);
|
|
270
|
+
}
|
|
271
|
+
return addrs;
|
|
272
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Agent } from "undici";
|
|
2
|
+
import { type LookupFn, type NetPolicy } from "./public-address.js";
|
|
3
|
+
/**
|
|
4
|
+
* `fetch` for URLs that come from a marketplace or an admin (spec §5.1):
|
|
5
|
+
* - https only; plain http only for a loopback host under `allowInsecureLoopback` (testing);
|
|
6
|
+
* - the host is resolved once by {@link resolvePublic} and the connection goes to the checked
|
|
7
|
+
* addresses: a per-request undici `Agent` whose `connect.lookup` answers only those addresses,
|
|
8
|
+
* so there is no second DNS lookup (no rebinding), while the Host header and TLS SNI keep the
|
|
9
|
+
* original hostname;
|
|
10
|
+
* - with `policy.proxy` (`net.httpsProxy`), an https URL whose host is not loopback and not in
|
|
11
|
+
* `noProxy` tunnels through the proxy (`proxy.ts`) instead: the host is not resolved locally
|
|
12
|
+
* (the proxy resolves it and owns SSRF protection for the resolved address), but an IP-literal
|
|
13
|
+
* host is still checked against the private ranges and `allowPrivateHosts`;
|
|
14
|
+
* - redirects are never followed: a 3xx (other than 304) is {@link NetDeniedError} `net.redirect`;
|
|
15
|
+
* - with `maxBytes`, a declared or streamed body over the limit is {@link NetBodyTooLargeError}.
|
|
16
|
+
*/
|
|
17
|
+
/** The response body is larger than `maxBytes`. */
|
|
18
|
+
export declare class NetBodyTooLargeError extends Error {
|
|
19
|
+
readonly maxBytes: number;
|
|
20
|
+
constructor(maxBytes: number);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* An undici dispatcher whose connections go only to `ips` (already checked), whatever the URL's
|
|
24
|
+
* hostname; the hostname still names the Host header and TLS SNI. One agent per download.
|
|
25
|
+
*/
|
|
26
|
+
export declare function pinnedAgent(ips: string[], tls?: {
|
|
27
|
+
ca?: string | string[];
|
|
28
|
+
}): Agent;
|
|
29
|
+
export declare function safeFetch(url: string, init: RequestInit & {
|
|
30
|
+
signal: AbortSignal;
|
|
31
|
+
}, policy: NetPolicy, opts?: {
|
|
32
|
+
lookup?: LookupFn;
|
|
33
|
+
maxBytes?: number;
|
|
34
|
+
/** Tests only: wraps the pinned dispatcher (defaults to {@link pinnedAgent}). */
|
|
35
|
+
dispatcherFor?: (ips: string[]) => Agent;
|
|
36
|
+
/** Tests only: builds the proxy dispatcher (defaults to {@link proxyAgent}). */
|
|
37
|
+
proxyDispatcherFor?: (proxyUrl: string) => Agent;
|
|
38
|
+
}): Promise<Response>;
|