Class: Hermetic::Remote

Inherits:
Backends::Base show all
Defined in:
lib/hermetic/remote.rb

Overview

Off-host executor CLIENT — the self-host trust boundary (spec §3). Wraps a local backend kind (:gvisor/:firecracker/:docker) and ships each run as JSON to a dedicated sandbox host that holds no database creds, no RAILS_MASTER_KEY, no ledger. This process keeps only the URL + token. EXECUTOR.md is the server side of this contract.

Constant Summary collapse

BACKENDS =
%i[docker gvisor firecracker].freeze

Constants inherited from Backends::Base

Backends::Base::OFF_HOST_TRUST, Backends::Base::TIMEOUT_EXIT

Instance Attribute Summary collapse

Attributes inherited from Backends::Base

#limits, #trust

Instance Method Summary collapse

Methods inherited from Backends::Base

#enabled?, #off_host?, #run

Methods included from SilasLedgerGuard

#run

Constructor Details

#initialize(executor:, token:, backend: :gvisor, backend_options: {}, transport: nil, **opts) ⇒ Remote

Returns a new instance of Remote.

Raises:



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/hermetic/remote.rb', line 14

def initialize(executor:, token:, backend: :gvisor, backend_options: {}, transport: nil, **opts)
  raise ConfigError, "executor URL is required" if executor.to_s.strip.empty?
  raise ConfigError, "token is required — the executor only accepts authenticated runs" if token.to_s.strip.empty?
  unless BACKENDS.include?(backend)
    raise ConfigError, "unknown executor backend #{backend.inspect} (known: #{BACKENDS.inspect})"
  end

  super(trust: :remote, **opts)
  @executor = executor.to_s.chomp("/")
  @token = token
  @backend = backend
  @backend_options = backend_options.to_h
  @transport = transport || Transport::Http.new
end

Instance Attribute Details

#backendObject (readonly)

Returns the value of attribute backend.



12
13
14
# File 'lib/hermetic/remote.rb', line 12

def backend
  @backend
end

#executorObject (readonly)

Returns the value of attribute executor.



12
13
14
# File 'lib/hermetic/remote.rb', line 12

def executor
  @executor
end

Instance Method Details

#backend_nameObject

Result#backend reports the isolation tech the executor runs; trust :remote carries the boundary — the two axes stay unconflated (spec §3).



31
# File 'lib/hermetic/remote.rb', line 31

def backend_name = @backend

#run_spec(request) ⇒ Object

Pure: one run as an HTTP request spec. Idempotency-Key is deterministic for the same logical run — the executor-side dedup handle that makes a retry of an in-doubt run safe (spec §7 risk 2, EXECUTOR.md).



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/hermetic/remote.rb', line 36

def run_spec(request)
  {
    method: :post,
    url: "#{@executor}/run",
    headers: {
      "Authorization" => "Bearer #{@token}",
      "Content-Type" => "application/json",
      "Idempotency-Key" => request.idempotency_key
    },
    body: JSON.generate(
      v: 1,
      backend: @backend,
      backend_options: @backend_options,
      argv: request.exec_argv,
      stdin: request.stdin,
      files: request.files,
      env: request.clean_env,
      network: { egress: request.network.egress },
      timeout: request.timeout,
      limits: request.limits.to_h
    )
  }
end