microsandbox-rb 0.15.0 → 0.16.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 241dfe5d94b8c98d3c790994698b004a591d66229d9965799fc5886b01e5a19d
4
- data.tar.gz: a134b4cbb4b58a60d72d6a7ace30ab6333da4057d0868c1a6e351396b7ff4d00
3
+ metadata.gz: 011c5bcfdd4eff6b2f86ec6ded70720520b5c77d93ceb575dc4ac9b0ce0a5078
4
+ data.tar.gz: 2e84a073bd4852e2cdbc124f4ce6b400beb5b20012c6b9ff81833169f13d58e1
5
5
  SHA512:
6
- metadata.gz: c326c0481781ae1f3fc19994dfd8e4c004c4bdc8aa81b33e67386538f4fa9ff58cb84514955079c39daa09817c8eba65ac7d4ebe91ab34698ac5fce8cfa9c574
7
- data.tar.gz: 1d93018f5982d2767cd66e29c50a195a3d138d7f60f93a2a3e6020384f41ce843e3a0b85d5152a2d17995a724ed9cc6169e72c0bcfc506017e7ae84b3acbe73f
6
+ metadata.gz: 6a12d8b308f479630dc8b266c3129bb7e337939da1963faf975fda7ebb890fe95d50ccbf77b37e9f33d3ccb0506dd94633e0374ac6c52cac599c6c80348ee931
7
+ data.tar.gz: 730a26aef15b87d348e95a23ede127520aee10d410856526f956d3366118959dc51f60d418e7c876781191be0c72009daafaa442a353afc6b6010643adf1a46f
data/CHANGELOG.md CHANGED
@@ -6,6 +6,105 @@ All notable changes to this gem are documented here. The format is based on
6
6
  microsandbox runtime it embeds; each release notes the upstream runtime tag it
7
7
  wraps, and the README's Versioning section keeps the full gem→runtime map.
8
8
 
