{"version":3,"sources":["../src/index.ts","../src/bundler.ts","../src/host.ts","../src/key-extractor.ts","../src/types.ts","../src/validator.ts","../src/sanitize-stack.ts"],"sourcesContent":["/**\n * Public API for `@directive-run/sandbox`.\n *\n * Single entry point: `runInSandbox({files, timeoutMs})` validates the\n * payload against the AST allowlist, bundles the multi-file payload via\n * esbuild, and executes the result in a bounded worker_threads sandbox.\n * Returns a structured `SandboxResult` with captured logs, the final\n * facts snapshot, and any errors that occurred at any stage.\n *\n * Consumers:\n *\n * - `@directive-run/mcp` — the `run_in_sandbox` MCP tool returns the\n *   result to AI clients alongside a `playground_link` URL.\n * - `directive-docs` — the `/api/run-sandbox` Next.js route wraps this\n *   for the playground page's live DevTools transcript view.\n */\n\nimport { BundleError, bundleSandboxFiles } from \"./bundler.js\";\nimport { WorkerExecError, execInWorker } from \"./host.js\";\nimport { extractDerivationKeys } from \"./key-extractor.js\";\nimport { SandboxError } from \"./types.js\";\nimport type {\n  PlaygroundFile,\n  RunInSandboxInput,\n  SandboxResult,\n} from \"./types.js\";\nimport { validateSandboxInput } from \"./validator.js\";\n\nexport {\n  SandboxError,\n  type PlaygroundFile,\n  type RunInSandboxInput,\n  type SandboxResult,\n} from \"./types.js\";\nexport type { ValidationError } from \"./validator.js\";\nexport { setMaxConcurrentWorkers } from \"./host.js\";\nexport { sanitizeStack } from \"./sanitize-stack.js\";\n\nconst MAX_PAYLOAD_BYTES = 200_000;\nconst MAX_FILES = 10;\nconst MAIN_PATH = \"src/main.ts\";\n\nfunction normalizeInput(input: RunInSandboxInput): PlaygroundFile[] {\n  if (input.files && input.source) {\n    throw new SandboxError(\n      \"pass either `source` or `files`, not both\",\n      \"input-invalid\",\n    );\n  }\n  if (!input.files && !input.source) {\n    throw new SandboxError(\n      \"must pass either `source` or `files`\",\n      \"input-invalid\",\n    );\n  }\n  const files: PlaygroundFile[] = input.files\n    ? input.files\n    : [{ path: MAIN_PATH, source: input.source ?? \"\" }];\n\n  if (files.length === 0) {\n    throw new SandboxError(\"files array is empty\", \"input-invalid\");\n  }\n  if (files.length > MAX_FILES) {\n    throw new SandboxError(\n      `payload exceeds ${MAX_FILES} files`,\n      \"input-invalid\",\n    );\n  }\n  let totalBytes = 0;\n  for (const file of files) {\n    if (typeof file.path !== \"string\" || file.path.length === 0) {\n      throw new SandboxError(\n        \"every file must have a non-empty path\",\n        \"input-invalid\",\n      );\n    }\n    if (typeof file.source !== \"string\" || file.source.length === 0) {\n      throw new SandboxError(\n        `file \"${file.path}\" has empty source`,\n        \"input-invalid\",\n      );\n    }\n    totalBytes += Buffer.byteLength(file.source, \"utf8\");\n  }\n  if (totalBytes > MAX_PAYLOAD_BYTES) {\n    throw new SandboxError(\n      `total payload is ${totalBytes} bytes (max ${MAX_PAYLOAD_BYTES})`,\n      \"input-invalid\",\n    );\n  }\n  // Ensure src/main.ts is present — that's the runner / entry point.\n  if (!files.some((f) => f.path === MAIN_PATH)) {\n    throw new SandboxError(\n      `payload must include \"${MAIN_PATH}\" — the runner entry point`,\n      \"input-invalid\",\n    );\n  }\n  return files;\n}\n\nexport async function runInSandbox(\n  input: RunInSandboxInput,\n): Promise<SandboxResult> {\n  let files: PlaygroundFile[];\n  try {\n    files = normalizeInput(input);\n  } catch (err) {\n    if (err instanceof SandboxError) {\n      return {\n        logs: [],\n        facts: {},\n        derived: {},\n        errors: [err.message],\n        durationMs: 0,\n        timedOut: false,\n      };\n    }\n    throw err;\n  }\n\n  const validationErrors = validateSandboxInput(files);\n  if (validationErrors.length > 0) {\n    return {\n      logs: [],\n      facts: {},\n      derived: {},\n      errors: validationErrors.map(\n        (e) => `${e.path}:${e.line}:${e.column} — ${e.message}`,\n      ),\n      durationMs: 0,\n      timedOut: false,\n    };\n  }\n\n  // Pre-extract derivation key names from the source files so the\n  // worker can iterate them after settle. The `system.derive` proxy\n  // has no `ownKeys` trap.\n  const derivationKeys = extractDerivationKeys(files);\n\n  let bundled: { source: string; bytes: number };\n  try {\n    bundled = await bundleSandboxFiles(files);\n  } catch (err) {\n    if (err instanceof BundleError) {\n      return {\n        logs: [],\n        facts: {},\n        derived: {},\n        errors: [err.message],\n        durationMs: 0,\n        timedOut: false,\n      };\n    }\n    throw err;\n  }\n\n  try {\n    const result = await execInWorker({\n      bundledSource: bundled.source,\n      derivationKeys,\n      timeoutMs: input.timeoutMs,\n      signal: input.signal,\n    });\n    return result;\n  } catch (err) {\n    if (err instanceof WorkerExecError) {\n      return {\n        logs: [],\n        facts: {},\n        derived: {},\n        errors: [err.message],\n        durationMs: 0,\n        timedOut: err.code === \"timeout\",\n      };\n    }\n    throw err;\n  }\n}\n","/**\n * esbuild adapter for the sandbox. Takes the user's multi-file payload\n * and produces a single ESM string the worker can evaluate.\n *\n * `@directive-run/*` packages are marked **external** — the worker\n * imports them at runtime via Node's normal ESM resolver, which finds\n * them in `node_modules`. We don't inline them because (a) bundle size\n * would explode, (b) they're already cached in the parent process so\n * the runtime resolver is fast.\n *\n * The bundler uses the in-memory plugin pattern: every file in the\n * payload is registered as a virtual entry, and relative imports\n * resolve against the in-memory map. esbuild handles TS → JS, top-\n * level await, and ESM linking in one pass.\n */\n\nimport { createRequire } from \"node:module\";\nimport { pathToFileURL } from \"node:url\";\nimport { build } from \"esbuild\";\nimport type { PlaygroundFile } from \"./types.js\";\n\n/**\n * Resolve a `@directive-run/*` bare specifier to an absolute file://\n * URL using the host process's node_modules. Required because the\n * worker imports the bundle from `/tmp` where Node's ESM resolver\n * can't walk up to find `@directive-run/*`. By rewriting\n * to absolute file URLs at bundle time, the worker doesn't need a\n * node_modules anchor.\n *\n * Returns null when the package can't be resolved (e.g. consumer has\n * a different install layout); the caller falls back to leaving the\n * bare specifier in place, which works when the worker IS next to\n * node_modules.\n */\nfunction resolveDirectivePackageToFileUrl(specifier: string): string | null {\n  try {\n    const require = createRequire(import.meta.url);\n    const resolved = require.resolve(specifier);\n    return pathToFileURL(resolved).href;\n  } catch {\n    return null;\n  }\n}\n\nconst ENTRY_PATH = \"src/main.ts\";\nconst VIRTUAL_NAMESPACE = \"directive-sandbox-vfs\";\n\nexport interface BundleResult {\n  /** Single ESM string ready to evaluate inside the worker. */\n  source: string;\n  /** Total bytes of the bundled JS (informational). */\n  bytes: number;\n}\n\nexport class BundleError extends Error {\n  constructor(\n    message: string,\n    public readonly cause?: unknown,\n  ) {\n    super(message);\n    this.name = \"BundleError\";\n  }\n}\n\n/**\n * Find the `var system = createSystem(...)` declaration esbuild\n * emits for the runner and inject a side-channel global assignment\n * immediately after it. Captures the system BEFORE any subsequent\n * `system.start()`, dispatches, or `await system.settle()` can\n * throw — so the worker can post-mortem facts even on a runtime\n * error inside the user's runner.\n *\n * esbuild's output uses `var` for hoisted top-level bindings, and\n * the entry's `const system = createSystem(...)` becomes one of:\n *\n *   var system = createSystem({ ... });\n *   var system2 = createSystem({ ... });   // when \"system\" collides\n *\n * The regex tolerates both. If no match, returns the source\n * unchanged (the entry-file epilogue still handles the clean-run\n * case via the appended assignment).\n */\nfunction injectEarlyCapture(bundled: string): string {\n  const re = /(var\\s+(system\\d*)\\s*=\\s*createSystem\\s*\\([\\s\\S]*?\\)\\s*;)/;\n  const match = bundled.match(re);\n  if (!match) {\n    return bundled;\n  }\n  const decl = match[1]!;\n  const localName = match[2]!;\n  const capture = `\\n(globalThis).__directiveSandbox_system__ = ${localName};\\n`;\n  return bundled.replace(decl, decl + capture);\n}\n\nexport async function bundleSandboxFiles(\n  files: PlaygroundFile[],\n): Promise<BundleResult> {\n  const entry = files.find((f) => f.path === ENTRY_PATH);\n  if (!entry) {\n    throw new BundleError(\n      `payload must include \"${ENTRY_PATH}\" — that's the entry point the runner targets`,\n    );\n  }\n\n  const fileMap = new Map<string, string>();\n  for (const file of files) {\n    fileMap.set(file.path, file.source);\n  }\n\n  try {\n    const result = await build({\n      entryPoints: [`${VIRTUAL_NAMESPACE}:${ENTRY_PATH}`],\n      bundle: true,\n      format: \"esm\",\n      target: \"node20\",\n      platform: \"node\",\n      write: false,\n      logLevel: \"silent\",\n      // The plugin's onResolve below intercepts every `@directive-run/*`\n      // import and rewrites it to an absolute file:// URL (so the\n      // worker can import the bundle from /tmp without needing\n      // node_modules above it). The wildcard external is the safety\n      // net for any specifier the plugin doesn't recognize.\n      external: [\"@directive-run/*\"],\n      // Top-level await is required (the runner does `await system.settle()`)\n      // and node20 supports it natively.\n      supported: { \"top-level-await\": true },\n      plugins: [\n        {\n          name: \"directive-sandbox-vfs\",\n          setup(b) {\n            b.onResolve({ filter: /.*/ }, (args) => {\n              if (args.kind === \"entry-point\") {\n                const path = args.path.replace(`${VIRTUAL_NAMESPACE}:`, \"\");\n                return { path, namespace: VIRTUAL_NAMESPACE };\n              }\n              if (args.namespace !== VIRTUAL_NAMESPACE) {\n                return null;\n              }\n              if (args.path.startsWith(\"@directive-run/\")) {\n                // Rewrite to absolute file:// URL so the worker's\n                // `/tmp/.../bundle.mjs` can import the package without\n                // needing node_modules above /tmp. Falls back to the\n                // bare specifier when resolution fails — the legacy\n                // \"write next to node_modules\" pattern still works\n                // as a backup.\n                const resolved = resolveDirectivePackageToFileUrl(args.path);\n                if (resolved) {\n                  return { external: true, path: resolved };\n                }\n                return { external: true, path: args.path };\n              }\n              if (args.path.startsWith(\"./\") || args.path.startsWith(\"../\")) {\n                // Resolve relative to the importer's path.\n                const importerDir = args.importer.replace(/\\/[^/]+$/, \"\");\n                // The runner imports `./counter.js`; the actual virtual\n                // file lives at `src/counter.ts`. Strip the `.js` and\n                // try both extensions so users can write either.\n                const stripped = args.path\n                  .replace(/^\\.\\//, \"\")\n                  .replace(/\\.js$/, \"\");\n                const candidates = [\n                  `${importerDir}/${stripped}.ts`,\n                  `${importerDir}/${stripped}.js`,\n                  `${importerDir}/${stripped}`,\n                  // Also try the raw path in case the importer's dir\n                  // resolution misses the leading slash.\n                  `${stripped}.ts`,\n                  `${stripped}.js`,\n                ].map((p) => p.replace(/\\/+/g, \"/\"));\n\n                for (const candidate of candidates) {\n                  if (fileMap.has(candidate)) {\n                    return { path: candidate, namespace: VIRTUAL_NAMESPACE };\n                  }\n                }\n                throw new BundleError(\n                  `cannot resolve \"${args.path}\" from \"${args.importer}\" — tried ${candidates.join(\", \")}`,\n                );\n              }\n              throw new BundleError(\n                `unexpected import \"${args.path}\" from \"${args.importer}\" — only relative or @directive-run/* allowed`,\n              );\n            });\n            b.onLoad({ filter: /.*/, namespace: VIRTUAL_NAMESPACE }, (args) => {\n              const contents = fileMap.get(args.path);\n              if (contents === undefined) {\n                throw new BundleError(`virtual file missing: ${args.path}`);\n              }\n              // For the entry file, append a trailing assignment so the\n              // runner's top-level `const system = …` binding ends up on\n              // a side-channel global the worker reads after execution.\n              // ESM module exports are sealed, so we can't patch\n              // `createSystem` post-import; instead we lift the binding\n              // out of the entry module's scope here. The convention is\n              // documented by `@directive-run/scaffold`'s `generateRunner`\n              // which always names the local binding `system`.\n              if (args.path === ENTRY_PATH) {\n                const epilogue = [\n                  \"\",\n                  \"// directive-sandbox: lift the runner's `system` binding\",\n                  \"// onto a side-channel global so the worker can read\",\n                  \"// system.facts.$store.toObject() after execution.\",\n                  \"if (typeof system !== 'undefined') {\",\n                  \"  (globalThis).__directiveSandbox_system__ = system;\",\n                  \"}\",\n                ].join(\"\\n\");\n                return { contents: contents + epilogue, loader: \"ts\" };\n              }\n              return { contents, loader: \"ts\" };\n            });\n          },\n        },\n      ],\n    });\n    const rawSource = result.outputFiles[0]?.text;\n    if (!rawSource) {\n      throw new BundleError(\"esbuild produced no output\");\n    }\n    // Inject an early-capture immediately after `createSystem(...)` so\n    // the worker can read facts even when subsequent runner code throws\n    // (e.g. an async settle() rejection from a bad event payload). The\n    // entry-file epilogue (appended in onLoad) only fires on a clean\n    // run; this regex fires regardless. Idempotent — duplicate\n    // assignments to the same global are harmless.\n    const source = injectEarlyCapture(rawSource);\n    return { source, bytes: Buffer.byteLength(source, \"utf8\") };\n  } catch (err) {\n    if (err instanceof BundleError) {\n      throw err;\n    }\n    throw new BundleError(\n      `bundle failed: ${(err as Error).message ?? String(err)}`,\n      err,\n    );\n  }\n}\n","/**\n * Host-side worker_threads orchestration. Mirrors the lint-runner\n * pattern in `@directive-run/mcp`: spawn a fresh worker per call,\n * race the response against a wall-clock timer, terminate on overrun.\n *\n * Workers are NOT pooled. Each call gets a clean process state — no\n * carry-over globals between snippets, no shared `console` patches,\n * no leaked timers from a prior run. Cold-start is ~5ms which is\n * cheap relative to the 50-200ms a typical Directive demo actually\n * spends in `system.settle()`.\n */\n\nimport { existsSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport type {\n  SandboxResult,\n  WorkerInputMessage,\n  WorkerOutputMessage,\n} from \"./types.js\";\n\nconst MIN_TIMEOUT_MS = 100;\nconst MAX_TIMEOUT_MS = 10_000;\nconst DEFAULT_TIMEOUT_MS = 5_000;\n\n/**\n * Concurrency cap on simultaneously-running workers within one host\n * process. Each worker reserves ~32 MB of heap + a thread; a malicious\n * burst (multi-tab playground, MCP client storm) can spawn enough\n * workers to OOM the surface. Cap to one-per-CPU by default; consumers\n * can override via `setMaxConcurrentWorkers()`. Excess calls queue\n * FIFO and run as slots free.\n */\nconst DEFAULT_MAX_WORKERS = Math.max(\n  1,\n  (globalThis as { navigator?: { hardwareConcurrency?: number } }).navigator\n    ?.hardwareConcurrency ?? 4,\n);\n\nlet maxConcurrentWorkers = DEFAULT_MAX_WORKERS;\nlet activeWorkers = 0;\n\n/**\n * A waiter holds the promise resolver for one caller blocked in\n * `acquireSlot()`. `aborted` lets a caller deregister BEFORE its\n * resolver fires — without this, an abandoned caller (HTTP client\n * disconnect, parent `Promise.race` rejection, AbortSignal trigger)\n * leaves a phantom resolver that bumps `activeWorkers` for a caller\n * that no longer exists, pinning a slot permanently. After enough\n * cancellations the pool deadlocks.\n */\ninterface Waiter {\n  resolve: () => void;\n  reject: (reason: unknown) => void;\n  aborted: boolean;\n}\nconst waiters: Waiter[] = [];\n\n/**\n * Wake the first non-aborted waiter, skipping any that aborted while\n * still queued. The `activeWorkers` increment happens HERE (not in\n * the waiter's resolve path) so a higher new cap or a freed slot\n * cannot accidentally allow more than `maxConcurrentWorkers` to run.\n */\nfunction wakeNextWaiter(): void {\n  while (waiters.length > 0 && activeWorkers < maxConcurrentWorkers) {\n    const next = waiters.shift();\n    if (!next || next.aborted) continue;\n    activeWorkers++;\n    next.resolve();\n    return;\n  }\n}\n\n/**\n * Override the per-process worker cap. Pass `Infinity` to disable.\n * Returns the previous value.\n *\n * Lowering the cap below `activeWorkers` does NOT terminate running\n * workers — the new ceiling applies as those workers drain. New\n * `acquireSlot()` callers queue until `activeWorkers` falls below\n * the new cap. Raising the cap immediately drains any waiters the\n * new ceiling can absorb.\n *\n * @example Cap the worker pool at boot for a Next.js API route\n * ```ts\n * // app/api/sandbox/route.ts — runs once per cold start\n * import { setMaxConcurrentWorkers } from \"@directive-run/sandbox\";\n * setMaxConcurrentWorkers(8);\n * ```\n */\nexport function setMaxConcurrentWorkers(value: number): number {\n  const prev = maxConcurrentWorkers;\n  if (!Number.isFinite(value) && value !== Number.POSITIVE_INFINITY) {\n    return prev;\n  }\n  maxConcurrentWorkers = Math.max(1, Math.floor(value));\n  // Drain waiters the new (higher) cap can absorb. wakeNextWaiter()\n  // checks the cap before each increment so a LOWER cap does nothing\n  // here — drains happen organically as releaseSlot() fires.\n  while (waiters.length > 0 && activeWorkers < maxConcurrentWorkers) {\n    wakeNextWaiter();\n  }\n  return prev;\n}\n\nfunction acquireSlot(signal?: AbortSignal): Promise<void> {\n  if (signal?.aborted) {\n    return Promise.reject(\n      signal.reason instanceof Error\n        ? signal.reason\n        : new Error(\"sandbox: acquireSlot aborted\"),\n    );\n  }\n  if (activeWorkers < maxConcurrentWorkers) {\n    activeWorkers++;\n    return Promise.resolve();\n  }\n  return new Promise<void>((resolve, reject) => {\n    const waiter: Waiter = { resolve, reject, aborted: false };\n    waiters.push(waiter);\n    if (signal) {\n      const onAbort = () => {\n        waiter.aborted = true;\n        reject(\n          signal.reason instanceof Error\n            ? signal.reason\n            : new Error(\"sandbox: acquireSlot aborted\"),\n        );\n        // Don't splice — `wakeNextWaiter()` will skip aborted waiters\n        // naturally. Splicing here would race with concurrent shifts.\n      };\n      signal.addEventListener(\"abort\", onAbort, { once: true });\n      // Decorate resolve/reject to clean up the listener once the\n      // waiter is finally settled (acquired OR aborted).\n      const originalResolve = waiter.resolve;\n      const originalReject = waiter.reject;\n      waiter.resolve = () => {\n        signal.removeEventListener(\"abort\", onAbort);\n        originalResolve();\n      };\n      waiter.reject = (reason) => {\n        signal.removeEventListener(\"abort\", onAbort);\n        originalReject(reason);\n      };\n    }\n  });\n}\n\nfunction releaseSlot(): void {\n  activeWorkers = Math.max(0, activeWorkers - 1);\n  // Only hand the slot off when the cap allows — protects against\n  // `setMaxConcurrentWorkers(lower)` followed by releases that would\n  // otherwise immediately re-saturate above the new ceiling.\n  if (activeWorkers < maxConcurrentWorkers) {\n    wakeNextWaiter();\n  }\n}\n\nasync function resolveWorkerPath(): Promise<string> {\n  // PRIMARY: static URL relative to this module's own file. Bundlers\n  // (Next.js outputFileTracing, esbuild, webpack, etc.) follow this\n  // static reference at build time and include `worker.js` in the\n  // output bundle automatically. Works on Vercel + AWS Lambda + Cloud\n  // Run without any consumer-side config.\n  //\n  // FALLBACK (Vitest dev path): `import.meta.url` resolves to the\n  // .ts source file in tests, so `./worker.js` doesn't exist there —\n  // fall through to `createRequire(import.meta.url).resolve(...)`\n  // which Vitest handles correctly via its SSR loader.\n  try {\n    const staticUrl = new URL(\"./worker.js\", import.meta.url);\n    const path = fileURLToPath(staticUrl);\n    if (existsSync(path)) {\n      return path;\n    }\n  } catch {\n    // fall through\n  }\n  const { createRequire } = await import(\"node:module\");\n  const require = createRequire(import.meta.url);\n  return require.resolve(\"@directive-run/sandbox/worker\");\n}\n\nexport interface HostRunInput {\n  bundledSource: string;\n  /** Derivation key names extracted from the payload's source files. */\n  derivationKeys: string[];\n  timeoutMs?: number;\n  /**\n   * Optional AbortSignal. When the signal aborts BEFORE a worker slot\n   * is acquired, the queued waiter is removed cleanly — no phantom\n   * slot increment. When the signal aborts AFTER worker spawn, the\n   * worker is terminated and the slot released. Callers wiring this\n   * to an HTTP request signal close the connection-cancel → leaked-\n   * slot DoS vector that landed in v0.3.x.\n   */\n  signal?: AbortSignal;\n}\n\nexport class WorkerExecError extends Error {\n  constructor(\n    message: string,\n    public readonly code: \"worker-error\" | \"timeout\",\n  ) {\n    super(message);\n    this.name = \"WorkerExecError\";\n  }\n}\n\nfunction clampTimeout(value: number | undefined): number {\n  const raw = value ?? DEFAULT_TIMEOUT_MS;\n  if (!Number.isFinite(raw)) {\n    return DEFAULT_TIMEOUT_MS;\n  }\n  return Math.min(MAX_TIMEOUT_MS, Math.max(MIN_TIMEOUT_MS, Math.floor(raw)));\n}\n\n/**\n * Try `os.tmpdir()` first (Vercel-friendly: /tmp is the only writable\n * location on serverless functions). Fall back to the sandbox package\n * dir if /tmp ISN'T writable for some reason. The fallback inherits\n * the package's node_modules walking chain so bare specifiers like\n * `@directive-run/core` resolve naturally.\n */\nasync function getTempBundleDir(): Promise<string> {\n  const osTmp = tmpdir();\n  if (existsSync(osTmp)) {\n    return osTmp;\n  }\n  // Reuse the worker-resolution path so we land at the same package\n  // regardless of whether the consumer is in production or Vitest dev.\n  const workerPath = await resolveWorkerPath();\n  // dist/worker.js → ../ → package root.\n  return dirname(dirname(workerPath));\n}\n\n/**\n * Write the bundled snippet to a temp file Node's ESM loader can\n * import via a file:// URL.\n *\n * Previous versions wrote inside the sandbox package's own directory\n * so Node's resolver could walk up to find `@directive-run/core` in\n * node_modules — but Vercel / AWS Lambda / Cloud Run all ship\n * read-only FS outside `/tmp`. The bundler now rewrites\n * `@directive-run/*` imports to ABSOLUTE `file://` URLs of the\n * host's resolved paths (see `bundleSandboxFiles`), so the temp\n * file can live in `/tmp` without needing a node_modules anchor.\n *\n * Caller MUST clean the directory up in a finally block.\n */\nasync function writeBundleToTemp(bundledSource: string): Promise<{\n  bundlePath: string;\n  cleanup: () => void;\n}> {\n  const baseDir = await getTempBundleDir();\n  const dir = mkdtempSync(join(baseDir, \"directive-sandbox-\"));\n  const bundlePath = join(dir, \"bundle.mjs\");\n  writeFileSync(bundlePath, bundledSource, \"utf8\");\n  return {\n    bundlePath,\n    cleanup: () => {\n      try {\n        rmSync(dir, { recursive: true, force: true });\n      } catch {\n        // best-effort\n      }\n    },\n  };\n}\n\nexport async function execInWorker(\n  input: HostRunInput,\n): Promise<SandboxResult> {\n  const timeoutMs = clampTimeout(input.timeoutMs);\n  // Block here until a slot frees. A burst that exceeds the cap is\n  // queued rather than amplified into worker-spawn pressure on the host.\n  // The optional signal lets a cancelled caller deregister from the\n  // wait queue without leaking a phantom slot.\n  await acquireSlot(input.signal);\n  let workerPath: string;\n  let bundlePath: string;\n  let cleanupTempDir: () => void;\n  try {\n    workerPath = await resolveWorkerPath();\n    ({ bundlePath, cleanup: cleanupTempDir } = await writeBundleToTemp(\n      input.bundledSource,\n    ));\n  } catch (err) {\n    // Release the slot if we never made it to the worker construction.\n    releaseSlot();\n    throw err;\n  }\n  const worker = new Worker(workerPath, {\n    // 32 MB heap ceiling — bounded enough to prevent runaway allocations\n    // without crowding the typical demo footprint (~2-5 MB).\n    resourceLimits: {\n      maxOldGenerationSizeMb: 32,\n      maxYoungGenerationSizeMb: 8,\n      codeRangeSizeMb: 16,\n    },\n    // Bypass stderr noise from the worker process showing up in the\n    // host's logs. The transcript captures everything we care about.\n    stderr: false,\n  });\n\n  let timer: NodeJS.Timeout | null = null;\n  let timedOut = false;\n  let aborted = false;\n  let abortListener: (() => void) | null = null;\n  const startMs = Date.now();\n\n  try {\n    const result = await new Promise<SandboxResult>((resolve, reject) => {\n      let settled = false;\n\n      worker.once(\"message\", (msg: WorkerOutputMessage) => {\n        settled = true;\n        if (msg.ok) {\n          resolve(msg.result);\n        } else {\n          reject(new WorkerExecError(msg.error, \"worker-error\"));\n        }\n      });\n\n      worker.once(\"error\", (err: Error) => {\n        settled = true;\n        reject(new WorkerExecError(err.message, \"worker-error\"));\n      });\n\n      worker.once(\"exit\", (code) => {\n        if (!settled && code !== 0 && code !== null) {\n          reject(\n            new WorkerExecError(\n              `worker exited with code ${code} before responding`,\n              \"worker-error\",\n            ),\n          );\n        }\n      });\n\n      timer = setTimeout(() => {\n        timedOut = true;\n        worker.terminate();\n        reject(\n          new WorkerExecError(\n            `wall-clock budget of ${timeoutMs}ms elapsed`,\n            \"timeout\",\n          ),\n        );\n      }, timeoutMs);\n\n      // Post-acquisition signal wiring: when the caller's AbortSignal\n      // fires (HTTP client disconnect, parent cancellation), terminate\n      // the running worker so the slot frees IMMEDIATELY instead of\n      // hanging until `timeoutMs` (up to 10s) elapses. Without this,\n      // an abandoned caller still ties up the slot for the full\n      // worker timeout — driving the per-process pool to deadlock\n      // under sustained disconnect load.\n      if (input.signal) {\n        abortListener = () => {\n          if (settled) return;\n          settled = true;\n          aborted = true;\n          worker.terminate();\n          reject(\n            new WorkerExecError(\n              \"sandbox: aborted by caller signal\",\n              \"worker-error\",\n            ),\n          );\n        };\n        if (input.signal.aborted) {\n          // Pre-acquired-then-aborted — fire synchronously.\n          abortListener();\n        } else {\n          input.signal.addEventListener(\"abort\", abortListener, {\n            once: true,\n          });\n        }\n      }\n\n      const message: WorkerInputMessage = {\n        bundlePath: pathToFileURL(bundlePath).href,\n        timeoutMs,\n        derivationKeys: input.derivationKeys,\n      };\n      worker.postMessage(message);\n    });\n\n    return result;\n  } catch (err) {\n    if (err instanceof WorkerExecError && err.code === \"timeout\") {\n      // The worker captured nothing because we killed it; surface\n      // structured timeout info to the caller.\n      return {\n        logs: [],\n        facts: {},\n        derived: {},\n        errors: [err.message],\n        durationMs: Date.now() - startMs,\n        timedOut: true,\n      };\n    }\n    throw err;\n  } finally {\n    if (timer) {\n      clearTimeout(timer);\n    }\n    if (abortListener && input.signal) {\n      input.signal.removeEventListener(\"abort\", abortListener);\n    }\n    await worker.terminate().catch(() => undefined);\n    cleanupTempDir();\n    releaseSlot();\n    void timedOut;\n    void aborted;\n  }\n}\n","/**\n * Pure regex-based extractor for `derive:` / `derivations:` block keys\n * across a payload of source files. Mirrors the lightweight pattern the\n * docs site's DevTools panel uses for static-structure parsing.\n *\n * `system.derive` is a Proxy with no `ownKeys` trap, so the worker\n * can't enumerate derivations from inside the sandbox. Instead, the\n * host pre-scans source files for the declared keys and forwards them\n * to the worker, which then reads `system.derive[key]` for each.\n *\n * Best-effort: a module that builds derivation keys dynamically (e.g.\n * `derive: Object.fromEntries(keys.map(k => [k, fn]))`) won't be\n * extracted. That's acceptable for the stated goal of \"transcript\n * reflects what the module declared.\"\n */\n\nimport type { PlaygroundFile } from \"./types.js\";\n\n/**\n * Find the matching `}` for the `{` at `openBrace`. Returns the index\n * of the close brace, or -1 if unbalanced.\n */\nfunction findMatchingClose(source: string, openBrace: number): number {\n  let depth = 0;\n  for (let i = openBrace; i < source.length; i++) {\n    const ch = source[i];\n    if (ch === \"{\") depth += 1;\n    else if (ch === \"}\") {\n      depth -= 1;\n      if (depth === 0) return i;\n    }\n  }\n  return -1;\n}\n\n/**\n * Pull top-level `key:` segments out of a brace-balanced block. Keys\n * are found between `,` or `\\n` or the block start at brace depth 0\n * AND paren depth 0. Works for both multi-line and compact `{ a: 1,\n * b: 2 }` forms.\n */\nfunction collectTopLevelKeys(block: string): string[] {\n  const keys: string[] = [];\n  let segStart = 0;\n  let braceDepth = 0;\n  let parenDepth = 0;\n  let bracketDepth = 0;\n\n  const flushSegment = (end: number) => {\n    const seg = block.slice(segStart, end).trim();\n    segStart = end + 1;\n    if (!seg) return;\n    // Tolerate leading quotes for `\"foo\":` quoted keys.\n    const m = seg.match(/^['\"]?(\\w+)['\"]?\\s*:/);\n    if (m) keys.push(m[1]!);\n  };\n\n  for (let j = 0; j < block.length; j++) {\n    const ch = block[j];\n    if (ch === \"{\") braceDepth += 1;\n    else if (ch === \"}\") braceDepth -= 1;\n    else if (ch === \"(\") parenDepth += 1;\n    else if (ch === \")\") parenDepth -= 1;\n    else if (ch === \"[\") bracketDepth += 1;\n    else if (ch === \"]\") bracketDepth -= 1;\n    else if (\n      (ch === \",\" || ch === \"\\n\") &&\n      braceDepth === 0 &&\n      parenDepth === 0 &&\n      bracketDepth === 0\n    ) {\n      flushSegment(j);\n    }\n  }\n  // Final segment (no trailing comma/newline).\n  flushSegment(block.length);\n  return keys;\n}\n\nfunction extractTopLevelKeys(source: string, sectionName: string): string[] {\n  const headerRe = new RegExp(`\\\\b${sectionName}\\\\s*:\\\\s*\\\\{`);\n  const headerMatch = source.match(headerRe);\n  if (!headerMatch || headerMatch.index === undefined) {\n    return [];\n  }\n  const openBrace = source.indexOf(\"{\", headerMatch.index);\n  if (openBrace === -1) {\n    return [];\n  }\n  const closeBrace = findMatchingClose(source, openBrace);\n  if (closeBrace === -1) {\n    return [];\n  }\n  return collectTopLevelKeys(source.slice(openBrace + 1, closeBrace));\n}\n\n/**\n * Collect the union of derivation key names declared across all files\n * in the payload. Looks at both `derive:` (module config block) and\n * `derivations:` (schema block). De-duplicates.\n */\nexport function extractDerivationKeys(files: PlaygroundFile[]): string[] {\n  const seen = new Set<string>();\n  const out: string[] = [];\n  for (const file of files) {\n    for (const k of extractTopLevelKeys(file.source, \"derive\")) {\n      if (!seen.has(k)) {\n        seen.add(k);\n        out.push(k);\n      }\n    }\n    for (const k of extractTopLevelKeys(file.source, \"derivations\")) {\n      if (!seen.has(k)) {\n        seen.add(k);\n        out.push(k);\n      }\n    }\n  }\n  return out;\n}\n","/**\n * Public types for `@directive-run/sandbox`.\n *\n * The package executes user-supplied Directive snippets in a bounded\n * worker_threads sandbox and returns a structured transcript. The\n * shape below is what the MCP `run_in_sandbox` tool returns to the\n * AI client and what `directive.run/playground`'s `/api/run-sandbox`\n * route serializes to JSON.\n */\n\nexport interface PlaygroundFile {\n  /**\n   * Relative path inside the project, e.g. \"src/main.ts\" or\n   * \"src/counter.ts\". One file should be \"src/main.ts\" — that's\n   * the entry point the runner targets.\n   */\n  path: string;\n  /** File contents. */\n  source: string;\n}\n\nexport interface RunInSandboxInput {\n  /** Single-file shortcut. Mapped onto \"src/main.ts\" internally. */\n  source?: string;\n  /** Multi-file payload (the `generate_module` paired output shape). */\n  files?: PlaygroundFile[];\n  /** Wall-clock timeout in milliseconds. Defaults to 5000. Clamped to [100, 10000]. */\n  timeoutMs?: number;\n  /**\n   * Optional cancellation signal. Wire this to your HTTP request's\n   * AbortSignal (Next.js / Express both expose one) so a client that\n   * disconnects mid-flight releases its worker slot immediately\n   * instead of leaking it. Without a signal, an abandoned `runInSandbox`\n   * call still queues into the per-process worker cap and only frees\n   * when the worker times out — under load this drives the cap to\n   * permanent deadlock.\n   */\n  signal?: AbortSignal;\n}\n\nexport interface SandboxResult {\n  /**\n   * Captured `console.log` / `console.warn` / `console.error` lines,\n   * in dispatch order. Each entry is the stringified arguments\n   * joined by \" \" (matches Node's default console format).\n   */\n  logs: string[];\n  /**\n   * Final `system.facts.$store.toObject()` snapshot at end-of-run.\n   * Empty when no system was constructed (e.g. validator rejection).\n   */\n  facts: Record<string, unknown>;\n  /**\n   * Final `system.derive` snapshot — every derivation declared in the\n   * module config, evaluated by reading `system.derive[key]`. Empty\n   * when the module has no `derive:` block or when validation rejected\n   * before bundle. The June 2026 security audit flagged the original\n   * sandbox for snapshotting only facts; modules whose primary product\n   * is a derivation (`status`, `isReady`, etc.) returned an empty-\n   * looking transcript.\n   */\n  derived: Record<string, unknown>;\n  /**\n   * Structured error messages from validation, bundling, or runtime\n   * exceptions. Empty on a clean run.\n   */\n  errors: string[];\n  /** Elapsed wall-clock duration of the worker execution. */\n  durationMs: number;\n  /** True when the wall-clock budget elapsed before settle()/destroy(). */\n  timedOut: boolean;\n}\n\nexport type SandboxErrorCode =\n  | \"validation-failed\"\n  | \"bundle-failed\"\n  | \"worker-error\"\n  | \"timeout\"\n  | \"input-invalid\";\n\nexport class SandboxError extends Error {\n  constructor(\n    message: string,\n    public readonly code: SandboxErrorCode,\n  ) {\n    super(message);\n    this.name = \"SandboxError\";\n  }\n}\n\n/**\n * Wire shape for messages from host → worker. The host writes the\n * bundled snippet to a temp file (so Node's ESM loader can resolve\n * `@directive-run/core` against the parent's node_modules; bare\n * specifiers don't resolve from data: URLs) and passes the file URL.\n * Replies on the same channel with a `SandboxResult`.\n */\nexport interface WorkerInputMessage {\n  /** `file://` URL of the temp .mjs bundle the host wrote. */\n  bundlePath: string;\n  timeoutMs: number;\n  /**\n   * Derivation key names the host extracted from the source files.\n   * `system.derive` is a Proxy with no `ownKeys` trap, so we can't\n   * enumerate from the worker; the host's pre-bundle pass scans the\n   * source for `derive:` and `derivations:` blocks and forwards the\n   * keys here. Worker reads `system.derive[key]` for each.\n   */\n  derivationKeys: string[];\n}\n\n/** Wire shape for messages from worker → host. */\nexport type WorkerOutputMessage =\n  | { ok: true; result: SandboxResult }\n  | { ok: false; error: string };\n","/**\n * AST allowlist validator. Pre-flights every file in the payload\n * BEFORE the bundler so a hostile snippet never reaches the runtime\n * surface. Without this layer, `worker_threads` resource limits\n * (heap-only) leak FS + network access through — a snippet that\n * `import(\"node:fs\")` would still pwn the host process.\n *\n * Allowlist:\n *\n * - Imports: must match `@directive-run/*` (specifically `core`, `ai`,\n *   `query`) OR a relative path ending in `.js` (the multi-file\n *   payload's own files).\n * - Identifier accesses: only the allowlisted Directive API surface\n *   plus `console.*`, `Math.*`, `JSON.*`. Anything that touches\n *   global Node namespaces (`process`, `require`, `fs`, `child_process`,\n *   `net`, `dgram`, `cluster`, etc.) is rejected.\n *\n * Strict by default — we'd rather reject a valid pattern (and learn\n * about it via a real-world report) than ship a \"mostly safe\" sandbox.\n * The Phase 2 plan calls out that we expand based on actual failures.\n *\n * Returns the list of validation errors; an empty list means safe to\n * bundle + execute. Callers should bail on any non-empty result.\n */\n\nimport { Project, SyntaxKind } from \"ts-morph\";\nimport type { PlaygroundFile } from \"./types.js\";\n\n/**\n * Consumer-safe @directive-run/* packages. These are the things a\n * realistic Directive demo might import: the runtime + UI adapters +\n * data primitives. Each has been audited for whether it can pull in a\n * sandbox-escape surface (process, fs, child_process, etc.); the ones\n * listed here can't.\n *\n * Packages deliberately EXCLUDED:\n *\n * - `@directive-run/cli` — uses process.argv + fs.write.\n * - `@directive-run/mcp` — speaks MCP over process.stdin/stdout; we\n *   don't want sandboxed snippets opening a transport.\n * - `@directive-run/sandbox` — sandbox-in-sandbox; needs esbuild +\n *   worker_threads. No legitimate use case.\n * - `@directive-run/vite-plugin-api-proxy` — build tooling, expects a\n *   vite config that isn't present.\n *\n * The denylist below catches anyone who tries to import one of these\n * by pattern; the allowlist catches everything else.\n */\nconst ALLOWED_DIRECTIVE_PACKAGES = new Set<string>([\n  \"core\",\n  \"ai\",\n  \"query\",\n  \"el\",\n  \"react\",\n  \"vue\",\n  \"svelte\",\n  \"solid\",\n  \"lit\",\n  \"optimistic\",\n  \"timeline\",\n  \"mutator\",\n  \"knowledge\",\n  \"scaffold\",\n  \"claude-plugin\",\n  \"lint\",\n  \"sources\",\n]);\n\nconst DENIED_DIRECTIVE_PACKAGES = new Set<string>([\n  \"cli\",\n  \"mcp\",\n  \"sandbox\",\n  \"vite-plugin-api-proxy\",\n]);\n\n/**\n * Extract the package name segment from a @directive-run/* specifier.\n *\n *   \"@directive-run/core\"          → \"core\"\n *   \"@directive-run/ai/openai\"     → \"ai\"\n *   \"@directive-run/react/hooks\"   → \"react\"\n *\n * Returns null when the specifier doesn't match the scope.\n */\nfunction extractDirectivePackage(specifier: string): string | null {\n  const match = specifier.match(/^@directive-run\\/([^/]+)/);\n  return match ? match[1]! : null;\n}\n\nfunction isAllowedImport(specifier: string): boolean {\n  if (/^\\.{1,2}\\/.+\\.js$/.test(specifier)) {\n    return true;\n  }\n  const dpkg = extractDirectivePackage(specifier);\n  if (dpkg === null) {\n    return false;\n  }\n  if (DENIED_DIRECTIVE_PACKAGES.has(dpkg)) {\n    return false;\n  }\n  return ALLOWED_DIRECTIVE_PACKAGES.has(dpkg);\n}\n\n/**\n * Globals/identifiers the snippet may touch at top level. The runner\n * shape `generateRunner` emits + idiomatic Directive demos. Anything\n * else (process, require, fetch, fs, child_process, net, etc.) is a\n * sandbox escape attempt.\n */\nconst ALLOWED_GLOBALS = new Set<string>([\n  // Directive runtime surface\n  \"createSystem\",\n  // We also allow the destructured exports the runner might use:\n  \"system\",\n  // Standard JS we'll let through\n  \"console\",\n  \"Math\",\n  \"JSON\",\n  \"Object\",\n  \"Array\",\n  \"Number\",\n  \"String\",\n  \"Boolean\",\n  \"Symbol\",\n  \"Promise\",\n  \"Error\",\n  \"Date\",\n  \"Map\",\n  \"Set\",\n  \"WeakMap\",\n  \"WeakSet\",\n  \"Reflect\",\n  \"globalThis\",\n  // Top-level await + iteration sugar\n  \"undefined\",\n  \"null\",\n  \"NaN\",\n  \"Infinity\",\n]);\n\n/**\n * Identifiers that ALWAYS represent a sandbox escape — even if they'd\n * be allowed in some other context. Listed explicitly so a reader of\n * the validator can audit the threat model in one place.\n */\nconst DENIED_GLOBALS = new Set<string>([\n  \"process\",\n  \"require\",\n  \"module\",\n  \"__dirname\",\n  \"__filename\",\n  \"fetch\",\n  \"XMLHttpRequest\",\n  \"WebSocket\",\n  \"eval\",\n  \"Function\",\n  // The MCP server runs on Node; these are Node-only globals that\n  // bypass workers' resource isolation entirely.\n  \"Buffer\",\n  \"setImmediate\",\n  \"queueMicrotask\",\n  \"setTimeout\",\n  \"setInterval\",\n  \"clearTimeout\",\n  \"clearInterval\",\n]);\n\nexport interface ValidationError {\n  path: string;\n  line: number;\n  column: number;\n  message: string;\n}\n\nfunction importRejectionMessage(specifier: string): string {\n  const dpkg = extractDirectivePackage(specifier);\n  if (dpkg && DENIED_DIRECTIVE_PACKAGES.has(dpkg)) {\n    return `import \"${specifier}\" is denied — @directive-run/${dpkg} is a build/CLI/sandbox tool, not for use inside a sandboxed demo`;\n  }\n  return `import \"${specifier}\" is not allowed in the sandbox. Allowed: relative \"./X.js\" paths or any of @directive-run/{${Array.from(\n    ALLOWED_DIRECTIVE_PACKAGES,\n  )\n    .sort()\n    .join(\",\")}}.`;\n}\n\nfunction checkImports(\n  fileLabel: string,\n  project: Project,\n  errors: ValidationError[],\n): void {\n  const sourceFile = project.getSourceFileOrThrow(fileLabel);\n  for (const decl of sourceFile.getImportDeclarations()) {\n    const moduleSpecifier = decl.getModuleSpecifierValue();\n    if (!isAllowedImport(moduleSpecifier)) {\n      const { line, column } = sourceFile.getLineAndColumnAtPos(\n        decl.getStart(),\n      );\n      errors.push({\n        path: fileLabel,\n        line,\n        column,\n        message: importRejectionMessage(moduleSpecifier),\n      });\n    }\n  }\n}\n\nfunction checkDynamicImportsAndCalls(\n  fileLabel: string,\n  project: Project,\n  errors: ValidationError[],\n): void {\n  const sourceFile = project.getSourceFileOrThrow(fileLabel);\n  // Reject `import(\"…\")` (dynamic), `require(\"…\")` (CommonJS), and\n  // `new Function(\"…\")` (string-to-code) at any depth.\n  sourceFile.forEachDescendant((node) => {\n    if (node.getKind() === SyntaxKind.ImportKeyword) {\n      const parent = node.getParent();\n      if (parent && parent.getKind() === SyntaxKind.CallExpression) {\n        const { line, column } = sourceFile.getLineAndColumnAtPos(\n          node.getStart(),\n        );\n        errors.push({\n          path: fileLabel,\n          line,\n          column,\n          message: \"dynamic import() is not allowed in the sandbox\",\n        });\n      }\n    }\n    if (node.getKind() === SyntaxKind.NewExpression) {\n      const text = node.getText();\n      if (/^new\\s+Function\\s*\\(/.test(text)) {\n        const { line, column } = sourceFile.getLineAndColumnAtPos(\n          node.getStart(),\n        );\n        errors.push({\n          path: fileLabel,\n          line,\n          column,\n          message: \"new Function(...) is not allowed in the sandbox\",\n        });\n      }\n    }\n  });\n}\n\n/**\n * The June 2026 security audit (docs/security/sandbox-audit-2026-06.md)\n * found that the original \"skip identifiers in property-access position\"\n * rule (added to avoid `{module: x}` false-positives) was a TOTAL bypass:\n * `globalThis.process.exit()` worked because `process` was a property\n * name and got skipped. This pass closes that hole.\n *\n * The threat model: an allowed receiver (`globalThis`, `Object`,\n * `Reflect`, an allowed class) is reached freely, but accessing any\n * denied identifier name on it OR `.constructor` on any value OR\n * calling Function via property-access must be rejected.\n *\n * Rules:\n *\n * 1. Property access (`a.b`) where `b` is in DENIED_GLOBALS — reject.\n *    Catches `globalThis.process`, `globalThis.fetch`, `obj.eval`,\n *    `mod.Function`, etc.\n * 2. Property access where `b` is `constructor` — reject. Catches the\n *    `({}).constructor.constructor(\"...\")()` Function-smuggle chain.\n *    No legitimate Directive use.\n * 3. Element access (`a[\"b\"]`) where `b` is a STRING LITERAL matching\n *    a denied name — reject. Catches `globalThis[\"process\"]`,\n *    `globalThis[\"fetch\"]`, etc. String concatenation\n *    (`globalThis[\"proc\" + \"ess\"]`) isn't catchable at AST time;\n *    documented as a known gap.\n * 4. Element access on `globalThis` with ANY string literal — reject.\n *    Stricter than (3); `globalThis[\"Object\"]` is denied even though\n *    `Object` is allowlisted because there's no legitimate reason\n *    to reach Object via bracket syntax.\n * 5. Call expression where callee is `Function` (free identifier or\n *    property access on globalThis/Object) — reject. Catches\n *    `Function(\"return process\")()` without `new`.\n * 6. `Reflect.get(globalThis, \"X\")` / `Reflect.has(globalThis, \"X\")` /\n *    `Object.getOwnPropertyDescriptor(globalThis, \"X\")` — reject when\n *    first arg is `globalThis` (or any allowed global) and second arg\n *    is a string literal matching a denied name OR `constructor`.\n */\nfunction checkPropertyAccessEscapes(\n  fileLabel: string,\n  project: Project,\n  errors: ValidationError[],\n): void {\n  const sourceFile = project.getSourceFileOrThrow(fileLabel);\n\n  const report = (node: import(\"ts-morph\").Node, message: string) => {\n    const { line, column } = sourceFile.getLineAndColumnAtPos(node.getStart());\n    errors.push({ path: fileLabel, line, column, message });\n  };\n\n  const stripStringLiteral = (text: string): string | null => {\n    const trimmed = text.trim();\n    if (\n      (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n      (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) ||\n      (trimmed.startsWith(\"`\") && trimmed.endsWith(\"`\"))\n    ) {\n      return trimmed.slice(1, -1);\n    }\n    return null;\n  };\n\n  sourceFile.forEachDescendant((node) => {\n    const kind = node.getKind();\n\n    // Rule 1 + 2: PropertyAccessExpression — receiver.name\n    if (kind === SyntaxKind.PropertyAccessExpression) {\n      const name = (node as { getName?: () => string }).getName?.();\n      if (!name) {\n        return;\n      }\n      if (name === \"constructor\") {\n        report(\n          node,\n          \"`.constructor` access is denied in the sandbox (Function-constructor smuggle vector)\",\n        );\n        return;\n      }\n      if (DENIED_GLOBALS.has(name)) {\n        report(\n          node,\n          `\\`.${name}\\` access is denied in the sandbox (FS/network/eval surface) — accessing a denied global via property syntax was the property-access bypass closed in v0.3.0`,\n        );\n        return;\n      }\n    }\n\n    // Rule 3 + 4: ElementAccessExpression — receiver[\"string-literal\"]\n    if (kind === SyntaxKind.ElementAccessExpression) {\n      const expression = (\n        node as { getExpression?: () => { getText: () => string } }\n      ).getExpression?.();\n      const argument = (\n        node as {\n          getArgumentExpression?: () => { getText: () => string } | undefined;\n        }\n      ).getArgumentExpression?.();\n      const receiverText = expression?.getText() ?? \"\";\n      const argText = argument?.getText() ?? \"\";\n      const literal = stripStringLiteral(argText);\n\n      // Rule 4: ANY bracket access on globalThis with a string literal.\n      if (receiverText === \"globalThis\" && literal !== null) {\n        report(\n          node,\n          \"bracket-access on `globalThis` with a string literal is denied in the sandbox (use direct identifier reference for allowlisted names)\",\n        );\n        return;\n      }\n      // Rule 3: bracket access whose literal matches a denied name OR\n      // `constructor`, on ANY receiver.\n      if (literal !== null) {\n        if (literal === \"constructor\" || DENIED_GLOBALS.has(literal)) {\n          report(\n            node,\n            `bracket-access \\`[\"${literal}\"]\\` is denied in the sandbox (would reach a denied name)`,\n          );\n          return;\n        }\n      }\n    }\n\n    // Rule 5: CallExpression with callee `Function(...)` (no `new`).\n    if (kind === SyntaxKind.CallExpression) {\n      const expression = (\n        node as {\n          getExpression?: () => {\n            getKind: () => number;\n            getText: () => string;\n          };\n        }\n      ).getExpression?.();\n      const exprText = expression?.getText() ?? \"\";\n      if (exprText === \"Function\") {\n        report(node, \"`Function(...)` call is denied in the sandbox\");\n        return;\n      }\n      // Rule 6: Reflect.get / Reflect.has / Object.getOwnPropertyDescriptor\n      // with `globalThis` (or any allowed global) + denied string-literal.\n      const reflectAccess = exprText.match(/^(Reflect|Object)\\.(\\w+)$/);\n      if (reflectAccess) {\n        const callExpr = node as {\n          getArguments?: () => { getText: () => string }[];\n        };\n        const args = callExpr.getArguments?.() ?? [];\n        if (args.length >= 2) {\n          const firstArg = args[0]!.getText();\n          const secondArgLiteral = stripStringLiteral(args[1]!.getText());\n          const denyMethods = new Set([\n            \"get\",\n            \"has\",\n            \"getOwnPropertyDescriptor\",\n            \"getOwnPropertyDescriptors\",\n            \"ownKeys\",\n            \"getPrototypeOf\",\n          ]);\n          if (\n            denyMethods.has(reflectAccess[2]!) &&\n            (firstArg === \"globalThis\" || ALLOWED_GLOBALS.has(firstArg)) &&\n            secondArgLiteral !== null &&\n            (secondArgLiteral === \"constructor\" ||\n              DENIED_GLOBALS.has(secondArgLiteral))\n          ) {\n            report(\n              node,\n              `\\`${reflectAccess[1]}.${reflectAccess[2]}(${firstArg}, \"${secondArgLiteral}\")\\` would reach a denied name`,\n            );\n          }\n        }\n      }\n    }\n  });\n}\n\nfunction checkGlobalIdentifiers(\n  fileLabel: string,\n  project: Project,\n  errors: ValidationError[],\n): void {\n  const sourceFile = project.getSourceFileOrThrow(fileLabel);\n  // Walk every Identifier and check whether it resolves to a\n  // top-level binding. We only care about the \"free\" identifiers —\n  // ones the snippet didn't declare via import, var/let/const, or\n  // function/class declaration. Those are globals.\n  const localBindings = new Set<string>();\n  for (const decl of sourceFile.getImportDeclarations()) {\n    for (const n of decl.getNamedImports()) {\n      localBindings.add(n.getName());\n    }\n    const def = decl.getDefaultImport();\n    if (def) localBindings.add(def.getText());\n    const ns = decl.getNamespaceImport();\n    if (ns) localBindings.add(ns.getText());\n  }\n  for (const v of sourceFile.getVariableDeclarations()) {\n    localBindings.add(v.getName());\n  }\n  for (const f of sourceFile.getFunctions()) {\n    const name = f.getName();\n    if (name) localBindings.add(name);\n  }\n  for (const c of sourceFile.getClasses()) {\n    const name = c.getName();\n    if (name) localBindings.add(name);\n  }\n\n  sourceFile.forEachDescendant((node) => {\n    if (node.getKind() !== SyntaxKind.Identifier) {\n      return;\n    }\n    const name = node.getText();\n    if (localBindings.has(name)) {\n      return;\n    }\n    if (ALLOWED_GLOBALS.has(name)) {\n      return;\n    }\n\n    // Skip identifiers in non-reference positions where the name is\n    // just a label, not a binding reference:\n    //\n    // - Property-assignment KEYS in object literals: `{ module: x }`\n    //   — the LHS `module` is a label, not a reference to Node's `module`.\n    // - Property-access NAMES: `obj.foo` — `foo` is a property selector.\n    // - Property-access in shorthand: `{ foo }` — `foo` IS a reference;\n    //   ts-morph's ShorthandPropertyAssignment parents that case, so we\n    //   only filter PropertyAssignment.name and PropertyAccessExpression.name.\n    // - Type-annotation positions: `let x: foo` — `foo` is a type.\n    // - Import/export specifier names.\n    const parent = node.getParent();\n    if (parent) {\n      const parentKind = parent.getKind();\n      // `{ module: x }` — name child of a PropertyAssignment.\n      if (parentKind === SyntaxKind.PropertyAssignment) {\n        const propertyName = (\n          parent as { getNameNode?: () => unknown }\n        ).getNameNode?.();\n        if (propertyName === node) {\n          return;\n        }\n      }\n      // `obj.foo` — `foo` is the .name on the right of a dot.\n      if (parentKind === SyntaxKind.PropertyAccessExpression) {\n        const accessName = (\n          parent as { getNameNode?: () => unknown }\n        ).getNameNode?.();\n        if (accessName === node) {\n          return;\n        }\n      }\n      // `{ foo: bar }` LHS for shorthand-style method declarations.\n      if (parentKind === SyntaxKind.MethodDeclaration) {\n        return;\n      }\n      // import { foo } / import { foo as bar } / export { foo }\n      if (\n        parentKind === SyntaxKind.ImportSpecifier ||\n        parentKind === SyntaxKind.ExportSpecifier ||\n        parentKind === SyntaxKind.NamespaceImport ||\n        parentKind === SyntaxKind.ImportClause\n      ) {\n        return;\n      }\n      // Function/method parameter names.\n      if (parentKind === SyntaxKind.Parameter) {\n        return;\n      }\n      // Type references — `let x: foo` etc.\n      if (\n        parentKind === SyntaxKind.TypeReference ||\n        parentKind === SyntaxKind.TypeQuery\n      ) {\n        return;\n      }\n    }\n\n    if (DENIED_GLOBALS.has(name)) {\n      const { line, column } = sourceFile.getLineAndColumnAtPos(\n        node.getStart(),\n      );\n      errors.push({\n        path: fileLabel,\n        line,\n        column,\n        message: `identifier \"${name}\" is denied in the sandbox (FS/network/eval surface)`,\n      });\n    }\n    // We don't reject unknown identifiers — they might be legitimate\n    // members of an allowlist-imported binding (e.g. `system.events.foo`\n    // — `foo` is an identifier in property-access position). The\n    // import + denylist + dynamic-import check above already covers\n    // the actual escape paths.\n  });\n}\n\nexport function validateSandboxInput(\n  files: PlaygroundFile[],\n): ValidationError[] {\n  const errors: ValidationError[] = [];\n  const project = new Project({\n    useInMemoryFileSystem: true,\n    compilerOptions: {\n      target: 99, // ESNext\n      module: 99, // ESNext\n      allowJs: true,\n      strict: false,\n    },\n  });\n\n  for (const file of files) {\n    project.createSourceFile(file.path, file.source, { overwrite: true });\n  }\n\n  for (const file of files) {\n    checkImports(file.path, project, errors);\n    checkDynamicImportsAndCalls(file.path, project, errors);\n    checkPropertyAccessEscapes(file.path, project, errors);\n    checkGlobalIdentifiers(file.path, project, errors);\n  }\n\n  return errors;\n}\n","/**\n * Strip absolute paths from a stack trace before it crosses the\n * worker→host→client boundary. Stack traces leak the sandbox host's\n * filesystem layout — `/Users/<name>/`, `/home/<user>/`, the mkdtemp\n * bundle directory, and on serverless surfaces `/var/task/...`. These\n * become a fingerprint of the host environment any sandbox client can\n * read. Sanitize once at the boundary so every error path benefits.\n *\n * Lives in its own module because `worker.ts` throws at top-level when\n * loaded outside a worker_threads context — extracting `sanitizeStack`\n * lets the unit test suite import the function directly.\n *\n * Terminator characters in the patterns below intentionally include\n * matched-delimiter punctuation (`)`, `]`, `>`, `\"`, `'`, `,`) so a\n * path inside an `at fn (…)` frame or a JSON-stringified `\"path\"`\n * field is bounded correctly. The character class is shared across\n * POSIX + Windows patterns to keep the boundary consistent.\n */\nconst PATH_TERMINATOR = \"[^\\\\s)\\\\]>\\\"',]\";\n\nexport function sanitizeStack(s: string | undefined): string {\n  if (!s) return \"\";\n  const TAIL = `${PATH_TERMINATOR}+`;\n  return (\n    s\n      // file:// URLs\n      .replace(\n        new RegExp(`file:\\\\/\\\\/\\\\/${PATH_TERMINATOR}+`, \"g\"),\n        \"<sandbox>\",\n      )\n      // UNC paths — must run BEFORE the generic `\\\\` Windows pattern so\n      // `\\\\server\\share\\file` becomes `<unc>`, not `<unc>\\share\\file`.\n      .replace(new RegExp(`\\\\\\\\\\\\\\\\${TAIL}`, \"g\"), \"<unc>\")\n      // Windows drive paths — `C:\\Users\\<user>\\...` and friends.\n      // Captures any drive letter + `\\Users\\<name>` or `\\Documents and Settings\\<name>`.\n      .replace(/[A-Za-z]:\\\\Users\\\\[^\\\\\\s)\\]>\"',]+/g, \"<home>\")\n      .replace(/[A-Za-z]:\\\\Documents and Settings\\\\[^\\\\\\s)\\]>\"',]+/g, \"<home>\")\n      // Generic Windows absolute paths — `C:\\<anything-not-Users>` that\n      // didn't match above. Catches CI runners (`D:\\a\\_work\\…`) and\n      // tempdirs.\n      .replace(/[A-Za-z]:\\\\[^\\\\\\s)\\]>\"',]+(?:\\\\[^\\\\\\s)\\]>\"',]+)+/g, \"<path>\")\n      // POSIX dev-machine home directories — macOS + Linux\n      .replace(new RegExp(`\\\\/Users\\\\/${TAIL}`, \"g\"), \"/<home>\")\n      .replace(new RegExp(`\\\\/home\\\\/${TAIL}`, \"g\"), \"/<home>\")\n      // macOS private-var prefix\n      .replace(new RegExp(`\\\\/private\\\\/var\\\\/${TAIL}`, \"g\"), \"<tmp>\")\n      // serverless lambda / vercel function task root\n      .replace(new RegExp(`\\\\/var\\\\/task\\\\/${TAIL}`, \"g\"), \"<task>\")\n      // generic tmp + lambda-runtime task paths\n      .replace(new RegExp(`\\\\/tmp\\\\/${TAIL}`, \"g\"), \"<tmp>\")\n      // /opt and /usr/local — common Linux distro prefixes that leak\n      // package layout (e.g. `/opt/render/project/src/...`).\n      .replace(new RegExp(`\\\\/opt\\\\/${TAIL}`, \"g\"), \"<opt>\")\n      .replace(new RegExp(`\\\\/usr\\\\/local\\\\/${TAIL}`, \"g\"), \"<usr-local>\")\n      // Common deploy roots — Heroku/Render/Docker/Codespaces/GitHub\n      // Actions all root applications under one of these. Without\n      // these, a worker error from a containerized host leaks the\n      // deploy layout + package versions inside `/app/node_modules/`.\n      .replace(new RegExp(`\\\\/app\\\\/${TAIL}`, \"g\"), \"<app>\")\n      .replace(new RegExp(`\\\\/srv\\\\/${TAIL}`, \"g\"), \"<srv>\")\n      .replace(new RegExp(`\\\\/workspace\\\\/${TAIL}`, \"g\"), \"<workspace>\")\n      .replace(new RegExp(`\\\\/data\\\\/${TAIL}`, \"g\"), \"<data>\")\n      // /etc and /root — high-sensitivity Linux paths (config files,\n      // root home). A snippet that throws referencing one of these\n      // should not echo the absolute path back to the caller.\n      .replace(new RegExp(`\\\\/etc\\\\/${TAIL}`, \"g\"), \"<etc>\")\n      .replace(new RegExp(`\\\\/root\\\\/${TAIL}`, \"g\"), \"<root>\")\n  );\n}\n"],"mappings":"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","names":["src_exports","__export","SandboxError","runInSandbox","sanitizeStack","setMaxConcurrentWorkers","__toCommonJS","import_node_module","import_node_url","import_esbuild","import_meta","resolveDirectivePackageToFileUrl","specifier","resolved","ENTRY_PATH","VIRTUAL_NAMESPACE","BundleError","message","cause","injectEarlyCapture","bundled","re","match","decl","capture","bundleSandboxFiles","files","f","fileMap","file","rawSource","b","args","importerDir","stripped","candidates","p","candidate","contents","epilogue","source","err","import_node_fs","import_node_os","import_node_path","import_node_url","import_node_worker_threads","import_meta","MIN_TIMEOUT_MS","MAX_TIMEOUT_MS","DEFAULT_TIMEOUT_MS","DEFAULT_MAX_WORKERS","maxConcurrentWorkers","activeWorkers","waiters","wakeNextWaiter","next","setMaxConcurrentWorkers","value","prev","acquireSlot","signal","resolve","reject","waiter","onAbort","originalResolve","originalReject","reason","releaseSlot","resolveWorkerPath","staticUrl","path","createRequire","WorkerExecError","message","code","clampTimeout","raw","getTempBundleDir","osTmp","workerPath","writeBundleToTemp","bundledSource","baseDir","dir","bundlePath","execInWorker","input","timeoutMs","cleanupTempDir","err","worker","timer","timedOut","aborted","abortListener","startMs","settled","msg","findMatchingClose","source","openBrace","depth","i","ch","collectTopLevelKeys","block","keys","segStart","braceDepth","parenDepth","bracketDepth","flushSegment","end","seg","m","j","extractTopLevelKeys","sectionName","headerRe","headerMatch","closeBrace","extractDerivationKeys","files","seen","out","file","k","SandboxError","message","code","import_ts_morph","ALLOWED_DIRECTIVE_PACKAGES","DENIED_DIRECTIVE_PACKAGES","extractDirectivePackage","specifier","match","isAllowedImport","dpkg","ALLOWED_GLOBALS","DENIED_GLOBALS","importRejectionMessage","checkImports","fileLabel","project","errors","sourceFile","decl","moduleSpecifier","line","column","checkDynamicImportsAndCalls","node","parent","text","checkPropertyAccessEscapes","report","message","stripStringLiteral","trimmed","kind","name","expression","argument","receiverText","argText","literal","exprText","reflectAccess","args","firstArg","secondArgLiteral","checkGlobalIdentifiers","localBindings","n","def","ns","v","f","c","parentKind","validateSandboxInput","files","file","PATH_TERMINATOR","sanitizeStack","s","TAIL","MAX_PAYLOAD_BYTES","MAX_FILES","MAIN_PATH","normalizeInput","input","SandboxError","files","totalBytes","file","f","runInSandbox","err","validationErrors","validateSandboxInput","e","derivationKeys","extractDerivationKeys","bundled","bundleSandboxFiles","BundleError","execInWorker","WorkerExecError"]}