kobako 0.27.0 → 0.29.0

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.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +1 -1
  3. data/CHANGELOG.md +241 -0
  4. data/Cargo.lock +132 -126
  5. data/README.md +240 -147
  6. data/ROADMAP.md +28 -22
  7. data/SECURITY.md +2 -2
  8. data/crates/kobako-runtime/CHANGELOG.md +117 -0
  9. data/crates/kobako-runtime/Cargo.toml +27 -6
  10. data/crates/kobako-runtime/README.md +16 -10
  11. data/crates/kobako-runtime/src/dispatch.rs +8 -0
  12. data/crates/kobako-runtime/src/error.rs +8 -9
  13. data/crates/kobako-runtime/src/filesystem/directory/spelling.rs +194 -0
  14. data/crates/kobako-runtime/src/filesystem/directory.rs +1082 -0
  15. data/crates/kobako-runtime/src/filesystem/memory.rs +1100 -0
  16. data/crates/kobako-runtime/src/filesystem/overlay/exclusive.rs +88 -0
  17. data/crates/kobako-runtime/src/filesystem/overlay/stack.rs +808 -0
  18. data/crates/kobako-runtime/src/filesystem/overlay.rs +1955 -0
  19. data/crates/kobako-runtime/src/filesystem/path.rs +60 -0
  20. data/crates/kobako-runtime/src/filesystem/temporary.rs +167 -0
  21. data/crates/kobako-runtime/src/filesystem.rs +392 -0
  22. data/crates/kobako-runtime/src/grant.rs +20 -0
  23. data/crates/kobako-runtime/src/lib.rs +12 -2
  24. data/crates/kobako-runtime/src/mount.rs +178 -0
  25. data/crates/kobako-runtime/src/profile.rs +4 -4
  26. data/crates/kobako-runtime/src/runtime.rs +43 -17
  27. data/crates/kobako-runtime/src/snapshot.rs +33 -15
  28. data/crates/kobako-runtime/src/yielder.rs +14 -6
  29. data/crates/kobako-transport/CHANGELOG.md +45 -0
  30. data/crates/kobako-transport/Cargo.toml +1 -1
  31. data/crates/kobako-transport/README.md +21 -12
  32. data/crates/kobako-transport/src/abi.rs +11 -14
  33. data/crates/kobako-transport/src/envelope/bytes.rs +18 -6
  34. data/crates/kobako-transport/src/envelope/compile_reply.rs +139 -0
  35. data/crates/kobako-transport/src/envelope/fault.rs +2 -1
  36. data/crates/kobako-transport/src/envelope/outcome.rs +17 -16
  37. data/crates/kobako-transport/src/envelope/preamble.rs +513 -0
  38. data/crates/kobako-transport/src/envelope/reply.rs +103 -61
  39. data/crates/kobako-transport/src/envelope/request.rs +305 -0
  40. data/crates/kobako-transport/src/envelope/run.rs +1 -2
  41. data/crates/kobako-transport/src/envelope/tag.rs +49 -0
  42. data/crates/kobako-transport/src/envelope/unsupported.rs +105 -0
  43. data/crates/kobako-transport/src/envelope.rs +19 -12
  44. data/crates/kobako-transport/src/lib.rs +0 -2
  45. data/crates/kobako-wasmtime/CHANGELOG.md +163 -0
  46. data/crates/kobako-wasmtime/Cargo.toml +23 -16
  47. data/crates/kobako-wasmtime/README.md +6 -4
  48. data/crates/kobako-wasmtime/src/abi.rs +67 -36
  49. data/crates/kobako-wasmtime/src/ambient.rs +64 -5
  50. data/crates/kobako-wasmtime/src/cache.rs +204 -127
  51. data/crates/kobako-wasmtime/src/capture.rs +4 -11
  52. data/crates/kobako-wasmtime/src/config.rs +69 -15
  53. data/crates/kobako-wasmtime/src/descriptors.rs +167 -0
  54. data/crates/kobako-wasmtime/src/dispatch.rs +95 -87
  55. data/crates/kobako-wasmtime/src/driver.rs +174 -125
  56. data/crates/kobako-wasmtime/src/exports.rs +88 -34
  57. data/crates/kobako-wasmtime/src/guest_mem.rs +151 -138
  58. data/crates/kobako-wasmtime/src/imports.rs +46 -0
  59. data/crates/kobako-wasmtime/src/instance_pre.rs +19 -58
  60. data/crates/kobako-wasmtime/src/invocation.rs +84 -412
  61. data/crates/kobako-wasmtime/src/io.rs +89 -0
  62. data/crates/kobako-wasmtime/src/lib.rs +7 -24
  63. data/crates/kobako-wasmtime/src/limiter.rs +253 -0
  64. data/crates/kobako-wasmtime/src/preview1/args.rs +60 -0
  65. data/crates/kobako-wasmtime/src/preview1/beneath.rs +188 -0
  66. data/crates/kobako-wasmtime/src/preview1/differential/mount.rs +609 -0
  67. data/crates/kobako-wasmtime/src/preview1/differential.rs +372 -0
  68. data/crates/kobako-wasmtime/src/preview1/errno.rs +267 -0
  69. data/crates/kobako-wasmtime/src/preview1/fd.rs +672 -0
  70. data/crates/kobako-wasmtime/src/preview1/memory.rs +205 -0
  71. data/crates/kobako-wasmtime/src/preview1/mount_view.rs +2499 -0
  72. data/crates/kobako-wasmtime/src/preview1/path.rs +421 -0
  73. data/crates/kobako-wasmtime/src/preview1/poll.rs +333 -0
  74. data/crates/kobako-wasmtime/src/preview1/sock.rs +30 -0
  75. data/crates/kobako-wasmtime/src/preview1.rs +461 -0
  76. data/crates/kobako-wasmtime/src/trap.rs +66 -59
  77. data/crates/kobako-wasmtime/src/wasi.rs +317 -0
  78. data/crates/kobako-wasmtime/tests/compile_posture.rs +43 -0
  79. data/crates/kobako-wasmtime/tests/guest_file.rs +1054 -0
  80. data/crates/kobako-wasmtime/tests/preamble_flags.rs +70 -0
  81. data/crates/kobako-wasmtime/tests/snippet_compile.rs +95 -0
  82. data/crates/kobako-wasmtime/tests/support/mod.rs +30 -0
  83. data/crates/kobako-wasmtime/tests/unanswered_call.rs +86 -0
  84. data/crates/kobako-wasmtime/tests/unsupported_call.rs +51 -0
  85. data/data/kobako.wasm +0 -0
  86. data/ext/kobako/Cargo.toml +4 -2
  87. data/ext/kobako/src/runtime/bridge.rs +177 -113
  88. data/ext/kobako/src/runtime/errors.rs +26 -32
  89. data/ext/kobako/src/runtime/escape.rs +53 -0
  90. data/ext/kobako/src/runtime/filesystem/grants.rs +91 -0
  91. data/ext/kobako/src/runtime/filesystem/ruby.rs +400 -0
  92. data/ext/kobako/src/runtime/filesystem.rs +236 -0
  93. data/ext/kobako/src/runtime/gvl.rs +11 -13
  94. data/ext/kobako/src/runtime/pinned_value.rs +31 -0
  95. data/ext/kobako/src/runtime/snapshot.rs +127 -0
  96. data/ext/kobako/src/runtime.rs +190 -312
  97. data/lib/kobako/capture.rb +1 -4
  98. data/lib/kobako/catalog/extensions.rb +21 -59
  99. data/lib/kobako/catalog/flags.rb +29 -0
  100. data/lib/kobako/catalog/grants.rb +30 -0
  101. data/lib/kobako/catalog/handles.rb +7 -54
  102. data/lib/kobako/catalog/mount.rb +27 -0
  103. data/lib/kobako/catalog/services.rb +17 -60
  104. data/lib/kobako/catalog/snippets.rb +41 -69
  105. data/lib/kobako/catalog.rb +13 -10
  106. data/lib/kobako/codec/decoder.rb +10 -28
  107. data/lib/kobako/codec/encoder.rb +3 -22
  108. data/lib/kobako/codec/error.rb +6 -27
  109. data/lib/kobako/codec/ext_types.rb +72 -94
  110. data/lib/kobako/codec/handle_walk.rb +65 -130
  111. data/lib/kobako/codec/nesting.rb +3 -8
  112. data/lib/kobako/codec/state.rb +21 -11
  113. data/lib/kobako/codec/utils.rb +6 -34
  114. data/lib/kobako/codec/value_budget.rb +86 -0
  115. data/lib/kobako/codec.rb +10 -22
  116. data/lib/kobako/constant_name.rb +8 -0
  117. data/lib/kobako/context.rb +83 -117
  118. data/lib/kobako/errors.rb +57 -132
  119. data/lib/kobako/execution.rb +16 -21
  120. data/lib/kobako/extension.rb +23 -40
  121. data/lib/kobako/filesystem.rb +38 -0
  122. data/lib/kobako/handle.rb +7 -12
  123. data/lib/kobako/outcome.rb +51 -80
  124. data/lib/kobako/payload/arguments.rb +1 -16
  125. data/lib/kobako/payload.rb +4 -12
  126. data/lib/kobako/pool.rb +25 -55
  127. data/lib/kobako/runtime.rb +7 -21
  128. data/lib/kobako/sandbox.rb +128 -137
  129. data/lib/kobako/sandbox_options.rb +71 -90
  130. data/lib/kobako/snippet/bytecode.rb +11 -0
  131. data/lib/kobako/snippet/source.rb +1 -16
  132. data/lib/kobako/snippet.rb +2 -10
  133. data/lib/kobako/transport/block_failure.rb +35 -0
  134. data/lib/kobako/transport/call.rb +1 -14
  135. data/lib/kobako/transport/dispatcher.rb +127 -206
  136. data/lib/kobako/transport/error.rb +6 -20
  137. data/lib/kobako/transport/exposure.rb +10 -17
  138. data/lib/kobako/transport/reflection.rb +108 -63
  139. data/lib/kobako/transport/run.rb +17 -71
  140. data/lib/kobako/transport/yielder.rb +20 -94
  141. data/lib/kobako/transport.rb +4 -15
  142. data/lib/kobako/unresolved.rb +4 -11
  143. data/lib/kobako/usage.rb +2 -6
  144. data/lib/kobako/version.rb +1 -1
  145. data/lib/kobako.rb +1 -0
  146. data/sig/kobako/catalog/extensions.rbs +2 -2
  147. data/sig/kobako/catalog/flags.rbs +13 -0
  148. data/sig/kobako/catalog/grants.rbs +13 -0
  149. data/sig/kobako/catalog/mount.rbs +28 -0
  150. data/sig/kobako/catalog/services.rbs +3 -5
  151. data/sig/kobako/catalog/snippets.rbs +5 -5
  152. data/sig/kobako/catalog.rbs +1 -0
  153. data/sig/kobako/codec/ext_types.rbs +10 -8
  154. data/sig/kobako/codec/handle_walk.rbs +9 -7
  155. data/sig/kobako/codec/state.rbs +7 -1
  156. data/sig/kobako/codec/utils.rbs +2 -2
  157. data/sig/kobako/codec/value_budget.rbs +23 -0
  158. data/sig/kobako/codec.rbs +4 -2
  159. data/sig/kobako/constant_name.rbs +3 -0
  160. data/sig/kobako/context.rbs +15 -8
  161. data/sig/kobako/errors.rbs +10 -4
  162. data/sig/kobako/filesystem.rbs +88 -0
  163. data/sig/kobako/guest_yielder.rbs +9 -0
  164. data/sig/kobako/outcome.rbs +6 -8
  165. data/sig/kobako/pool.rbs +1 -1
  166. data/sig/kobako/runtime.rbs +21 -45
  167. data/sig/kobako/sandbox.rbs +11 -1
  168. data/sig/kobako/sandbox_options.rbs +25 -7
  169. data/sig/kobako/snapshot.rbs +20 -0
  170. data/sig/kobako/snippet/bytecode.rbs +12 -0
  171. data/sig/kobako/transport/block_failure.rbs +13 -0
  172. data/sig/kobako/transport/dispatcher.rbs +15 -19
  173. data/sig/kobako/transport/exposure.rbs +1 -1
  174. data/sig/kobako/transport/reflection.rbs +19 -4
  175. data/sig/kobako/transport/run.rbs +1 -3
  176. data/sig/kobako/transport/yielder.rbs +5 -9
  177. data/sig/kobako/transport.rbs +9 -8
  178. metadata +75 -10
  179. data/crates/kobako-transport/src/envelope/invocation_frames.rs +0 -241
  180. data/crates/kobako-wasmtime/src/frames.rs +0 -273
  181. data/lib/kobako/snippet/binary.rb +0 -26
  182. data/rust-toolchain.toml +0 -15
  183. data/sig/kobako/snippet/binary.rbs +0 -12