9
+ ## [0.16.0] - 2026-09-01
10
+
11
+ Adopts upstream runtime **`v0.6.14` → `v0.6.16`**, stepping through the
12
+ intermediate tag (`v0.6.15` verified and committed on its own).
13
+
14
+ ### Added
15
+
16
+ - Per-mount fallback ownership: a bind or named mount in `volumes:` accepts
17
+ `uid:`/`gid:`, pinning the guest owner presented for host files that carry no
18
+ per-file stat override (upstream #1451, `v0.6.15`). They travel on the wire as
19
+ the core's `override_uid`/`override_gid` and mirror the Python SDK's public
20
+ `uid:`/`gid:` spelling. Validation matches the Python SDK: the pair must be
21
+ given together, each must be a plain `Integer` in `0..4294967295` (strings,
22
+ Floats and Booleans are rejected rather than coerced — a truncated or parsed
23
+ owner ID is never what the caller meant), and they conflict with both
24
+ `stat_virtualization: :off` (no overlay to rewrite the owner in) and
25
+ tmpfs/disk mounts. The one Python rule with no Ruby counterpart is
26
+ "unsupported for disk-backed named volumes": a Ruby `{ named: "vol" }` spec
27
+ only references an existing volume by name, so the volume's kind is known
28
+ only to the core, which rejects that combination at create time.
29
+ - **Convergent lifecycle APIs** (upstream #1462, `v0.6.16`) — idempotent
30
+ operations that take a name to the state you want, whatever state it is in
31
+ now:
32
+ - `Sandbox.connect_or_create(name, **kwargs)` — connect to (and start) the
33
+ persisted sandbox with this name, or create it when none exists; concurrent
34
+ callers converge on the winning identity instead of one losing to a name
35
+ clash. Takes exactly `create`'s keyword options — the same normalization
36
+ path, not a second copy of it — and they apply only when a create actually
37
+ happens. The block form yields the sandbox and then stops it **only when the
38
+ call owns its lifecycle** — a deliberate divergence from `create`, whose
39
+ block form always stops: `connect_or_create` can hand back a sandbox this
40
+ process did not start, and tearing down someone else's long-lived service on
41
+ the way out of a block is never what the caller meant. So a sandbox created
42
+ here is stopped as usual; one merely *connected* to, or started with
43
+ `detached: true`, is left running. `replace:` / `replace_with_timeout:` are
44
+ accepted for kwargs parity but rejected by the core with
45
+ `InvalidConfigError`: replacing a sandbox is the opposite of converging
46
+ on it.
47
+ - `Sandbox#id` and `SandboxHandle#id` — the opaque, backend-assigned identity
48
+ of the *persisted* sandbox. Names are reusable labels; this changes when a
49
+ name is removed and recreated.
50
+ - `Sandbox#wait_for_status(status)` and `SandboxHandle#wait_for_status(status)`
51
+ — block until this exact sandbox reaches one of `:created`, `:starting`,
52
+ `:running`, `:draining`, `:paused`, `:stopped`, `:crashed`, returning a fresh
53
+ `SandboxHandle` (from both receivers, mirroring the official SDKs). There is
54
+ no built-in timeout and the wait is uninterruptible from Ruby (the native
55
+ call releases the GVL with no unblock function), so an unknown status name
56
+ raises `ArgumentError` up front rather than blocking forever — and only
57
+ states the active backend can reach are worth waiting for (`:created` and
58
+ `:paused` are cloud-side). Impose a deadline by running the call on its own
59
+ Thread.
60
+ - `Sandbox#restart(force:, timeout:, detached:)` and
61
+ `SandboxHandle#restart(...)` — stop and start this exact sandbox, returning a
62
+ new live `Sandbox`.
63
+ - `Sandbox#destroy(force:, timeout:)` and `SandboxHandle#destroy(...)` — stop
64
+ and remove this exact sandbox in one step.
65
+ - `SandboxHandle#connect_or_start(detached:)` — connect when the sandbox is
66
+ running, wait while it is starting, start it when it is created/stopped/
67
+ crashed.
68
+ - `Microsandbox::SandboxReplacedError` (code `"sandbox-replaced"`) — raised by
69
+ every one of the identity-checked operations above when the name now refers to
70
+ a different persisted sandbox, instead of quietly acting on the replacement.
71
+ Mirrors the Python SDK's `SandboxReplacedError`; wired into the native
72
+ error-code mapping like the other `sandbox-*` codes.
73
+
74
+ ### Fixed
75
+
76
+ - **The live `Sandbox#stop` no longer stops a same-name replacement.** The
77
+ binding re-fetched a `SandboxHandle` *by name* and stopped that — a pattern
78
+ left over from before the core's live `stop` was identity-scoped. As of
79
+ runtime v0.6.16 the core routes `stop` → `request_stop` →
80
+ `stop_identified(name, self.identity())`, so the fix is to route through the
81
+ live sandbox (`self.inner.stop()`) the way `kill`/`drain`/`wait`/
82
+ `stop_and_wait` already did, and the way both official bindings do. A sandbox
83
+ removed and recreated under the same name now raises `SandboxReplacedError`
84
+ (or `SandboxNotFoundError` when nothing holds the name) instead of terminating
85
+ whoever answers to it. This also hardens `Sandbox.connect_or_create`'s block
86
+ form, whose teardown calls `#stop`.
87
+ - **Operations that can boot a microVM now provision the runtime first.**
88
+ `SandboxHandle#connect_or_start`, `SandboxHandle#restart` and
89
+ `Sandbox#restart` were missing the `ensure_runtime!` call `Sandbox.create` and
90
+ `Sandbox.start` make, so on a machine with no runtime installed they failed in
91
+ the native layer instead of fetching it. (`Sandbox.connect_or_create` was
92
+ already covered — it shares `create`'s option builder.)
93
+
94
+ ### Changed
95
+
96
+ - Upstream runtime highlights carried without further Ruby surface:
97
+ - `v0.6.15` — read-only mounts no longer fail a write probe at mount time,
98
+ Windows DNS/NTFS handling, and the mount-ownership core work above.
99
+ - `v0.6.16` — log retrieval rerouted through the SDK backends (#1459; the
100
+ `logs`/`log_stream` bindings are unchanged and keep their behaviour — the
101
+ new `follow_logs`/`boot_error` core entry points are not bound, matching the
102
+ Python binding), sandbox config overlaid by field presence with
103
+ `LocalConfig` renamed to `GlobalConfig` (#1460; the gem touches neither —
104
+ the ext only calls `config::set_sdk_*_path` — and no Ruby config
105
+ round-trip or `modify` semantics changed), network-slot recycling and
106
+ migration, single-file mount isolation, empty `MSB_HOME` treated as unset.
107
+
9
108
  ## [0.15.0] - 2026-08-24
10
109
 
11
110
  Adopts upstream runtime **`v0.6.9` → `v0.6.14`**, stepping through every
data/Cargo.lock CHANGED
@@ -153,7 +153,7 @@ version = "1.1.5"
153
153
  source = "registry+https://github.com/rust-lang/crates.io-index"
154
154
  checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
155
155
  dependencies = [
156
- "windows-sys 0.60.2",
156
+ "windows-sys 0.61.2",
157
157
  ]
158
158
 
159
159
  [[package]]
@@ -164,7 +164,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
164
164
  dependencies = [
165
165
  "anstyle",
166
166
  "once_cell_polyfill",
167
- "windows-sys 0.60.2",
167
+ "windows-sys 0.61.2",
168
168
  ]
169
169
 
170
170
  [[package]]
@@ -889,7 +889,7 @@ dependencies = [
889
889
  "maybe-owned",
890
890
  "rustix",
891
891
  "rustix-linux-procfs",
892
- "windows-sys 0.60.2",
892
+ "windows-sys 0.61.2",
893
893
  "winx",
894
894
  ]
895
895
 
@@ -1759,7 +1759,7 @@ dependencies = [
1759
1759
  "libc",
1760
1760
  "option-ext",
1761
1761
  "redox_users",
1762
- "windows-sys 0.60.2",
1762
+ "windows-sys 0.61.2",
1763
1763
  ]
1764
1764
 
1765
1765
  [[package]]
@@ -1938,7 +1938,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1938
1938
  checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
1939
1939
  dependencies = [
1940
1940
  "libc",
1941
- "windows-sys 0.52.0",
1941
+ "windows-sys 0.61.2",
1942
1942
  ]
1943
1943
 
1944
1944
  [[package]]
@@ -2067,7 +2067,7 @@ checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a"
2067
2067
  dependencies = [
2068
2068
  "io-lifetimes 2.0.4",
2069
2069
  "rustix",
2070
- "windows-sys 0.52.0",
2070
+ "windows-sys 0.59.0",
2071
2071
  ]
2072
2072
 
2073
2073
  [[package]]
@@ -2886,7 +2886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2886
2886
  checksum = "20fd6de4ccfcc187e38bc21cfa543cb5a302cb86a8b114eb7f0bf0dc9f8ac00f"
2887
2887
  dependencies = [
2888
2888
  "io-lifetimes 3.0.1",
2889
- "windows-sys 0.52.0",
2889
+ "windows-sys 0.60.2",
2890
2890
  ]
2891
2891
 
2892
2892
  [[package]]
@@ -3392,8 +3392,8 @@ dependencies = [
3392
3392
 
3393
3393
  [[package]]
3394
3394
  name = "microsandbox"
3395
- version = "0.6.14"
3396
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3395
+ version = "0.6.16"
3396
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3397
3397
  dependencies = [
3398
3398
  "anyhow",
3399
3399
  "astral-tokio-tar",
@@ -3454,8 +3454,8 @@ dependencies = [
3454
3454
 
3455
3455
  [[package]]
3456
3456
  name = "microsandbox-agent-client"
3457
- version = "0.6.14"
3458
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3457
+ version = "0.6.16"
3458
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3459
3459
  dependencies = [
3460
3460
  "ciborium",
3461
3461
  "microsandbox-protocol",
@@ -3467,8 +3467,8 @@ dependencies = [
3467
3467
 
3468
3468
  [[package]]
3469
3469
  name = "microsandbox-db"
3470
- version = "0.6.14"
3471
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3470
+ version = "0.6.16"
3471
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3472
3472
  dependencies = [
3473
3473
  "async-trait",
3474
3474
  "sea-orm",
@@ -3479,8 +3479,8 @@ dependencies = [
3479
3479
 
3480
3480
  [[package]]
3481
3481
  name = "microsandbox-filesystem"
3482
- version = "0.6.14"
3483
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3482
+ version = "0.6.16"
3483
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3484
3484
  dependencies = [
3485
3485
  "libc",
3486
3486
  "microsandbox-utils",
@@ -3488,12 +3488,13 @@ dependencies = [
3488
3488
  "scopeguard",
3489
3489
  "tempfile",
3490
3490
  "tracing",
3491
+ "windows-sys 0.61.2",
3491
3492
  ]
3492
3493
 
3493
3494
  [[package]]
3494
3495
  name = "microsandbox-image"
3495
- version = "0.6.14"
3496
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3496
+ version = "0.6.16"
3497
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3497
3498
  dependencies = [
3498
3499
  "astral-tokio-tar",
3499
3500
  "async-compression",
@@ -3519,8 +3520,8 @@ dependencies = [
3519
3520
 
3520
3521
  [[package]]
3521
3522
  name = "microsandbox-metrics"
3522
- version = "0.6.14"
3523
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3523
+ version = "0.6.16"
3524
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3524
3525
  dependencies = [
3525
3526
  "chrono",
3526
3527
  "libc",
@@ -3531,8 +3532,8 @@ dependencies = [
3531
3532
 
3532
3533
  [[package]]
3533
3534
  name = "microsandbox-migration"
3534
- version = "0.6.14"
3535
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3535
+ version = "0.6.16"
3536
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3536
3537
  dependencies = [
3537
3538
  "sea-orm-migration",
3538
3539
  "serde_json",
@@ -3540,8 +3541,8 @@ dependencies = [
3540
3541
 
3541
3542
  [[package]]
3542
3543
  name = "microsandbox-network"
3543
- version = "0.6.14"
3544
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3544
+ version = "0.6.16"
3545
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3545
3546
  dependencies = [
3546
3547
  "base64 0.22.1",
3547
3548
  "bytes",
@@ -3584,8 +3585,8 @@ dependencies = [
3584
3585
 
3585
3586
  [[package]]
3586
3587
  name = "microsandbox-protocol"
3587
- version = "0.6.14"
3588
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3588
+ version = "0.6.16"
3589
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3589
3590
  dependencies = [
3590
3591
  "chrono",
3591
3592
  "ciborium",
@@ -3599,8 +3600,8 @@ dependencies = [
3599
3600
 
3600
3601
  [[package]]
3601
3602
  name = "microsandbox-runtime"
3602
- version = "0.6.14"
3603
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3603
+ version = "0.6.16"
3604
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3604
3605
  dependencies = [
3605
3606
  "bytes",
3606
3607
  "chrono",
@@ -3634,11 +3635,12 @@ dependencies = [
3634
3635
 
3635
3636
  [[package]]
3636
3637
  name = "microsandbox-types"
3637
- version = "0.6.14"
3638
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3638
+ version = "0.6.16"
3639
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3639
3640
  dependencies = [
3640
3641
  "chrono",
3641
3642
  "ipnetwork",
3643
+ "microsandbox-types-macros",
3642
3644
  "serde",
3643
3645
  "serde_json",
3644
3646
  "sha2 0.11.0",
@@ -3647,10 +3649,20 @@ dependencies = [
3647
3649
  "zeroize",
3648
3650
  ]
3649
3651
 
3652
+ [[package]]
3653
+ name = "microsandbox-types-macros"
3654
+ version = "0.6.16"
3655
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3656
+ dependencies = [
3657
+ "proc-macro2",
3658
+ "quote",
3659
+ "syn 3.0.4",
3660
+ ]
3661
+
3650
3662
  [[package]]
3651
3663
  name = "microsandbox-utils"
3652
- version = "0.6.14"
3653
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3664
+ version = "0.6.16"
3665
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3654
3666
  dependencies = [
3655
3667
  "dirs",
3656
3668
  "libc",
@@ -3662,8 +3674,8 @@ dependencies = [
3662
3674
 
3663
3675
  [[package]]
3664
3676
  name = "microsandbox-vsock"
3665
- version = "0.6.14"
3666
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.14#b30fd164ad8640cbc34f6aa9645f9c265c3490b8"
3677
+ version = "0.6.16"
3678
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.6.16#93c14431b387d4666c7c9ca6599bb2fafdc01782"
3667
3679
  dependencies = [
3668
3680
  "libc",
3669
3681
  "msb_krun",
@@ -3675,7 +3687,7 @@ dependencies = [
3675
3687
 
3676
3688
  [[package]]
3677
3689
  name = "microsandbox_rb"
3678
- version = "0.15.0"
3690
+ version = "0.16.0"
3679
3691
  dependencies = [
3680
3692
  "chrono",
3681
3693
  "futures",
@@ -4717,7 +4729,7 @@ dependencies = [
4717
4729
  "once_cell",
4718
4730
  "socket2",
4719
4731
  "tracing",
4720
- "windows-sys 0.52.0",
4732
+ "windows-sys 0.60.2",
4721
4733
  ]
4722
4734
 
4723
4735
  [[package]]
@@ -5255,7 +5267,7 @@ dependencies = [
5255
5267
  "errno",
5256
5268
  "libc",
5257
5269
  "linux-raw-sys",
5258
- "windows-sys 0.52.0",
5270
+ "windows-sys 0.61.2",
5259
5271
  ]
5260
5272
 
5261
5273
  [[package]]
@@ -5324,7 +5336,7 @@ dependencies = [
5324
5336
  "security-framework 3.7.0",
5325
5337
  "security-framework-sys",
5326
5338
  "webpki-root-certs",
5327
- "windows-sys 0.52.0",
5339
+ "windows-sys 0.61.2",
5328
5340
  ]
5329
5341
 
5330
5342
  [[package]]
@@ -5949,7 +5961,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
5949
5961
  checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
5950
5962
  dependencies = [
5951
5963
  "libc",
5952
- "windows-sys 0.60.2",
5964
+ "windows-sys 0.61.2",
5953
5965
  ]
5954
5966
 
5955
5967
  [[package]]
@@ -6398,7 +6410,7 @@ dependencies = [
6398
6410
  "getrandom 0.4.2",
6399
6411
  "once_cell",
6400
6412
  "rustix",
6401
- "windows-sys 0.52.0",
6413
+ "windows-sys 0.61.2",
6402
6414
  ]
6403
6415
 
6404
6416
  [[package]]
@@ -6758,7 +6770,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
6758
6770
  dependencies = [
6759
6771
  "memoffset",
6760
6772
  "tempfile",
6761
- "windows-sys 0.60.2",
6773
+ "windows-sys 0.61.2",
6762
6774
  ]
6763
6775
 
6764
6776
  [[package]]
@@ -7163,7 +7175,7 @@ version = "0.1.11"
7163
7175
  source = "registry+https://github.com/rust-lang/crates.io-index"
7164
7176
  checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
7165
7177
  dependencies = [
7166
- "windows-sys 0.52.0",
7178
+ "windows-sys 0.61.2",
7167
7179
  ]
7168
7180
 
7169
7181
  [[package]]
@@ -7474,7 +7486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
7474
7486
  checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d"
7475
7487
  dependencies = [
7476
7488
  "bitflags 2.13.0",
7477
- "windows-sys 0.52.0",
7489
+ "windows-sys 0.59.0",
7478
7490
  ]
7479
7491
 
7480
7492
  [[package]]
data/DESIGN.md CHANGED
@@ -184,7 +184,7 @@ extension.
184
184
 
185
185
  `ext/microsandbox/Cargo.toml` depends on the core crate via a **pinned git tag**
186
186
  (`microsandbox` / `microsandbox-network`, pinned to the same tag as
187
- `Microsandbox::RUNTIME_VERSION` — currently `v0.6.14`), so the gem builds anywhere
187
+ `Microsandbox::RUNTIME_VERSION` — currently `v0.6.16`), so the gem builds anywhere
188
188
  — CI, `rake-compiler-dock` release containers, and end-user source installs —
189
189
  without an adjacent checkout. For fast local development against a sibling
190
190
  microsandbox checkout, copy `.cargo/config.toml.example` to `.cargo/config.toml`
data/README.md CHANGED
@@ -186,6 +186,39 @@ Microsandbox::Sandbox.start("box") # restart a stopped sandbox
186
186
  Microsandbox::Sandbox.remove("box") # remove a stopped sandbox
187
187
  ```
188
188
 
189
+ **Convergent lifecycle** (runtime `v0.6.16`) — idempotent operations that take a
190
+ name to the state you want, whatever state it is in now:
191
+
192
+ ```ruby
193
+ # Create it, or connect to (and start) the one that is already there. The
194
+ # keyword options are `create`'s and apply only when a create actually happens.
195
+ sb = Microsandbox::Sandbox.connect_or_create("box", image: "public.ecr.aws/docker/library/alpine:latest")
196
+
197
+ sb.id # opaque identity of the *persisted* sandbox — unlike
198
+ # the reusable name, it changes on remove+recreate
199
+ sb.wait_for_status(:running) # => SandboxHandle (no built-in timeout)
200
+ sb = sb.restart # stop + start; => a new live Sandbox
201
+ sb.destroy # stop + remove, in one step
202
+
203
+ h = Microsandbox::Sandbox.get("box")
204
+ h.connect_or_start # connect if running, start if not => Sandbox
205
+ h.restart(force: true, timeout: 5)
206
+ h.destroy
207
+ ```
208
+
209
+ Everything that acts on an *existing* receiver — `wait_for_status`, `restart`,
210
+ `destroy`, `connect_or_start` — compares the identity it was bound to against
211
+ the name's current owner first, raising `Microsandbox::SandboxReplacedError`
212
+ rather than touching a sandbox someone else recreated under the same name.
213
+ (`connect_or_create` is the entry point, so it has no prior identity to check:
214
+ it simply converges on whichever sandbox now owns the name.)
215
+
216
+ `connect_or_create`'s block form stops the sandbox only when the call owns its
217
+ lifecycle — i.e. when it created it attached. A sandbox it merely connected to,
218
+ or started with `detached: true`, is left running. And the stop it does issue is
219
+ scoped to that sandbox's `id`, so a name removed and recreated while the block
220
+ ran cannot be taken down by the teardown either.
221
+
189
222
  > **v0.5.8 lifecycle change.** Upstream split the lifecycle into the live
190
223
  > `Sandbox` and a controllable `SandboxHandle`, and the gem mirrors it. The live
191
224
  > `Sandbox#stop`/`#kill` no longer take a `timeout:`; `#request_stop`/
@@ -430,7 +463,9 @@ Microsandbox::Volume.remove("cache")
430
463
  ```
431
464
 
432
465
  `volumes:` accepts a host path String (bind mount) or `{ bind: "/host" }` /
433
- `{ named: "volume-name" }` per guest path. Boot from a snapshot with
466
+ `{ named: "volume-name" }` per guest path. A bind or named mount may pin the
467
+ fallback guest owner for host files with `uid:`/`gid:` (both required together,
468
+ runtime `v0.6.15`). Boot from a snapshot with
434
469
  `Sandbox.create(name, from_snapshot: "snap-name-or-path")`.
435
470
 
436
471
  ### Error handling
@@ -524,8 +559,8 @@ change diverged the two numbers — the gem version is **not** a reliable indica
524
559
  of the embedded runtime version. To learn which runtime a build wraps, ask it:
525
560
 
526
561
  ```ruby
527
- Microsandbox::VERSION # => "0.15.0" (the gem's own version)
528
- Microsandbox.runtime_version # => "v0.6.14" (the embedded upstream runtime tag)
562
+ Microsandbox::VERSION # => "0.16.0" (the gem's own version)
563
+ Microsandbox.runtime_version # => "v0.6.16" (the embedded upstream runtime tag)
529
564
  ```
530
565
 
531
566
  The companion [`microsandbox-rb-binaries`](#the-runtime-binaries) gem is
@@ -558,6 +593,7 @@ stale.
558
593
  | `0.13.0` | `v0.6.9` | adopts upstream `v0.6.9` (**breaking**): a bare `MSB_API_KEY` no longer selects the cloud backend (explicit `MSB_BACKEND=cloud` or a cloud profile required; invalid cloud config fails closed with `InvalidConfigError`); snapshot payload integrity becomes opt-in (`record_integrity:`, `verify` can report `:not_recorded`). Parity: default-workload execution (`exec_default`/`exec_default_stream`/`attach_default`, `cmd:`), flat root disks (`RootDisk.flat`), `modify(root_disk_size:)`, `rate_limiter:`, `vsock:`, `default_backend_info`, `Volume.get_default` |
559
594
  | `0.14.0` | `v0.6.9` | two-gem split: SDK-only gem (no build-time runtime download) + companion `microsandbox-rb-binaries` platform gems |
560
595
  | `0.15.0` | `v0.6.14` | adopts upstream `v0.6.10`–`v0.6.14` step by step: bind-mount correctness, guest bootstrap off the kernel command line, DNS pins for deferred domain allows, Linux glibc 2.28 baseline for the prebuilt runtime, legacy ext4 upper-disk resize, `msb_krun` 0.1.32. Parity: `ssh.open_client`/`prepare_server` accept `inactivity_timeout:` (seconds; `0` disables, `nil` inherits the 600s global default) |
596
+ | `0.16.0` | `v0.6.16` | adopts upstream `v0.6.15`+`v0.6.16` step by step: mount fallback ownership, readonly-mount write-probe fix, log retrieval rerouted through the SDK backends, config overlaid by field presence, network-slot recycling. Parity: per-mount `uid:`/`gid:`, and the convergent lifecycle — `Sandbox.connect_or_create`, `#id`, `#wait_for_status`, `#restart`, `#destroy`, `SandboxHandle#connect_or_start`, `SandboxReplacedError` |
561
597
 
562
598
  **Going forward** — the gem version moves on its own semver track and no longer
563
599
  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.6.14).
10
- version = "0.15.0"
9
+ # The core-crate dependency below stays pinned at its own tag (v0.6.16).
10
+ version = "0.16.0"
11
11
  authors = ["Super Rad Company <development@superrad.company>"]
12
12
  repository = "https://github.com/superradcompany/microsandbox"
13
13
  license = "Apache-2.0"
@@ -42,8 +42,8 @@ rb-sys = "0.9"
42
42
  # first-use download into ~/.microsandbox (`setup::install`, which is not
43
43
  # gated on "prebuilt"). "net"/"ssh"/"keyring" are the features the official
44
44
  # SDKs ship with.
45
- microsandbox = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.6.14", default-features = false, features = ["keyring", "net", "ssh"] }
46
- microsandbox-network = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.6.14" }
45
+ microsandbox = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.6.16", default-features = false, features = ["keyring", "net", "ssh"] }
46
+ microsandbox-network = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.6.16" }
47
47
  # The *guest* agent (`agentd`, PID 1 inside every microVM) is embedded into the
48
48
  # extension by microsandbox-filesystem's build.rs, which without its "prebuilt"
49
49
  # feature demands a locally built `build/agentd` (workspace-only, `just
@@ -52,7 +52,7 @@ microsandbox-network = { git = "https://github.com/superradcompany/microsandbox"
52
52
  # prebuilt agentd for the target arch is fetched (same behaviour as before)
53
53
  # while the SDK-level msb download above stays off. Feature unification means
54
54
  # this adds no new crates; keep it on the same tag as the deps above.
55
- microsandbox-runtime = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.6.14", default-features = false, features = ["prebuilt"] }
55
+ microsandbox-runtime = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.6.16", default-features = false, features = ["prebuilt"] }
56
56
 
57
57
  # Async core bridged to Ruby's synchronous API via a blocking tokio runtime.
58
58
  tokio = { version = "1", features = ["rt-multi-thread", "sync", "time"] }
@@ -17,6 +17,11 @@ fn class_name(err: &MicrosandboxError) -> &'static str {
17
17
  SandboxNotFound(_) => "SandboxNotFoundError",
18
18
  SandboxAlreadyExists(_) => "SandboxAlreadyExistsError",
19
19
  SandboxStillRunning(_) => "SandboxStillRunningError",
20
+ // v0.6.16 (#1462): the receiver's captured identity no longer owns the
21
+ // name — it was removed and recreated. Raised by the identity-checked
22
+ // convergent lifecycle APIs instead of acting on the replacement.
23
+ // Mirrors the Python `SandboxReplacedError`.
24
+ SandboxReplaced { .. } => "SandboxReplacedError",
20
25
  // v0.6.6 (#1099): the sandbox exists but isn't running. Raised by the
21
26
  // handle's exec/attach/ping/touch not-running guards and the fs
22
27
  // agent-endpoint lookup. The `SandboxNotRunningError` class already