{"version":3,"file":"sandbox.cjs","names":[],"sources":["../../src/batteries/sandbox/preflight.ts","../../src/batteries/sandbox/observability.ts","../../src/batteries/sandbox/manager.ts","../../src/batteries/sandbox/executor.ts","../../src/batteries/sandbox/tool.ts","../../src/batteries/sandbox/contracts/policy_enforcer.ts","../../src/batteries/sandbox/contracts/file_system.ts","../../src/batteries/sandbox/contracts/search.ts","../../src/batteries/sandbox/contracts/path_translator.ts","../../src/batteries/sandbox/contracts/guest_runtime.ts","../../src/batteries/sandbox/contracts/mime_resolver.ts","../../src/batteries/sandbox/contracts/artifact_minter.ts"],"sourcesContent":["/**\n * Construction-time admission for the sandbox.\n *\n * This is the seam consumed by WP-A1: `createSandbox()` must call this function once and\n * retain the returned, frozen decision.  In particular, WP-A1 must not reproduce the three\n * fallback predicates here; doing so would make the handle's security posture depend on two\n * subtly different implementations.\n */\nimport { isException } from '../../lib/utils/exceptions'\nimport {\n  E_SANDBOX_DEPENDENCY_MISSING,\n  E_SANDBOX_FAILED,\n  E_SANDBOX_UNSUPPORTED_ENV,\n} from './exceptions'\nimport type { SandboxPolicy } from './types'\nimport type { SandboxEventSink } from './observability'\nimport type { SandboxPolicyEnforcer } from './contracts/policy_enforcer'\n\n/** Platform identity supplied by the construction site. */\nexport type SandboxPlatform = 'darwin' | 'linux' | 'win32' | string\n\n/** Inputs to the construction-time environment admission check. */\nexport interface PreflightOptions {\n  /** Policy backend to admit. */\n  readonly enforcer: SandboxPolicyEnforcer\n  /** Platform override, primarily for hermetic tests. */\n  readonly platform?: SandboxPlatform\n  /** Explicit opt-in to run without OS containment when a pre-execution condition applies. */\n  readonly allowUnsandboxedFallback?: boolean\n  /** Claude Code's strict mode: per-call escape/bypass is ignored by the consumer. */\n  readonly strictMode?: boolean\n  /** Whether the optional SRT peer was resolved. Defaults to true for injected test enforcers. */\n  readonly optionalPeerPresent?: boolean\n  /** Receives dependency warnings; warnings never make admission fail. */\n  readonly onSandbox?: SandboxEventSink\n  /** Path redaction is performed by the observability sink, not by this admission check. */\n  readonly fsNodeVersion?: string\n}\n\n/** Immutable decision retained by a sandbox handle for its entire lifetime. */\nexport interface SandboxPreflight {\n  /** Whether the construction opted into fallback. */\n  readonly allowUnsandboxedFallback: boolean\n  /** Whether one of the permitted pre-execution conditions fired. */\n  readonly fallbackFired: boolean\n  /** Whether per-call bypasses must be ignored. */\n  readonly strictMode: boolean\n  /** Non-fatal dependency diagnostics. */\n  readonly dependencyWarnings: readonly string[]\n  /** Version provenance for fs_node, when supplied by the backend. */\n  readonly fsNodeVersion?: string\n}\n\nconst currentPlatform = (): SandboxPlatform =>\n  typeof process !== 'undefined' && typeof process.platform === 'string'\n    ? process.platform\n    : 'browser'\n\n/** Run the once-only, fail-closed environment gauntlet used by `createSandbox()`. */\nexport const preflightSandbox = async (options: PreflightOptions): Promise<SandboxPreflight> => {\n  const platform = options.platform ?? currentPlatform()\n  if (platform === 'win32') {\n    throw new E_SANDBOX_UNSUPPORTED_ENV([\n      'Native Windows is not supported; run the sandbox inside a WSL2 distribution.',\n    ])\n  }\n\n  if (!options.enforcer.isSupported()) {\n    throw new E_SANDBOX_UNSUPPORTED_ENV([\n      'The browser environment has no SRT boundary; use Part B (SES) as the cross-environment layer.',\n    ])\n  }\n\n  const dependencies = await options.enforcer.checkDependencies()\n  const warnings = Object.freeze([...dependencies.warnings])\n  if (dependencies.warnings.length > 0) {\n    options.onSandbox?.({ kind: 'dependency-warnings', warnings })\n  }\n  const optionalPeerPresent = options.optionalPeerPresent ?? true\n  const platformCannotSandbox = options.enforcer.effectivePolicy() === undefined\n  const fallbackCondition =\n    platformCannotSandbox || dependencies.errors.length > 0 || !optionalPeerPresent\n  if (dependencies.errors.length > 0 && !options.allowUnsandboxedFallback) {\n    throw new E_SANDBOX_DEPENDENCY_MISSING([\n      `Sandbox dependencies are unavailable: ${dependencies.errors.join('; ')}`,\n    ])\n  }\n  const fallbackFired = Boolean(options.allowUnsandboxedFallback && fallbackCondition)\n  const result: SandboxPreflight = {\n    allowUnsandboxedFallback: fallbackFired,\n    fallbackFired,\n    strictMode: Boolean(options.strictMode),\n    dependencyWarnings: warnings,\n    ...(options.fsNodeVersion === undefined ? {} : { fsNodeVersion: options.fsNodeVersion }),\n  }\n  return Object.freeze(result)\n}\n\n/** Compatibility alias for the construction-site call in WP-A1. */\nexport const runSandboxPreflight = preflightSandbox\n\n/** Probe spawning after policy admission, rather than as part of preflight. */\nexport const probeSandboxSpawn = async (\n  enforcer: SandboxPolicyEnforcer,\n  policy: SandboxPolicy\n): Promise<void> => {\n  let result: Awaited<ReturnType<SandboxPolicyEnforcer['run']>>\n  try {\n    result = await enforcer.run({\n      argv: ['true'],\n      policy,\n      correlationId: crypto.randomUUID(),\n      cwd: process.cwd(),\n    })\n  } catch (error) {\n    // Preserve policy and lifecycle classifications; only an untyped spawn failure is treated as\n    // the dependency/liveness failure this opt-in probe is designed to detect.\n    if (isException(error) && error.name.startsWith('E_SANDBOX_')) throw error\n    throw new E_SANDBOX_DEPENDENCY_MISSING([`Sandbox spawn probe failed: ${String(error)}`])\n  }\n  const drain = async (stream: ReadableStream<Uint8Array>): Promise<string> => {\n    const reader = stream.getReader()\n    const chunks: Uint8Array[] = []\n    try {\n      for (;;) {\n        const next = await reader.read()\n        if (next.done) break\n        chunks.push(next.value)\n      }\n    } finally {\n      reader.releaseLock()\n    }\n    const bytes = new Uint8Array(chunks.reduce((size, chunk) => size + chunk.length, 0))\n    let offset = 0\n    for (const chunk of chunks) {\n      bytes.set(chunk, offset)\n      offset += chunk.length\n    }\n    return new TextDecoder().decode(bytes)\n  }\n  let stderr: string\n  let completed: Awaited<ReturnType<SandboxPolicyEnforcer['run']>>['completed'] extends Promise<\n    infer T\n  >\n    ? T\n    : never\n  try {\n    ;[, stderr, completed] = await Promise.all([\n      drain(result.stdout),\n      drain(result.stderr),\n      result.completed,\n    ])\n  } catch (error) {\n    if (isException(error) && error.name.startsWith('E_SANDBOX_')) throw error\n    throw new E_SANDBOX_DEPENDENCY_MISSING([\n      `Sandbox spawn probe failed while draining output: ${String(error)}`,\n    ])\n  }\n  if (completed.failed)\n    throw new E_SANDBOX_FAILED([\n      `Sandbox spawn probe failed (exit code ${completed.exitCode}): ${stderr || 'no stderr'}`,\n    ])\n}\n","/**\n * The single sandbox observability firehose.\n *\n * WP-A1 wires the callbacks from `createSandbox()` to `createSandboxObservability()`;\n * it must not emit parallel ad-hoc events.  Every path-bearing field is redacted here,\n * before it reaches an operator, logger, or audit sink.\n */\nimport type { PathTranslator } from './contracts/path_translator'\n\n/** Typed records emitted by the sandbox's single audit firehose. */\nexport type SandboxEvent =\n  | {\n      readonly kind: 'bypass'\n      readonly command: string\n      readonly path?: string\n      readonly loud: true\n    }\n  | {\n      readonly kind: 'unsandboxed-fallback'\n      readonly handleId: string\n      readonly reason: string\n      readonly path?: string\n      readonly loud: true\n    }\n  | {\n      readonly kind: 'drift-check'\n      readonly outcome: 'passed' | 'failed' | 'skipped'\n      readonly reason?: string\n      readonly path?: string\n      /** `skipped` is specifically the network-domain comparison, not adoption. */\n      readonly comparison?: 'network-domains'\n    }\n  | {\n      readonly kind: 'fs-node-version'\n      readonly version: string\n    }\n  | { readonly kind: 'dependency-warnings'; readonly warnings: readonly string[] }\n\n/** Consumer callback for sandbox audit events. */\nexport type SandboxEventSink = (event: SandboxEvent) => void\n\n/** Dependencies used to create the redacting firehose. */\nexport interface SandboxObservabilityOptions {\n  /** Translator used for every path-bearing event field. */\n  readonly pathTranslator: PathTranslator\n  /** Destination for already-redacted events. */\n  readonly sink: SandboxEventSink\n}\n\nconst redactEvent = (event: SandboxEvent, translator: PathTranslator): SandboxEvent => {\n  if (event.kind === 'bypass') {\n    return Object.freeze({\n      ...event,\n      command: translator.redact(event.command),\n      ...(event.path === undefined ? {} : { path: translator.redact(event.path) }),\n    })\n  }\n  if (event.kind === 'unsandboxed-fallback') {\n    return Object.freeze({\n      ...event,\n      handleId: translator.redact(event.handleId),\n      reason: translator.redact(event.reason),\n      ...(event.path === undefined ? {} : { path: translator.redact(event.path) }),\n    })\n  }\n  if (event.kind === 'drift-check') {\n    return Object.freeze({\n      ...event,\n      ...(event.reason === undefined ? {} : { reason: translator.redact(event.reason) }),\n      ...(event.path === undefined ? {} : { path: translator.redact(event.path) }),\n    })\n  }\n  if (event.kind === 'dependency-warnings') {\n    return Object.freeze({\n      ...event,\n      warnings: Object.freeze(event.warnings.map((warning) => translator.redact(warning))),\n    })\n  }\n  return Object.freeze(event)\n}\n\n/** Build the one event surface consumed by WP-A1's sandbox handle. */\nexport const createSandboxObservability = (\n  options: SandboxObservabilityOptions\n): SandboxEventSink => {\n  return (event) => options.sink(redactEvent(event, options.pathTranslator))\n}\n\n/** Emit a loud audit-only bypass report. */\nexport const emitBypass = (sink: SandboxEventSink, command: string, path?: string): void => {\n  sink({ kind: 'bypass', command, ...(path === undefined ? {} : { path }), loud: true })\n}\n\n/** Emit the permanent loud report for an unsandboxed invocation. */\nexport const emitFallback = (\n  sink: SandboxEventSink,\n  handleId: string,\n  reason: string,\n  path?: string\n): void => {\n  sink({\n    kind: 'unsandboxed-fallback',\n    handleId,\n    reason,\n    ...(path === undefined ? {} : { path }),\n    loud: true,\n  })\n}\n\n/** Emit a drift result, including an explicit network-domain skip when requested. */\nexport const emitDriftCheck = (\n  sink: SandboxEventSink,\n  outcome: 'passed' | 'failed' | 'skipped',\n  details?: {\n    readonly reason?: string\n    readonly path?: string\n    readonly networkDomainsSkipped?: boolean\n  }\n): void => {\n  sink({\n    kind: 'drift-check',\n    outcome,\n    ...(details?.reason === undefined ? {} : { reason: details.reason }),\n    ...(details?.path === undefined ? {} : { path: details.path }),\n    ...(details?.networkDomainsSkipped ? { comparison: 'network-domains' as const } : {}),\n  })\n}\n\n/** Emit the SRT version used by the in-process evaluator. */\nexport const emitFsNodeVersion = (sink: SandboxEventSink, version: string): void => {\n  sink({ kind: 'fs-node-version', version })\n}\n","import { createSandboxEpoch } from './types'\nimport { probeSandboxSpawn, runSandboxPreflight } from './preflight'\nimport { createSandboxObservability, emitDriftCheck, emitFallback } from './observability'\nimport {\n  E_SANDBOX_NOT_INITIALIZED,\n  E_SANDBOX_POLICY_CONFLICT,\n  E_SANDBOX_NARROWING_UNSUPPORTED,\n} from './exceptions'\nimport type { PathTranslator } from './contracts/path_translator'\nimport type { SandboxPolicy, DerivedRules, SandboxEpoch } from './types'\nimport type { SandboxPolicyEnforcer } from './contracts/policy_enforcer'\n\ntype RunOptions = Parameters<SandboxPolicyEnforcer['run']>[0]\n/**\n * A live sandbox session: the object every sandbox tool is built against.\n *\n * @remarks\n * THIS IS A PROCESS-GLOBAL CAPABILITY WEARING A PER-HANDLE API, and the shape is a promise narrowed\n * rather than a promise kept. `SandboxManager` is a singleton, so the first `createSandbox()` in a\n * process establishes the policy and a later one may only NARROW it — a request that is not a subset\n * throws `E_SANDBOX_POLICY_CONFLICT` naming both. One policy per process is the safe deployment;\n * multi-tenant agents with different policies want separate processes.\n *\n * Every `run()` re-validates against the admission baseline before spawning, so a widening of the live\n * policy is DETECTED. Detection is not prevention: SRT's proxies consult policy per request, so a\n * widening already affects an in-flight child for its whole lifetime.\n */\nexport interface SandboxHandle {\n  /**\n   * Opaque token issued at construction and invalidated by {@link SandboxHandle.dispose}.\n   *\n   * @remarks\n   * File-backed readers hold this rather than a filesystem reference, which is what makes disposal\n   * deterministic: a staged reader outliving its TURN is legitimate, outliving its HANDLE is not.\n   */\n  readonly epoch: SandboxEpoch\n  /**\n   * The live DERIVED rules — not the `SandboxPolicy` that was requested.\n   *\n   * @remarks\n   * A policy cannot express what the drift check has to compare (`denyOnly`/`allowWithinDeny`, the\n   * unioned default write paths, Linux-expanded read globs, the profile-only mandatory denies), so\n   * returning one here would compare the wrong thing and pass while the live sandbox had widened.\n   * Under ADOPTION this re-derives from the live manager on every call; an owned session is cached.\n   */\n  readonly effectivePolicy: () => DerivedRules | undefined\n  /**\n   * Spawn under this session's policy, optionally narrowed for the single invocation.\n   *\n   * @remarks\n   * Resolves as soon as the child is SPAWNED, handing back live `stdout`/`stderr` streams plus a\n   * separate `completed` promise. Drain BOTH concurrently: pipe buffers are per-fd, so draining one to\n   * completion first can block the other and hang the child. A non-zero exit is data on `completed`,\n   * never a rejection.\n   */\n  run(options: RunOptions): ReturnType<SandboxPolicyEnforcer['run']>\n  /**\n   * Narrow the session policy for subsequent operations.\n   *\n   * @param policy - Must be a subset per the per-axis rules; reads are deny-then-allow while writes\n   * are allow-only, so \"narrower\" is not symmetric. Throws\n   * `E_SANDBOX_NARROWING_UNSUPPORTED` naming the axis where the platform cannot narrow it.\n   */\n  narrow(policy: SandboxPolicy): Promise<void>\n  /** Predicate consumed by file-backed readers; disposal makes the epoch unusable. */\n  isEpochLive(epoch: SandboxEpoch): boolean\n  /**\n   * Quiesce the session: it does not abandon in-flight work.\n   *\n   * @remarks\n   * Rejects new work with `E_SANDBOX_NOT_INITIALIZED`, aborts in-flight invocations through their\n   * signals, kills spawned children, then releases the enforcer. On an ADOPTED session this is a\n   * reported NO-OP — resetting a manager we did not create would strip ACEs a host application\n   * depends on.\n   */\n  dispose(): Promise<void>\n}\n\n/** Options for {@link createSandbox}. */\nexport interface CreateSandboxOptions {\n  /**\n   * ADK-owned policy vocabulary, mapped to the backend's config inside the enforcer.\n   *\n   * @remarks\n   * The per-axis defaults DIFFER and are not a symmetry worth \"fixing\": reads default to ALLOW\n   * (absent `denyRead` means everything is readable, and `allowRead` re-permits WITHIN a deny), while\n   * writes default to DENY and network is an allow-list. A checker that unified them would disagree\n   * with the OS by construction.\n   */\n  readonly policy: SandboxPolicy\n  /** The boundary itself. Node's SRT-backed enforcer lives on the `sandbox/node` subpath. */\n  readonly enforcer: SandboxPolicyEnforcer\n  /**\n   * Model-path translation, and the redaction used on every observability event.\n   *\n   * @remarks\n   * Supply it if you want host identifiers scrubbed from the event stream — no battery-generated\n   * surface should carry the sandbox root, home directory, or user name.\n   */\n  readonly translator?: PathTranslator\n  /** Observability firehose: bypasses, fallbacks, drift outcomes, and the SRT version rules came from. */\n  readonly onSandbox?: (event: Parameters<ReturnType<typeof createSandboxObservability>>[0]) => void\n  /**\n   * Permit degraded operation when the environment cannot provide OS containment.\n   *\n   * @remarks\n   * Fires only for pre-execution conditions resolved once at construction — a platform the backend\n   * cannot sandbox that we still run on, dependency errors, or an absent optional peer. It NEVER fires\n   * for a violation (a violation means the sandbox worked), and native Windows is refused outright\n   * rather than degraded. When it fires the handle is permanently marked and every invocation emits\n   * a loud observability event. Execution STILL goes through `enforcer.run`; this option never runs\n   * a command unsandboxed, and the tool descriptions tell the model it has no OS containment.\n   */\n  readonly allowUnsandboxedFallback?: boolean\n  /** Ignore the per-call escape entirely, matching the reference consumer's strict mode. */\n  readonly strictMode?: boolean\n  /** Whether the optional peer resolved; feeds the preflight decision above. */\n  readonly optionalPeerPresent?: boolean\n  /** Recorded on observability events so a rules-versus-backend mismatch is diagnosable without a bisect. */\n  readonly fsNodeVersion?: string\n  /** Opt in to a real child-spawn liveness check during construction. */\n  readonly probeSpawn?: boolean\n}\n\nlet owner: { baseline: DerivedRules; enforcer: SandboxPolicyEnforcer; owned: boolean } | undefined\nlet establishment: Promise<void> = Promise.resolve()\nlet disposalRequested = 0\nconst acquireEstablishment = async (): Promise<() => void> => {\n  const previous = establishment\n  let release!: () => void\n  establishment = new Promise<void>((resolve) => {\n    release = resolve\n  })\n  await previous\n  return release\n}\n\nconst list = (value: readonly string[] | undefined): readonly string[] => value ?? []\nconst json = (value: unknown): string => JSON.stringify(value)\n\n/**\n * Conservative list inclusion. Globs which are not lexically identical are deliberately\n * undecidable and therefore fail closed. This is a sufficient test, not a complete relation.\n */\nconst subset = (small: readonly string[], large: readonly string[]): boolean =>\n  small.every((item) => large.includes(item))\nconst same = (a: unknown, b: unknown): boolean => json(a) === json(b)\n\n/** Compare a requested (admission) derived policy with the live one: requested ⊆ live. */\nconst admission = (ours: DerivedRules, live: DerivedRules): boolean => {\n  if (!same(ours.matcher, live.matcher) || !same(ours.mandatoryDeny, live.mandatoryDeny))\n    return false\n  if (ours.filesystemDisabled && !live.filesystemDisabled) return false\n  if (!ours.filesystemDisabled && live.filesystemDisabled) {\n    // A kill switch is widening, and is consequently safe for admission.\n  }\n  return (\n    subset(live.read.denyOnly, ours.read.denyOnly) &&\n    subset(ours.read.allowWithinDeny, live.read.allowWithinDeny) &&\n    subset(ours.write.allowOnly, live.write.allowOnly) &&\n    subset(live.write.denyWithinAllow, ours.write.denyWithinAllow) &&\n    subset(ours.network.allowedDomains, live.network.allowedDomains) &&\n    subset(live.network.deniedDomains, ours.network.deniedDomains)\n  )\n}\n\n/** Compare a live snapshot with the admission baseline: widening is drift. */\nconst drift = (baseline: DerivedRules, live: DerivedRules): string | undefined => {\n  if (!same(baseline.matcher, live.matcher)) return 'matcher changed'\n  if (!same(baseline.mandatoryDeny, live.mandatoryDeny)) return 'mandatory deny inputs changed'\n  if (!baseline.filesystemDisabled && live.filesystemDisabled) return 'filesystem.disabled widened'\n  if (baseline.filesystemDisabled && !live.filesystemDisabled) {\n    // Narrowing is explicitly allowed.\n  }\n  if (live.unknownKeys.length > 0) return `unknown live config keys: ${live.unknownKeys.join(', ')}`\n  if (live.undecidableGlobs.length > 0)\n    return `uncompilable live globs: ${live.undecidableGlobs.join(', ')}`\n  if (!subset(live.read.denyOnly, baseline.read.denyOnly)) return 'read deny rules widened'\n  if (!subset(live.read.allowWithinDeny, baseline.read.allowWithinDeny))\n    return 'read allow rules widened'\n  if (!subset(live.write.allowOnly, baseline.write.allowOnly)) return 'write allow rules widened'\n  if (!subset(live.write.denyWithinAllow, baseline.write.denyWithinAllow))\n    return 'write deny rules widened'\n  if (baseline.network.disabled) {\n    // Disabled means unrestricted, which cannot be represented by a domain list.\n  } else {\n    if (live.network.disabled) return 'network.disabled widened'\n    if (!subset(live.network.allowedDomains, baseline.network.allowedDomains))\n      return 'allowed domains widened'\n    if (!subset(baseline.network.deniedDomains, live.network.deniedDomains))\n      return 'denied domains widened'\n  }\n  if (baseline.network.strictAllowlist !== live.network.strictAllowlist)\n    return 'strictAllowlist changed'\n  return undefined\n}\n\nconst policyEffect = (policy: SandboxPolicy, template: DerivedRules): DerivedRules => ({\n  ...template,\n  filesystemDisabled: Boolean(policy.filesystem.disabled),\n  read: {\n    denyOnly: [...list(policy.filesystem.denyRead)],\n    allowWithinDeny: [...list(policy.filesystem.allowRead)],\n  },\n  write: {\n    allowOnly: [...list(policy.filesystem.allowWrite)],\n    denyWithinAllow: [...list(policy.filesystem.denyWrite)],\n  },\n  network: {\n    ...template.network,\n    disabled: Boolean(policy.network.disabled),\n    allowedDomains: policy.network.disabled ? ['*'] : [...list(policy.network.allowedDomains)],\n    deniedDomains: policy.network.disabled ? [] : [...list(policy.network.deniedDomains)],\n  },\n})\n\n/**\n * Admit one process-global sandbox. Drift is detection, not prevention: SRT consults its\n * proxies per request, so a widening can affect an already-spawned child for its lifetime.\n */\nexport const createSandbox = async (options: CreateSandboxOptions): Promise<SandboxHandle> => {\n  const sink =\n    options.onSandbox && options.translator\n      ? createSandboxObservability({ pathTranslator: options.translator, sink: options.onSandbox })\n      : (options.onSandbox ?? (() => undefined))\n  const release = await acquireEstablishment()\n  let assignedOwner: typeof owner\n  try {\n    const preflight = await runSandboxPreflight({\n      enforcer: options.enforcer,\n      allowUnsandboxedFallback: options.allowUnsandboxedFallback,\n      strictMode: options.strictMode,\n      optionalPeerPresent: options.optionalPeerPresent,\n      fsNodeVersion: options.fsNodeVersion,\n      onSandbox: sink,\n    })\n    const live = options.enforcer.effectivePolicy()\n    if (!live) throw new E_SANDBOX_POLICY_CONFLICT(['Sandbox has no derived policy'])\n    // An adopted enforcer has no ADK policy provenance, so admission must compare the requested\n    // effect against its genuinely live foreign baseline. Owned sessions retain the established\n    // first-writer baseline for subsequent handles.\n    const adopted = options.enforcer.adopted === true\n    const firstHandle = owner === undefined\n    if (owner !== undefined) {\n      const admissionBaseline = adopted ? live : owner.baseline\n      const requested = policyEffect(options.policy, admissionBaseline)\n      if (!admission(requested, admissionBaseline)) {\n        throw new E_SANDBOX_POLICY_CONFLICT([\n          `requested policy ${json(options.policy)} conflicts with ${json(admissionBaseline)}`,\n        ])\n      }\n    } else {\n      // Adoption has no caller policy to compare against until this point; rule 3b compares the\n      // requested effect with the foreign live baseline before admitting the first handle.\n      if (adopted && !admission(policyEffect(options.policy, live), live))\n        throw new E_SANDBOX_POLICY_CONFLICT([\n          `requested policy ${json(options.policy)} conflicts with ${json(live)}`,\n        ])\n      owner = { baseline: live, enforcer: options.enforcer, owned: !adopted }\n      assignedOwner = owner\n    }\n    const admittedOwner = owner\n    if (!admittedOwner) throw new E_SANDBOX_NOT_INITIALIZED(['Sandbox owner was not established'])\n    if (options.probeSpawn) {\n      // Probe only after admission: preflight runs before admission and could exercise a rejected policy.\n      // Probe failures fail closed; manager.ts:272 calls enforcer.run() unconditionally, so\n      // allowUnsandboxedFallback cannot provide an unsandboxed alternative here.\n      await probeSandboxSpawn(admittedOwner.enforcer, options.policy)\n    }\n    if (owner !== admittedOwner)\n      throw new E_SANDBOX_NOT_INITIALIZED(['Sandbox owner changed during construction'])\n    // A disposal requested while this construction was probing must invalidate construction rather\n    // than return a handle that the queued disposal would immediately reset.\n    if (disposalRequested > 0)\n      throw new E_SANDBOX_NOT_INITIALIZED(['Sandbox disposal was requested during construction'])\n    const baseline = admittedOwner.baseline\n    const epoch = createSandboxEpoch()\n    let disposed = false\n    const controllers = new Set<AbortController>()\n    const check = (): void => {\n      if (disposed) throw new E_SANDBOX_NOT_INITIALIZED(['Sandbox handle has been disposed'])\n      const current = owner?.enforcer.effectivePolicy()\n      if (!current) throw new E_SANDBOX_NOT_INITIALIZED(['Sandbox policy is unavailable'])\n      const reason = drift(baseline, current)\n      if (reason) {\n        emitDriftCheck(sink, 'failed', { reason })\n        throw new E_SANDBOX_POLICY_CONFLICT([`sandbox drift detected: ${reason}`])\n      }\n      if (baseline.network.disabled)\n        emitDriftCheck(sink, 'skipped', { networkDomainsSkipped: true })\n      else emitDriftCheck(sink, 'passed')\n    }\n    const handle: SandboxHandle = {\n      epoch,\n      effectivePolicy: () => owner?.enforcer.effectivePolicy(),\n      run: async (runOptions) => {\n        check()\n        // The manager owns this controller so disposal cancels every in-flight invocation. The\n        // enforcer contract requires that cancellation terminate the corresponding child and settle\n        // its `completed` promise; the caller's signal is mirrored into this lifecycle signal.\n        const controller = new AbortController()\n        controllers.add(controller)\n        const signal = runOptions.signal\n        let callerAbortListener: (() => void) | undefined\n        const cleanup = (): void => {\n          if (signal && callerAbortListener) {\n            signal.removeEventListener('abort', callerAbortListener)\n            callerAbortListener = undefined\n          }\n          controllers.delete(controller)\n        }\n        if (signal) {\n          if (signal.aborted) controller.abort(signal.reason)\n          else {\n            callerAbortListener = () => controller.abort(signal.reason)\n            signal.addEventListener('abort', callerAbortListener, { once: true })\n          }\n        }\n        let result: ReturnType<SandboxPolicyEnforcer['run']>\n        try {\n          result = owner!.enforcer.run({ ...runOptions, signal: controller.signal })\n        } catch (error) {\n          cleanup()\n          throw error\n        }\n        // `run` resolves after spawn, while `completed` settles after exit. Keep this controller\n        // registered until completion so disposal can still cancel a live child.\n        void result.then(({ completed }) => completed.then(cleanup, cleanup), cleanup)\n        if (preflight.fallbackFired) emitFallback(sink, 'sandbox', 'unsandboxed fallback')\n        return result\n      },\n      narrow: async (policy) => {\n        check()\n        const candidate = options.enforcer as SandboxPolicyEnforcer & {\n          narrow?: (requested: SandboxPolicy) => Promise<void>\n        }\n        if (typeof candidate.narrow !== 'function')\n          throw new E_SANDBOX_NARROWING_UNSUPPORTED(['filesystem/network'])\n        await candidate.narrow(policy)\n      },\n      isEpochLive: (candidate) => !disposed && candidate === epoch,\n      dispose: async () => {\n        if (disposed) return\n        disposed = true\n        // Mark synchronously, before waiting for the establishment queue, so a pending probe can\n        // fail with a lifecycle error instead of returning a handle that this disposal resets.\n        if (firstHandle) disposalRequested += 1\n        const releaseDispose = await acquireEstablishment()\n        try {\n          for (const controller of controllers) controller.abort()\n          controllers.clear()\n          if (firstHandle) {\n            if (!adopted) await options.enforcer.dispose()\n            if (owner?.enforcer === options.enforcer) owner = undefined\n          }\n        } finally {\n          if (firstHandle) disposalRequested -= 1\n          releaseDispose()\n        }\n      },\n    }\n    release()\n    return handle\n  } catch (error) {\n    try {\n      if (assignedOwner && owner === assignedOwner) {\n        owner = undefined\n        // Roll back the backend session as well as the manager record. Calling the enforcer\n        // directly avoids re-entering the establishment queue held by this construction.\n        if (assignedOwner.owned) await options.enforcer.dispose()\n      }\n    } finally {\n      release()\n    }\n    throw error\n  }\n}\n","import { quoteShellArgs } from './escape'\nimport { emitBypass, type SandboxEventSink } from './observability'\nimport type { BinaryExecutor, BinaryInvocation } from '../media/contracts'\n\n/**\n * A small command-wrapper seam used by {@link sandboxedExecutor}.  The wrapper returns the\n * invocation that the inner executor should receive; it must not execute the command itself.\n */\n/** Command wrapping contract used by the executor adapter. */\nexport interface BinarySandbox {\n  /** Wrap an invocation without executing it. */\n  wrap(\n    invocation: BinaryInvocation & { command: string }\n  ): Promise<BinaryInvocation & { command: string }>\n}\n\n/** Configuration for the sandboxed binary executor. */\nexport interface SandboxedExecutorOptions {\n  /** Command wrapper used for non-bypassed invocations. */\n  readonly sandbox: BinarySandbox\n  /** Underlying executor receiving the wrapped invocation. */\n  readonly inner: BinaryExecutor\n  /** Command-only opt-out. This is deliberately never passed argv to the predicate. */\n  readonly bypass?: (cmd: string) => boolean\n  /** Loud audit sink; bypass is observability, not enforcement. */\n  readonly onSandbox?: SandboxEventSink\n}\n\n/**\n * Adapt a {@link BinaryExecutor} to a command sandbox. This WRAPS `inner.exec()` and DOES NOT\n * STREAM: the shipped BinaryExecutor contract returns settled strings. Consequently an execa\n * inner executor retains its output and inherits execa's bounded `maxBuffer` behaviour; this\n * adapter does not raise that bound (and never sets `maxBuffer: Infinity`). The streaming path is\n * {@link createRunShellCommandTool}, which uses the policy-enforcer stream contract instead.\n *\n * Bypass is an audit-only opt-out. Its predicate receives `cmd` only, never argv: callers must\n * allow only binaries safe with hostile arguments and must never allow an interpreter. Non-zero\n * exits remain data and are never thrown. Removing this wrapper call restores the inner executor.\n */\n/** Create a BinaryExecutor that wraps invocations unless an explicitly audited bypass applies. */\nexport const sandboxedExecutor = (options: SandboxedExecutorOptions): BinaryExecutor => ({\n  async exec(invocation) {\n    if (options.bypass?.(invocation.cmd)) {\n      options.onSandbox?.({ kind: 'bypass', command: invocation.cmd, loud: true })\n      return options.inner.exec(invocation)\n    }\n    const command = await quoteShellArgs([invocation.cmd, ...invocation.args])\n    const wrapped = await options.sandbox.wrap({ ...invocation, command })\n    return options.inner.exec({ ...wrapped, cmd: wrapped.command })\n  },\n})\n\n/** Emit a bypass through the canonical sink for consumers that do not retain the adapter. */\nexport const reportSandboxBypass = (sink: SandboxEventSink, command: string): void =>\n  emitBypass(sink, command)\n","import { Tool } from '@nhtio/adk/forge'\nimport { validator } from '@nhtio/validation'\nimport { classifySandboxPathRejection } from './paths'\nimport { isError, isInstanceOf } from '@nhtio/adk/guards'\nimport { SpooledArtifact } from '@nhtio/adk/spooled_artifact'\nimport { runToolGate, type ToolGateFn } from '../tools/_shared'\nimport { E_TURN_GATE_ABORTED } from '../../lib/exceptions/runtime'\nimport { E_SANDBOX_GATE_REQUIRED, E_SANDBOX_REFUSED, E_SANDBOX_FAILED } from './exceptions'\nimport { defaultSandboxNarrator, type SandboxNarrator, type SandboxOutcome } from './narrator'\nimport type { SandboxPolicy } from './types'\nimport type { PathTranslator } from './contracts/path_translator'\nimport type { SandboxPolicyEnforcer } from './contracts/policy_enforcer'\n\n/** Configuration for the streaming shell-command tool. */\nexport interface RunShellCommandOptions {\n  /** Streaming policy enforcer; unlike BinaryExecutor this exposes live stdout/stderr. */\n  readonly sandbox: SandboxPolicyEnforcer\n  /** Policy applied to the spawned command. */\n  readonly policy: SandboxPolicy\n  /** Model-path translator for the working directory. */\n  readonly translator: PathTranslator\n  /** Required human/policy approval gate. */\n  readonly gate?: ToolGateFn\n  /** Optional command-name allow-list. */\n  readonly allowedCommands?: readonly string[]\n  /**\n   * Environment variables to add to every command this tool spawns.\n   *\n   * @remarks\n   * ADDITIVE, and applied LAST — over both the host variables the enforcer allow-listed and SRT's own\n   * proxy/CA plumbing. It is not the host-inheritance control: the enforcer decides what the child\n   * inherits (`envAllowList` / `inheritHostEnv` on the Node adapter), and this cannot re-admit a\n   * variable the enforcer withheld except by supplying the value literally here.\n   *\n   * Anything put here is readable by the model — `run_shell_command` runs commands the model chose,\n   * and `env` is one of them — so pass configuration, not credentials.\n   */\n  readonly env?: Readonly<Record<string, string>>\n  /** Optional tool description override. */\n  readonly description?: string\n  /** Injectable model-facing outcome renderer. */\n  readonly narrate?: SandboxNarrator\n}\n\nconst encoder = new TextEncoder()\nconst line = (value: string): Uint8Array => encoder.encode(`${value}\\n`)\n\n/**\n * Assemble the factory-style `run_shell_command` tool. It is intentionally not a bulk-registered\n * battery value. `cwd` is a model-supplied workspace-relative path and receives the complete\n * PathTranslator gauntlet, including symlink refusal; the default is the workspace root.\n *\n * The command spawns first, then stdout and stderr are drained concurrently and merged in arrival\n * order into one stream and one `storeRetrievableBytes` call. Diagnostics are polled while drains\n * run and written as `[sandbox] denied: …` at their observation point (\"observed after\", not\n * \"caused by\"). The command is never accumulated here. `timeout_seconds` defaults to 300 and is\n * a tool argument. Non-zero exits, violations, timeouts, and post-spawn I/O failures return the\n * singular artifact; failures meaning the command never ran throw instead.\n */\nexport const createRunShellCommandTool = (options: RunShellCommandOptions): Tool => {\n  if (!options.gate) throw new E_SANDBOX_GATE_REQUIRED(['run_shell_command requires a gate'])\n  const inputSchema = validator.object({\n    command: validator.string().required().description('Shell command to execute.'),\n    cwd: validator\n      .string()\n      .default('')\n      .allow('')\n      .description('Workspace-relative working directory; defaults to the workspace root.'),\n    timeout_seconds: validator\n      .number()\n      .min(1)\n      .default(300)\n      .description('Command timeout in seconds; defaults to 300. Raise it for slow commands.'),\n  })\n  return new Tool({\n    name: 'run_shell_command',\n    description:\n      options.description ??\n      'Run a shell command under the sandbox. Output is one interleaved artifact; sandbox denials appear inline. cwd is workspace-relative and timeout_seconds defaults to 300.',\n    inputSchema,\n    trusted: false,\n    handler: async (raw, ctx) => {\n      const args = raw as {\n        command: string\n        cwd: string\n        timeout_seconds: number\n      }\n      const narrate = options.narrate ?? defaultSandboxNarrator\n      try {\n        await runToolGate(options.gate, ctx, 'run_shell_command', args)\n      } catch (error) {\n        if (isInstanceOf(error, 'E_TURN_GATE_ABORTED', E_TURN_GATE_ABORTED)) {\n          if (ctx.abortSignal.aborted) throw error\n          throw new E_SANDBOX_FAILED([narrate({ kind: 'aborted' })])\n        }\n        const outcome =\n          (error as { outcome?: SandboxOutcome; kind?: string }).outcome ??\n          ((error as { kind?: string }).kind === 'gate-declined'\n            ? ({ kind: 'gate-declined' } satisfies SandboxOutcome)\n            : undefined)\n        if (outcome?.kind === 'gate-declined') throw new E_SANDBOX_REFUSED([narrate(outcome)])\n        throw new E_SANDBOX_REFUSED([narrate({ kind: 'gate-unavailable', reason: 'error' })])\n      }\n      let relative: string\n      try {\n        // NO pre-emptive leading-`/` rejection. The model's world IS the sandbox, so `/src/index.ts`\n        // means \"top of what I can see\" and must NORMALISE to the root — rejecting it punishes the\n        // model for a distinction we deliberately hid, and produces the mangle-retry loop the\n        // LLM-operator rules exist to prevent. `toRelative` owns the whole gauntlet, `~` included.\n        relative = await options.translator.toRelative(args.cwd)\n        await options.translator.assertNoSymlinkComponents(relative)\n      } catch (error) {\n        // An ALREADY-NARRATED refusal passes through: re-wrapping it would discard a more precise\n        // outcome and relabel it `escape`.\n        if (\n          isInstanceOf(error, 'E_SANDBOX_REFUSED', E_SANDBOX_REFUSED) ||\n          isInstanceOf(error, 'E_SANDBOX_FAILED', E_SANDBOX_FAILED)\n        )\n          throw error\n        // And the REASON is classified, not assumed — `cwd` is the model-supplied path on the one\n        // tool that runs arbitrary code, so \"use a workspace-relative path\" is the wrong advice for\n        // a NUL byte or a UNC form.\n        throw new E_SANDBOX_FAILED([\n          narrate({\n            kind: 'path-rejected',\n            input: args.cwd,\n            reason: classifySandboxPathRejection(args.cwd) ?? 'escape',\n          }),\n        ])\n      }\n      const commandName = args.command.trim().split(/\\s+/, 1)[0]\n      if (options.allowedCommands && !options.allowedCommands.includes(commandName))\n        throw new E_SANDBOX_REFUSED([\n          narrate({\n            kind: 'denied-by-policy',\n            path: commandName,\n            axis: 'read',\n          }),\n        ])\n      const correlationId = crypto.randomUUID()\n      const controller = new AbortController()\n      const abort = (): void => controller.abort(ctx.abortSignal.reason)\n      if (ctx.abortSignal.aborted) abort()\n      else ctx.abortSignal.addEventListener('abort', abort, { once: true })\n      let timerFired = false\n      const timeout = setTimeout(() => {\n        timerFired = true\n        controller.abort()\n      }, args.timeout_seconds * 1000)\n      // A stream controller is captured without buffering any payload.\n      let streamController: ReadableStreamDefaultController<Uint8Array> | undefined\n      const merged = new ReadableStream<Uint8Array>({\n        start(mergedController) {\n          streamController = mergedController\n        },\n      })\n      const write = (bytes: Uint8Array): void => streamController?.enqueue(bytes)\n      const close = (): void => streamController?.close()\n      let execution: Awaited<ReturnType<SandboxPolicyEnforcer['run']>>\n      try {\n        // The policy enforcer owns the configured shell (including binShell); this is a shell\n        // command payload, not a second shell selection made by the tool.\n        const argv = [args.command]\n        execution = await options.sandbox.run({\n          argv,\n          policy: options.policy,\n          correlationId,\n          cwd: options.translator.toBackendPath(relative),\n          signal: controller.signal,\n          ...(options.env === undefined ? {} : { env: { ...options.env } }),\n        })\n      } catch (error) {\n        clearTimeout(timeout)\n        const outcome = (error as { outcome?: SandboxOutcome }).outcome\n        if (outcome?.kind === 'denied-by-policy') throw new E_SANDBOX_REFUSED([narrate(outcome)])\n        throw new E_SANDBOX_FAILED([\n          narrate({\n            kind: 'io-failure',\n            detail: isError(error) ? error.message : String(error),\n          }),\n        ])\n      }\n      const storeWrite = ctx.storeRetrievableBytes(correlationId, merged)\n      const seen = new Set<string>()\n      const poll = (): void => {\n        for (const denial of options.sandbox.diagnosticsFor(correlationId)) {\n          if (!seen.has(denial)) {\n            seen.add(denial)\n            // Redacted because a denial is upstream TEXT and routinely names an absolute host path —\n            // the one line in this stream the battery authors from someone else's words. The exit-code\n            // and timeout lines below are numbers this battery formats, so they carry nothing to scrub.\n            // This does NOT extend to the child's own stdout, which no field translation can reach.\n            write(line(`[sandbox] denied: ${options.translator.redact(denial)} (observed after)`))\n          }\n        }\n      }\n      const drain = async (source: ReadableStream<Uint8Array>): Promise<void> => {\n        const reader = source.getReader()\n        try {\n          for (;;) {\n            const item = await reader.read()\n            if (item.done) return\n            write(item.value)\n            poll()\n          }\n        } finally {\n          reader.releaseLock()\n        }\n      }\n      let polling = true\n      const poller = (async (): Promise<void> => {\n        while (polling) {\n          await new Promise<void>((resolve) => setTimeout(resolve, 10))\n          if (polling) poll()\n        }\n      })()\n      let completed: Awaited<typeof execution.completed> | undefined\n      try {\n        await Promise.all([drain(execution.stdout), drain(execution.stderr)])\n        completed = await execution.completed\n      } finally {\n        clearTimeout(timeout)\n        polling = false\n        await poller\n        poll()\n        if (timerFired) write(line(`[timed out after ${args.timeout_seconds}s]`))\n        else if (completed && completed.exitCode !== 0)\n          write(line(`Exit code: ${completed.exitCode}`))\n        close()\n      }\n      const reader = await storeWrite\n      return new SpooledArtifact(reader)\n    },\n  })\n}\n","import { passesSchema } from '../validation'\nimport { validator } from '@nhtio/validation'\nimport type { SandboxPolicy, DerivedRules } from '../types'\n\n/** Policy boundary. `run` resolves on spawn and exposes live streams plus a later completion promise. */\nexport interface SandboxPolicyEnforcer {\n  /** Whether this enforcer can enforce on the current platform. `false` (a browser tab, where SRT does not exist) raises `E_SANDBOX_UNSUPPORTED_ENV` at construction rather than degrading — a shim that enforces nothing reads as sandboxed. */\n  isSupported(): boolean\n  /** Whether this adapter adopted an already-enabled process-global sandbox rather than initializing it. */\n  readonly adopted?: boolean\n  /** Probe external prerequisites. A non-empty `errors` throws `E_SANDBOX_DEPENDENCY_MISSING`; `warnings` are surfaced through observability and are NOT fatal. */\n  checkDependencies(): Promise<{ errors: string[]; warnings: string[] }>\n  /**\n   * Spawn under a narrowing policy; a non-zero exit is data, not a rejected promise.\n   *\n   * @remarks\n   * When `op.signal` aborts, an implementation MUST terminate the spawned child (including a\n   * child hidden behind a sandbox wrapper) and settle `completed`; it MUST NOT leave the child\n   * running after the lifecycle owner has cancelled the invocation. The returned streams may end\n   * as a consequence of termination, but `completed` remains the authoritative settlement signal.\n   */\n  run(op: {\n    argv: string[]\n    policy: SandboxPolicy\n    correlationId: string\n    cwd: string\n    /**\n     * An ADDITIVE per-call overlay on the child's environment, applied LAST.\n     *\n     * @remarks\n     * NOT the host-inheritance control. What a child inherits from the host is the ADAPTER's decision\n     * (the Node/SRT one denies by default and takes an allow-list at construction); this field only\n     * adds to whatever that produced, and an adapter MUST NOT let it silently widen what the deployment\n     * allowed. Leaving these semantics unstated is how the Node adapter came to spread the entire\n     * `process.env` into every child while this field sat unused.\n     */\n    env?: Record<string, string>\n    /**\n     * Lifecycle cancellation for this child. Implementations must kill the spawned child and\n     * settle `completed` when this signal aborts.\n     */\n    signal?: AbortSignal\n  }): Promise<{\n    stdout: ReadableStream<Uint8Array>\n    stderr: ReadableStream<Uint8Array>\n    completed: Promise<{ exitCode: number; failed: boolean }>\n  }>\n  /** Return the opaque derived snapshot used for drift validation. */\n  effectivePolicy(): DerivedRules | undefined\n  /** Retrieve diagnostics by correlation id, never by command text. */\n  diagnosticsFor(correlationId: string): string[]\n  /** Release what this enforcer OWNS. A no-op when it adopted a foreign sandbox — tearing down a manager we did not initialize would strip ACEs a host app depends on. */\n  dispose(): Promise<void>\n}\n\n/** Duck-type schema. */\nexport const sandboxPolicyEnforcerSchema = validator\n  .any()\n  .required()\n  .custom((value, helpers) => {\n    if (\n      value !== null &&\n      value !== undefined &&\n      typeof (value as any).isSupported === 'function' &&\n      typeof (value as any).checkDependencies === 'function' &&\n      typeof (value as any).run === 'function' &&\n      typeof (value as any).effectivePolicy === 'function' &&\n      typeof (value as any).diagnosticsFor === 'function' &&\n      typeof (value as any).dispose === 'function'\n    )\n      return value\n    return helpers.error('any.invalid')\n  })\n\n/** Structural guard. */\nexport const implementsSandboxPolicyEnforcer = (value: unknown): value is SandboxPolicyEnforcer =>\n  passesSchema(sandboxPolicyEnforcerSchema, value)\n","import { passesSchema } from '../validation'\nimport { validator } from '@nhtio/validation'\nimport type { ListFrame } from '../types'\n\n/** Filesystem capability with no copy primitive; traversal is complete and terminal-framed. */\nexport interface SandboxFileSystem {\n  /** Return metadata. A changed version token is evidence of change; equality is not a no-change guarantee. */\n  stat(path: string): Promise<{\n    size: number\n    version: string\n    kind: 'file' | 'dir' | 'symlink' | 'other'\n    mtimeMs?: number\n    ino?: number\n    dev?: number\n  }>\n  /** Lazily yield every item, followed by exactly one mandatory done frame. */\n  list(path: string, o: { maxDepth: number; signal?: AbortSignal }): AsyncIterable<ListFrame>\n  /** Open a fresh, replayable byte stream; non-regular kinds are refused by adapters. */\n  read(path: string, o?: { signal?: AbortSignal }): Promise<ReadableStream<Uint8Array>>\n  /** Write bytes without imposing a battery-level size cap. */\n  write(\n    path: string,\n    bytes: ReadableStream<Uint8Array> | Uint8Array,\n    o?: { signal?: AbortSignal }\n  ): Promise<void>\n  /** Delete a path. Deletion is idempotent: deleting an absent path resolves. */\n  delete?(path: string, o?: { signal?: AbortSignal }): Promise<void>\n  /**\n   * Move a path. MUST overwrite an existing destination (POSIX move semantics).\n   * Dev-tools relies on this behaviour when breaking rename cycles.\n   */\n  rename?(from: string, to: string, o?: { signal?: AbortSignal }): Promise<void>\n  /** Create a directory. */\n  mkdir?(path: string, o?: { signal?: AbortSignal }): Promise<void>\n}\n\n/** Duck-type schema. */\nexport const sandboxFileSystemSchema = validator\n  .any()\n  .required()\n  .custom((value, helpers) => {\n    if (\n      value !== null &&\n      value !== undefined &&\n      typeof (value as any).stat === 'function' &&\n      typeof (value as any).list === 'function' &&\n      typeof (value as any).read === 'function' &&\n      typeof (value as any).write === 'function'\n    )\n      return value\n    return helpers.error('any.invalid')\n  })\n\n/** Structural guard. */\nexport const implementsSandboxFileSystem = (value: unknown): value is SandboxFileSystem =>\n  passesSchema(sandboxFileSystemSchema, value)\n","import { passesSchema } from '../validation'\nimport { validator } from '@nhtio/validation'\nimport type { HitFrame, PathFrame } from '../types'\n\n/** Search capability; every result is lazy, complete, and terminal-framed. */\nexport interface SandboxSearch {\n  /**\n   * Whether this adapter can CONTAIN symlinked descendants when `follow` is enabled.\n   *\n   * `rg --follow` traverses links whose targets never pass through the path translator, so an\n   * uncontained backend turns `follow: true` into an unbounded read of wherever they point.\n   * The tools layer cannot inspect what is behind this interface, so an adapter declares it:\n   * omitted or `false` means the forged `search_files`/`find_files` schemas REJECT `follow: true`\n   * outright rather than accepting it and failing at execution. Set it only if you have verified\n   * containment; the bundled ripgrep adapter has not, and does not set it.\n   */\n  readonly supportsFollow?: boolean\n  /** Lazily yield every whole matching line, then one done frame. */\n  searchContent(o: {\n    root: string\n    pattern: string\n    maxDepth: number\n    /** Maximum results to yield. MUST be an integer >= 1; adapters reject anything else. */\n    limit: number\n    ignoreCase?: boolean\n    literal?: boolean\n    glob?: string\n    iglob?: string\n    follow?: boolean\n    hidden?: boolean\n    noIgnore?: boolean\n    signal?: AbortSignal\n  }): AsyncIterable<HitFrame>\n  /** Lazily yield every matching path, then one done frame. */\n  findPaths(o: {\n    root: string\n    glob: string\n    maxDepth: number\n    /** Maximum results to yield. MUST be an integer >= 1; adapters reject anything else. */\n    limit: number\n    iglob?: string\n    follow?: boolean\n    hidden?: boolean\n    noIgnore?: boolean\n    signal?: AbortSignal\n  }): AsyncIterable<PathFrame>\n}\n\n/** Duck-type schema. */\nexport const sandboxSearchSchema = validator\n  .any()\n  .required()\n  .custom((value, helpers) => {\n    if (\n      value !== null &&\n      value !== undefined &&\n      typeof (value as any).searchContent === 'function' &&\n      typeof (value as any).findPaths === 'function'\n    )\n      return value\n    return helpers.error('any.invalid')\n  })\n\n/** Structural guard. */\nexport const implementsSandboxSearch = (value: unknown): value is SandboxSearch =>\n  passesSchema(sandboxSearchSchema, value)\n","import { passesSchema } from '../validation'\nimport { validator } from '@nhtio/validation'\n\n/** Model-path boundary: normalises ergonomic paths while refusing unambiguous host escapes. */\nexport interface PathTranslator {\n  /** Validate and convert a model path; leading separators mean the sandbox root. */\n  toRelative(modelPath: string): Promise<string>\n  /** Convert a validated relative path to an opaque backend locator. */\n  toBackendPath(relative: string): string\n  /** Scrub root and common host identifiers from battery-generated text. */\n  redact(text: string): string\n  /** The translator always inspects the resolved path and every parent for symlink components. */\n  assertNoSymlinkComponents(relative: string): Promise<void>\n}\n\n/** Duck-type schema. */\nexport const pathTranslatorSchema = validator\n  .any()\n  .required()\n  .custom((value, helpers) => {\n    if (\n      value !== null &&\n      value !== undefined &&\n      typeof (value as any).toRelative === 'function' &&\n      typeof (value as any).toBackendPath === 'function' &&\n      typeof (value as any).redact === 'function' &&\n      typeof (value as any).assertNoSymlinkComponents === 'function'\n    )\n      return value\n    return helpers.error('any.invalid')\n  })\n\n/** Structural guard. */\nexport const implementsPathTranslator = (value: unknown): value is PathTranslator =>\n  passesSchema(pathTranslatorSchema, value)\n","import { passesSchema } from '../validation'\nimport { validator } from '@nhtio/validation'\nimport type { GuestLimits, GuestHandle } from '../types'\n\n/** Runtime boundary for a hardened guest realm; limits and capability declarations cross the boundary. */\nexport interface GuestRuntime {\n  /** Spawn a guest with fully resolved hostile-realm limits and async capability stubs. */\n  spawn(o: {\n    modules: string[]\n    globals: ReadonlyArray<{ name: string; kind: 'async-fn' }>\n    limits: GuestLimits\n    signal?: AbortSignal\n  }): Promise<GuestHandle>\n}\n\n/** Duck-type schema. */\nexport const guestRuntimeSchema = validator\n  .any()\n  .required()\n  .custom((value, helpers) => {\n    if (value !== null && value !== undefined && typeof (value as any).spawn === 'function')\n      return value\n    return helpers.error('any.invalid')\n  })\n\n/** Structural guard. */\nexport const implementsGuestRuntime = (value: unknown): value is GuestRuntime =>\n  passesSchema(guestRuntimeSchema, value)\n","import { passesSchema } from '../validation'\nimport { validator } from '@nhtio/validation'\n/** MIME resolver; `undefined` means the resolver declines and a later resolver may decide. */\nexport type MimeResolver = (ctx: {\n  path: string\n  declared?: string\n  /** Read a bounded prefix only; this callback cannot read the whole file. */\n  peek: (bytes: number) => Promise<Uint8Array>\n}) => string | undefined | Promise<string | undefined>\n/** MIME resolver schema. */\nexport const mimeResolverSchema = validator\n  .any()\n  .required()\n  .custom((v, h) => (typeof v === 'function' ? v : h.error('any.invalid')))\n/** MIME resolver guard. */\nexport const implementsMimeResolver = (v: unknown): v is MimeResolver =>\n  passesSchema(mimeResolverSchema, v)\n","import { passesSchema } from '../validation'\nimport { validator } from '@nhtio/validation'\n\n/** Artifact-class registry. Format constructors are lazy so unused parsers are never loaded. */\nexport interface ArtifactMinter {\n  /** Return available formats and async constructors. */\n  formats(): Promise<\n    Array<{ id: string; mime: string[]; extensions: string[]; ctor: () => Promise<unknown> }>\n  >\n}\n\n/** Duck-type schema. */\nexport const artifactMinterSchema = validator\n  .any()\n  .required()\n  .custom((value, helpers) => {\n    if (value !== null && value !== undefined && typeof (value as any).formats === 'function')\n      return value\n    return helpers.error('any.invalid')\n  })\n\n/** Structural guard. */\nexport const implementsArtifactMinter = (value: unknown): value is ArtifactMinter =>\n  passesSchema(artifactMinterSchema, value)\n"],"mappings":"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"}