@@ -0,0 +1,28 @@
1
+ module Kobako
2
+ module Catalog
3
+ class Mount < Data
4
+ type access = Kobako::Filesystem::access
5
+
6
+ type policy = ^(String path, access access) -> boolish
7
+
8
+ type tuple = [String, access, Kobako::Filesystem::mountable, policy?]
9
+
10
+ attr_reader at: String
11
+ attr_reader access: access
12
+ attr_reader filesystem: Kobako::Filesystem::mountable
13
+ attr_reader policy: policy?
14
+
15
+ def self.new: (at: untyped, access: untyped, filesystem: untyped, policy: policy?) -> Mount
16
+
17
+ def key: () -> String
18
+
19
+ def conflict: (Mount other) -> String?
20
+
21
+ def to_native: () -> tuple
22
+
23
+ private
24
+
25
+ def nested?: (String other) -> bool
26
+ end
27
+ end
28
+ end
@@ -1,7 +1,7 @@
1
1
  module Kobako
2
2
  module Catalog
3
3
  class Services
4
- NAME_PATTERN: Regexp
4
+ RESERVED_NAMESPACE: String
5
5
 
6
6
  def initialize: () -> void
7
7
 
@@ -13,14 +13,12 @@ module Kobako
13
13
 
14
14
  def paths: () -> Array[String]
