microsandbox-rb 0.7.0 → 0.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 158469a5ebe84ee4863c2a141cbeb486407bfc5ee05866be9005f9aee3bd249d
4
- data.tar.gz: ef08b6519ac87f66c20f704e4c55590f56b3d6c05fa01ab6f9187db46f8b43af
3
+ metadata.gz: f8cc1edaf4e221fe6e4addf4eea0d06e63370dd73bbcb1a7eb4d13e91bac7b40
4
+ data.tar.gz: 17f18d5aefead5fbb584a7b06ecd82d0aade2394c3e9c48aafd0f5d98673abfd
5
5
  SHA512:
6
- metadata.gz: d63ed9d45bdf68fb2f8352927412b23debd45e5e011f30a835fd2e75bae206e2ce19d1875c6099ce72c808c7d5e05e62a459f81794589e090ab837b9541d5da7
7
- data.tar.gz: '09a726c22f8b12ecb0d575f0c4e20ce446aa5761cf5ed8cc15155a6b567e7ee867c4f95545a9595f786b88ec2f6dbd75b1bfe721fb629025ce8bfc19aa63fda0'
6
+ metadata.gz: e7c98769be2508875e54b1449d290c18b63af3189af497d311c6222073b6018290950faa4438c165f656928d175e6f6a50ec0f7af6323a8174dbf0e460b99042
7
+ data.tar.gz: 7a8edef36f6f7e3c12a5075e684d64ca71570350dd678ebcd3b819a9ebfab309007e2b71e348f1c0925ab8e3beb474787aeec741935f5e803676f5ce00daf513
data/CHANGELOG.md CHANGED
@@ -8,6 +8,80 @@ wraps, and the README's Versioning section keeps the full gem→runtime map.
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [0.8.1] - 2026-06-25
12
+
13
+ Gem-only release on the `v0.5.10` runtime (unchanged) — the two follow-ups to
14
+ `0.8.0`'s runtime adoption that review surfaced.
15
+
16
+ ### Added
17
+
18
+ - **Per-bind-mount guest-write quota override** (issue #19). An inline `volumes:`
19
+ bind mount now accepts a `quota_mib:` key to override the runtime's default
20
+ guest-write budget (4 GiB as of `v0.5.10`, documented in `0.8.0`), e.g.
21
+ `volumes: { "/out" => { bind: "/host/out", quota_mib: 16_384 } }`. The runtime
22
+ still applies the 4 GiB default when unset; there is no unbounded option, so
23
+ raise the value if a workload writes more. Valid on bind mounts only — the core
24
+ rejects it on tmpfs/disk/named mounts (set a named volume's quota via
25
+ `Volume.create(quota_mib:)`).
26
+
27
+ ### Fixed
28
+
29
+ - **Stale local runtime is now re-provisioned instead of boot-failing**
30
+ (issue #18). `Microsandbox.ensure_runtime!` short-circuited as soon as
31
+ `installed?` was true, but that check confirms only that the `msb`/`libkrunfw`
32
+ files *exist*, not that their version matches the runtime this gem build links.
33
+ An older `msb` left in `~/.microsandbox` by a previous gem version therefore
34
+ passed and then failed every `Sandbox.create` at boot on a host↔guest
35
+ wire-protocol mismatch (e.g. a `v0.5.8` `msb` rejecting the `--config-fd` flag
36
+ the `v0.5.10` runtime passes). `ensure_runtime!` now delegates to the
37
+ idempotent, version-correcting installer on first use even when the runtime is
38
+ present (a cheap `msb --version`; re-downloads only on absence/mismatch), so an
39
+ upgrade-over-stale-install self-heals. Source-gem installs were already
40
+ corrected at build time; this closes the gap for the precompiled-gem upgrade
41
+ path. `MICROSANDBOX_NO_AUTO_INSTALL` still fully opts out.
42
+
43
+ ## [0.8.0] - 2026-06-25
44
+
45
+ Adopts upstream runtime **`v0.5.10`** (up from the `v0.5.8` that `0.7.0` shipped).
46
+ Runtime-only bump — no public Ruby API change.
47
+
48
+ ### Runtime
49
+
50
+ - **Adopted upstream `v0.5.10`** — the `microsandbox`/`microsandbox-network` git
51
+ deps and `Microsandbox::RUNTIME_VERSION` now pin `v0.5.10`. This is the runtime
52
+ bump originally attempted against `v0.5.9` during the `0.7.0` cycle and reverted:
53
+ upstream's `v0.5.9` git tag predated its own crate-version bump, so the prebuilt
54
+ runtime-provisioning path (`PREBUILT_VERSION = env!("CARGO_PKG_VERSION")`)
55
+ resolved to `0.5.8` and downloaded a `msb` that rejected the new `--config-fd`
56
+ flag the SDK unconditionally passes — every `Sandbox.create` died at boot.
57
+ Upstream chose not to re-tag (most package registries forbid republishing a tag)
58
+ and instead cut a clean **`v0.5.10`** whose tag carries the matching crate
59
+ version `0.5.10` (upstream
60
+ [#1029](https://github.com/superradcompany/microsandbox/issues/1029)). The bump
61
+ carries the following upstream changes:
62
+ - **Heartbeat no longer reclaims busy sandboxes** (upstream #1011). The host
63
+ watchdog is now idle-detection only — a healthy sandbox with an active (or
64
+ briefly starved) `exec` session is never killed for a stale heartbeat, the
65
+ way it could be before.
66
+ - **Launch config moved off the process argv** (upstream #1006). Bulky and
67
+ secret-bearing config (the network blob, env) is handed to the sandbox over
68
+ an inherited, unlinked-tempfile fd instead of `--`-flags, so it no longer
69
+ leaks into `ps` / `/proc/<pid>/cmdline`.
70
+
71
+ ### Changed
72
+
73
+ - **Directory bind mounts now carry a default 4 GiB guest-write quota**
74
+ (upstream #1020). Any `volumes:` entry that binds a host directory (e.g.
75
+ `volumes: { "/out" => "/host/out" }`) is given a `DEFAULT_BIND_QUOTA_MIB`
76
+ (4096 MiB) guest-write budget by the v0.5.10 runtime when no explicit quota is
77
+ set, so a sandbox can no longer fill the host disk through a bind mount. This
78
+ is a **behavior change**: a workload that wrote more than 4 GiB to a bind mount
79
+ under the `v0.5.8` runtime (`0.7.0`) will now fail with `ENOSPC`. The gem does
80
+ not yet expose a per-bind quota override (named-volume `Volume.create` accepts
81
+ `quota_mib:`, but the inline bind-mount path does not) — that escape hatch is a
82
+ tracked follow-up. Until then, route large-write mounts through a named volume
83
+ with an explicit `quota_mib:`.
84
+
11
85
  ## [0.7.0] - 2026-06-23
12
86
 
13
87
  A large parity release closing the binding gaps an audit against the upstream
data/Cargo.lock CHANGED
@@ -3003,8 +3003,8 @@ dependencies = [
3003
3003
 
3004
3004
  [[package]]
3005
3005
  name = "microsandbox"
3006
- version = "0.5.8"
3007
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3006
+ version = "0.5.10"
3007
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3008
3008
  dependencies = [
3009
3009
  "anyhow",
3010
3010
  "astral-tokio-tar",
@@ -3056,8 +3056,8 @@ dependencies = [
3056
3056
 
3057
3057
  [[package]]
3058
3058
  name = "microsandbox-agent-client"
3059
- version = "0.5.8"
3060
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3059
+ version = "0.5.10"
3060
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3061
3061
  dependencies = [
3062
3062
  "ciborium",
3063
3063
  "microsandbox-protocol",
@@ -3069,8 +3069,8 @@ dependencies = [
3069
3069
 
3070
3070
  [[package]]
3071
3071
  name = "microsandbox-db"
3072
- version = "0.5.8"
3073
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3072
+ version = "0.5.10"
3073
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3074
3074
  dependencies = [
3075
3075
  "async-trait",
3076
3076
  "sea-orm",
@@ -3081,8 +3081,8 @@ dependencies = [
3081
3081
 
3082
3082
  [[package]]
3083
3083
  name = "microsandbox-filesystem"
3084
- version = "0.5.8"
3085
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3084
+ version = "0.5.10"
3085
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3086
3086
  dependencies = [
3087
3087
  "libc",
3088
3088
  "microsandbox-utils",
@@ -3094,8 +3094,8 @@ dependencies = [
3094
3094
 
3095
3095
  [[package]]
3096
3096
  name = "microsandbox-image"
3097
- version = "0.5.8"
3098
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3097
+ version = "0.5.10"
3098
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3099
3099
  dependencies = [
3100
3100
  "astral-tokio-tar",
3101
3101
  "async-compression",
@@ -3120,8 +3120,8 @@ dependencies = [
3120
3120
 
3121
3121
  [[package]]
3122
3122
  name = "microsandbox-metrics"
3123
- version = "0.5.8"
3124
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3123
+ version = "0.5.10"
3124
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3125
3125
  dependencies = [
3126
3126
  "chrono",
3127
3127
  "libc",
@@ -3131,8 +3131,8 @@ dependencies = [
3131
3131
 
3132
3132
  [[package]]
3133
3133
  name = "microsandbox-migration"
3134
- version = "0.5.8"
3135
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3134
+ version = "0.5.10"
3135
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3136
3136
  dependencies = [
3137
3137
  "sea-orm-migration",
3138
3138
  "serde_json",
@@ -3140,8 +3140,8 @@ dependencies = [
3140
3140
 
3141
3141
  [[package]]
3142
3142
  name = "microsandbox-network"
3143
- version = "0.5.8"
3144
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3143
+ version = "0.5.10"
3144
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3145
3145
  dependencies = [
3146
3146
  "base64",
3147
3147
  "bytes",
@@ -3180,8 +3180,8 @@ dependencies = [
3180
3180
 
3181
3181
  [[package]]
3182
3182
  name = "microsandbox-protocol"
3183
- version = "0.5.8"
3184
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3183
+ version = "0.5.10"
3184
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3185
3185
  dependencies = [
3186
3186
  "chrono",
3187
3187
  "ciborium",
@@ -3195,8 +3195,8 @@ dependencies = [
3195
3195
 
3196
3196
  [[package]]
3197
3197
  name = "microsandbox-runtime"
3198
- version = "0.5.8"
3199
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3198
+ version = "0.5.10"
3199
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3200
3200
  dependencies = [
3201
3201
  "bytes",
3202
3202
  "chrono",
@@ -3225,8 +3225,8 @@ dependencies = [
3225
3225
 
3226
3226
  [[package]]
3227
3227
  name = "microsandbox-types"
3228
- version = "0.5.8"
3229
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3228
+ version = "0.5.10"
3229
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3230
3230
  dependencies = [
3231
3231
  "chrono",
3232
3232
  "serde",
@@ -3237,8 +3237,8 @@ dependencies = [
3237
3237
 
3238
3238
  [[package]]
3239
3239
  name = "microsandbox-utils"
3240
- version = "0.5.8"
3241
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3240
+ version = "0.5.10"
3241
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.10#a62c4e45da7320e89aafc44b8a44fc74ec49fb53"
3242
3242
  dependencies = [
3243
3243
  "dirs",
3244
3244
  "libc",
@@ -3249,7 +3249,7 @@ dependencies = [
3249
3249
 
3250
3250
  [[package]]
3251
3251
  name = "microsandbox_rb"
3252
- version = "0.7.0"
3252
+ version = "0.8.1"
3253
3253
  dependencies = [
3254
3254
  "chrono",
3255
3255
  "futures",
data/README.md CHANGED
@@ -383,8 +383,8 @@ change diverged the two numbers — the gem version is **not** a reliable indica
383
383
  of the embedded runtime version. To learn which runtime a build wraps, ask it:
384
384
 
385
385
  ```ruby
386
- Microsandbox::VERSION # => "0.6.0" (the gem's own version)
387
- Microsandbox.runtime_version # => "v0.5.8" (the embedded upstream runtime tag)
386
+ Microsandbox::VERSION # => "0.8.0" (the gem's own version)
387
+ Microsandbox.runtime_version # => "v0.5.10" (the embedded upstream runtime tag)
388
388
  ```
389
389
 
390
390
  | Gem version | Upstream runtime | Notes |
@@ -396,6 +396,9 @@ Microsandbox.runtime_version # => "v0.5.8" (the embedded upstream runtime tag
396
396
  | `0.5.11` | `v0.5.8` | gem-only revision |
397
397
  | `0.5.12` | `v0.5.8` | gem-only revision |
398
398
  | `0.6.0` | `v0.5.8` | gem version decoupled from the upstream tag; adds `runtime_version` |
399
+ | `0.7.0` | `v0.5.8` | SDK parity release (large binding-gap closure) |
400
+ | `0.8.0` | `v0.5.10` | adopts upstream `v0.5.10` (idle-only heartbeat, config-fd hardening, **4 GiB default bind-mount quota**); supersedes the reverted `v0.5.9` attempt |
401
+ | `0.8.1` | `v0.5.10` | gem-only: re-provision a stale local runtime; per-bind-mount `quota_mib:` override |
399
402
 
400
403
  **Going forward** — the gem version moves on its own semver track and no longer
401
404
  mirrors the upstream tag:
@@ -6,8 +6,8 @@ name = "microsandbox_rb"
6
6
  description = "Ruby SDK native extension for microsandbox — secure, fast microVM-based sandboxing."
7
7
  # Must equal Microsandbox::VERSION (lib/microsandbox/version.rb) — Native.version
8
8
  # returns this via env!("CARGO_PKG_VERSION") and version_spec.rb asserts equality.
9
- # The core-crate dependency below stays pinned at its own tag (v0.5.8).
10
- version = "0.7.0"
9
+ # The core-crate dependency below stays pinned at its own tag (v0.5.10).
10
+ version = "0.8.1"
11
11
  authors = ["Super Rad Company <development@superrad.company>"]
12
12
  repository = "https://github.com/superradcompany/microsandbox"
13
13
  license = "Apache-2.0"
@@ -35,8 +35,8 @@ rb-sys = "0.9"
35
35
  # `.cargo/config.toml.example`). "ssh" matches the feature set the Python/Node
36
36
  # SDKs ship with; default features add "prebuilt" (provisions msb + libkrunfw at
37
37
  # build time), "net", and "keyring".
38
- microsandbox = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.8", default-features = true, features = ["ssh"] }
39
- microsandbox-network = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.8" }
38
+ microsandbox = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.10", default-features = true, features = ["ssh"] }
39
+ microsandbox-network = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.10" }
40
40
 
41
41
  # Async core bridged to Ruby's synchronous API via a blocking tokio runtime.
42
42
  tokio = { version = "1", features = ["rt-multi-thread", "sync", "time"] }
@@ -122,6 +122,10 @@ impl Sandbox {
122
122
  .ok_or_else(|| error::base_error("volume mount is missing :kind"))?;
123
123
  let source = conv::opt_string(m, "source")?;
124
124
  let size_mib = conv::opt_u32(m, "size_mib")?;
125
+ // Bind-mount guest-write quota override (MiB). The core's MountBuilder
126
+ // applies it to bind mounts only and rejects it on tmpfs/disk/named at
127
+ // build(); we forward it as-is so that validation lives in one place.
128
+ let quota_mib = conv::opt_u32(m, "quota_mib")?;
125
129
  let fstype = conv::opt_string(m, "fstype")?;
126
130
  let readonly = conv::opt_bool(m, "readonly")?;
127
131
  let noexec = conv::opt_bool(m, "noexec")?;
@@ -161,6 +165,9 @@ impl Sandbox {
161
165
  if let Some(n) = size_mib {
162
166
  mb = mb.size(n);
163
167
  }
168
+ if let Some(q) = quota_mib {
169
+ mb = mb.quota(q);
170
+ }
164
171
  if let Some(f) = format {
165
172
  mb = mb.format(f);
166
173
  }
@@ -230,7 +230,10 @@ module Microsandbox
230
230
  # `{ disk: "/img.raw", format: "raw", fstype: "ext4" }`. Any mount may add
231
231
  # flags `ro:`/`readonly:`, `noexec:`, `nosuid:`, `nodev:`, and (bind/named
232
232
  # only) `stat_virtualization:` (:strict/:relaxed/:off) and
233
- # `host_permissions:` (:private/:mirror).
233
+ # `host_permissions:` (:private/:mirror). A bind mount accepts
234
+ # `quota_mib:` to override the runtime's default guest-write budget
235
+ # (4 GiB as of `v0.5.10`); the core rejects it on tmpfs/disk/named (for a
236
+ # named volume, set its quota via {Volume.create}).
234
237
  # @param network [String, Symbol, NetworkPolicy, Hash, nil] network policy.
235
238
  # A preset name ("public_only" (default), "none", "allow_all",
236
239
  # "non_local"), a {NetworkPolicy} (e.g. {NetworkPolicy.custom}), or a Hash
@@ -677,11 +680,12 @@ module Microsandbox
677
680
  # Hashes for the native layer. A spec is a host path String (a read-write
678
681
  # bind mount) or a Hash describing the mount:
679
682
  # { bind: "/host", ro: true, noexec: true } # host bind mount
683
+ # { bind: "/host", quota_mib: 16_384 } # raise the 4 GiB cap
680
684
  # { named: "vol" } # named volume
681
685
  # { tmpfs: true, size_mib: 64 } # memory-backed
682
686
  # { disk: "/img.raw", format: "raw", fstype: "ext4" } # disk-image mount
683
687
  # Any mount may also carry stat_virtualization: (:strict/:relaxed/:off) and
684
- # host_permissions: (:private/:mirror).
688
+ # host_permissions: (:private/:mirror); a bind mount may carry quota_mib:.
685
689
  def normalize_volumes(volumes)
686
690
  volumes.map do |guest, spec|
687
691
  mount = {"guest" => guest.to_s}
@@ -722,6 +726,12 @@ module Microsandbox
722
726
  mount["size_mib"] = Integer(size) if size
723
727
  fstype = spec[:fstype] || spec["fstype"]
724
728
  mount["fstype"] = fstype.to_s if fstype
729
+ # Bind-mount guest-write quota (MiB). Overrides the runtime's default
730
+ # budget (4 GiB as of v0.5.10); the core applies it only to bind mounts
731
+ # and rejects it on tmpfs/disk/named. `0` is forwarded as-is (a zero
732
+ # budget), not treated as "unset".
733
+ quota = spec[:quota_mib] || spec["quota_mib"]
734
+ mount["quota_mib"] = Integer(quota) if quota
725
735
  end
726
736
 
727
737
  # Apply a volume spec Hash's mount flags. `ro:`/`readonly:` makes the mount
@@ -8,12 +8,12 @@ module Microsandbox
8
8
  # Versioning section of the README for the full gem-to-runtime map. Must equal
9
9
  # the native ext's Cargo crate version (`Native.version`), enforced by
10
10
  # spec/unit/version_spec.rb.
11
- VERSION = "0.7.0"
11
+ VERSION = "0.8.1"
12
12
 
13
13
  # The upstream microsandbox runtime release this gem build embeds — the `tag`
14
14
  # pinned on the `microsandbox`/`microsandbox-network` git deps in
15
15
  # ext/microsandbox/Cargo.toml. Exposed at runtime as
16
16
  # {Microsandbox.runtime_version}. spec/unit/version_spec.rb asserts it stays in
17
17
  # sync with the Cargo tag so it can't silently drift out of date.
18
- RUNTIME_VERSION = "v0.5.8"
18
+ RUNTIME_VERSION = "v0.5.10"
19
19
  end
data/lib/microsandbox.rb CHANGED
@@ -93,16 +93,27 @@ module Microsandbox
93
93
  Native.installed?
94
94
  end
95
95
 
96
- # Ensure the `msb` runtime + `libkrunfw` are present, provisioning them on
97
- # first use if not. Called automatically by {Sandbox.create}/{Sandbox.start}
98
- # so precompiled-gem users (who never ran the source build) get a working
99
- # runtime without a manual {install} step.
96
+ # Ensure the `msb` runtime + `libkrunfw` are present *and version-matched*,
97
+ # provisioning them on first use if not. Called automatically by
98
+ # {Sandbox.create}/{Sandbox.start} so precompiled-gem users (who never ran the
99
+ # source build) get a working runtime without a manual {install} step.
100
100
  #
101
- # The download is attempted at most once per process. Opt out by setting
101
+ # Runs at most once per process. Opt out by setting
102
102
  # `MICROSANDBOX_NO_AUTO_INSTALL` (e.g. air-gapped hosts that provision the
103
- # runtime out of band); the subsequent operation then surfaces the missing
104
- # runtime itself. Already-installed runtimes (e.g. source builds) skip
105
- # straight through with only a cheap presence check.
103
+ # runtime out of band); the runtime is then left untouched and a missing or
104
+ # stale one surfaces at the operation itself.
105
+ #
106
+ # NOTE: this delegates to {install} even when {installed?} is already true,
107
+ # rather than short-circuiting on presence. {installed?} (upstream
108
+ # `verify_installation`) only confirms the `msb`/`libkrunfw` files *exist*, not
109
+ # that their version matches the runtime this gem build links. {install} is
110
+ # idempotent and *version-correcting*: it runs a cheap `msb --version` and
111
+ # re-downloads ONLY when the binary is absent or its version differs, then
112
+ # no-ops. A presence-only short-circuit would let a stale `msb` left in
113
+ # `~/.microsandbox` by an older gem pass, then fail every {Sandbox.create} on a
114
+ # host↔guest wire-protocol mismatch (e.g. a `v0.5.8` `msb` rejecting the
115
+ # `--config-fd` flag the `v0.5.10` runtime passes). Keep the {install} call on
116
+ # this path — do not "optimize" it back to skip-when-present.
106
117
  # @return [nil]
107
118
  def ensure_runtime!
108
119
  return if @runtime_ready
@@ -111,14 +122,18 @@ module Microsandbox
111
122
  # uses the same lazy env/profile/config ladder every operation already
112
123
  # consults, so this adds no work for local hosts (the common case).
113
124
  return if default_backend_kind == :cloud
114
- if installed?
125
+ # Opted out: the caller manages the runtime out of band, so don't fetch,
126
+ # verify, or repair it here. Memoize the decision (the env var is stable for
127
+ # the process); the operation resolves `msb` itself and surfaces any problem.
128
+ if auto_install_disabled?
115
129
  @runtime_ready = true
116
130
  return
117
131
  end
118
- return if auto_install_disabled?
119
132
 
120
- warn "[microsandbox] runtime (msb + libkrunfw) not found; " \
121
- "downloading to ~/.microsandbox (set MICROSANDBOX_NO_AUTO_INSTALL to skip)..."
133
+ unless installed?
134
+ warn "[microsandbox] runtime (msb + libkrunfw) not found; " \
135
+ "downloading to ~/.microsandbox (set MICROSANDBOX_NO_AUTO_INSTALL to skip)..."
136
+ end
122
137
  install
123
138
  @runtime_ready = true
124
139
  nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: microsandbox-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ya-luotao