kobako 0.12.1-aarch64-linux → 0.13.0-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +22 -0
- data/README.md +3 -1
- data/crates/kobako-runtime/CHANGELOG.md +16 -0
- data/crates/kobako-runtime/README.md +34 -0
- data/crates/kobako-wasmtime/CHANGELOG.md +16 -0
- data/crates/kobako-wasmtime/README.md +32 -0
- data/data/kobako.wasm +0 -0
- data/lib/kobako/3.3/kobako.so +0 -0
- data/lib/kobako/3.4/kobako.so +0 -0
- data/lib/kobako/4.0/kobako.so +0 -0
- data/lib/kobako/catalog/handles.rb +3 -3
- data/lib/kobako/catalog/namespaces.rb +4 -0
- data/lib/kobako/catalog/snippets.rb +4 -0
- data/lib/kobako/codec/encoder.rb +5 -1
- data/lib/kobako/codec/factory.rb +41 -13
- data/lib/kobako/codec/handle_walk.rb +4 -0
- data/lib/kobako/codec.rb +1 -1
- data/lib/kobako/errors.rb +18 -16
- data/lib/kobako/sandbox.rb +71 -39
- data/lib/kobako/sandbox_options.rb +71 -13
- data/lib/kobako/transport/dispatcher.rb +2 -2
- data/lib/kobako/transport/response.rb +14 -14
- data/lib/kobako/transport/run.rb +2 -6
- data/lib/kobako/transport/yield.rb +1 -1
- data/lib/kobako/transport/yielder.rb +2 -2
- data/lib/kobako/version.rb +1 -1
- data/lib/kobako.rb +0 -1
- data/release-please-config.json +78 -3
- data/sig/kobako/codec/factory.rbs +3 -0
- data/sig/kobako/errors.rbs +7 -14
- data/sig/kobako/runtime.rbs +16 -6
- data/sig/kobako/sandbox.rbs +11 -7
- data/sig/kobako/sandbox_options.rbs +15 -4
- data/sig/kobako/transport/dispatcher.rbs +1 -1
- data/sig/kobako/transport/run.rbs +2 -2
- data/sig/kobako/transport/yielder.rbs +2 -2
- data/sig/kobako/transport.rbs +8 -0
- metadata +6 -4
- data/lib/kobako/snapshot.rb +0 -38
- data/sig/kobako/snapshot.rbs +0 -15
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "errors"
|
|
4
|
+
|
|
3
5
|
module Kobako
|
|
4
6
|
# Kobako::SandboxOptions — immutable Value Object holding the four
|
|
5
|
-
# per-Sandbox configuration caps
|
|
6
|
-
# Data.define(...)+ subclass form (the
|
|
7
|
-
# +lib/kobako/outcome/panic.rb+).
|
|
7
|
+
# per-Sandbox configuration caps and the requested isolation profile.
|
|
8
|
+
# Built on the +class X < Data.define(...)+ subclass form (the
|
|
9
|
+
# Steep-friendly shape — see +lib/kobako/outcome/panic.rb+).
|
|
8
10
|
#
|
|
9
|
-
# The +initialize+
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
|
|
11
|
+
# The +initialize+ normalises every option before delegating to Data's
|
|
12
|
+
# +super+: +timeout+ to Float seconds, +memory_limit+ / +stdout_limit+ /
|
|
13
|
+
# +stderr_limit+ to positive Integer bytes. Each cap is +nil+-disablable
|
|
14
|
+
# (an absent argument takes its DEFAULT; an explicit +nil+ leaves the
|
|
15
|
+
# bound off), so all four behave uniformly. +profile+ is the one
|
|
16
|
+
# non-cap: a Symbol on the PROFILES ladder naming the posture the
|
|
17
|
+
# runtime builds, which is also the weakest the Host App accepts —
|
|
18
|
+
# +nil+ is rejected because the weakest posture is requested as an
|
|
19
|
+
# explicit +:permissive+. Anything that survives +SandboxOptions.new+
|
|
20
|
+
# is a wire-ready bundle the +Kobako::Runtime+ constructor consumes
|
|
21
|
+
# as-is. The options also own the ladder comparison
|
|
22
|
+
# (+#enforce_floor!+) that +Kobako::Sandbox+ delegates its
|
|
23
|
+
# construction floor check to.
|
|
24
|
+
class SandboxOptions < Data.define(:timeout, :memory_limit, :stdout_limit, :stderr_limit, :profile)
|
|
15
25
|
# Default wall-clock timeout for a single invocation: 60 seconds.
|
|
16
26
|
DEFAULT_TIMEOUT_SECONDS = 60.0
|
|
17
27
|
|
|
@@ -23,17 +33,41 @@ module Kobako
|
|
|
23
33
|
# Default per-channel capture ceiling: 1 MiB.
|
|
24
34
|
DEFAULT_OUTPUT_LIMIT = 1 << 20
|
|
25
35
|
|
|
36
|
+
# The isolation ladder, weakest first — index order is rank order,
|
|
37
|
+
# so a floor check is an index comparison.
|
|
38
|
+
PROFILES = %i[permissive hermetic].freeze
|
|
39
|
+
|
|
40
|
+
# Default isolation profile: the strictest rung — opting down to
|
|
41
|
+
# +:permissive+ is the Host App's explicit trade.
|
|
42
|
+
DEFAULT_PROFILE = :hermetic
|
|
43
|
+
|
|
26
44
|
def initialize(timeout: DEFAULT_TIMEOUT_SECONDS,
|
|
27
45
|
memory_limit: DEFAULT_MEMORY_LIMIT,
|
|
28
|
-
stdout_limit:
|
|
29
|
-
stderr_limit:
|
|
46
|
+
stdout_limit: DEFAULT_OUTPUT_LIMIT,
|
|
47
|
+
stderr_limit: DEFAULT_OUTPUT_LIMIT,
|
|
48
|
+
profile: DEFAULT_PROFILE)
|
|
30
49
|
timeout = normalize_timeout(timeout)
|
|
31
50
|
memory_limit = normalize_memory_limit(memory_limit)
|
|
32
|
-
stdout_limit
|
|
33
|
-
stderr_limit
|
|
51
|
+
stdout_limit = normalize_output_limit(stdout_limit, "stdout_limit")
|
|
52
|
+
stderr_limit = normalize_output_limit(stderr_limit, "stderr_limit")
|
|
53
|
+
profile = normalize_profile(profile)
|
|
34
54
|
super
|
|
35
55
|
end
|
|
36
56
|
|
|
57
|
+
# Enforce the requested +profile+ as the floor against +declared+ —
|
|
58
|
+
# the posture a runtime reports having built — so a runtime that
|
|
59
|
+
# cannot honor the request fails construction with
|
|
60
|
+
# +Kobako::SetupError+ instead of weakening the posture silently.
|
|
61
|
+
# Both fallbacks fail closed: a declaration off the PROFILES ladder
|
|
62
|
+
# ranks below every request, and a request off the ladder
|
|
63
|
+
# (unreachable past +initialize+) refuses every declaration.
|
|
64
|
+
def enforce_floor!(declared)
|
|
65
|
+
return if (PROFILES.index(declared) || -1) >= (PROFILES.index(profile) || PROFILES.size)
|
|
66
|
+
|
|
67
|
+
raise Kobako::SetupError, "runtime declares isolation profile #{declared.inspect}, " \
|
|
68
|
+
"below the requested floor #{profile.inspect}"
|
|
69
|
+
end
|
|
70
|
+
|
|
37
71
|
private
|
|
38
72
|
|
|
39
73
|
# Coerce +timeout+ into the Float seconds the ext expects, or +nil+
|
|
@@ -62,5 +96,29 @@ module Kobako
|
|
|
62
96
|
|
|
63
97
|
memory_limit
|
|
64
98
|
end
|
|
99
|
+
|
|
100
|
+
# Coerce a per-channel output cap (+stdout_limit+ / +stderr_limit+)
|
|
101
|
+
# into the byte cap the ext expects, or +nil+ to leave the channel
|
|
102
|
+
# uncapped. Same shape as +normalize_memory_limit+: a positive Integer
|
|
103
|
+
# when set, Float / zero / negative rejected. +name+ tags the
|
|
104
|
+
# +ArgumentError+ with the offending keyword.
|
|
105
|
+
def normalize_output_limit(limit, name)
|
|
106
|
+
return nil if limit.nil?
|
|
107
|
+
unless limit.is_a?(Integer) && limit.positive?
|
|
108
|
+
raise ArgumentError, "#{name} must be a positive Integer or nil, got #{limit.inspect}"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
limit
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Validate +profile+ against the PROFILES ladder. Unlike the caps
|
|
115
|
+
# there is no +nil+ form: the weakest posture is requested as an
|
|
116
|
+
# explicit +:permissive+, so anything off the ladder — +nil+
|
|
117
|
+
# included — is rejected.
|
|
118
|
+
def normalize_profile(profile)
|
|
119
|
+
return profile if PROFILES.include?(profile)
|
|
120
|
+
|
|
121
|
+
raise ArgumentError, "profile must be one of #{PROFILES.map(&:inspect).join(", ")}, got #{profile.inspect}"
|
|
122
|
+
end
|
|
65
123
|
end
|
|
66
124
|
end
|
|
@@ -72,8 +72,8 @@ module Kobako
|
|
|
72
72
|
# closure so the Dispatcher stays stateless and the registry doesn't
|
|
73
73
|
# need to publish accessors for the Sandbox-owned +Catalog::Handles+
|
|
74
74
|
# or +Runtime+. +yield_to_guest+ is a +String → String+ callable
|
|
75
|
-
# (
|
|
76
|
-
#
|
|
75
|
+
# (the ext's per-dispatch +Kobako::Runtime::GuestYielder+) used only
|
|
76
|
+
# when the Request carries +block_given: true+. Always
|
|
77
77
|
# returns a binary String — every failure path is reified as a
|
|
78
78
|
# Response.error envelope so the guest sees a transport error rather
|
|
79
79
|
# than a wasm trap.
|
|
@@ -38,20 +38,6 @@ module Kobako
|
|
|
38
38
|
new(status: STATUS_ERROR, payload: fault)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
# Decode +bytes+ into a {Response}. Raises +Codec::InvalidType+ when the
|
|
42
|
-
# envelope is not the expected 2-element msgpack array, or when the
|
|
43
|
-
# Value Object's construction invariants reject the decoded fields.
|
|
44
|
-
def self.decode(bytes)
|
|
45
|
-
Codec::Decoder.decode(bytes) do |arr|
|
|
46
|
-
unless arr.is_a?(Array) && arr.length == 2
|
|
47
|
-
raise Codec::InvalidType, "Response envelope is malformed (expected a 2-element array)"
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
status, payload = arr
|
|
51
|
-
new(status: status, payload: payload)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
41
|
def initialize(status:, payload:)
|
|
56
42
|
unless [STATUS_OK, STATUS_ERROR].include?(status)
|
|
57
43
|
raise ArgumentError, "Response status must be 0 (ok) or 1 (error), got #{status.inspect}"
|
|
@@ -71,6 +57,20 @@ module Kobako
|
|
|
71
57
|
def encode
|
|
72
58
|
Codec::Encoder.encode([status, payload])
|
|
73
59
|
end
|
|
60
|
+
|
|
61
|
+
# Decode +bytes+ into a {Response}. Raises +Codec::InvalidType+ when the
|
|
62
|
+
# envelope is not the expected 2-element msgpack array, or when the
|
|
63
|
+
# Value Object's construction invariants reject the decoded fields.
|
|
64
|
+
def self.decode(bytes)
|
|
65
|
+
Codec::Decoder.decode(bytes) do |arr|
|
|
66
|
+
unless arr.is_a?(Array) && arr.length == 2
|
|
67
|
+
raise Codec::InvalidType, "Response envelope is malformed (expected a 2-element array)"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
status, payload = arr
|
|
71
|
+
new(status: status, payload: payload)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
end
|
data/lib/kobako/transport/run.rb
CHANGED
|
@@ -43,8 +43,8 @@ module Kobako
|
|
|
43
43
|
|
|
44
44
|
def initialize(entrypoint:, args: [], kwargs: {})
|
|
45
45
|
entrypoint = normalize_entrypoint(entrypoint)
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
validate_args!(args)
|
|
47
|
+
validate_kwargs!(kwargs)
|
|
48
48
|
super
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -100,8 +100,6 @@ module Kobako
|
|
|
100
100
|
def validate_args!(args)
|
|
101
101
|
raise ArgumentError, "arguments must be an Array" unless args.is_a?(Array)
|
|
102
102
|
raise ArgumentError, forged_handle_message("arguments") if args.any?(Kobako::Handle)
|
|
103
|
-
|
|
104
|
-
args
|
|
105
103
|
end
|
|
106
104
|
|
|
107
105
|
# Reject a non-Symbol kwargs key, and a +Kobako::Handle+ arriving
|
|
@@ -117,8 +115,6 @@ module Kobako
|
|
|
117
115
|
"keyword argument keys must be Symbols (got #{bad_keys.inspect})"
|
|
118
116
|
end
|
|
119
117
|
raise ArgumentError, forged_handle_message("keyword argument values") if kwargs.each_value.any?(Kobako::Handle)
|
|
120
|
-
|
|
121
|
-
kwargs
|
|
122
118
|
end
|
|
123
119
|
|
|
124
120
|
# Single source of truth for the forged-Handle reject message so the
|
|
@@ -67,7 +67,7 @@ module Kobako
|
|
|
67
67
|
raise Codec::InvalidType, "YieldResponse must carry at least one byte" if bytes.empty?
|
|
68
68
|
|
|
69
69
|
tag = bytes.getbyte(0) # : Integer
|
|
70
|
-
body = bytes.byteslice(1, bytes.bytesize - 1)
|
|
70
|
+
body = bytes.byteslice(1, bytes.bytesize - 1) # : String
|
|
71
71
|
|
|
72
72
|
reject_dead_tag!(tag)
|
|
73
73
|
new(tag: tag, value: Codec::Decoder.decode(body))
|
|
@@ -28,8 +28,8 @@ module Kobako
|
|
|
28
28
|
# dispatch completes; any later call to a stashed Yielder then raises
|
|
29
29
|
# +LocalJumpError+ — the observable shape of an escaped Yielder.
|
|
30
30
|
class Yielder
|
|
31
|
-
# +yield_to_guest+ is a +String → String+ callable (
|
|
32
|
-
# +Runtime
|
|
31
|
+
# +yield_to_guest+ is a +String → String+ callable (the ext's
|
|
32
|
+
# per-dispatch +Kobako::Runtime::GuestYielder+) that
|
|
33
33
|
# {#yield} invokes to re-enter the guest; +break_tag+ is the +catch+
|
|
34
34
|
# throw tag the Dispatcher matches against to unwind the Service on
|
|
35
35
|
# +tag 0x02+. +handler+ is the Sandbox's +Kobako::Catalog::Handles+,
|
data/lib/kobako/version.rb
CHANGED
data/lib/kobako.rb
CHANGED
data/release-please-config.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
|
3
3
|
"release-type": "ruby",
|
|
4
|
-
"last-release-sha": "
|
|
4
|
+
"last-release-sha": "98509af508988f708bf0d7a76a718bb0428a177e",
|
|
5
5
|
"packages": {
|
|
6
6
|
".": {
|
|
7
7
|
"component": "kobako",
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"path": "/wasm/Cargo.lock",
|
|
19
19
|
"jsonpath": "$.package[?(@.name=='kobako-core')].version"
|
|
20
20
|
},
|
|
21
|
+
{
|
|
22
|
+
"type": "toml",
|
|
23
|
+
"path": "/wasm/kobako-core/Cargo.toml",
|
|
24
|
+
"jsonpath": "$.dependencies['kobako-codec'].version"
|
|
25
|
+
},
|
|
21
26
|
{
|
|
22
27
|
"type": "generic",
|
|
23
28
|
"path": "/wasm/kobako-core/README.md"
|
|
@@ -38,6 +43,11 @@
|
|
|
38
43
|
"path": "/wasm/kobako/Cargo.toml",
|
|
39
44
|
"jsonpath": "$.dependencies['kobako-core'].version"
|
|
40
45
|
},
|
|
46
|
+
{
|
|
47
|
+
"type": "toml",
|
|
48
|
+
"path": "/wasm/kobako/Cargo.toml",
|
|
49
|
+
"jsonpath": "$.dependencies['kobako-codec'].version"
|
|
50
|
+
},
|
|
41
51
|
{
|
|
42
52
|
"type": "generic",
|
|
43
53
|
"path": "/wasm/kobako/README.md"
|
|
@@ -103,13 +113,78 @@
|
|
|
103
113
|
"path": "/wasm/kobako-baker/README.md"
|
|
104
114
|
}
|
|
105
115
|
]
|
|
116
|
+
},
|
|
117
|
+
"crates/kobako-codec": {
|
|
118
|
+
"component": "kobako-codec",
|
|
119
|
+
"release-type": "rust",
|
|
120
|
+
"extra-files": [
|
|
121
|
+
{
|
|
122
|
+
"type": "toml",
|
|
123
|
+
"path": "/crates/Cargo.lock",
|
|
124
|
+
"jsonpath": "$.package[?(@.name=='kobako-codec')].version"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"type": "toml",
|
|
128
|
+
"path": "/wasm/Cargo.lock",
|
|
129
|
+
"jsonpath": "$.package[?(@.name=='kobako-codec')].version"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "generic",
|
|
133
|
+
"path": "/crates/kobako-codec/README.md"
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
"crates/kobako-runtime": {
|
|
138
|
+
"component": "kobako-runtime",
|
|
139
|
+
"release-type": "rust",
|
|
140
|
+
"extra-files": [
|
|
141
|
+
{
|
|
142
|
+
"type": "toml",
|
|
143
|
+
"path": "/crates/Cargo.lock",
|
|
144
|
+
"jsonpath": "$.package[?(@.name=='kobako-runtime')].version"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"type": "toml",
|
|
148
|
+
"path": "/Cargo.lock",
|
|
149
|
+
"jsonpath": "$.package[?(@.name=='kobako-runtime')].version"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"type": "generic",
|
|
153
|
+
"path": "/crates/kobako-runtime/README.md"
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
"crates/kobako-wasmtime": {
|
|
158
|
+
"component": "kobako-wasmtime",
|
|
159
|
+
"release-type": "rust",
|
|
160
|
+
"extra-files": [
|
|
161
|
+
{
|
|
162
|
+
"type": "toml",
|
|
163
|
+
"path": "/crates/Cargo.lock",
|
|
164
|
+
"jsonpath": "$.package[?(@.name=='kobako-wasmtime')].version"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"type": "toml",
|
|
168
|
+
"path": "/Cargo.lock",
|
|
169
|
+
"jsonpath": "$.package[?(@.name=='kobako-wasmtime')].version"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"type": "toml",
|
|
173
|
+
"path": "/crates/kobako-wasmtime/Cargo.toml",
|
|
174
|
+
"jsonpath": "$.dependencies['kobako-runtime'].version"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"type": "generic",
|
|
178
|
+
"path": "/crates/kobako-wasmtime/README.md"
|
|
179
|
+
}
|
|
180
|
+
]
|
|
106
181
|
}
|
|
107
182
|
},
|
|
108
183
|
"plugins": [
|
|
109
184
|
{
|
|
110
185
|
"type": "linked-versions",
|
|
111
|
-
"groupName": "kobako
|
|
112
|
-
"components": ["kobako-core", "kobako-rs", "kobako-io", "kobako-json", "kobako-regexp", "kobako-baker"]
|
|
186
|
+
"groupName": "kobako crates",
|
|
187
|
+
"components": ["kobako-codec", "kobako-core", "kobako-rs", "kobako-io", "kobako-json", "kobako-regexp", "kobako-baker", "kobako-runtime", "kobako-wasmtime"]
|
|
113
188
|
}
|
|
114
189
|
],
|
|
115
190
|
"extra-files": [
|
|
@@ -8,6 +8,8 @@ module Kobako
|
|
|
8
8
|
EXT_SYMBOL: Integer
|
|
9
9
|
EXT_HANDLE: Integer
|
|
10
10
|
EXT_ERRENV: Integer
|
|
11
|
+
MAX_EXT_DEPTH: Integer
|
|
12
|
+
EXT_DEPTH_KEY: Symbol
|
|
11
13
|
|
|
12
14
|
def dump: (untyped value) -> String
|
|
13
15
|
def load: (String bytes) -> untyped
|
|
@@ -26,6 +28,7 @@ module Kobako
|
|
|
26
28
|
def unpack_handle: (String payload) -> Kobako::Handle
|
|
27
29
|
def pack_fault: (Kobako::Fault fault) -> String
|
|
28
30
|
def unpack_fault: (String payload) -> Kobako::Fault
|
|
31
|
+
def within_ext_frame: [T] (singleton(Kobako::Codec::Error) over_limit) { () -> T } -> T
|
|
29
32
|
end
|
|
30
33
|
end
|
|
31
34
|
end
|
data/sig/kobako/errors.rbs
CHANGED
|
@@ -17,7 +17,7 @@ module Kobako
|
|
|
17
17
|
class ModuleNotBuiltError < SetupError
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
module StructuredError : Error
|
|
21
21
|
attr_reader origin: String?
|
|
22
22
|
attr_reader klass: String?
|
|
23
23
|
attr_reader backtrace_lines: Array[String]?
|
|
@@ -32,22 +32,15 @@ module Kobako
|
|
|
32
32
|
) -> void
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
class
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
attr_reader backtrace_lines: Array[String]?
|
|
39
|
-
attr_reader details: untyped
|
|
35
|
+
class SandboxError < Error
|
|
36
|
+
include StructuredError
|
|
37
|
+
end
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
?origin: String?,
|
|
44
|
-
?klass: String?,
|
|
45
|
-
?backtrace_lines: Array[String]?,
|
|
46
|
-
?details: untyped
|
|
47
|
-
) -> void
|
|
39
|
+
class ServiceError < Error
|
|
40
|
+
include StructuredError
|
|
48
41
|
end
|
|
49
42
|
|
|
50
|
-
class
|
|
43
|
+
class HandleExhaustedError < SandboxError
|
|
51
44
|
end
|
|
52
45
|
|
|
53
46
|
class BytecodeError < SandboxError
|
data/sig/kobako/runtime.rbs
CHANGED
|
@@ -7,17 +7,27 @@ module Kobako
|
|
|
7
7
|
(Float | Integer)? timeout_seconds,
|
|
8
8
|
Integer? memory_limit,
|
|
9
9
|
Integer? stdout_limit_bytes,
|
|
10
|
-
Integer? stderr_limit_bytes
|
|
10
|
+
Integer? stderr_limit_bytes,
|
|
11
|
+
Symbol profile
|
|
11
12
|
) -> Runtime
|
|
12
13
|
|
|
13
|
-
def on_dispatch=: (^(String) -> String dispatch_proc) -> void
|
|
14
|
+
def on_dispatch=: (^(String, Kobako::Transport::_GuestYielder) -> String dispatch_proc) -> void
|
|
14
15
|
|
|
15
|
-
def
|
|
16
|
+
def eval: (String preamble, String source, String snippets) -> String
|
|
16
17
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
def run: (String preamble, String snippets, String envelope) -> Kobako::Snapshot
|
|
18
|
+
def run: (String preamble, String snippets, String envelope) -> String
|
|
20
19
|
|
|
21
20
|
def usage: () -> [Float, Integer]
|
|
21
|
+
|
|
22
|
+
def captures: () -> [String, bool, String, bool]
|
|
23
|
+
|
|
24
|
+
def profile: () -> Symbol
|
|
25
|
+
|
|
26
|
+
# Frame-scoped guest re-entry handle the ext hands the dispatch Proc as
|
|
27
|
+
# its second argument; stands in as the +String -> String+ callable the
|
|
28
|
+
# host +Transport::Yielder+ invokes for a block yield.
|
|
29
|
+
class GuestYielder
|
|
30
|
+
def call: (String args_bytes) -> String
|
|
31
|
+
end
|
|
22
32
|
end
|
|
23
33
|
end
|
data/sig/kobako/sandbox.rbs
CHANGED
|
@@ -8,15 +8,15 @@ module Kobako
|
|
|
8
8
|
# Forwarded to @options via Forwardable#def_delegators.
|
|
9
9
|
def timeout: () -> Float?
|
|
10
10
|
def memory_limit: () -> Integer?
|
|
11
|
-
def stdout_limit: () -> Integer
|
|
12
|
-
def stderr_limit: () -> Integer
|
|
11
|
+
def stdout_limit: () -> Integer?
|
|
12
|
+
def stderr_limit: () -> Integer?
|
|
13
|
+
def profile: () -> Symbol
|
|
13
14
|
|
|
15
|
+
# Every keyword beyond wasm_path forwards verbatim to
|
|
16
|
+
# SandboxOptions.new (the four caps + the profile floor).
|
|
14
17
|
def initialize: (
|
|
15
18
|
?wasm_path: String?,
|
|
16
|
-
|
|
17
|
-
?stderr_limit: Integer?,
|
|
18
|
-
?timeout: (Float | Integer)?,
|
|
19
|
-
?memory_limit: Integer?
|
|
19
|
+
**untyped options
|
|
20
20
|
) -> void
|
|
21
21
|
|
|
22
22
|
def stdout: () -> String
|
|
@@ -42,14 +42,18 @@ module Kobako
|
|
|
42
42
|
|
|
43
43
|
private
|
|
44
44
|
|
|
45
|
+
def build_runtime!: () -> Kobako::Runtime
|
|
46
|
+
|
|
45
47
|
def install_dispatch_proc!: () -> void
|
|
46
48
|
|
|
47
49
|
def begin_invocation!: () -> void
|
|
48
50
|
|
|
49
51
|
def read_usage!: () -> void
|
|
50
52
|
|
|
53
|
+
def read_captures!: () -> void
|
|
54
|
+
|
|
51
55
|
def trap_class_for: (Kobako::TrapError err) -> singleton(Kobako::TrapError)
|
|
52
56
|
|
|
53
|
-
def invoke!: (Symbol verb) { () ->
|
|
57
|
+
def invoke!: (Symbol verb) { () -> String } -> untyped
|
|
54
58
|
end
|
|
55
59
|
end
|
|
@@ -3,30 +3,41 @@ module Kobako
|
|
|
3
3
|
DEFAULT_TIMEOUT_SECONDS: Float
|
|
4
4
|
DEFAULT_MEMORY_LIMIT: Integer
|
|
5
5
|
DEFAULT_OUTPUT_LIMIT: Integer
|
|
6
|
+
DEFAULT_PROFILE: Symbol
|
|
7
|
+
PROFILES: Array[Symbol]
|
|
6
8
|
|
|
7
9
|
attr_reader timeout: Float?
|
|
8
10
|
attr_reader memory_limit: Integer?
|
|
9
|
-
attr_reader stdout_limit: Integer
|
|
10
|
-
attr_reader stderr_limit: Integer
|
|
11
|
+
attr_reader stdout_limit: Integer?
|
|
12
|
+
attr_reader stderr_limit: Integer?
|
|
13
|
+
attr_reader profile: Symbol
|
|
11
14
|
|
|
12
15
|
def self.new: (
|
|
13
16
|
?timeout: (Float | Integer)?,
|
|
14
17
|
?memory_limit: Integer?,
|
|
15
18
|
?stdout_limit: Integer?,
|
|
16
|
-
?stderr_limit: Integer
|
|
19
|
+
?stderr_limit: Integer?,
|
|
20
|
+
?profile: Symbol
|
|
17
21
|
) -> SandboxOptions
|
|
18
22
|
|
|
19
23
|
def initialize: (
|
|
20
24
|
?timeout: (Float | Integer)?,
|
|
21
25
|
?memory_limit: Integer?,
|
|
22
26
|
?stdout_limit: Integer?,
|
|
23
|
-
?stderr_limit: Integer
|
|
27
|
+
?stderr_limit: Integer?,
|
|
28
|
+
?profile: Symbol
|
|
24
29
|
) -> void
|
|
25
30
|
|
|
31
|
+
def enforce_floor!: (Symbol declared) -> void
|
|
32
|
+
|
|
26
33
|
private
|
|
27
34
|
|
|
28
35
|
def normalize_timeout: ((Float | Integer)? timeout) -> Float?
|
|
29
36
|
|
|
30
37
|
def normalize_memory_limit: (Integer? memory_limit) -> Integer?
|
|
38
|
+
|
|
39
|
+
def normalize_output_limit: (Integer? limit, String name) -> Integer?
|
|
40
|
+
|
|
41
|
+
def normalize_profile: (untyped profile) -> Symbol
|
|
31
42
|
end
|
|
32
43
|
end
|
|
@@ -12,7 +12,7 @@ module Kobako
|
|
|
12
12
|
|
|
13
13
|
CALLABLE_ALLOW: Array[Symbol]
|
|
14
14
|
|
|
15
|
-
def self?.dispatch: (String request_bytes, Kobako::Catalog::Namespaces namespaces, Kobako::Catalog::Handles handler,
|
|
15
|
+
def self?.dispatch: (String request_bytes, Kobako::Catalog::Namespaces namespaces, Kobako::Catalog::Handles handler, Kobako::Transport::_GuestYielder yield_to_guest) -> String
|
|
16
16
|
|
|
17
17
|
def self?.resolve_call_args: (Kobako::Transport::Request request, Kobako::Catalog::Handles handler) -> [Array[untyped], Hash[Symbol, untyped]]
|
|
18
18
|
|
|
@@ -17,9 +17,9 @@ module Kobako
|
|
|
17
17
|
|
|
18
18
|
def normalize_entrypoint: (Symbol | String target) -> Symbol
|
|
19
19
|
|
|
20
|
-
def validate_args!: (Array[untyped] args) ->
|
|
20
|
+
def validate_args!: (Array[untyped] args) -> void
|
|
21
21
|
|
|
22
|
-
def validate_kwargs!: (Hash[untyped, untyped] kwargs) ->
|
|
22
|
+
def validate_kwargs!: (Hash[untyped, untyped] kwargs) -> void
|
|
23
23
|
|
|
24
24
|
def forged_handle_message: (String slot) -> String
|
|
25
25
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module Transport
|
|
3
3
|
class Yielder
|
|
4
|
-
@yield_to_guest:
|
|
4
|
+
@yield_to_guest: Kobako::Transport::_GuestYielder
|
|
5
5
|
@break_tag: Symbol
|
|
6
6
|
@handler: Kobako::Catalog::Handles
|
|
7
7
|
@active: bool
|
|
8
8
|
|
|
9
|
-
def initialize: (
|
|
9
|
+
def initialize: (Kobako::Transport::_GuestYielder yield_to_guest, Symbol break_tag, Kobako::Catalog::Handles handler) -> void
|
|
10
10
|
|
|
11
11
|
def yield: (*untyped args) -> untyped
|
|
12
12
|
|
data/sig/kobako/transport.rbs
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module Transport
|
|
3
|
+
# The guest re-entry callable a dispatch hands to a Yielder: invoked
|
|
4
|
+
# with the encoded yield args, it returns the encoded YieldResponse.
|
|
5
|
+
# The ext's Kobako::Runtime::GuestYielder is the production conformer;
|
|
6
|
+
# modelled structurally so the Transport layer needs no upward
|
|
7
|
+
# dependency on Runtime.
|
|
8
|
+
interface _GuestYielder
|
|
9
|
+
def call: (String) -> String
|
|
10
|
+
end
|
|
3
11
|
end
|
|
4
12
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kobako
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Aotokitsuruya
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: msgpack
|
|
@@ -38,6 +38,10 @@ files:
|
|
|
38
38
|
- LICENSE
|
|
39
39
|
- README.md
|
|
40
40
|
- SECURITY.md
|
|
41
|
+
- crates/kobako-runtime/CHANGELOG.md
|
|
42
|
+
- crates/kobako-runtime/README.md
|
|
43
|
+
- crates/kobako-wasmtime/CHANGELOG.md
|
|
44
|
+
- crates/kobako-wasmtime/README.md
|
|
41
45
|
- data/kobako.wasm
|
|
42
46
|
- lib/kobako.rb
|
|
43
47
|
- lib/kobako/3.3/kobako.so
|
|
@@ -65,7 +69,6 @@ files:
|
|
|
65
69
|
- lib/kobako/runtime.rb
|
|
66
70
|
- lib/kobako/sandbox.rb
|
|
67
71
|
- lib/kobako/sandbox_options.rb
|
|
68
|
-
- lib/kobako/snapshot.rb
|
|
69
72
|
- lib/kobako/snippet.rb
|
|
70
73
|
- lib/kobako/snippet/binary.rb
|
|
71
74
|
- lib/kobako/snippet/source.rb
|
|
@@ -104,7 +107,6 @@ files:
|
|
|
104
107
|
- sig/kobako/runtime.rbs
|
|
105
108
|
- sig/kobako/sandbox.rbs
|
|
106
109
|
- sig/kobako/sandbox_options.rbs
|
|
107
|
-
- sig/kobako/snapshot.rbs
|
|
108
110
|
- sig/kobako/snippet.rbs
|
|
109
111
|
- sig/kobako/snippet/binary.rbs
|
|
110
112
|
- sig/kobako/snippet/source.rbs
|
data/lib/kobako/snapshot.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "capture"
|
|
4
|
-
require_relative "usage"
|
|
5
|
-
|
|
6
|
-
module Kobako
|
|
7
|
-
# Kobako::Snapshot — per-invocation observable bundle returned from
|
|
8
|
-
# +Kobako::Runtime#eval+ and +#run+.
|
|
9
|
-
#
|
|
10
|
-
# The magnus class (see ext/kobako/src/snapshot.rs) carries seven raw
|
|
11
|
-
# readers: +return_bytes+, +stdout_bytes+, +stdout_truncated+,
|
|
12
|
-
# +stderr_bytes+, +stderr_truncated+, +wall_time+, +memory_peak+. This
|
|
13
|
-
# file reopens the class to add the Ruby-side helpers that pack those
|
|
14
|
-
# raw fields into the user-facing value objects +Kobako::Capture+ and
|
|
15
|
-
# +Kobako::Usage+ — the same shape +Kobako::Sandbox+ exposes to the
|
|
16
|
-
# Host App.
|
|
17
|
-
class Snapshot
|
|
18
|
-
# Wrap the stdout capture pair (+stdout_bytes+, +stdout_truncated+)
|
|
19
|
-
# as a +Kobako::Capture+ value object. The byte content never carries
|
|
20
|
-
# a truncation sentinel; +#truncated?+ is the only way to observe
|
|
21
|
-
# that the cap was hit.
|
|
22
|
-
def stdout
|
|
23
|
-
Capture.new(bytes: stdout_bytes, truncated: stdout_truncated)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Wrap the stderr capture pair as a +Kobako::Capture+ value object.
|
|
27
|
-
# Mirror of +#stdout+.
|
|
28
|
-
def stderr
|
|
29
|
-
Capture.new(bytes: stderr_bytes, truncated: stderr_truncated)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Wrap the per-last-invocation usage pair (+wall_time+,
|
|
33
|
-
# +memory_peak+) as a +Kobako::Usage+ value object.
|
|
34
|
-
def usage
|
|
35
|
-
Usage.new(wall_time: wall_time, memory_peak: memory_peak)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|