15
15
 
16
- def seal!: () -> self
17
-
18
- def sealed?: () -> bool
19
-
20
16
  private
21
17
 
22
18
  def validate_path!: (Symbol | String path) -> String
23
19
 
20
+ def reserved?: (String path) -> bool
21
+
24
22
  def collision?: (String path) -> bool
25
23
  end
26
24
  end
@@ -1,21 +1,21 @@
1
1
  module Kobako
2
2
  module Catalog
3
3
  class Snippets
4
- NAME_PATTERN: Regexp
5
-
6
- type entry = Kobako::Snippet::Source | Kobako::Snippet::Binary
4
+ type entry = Kobako::Snippet::Source | Kobako::Snippet::Bytecode
7
5
 
8
6
  type tuple = [Symbol, String?, String]
9
7
 
10
8
  def initialize: () -> void
11
9
 
12
- def register: (?code: String?, ?name: (Symbol | String)?, ?binary: String?) -> (Symbol | nil)
10
+ def register: (?code: String?, ?name: (Symbol | String)?, ?binary: String?) -> nil
13
11
 
14
12
  def entries: () -> Array[tuple]
15
13
 
14
+ def compile: () { (Array[tuple] entries) -> Array[String]? } -> nil
15
+
16
16
  private
17
17
 
18
- def register_source!: (String? code, (Symbol | String)? name) -> Symbol
18
+ def register_source!: (String? code, (Symbol | String)? name) -> nil
19
19
 
