Module: Rigor::Plugin::Box

Defined in:
lib/rigor/plugin/box.rb

Overview

ADR-39 slice 5 — the isolation boundary for target-library invocation. When Rigor is launched with RUBY_BOX=1 (opt-in; the launcher re-execs only when a project opts in), a target library is loaded and called inside a Ruby::Box so its core-class monkey-patches and gem version cannot contaminate Rigor's main space. Ruby::Box is not a security sandbox (the gem's code still runs in-process) — it is the contamination boundary the rule needs, which is sufficient because the rule only ever invokes a declared, trusted, pure target library.

Disabled by default. Box.enabled? is false unless the experimental Ruby::Box feature is active, so every consumer keeps a non-box path and the default behaviour (loading the trusted library into the main space, per slices 2/4) is unchanged. The box only ever holds the trusted, project-agnostic target libraries (inflection rules, the Rack status table); per-project / exact-version boxes are a later slice.

Class Method Summary collapse

Class Method Details

.enabled?Boolean

True only when the experimental Ruby::Box feature is present and active (the process was started with RUBY_BOX=1). Any error answers false so a consumer silently keeps its non-box path.

Returns:

  • (Boolean)


21
22
23
24
25
# File 'lib/rigor/plugin/box.rb', line 21

def enabled?
  defined?(::Ruby::Box) && ::Ruby::Box.respond_to?(:enabled?) && ::Ruby::Box.enabled?
rescue StandardError
  false
end

.eval(code) ⇒ Object

Evaluates code inside the shared box and returns the result across the box boundary. The caller MUST build code safely — interpolate value arguments through String#inspect (which round-trips as a safe Ruby literal) and only ever interpolate method names from a fixed allow-list, never free user input.



48
49
50
# File 'lib/rigor/plugin/box.rb', line 48

def eval(code)
  shared.eval(code)
end

.require_feature(feature) ⇒ Object

Requires feature into the shared box exactly once. Returns true when the feature is available in the box, false when it could not be loaded (the caller then declines — never falls back to loading into the main space, which would defeat the boundary).



35
36
37
38
39
40
41
42
43
# File 'lib/rigor/plugin/box.rb', line 35

def require_feature(feature)
  @required ||= {}
  return @required[feature] if @required.key?(feature)

  shared.require(feature)
  @required[feature] = true
rescue StandardError
  @required[feature] = false
end

.sharedObject

The process-shared box for trusted, project-agnostic target libraries. Built lazily on first use.



28
29
30
# File 'lib/rigor/plugin/box.rb', line 28

def shared
  @shared ||= ::Ruby::Box.new
end