@veris-ai/daytona 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/daytona.ts","../src/errors.ts","../src/control-plane.ts","../src/receipt.ts","../src/network.ts","../src/trust.ts","../src/gateway.ts","../src/veris-api.ts","../src/version.ts"],"sourcesContent":["// @veris-ai/daytona — Veris twin interception for Daytona sandboxes.\n//\n// This is the ENGINE integration, and it is deliberately generic: it knows\n// nothing about what you run in the sandbox, and needs no particular image.\n// Running an agent in there is one use of it (see @veris-ai/daytona-opencode)\n// rather than what it is for — the same relationship @veris-ai/e2b has to E2B.\n//\n// A drop-in for @daytona/sdk. The only difference is that `Daytona` is ours,\n// so every sandbox it creates comes up with a Veris twin already answering its\n// vendor API calls:\n//\n// import { Daytona } from '@veris-ai/daytona' // was '@daytona/sdk'\n// const daytona = new Daytona({ apiKey: process.env.DAYTONA_API_KEY })\n// const sbx = await daytona.create()\n// await sbx.process.executeCommand('curl https://api.stripe.com/v1/charges')\n// await sbx.veris.assertTouched('stripe')\n// await sbx.delete() // deletes the twin too\n//\n// Everything else from @daytona/sdk is re-exported unchanged, so apps depend\n// only on this package.\n//\n// @daytona/sdk is a PEER dependency, deliberately. Consumers do\n// `err instanceof DaytonaNotFoundError` on errors that cross this boundary\n// (the OpenCode plugin branches on exactly that to tell \"sandbox is gone\" from\n// \"transient failure\"), and two copies of the SDK in one tree would make those\n// checks silently return false.\nexport * from '@daytona/sdk'\n\n// Ours wins the name. An explicit local export takes precedence over the star\n// above, which is the whole trick that makes the plugin fork a one-line diff.\nexport { Daytona, default } from './daytona'\nexport type { VerisOpts, VerisDaytonaConfig, VerisSandbox } from './daytona'\nexport { isVerisSandbox } from './daytona'\n\nexport type { VerisApi, TouchMatcher, DeliverToOpts, VerisContext } from './veris-api'\nexport type { Receipt, ReceiptEntry, ReceiptRequest, ReceiptLeak } from './receipt'\nexport type { EgressMode, NetworkParams } from './network'\nexport { DEFAULT_REGISTRY_HOSTS, vendorHosts, twinHosts, dataPlaneHosts } from './network'\nexport type { ServiceInfo as VerisServiceInfo, RouteEntry, TwinSandbox } from './control-plane'\nexport { ControlPlane } from './control-plane'\nexport { CA_CERT_PATH, SYSTEM_BUNDLE, VERIS_BUNDLE, VERIS_CA_FILE, vendoredTrustEnv } from './trust'\nexport { gatewayProxyUrl } from './gateway'\nexport {\n VerisError,\n MissingCredentialsError,\n VerisGatewayUnreachableError,\n VerisGatewayNotOfferedError,\n ReceiptIntegrityError,\n VerisUntouchedError,\n TwinExpiredError,\n SnapshotUnsupportedError,\n UnsupportedOperationError,\n} from './errors'\nexport type { VerisErrorPhase } from './errors'\nexport { SDK_VERSION } from './version'\n","// The Veris Daytona client: a drop-in subclass of @daytona/sdk's Daytona whose\n// sandboxes come up with a Veris twin already answering their vendor calls.\n//\n// Everything the product needs happens inside create() — snapshot registration,\n// twin provisioning, the network allowlist, the CA, starting the proxy and\n// waiting for it to bind. That is deliberate: it keeps the OpenCode plugin's\n// diff to a single changed import, and it means create() resolving is a promise\n// that interception is live.\n//\n// Note we do NOT subclass Sandbox the way @veris-ai/e2b does. Daytona builds\n// Sandbox internally from seven arguments, six of them private SDK types, so\n// there is nothing to extend. We enrich the params, call super, and attach the\n// Veris surface to the instance that comes back.\nimport { Daytona as BaseDaytona } from '@daytona/sdk'\nimport type {\n CreateSandboxFromImageParams,\n CreateSandboxFromSnapshotParams,\n DaytonaConfig,\n Image,\n ListSandboxesQuery,\n Sandbox,\n} from '@daytona/sdk'\nimport { ControlPlane } from './control-plane'\nimport type { TwinSandbox } from './control-plane'\nimport { VerisApiImpl } from './veris-api'\nimport type { VerisApi, VerisContext } from './veris-api'\nimport { buildNetwork, dataPlaneEnv } from './network'\nimport type { EgressMode } from './network'\nimport { CA_CERT_PATH, sanitizeTrustEnv } from './trust'\nimport { gatewayProxyUrl, installCa, probeCanary } from './gateway'\nimport { MissingCredentialsError, VerisError, VerisGatewayNotOfferedError } from './errors'\nimport { SDK_VERSION } from './version'\n\nexport interface VerisOpts {\n /** Veris API key. Falls back to process.env.VERIS_API_KEY. Required. */\n apiKey?: string\n /** Veris environment the twin is deployed from. Falls back to process.env.VERIS_ENVIRONMENT_ID. */\n environmentId?: string\n /** Control plane base. Falls back to process.env.VERIS_API_BASE, then 'https://svc.api.veris.ai'. */\n apiBase?: string\n /** Attach to an EXISTING twin instead of provisioning one (advanced). delete() will NOT remove it. */\n attachSandboxId?: string\n /** Twin TTL backstop, minutes. Default 60, kept in step with the sandbox's ttlMinutes. */\n ttlMinutes?: number\n /** 'strict' (default): the sandbox reaches only its twin, its data planes,\n * the control plane and package registries. 'open': no allowlist at all —\n * debugging only, because a bypassing client then reaches the real vendor. */\n egress?: EgressMode\n /** Extra hostnames to allow out. */\n allowOut?: string[]\n /** Allow package registries (npm, PyPI, apt, …). Default true: a coding\n * sandbox that cannot install dependencies is not usable. */\n allowRegistries?: boolean\n /** Install the gateway CA into the sandbox trust store. Default true; without\n * it every HTTPS call to a vendor host fails certificate validation. */\n installCa?: boolean\n /** Inject { [env_hint]: dsn } for non-HTTP twin services. Default true. */\n dataPlaneEnv?: boolean\n /** Turn Veris off entirely for this create — a plain Daytona sandbox. */\n disabled?: boolean\n}\n\nexport interface VerisDaytonaConfig extends DaytonaConfig {\n veris?: VerisOpts\n}\n\ntype CreateParams = (CreateSandboxFromSnapshotParams | CreateSandboxFromImageParams) & { veris?: VerisOpts }\n\n/** Labels the class stamps so get() can rehydrate without re-asking. */\nconst LABEL = {\n twinId: 'veris_twin_id',\n envId: 'veris_env_id',\n apiBase: 'veris_api_base',\n mode: 'veris_mode',\n egress: 'veris_egress',\n ownsTwin: 'veris_owns_twin',\n canaryHost: 'veris_canary_host',\n} as const\n\nconst VERIS_LABEL_KEYS: readonly string[] = Object.values(LABEL)\n\n/** A Daytona sandbox with the Veris surface attached. */\nexport type VerisSandbox = Sandbox & {\n /** Receipts, services, assertions. Everything Veris adds. */\n veris: VerisApi\n /** The Veris twin's id. Not to be confused with `sandbox.id`, the Daytona one. */\n verisSandboxId: string\n}\n\n/** Is this sandbox one of ours? Narrows for callers who hold a bare Sandbox. */\nexport function isVerisSandbox(sbx: Sandbox): sbx is VerisSandbox {\n return typeof (sbx as VerisSandbox).verisSandboxId === 'string'\n}\n\nexport class Daytona extends BaseDaytona {\n private readonly verisDefaults: VerisOpts\n\n constructor(config?: VerisDaytonaConfig) {\n super(config)\n this.verisDefaults = config?.veris ?? {}\n }\n\n // Both of the base class's overloads, redeclared so a caller passing either\n // params shape still type-checks against the subclass.\n override create(\n params?: CreateSandboxFromSnapshotParams & { veris?: VerisOpts },\n options?: { timeout?: number },\n ): Promise<Sandbox>\n override create(\n params?: CreateSandboxFromImageParams & { veris?: VerisOpts },\n options?: { onSnapshotCreateLogs?: (chunk: string) => void; timeout?: number },\n ): Promise<Sandbox>\n override async create(\n params?: CreateParams,\n options?: { onSnapshotCreateLogs?: (chunk: string) => void; timeout?: number },\n ): Promise<Sandbox> {\n const v: VerisOpts = { ...this.verisDefaults, ...(params?.veris ?? {}) }\n const rest = stripVeris(params)\n\n if (v.disabled) return this.baseCreate(rest, options)\n\n const coords = resolveCoordinates(v)\n const controlPlane = new ControlPlane({\n apiKey: coords.apiKey, apiBase: coords.apiBase, sdkVersion: SDK_VERSION,\n })\n const egress: EgressMode = v.egress ?? 'strict'\n const ttlMinutes = v.ttlMinutes ?? 60\n const ownsTwin = !v.attachSandboxId\n\n // 1. Provision the twin first: the allowlist needs the vendor hostnames it\n // answers for, and the egress credential is minted against it.\n const twin = await this.provisionTwin(controlPlane, v, coords, ttlMinutes)\n const cleanupTwin = async () => {\n if (ownsTwin) await controlPlane.deleteTwin(twin.environment_id, twin.id).catch(() => {})\n }\n\n let sandbox: Sandbox\n let credential\n try {\n // 2. Mint the egress credential. Daytona accepts only http/https outbound\n // proxies, so a control plane that offers SOCKS alone cannot be used\n // here at all — say so plainly rather than failing later in TLS.\n credential = await controlPlane.mintEgressCredential(twin.environment_id, twin.id)\n if (!credential) {\n throw new VerisGatewayNotOfferedError(\n 'this Veris control plane does not offer egress credentials, so there is no gateway ' +\n 'for the sandbox to route through',\n { phase: 'credential-mint', verisSandboxId: twin.id })\n }\n if (!credential.connect_address && !credential.http_proxy_url) {\n throw new VerisGatewayNotOfferedError(\n 'the Veris gateway offers SOCKS5 but no HTTP CONNECT endpoint, and Daytona accepts ' +\n 'only http/https outbound proxies (\"Unsupported outbound proxy scheme\"). Upgrade the ' +\n 'control plane to one that returns connect_address.',\n { phase: 'credential-mint', verisSandboxId: twin.id })\n }\n\n const services = twin.services?.length ? twin.services : await controlPlane.services(twin.id)\n // Validated here, before it reaches either the allowlist or Daytona.\n const proxyUrl = gatewayProxyUrl(credential)\n const network = buildNetwork({\n services, mode: egress,\n // The gateway has to be reachable or nothing is: taken from the URL we\n // are actually going to use, so the two can never disagree.\n gatewayHosts: [new URL(proxyUrl).hostname, credential.canary_host].filter(Boolean),\n allowOut: v.allowOut, allowRegistries: v.allowRegistries,\n })\n\n // Veris-managed vars WIN over caller envs: a caller value for a\n // data-plane env_hint (e.g. DATABASE_URL) would silently point the code\n // under test at production.\n const verisManaged: Record<string, string> = {\n ...(v.installCa !== false ? sanitizeTrustEnv(undefined) : {}),\n ...(v.dataPlaneEnv !== false ? dataPlaneEnv(services) : {}),\n VERIS_SANDBOX_ID: twin.id,\n }\n\n const createParams = {\n ...rest,\n envVars: { ...(rest.envVars ?? {}), ...verisManaged },\n labels: {\n ...reserveLabels(rest.labels),\n [LABEL.twinId]: twin.id,\n [LABEL.envId]: twin.environment_id,\n [LABEL.apiBase]: coords.apiBase,\n [LABEL.egress]: egress,\n [LABEL.ownsTwin]: String(ownsTwin),\n [LABEL.mode]: 'gateway',\n [LABEL.canaryHost]: credential.canary_host,\n },\n ...network,\n // 3. Where Daytona forwards everything the allowlist permits. Chained,\n // not advisory: an unreachable gateway makes allowed traffic 502\n // rather than quietly going direct.\n outboundProxyUrl: proxyUrl,\n ttlMinutes: rest.ttlMinutes ?? ttlMinutes,\n }\n\n sandbox = await this.baseCreate(createParams as CreateParams, options)\n } catch (cause) {\n await cleanupTwin()\n if (cause instanceof VerisError) throw cause\n throw new VerisError('Daytona sandbox create failed', {\n phase: 'sandbox-create', verisSandboxId: twin.id, cause })\n }\n\n // 4. Trust the gateway's CA, then prove the tunnel is live. Until the canary\n // answers, nothing about this sandbox is worth believing.\n try {\n await installCa(sandbox, credential.ca_pem)\n await probeCanary(sandbox, credential.canary_host, twin.id)\n } catch (err) {\n await sandbox.delete().catch(() => {})\n await cleanupTwin()\n throw err\n }\n\n return this.attach(sandbox, {\n controlPlane, environmentId: twin.environment_id, twinId: twin.id,\n egress, ownsTwin, canaryHost: credential.canary_host,\n })\n }\n\n /**\n * Rehydrate the Veris surface on an existing sandbox.\n *\n * Not an optimisation — a necessity. The OpenCode plugin reconnects to a\n * sandbox with get() on every resumed session and deletes through get() too,\n * so a get() that returned a bare Sandbox would mean no receipts after any\n * restart and a leaked twin on every delete.\n */\n override async get(sandboxIdOrName: string): Promise<Sandbox> {\n const sandbox = await super.get(sandboxIdOrName)\n return this.rehydrate(sandbox)\n }\n\n /** Same rehydration for the sandboxes a list() streams. */\n override list(query?: ListSandboxesQuery): AsyncIterableIterator<Sandbox> {\n const inner = super.list(query)\n const rehydrate = (s: Sandbox) => this.rehydrate(s)\n return (async function* () {\n for await (const sandbox of inner) yield rehydrate(sandbox)\n })()\n }\n\n /**\n * Attach the Veris surface to a sandbox whose labels say it has a twin.\n * A sandbox without our labels is passed through untouched — callers can use\n * this client for ordinary Daytona work.\n */\n private rehydrate(sandbox: Sandbox): Sandbox {\n const labels = sandbox.labels ?? {}\n const twinId = labels[LABEL.twinId]\n if (!twinId) return sandbox\n\n const apiKey = this.verisDefaults.apiKey ?? process.env.VERIS_API_KEY\n if (!apiKey) return sandbox // no key: no Veris surface, but not an error\n\n // A trusted source decides where the API key is sent — NEVER the sandbox\n // labels, which a compromised sandbox could rewrite to exfiltrate the key.\n const trustedBase = this.verisDefaults.apiBase ?? process.env.VERIS_API_BASE\n const labelBase = labels[LABEL.apiBase]\n if (trustedBase && labelBase && labelBase !== trustedBase) {\n throw new VerisError(\n `sandbox ${sandbox.id} labels name a different Veris control plane (${labelBase}) than ` +\n `your configuration (${trustedBase}) — refusing to send the API key to an unverified host`,\n { phase: 'attach' })\n }\n const apiBase = trustedBase ?? labelBase ?? 'https://svc.api.veris.ai'\n\n return this.attach(sandbox, {\n controlPlane: new ControlPlane({ apiKey, apiBase, sdkVersion: SDK_VERSION }),\n environmentId: labels[LABEL.envId] ?? '',\n twinId,\n // Re-minted below when a receipt is actually asked for; the label only\n // has to survive the reconnect.\n canaryHost: labels[LABEL.canaryHost] ?? '',\n egress: (labels[LABEL.egress] as EgressMode | undefined) ?? 'strict',\n ownsTwin: labels[LABEL.ownsTwin] !== 'false',\n })\n }\n\n private async provisionTwin(\n controlPlane: ControlPlane, v: VerisOpts, coords: ResolvedCoordinates, ttlMinutes: number,\n ): Promise<TwinSandbox> {\n if (v.attachSandboxId) {\n const existing = await controlPlane.getTwin(v.attachSandboxId)\n if (!existing) {\n throw new VerisError(`attach target ${v.attachSandboxId} not found`, {\n phase: 'twin-provision', verisSandboxId: v.attachSandboxId })\n }\n return existing.status === 'ready' ? existing : controlPlane.waitReady(v.attachSandboxId, 240_000)\n }\n if (!coords.environmentId) {\n throw new MissingCredentialsError(\n 'no Veris environment: set VERIS_ENVIRONMENT_ID, or pass veris.environmentId',\n { phase: 'credentials' })\n }\n const created = await controlPlane.createTwin(coords.environmentId, { ttlMinutes })\n try {\n return await controlPlane.waitReady(created.id, 240_000)\n } catch (e) {\n await controlPlane.deleteTwin(coords.environmentId, created.id).catch(() => {})\n throw e\n }\n }\n\n /**\n * Hang the Veris surface off the instance, and wrap delete() so teardown is\n * automatic.\n *\n * Wrapping rather than asking callers to remember is the point: the OpenCode\n * plugin's existing `sandbox.delete()` then removes the twin too, with no\n * change to the plugin at all. A twin outlives its sandbox otherwise, until\n * its TTL reaps it — invisible until the bill arrives.\n */\n private attach(sandbox: Sandbox, ctx: Omit<VerisContext, 'sandbox'>): Sandbox {\n // Attaching twice would capture our own wrapper as `originalDelete` and\n // tear the twin down twice. Only the prototype's delete is ever wrapped.\n if (isVerisSandbox(sandbox)) return sandbox\n\n const veris = new VerisApiImpl({ ...ctx, sandbox })\n const originalDelete = sandbox.delete.bind(sandbox)\n\n Object.defineProperties(sandbox, {\n veris: { value: veris, enumerable: true, configurable: true },\n verisSandboxId: { value: ctx.twinId, enumerable: true, configurable: true },\n delete: {\n configurable: true,\n value: async (timeout?: number, wait?: boolean): Promise<void> => {\n // Drop the twin before the container goes. Nothing to stop inside\n // the sandbox — the gateway is ours and host-side.\n if (ctx.ownsTwin) {\n await ctx.controlPlane.deleteTwin(ctx.environmentId, ctx.twinId).catch(() => {})\n }\n return originalDelete(timeout, wait)\n },\n },\n })\n return sandbox\n }\n\n /** super.create through the overload the params actually match. */\n private baseCreate(\n params: CreateParams | undefined,\n options?: { onSnapshotCreateLogs?: (chunk: string) => void; timeout?: number },\n ): Promise<Sandbox> {\n type Create = (p?: CreateParams, o?: typeof options) => Promise<Sandbox>\n return (super.create as unknown as Create).call(this, params, options)\n }\n}\n\nexport default Daytona\n\ninterface ResolvedCoordinates {\n apiKey: string\n environmentId?: string\n apiBase: string\n}\n\nfunction resolveCoordinates(v: VerisOpts): ResolvedCoordinates {\n const apiKey = v.apiKey ?? process.env.VERIS_API_KEY\n if (!apiKey) {\n throw new MissingCredentialsError(\n 'no Veris API key: set VERIS_API_KEY in your environment, or pass veris.apiKey. ' +\n 'Get one at https://studio.veris.ai',\n { phase: 'credentials' })\n }\n return {\n apiKey,\n environmentId: v.environmentId ?? process.env.VERIS_ENVIRONMENT_ID,\n apiBase: (v.apiBase ?? process.env.VERIS_API_BASE ?? 'https://svc.api.veris.ai').replace(/\\/$/, ''),\n }\n}\n\nfunction stripVeris(params: CreateParams | undefined): Omit<CreateParams, 'veris'> {\n const { veris: _veris, ...rest } = params ?? {}\n return rest\n}\n\n/** Strip any Veris-reserved keys a caller tried to set in labels. */\nfunction reserveLabels(labels: Record<string, string> | undefined): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [k, val] of Object.entries(labels ?? {})) {\n if (!VERIS_LABEL_KEYS.includes(k)) out[k] = val\n }\n return out\n}\n\nexport { CA_CERT_PATH }\n","/**\n * Every failure phase a Veris error can name. Bring-up spans four systems\n * (control plane, Daytona API, the sandbox, the Veris gateway), so errors\n * carry a structured phase rather than a wall of logs.\n */\nexport type VerisErrorPhase =\n | 'credentials'\n | 'twin-provision'\n | 'gateway-preflight'\n | 'credential-mint'\n | 'sandbox-create'\n | 'ca-install'\n | 'canary'\n | 'receipt'\n | 'attach'\n\n/**\n * Base class for every error this package throws. Deliberately NOT a subclass\n * of any Daytona error: `e instanceof VerisError` cleanly separates Veris\n * failures from Daytona failures in one catch.\n */\nexport class VerisError extends Error {\n readonly phase?: VerisErrorPhase\n /** The Veris twin's sandbox id, when one exists yet. */\n readonly verisSandboxId?: string\n /** Verbatim control-plane response body, when the failure came from an API call. */\n readonly responseBody?: unknown\n\n constructor(\n message: string,\n opts: { phase?: VerisErrorPhase; verisSandboxId?: string; responseBody?: unknown; cause?: unknown } = {},\n ) {\n super(message, opts.cause !== undefined ? { cause: opts.cause } : undefined)\n this.name = new.target.name\n this.phase = opts.phase\n this.verisSandboxId = opts.verisSandboxId\n this.responseBody = opts.responseBody\n }\n}\n\n/** A required credential/coordinate is missing. Thrown before any network call, naming the exact variable. */\nexport class MissingCredentialsError extends VerisError {}\n\n/** The Veris gateway infrastructure is down (control-plane health said so). */\nexport class VerisGatewayUnreachableError extends VerisError {}\n\n/** The control plane does not offer gateway mode (endpoint absent, or this SDK version is below min_sdk). */\nexport class VerisGatewayNotOfferedError extends VerisError {\n /** Server-announced minimum SDK version, when the refusal carried one. */\n readonly minSdk?: string\n constructor(message: string, opts: ConstructorParameters<typeof VerisError>[1] & { minSdk?: string } = {}) {\n super(message, opts)\n this.minSdk = opts.minSdk\n }\n}\n\n/** The canary probe failed: egress is not (or no longer) reaching the twin. */\nexport class ReceiptIntegrityError extends VerisError {}\n\n/** assertTouched(): the named service saw zero intercepted requests — green without the receipt. */\nexport class VerisUntouchedError extends VerisError {\n readonly service: string\n constructor(message: string, service: string, opts: ConstructorParameters<typeof VerisError>[1] = {}) {\n super(message, opts)\n this.service = service\n }\n}\n\n/** The Daytona sandbox is alive but its Veris twin is gone (TTL expiry, delete, reset). */\nexport class TwinExpiredError extends VerisError {}\n\n/** The sandbox image cannot host the Veris layer — in practice, no\n * ca-certificates, so the gateway CA cannot be trusted. */\nexport class SnapshotUnsupportedError extends VerisError {}\n\n/** An inherited Daytona operation that would break the one-sandbox-one-twin invariant (e.g. fork). */\nexport class UnsupportedOperationError extends VerisError {}\n","// Typed client for the Veris control plane (svc.api.veris.ai). Only the routes\n// the SDK needs; shapes mirror the platform's public models.\nimport { VerisError, VerisGatewayNotOfferedError, VerisGatewayUnreachableError, TwinExpiredError } from './errors'\n\nexport interface RouteEntry {\n /** A real vendor hostname the service answers for. */\n host: string\n /** Path prefixes narrowing the claim when several services share the host. */\n paths?: string[] | null\n}\n\nexport interface ServiceInfo {\n name: string\n status: string\n /** What the code under test points at: gateway URL for http services, a DSN for e.g. postgres. */\n url: string\n /** Where /veris/* lives — always an http URL. */\n control_url: string\n env_hint?: string | null\n routes?: RouteEntry[] | null\n}\n\nexport interface TwinSandbox {\n id: string\n environment_id: string\n status: 'provisioning' | 'ready' | 'failed' | 'degraded' | 'terminating' | string\n created_at?: string | null\n expires_at?: string | null\n services: ServiceInfo[]\n failure_reason?: string | null\n metadata?: Record<string, string>\n}\n\n/** Response of POST /v1/sandboxes/{sid}/egress-credential (gateway mode). */\nexport interface EgressCredential {\n /** SOCKS5 endpoint. What @veris-ai/e2b uses; Daytona cannot (it accepts only\n * http/https outbound proxies). */\n socks_address: string\n /** HTTP CONNECT endpoint, host:port. Absent on a control plane that predates\n * the CONNECT listener — which is a hard error here, since Daytona has no\n * other way to reach the gateway. */\n connect_address?: string\n /** The CONNECT endpoint as a complete proxy URL, credentials included.\n * Preferred over building one from connect_address: the gateway owns its own\n * auth format, and guessing it is how you end up sending the wrong password. */\n http_proxy_url?: string\n username: string\n password: string\n ca_pem: string\n canary_host: string\n min_sdk?: string\n expires_at?: string\n /** Server-served CA trust env map; the SDK's vendored list is the fallback. */\n trust_env?: Record<string, string>\n}\n\n/** Mutable fields of a running twin. An OMITTED key is left alone; an explicit\n * null is a value (client_base_url: null unregisters). */\nexport interface SandboxPatch {\n ttl_minutes?: number\n client_base_url?: string | null\n}\n\nexport interface ControlPlaneOpts {\n apiKey: string\n apiBase: string\n /** Sent as X-Veris-SDK on every request, so the server can version-gate. */\n sdkVersion: string\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport class ControlPlane {\n readonly apiBase: string\n private readonly headers: Record<string, string>\n\n constructor(opts: ControlPlaneOpts) {\n this.apiBase = opts.apiBase.replace(/\\/$/, '')\n this.headers = {\n 'X-API-Key': opts.apiKey,\n 'X-Veris-SDK': opts.sdkVersion,\n 'Content-Type': 'application/json',\n }\n }\n\n private async request(method: string, path: string, body?: unknown): Promise<Response> {\n let res: Response\n try {\n res = await fetch(`${this.apiBase}${path}`, {\n method,\n headers: this.headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n })\n } catch (cause) {\n throw new VerisError(`Veris control plane unreachable (${method} ${path})`, { cause })\n }\n return res\n }\n\n private async json<T>(res: Response, context: string, phase?: import('./errors').VerisErrorPhase): Promise<T> {\n const text = await res.text()\n let parsed: unknown\n try { parsed = text ? JSON.parse(text) : undefined } catch { parsed = text }\n if (!res.ok) {\n throw new VerisError(`${context}: ${res.status}`, { phase, responseBody: parsed })\n }\n // A success with no body would surface downstream as an opaque\n // \"cannot read properties of undefined\" — turn it into a legible error here.\n if (parsed === undefined) {\n throw new VerisError(`${context}: empty response body`, { phase, responseBody: text })\n }\n return parsed as T\n }\n\n async createTwin(environmentId: string, opts: { ttlMinutes?: number; metadata?: Record<string, string> } = {}): Promise<TwinSandbox> {\n const res = await this.request('POST', `/v1/environments/${environmentId}/sandboxes`, {\n ttl_minutes: opts.ttlMinutes,\n metadata: opts.metadata,\n })\n return this.json<TwinSandbox>(res, `create sandbox in environment ${environmentId}`, 'twin-provision')\n }\n\n async getTwin(sandboxId: string): Promise<TwinSandbox | null> {\n const res = await this.request('GET', `/v1/sandboxes/${sandboxId}`)\n if (res.status === 404) return null\n return this.json<TwinSandbox>(res, `get sandbox ${sandboxId}`)\n }\n\n /** Poll until the twin reports ready. \"failed\" is terminal per the API docs. */\n async waitReady(sandboxId: string, timeoutMs: number): Promise<TwinSandbox> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n const twin = await this.getTwin(sandboxId)\n if (!twin) throw new TwinExpiredError(`Veris sandbox ${sandboxId} disappeared while provisioning`, { verisSandboxId: sandboxId })\n if (twin.status === 'ready') return twin\n if (twin.status === 'failed') {\n throw new VerisError(\n `Veris sandbox ${sandboxId} failed to provision: ${twin.failure_reason ?? 'no failure_reason'}`,\n { phase: 'twin-provision', verisSandboxId: sandboxId })\n }\n if (Date.now() > deadline) {\n throw new VerisError(\n `Veris sandbox ${sandboxId} not ready after ${timeoutMs}ms (status: ${twin.status})`,\n { phase: 'twin-provision', verisSandboxId: sandboxId })\n }\n await sleep(1500)\n }\n }\n\n async services(sandboxId: string): Promise<ServiceInfo[]> {\n const res = await this.request('GET', `/v1/sandboxes/${sandboxId}/services`)\n if (res.status === 404) {\n throw new TwinExpiredError(`Veris sandbox ${sandboxId} not found — expired or deleted`, { verisSandboxId: sandboxId })\n }\n return this.json<ServiceInfo[]>(res, `services of sandbox ${sandboxId}`, 'receipt')\n }\n\n async deleteTwin(environmentId: string, sandboxId: string): Promise<boolean> {\n const res = await this.request('DELETE', `/v1/environments/${environmentId}/sandboxes/${sandboxId}`)\n if (res.status === 404) return false\n if (!res.ok) await this.json(res, `delete sandbox ${sandboxId}`)\n return true\n }\n\n /**\n * Mint (or re-mint) the gateway egress credential for a twin. Returns null\n * when the control plane does not offer gateway mode at all (404 — route\n * absent), so `mode: 'auto'` can fall back; throws VerisGatewayNotOfferedError\n * on an explicit version refusal (409 sdk_too_old).\n */\n async mintEgressCredential(environmentId: string, sandboxId: string): Promise<EgressCredential | null> {\n const res = await this.request('POST', `/v1/environments/${environmentId}/sandboxes/${sandboxId}/egress-credential`)\n if (res.status === 404) return null\n if (res.status === 409) {\n const body = await res.json().catch(() => ({})) as { min_sdk?: string }\n throw new VerisGatewayNotOfferedError(\n `this SDK version is below the control plane's minimum for gateway mode${body.min_sdk ? ` (min_sdk ${body.min_sdk})` : ''} — upgrade @veris-ai/daytona`,\n { phase: 'credential-mint', verisSandboxId: sandboxId, minSdk: body.min_sdk, responseBody: body })\n }\n return this.json<EgressCredential>(res, `mint egress credential for ${sandboxId}`, 'credential-mint')\n }\n\n /** PATCH the twin resource. Omitted fields are untouched by the server. */\n async updateSandbox(environmentId: string, sandboxId: string, patch: SandboxPatch): Promise<void> {\n const res = await this.request('PATCH', `/v1/environments/${environmentId}/sandboxes/${sandboxId}`, patch)\n if (res.status === 404) {\n throw new TwinExpiredError(`Veris sandbox ${sandboxId} not found`, { verisSandboxId: sandboxId })\n }\n if (!res.ok) await this.json(res, `update sandbox ${sandboxId}`)\n }\n\n /** Extend a twin's TTL so it stays in lockstep with an extended Daytona sandbox. */\n async extendTtl(environmentId: string, sandboxId: string, ttlMinutes: number): Promise<void> {\n const res = await this.request('PATCH', `/v1/environments/${environmentId}/sandboxes/${sandboxId}`, { ttl_minutes: ttlMinutes })\n if (res.status === 404) {\n throw new TwinExpiredError(`Veris sandbox ${sandboxId} not found — cannot extend TTL`, { verisSandboxId: sandboxId })\n }\n // 405 = a control plane that does not accept this field yet: tolerated, the\n // original TTL keeps its backstop role and kill() still cleans up.\n if (!res.ok && res.status !== 405) await this.json(res, `extend TTL of ${sandboxId}`)\n }\n\n /** Create-time preflight: is the gateway infrastructure up, per the control plane? */\n async gatewayHealth(): Promise<void> {\n const res = await this.request('GET', '/v1/gateway/health')\n if (res.status === 404) return // control plane predates gateway mode; the credential probe decides\n if (!res.ok) {\n throw new VerisGatewayUnreachableError(\n `Veris gateway reported unhealthy (${res.status})`, { phase: 'gateway-preflight' })\n }\n }\n}\n","// The receipt: what the twin actually received, parsed from each service's\n// /veris/requests log — plus the integrity probe that keeps it honest.\nimport type { Sandbox } from '@daytona/sdk'\nimport { ReceiptIntegrityError, VerisError } from './errors'\nimport type { ServiceInfo } from './control-plane'\n\n/** One intercepted request, from the twin's trace log. */\nexport interface ReceiptRequest {\n method: string\n path: string\n /** null = no response sent (fault hang). */\n status: number | null\n}\n\nexport interface ReceiptEntry {\n /** Count of intercepted requests (real JSON parse, not a regex). */\n requests: number\n /** The twin service's /veris/* control plane. */\n controlUrl: string\n /** Typed request list, newest first. */\n entries: ReceiptRequest[]\n /** Verbatim /veris/requests body. */\n raw: unknown\n}\n\nexport type ReceiptLeak = 'udp-quic-possible' | 'ech-possible'\n\nexport interface Receipt {\n /** Keyed by service name. Partial: indexing an absent service is a type\n * error to handle, not a runtime TypeError to discover. */\n services: Partial<Record<string, ReceiptEntry>>\n /** How the traffic was moved. One tier now: the Veris gateway. */\n mode: 'gateway'\n /** 'verified' iff the canary probe confirmed egress is still tunnelled\n * through the gateway and demuxed to THIS twin. */\n integrity: 'verified'\n /** Known blind spots of THIS receipt. */\n leaks: ReceiptLeak[]\n}\n\ninterface RawRequestsBody { requests?: unknown[] }\n\nexport function parseRequestsBody(body: unknown): { count: number; entries: ReceiptRequest[] } {\n const rows = Array.isArray((body as RawRequestsBody)?.requests)\n ? (body as RawRequestsBody).requests!\n : []\n const entries: ReceiptRequest[] = rows.map((r) => {\n const row = r as Record<string, unknown>\n return {\n method: String(row.method ?? ''),\n path: String(row.path ?? ''),\n status: typeof row.status === 'number' ? row.status : null,\n }\n })\n return { count: entries.length, entries }\n}\n\nexport async function fetchReceiptEntry(svc: ServiceInfo): Promise<ReceiptEntry> {\n const url = `${svc.control_url}/veris/requests`\n const res = await fetch(url)\n const text = await res.text()\n if (!res.ok) {\n throw new VerisError(`could not read receipt for service '${svc.name}' (${res.status})`, {\n phase: 'receipt', responseBody: text.slice(0, 500) })\n }\n let raw: unknown\n try { raw = JSON.parse(text) } catch {\n throw new VerisError(`service '${svc.name}' returned a non-JSON receipt body`, {\n phase: 'receipt', responseBody: text.slice(0, 500) })\n }\n const { count, entries } = parseRequestsBody(raw)\n return { requests: count, controlUrl: svc.control_url, entries, raw }\n}\n","// Builds the Daytona network params.\n//\n// domainAllowList deny-all-except, enforced at the runner. Verified\n// transparent: a client that strips every proxy variable\n// still cannot reach a host directly, so this is a network\n// boundary and not an env-var convention.\n// outboundProxyUrl where Daytona forwards allowed traffic. Chained, not\n// advisory — an unreachable one makes allowed traffic 502.\n//\n// Together those two are the whole mechanism: the allowlist decides what may\n// leave, and the outbound proxy (the Veris gateway) decides what answers.\nimport type { ServiceInfo } from './control-plane'\n\nexport type EgressMode = 'strict' | 'open'\n\n/** A service whose `url` is an HTTP endpoint (vs a wire-protocol DSN). */\nexport const isHttpUrl = (u: string) => /^https?:/.test(u)\n\n/**\n * Vendor hostnames the twin answers for. These MUST be on the allowlist.\n *\n * That reads backwards until you follow the path: the sandbox's traffic goes to\n * Daytona's proxy, which drops anything not allowlisted and forwards the rest\n * to `outboundProxyUrl` — the Veris gateway. So a vendor host that is absent\n * never reaches the gateway and never reaches the twin; it is simply blocked.\n *\n * Allowing it is not a leak, because the allowlist is not what stands between\n * the sandbox and the real vendor — the gateway is. Verified: with every proxy\n * variable stripped, an allowlisted host is still intercepted rather than\n * dialled directly.\n */\nexport function vendorHosts(services: ServiceInfo[]): string[] {\n const hosts = new Set<string>()\n for (const svc of services) {\n for (const r of svc.routes ?? []) hosts.add(r.host)\n }\n return [...hosts].sort()\n}\n\n/** Hosts the twin itself lives at — the proxy must reach these or nothing works. */\nexport function twinHosts(services: ServiceInfo[]): string[] {\n const hosts = new Set<string>()\n for (const svc of services) {\n for (const u of [svc.control_url, svc.url]) {\n if (!u || !isHttpUrl(u)) continue\n try { hosts.add(new URL(u).hostname) } catch { /* skip unparseable */ }\n }\n }\n return [...hosts].sort()\n}\n\n/**\n * Endpoints of non-HTTP data planes (e.g. the pg-gateway a postgres DSN\n * targets). Handed over rather than intercepted, so they need plain\n * reachability on the allowlist or the data plane silently breaks.\n *\n * DSNs come in every shape — with/without credentials, with/without a trailing\n * path, redis/kafka/mongo, IPv6 in brackets, comma-separated multi-host — so we\n * parse with the URL parser (which handles all of them) and only fall back to a\n * regex for exotic non-URL forms. Every host in a multi-host DSN is allowed.\n */\nexport function dataPlaneHosts(services: ServiceInfo[]): string[] {\n const hosts = new Set<string>()\n for (const svc of services) {\n if (!svc.url || isHttpUrl(svc.url)) continue\n for (const h of hostsFromDsn(svc.url)) hosts.add(h)\n }\n return [...hosts].sort()\n}\n\nfunction hostsFromDsn(dsn: string): string[] {\n const out: string[] = []\n try {\n const u = new URL(dsn)\n // URL.hostname keeps IPv6 brackets; strip them for the allowlist entry.\n if (u.hostname) out.push(u.hostname.replace(/^\\[|\\]$/g, ''))\n } catch {\n // Not URL-parseable — fall through to the regex.\n }\n // Multi-host DSNs (mongodb://a:27017,b:27017/db) — the URL parser only sees\n // the first authority, so sweep the raw authority for the rest.\n const authority = dsn.replace(/^[^:]+:\\/\\//, '').split(/[/?]/)[0] ?? ''\n const afterAt = authority.includes('@') ? authority.slice(authority.lastIndexOf('@') + 1) : authority\n for (const part of afterAt.split(',')) {\n const m = part.match(/^\\[?([A-Za-z0-9_.:-]+?)\\]?(?::\\d+)?$/)\n if (m?.[1] && !/^\\d+$/.test(m[1])) out.push(m[1].replace(/^\\[|\\]$/g, ''))\n }\n return out\n}\n\n/**\n * `{ [env_hint]: dsn }` for the twin's non-HTTP data planes — the env the code\n * under test reads (e.g. DATABASE_URL). Sibling of dataPlaneHosts: same field,\n * one derivation, so a new service type changes one place.\n */\nexport function dataPlaneEnv(services: ServiceInfo[]): Record<string, string> {\n const envs: Record<string, string> = {}\n for (const svc of services) {\n if (!svc.env_hint || !svc.url || isHttpUrl(svc.url)) continue\n // The env NAME comes from the control plane and is injected into every\n // command, so it is shape-checked before use: a response naming PATH,\n // NODE_OPTIONS or BASH_ENV would otherwise steer the sandbox's processes.\n if (!isSafeEnvName(svc.env_hint)) continue\n envs[svc.env_hint] = svc.url\n }\n return envs\n}\n\n/** Env names a data-plane hint may claim: conventional SCREAMING_SNAKE, and\n * never one of the process-controlling variables. */\nconst PROCESS_CONTROLLING = new Set([\n 'PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH', 'NODE_OPTIONS', 'BASH_ENV', 'ENV',\n 'PYTHONPATH', 'PYTHONSTARTUP', 'SHELL', 'IFS', 'HOME', 'PROMPT_COMMAND',\n])\nexport function isSafeEnvName(name: string): boolean {\n return /^[A-Z][A-Z0-9_]{0,63}$/.test(name) && !PROCESS_CONTROLLING.has(name)\n}\n\n/**\n * Package registries and toolchain hosts, allowed by default.\n *\n * A coding sandbox that cannot `npm install` is not a coding sandbox, and\n * registries are not vendors under test, so they must stay reachable. Naming\n * them here keeps the list auditable rather than punching a wildcard.\n *\n * Override wholesale with `veris.allowRegistries: false` plus your own\n * `veris.allowOut`, for a sandbox that should reach nothing but its twin.\n */\nexport const DEFAULT_REGISTRY_HOSTS: readonly string[] = [\n // JS\n 'registry.npmjs.org', 'registry.yarnpkg.com',\n // Python\n 'pypi.org', 'files.pythonhosted.org',\n // Go\n 'proxy.golang.org', 'sum.golang.org',\n // Rust\n 'crates.io', 'static.crates.io', 'index.crates.io',\n // Debian/Ubuntu\n 'deb.debian.org', 'security.debian.org', 'archive.ubuntu.com', 'security.ubuntu.com',\n // Source + container hosts the above routinely redirect to\n 'github.com', 'codeload.github.com', 'objects.githubusercontent.com',\n 'raw.githubusercontent.com', 'ghcr.io',\n]\n\nexport interface BuildNetworkArgs {\n services: ServiceInfo[]\n mode: EgressMode\n /** The Veris gateway's host, and the canary hostname it answers on. Without\n * these the sandbox cannot reach the gateway at all. */\n gatewayHosts: string[]\n /** Extra hostnames the caller wants reachable. */\n allowOut?: string[]\n /** Include DEFAULT_REGISTRY_HOSTS. Default true. */\n allowRegistries?: boolean\n}\n\n/** The Daytona create params that decide what the sandbox may reach. */\nexport interface NetworkParams {\n networkBlockAll?: boolean\n domainAllowList?: string\n}\n\n/**\n * Strict (the default) is deny-all-except: the vendor hosts the twin answers\n * for, the gateway itself, the twin's data planes, and package registries.\n *\n * Open sets no allowlist at all. It exists for debugging and is never the\n * default: with no allowlist there is nothing forcing traffic at the gateway,\n * and the receipt cannot tell you what slipped past.\n */\nexport function buildNetwork(args: BuildNetworkArgs): NetworkParams {\n const { services, mode, gatewayHosts, allowOut = [], allowRegistries = true } = args\n if (mode === 'open') return {}\n\n const domains = [\n ...vendorHosts(services),\n ...gatewayHosts,\n ...dataPlaneHosts(services),\n ...(allowRegistries ? DEFAULT_REGISTRY_HOSTS : []),\n ...allowOut,\n ].filter((h): h is string => Boolean(h))\n\n return {\n // NOT networkBlockAll: that blocks everything including the gateway, and the\n // allowlist is what Daytona documents as \"unbypassable network-layer\n // enforcement\". Blocking all and then allowing is not a shape the API\n // offers; a non-empty domainAllowList IS the deny-by-default.\n domainAllowList: [...new Set(domains)].sort().join(','),\n }\n}\n","// CA trust: which env vars point which client stacks at the system bundle,\n// and the single tested install command.\n\n/** Where the Veris CA certificate lands in the Daytona sandbox. This is the\n * standard Debian drop-in directory, so any later `update-ca-certificates`\n * rebuilds the bundle with our cert still included. */\nexport const CA_CERT_PATH = '/usr/local/share/ca-certificates/veris-ca.crt'\n\n/** The distribution's own bundle, when it has one. */\nexport const SYSTEM_BUNDLE = '/etc/ssl/certs/ca-certificates.crt'\n\n/**\n * Our CA alone, world-readable, written before anything needs it.\n * NODE_EXTRA_CA_CERTS is additive by design and takes this.\n */\nexport const VERIS_CA_FILE = '/tmp/veris-ca.crt'\n\n/**\n * The public roots plus ours, concatenated by us.\n *\n * Every path-valued trust var points here rather than at SYSTEM_BUNDLE, because\n * `update-ca-certificates` is not always present — Daytona's default image does\n * not ship it — and a var pointing at a bundle that was never rebuilt trusts\n * everything except the one CA that matters. We write this file ourselves, so\n * it is correct whether or not the distribution has the tooling.\n */\nexport const VERIS_BUNDLE = '/tmp/veris-ca-bundle.crt'\n\n/**\n * The trust variables injected into every sandbox at create time.\n *\n * This is the load-bearing half of CA trust: the gateway forges a leaf for each\n * vendor hostname, and a client that does not trust the Veris CA rejects it, so\n * without these (or the store install below) every HTTPS vendor call fails on\n * certificate validation.\n *\n * Every var is path-valued and points at VERIS_BUNDLE (public roots + ours, so\n * passthrough hosts keep verifying), except NODE_EXTRA_CA_CERTS, which is\n * additive by design and takes the single cert.\n */\nexport function vendoredTrustEnv(): Record<string, string> {\n return {\n SSL_CERT_FILE: VERIS_BUNDLE,\n REQUESTS_CA_BUNDLE: VERIS_BUNDLE,\n CURL_CA_BUNDLE: VERIS_BUNDLE,\n GIT_SSL_CAINFO: VERIS_BUNDLE,\n AWS_CA_BUNDLE: VERIS_BUNDLE,\n CARGO_HTTP_CAINFO: VERIS_BUNDLE,\n DENO_CERT: VERIS_BUNDLE,\n PIP_CERT: VERIS_BUNDLE,\n npm_config_cafile: VERIS_BUNDLE,\n GRPC_DEFAULT_SSL_ROOTS_FILE_PATH: VERIS_BUNDLE,\n BUNDLE_SSL_CA_CERT: VERIS_BUNDLE,\n COMPOSER_CAFILE: VERIS_BUNDLE,\n HEX_CACERTS_PATH: VERIS_BUNDLE,\n JULIA_SSL_CA_ROOTS_PATH: VERIS_BUNDLE,\n NIX_SSL_CERT_FILE: VERIS_BUNDLE,\n PERL_LWP_SSL_CA_FILE: VERIS_BUNDLE,\n CLOUDSDK_CORE_CUSTOM_CA_CERTS_FILE: VERIS_BUNDLE,\n NODE_EXTRA_CA_CERTS: VERIS_CA_FILE,\n }\n}\n\n/**\n * The store-based install, for stacks that read a trust store rather than an\n * env var — a Java client honours no CA variable at all. Rebuilds the system\n * bundle with the Veris CA (already at CA_CERT_PATH), imports it into the JVM\n * cacerts (`|| true`: no Java → skipped), and adds it to NSS databases when\n * certutil exists.\n *\n * Entirely best-effort: it needs root and tooling the image may not have, which\n * is why VERIS_BUNDLE plus the trust variables — not this — is what actually\n * makes interception work.\n */\nexport const CA_INSTALL_CMD = [\n 'update-ca-certificates',\n `(keytool -importcert -noprompt -cacerts -storepass changeit -alias veris -file ${CA_CERT_PATH} 2>/dev/null || true)`,\n '(command -v certutil >/dev/null 2>&1 && ' +\n 'for db in $(find /home /root -maxdepth 4 -name \"cert9.db\" 2>/dev/null | xargs -r -n1 dirname); do ' +\n `certutil -A -n veris -t \"C,,\" -i ${CA_CERT_PATH} -d \"sql:$db\" 2>/dev/null || true; done || true)`,\n].join(' && ')\n\n/**\n * Sanitize a server-served trust_env map before injecting it into the sandbox.\n * A control-plane response must never become arbitrary env-var injection, so\n * only known trust variables survive, and every value is forced to a\n * path-shaped string (the vars are all CA *file paths*). Unknown keys and\n * non-path values are dropped. Returns the vendored map when nothing valid\n * remains.\n */\nexport function sanitizeTrustEnv(served: Record<string, unknown> | undefined): Record<string, string> {\n const vendored = vendoredTrustEnv()\n // Start from the vendored map so a single bad or absent served value falls\n // back PER KEY to the known-good default, rather than dropping that variable\n // and leaving (e.g.) Python's requests with no CA bundle.\n const out: Record<string, string> = { ...vendored }\n for (const [k, val] of Object.entries(served ?? {})) {\n if (!(k in vendored)) continue // unknown key: never injected\n if (typeof val !== 'string') continue\n // Absolute path; allow the common path characters (incl. + and ~).\n if (!/^\\/[\\w./+~-]+$/.test(val)) continue\n out[k] = val\n }\n return out\n}\n","// Gateway mode: the sandbox's egress is routed through the Veris gateway, which\n// answers vendor hostnames from the twin. Nothing Veris runs inside the sandbox\n// but one CA file.\n//\n// This is the same tier @veris-ai/e2b uses (there via network.egressProxy), and\n// the reason Daytona can host it is that outboundProxyUrl is genuinely chained:\n// Daytona's proxy forwards allowed traffic to it and returns 502 when it cannot.\n//\n// Two things still have to happen inside the sandbox, and both are here:\n// install the gateway's CA so the forged vendor leaves validate, and prove the\n// tunnel is actually live before anyone trusts a receipt.\nimport type { Sandbox } from '@daytona/sdk'\nimport { ReceiptIntegrityError, SnapshotUnsupportedError, VerisError } from './errors'\nimport { CA_CERT_PATH, CA_INSTALL_CMD, SYSTEM_BUNDLE, VERIS_BUNDLE, VERIS_CA_FILE } from './trust'\n\n/** A canary hostname must look like a hostname before it goes in a shell command. */\nconst HOSTNAME_RE = /^[A-Za-z0-9.-]+$/\n/** host:port, the only shape an outbound proxy address may take. */\nconst HOSTPORT_RE = /^[A-Za-z0-9.-]+:\\d{1,5}$/\n\n/** Single-quote a string for POSIX sh. */\nexport function shellQuote(s: string): string {\n return `'${s.replace(/'/g, `'\\\\''`)}'`\n}\n\nconst sh = (sandbox: Sandbox, cmd: string, timeoutSec = 60) =>\n sandbox.process.executeCommand(`sh -lc ${shellQuote(cmd)}`, undefined, undefined, timeoutSec)\n\n/**\n * Build the proxy URL Daytona is handed.\n *\n * The username is the tenant demux key — the gateway reads the sandbox id out\n * of it. There is no separate secret: the id IS the capability, exactly as the\n * SOCKS path treats it, so the password is a placeholder the gateway ignores.\n *\n * RFC 3986 §3.2.1 notes that `user:password` in userinfo is deprecated. It is\n * also the only form HTTP proxy clients accept for RFC 7617 Basic credentials,\n * and it is what Daytona forwards, so it is what we emit.\n *\n * `encodeURIComponent` is exactly right for userinfo: everything it leaves raw\n * is unreserved or a sub-delim, and it escapes both separators — `:` to %3A and\n * `@` to %40 — so a username can never break out into the authority.\n *\n * The address is validated rather than interpolated: it arrives from the\n * control plane, and an unchecked value here would land in a URL and then in\n * every client's proxy configuration.\n */\nexport function gatewayProxyUrl(credential: {\n http_proxy_url?: string\n connect_address?: string\n username: string\n}): string {\n // The gateway's own URL wins when it serves one. It knows its auth format —\n // the password is the twin id, not a placeholder — and a locally built URL\n // that guesses wrong authenticates as nobody.\n if (credential.http_proxy_url) return assertProxyUrl(credential.http_proxy_url)\n\n if (!credential.connect_address || !HOSTPORT_RE.test(credential.connect_address)) {\n throw new VerisError(\n `the control plane returned a malformed gateway address: ` +\n `${JSON.stringify(credential.connect_address)} (expected host:port)`,\n { phase: 'credential-mint' })\n }\n return `http://${encodeURIComponent(credential.username)}:x@${credential.connect_address}`\n}\n\n/**\n * A proxy URL from the control plane, before it becomes every client's egress\n * configuration. Untrusted input: it must parse, name a port, and speak a\n * scheme Daytona accepts — it rejects anything but http/https outright.\n */\nfunction assertProxyUrl(raw: string): string {\n let u: URL\n try { u = new URL(raw) } catch {\n throw new VerisError(\n `the control plane returned an unparseable gateway proxy URL: ${JSON.stringify(raw)}`,\n { phase: 'credential-mint' })\n }\n if (u.protocol !== 'http:' && u.protocol !== 'https:') {\n throw new VerisError(\n `the gateway proxy URL uses scheme \"${u.protocol.replace(':', '')}\", and Daytona accepts ` +\n `only http or https outbound proxies`,\n { phase: 'credential-mint' })\n }\n if (!u.hostname || !u.port) {\n throw new VerisError(\n `the gateway proxy URL is missing a host or port: ${JSON.stringify(raw)}`,\n { phase: 'credential-mint' })\n }\n return raw\n}\n\n/**\n * Make the gateway's CA trusted, without requiring anything of the image.\n *\n * Defensive rather than load-bearing on Daytona today, and the distinction is\n * worth recording. Daytona's own proxy terminates TLS with a certificate signed\n * by ITS CA — already trusted in the image — and re-originates to the gateway,\n * so the client never validates our forged leaf. Verified: a vendor call\n * succeeds with --cacert naming only Daytona's CA.\n *\n * We install ours regardless, because the day Daytona tunnels CONNECT\n * end-to-end (the ordinary behaviour for an HTTP proxy) the gateway's leaf\n * reaches the client directly and nothing works without it. One upload and one\n * shell command against a total outage is a trade worth making.\n *\n * The obvious approach — drop the cert in /usr/local/share/ca-certificates and\n * run update-ca-certificates — needs root AND that tool, and Daytona's default\n * image has neither. So the artefact is a bundle we build ourselves at a\n * world-writable path: the distribution's roots (when it has any) plus ours.\n *\n * Daytona overrides the best-known trust variables with its own CA, correctly\n * for its proxy. The dozen it does not set still point at this bundle, which\n * carries both CAs and every public root — so those tools verify rather than\n * break.\n *\n * The system-store install still runs when it can, for anything that reads the\n * store directly rather than honouring the variables. It is best-effort.\n */\nexport async function installCa(sandbox: Sandbox, caPem: string): Promise<void> {\n await sandbox.fs.uploadFile(Buffer.from(caPem, 'utf8'), VERIS_CA_FILE)\n\n const script = [\n `chmod 0644 ${VERIS_CA_FILE}`,\n // Public roots first so they keep working; ours appended. `cat` of a\n // missing file is tolerated — an image with no roots at all still gets a\n // bundle containing the one CA that matters here.\n `{ cat ${SYSTEM_BUNDLE} 2>/dev/null; cat ${VERIS_CA_FILE}; } > ${VERIS_BUNDLE}`,\n `chmod 0644 ${VERIS_BUNDLE}`,\n // Best-effort, for the stacks that read a store rather than a variable:\n // the system bundle, the JVM truststore, and NSS databases. All of it needs\n // root and tooling that may not be there, so none of it is load-bearing —\n // but a Java client honours no CA env var at all, so where we CAN do it,\n // we should.\n `SUDO=; [ \"$(id -u)\" = 0 ] || SUDO=\"sudo -n\"`,\n `($SUDO install -m 0644 -D ${VERIS_CA_FILE} ${CA_CERT_PATH} 2>/dev/null && ` +\n `$SUDO sh -c ${shellQuote(CA_INSTALL_CMD)} 2>/dev/null) || true`,\n // The bundle is the load-bearing one: fail loudly if it is not there.\n `[ -s ${VERIS_BUNDLE} ] && echo __VERIS_CA_OK__`,\n ].join('; ')\n\n const r = await sh(sandbox, script, 120).catch((e: unknown) => ({ exitCode: 1, result: String(e) }))\n if (!(r.result ?? '').includes('__VERIS_CA_OK__')) {\n throw new SnapshotUnsupportedError(\n `could not assemble a CA bundle at ${VERIS_BUNDLE}, so the gateway's certificates ` +\n `cannot be trusted (${(r.result ?? '').trim().slice(0, 200)})`,\n { phase: 'ca-install' })\n }\n}\n\n/**\n * The canary probe: one HTTPS request from inside the sandbox to a reserved\n * hostname only the gateway answers, with the twin id in the body.\n *\n * Green proves three things in a single request — egress really is tunnelled\n * through the gateway, the credential demuxed to the right twin, and the CA\n * install worked. Dialled outside the tunnel the host has no listener, so this\n * cannot pass by accident, which is what makes a receipt worth reading.\n */\nexport async function probeCanary(\n sandbox: Sandbox,\n canaryHost: string,\n expectedTwinId: string,\n): Promise<void> {\n if (!HOSTNAME_RE.test(canaryHost)) {\n throw new ReceiptIntegrityError(\n `refusing to probe a malformed canary host from the control plane: ${JSON.stringify(canaryHost)}`,\n { phase: 'canary', verisSandboxId: expectedTwinId })\n }\n // A non-zero curl exit must surface as a ReceiptIntegrityError, not as the\n // raw command failure, so print a marker and inspect the output ourselves.\n const r = await sh(\n sandbox,\n `curl -sS --cacert ${VERIS_BUNDLE} --max-time 20 https://${canaryHost}/ || echo __VERIS_CANARY_FAIL__`,\n 45,\n ).catch((e: unknown) => ({ exitCode: 1, result: String(e) }))\n\n let body: { veris_sandbox_id?: string } = {}\n try { body = JSON.parse(r.result ?? '') } catch { /* handled below */ }\n if (body.veris_sandbox_id !== expectedTwinId) {\n throw new ReceiptIntegrityError(\n `canary probe failed: egress from this Daytona sandbox is not tunnelled through the ` +\n `Veris gateway (expected twin ${expectedTwinId}, canary answered: ` +\n `${(r.result || 'nothing').trim().slice(0, 200)})`,\n { phase: 'canary', verisSandboxId: expectedTwinId })\n }\n}\n","// The namespaced Veris surface: everything this package adds hangs off\n// `sbx.veris`, matching Daytona's own `sbx.fs` / `sbx.process` idiom so a\n// future @daytona/sdk minor can never collide with a generic method name.\nimport type { Sandbox } from '@daytona/sdk'\nimport type { ControlPlane, ServiceInfo } from './control-plane'\nimport { fetchReceiptEntry } from './receipt'\nimport type { Receipt, ReceiptEntry, ReceiptLeak } from './receipt'\nimport { VerisUntouchedError, VerisError } from './errors'\nimport { dataPlaneEnv, isHttpUrl } from './network'\nimport type { EgressMode } from './network'\nimport { probeCanary } from './gateway'\nimport { vendoredTrustEnv } from './trust'\n\n/** Everything needed to answer Veris queries about a live sandbox. */\nexport interface VerisContext {\n sandbox: Sandbox\n controlPlane: ControlPlane\n environmentId: string\n twinId: string\n egress: EgressMode\n /** The reserved host the canary probe dials to prove the tunnel is live. */\n canaryHost: string\n /** Whether this twin is owned (delete removes it) or attached (caller owns it). */\n ownsTwin: boolean\n}\n\n/** Narrow assertTouched to specific requests. All fields AND together. */\nexport interface TouchMatcher {\n method?: string\n /** Substring match against the request path. */\n path?: string\n /** Minimum matching requests required (default 1). */\n minRequests?: number\n}\n\nexport interface VerisApi {\n /** The Veris twin's sandbox id — NOT the Daytona sandbox id. */\n readonly sandboxId: string\n readonly mode: 'gateway'\n services(): Promise<ServiceInfo[]>\n receipt(): Promise<Receipt>\n receipt(service: string): Promise<ReceiptEntry>\n assertTouched(service: string, match?: TouchMatcher): Promise<void>\n getDataPlaneEnv(): Promise<Record<string, string>>\n getTrustEnv(): Record<string, string>\n deliverTo(port: number, opts?: DeliverToOpts): Promise<string>\n deliverTo(url: string | null, opts?: DeliverToOpts): Promise<string | null>\n}\n\nexport interface DeliverToOpts {\n /** Verify the destination is actually reachable from the twin before\n * returning, via each service's /veris/client/probe. Default true. */\n probe?: boolean\n}\n\nexport class VerisApiImpl implements VerisApi {\n constructor(private readonly ctx: VerisContext) {}\n\n get sandboxId(): string { return this.ctx.twinId }\n get mode(): 'gateway' { return 'gateway' }\n\n services(): Promise<ServiceInfo[]> {\n return this.ctx.controlPlane.services(this.ctx.twinId)\n }\n\n receipt(): Promise<Receipt>\n receipt(service: string): Promise<ReceiptEntry>\n async receipt(service?: string): Promise<Receipt | ReceiptEntry> {\n // Prove egress is STILL tunnelled before trusting any count. A receipt read\n // from a sandbox whose egress was detached would be a confident lie, which\n // is worse than no receipt at all.\n await probeCanary(this.ctx.sandbox, this.ctx.canaryHost, this.ctx.twinId)\n\n const services = await this.services()\n if (service !== undefined) {\n const svc = services.find((s) => s.name === service)\n if (!svc) {\n throw new VerisError(\n `unknown service '${service}' — the twin has no service by that name (available: ${services.map((s) => s.name).join(', ') || 'none'})`,\n { verisSandboxId: this.ctx.twinId })\n }\n return fetchReceiptEntry(svc)\n }\n const entries = await Promise.all(\n services.filter((s) => isHttpUrl(s.control_url)).map(async (svc) => [svc.name, await fetchReceiptEntry(svc)] as const))\n return {\n services: Object.fromEntries(entries),\n mode: 'gateway',\n integrity: 'verified',\n leaks: this.leaks(),\n }\n }\n\n /**\n * What this receipt cannot see. The gateway relays TCP, so QUIC/HTTP3 and ECH\n * ride around it — named rather than rounded off.\n */\n private leaks(): ReceiptLeak[] {\n return ['udp-quic-possible', 'ech-possible']\n }\n\n async assertTouched(service: string, match?: TouchMatcher): Promise<void> {\n // Throws VerisError (not VerisUntouchedError) for an unknown service — a\n // typo is a different failure from a service that saw zero traffic.\n const entry: ReceiptEntry = await this.receipt(service)\n const need = match?.minRequests ?? 1\n const matched = match\n ? entry.entries.filter((r) =>\n (match.method === undefined || r.method.toUpperCase() === match.method.toUpperCase()) &&\n (match.path === undefined || r.path.includes(match.path)))\n : entry.entries\n if (matched.length < need) {\n const what = match\n ? `matching ${match.method ?? 'ANY'} ${match.path ?? '*'} (${matched.length}/${need})`\n : 'any intercepted requests'\n throw new VerisUntouchedError(\n `service '${service}' saw no ${what} — the code under test never reached it ` +\n `(a green run that skipped its dependency looks identical to a working one)`,\n service, { verisSandboxId: this.ctx.twinId })\n }\n }\n\n async getDataPlaneEnv(): Promise<Record<string, string>> {\n return dataPlaneEnv(await this.services())\n }\n\n /** The CA trust vars injected at create, for callers building their own env. */\n getTrustEnv(): Record<string, string> {\n return vendoredTrustEnv()\n }\n\n /**\n * Point every mocked vendor's callbacks/webhooks at this sandbox.\n *\n * Pass a PORT your app listens on and it resolves the sandbox's own preview\n * URL — the address a vendor would POST to in production. Pass a full URL to\n * use that instead, or null to unregister.\n *\n * One call covers every service: a twin has ONE client, so the control plane\n * fans the destination out to all of them.\n */\n deliverTo(port: number, opts?: DeliverToOpts): Promise<string>\n deliverTo(url: string | null, opts?: DeliverToOpts): Promise<string | null>\n async deliverTo(target: number | string | null, opts: DeliverToOpts = {}): Promise<string | null> {\n const url = typeof target === 'number'\n ? (await this.ctx.sandbox.getPreviewLink(target)).url\n : target\n await this.ctx.controlPlane.updateSandbox(\n this.ctx.environmentId, this.ctx.twinId, { client_base_url: url })\n if (url !== null && opts.probe !== false) await this.probeDelivery(url)\n return url\n }\n\n /** Ask each service to re-probe the registered destination; throw if none can reach it. */\n private async probeDelivery(url: string): Promise<void> {\n const services = (await this.services()).filter((s) => isHttpUrl(s.control_url))\n if (!services.length) return\n const probes = await Promise.all(services.map(async (svc) => {\n try {\n const res = await fetch(`${svc.control_url}/veris/client/probe`, { method: 'POST' })\n return res.ok ? await res.json() as { answered?: boolean } : null\n } catch { return null }\n }))\n if (!probes.some((p) => p?.answered)) {\n throw new VerisError(\n `no service could reach ${url} — is your app listening on that port inside the Daytona sandbox?`,\n { phase: 'receipt', verisSandboxId: this.ctx.twinId, responseBody: probes })\n }\n }\n}\n","// The SDK version sent to the control plane as X-Veris-SDK (it version-gates\n// gateway mode on it). Injected from package.json at build time by tsup's\n// `define`; the fallback keeps `tsx`/vitest runs working from source.\ndeclare const __SDK_VERSION__: string | undefined\n\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ === 'string' ? __SDK_VERSION__ : '0.0.0-dev'\n"],"mappings":"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","names":[]}
@@ -0,0 +1,74 @@
1
+ import type { ServiceInfo } from './control-plane';
2
+ export type EgressMode = 'strict' | 'open';
3
+ /** A service whose `url` is an HTTP endpoint (vs a wire-protocol DSN). */
4
+ export declare const isHttpUrl: (u: string) => boolean;
5
+ /**
6
+ * Vendor hostnames the twin answers for. These MUST be on the allowlist.
7
+ *
8
+ * That reads backwards until you follow the path: the sandbox's traffic goes to
9
+ * Daytona's proxy, which drops anything not allowlisted and forwards the rest
10
+ * to `outboundProxyUrl` — the Veris gateway. So a vendor host that is absent
11
+ * never reaches the gateway and never reaches the twin; it is simply blocked.
12
+ *
13
+ * Allowing it is not a leak, because the allowlist is not what stands between
14
+ * the sandbox and the real vendor — the gateway is. Verified: with every proxy
15
+ * variable stripped, an allowlisted host is still intercepted rather than
16
+ * dialled directly.
17
+ */
18
+ export declare function vendorHosts(services: ServiceInfo[]): string[];
19
+ /** Hosts the twin itself lives at — the proxy must reach these or nothing works. */
20
+ export declare function twinHosts(services: ServiceInfo[]): string[];
21
+ /**
22
+ * Endpoints of non-HTTP data planes (e.g. the pg-gateway a postgres DSN
23
+ * targets). Handed over rather than intercepted, so they need plain
24
+ * reachability on the allowlist or the data plane silently breaks.
25
+ *
26
+ * DSNs come in every shape — with/without credentials, with/without a trailing
27
+ * path, redis/kafka/mongo, IPv6 in brackets, comma-separated multi-host — so we
28
+ * parse with the URL parser (which handles all of them) and only fall back to a
29
+ * regex for exotic non-URL forms. Every host in a multi-host DSN is allowed.
30
+ */
31
+ export declare function dataPlaneHosts(services: ServiceInfo[]): string[];
32
+ /**
33
+ * `{ [env_hint]: dsn }` for the twin's non-HTTP data planes — the env the code
34
+ * under test reads (e.g. DATABASE_URL). Sibling of dataPlaneHosts: same field,
35
+ * one derivation, so a new service type changes one place.
36
+ */
37
+ export declare function dataPlaneEnv(services: ServiceInfo[]): Record<string, string>;
38
+ export declare function isSafeEnvName(name: string): boolean;
39
+ /**
40
+ * Package registries and toolchain hosts, allowed by default.
41
+ *
42
+ * A coding sandbox that cannot `npm install` is not a coding sandbox, and
43
+ * registries are not vendors under test, so they must stay reachable. Naming
44
+ * them here keeps the list auditable rather than punching a wildcard.
45
+ *
46
+ * Override wholesale with `veris.allowRegistries: false` plus your own
47
+ * `veris.allowOut`, for a sandbox that should reach nothing but its twin.
48
+ */
49
+ export declare const DEFAULT_REGISTRY_HOSTS: readonly string[];
50
+ export interface BuildNetworkArgs {
51
+ services: ServiceInfo[];
52
+ mode: EgressMode;
53
+ /** The Veris gateway's host, and the canary hostname it answers on. Without
54
+ * these the sandbox cannot reach the gateway at all. */
55
+ gatewayHosts: string[];
56
+ /** Extra hostnames the caller wants reachable. */
57
+ allowOut?: string[];
58
+ /** Include DEFAULT_REGISTRY_HOSTS. Default true. */
59
+ allowRegistries?: boolean;
60
+ }
61
+ /** The Daytona create params that decide what the sandbox may reach. */
62
+ export interface NetworkParams {
63
+ networkBlockAll?: boolean;
64
+ domainAllowList?: string;
65
+ }
66
+ /**
67
+ * Strict (the default) is deny-all-except: the vendor hosts the twin answers
68
+ * for, the gateway itself, the twin's data planes, and package registries.
69
+ *
70
+ * Open sets no allowlist at all. It exists for debugging and is never the
71
+ * default: with no allowlist there is nothing forcing traffic at the gateway,
72
+ * and the receipt cannot tell you what slipped past.
73
+ */
74
+ export declare function buildNetwork(args: BuildNetworkArgs): NetworkParams;
@@ -0,0 +1,36 @@
1
+ import type { ServiceInfo } from './control-plane';
2
+ /** One intercepted request, from the twin's trace log. */
3
+ export interface ReceiptRequest {
4
+ method: string;
5
+ path: string;
6
+ /** null = no response sent (fault hang). */
7
+ status: number | null;
8
+ }
9
+ export interface ReceiptEntry {
10
+ /** Count of intercepted requests (real JSON parse, not a regex). */
11
+ requests: number;
12
+ /** The twin service's /veris/* control plane. */
13
+ controlUrl: string;
14
+ /** Typed request list, newest first. */
15
+ entries: ReceiptRequest[];
16
+ /** Verbatim /veris/requests body. */
17
+ raw: unknown;
18
+ }
19
+ export type ReceiptLeak = 'udp-quic-possible' | 'ech-possible';
20
+ export interface Receipt {
21
+ /** Keyed by service name. Partial: indexing an absent service is a type
22
+ * error to handle, not a runtime TypeError to discover. */
23
+ services: Partial<Record<string, ReceiptEntry>>;
24
+ /** How the traffic was moved. One tier now: the Veris gateway. */
25
+ mode: 'gateway';
26
+ /** 'verified' iff the canary probe confirmed egress is still tunnelled
27
+ * through the gateway and demuxed to THIS twin. */
28
+ integrity: 'verified';
29
+ /** Known blind spots of THIS receipt. */
30
+ leaks: ReceiptLeak[];
31
+ }
32
+ export declare function parseRequestsBody(body: unknown): {
33
+ count: number;
34
+ entries: ReceiptRequest[];
35
+ };
36
+ export declare function fetchReceiptEntry(svc: ServiceInfo): Promise<ReceiptEntry>;
@@ -0,0 +1,55 @@
1
+ /** Where the Veris CA certificate lands in the Daytona sandbox. This is the
2
+ * standard Debian drop-in directory, so any later `update-ca-certificates`
3
+ * rebuilds the bundle with our cert still included. */
4
+ export declare const CA_CERT_PATH = "/usr/local/share/ca-certificates/veris-ca.crt";
5
+ /** The distribution's own bundle, when it has one. */
6
+ export declare const SYSTEM_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
7
+ /**
8
+ * Our CA alone, world-readable, written before anything needs it.
9
+ * NODE_EXTRA_CA_CERTS is additive by design and takes this.
10
+ */
11
+ export declare const VERIS_CA_FILE = "/tmp/veris-ca.crt";
12
+ /**
13
+ * The public roots plus ours, concatenated by us.
14
+ *
15
+ * Every path-valued trust var points here rather than at SYSTEM_BUNDLE, because
16
+ * `update-ca-certificates` is not always present — Daytona's default image does
17
+ * not ship it — and a var pointing at a bundle that was never rebuilt trusts
18
+ * everything except the one CA that matters. We write this file ourselves, so
19
+ * it is correct whether or not the distribution has the tooling.
20
+ */
21
+ export declare const VERIS_BUNDLE = "/tmp/veris-ca-bundle.crt";
22
+ /**
23
+ * The trust variables injected into every sandbox at create time.
24
+ *
25
+ * This is the load-bearing half of CA trust: the gateway forges a leaf for each
26
+ * vendor hostname, and a client that does not trust the Veris CA rejects it, so
27
+ * without these (or the store install below) every HTTPS vendor call fails on
28
+ * certificate validation.
29
+ *
30
+ * Every var is path-valued and points at VERIS_BUNDLE (public roots + ours, so
31
+ * passthrough hosts keep verifying), except NODE_EXTRA_CA_CERTS, which is
32
+ * additive by design and takes the single cert.
33
+ */
34
+ export declare function vendoredTrustEnv(): Record<string, string>;
35
+ /**
36
+ * The store-based install, for stacks that read a trust store rather than an
37
+ * env var — a Java client honours no CA variable at all. Rebuilds the system
38
+ * bundle with the Veris CA (already at CA_CERT_PATH), imports it into the JVM
39
+ * cacerts (`|| true`: no Java → skipped), and adds it to NSS databases when
40
+ * certutil exists.
41
+ *
42
+ * Entirely best-effort: it needs root and tooling the image may not have, which
43
+ * is why VERIS_BUNDLE plus the trust variables — not this — is what actually
44
+ * makes interception work.
45
+ */
46
+ export declare const CA_INSTALL_CMD: string;
47
+ /**
48
+ * Sanitize a server-served trust_env map before injecting it into the sandbox.
49
+ * A control-plane response must never become arbitrary env-var injection, so
50
+ * only known trust variables survive, and every value is forced to a
51
+ * path-shaped string (the vars are all CA *file paths*). Unknown keys and
52
+ * non-path values are dropped. Returns the vendored map when nothing valid
53
+ * remains.
54
+ */
55
+ export declare function sanitizeTrustEnv(served: Record<string, unknown> | undefined): Record<string, string>;
@@ -0,0 +1,74 @@
1
+ import type { Sandbox } from '@daytona/sdk';
2
+ import type { ControlPlane, ServiceInfo } from './control-plane';
3
+ import type { Receipt, ReceiptEntry } from './receipt';
4
+ import type { EgressMode } from './network';
5
+ /** Everything needed to answer Veris queries about a live sandbox. */
6
+ export interface VerisContext {
7
+ sandbox: Sandbox;
8
+ controlPlane: ControlPlane;
9
+ environmentId: string;
10
+ twinId: string;
11
+ egress: EgressMode;
12
+ /** The reserved host the canary probe dials to prove the tunnel is live. */
13
+ canaryHost: string;
14
+ /** Whether this twin is owned (delete removes it) or attached (caller owns it). */
15
+ ownsTwin: boolean;
16
+ }
17
+ /** Narrow assertTouched to specific requests. All fields AND together. */
18
+ export interface TouchMatcher {
19
+ method?: string;
20
+ /** Substring match against the request path. */
21
+ path?: string;
22
+ /** Minimum matching requests required (default 1). */
23
+ minRequests?: number;
24
+ }
25
+ export interface VerisApi {
26
+ /** The Veris twin's sandbox id — NOT the Daytona sandbox id. */
27
+ readonly sandboxId: string;
28
+ readonly mode: 'gateway';
29
+ services(): Promise<ServiceInfo[]>;
30
+ receipt(): Promise<Receipt>;
31
+ receipt(service: string): Promise<ReceiptEntry>;
32
+ assertTouched(service: string, match?: TouchMatcher): Promise<void>;
33
+ getDataPlaneEnv(): Promise<Record<string, string>>;
34
+ getTrustEnv(): Record<string, string>;
35
+ deliverTo(port: number, opts?: DeliverToOpts): Promise<string>;
36
+ deliverTo(url: string | null, opts?: DeliverToOpts): Promise<string | null>;
37
+ }
38
+ export interface DeliverToOpts {
39
+ /** Verify the destination is actually reachable from the twin before
40
+ * returning, via each service's /veris/client/probe. Default true. */
41
+ probe?: boolean;
42
+ }
43
+ export declare class VerisApiImpl implements VerisApi {
44
+ private readonly ctx;
45
+ constructor(ctx: VerisContext);
46
+ get sandboxId(): string;
47
+ get mode(): 'gateway';
48
+ services(): Promise<ServiceInfo[]>;
49
+ receipt(): Promise<Receipt>;
50
+ receipt(service: string): Promise<ReceiptEntry>;
51
+ /**
52
+ * What this receipt cannot see. The gateway relays TCP, so QUIC/HTTP3 and ECH
53
+ * ride around it — named rather than rounded off.
54
+ */
55
+ private leaks;
56
+ assertTouched(service: string, match?: TouchMatcher): Promise<void>;
57
+ getDataPlaneEnv(): Promise<Record<string, string>>;
58
+ /** The CA trust vars injected at create, for callers building their own env. */
59
+ getTrustEnv(): Record<string, string>;
60
+ /**
61
+ * Point every mocked vendor's callbacks/webhooks at this sandbox.
62
+ *
63
+ * Pass a PORT your app listens on and it resolves the sandbox's own preview
64
+ * URL — the address a vendor would POST to in production. Pass a full URL to
65
+ * use that instead, or null to unregister.
66
+ *
67
+ * One call covers every service: a twin has ONE client, so the control plane
68
+ * fans the destination out to all of them.
69
+ */
70
+ deliverTo(port: number, opts?: DeliverToOpts): Promise<string>;
71
+ deliverTo(url: string | null, opts?: DeliverToOpts): Promise<string | null>;
72
+ /** Ask each service to re-probe the registered destination; throw if none can reach it. */
73
+ private probeDelivery;
74
+ }
@@ -0,0 +1 @@
1
+ export declare const SDK_VERSION: string;
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@veris-ai/daytona",
3
+ "version": "0.1.0",
4
+ "description": "Veris twin interception for Daytona: a drop-in @daytona/sdk whose sandboxes come up with a Veris twin already answering their vendor API calls. Unmodified code, real hostnames, receipts.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "sideEffects": false,
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "engines": {
22
+ "node": ">=20"
23
+ },
24
+ "scripts": {
25
+ "build": "tsup && tsc -p tsconfig.build.json",
26
+ "typecheck": "tsc --noEmit",
27
+ "test": "vitest run",
28
+ "prepublishOnly": "npm run build",
29
+ "dev": "tsup --watch"
30
+ },
31
+ "peerDependencies": {
32
+ "@daytona/sdk": ">=0.204.1 <1"
33
+ },
34
+ "devDependencies": {
35
+ "@daytona/sdk": "^0.204.1",
36
+ "@types/node": "^22",
37
+ "tsup": "^8.5.1",
38
+ "typescript": "^5.6.0",
39
+ "vitest": "^3.2.7"
40
+ },
41
+ "keywords": [
42
+ "veris",
43
+ "daytona",
44
+ "sandbox",
45
+ "integration-testing",
46
+ "agents"
47
+ ],
48
+ "license": "Apache-2.0",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/veris-ai/veris-daytona.git",
52
+ "directory": "veris-daytona"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "homepage": "https://github.com/veris-ai/veris-daytona/tree/main/veris-daytona#readme",
58
+ "bugs": {
59
+ "url": "https://github.com/veris-ai/veris-daytona/issues"
60
+ },
61
+ "author": "Veris AI"
62
+ }