20
20
  def ensure_source_args!: (String? code, (Symbol | String)? name) -> [String, Symbol | String]
21
21
 
@@ -1,4 +1,5 @@
1
1
  module Kobako
2
2
  module Catalog
3
+ def self.to_utf8!: (String text, String what) -> String
3
4
  end
4
5
  end
@@ -5,21 +5,23 @@ module Kobako
5
5
  EXT_HANDLE: Integer
6
6
  UNREPRESENTABLE_GUARD_ID: Integer
7
7
 
8
- def self?.build_factory: () -> MessagePack::Factory
8
+ def self.build_factory: () -> MessagePack::Factory
9
9
 
10
- def self?.pack_symbol: (Symbol symbol) -> String
10
+ private
11
11
 
12
- def self?.unpack_symbol: (String payload) -> Symbol
12
+ def self.pack_symbol: (Symbol symbol) -> String
13
13
 
14
- def self?.pack_handle: (Kobako::Handle handle) -> String
14
+ def self.unpack_symbol: (String payload) -> Symbol
15
15
 
16
- def self?.unpack_handle: (String payload, State state) -> Kobako::Handle
16
+ def self.pack_handle: (Kobako::Handle handle) -> String
17
17
 
18
- def self?.register_symbol: (MessagePack::Factory factory) -> void
18
+ def self.unpack_handle: (String payload, State state) -> Kobako::Handle
19
19
 
20
- def self?.register_handle: (MessagePack::Factory factory) -> void
20
+ def self.register_symbol: (MessagePack::Factory factory) -> void
21
21
 
22
- def self?.register_unrepresentable: (MessagePack::Factory factory) -> void
22
+ def self.register_handle: (MessagePack::Factory factory) -> void
23
+
24
+ def self.register_unrepresentable: (MessagePack::Factory factory) -> void
23
25
  end
24
26
 
25
27
  FACTORY: MessagePack::Factory
@@ -3,19 +3,21 @@ module Kobako
3
3
  module HandleWalk
4
4
  MSGPACK_INT_RANGE: Range[Integer]
5
5
 
6
- def self?.representable?: (untyped value, ?Integer depth) -> bool
6
+ def self.representable?: (untyped value, ?Integer depth) -> bool
7
7
 
8
- def self?.deep_wrap: (untyped value, Kobako::Codec::_HandleTable handler, ?Integer depth) -> untyped
8
+ def self.deep_wrap: (untyped value, Kobako::Codec::_HandleTable handles, ?Integer depth) -> untyped
9
9
 
10
- def self?.guard_nesting!: (Integer depth) -> void
10
+ def self.deep_restore: (untyped value, Kobako::Codec::_HandleTable handles) -> untyped
11
11
 
12
- def self?.deep_wrap_hash: (Hash[untyped, untyped] hash, Kobako::Codec::_HandleTable handler, Integer depth) -> Hash[untyped, untyped]
12
+ private
13
13
 
14
- def self?.deep_restore: (untyped value, Kobako::Codec::_HandleTable handler) -> untyped
14
+ def self.guard_nesting!: (Integer depth) -> void
15
15
 
16
- def self?.primitive_type?: (untyped value) -> bool
16
+ def self.deep_wrap_hash: (Hash[untyped, untyped] hash, Kobako::Codec::_HandleTable handles, Integer depth) -> Hash[untyped, untyped]
17
17
 
18
- def self?.container_representable?: (untyped value, Integer depth) -> bool
18
+ def self.primitive_type?: (untyped value) -> bool
19
+
20
+ def self.container_representable?: (untyped value, Integer depth) -> bool
19
21
  end
20
22
  end
21
23
  end
@@ -5,8 +5,14 @@ module Kobako
5
5
 
6
6
  def self.current: () -> State
7
7
 
8
+ @carried_handle: bool
9
+ @value_budget: Integer?
10
+
11
+ attr_reader value_budget: Integer?
12
+
8
13
  def track_handles: [T] { () -> T } -> [T, bool]
9
- def record_handle!: () -> void
14
+ def record_handle: () -> void
15
+ def within_value_budget: [T] (Integer? budget) { () -> T } -> T
10
16
 
11
17
  private
12
18
 
@@ -1,9 +1,9 @@
1
1
  module Kobako
2
2
  module Codec
3
3
  module Utils
4
- def self?.assert_utf8!: (String string, String label) -> void
4
+ def self.assert_utf8!: (String string, String label) -> void
5
5
 
6
- def self?.with_boundary: [T] () { () -> T } -> T
6
+ def self.with_boundary: [T] () { () -> T } -> T
7
7
  end
8
8
  end
9
9
  end
