Module: SecurityBox::GuestRpc
- Defined in:
- lib/security_box/guest_rpc.rb
Overview
Host side of the guest RPC channel (stage 6).
The image statically links the sb_rpc gem, whose C extension declares the wasm import ("sb", "call"). The linker must define it for every instantiation — even when no handlers are configured, or instantiation fails on an unresolved import. Per-eval state (the /work tmpdir, the handler map and the call transcript) travels through Store data and reaches the closure via caller.store_data, so a single definition is safe to share across evaluations, threads and Ractor workers.
Protocol (guest side: lib/security_box/guest/rpc.rb):
guest writes /work/rpc_req.json {"name", "args"}
guest calls SBExt.call (blocks inside the import)
host executes handlers[name], writes /work/rpc_resp.json
host returns 0 (any non-zero value is a transport failure)
Nothing escapes the closure: a raising handler (or any failure in the bridge) becomes an false, "error": {"class", "message"} response the guest can rescue. Messages never include host details (no backtraces, no paths). Handler results are JSON round-tripped, like guest return values — never Marshal.
Constant Summary collapse
- IMPORT_MODULE =
"sb"- IMPORT_NAME =
"call"- REQUEST_FILE =
"rpc_req.json"- RESPONSE_FILE =
"rpc_resp.json"- MAX_CALLS =
1_000- RESULT_LIMIT =
1 << 20
Class Method Summary collapse
-
.define_import(linker) ⇒ Object
Defines the import on
linker(once per linker; state is per-Store). -
.store_data(workdir, handlers) ⇒ Object
Per-eval Store data.
Class Method Details
.define_import(linker) ⇒ Object
Defines the import on linker (once per linker; state is
per-Store). The closure captures nothing — Ractor-safe.
38 39 40 41 42 43 |
# File 'lib/security_box/guest_rpc.rb', line 38 def define_import(linker) linker.func_new(IMPORT_MODULE, IMPORT_NAME, [], [:i32]) do |caller| serve(caller) end nil end |
.store_data(workdir, handlers) ⇒ Object
Per-eval Store data. handlers is the configuration's
name => callable map, or nil when no rpcs are configured (guest
calls still get a clean, rescuable error).
48 49 50 51 52 53 |
# File 'lib/security_box/guest_rpc.rb', line 48 def store_data(workdir, handlers) { workdir: workdir, rpc: handlers.nil? ? nil : { handlers: handlers, calls: [] } } end |