Class: Kobako::Sandbox

Inherits:
Object
  • Object
show all
Defined in:
lib/kobako/sandbox.rb

Overview

Kobako::Sandbox — the user-facing entry point for executing guest mruby scripts inside a wasmtime-hosted Wasm module (SPEC.md B-01).

The Sandbox owns the Kobako::Wasm::Instance, the per-instance RPC Server (which itself owns the per-run HandleTable), and the per-channel byte caches for guest stdout / stderr capture. The underlying wasmtime Engine and compiled Module are cached at process scope by the native ext and never surface to Ruby — constructing many Sandboxes amortises both costs automatically.

Output capture policy (SPEC.md B-04): the per-channel cap (stdout_limit / stderr_limit) is enforced inside the WASI pipe — the host buffer stops growing at the cap, subsequent guest writes on that channel fail or are dropped, and #run still returns normally. #stdout / #stderr return the captured prefix as a UTF-8 String; the byte content never carries a truncation sentinel. #stdout_truncated? / #stderr_truncated? are the only way to observe that the cap was hit.

Constant Summary collapse

DEFAULT_OUTPUT_LIMIT =

Default per-channel capture ceiling: 1 MiB (SPEC.md B-01).

1 << 20
DEFAULT_TIMEOUT_SECONDS =

Default wall-clock timeout for a single #run: 60 seconds (SPEC.md B-01).

60.0
DEFAULT_MEMORY_LIMIT =

Default cap on guest linear memory growth: 5 MiB (SPEC.md B-01).

5 << 20

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(wasm_path: nil, stdout_limit: nil, stderr_limit: nil, timeout: DEFAULT_TIMEOUT_SECONDS, memory_limit: DEFAULT_MEMORY_LIMIT) ⇒ Sandbox

Build a fresh Sandbox.

wasm_path is the absolute path to the Guest Binary; defaults to the gem-bundled data/kobako.wasm. stdout_limit and stderr_limit cap the per-run byte ceiling for each capture channel (default 1 MiB; nil disables the cap). timeout is the wall-clock cap on a single #run in seconds (SPEC.md B-01; default 60.0, nil disables); memory_limit caps guest linear memory growth in bytes (SPEC.md B-01, E-20; default 5 MiB, nil disables).



86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/kobako/sandbox.rb', line 86

def initialize(wasm_path: nil, stdout_limit: nil, stderr_limit: nil,
               timeout: DEFAULT_TIMEOUT_SECONDS,
               memory_limit: DEFAULT_MEMORY_LIMIT)
  @wasm_path = wasm_path || Kobako::Wasm.default_path
  @stdout_limit = stdout_limit || DEFAULT_OUTPUT_LIMIT
  @stderr_limit = stderr_limit || DEFAULT_OUTPUT_LIMIT
  @timeout = normalize_timeout(timeout)
  @memory_limit = normalize_memory_limit(memory_limit)
  @services = Kobako::RPC::Server.new
  @instance = Kobako::Wasm::Instance.from_path(@wasm_path, @timeout, @memory_limit, @stdout_limit, @stderr_limit)
  @instance.server = @services
  clear_captures!
end

Instance Attribute Details

#instanceObject (readonly)

Returns the value of attribute instance.



42
43
44
# File 'lib/kobako/sandbox.rb', line 42

def instance
  @instance
end

#memory_limitObject (readonly)

Returns the value of attribute memory_limit.



42
43
44
# File 'lib/kobako/sandbox.rb', line 42

def memory_limit
  @memory_limit
end

#servicesObject (readonly)

Returns the value of attribute services.



42
43
44
# File 'lib/kobako/sandbox.rb', line 42

def services
  @services
end

#stderr_limitObject (readonly)

Returns the value of attribute stderr_limit.



42
43
44
# File 'lib/kobako/sandbox.rb', line 42

def stderr_limit
  @stderr_limit
end

#stdout_limitObject (readonly)

Returns the value of attribute stdout_limit.



42
43
44
# File 'lib/kobako/sandbox.rb', line 42

def stdout_limit
  @stdout_limit
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



42
43
44
# File 'lib/kobako/sandbox.rb', line 42

def timeout
  @timeout
end

#wasm_pathObject (readonly)

Returns the value of attribute wasm_path.



42
43
44
# File 'lib/kobako/sandbox.rb', line 42

def wasm_path
  @wasm_path
end

Instance Method Details

#define(name) ⇒ Object

Declare or retrieve the Namespace named name on this Sandbox (SPEC.md B-07, B-09, B-10). name must be a Symbol or String in constant form. Returns the Kobako::RPC::Namespace.

Raises ArgumentError when called after #run, or when name does not match the constant-name pattern.



106
107
108
# File 'lib/kobako/sandbox.rb', line 106

def define(name)
  @services.define(name)
end

#run(source) ⇒ Object

Execute a guest mruby script (SPEC.md B-02 / B-03). source is the mruby source code as a UTF-8 String. Returns the deserialized last expression of the script.

Source delivery uses the WASI stdin two-frame protocol (SPEC.md ABI Signatures): Frame 1 carries the msgpack-encoded preamble (Namespace / Member registry snapshot) and Frame 2 carries the user script UTF-8 bytes. Each frame is prefixed by a 4-byte big-endian u32 length.

Raises Kobako::TrapError on a Wasm trap or wire-violation fallback; Kobako::SandboxError when the guest ran to completion but failed; Kobako::ServiceError on an unrescued Service capability failure.

Raises:



124
125
126
127
128
129
130
131
132
133
# File 'lib/kobako/sandbox.rb', line 124

def run(source)
  raise SandboxError, "source must be a String, got #{source.class}" unless source.is_a?(String)

  @services.seal!
  reset_run_state!

  run_guest(@services.encoded_preamble, source.b)
  read_captures!
  take_result!
end

#stderrObject

Returns the bytes the guest wrote to stderr during the most recent #run as a UTF-8 String, clipped at stderr_limit. Empty before any #run call. Mirror of #stdout.



58
59
60
# File 'lib/kobako/sandbox.rb', line 58

def stderr
  @stderr_capture.bytes
end

#stderr_truncated?Boolean

Returns true iff stderr capture during the most recent #run exceeded stderr_limit. Mirror of #stdout_truncated?.

Returns:

  • (Boolean)


72
73
74
# File 'lib/kobako/sandbox.rb', line 72

def stderr_truncated?
  @stderr_capture.truncated?
end

#stdoutObject

Returns the bytes the guest wrote to stdout during the most recent #run as a UTF-8 String, clipped at stdout_limit. Empty before any #run call. SPEC.md B-04 — the byte content never contains a truncation sentinel; use #stdout_truncated? to observe overflow.



51
52
53
# File 'lib/kobako/sandbox.rb', line 51

def stdout
  @stdout_capture.bytes
end

#stdout_truncated?Boolean

Returns true iff stdout capture during the most recent #run exceeded stdout_limit (SPEC.md B-04). Resets to false at the start of the next #run (SPEC.md B-03).

Returns:

  • (Boolean)


66
67
68
# File 'lib/kobako/sandbox.rb', line 66

def stdout_truncated?
  @stdout_capture.truncated?
end