@@ -0,0 +1,23 @@
1
+ module Kobako
2
+ module Codec
3
+ module ValueBudget
4
+ SCALARS: Hash[Integer, Integer]
5
+
6
+ COUNTS: Hash[Integer, [Integer, Integer]]
7
+
8
+ LENGTHS: Hash[Integer, [Integer, Integer]]
9
+
10
+ UINT: Hash[Integer, String]
11
+
12
+ def self.assert_within!: (String bytes, Integer? budget) -> void
13
+
14
+ private
15
+
16
+ def self.step: (String bytes, Integer pos) -> [Integer?, Integer]
17
+
18
+ def self.step_framed:(String bytes, Integer pos, Integer marker) -> [Integer?, Integer]
19
+
20
+ def self.uint: (String bytes, Integer pos, Integer width) -> Integer
21
+ end
22
+ end
23
+ end
data/sig/kobako/codec.rbs CHANGED
@@ -14,11 +14,13 @@ module Kobako
14
14
 
15
15
  def self.track_handles: [T] { () -> T } -> [T, bool]
16
16
 
17
+ def self.within_value_budget: [T] (Integer? budget) { () -> T } -> T
18
+
17
19
  # The Handle allocator/resolver a wire walk works against: alloc
18
20
  # registers a non-wire-representable object and returns its Handle,
19
21
  # fetch resolves a wire Handle id back to the live object. The
20
- # Sandbox's Kobako::Catalog::Handles is the production conformer;
21
- # modelled structurally so the Codec and Transport tiers need no
22
+ # Kobako::Catalog::Handles each invocation mints is the production
23
+ # conformer; modelled structurally so the Codec and Transport tiers need no
22
24
  # upward dependency on Catalog.
23
25
  interface _HandleTable
24
26
  def alloc: (untyped object) -> Kobako::Handle
@@ -0,0 +1,3 @@
1
+ module Kobako
2
+ CONSTANT_NAME: Regexp
3
+ end
@@ -1,14 +1,21 @@
1
1
  module Kobako
2
2
  class Context
3
+ type preamble = [Array[String], Array[Kobako::Catalog::Snippets::tuple], Array[Kobako::Catalog::Flags::tuple]]
4
+
5
+ @mounts: Hash[String, Kobako::Catalog::Mount]?
6
+
3
7
  def initialize: (
4
8
  runtime: Kobako::Runtime,
5
9
  services: Kobako::Catalog::Services,
6
- snippets: Kobako::Catalog::Snippets,
7
- extensions: Kobako::Catalog::Extensions
10
+ extensions: Kobako::Catalog::Extensions,
11
+ grants: Kobako::Catalog::Grants,
12
+ preamble: preamble
8
13
  ) -> void
9
14
 
10
15
  def bind: (Symbol | String path, untyped object) -> self
11
16
 
17
+ def mount: (String at, Kobako::Filesystem::mountable filesystem, ?access: Kobako::Filesystem::access) ?{ (String path, Kobako::Filesystem::access access) -> boolish } -> self
18
+
12
19
  def lookup: (Symbol | String path) -> Kobako::Transport::Exposure
13
20
 
14
21
  def eval: (String code) ?{ (Kobako::Context) -> void } -> Kobako::Execution
@@ -17,20 +24,20 @@ module Kobako
17
24
 
18
25
  private
19
26
 
27
+ def setup: () -> Kobako::Runtime::setup
28
+
20
29
  def collect_overrides: () { (Kobako::Context) -> void } -> void
21
30
 
22
31
  def dispatch_handler: () -> Kobako::Transport::dispatch_proc
23
32
 
24
- def populate_observability!: (Kobako::Runtime::Snapshot snapshot) -> void
25
-
26
- def trap_class_for: (Kobako::TrapError err) -> singleton(Kobako::TrapError)
33
+ def populate_observability:(Kobako::Snapshot snapshot) -> void
27
34
 
28
- def trap_error_for: (Kobako::Runtime::Snapshot snapshot, Symbol verb) -> Kobako::TrapError
35
+ def with_verb: (Kobako::TrapError err, Symbol verb) -> Kobako::TrapError
29
36
 
30
37
  def build_execution: (untyped value, failed: bool) -> Kobako::Execution
31
38
 
32
- def settle_outcome: (Kobako::Runtime::Snapshot snapshot, Symbol verb, Symbol? entrypoint) -> Kobako::Execution
39
+ def settle_outcome: (Kobako::Snapshot snapshot, Symbol verb, Symbol? entrypoint) -> Kobako::Execution
33
40
 
34
- def invoke!: (Symbol verb, ?entrypoint: Symbol?) { () -> Kobako::Runtime::Snapshot } -> Kobako::Execution
41
+ def invoke!: (Symbol verb, ?entrypoint: Symbol?) { () -> Kobako::Snapshot } -> Kobako::Execution
35
42
  end
36
43
  end
@@ -2,14 +2,14 @@ module Kobako
2
2
  class Error < StandardError
3
3
  end
4
4
 
5
- module CarriesExecution
5
+ module Recorded
6
6
  attr_reader execution: Kobako::Execution?
7
7
 
8
8
  def with_execution: (Kobako::Execution execution) -> self
9
9
  end
10
10
 
11
11
  class TrapError < Error
12
- include CarriesExecution
12
+ include Recorded
13
13
  end
14
14
 
15
15
  class TimeoutError < TrapError
@@ -39,12 +39,12 @@ module Kobako
39
39
 
40
40
  class SandboxError < Error
41
41
  include Diagnosable
42
- include CarriesExecution
42
+ include Recorded
43
43
  end
44
44
 
45
45
  class ServiceError < Error
46
46
  include Diagnosable
47
- include CarriesExecution
47
+ include Recorded
48
48
  end
49
49
 
50
50
  class NoServiceError < ServiceError
@@ -60,12 +60,18 @@ module Kobako
60
60
  class YieldValueError < Error
61
61
  end
62
62
 
63
+ class UnsupportedError < Error
64
+ end
65
+
63
66
  class HandleExhaustedError < SandboxError
64
67
  end
65
68
 
66
69
  class BytecodeError < SandboxError
67
70
  end
68
71
 
72
+ class UnsupportedFlagError < SandboxError
73
+ end
74
+
69
75
  class UndefinedEntrypointError < SandboxError
70
76
  attr_reader name: Symbol?
71
77
  attr_reader available: Array[Symbol]
@@ -0,0 +1,88 @@
1
+ module Kobako
2
+ module Filesystem
3
+ type mountable = Memory | Temporary | Directory | Overlay | _Readable
4
+
5
+ type access = :read | :read_write
6
+
7
+ # What a Filesystem written in Ruby answers to be mounted. One that
8
+ # also answers _Listable lists its directories, and one answering
9
+ # _Writable takes changes too; each method it lacks is refused alone.
10
+ interface _Readable
11
+ def open: (String path, Integer flags) -> _File
12
+ def stat: (String path) -> _Stat
13
+ end
14
+
15
+ interface _Listable
16
+ def children: (String path) -> Array[String]
17
+ end
18
+
19
+ interface _Writable
20
+ def mkdir: (String path) -> void
21
+ def rmdir: (String path) -> void
22
+ def unlink: (String path) -> void
23
+ def rename: (String from, String to, directory: bool?) -> void
24
+ end
25
+
26
+ # A file a Filesystem written in Ruby opened; +::File+ answers it. One
27
+ # that also answers _WritableFile takes writes too, one answering
28
+ # _AppendableFile takes appends, and any file may answer _SyncableFile
29
+ # to flush or _ClosableFile to close.
30
+ interface _File
31
+ def pread: (Integer length, Integer offset) -> String?
32
+ def size: () -> Integer
33
+ end
34
+
35
+ interface _WritableFile
36
+ def pwrite: (String data, Integer offset) -> Integer
37
+ def truncate: (Integer length) -> void
38
+ end
39
+
40
+ # Writes all of +data+ at the end in one step, answering where the file
41
+ # then ends.
42
+ interface _AppendableFile
43
+ def append: (String data) -> Integer
44
+ end
45
+
46
+ interface _SyncableFile
47
+ def fsync: () -> void
48
+ end
49
+
50
+ interface _ClosableFile
51
+ def close: () -> void
52
+ end
53
+
54
+ # What a Filesystem written in Ruby's +stat+ answers, as +File::Stat+
55
+ # does; an +ino+ of zero names no identity. One that also answers
56
+ # _StatDevice names the device its +ino+ belongs to.
57
+ interface _Stat
58
+ def directory?: () -> boolish
59
+ def size: () -> Integer
60
+ def ino: () -> Integer
61
+ end
62
+
63
+ interface _StatDevice
64
+ def dev: () -> Integer
65
+ end
66
+
67
+ class Memory
68
+ # A bare <tt>"path" => contents</tt> arrives as keywords, which RBS
69
+ # cannot key by String; a Symbol keyword past +limit+ and +inodes+
70
+ # raises ArgumentError.
71
+ def initialize: (?Hash[String, String] files, ?limit: Integer?, ?inodes: Integer?, **String) -> void
72
+ end
73
+
74
+ class Temporary
75
+ def initialize: (?limit: Integer?, ?inodes: Integer?) -> void
76
+ end
77
+
78
+ class Directory
79
+ def initialize: (String path) -> void
80
+ end
81
+
82
+ class Overlay
83
+ def initialize: () -> void
84
+ def layer: (mountable filesystem, ?access: access) -> Overlay
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,9 @@
1
+ module Kobako
2
+ # Frame-scoped guest re-entry handle the ext hands the dispatch Proc as
3
+ # its last argument — the production conformer of
4
+ # +Kobako::Transport::_GuestYielder+, answering the Yield Reply already
5
+ # split off the core envelope.
6
+ class GuestYielder
7
+ def call: (String args_bytes) -> [Symbol, String, String?]
8
+ end
9
+ end
@@ -6,18 +6,16 @@ module Kobako
6
6
 
7
7
  type panic_fields = [String, String, String, Array[String], Array[String]]
8
8
 
9
- def self?.reify: (Symbol kind, String payload, panic_fields? panic, ?entrypoint: Symbol?) -> Kobako::Codec::wire_value
9
+ def self.reify: (String payload, panic_fields? panic, ?entrypoint: Symbol?) -> Kobako::Codec::wire_value
10
10
 
11
- # Everything below is private_class_method at runtime; RBS cannot mark a
12
- # `self?` method private, so the declarations stay visible to the checker.
13
- def self?.panic_error: (panic_fields panic, Symbol? entrypoint) -> (SandboxError | ServiceError)
11
+ private
14
12
 
15
- def self?.error_class: (String origin, String klass) -> (singleton(SandboxError) | singleton(ServiceError))
13
+ def self.panic_error: (panic_fields panic, Symbol? entrypoint) -> (SandboxError | ServiceError)
16
14
 
17
- def self?.trap_error: (Symbol kind) -> TrapError
15
+ def self.error_class: (String origin, String klass) -> (singleton(SandboxError) | singleton(ServiceError))
18
16
 
19
- def self?.decode_value: (String payload) -> Kobako::Codec::wire_value
17
+ def self.decode_value: (String payload) -> Kobako::Codec::wire_value
20
18
 
21
- def self?.wire_error: (String message, ?diagnostic: String?) -> Transport::Error
19
+ def self.wire_error: (String message, ?diagnostic: String?) -> Transport::Error
22
20
  end
23
21
  end
data/sig/kobako/pool.rbs CHANGED
@@ -31,7 +31,7 @@ module Kobako
31
31
 
32
32
  def checkin: (Kobako::Sandbox sandbox) -> void
33
33
 
34
- def release_capacity!: () -> void
34
+ def release_capacity: () -> void
35
35
 
36
36
  def monotonic_now: () -> Float
37
37
 
@@ -2,62 +2,38 @@ module Kobako
2
2
  class Runtime
3
3
  def self.default_path: () -> String
4
4
 
5
+ def self.validate_mount!: (untyped at, untyped access, untyped filesystem) -> nil
6
+
5
7
  def self.from_path: (
6
8
  String path,
7
- (Float | Integer)? timeout_seconds,
8
- Integer? memory_limit,
9
- Integer? stdout_limit,
10
- Integer? stderr_limit,
11
- Symbol profile,
12
- Symbol gvl
9
+ timeout: (Float | Integer)?,
10
+ setup_timeout: (Float | Integer)?,
11
+ memory_limit: Integer?,
12
+ stdout_limit: Integer?,
13
+ stderr_limit: Integer?,
14
+ open_file_limit: Integer?,
15
+ profile: Symbol,
16
+ gvl: Symbol
13
17
  ) -> Runtime
14
18
 
15
- def eval: (
16
- Kobako::Transport::dispatch_proc dispatch,
17
- Array[String] paths,
18
- String source,
19
- Array[Kobako::Catalog::Snippets::tuple] snippets
20
- ) -> Kobako::Runtime::Snapshot
19
+ type setup = [
20
+ Array[String],
21
+ Array[Kobako::Catalog::Snippets::tuple],
22
+ Array[Kobako::Catalog::Flags::tuple],
23
+ Array[Kobako::Catalog::Mount::tuple]
24
+ ]
25
+
26
+ def eval: (Kobako::Transport::dispatch_proc dispatch, setup setup, String source) -> Kobako::Snapshot
21
27
 
22
28
  def run: (
23
29
  Kobako::Transport::dispatch_proc dispatch,
24
- Array[String] paths,
25
- Array[Kobako::Catalog::Snippets::tuple] snippets,
30
+ setup setup,
26
31
  String entrypoint,
27
32
  String payload
28
- ) -> Kobako::Runtime::Snapshot
33
+ ) -> Kobako::Snapshot
29
34
 
30
35
  def profile: () -> Symbol
31
36
 
32
- # Frame-scoped guest re-entry handle the ext hands the dispatch Proc as
33
- # its last argument — the production conformer of
34
- # +Kobako::Transport::_GuestYielder+, answering the Yield Reply already
35
- # split off the core envelope.
36
- class GuestYielder
37
- def call: (String args_bytes) -> [Symbol, String, String?]
38
- end
39
-
40
- # One invocation's result — the whole Snapshot the driver produced.
41
- class Snapshot
42
- def outcome: () -> [Symbol, String, Kobako::Outcome::panic_fields?]
43
-
44
- def trapped?: () -> bool
45
-
46
- def trap_kind: () -> Symbol?
47
-
48
- def trap_message: () -> String?
49
-
50
- def wall_time: () -> Float
51
-
52
- def memory_peak: () -> Integer
53
-
54
- def stdout: () -> String
55
-
56
- def stdout_truncated?: () -> bool
57
-
58
- def stderr: () -> String
59
-
60
- def stderr_truncated?: () -> bool
61
- end
37
+ def compile: (Kobako::Context::preamble preamble) -> Array[String]?
62
38
  end
63
39
  end
@@ -7,14 +7,16 @@ module Kobako
7
7
 
8
8
  # Forwarded to @options via Forwardable#def_delegators.
9
9
  def timeout: () -> Float?
10
+ def setup_timeout: () -> Float?
10
11
  def memory_limit: () -> Integer?
11
12
  def stdout_limit: () -> Integer?
12
13
  def stderr_limit: () -> Integer?
14
+ def open_file_limit: () -> Integer?
13
15
  def profile: () -> Symbol
14
16
  def gvl: () -> Symbol
15
17
 
16
18
  # Every keyword beyond wasm_path forwards verbatim to
17
- # SandboxOptions.new (the four caps + the profile floor).
19
+ # SandboxOptions.new (the caps + the profile floor).
18
20
  def initialize: (
19
21
  ?wasm_path: String?,
20
22
  **untyped options
@@ -24,9 +26,13 @@ module Kobako
24
26
 
25
27
  def install: (*untyped extensions) -> Kobako::Sandbox
26
28
 
29
+ def mount: (String at, Kobako::Filesystem::mountable filesystem, ?access: Kobako::Filesystem::access) ?{ (String path, Kobako::Filesystem::access access) -> boolish } -> Kobako::Sandbox
30
+
27
31
  def preload: (code: String, name: Symbol | String) -> Kobako::Sandbox
28
32
  | (binary: String) -> Kobako::Sandbox
29
33
 
34
+ def flag: (Symbol | String name, ?String value, ?advisory: bool) -> Kobako::Sandbox
35
+
30
36
  def run: (Symbol | String target, *untyped args, **untyped kwargs) ?{ (Kobako::Context) -> void } -> Kobako::Execution
31
37
 
32
38
  def eval: (String code) ?{ (Kobako::Context) -> void } -> Kobako::Execution
@@ -37,6 +43,10 @@ module Kobako
37
43
 
38
44
  def new_invocation: () -> Kobako::Context
39
45
 
46
+ def preamble: (Array[Kobako::Catalog::Snippets::tuple] snippets) -> Kobako::Context::preamble
47
+
48
+ def refuse_once_invoked!: (String verb) -> void
49
+
40
50
  def begin_invocation!: () -> void
41
51
  end
42
52
  end
@@ -1,50 +1,68 @@
1
1
  module Kobako
2
2
  class SandboxOptions < Data
3
3
  DEFAULT_TIMEOUT_SECONDS: Float
4
+ DEFAULT_SETUP_TIMEOUT_SECONDS: Float
4
5
  DEFAULT_MEMORY_LIMIT: Integer
5
6
  DEFAULT_OUTPUT_LIMIT: Integer
7
+ DEFAULT_OPEN_FILE_LIMIT: Integer
6
8
  DEFAULT_PROFILE: Symbol
7
9
  PROFILES: Array[Symbol]
8
10
  GVL_MODES: Array[Symbol]
9
11
  DEFAULT_GVL: Symbol
12
+ VALUE_BYTES: Integer
10
13
 
11
14
  attr_reader timeout: Float?
15
+ attr_reader setup_timeout: Float?
12
16
  attr_reader memory_limit: Integer?
13
17
  attr_reader stdout_limit: Integer?
14
18
  attr_reader stderr_limit: Integer?
19
+ attr_reader open_file_limit: Integer?
15
20
  attr_reader profile: Symbol
16
21
  attr_reader gvl: Symbol
17
22
 
18
23
  def self.new: (
19
24
  ?timeout: (Float | Integer)?,
25
+ ?setup_timeout: (Float | Integer)?,
20
26
  ?memory_limit: Integer?,
21
27
  ?stdout_limit: Integer?,
22
28
  ?stderr_limit: Integer?,
29
+ ?open_file_limit: Integer?,
23
30
  ?profile: Symbol,
24
31
  ?gvl: Symbol
25
32
  ) -> SandboxOptions
26
33
 
27
34
  def initialize: (
28
35
  ?timeout: (Float | Integer)?,
36
+ ?setup_timeout: (Float | Integer)?,
29
37
  ?memory_limit: Integer?,
30
38
  ?stdout_limit: Integer?,
31
39
  ?stderr_limit: Integer?,
40
+ ?open_file_limit: Integer?,
32
41
  ?profile: Symbol,
33
42
  ?gvl: Symbol
34
43
  ) -> void
35
44
 
36
- def enforce_floor!: (Symbol declared) -> void
45
+ def to_h: () -> {
46
+ timeout: Float?,
47
+ setup_timeout: Float?,
48
+ memory_limit: Integer?,
49
+ stdout_limit: Integer?,
50
+ stderr_limit: Integer?,
51
+ open_file_limit: Integer?,
52
+ profile: Symbol,
53
+ gvl: Symbol
54
+ }
37
55
 
38
- private
56
+ def value_budget: () -> Integer?
39
57
 
40
- def normalize_timeout: ((Float | Integer)? timeout) -> Float?
58
+ def enforce_floor!: (Symbol declared) -> void
41
59
 
42
- def normalize_memory_limit: (Integer? memory_limit) -> Integer?
60
+ private
43
61
 
44
- def normalize_output_limit: (Integer? limit, String name) -> Integer?
62
+ def normalize_timeout: ((Float | Integer)? timeout, String name) -> Float?
45
63
 
46
- def normalize_profile: (untyped profile) -> Symbol
64
+ def normalize_limit: (Integer? limit, String name) -> Integer?
47
65
 
48
- def normalize_gvl: (untyped gvl) -> Symbol
66
+ def normalize_choice: (untyped value, Array[Symbol] choices, String name) -> Symbol
49
67
  end
50
68
  end