rightsize 0.7.9 → 0.7.12

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 (103) hide show
  1. package/README.md +6 -4
  2. package/dist/backend-docker/backend.d.ts +29 -3
  3. package/dist/backend-docker/backend.d.ts.map +1 -1
  4. package/dist/backend-docker/backend.js +30 -3
  5. package/dist/backend-docker/backend.js.map +1 -1
  6. package/dist/backend-msb/backend.d.ts +657 -83
  7. package/dist/backend-msb/backend.d.ts.map +1 -1
  8. package/dist/backend-msb/backend.js +1319 -149
  9. package/dist/backend-msb/backend.js.map +1 -1
  10. package/dist/backend-msb/commands.d.ts +162 -16
  11. package/dist/backend-msb/commands.d.ts.map +1 -1
  12. package/dist/backend-msb/commands.js +228 -32
  13. package/dist/backend-msb/commands.js.map +1 -1
  14. package/dist/backend-msb/network-links.d.ts +86 -1
  15. package/dist/backend-msb/network-links.d.ts.map +1 -1
  16. package/dist/backend-msb/network-links.js +119 -4
  17. package/dist/backend-msb/network-links.js.map +1 -1
  18. package/dist/backend-msb/provisioner.d.ts +1 -1
  19. package/dist/backend-msb/provisioner.d.ts.map +1 -1
  20. package/dist/backend-msb/provisioner.js +1 -1
  21. package/dist/backend-msb/provisioner.js.map +1 -1
  22. package/dist/backend-msb/restore-access-denied.d.ts +50 -0
  23. package/dist/backend-msb/restore-access-denied.d.ts.map +1 -0
  24. package/dist/backend-msb/restore-access-denied.js +52 -0
  25. package/dist/backend-msb/restore-access-denied.js.map +1 -0
  26. package/dist/backend-msb/restore-broker.d.ts +181 -0
  27. package/dist/backend-msb/restore-broker.d.ts.map +1 -0
  28. package/dist/backend-msb/restore-broker.js +264 -0
  29. package/dist/backend-msb/restore-broker.js.map +1 -0
  30. package/dist/backend-msb/sandbox-already-exists.d.ts +32 -0
  31. package/dist/backend-msb/sandbox-already-exists.d.ts.map +1 -0
  32. package/dist/backend-msb/sandbox-already-exists.js +35 -0
  33. package/dist/backend-msb/sandbox-already-exists.js.map +1 -0
  34. package/dist/backend-msb/snapshot-create.d.ts +22 -0
  35. package/dist/backend-msb/snapshot-create.d.ts.map +1 -0
  36. package/dist/backend-msb/snapshot-create.js +33 -0
  37. package/dist/backend-msb/snapshot-create.js.map +1 -0
  38. package/dist/backend-msb/snapshot-import.d.ts +30 -14
  39. package/dist/backend-msb/snapshot-import.d.ts.map +1 -1
  40. package/dist/backend-msb/snapshot-import.js +35 -17
  41. package/dist/backend-msb/snapshot-import.js.map +1 -1
  42. package/dist/backend-msb/snapshot-rm.d.ts +28 -0
  43. package/dist/backend-msb/snapshot-rm.d.ts.map +1 -0
  44. package/dist/backend-msb/snapshot-rm.js +30 -0
  45. package/dist/backend-msb/snapshot-rm.js.map +1 -0
  46. package/dist/core/backend.d.ts +68 -23
  47. package/dist/core/backend.d.ts.map +1 -1
  48. package/dist/core/checkpoint/api.d.ts +2 -2
  49. package/dist/core/checkpoint/api.js +2 -2
  50. package/dist/core/checkpoint/registry.d.ts +46 -0
  51. package/dist/core/checkpoint/registry.d.ts.map +1 -1
  52. package/dist/core/checkpoint/registry.js +44 -3
  53. package/dist/core/checkpoint/registry.js.map +1 -1
  54. package/dist/core/errors.d.ts +49 -0
  55. package/dist/core/errors.d.ts.map +1 -1
  56. package/dist/core/errors.js +61 -0
  57. package/dist/core/errors.js.map +1 -1
  58. package/dist/core/free-ports.d.ts +18 -0
  59. package/dist/core/free-ports.d.ts.map +1 -1
  60. package/dist/core/free-ports.js +61 -0
  61. package/dist/core/free-ports.js.map +1 -1
  62. package/dist/core/generic-container.d.ts +101 -12
  63. package/dist/core/generic-container.d.ts.map +1 -1
  64. package/dist/core/generic-container.js +399 -71
  65. package/dist/core/generic-container.js.map +1 -1
  66. package/dist/core/model.d.ts +40 -3
  67. package/dist/core/model.d.ts.map +1 -1
  68. package/dist/core/network.d.ts +6 -2
  69. package/dist/core/network.d.ts.map +1 -1
  70. package/dist/core/network.js +4 -1
  71. package/dist/core/network.js.map +1 -1
  72. package/dist/core/reuse/hash.d.ts +12 -0
  73. package/dist/core/reuse/hash.d.ts.map +1 -1
  74. package/dist/core/reuse/hash.js +1 -0
  75. package/dist/core/reuse/hash.js.map +1 -1
  76. package/dist/core/reuse/registry.d.ts +10 -1
  77. package/dist/core/reuse/registry.d.ts.map +1 -1
  78. package/dist/core/reuse/registry.js +15 -1
  79. package/dist/core/reuse/registry.js.map +1 -1
  80. package/dist/core/sandbox-name.d.ts +3 -0
  81. package/dist/core/sandbox-name.d.ts.map +1 -0
  82. package/dist/core/sandbox-name.js +19 -0
  83. package/dist/core/sandbox-name.js.map +1 -0
  84. package/dist/index.d.ts +2 -2
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +1 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/modules/cassandra.d.ts +12 -12
  89. package/dist/modules/cassandra.js +13 -13
  90. package/dist/modules/cassandra.js.map +1 -1
  91. package/dist/modules/minio.d.ts +5 -3
  92. package/dist/modules/minio.d.ts.map +1 -1
  93. package/dist/modules/minio.js +14 -4
  94. package/dist/modules/minio.js.map +1 -1
  95. package/dist/modules/postgres.d.ts +2 -2
  96. package/dist/modules/postgres.d.ts.map +1 -1
  97. package/dist/modules/postgres.js +11 -9
  98. package/dist/modules/postgres.js.map +1 -1
  99. package/package.json +1 -1
  100. package/dist/backend-msb/snapshot-list.d.ts +0 -43
  101. package/dist/backend-msb/snapshot-list.d.ts.map +0 -1
  102. package/dist/backend-msb/snapshot-list.js +0 -53
  103. package/dist/backend-msb/snapshot-list.js.map +0 -1
@@ -0,0 +1,32 @@
1
+ /**
2
+ * True if `output` (an `msb restore` invocation's combined stdout/stderr)
3
+ * names msb's own sandbox-name collision refusal — msb refuses to create a
4
+ * second sandbox under a name it already has one for. Captured shape:
5
+ *
6
+ * ```text
7
+ * error: sandbox 'rz-abc-1' already exists
8
+ * ```
9
+ *
10
+ * EMPIRICALLY VERIFIED against msb 0.7.1's own source
11
+ * (`prepare_create_target` in `sdk/rust/lib/backend/local/sandbox/create.rs`):
12
+ * the check is `existing.is_some() || dir_exists` — the refusal fires when
13
+ * EITHER the sandbox's database record still exists OR its on-disk directory
14
+ * does, two independent things that can each still be mid-release on
15
+ * Windows. `MsbCliBackend.createCheckpoint`'s own stop/snapshot/`rm`/restore
16
+ * cycle removes the source sandbox and immediately restores a fresh one
17
+ * under the SAME name, so a lingering release on either side races the very
18
+ * next `restore` straight into this refusal.
19
+ *
20
+ * Deliberately a broad, case-insensitive substring match (mirrors this
21
+ * backend's own `isPortBindConflictOutput`, and the sibling classifiers this
22
+ * whole family of msb backends — rust, kotlin — use for the identical
23
+ * signature) rather than a strict parse: msb has no structured/typed error
24
+ * for this, only combined process output, and a collision can be worded
25
+ * around either the sandbox's name or (rarely, alternate msb builds) its
26
+ * dedicated "already in use" phrasing. Only ever checked against a
27
+ * `msb restore` invocation's own output — a `msb snapshot load` "already
28
+ * exists" (see `isSnapshotAlreadyExistsError`) is a completely different
29
+ * command and never appears here.
30
+ */
31
+ export declare function isSandboxAlreadyExistsFailure(output: string): boolean;
32
+ //# sourceMappingURL=sandbox-already-exists.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-already-exists.d.ts","sourceRoot":"","sources":["../../src/backend-msb/sandbox-already-exists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGrE"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * True if `output` (an `msb restore` invocation's combined stdout/stderr)
3
+ * names msb's own sandbox-name collision refusal — msb refuses to create a
4
+ * second sandbox under a name it already has one for. Captured shape:
5
+ *
6
+ * ```text
7
+ * error: sandbox 'rz-abc-1' already exists
8
+ * ```
9
+ *
10
+ * EMPIRICALLY VERIFIED against msb 0.7.1's own source
11
+ * (`prepare_create_target` in `sdk/rust/lib/backend/local/sandbox/create.rs`):
12
+ * the check is `existing.is_some() || dir_exists` — the refusal fires when
13
+ * EITHER the sandbox's database record still exists OR its on-disk directory
14
+ * does, two independent things that can each still be mid-release on
15
+ * Windows. `MsbCliBackend.createCheckpoint`'s own stop/snapshot/`rm`/restore
16
+ * cycle removes the source sandbox and immediately restores a fresh one
17
+ * under the SAME name, so a lingering release on either side races the very
18
+ * next `restore` straight into this refusal.
19
+ *
20
+ * Deliberately a broad, case-insensitive substring match (mirrors this
21
+ * backend's own `isPortBindConflictOutput`, and the sibling classifiers this
22
+ * whole family of msb backends — rust, kotlin — use for the identical
23
+ * signature) rather than a strict parse: msb has no structured/typed error
24
+ * for this, only combined process output, and a collision can be worded
25
+ * around either the sandbox's name or (rarely, alternate msb builds) its
26
+ * dedicated "already in use" phrasing. Only ever checked against a
27
+ * `msb restore` invocation's own output — a `msb snapshot load` "already
28
+ * exists" (see `isSnapshotAlreadyExistsError`) is a completely different
29
+ * command and never appears here.
30
+ */
31
+ export function isSandboxAlreadyExistsFailure(output) {
32
+ const m = output.toLowerCase();
33
+ return m.includes("already exists") || (m.includes("already in use") && m.includes("name"));
34
+ }
35
+ //# sourceMappingURL=sandbox-already-exists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-already-exists.js","sourceRoot":"","sources":["../../src/backend-msb/sandbox-already-exists.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,6BAA6B,CAAC,MAAc;IAC1D,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAC/B,OAAO,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9F,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Extracts the artifact path msb prints as the LAST line of a successful
3
+ * `msb snapshot create --from-sandbox ...` invocation's stdout. EMPIRICALLY
4
+ * VERIFIED against a real msb 0.7.1 binary: the command prints the snapshot
5
+ * ID line first, then the absolute artifact path as its final line —
6
+ * `<destDir-or-default>/<sourceSandbox>/snap_<32-hex-digest>` (see
7
+ * `MsbCommands.snapshotCreate`'s own doc for why the caller-supplied name
8
+ * never determines this path). `MsbCliBackend.createCheckpoint` uses the
9
+ * returned path — never the ref it asked msb to create the snapshot under —
10
+ * as the effective checkpoint ref for every later restore/rm/inspect call.
11
+ *
12
+ * Deliberately conservative, matching the HARD CONSTRAINT this parser was
13
+ * written to satisfy: trims the whole output, keeps only non-empty lines,
14
+ * takes the LAST one, and requires it to be an absolute path (`path.isAbsolute`)
15
+ * — anything else (empty output, a relative-looking last line, some future
16
+ * extra trailing line this parser has never seen) resolves `undefined`
17
+ * rather than guessing, so the caller can fail loudly with the raw,
18
+ * unparsed output quoted verbatim instead of minting a checkpoint ref from a
19
+ * misread line.
20
+ */
21
+ export declare function parseSnapshotCreateArtifactPath(stdout: string): string | undefined;
22
+ //# sourceMappingURL=snapshot-create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-create.d.ts","sourceRoot":"","sources":["../../src/backend-msb/snapshot-create.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUlF"}
@@ -0,0 +1,33 @@
1
+ import * as path from "node:path";
2
+ /**
3
+ * Extracts the artifact path msb prints as the LAST line of a successful
4
+ * `msb snapshot create --from-sandbox ...` invocation's stdout. EMPIRICALLY
5
+ * VERIFIED against a real msb 0.7.1 binary: the command prints the snapshot
6
+ * ID line first, then the absolute artifact path as its final line —
7
+ * `<destDir-or-default>/<sourceSandbox>/snap_<32-hex-digest>` (see
8
+ * `MsbCommands.snapshotCreate`'s own doc for why the caller-supplied name
9
+ * never determines this path). `MsbCliBackend.createCheckpoint` uses the
10
+ * returned path — never the ref it asked msb to create the snapshot under —
11
+ * as the effective checkpoint ref for every later restore/rm/inspect call.
12
+ *
13
+ * Deliberately conservative, matching the HARD CONSTRAINT this parser was
14
+ * written to satisfy: trims the whole output, keeps only non-empty lines,
15
+ * takes the LAST one, and requires it to be an absolute path (`path.isAbsolute`)
16
+ * — anything else (empty output, a relative-looking last line, some future
17
+ * extra trailing line this parser has never seen) resolves `undefined`
18
+ * rather than guessing, so the caller can fail loudly with the raw,
19
+ * unparsed output quoted verbatim instead of minting a checkpoint ref from a
20
+ * misread line.
21
+ */
22
+ export function parseSnapshotCreateArtifactPath(stdout) {
23
+ const lines = stdout
24
+ .split("\n")
25
+ .map((line) => line.trim())
26
+ .filter((line) => line.length > 0);
27
+ const lastLine = lines.at(-1);
28
+ if (lastLine === undefined || !path.isAbsolute(lastLine)) {
29
+ return undefined;
30
+ }
31
+ return lastLine;
32
+ }
33
+ //# sourceMappingURL=snapshot-create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-create.js","sourceRoot":"","sources":["../../src/backend-msb/snapshot-create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,+BAA+B,CAAC,MAAc;IAC5D,MAAM,KAAK,GAAG,MAAM;SACjB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -12,22 +12,38 @@
12
12
  * one rather than surfacing it. Deliberately a substring match on the stable
13
13
  * prefix, the same reasoning `isSnapshotNotFoundError` applies to its own
14
14
  * wording: the trailing path varies per host and msb has no structured/typed
15
- * error for this.
15
+ * error for this. Not re-verified against 0.7.1 specifically (the rename to
16
+ * `save`/`load` did not touch this message in any captured output), so this
17
+ * stays a defensive fallback rather than the primary success path.
16
18
  */
17
19
  export declare function isSnapshotAlreadyExistsError(stderr: string): boolean;
18
20
  /**
19
- * Extracts the digest-dir basename from one `msb snapshot load`
20
- * invocation's output. Verified against the real msb 0.6.8 binary: on both a
21
- * success (the printed stdout line) and an already-exists failure (the
22
- * `error: snapshot already exists: <path>` stderr line), the relevant line
23
- * ENDS with the artifact path under `~/.microsandbox/snapshots/`, whose
24
- * basename is the digest-derived directory name (e.g.
25
- * `sha256-b9c0448ee9d54e33`) — never the original archive's own recorded
26
- * ref. Callers pass whichever stream actually carries the signal (stdout on
27
- * success, stderr on an already-exists failure). `undefined` means the
28
- * output carried no recognizable trailing path — a shape this backend
29
- * doesn't understand, which the caller turns into its own actionable error
30
- * rather than guessing.
21
+ * Extracts the loaded artifact's absolute path from one `msb snapshot load`
22
+ * invocation's output — the EFFECTIVE ref `importCheckpoint` hands back.
23
+ * EMPIRICALLY VERIFIED against a real msb 0.7.1 binary: a successful load
24
+ * prints a `group msb-<hex>: head snap_<digest> (Initialized)` line, then a
25
+ * digest line, then the loaded artifact's absolute path as the LAST line —
26
+ * `<destDir>/<generated-group>/snap_<digest>`, where `<destDir>` is whatever
27
+ * `--dest` was given (see `MsbCommands.snapshotImport`). The same defensive
28
+ * pattern `parseSnapshotCreateArtifactPath` uses for `snapshot create`'s own
29
+ * trailing-path output: trims the whole output, keeps only non-empty lines,
30
+ * takes the LAST one, and requires it to be an absolute path — anything else
31
+ * (empty output, a relative-looking last line, msb's own preceding "group"/
32
+ * digest lines mistaken for the answer) resolves `undefined` rather than
33
+ * guessing, so the caller fails loudly with the raw output quoted verbatim
34
+ * instead of minting a checkpoint ref from a misread line. This replaces the
35
+ * pre-0.7.1 approach of parsing out just the digest-dir BASENAME and then
36
+ * confirming it via a separate `msb snapshot list` call — 0.7.1's `load`
37
+ * already prints the full, directly-usable ref, so that second call is gone.
38
+ *
39
+ * The already-exists failure path (see `isSnapshotAlreadyExistsError`) has a
40
+ * different last-line shape than a success's: msb's own message prefixes
41
+ * the path with prose on the SAME line (`error: snapshot already exists:
42
+ * <path>`), captured verbatim from the real 0.6.8 binary and not
43
+ * re-verified against 0.7.1 — so a whole-line match never fires for it.
44
+ * When the whole line isn't itself an absolute path, this falls back to the
45
+ * line's trailing whitespace-delimited token and requires THAT to be
46
+ * absolute instead, rather than guessing a ref out of prose.
31
47
  */
32
- export declare function parseImportedDigestDirName(output: string): string | undefined;
48
+ export declare function parseImportedArtifactPath(output: string): string | undefined;
33
49
  //# sourceMappingURL=snapshot-import.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-import.d.ts","sourceRoot":"","sources":["../../src/backend-msb/snapshot-import.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAY7E"}
1
+ {"version":3,"file":"snapshot-import.d.ts","sourceRoot":"","sources":["../../src/backend-msb/snapshot-import.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc5E"}
@@ -13,26 +13,42 @@ import * as path from "node:path";
13
13
  * one rather than surfacing it. Deliberately a substring match on the stable
14
14
  * prefix, the same reasoning `isSnapshotNotFoundError` applies to its own
15
15
  * wording: the trailing path varies per host and msb has no structured/typed
16
- * error for this.
16
+ * error for this. Not re-verified against 0.7.1 specifically (the rename to
17
+ * `save`/`load` did not touch this message in any captured output), so this
18
+ * stays a defensive fallback rather than the primary success path.
17
19
  */
18
20
  export function isSnapshotAlreadyExistsError(stderr) {
19
21
  return stderr.includes("snapshot already exists");
20
22
  }
21
23
  /**
22
- * Extracts the digest-dir basename from one `msb snapshot load`
23
- * invocation's output. Verified against the real msb 0.6.8 binary: on both a
24
- * success (the printed stdout line) and an already-exists failure (the
25
- * `error: snapshot already exists: <path>` stderr line), the relevant line
26
- * ENDS with the artifact path under `~/.microsandbox/snapshots/`, whose
27
- * basename is the digest-derived directory name (e.g.
28
- * `sha256-b9c0448ee9d54e33`) — never the original archive's own recorded
29
- * ref. Callers pass whichever stream actually carries the signal (stdout on
30
- * success, stderr on an already-exists failure). `undefined` means the
31
- * output carried no recognizable trailing path — a shape this backend
32
- * doesn't understand, which the caller turns into its own actionable error
33
- * rather than guessing.
24
+ * Extracts the loaded artifact's absolute path from one `msb snapshot load`
25
+ * invocation's output — the EFFECTIVE ref `importCheckpoint` hands back.
26
+ * EMPIRICALLY VERIFIED against a real msb 0.7.1 binary: a successful load
27
+ * prints a `group msb-<hex>: head snap_<digest> (Initialized)` line, then a
28
+ * digest line, then the loaded artifact's absolute path as the LAST line —
29
+ * `<destDir>/<generated-group>/snap_<digest>`, where `<destDir>` is whatever
30
+ * `--dest` was given (see `MsbCommands.snapshotImport`). The same defensive
31
+ * pattern `parseSnapshotCreateArtifactPath` uses for `snapshot create`'s own
32
+ * trailing-path output: trims the whole output, keeps only non-empty lines,
33
+ * takes the LAST one, and requires it to be an absolute path — anything else
34
+ * (empty output, a relative-looking last line, msb's own preceding "group"/
35
+ * digest lines mistaken for the answer) resolves `undefined` rather than
36
+ * guessing, so the caller fails loudly with the raw output quoted verbatim
37
+ * instead of minting a checkpoint ref from a misread line. This replaces the
38
+ * pre-0.7.1 approach of parsing out just the digest-dir BASENAME and then
39
+ * confirming it via a separate `msb snapshot list` call — 0.7.1's `load`
40
+ * already prints the full, directly-usable ref, so that second call is gone.
41
+ *
42
+ * The already-exists failure path (see `isSnapshotAlreadyExistsError`) has a
43
+ * different last-line shape than a success's: msb's own message prefixes
44
+ * the path with prose on the SAME line (`error: snapshot already exists:
45
+ * <path>`), captured verbatim from the real 0.6.8 binary and not
46
+ * re-verified against 0.7.1 — so a whole-line match never fires for it.
47
+ * When the whole line isn't itself an absolute path, this falls back to the
48
+ * line's trailing whitespace-delimited token and requires THAT to be
49
+ * absolute instead, rather than guessing a ref out of prose.
34
50
  */
35
- export function parseImportedDigestDirName(output) {
51
+ export function parseImportedArtifactPath(output) {
36
52
  const lines = output
37
53
  .split("\n")
38
54
  .map((line) => line.trim())
@@ -41,8 +57,10 @@ export function parseImportedDigestDirName(output) {
41
57
  if (lastLine === undefined) {
42
58
  return undefined;
43
59
  }
44
- const match = /(\S+)\s*$/.exec(lastLine);
45
- const artifactPath = match?.[1];
46
- return artifactPath === undefined ? undefined : path.basename(artifactPath);
60
+ if (path.isAbsolute(lastLine)) {
61
+ return lastLine;
62
+ }
63
+ const trailingToken = /(\S+)\s*$/.exec(lastLine)?.[1];
64
+ return trailingToken !== undefined && path.isAbsolute(trailingToken) ? trailingToken : undefined;
47
65
  }
48
66
  //# sourceMappingURL=snapshot-import.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-import.js","sourceRoot":"","sources":["../../src/backend-msb/snapshot-import.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAc;IACvD,MAAM,KAAK,GAAG,MAAM;SACjB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"snapshot-import.js","sourceRoot":"","sources":["../../src/backend-msb/snapshot-import.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,MAAM,KAAK,GAAG,MAAM;SACjB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;AACnG,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * True if `stderr` (an `msb snapshot rm <artifact-path> -f` non-zero exit)
3
+ * names msb's own "this snapshot is the current head of other snapshots
4
+ * from the same source sandbox" refusal, as opposed to a genuine "not
5
+ * found" (which `removeCheckpoint` treats as success, the same best-effort
6
+ * contract `removeByName` has) or some other, unrelated failure.
7
+ * EMPIRICALLY VERIFIED against a real msb 0.7.1 binary:
8
+ *
9
+ * ```
10
+ * error: invalid config: cannot remove current head snap_<digest>; first
11
+ * select another snapshot with 'msb snapshot head src:<snapshot>'
12
+ * ```
13
+ *
14
+ * Removing a non-head member, or a group's ONLY member, succeeds — this
15
+ * refusal is specifically "older siblings from the same source sandbox
16
+ * still exist and this is still the newest of them." `removeCheckpoint`
17
+ * propagates this one verbatim instead of swallowing it alongside an
18
+ * ordinary "not found": the caller has an actionable remedy (`msb snapshot
19
+ * head ...`, named in msb's own message), and this library deliberately
20
+ * does not attempt automatic head rotation on the caller's behalf — see the
21
+ * checkpoints guide's cleanup section for the documented limitation.
22
+ * Deliberately a substring match on the stable "cannot remove current head"
23
+ * phrase, the same reasoning `isSnapshotNotFoundError` applies to its own
24
+ * wording — the snapshot id and the exact command hint vary per occurrence,
25
+ * and msb has no structured/typed error for this.
26
+ */
27
+ export declare function isSnapshotHeadRemovalRefused(stderr: string): boolean;
28
+ //# sourceMappingURL=snapshot-rm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-rm.d.ts","sourceRoot":"","sources":["../../src/backend-msb/snapshot-rm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpE"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * True if `stderr` (an `msb snapshot rm <artifact-path> -f` non-zero exit)
3
+ * names msb's own "this snapshot is the current head of other snapshots
4
+ * from the same source sandbox" refusal, as opposed to a genuine "not
5
+ * found" (which `removeCheckpoint` treats as success, the same best-effort
6
+ * contract `removeByName` has) or some other, unrelated failure.
7
+ * EMPIRICALLY VERIFIED against a real msb 0.7.1 binary:
8
+ *
9
+ * ```
10
+ * error: invalid config: cannot remove current head snap_<digest>; first
11
+ * select another snapshot with 'msb snapshot head src:<snapshot>'
12
+ * ```
13
+ *
14
+ * Removing a non-head member, or a group's ONLY member, succeeds — this
15
+ * refusal is specifically "older siblings from the same source sandbox
16
+ * still exist and this is still the newest of them." `removeCheckpoint`
17
+ * propagates this one verbatim instead of swallowing it alongside an
18
+ * ordinary "not found": the caller has an actionable remedy (`msb snapshot
19
+ * head ...`, named in msb's own message), and this library deliberately
20
+ * does not attempt automatic head rotation on the caller's behalf — see the
21
+ * checkpoints guide's cleanup section for the documented limitation.
22
+ * Deliberately a substring match on the stable "cannot remove current head"
23
+ * phrase, the same reasoning `isSnapshotNotFoundError` applies to its own
24
+ * wording — the snapshot id and the exact command hint vary per occurrence,
25
+ * and msb has no structured/typed error for this.
26
+ */
27
+ export function isSnapshotHeadRemovalRefused(stderr) {
28
+ return stderr.includes("cannot remove current head");
29
+ }
30
+ //# sourceMappingURL=snapshot-rm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-rm.js","sourceRoot":"","sources":["../../src/backend-msb/snapshot-rm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;AACvD,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { ContainerSpec, ExecResult } from "./model.js";
1
+ import type { ContainerSpec, ExecResult, PortProtocol } from "./model.js";
2
2
  /**
3
3
  * One alias a container should be reachable under from a running sibling on
4
4
  * the same `Network`, computed by `Network.linksForNewMember()`. A native
@@ -12,6 +12,20 @@ export interface NetworkLink {
12
12
  readonly guestPort: number;
13
13
  /** The sibling's host-side mapped port to tunnel/route traffic to. */
14
14
  readonly targetHostPort: number;
15
+ /**
16
+ * The transport `guestPort` was exposed over. `"tcp"` for every link
17
+ * computed from a sibling's `exposedGuestPorts`/`mappedPort` (unchanged
18
+ * behavior); `"udp"` for one computed from `exposedUdpGuestPorts`/
19
+ * `mappedUdpPort`. Docker ignores this — its native bridge network already
20
+ * carries UDP with no per-link declaration (see `installNetworkLinks`'s
21
+ * own doc); msb has no shared network to carry either transport, so it
22
+ * emulates both, but by different means: a TCP link gets an exec-tunnel
23
+ * relayed through this process (`MsbCliBackend`'s `ExecTunnel`), a UDP
24
+ * link gets an in-guest forwarder dialing `targetHostPort` on the host
25
+ * gateway directly, with no per-connection relay on this side at all (see
26
+ * `MsbCliBackend.installNetworkLinks`).
27
+ */
28
+ readonly protocol: PortProtocol;
15
29
  }
16
30
  /**
17
31
  * Backend-native opaque container reference. Immutable id + spec; any
@@ -100,19 +114,49 @@ export interface SandboxBackend {
100
114
  /** Best-effort removal of the backend-native resource; callers swallow failures during teardown. */
101
115
  remove(handle: SandboxHandle): Promise<void>;
102
116
  /**
103
- * Captures `handle`'s current state under `ref` —
104
- * `GenericContainer.checkpoint()`'s backend call, gated on
117
+ * Captures `handle`'s current state and returns the EFFECTIVE ref to use
118
+ * from here on — `GenericContainer.checkpoint()`'s backend call, gated on
105
119
  * `capabilities.checkpoint` BEFORE this is ever reached, so an
106
120
  * unsupported backend never has to implement this for real (it may throw
107
- * defensively). Docker: commits the running container to image `ref`,
108
- * undisturbed. Microsandbox: stop the sandbox, `msb snapshot create` a
109
- * disk snapshot under `ref` (an absolute `<cacheDir>/checkpoints/rz-ckpt-*`
110
- * path — via `--dest-dir`, not msb's own default snapshot store), then
111
- * start the sandbox back up — the workload restarts, which is why
112
- * `capabilities.checkpointRestartsWorkload` exists. Never called on a
113
- * backend whose `capabilities.checkpoint` is `false`.
121
+ * defensively). `ref` is the WORKING ref the caller asks this to
122
+ * checkpoint under; the returned value is not necessarily `ref` itself —
123
+ * the same asymmetry `importCheckpoint` already has, for the same reason.
124
+ * Docker: commits the running container to image `ref`, undisturbed, and
125
+ * returns `ref` unchanged (docker's tag round-trips exactly). Microsandbox:
126
+ * stop the sandbox, `msb snapshot create` a disk snapshot (via `--dest-dir`,
127
+ * not msb's own default snapshot store), then start the sandbox back up —
128
+ * the workload restarts, which is why `capabilities.checkpointRestartsWorkload`
129
+ * exists. Since msb 0.7.1, `snapshot create`'s own artifact placement is
130
+ * content-addressed and `ref` never determines it (see `MsbCliBackend`'s
131
+ * own doc), so the microsandbox backend parses the real artifact path back
132
+ * out of that command's stdout and returns THAT as the effective ref — the
133
+ * caller (`GenericContainer.checkpoint()`) stores whatever this returns in
134
+ * the named-checkpoint registry and on the `Checkpoint` it hands back,
135
+ * never `ref` itself. Never called on a backend whose
136
+ * `capabilities.checkpoint` is `false`.
137
+ */
138
+ createCheckpoint(handle: SandboxHandle, ref: string): Promise<string>;
139
+ /**
140
+ * OPTIONAL: the workload argv this backend captured from `handle`'s guest
141
+ * during its MOST RECENT `createCheckpoint` call, when that call's source
142
+ * container had no explicit `spec.command` — `undefined` when nothing was
143
+ * captured (an explicit command needed no capture, the capture attempt
144
+ * itself failed, or this backend never captures at all). `createCheckpoint`
145
+ * itself never surfaces this — it stays `Promise<string>`, unchanged — so
146
+ * `GenericContainer.checkpoint()` calls this SEPARATELY, right after
147
+ * `createCheckpoint` returns, to fold the result into a NAMED checkpoint's
148
+ * registry entry (`CheckpointRegistryEntry.capturedCommand`) and into the
149
+ * `Checkpoint.spec.command` it hands back, so a later restore — registry-
150
+ * mediated or not — has the fully-resolved workload argv without a second
151
+ * capture attempt against a sandbox that (on msb) no longer even runs the
152
+ * old one. A backend that never captures (docker: restoring a checkpoint
153
+ * is an ordinary boot from the committed image, whose own baked
154
+ * ENTRYPOINT/CMD already reproduces the workload with no capture needed)
155
+ * simply omits this method — every existing implementation keeps compiling
156
+ * and behaving unchanged. See `MsbCliBackend.createCheckpoint`'s own doc
157
+ * for when and how the microsandbox backend actually captures one.
114
158
  */
115
- createCheckpoint(handle: SandboxHandle, ref: string): Promise<void>;
159
+ capturedWorkloadCommand?(handle: SandboxHandle): ReadonlyArray<string> | undefined;
116
160
  /**
117
161
  * Best-effort removal of a checkpoint identified by `ref` (docker: `rmi`;
118
162
  * microsandbox: `msb snapshot rm`) — "not found" is success, the same
@@ -155,18 +199,19 @@ export interface SandboxBackend {
155
199
  * Materializes an exported archive's backend payload from `srcFile` and
156
200
  * returns the EFFECTIVE ref to use from here on — not necessarily `ref`
157
201
  * itself. docker preserves the original tag on `docker load`, so its
158
- * effective ref IS `ref`; microsandbox's `snapshot load` writes under a
159
- * digest-derived DIRECTORY NAME (e.g. `sha256-b9c0448ee9d54e33`) it never
160
- * lets the caller choose, so its effective ref is that directory name,
161
- * confirmed present via `snapshot list --format json` — never the full
162
- * `sha256:<64hex>` digest, which does not resolve as a snapshot ref at
163
- * all. An already-exists failure for a content-addressed archive is
164
- * treated as success. `ref` is the archive's own recorded ref (from
165
- * `checkpoint.json`), passed through for backends (docker) that have no
166
- * new ref to derive. Only ever called once the generic layer has already
167
- * validated the archive's `checkpoint.json` (version, name, backend)
168
- * against the active backend; any failure other than "already imported"
169
- * surfaces the underlying tool's stderr in a `BackendError`.
202
+ * effective ref IS `ref`; microsandbox's `snapshot load --dest
203
+ * <checkpointsDir>` writes under a path msb itself generates (never the
204
+ * caller's `ref`, never a name the caller can choose), which this backend
205
+ * parses straight out of `load`'s own printed output — no separate
206
+ * confirmation call needed, since 0.7.1 already prints the full, directly
207
+ * usable path (see `MsbCliBackend.importCheckpoint`). An already-exists
208
+ * failure for a content-addressed archive is treated as success. `ref` is
209
+ * the archive's own recorded ref (from `checkpoint.json`), passed through
210
+ * for backends (docker) that have no new ref to derive. Only ever called
211
+ * once the generic layer has already validated the archive's
212
+ * `checkpoint.json` (version, name, backend) against the active backend;
213
+ * any failure other than "already imported" surfaces the underlying
214
+ * tool's stderr in a `BackendError`.
170
215
  */
171
216
  importCheckpoint(srcFile: string, ref: string): Promise<string>;
172
217
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/core/backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/core/backend.ts"],"names":[],"mappings":"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"}
@@ -91,8 +91,8 @@ export declare function exportTo(cp: Checkpoint, destPath: string): Promise<void
91
91
  * either way, before any backend call or registry write), then hands the
92
92
  * extracted `artifact` to `SandboxBackend.importCheckpoint`, which
93
93
  * materializes it and returns the EFFECTIVE ref (docker: the same `ref` the
94
- * archive recorded; microsandbox: the digest `snapshot load` actually
95
- * assigned it — never necessarily the archive's own `ref`).
94
+ * archive recorded; microsandbox: the loaded artifact's own path `snapshot
95
+ * load` actually assigned it — never necessarily the archive's own `ref`).
96
96
  *
97
97
  * A NAMED archive (`name` non-null) gets replace semantics matching
98
98
  * `checkpoint(name)`: if a registry entry already exists for that name under
@@ -189,8 +189,8 @@ export async function exportTo(cp, destPath) {
189
189
  * either way, before any backend call or registry write), then hands the
190
190
  * extracted `artifact` to `SandboxBackend.importCheckpoint`, which
191
191
  * materializes it and returns the EFFECTIVE ref (docker: the same `ref` the
192
- * archive recorded; microsandbox: the digest `snapshot load` actually
193
- * assigned it — never necessarily the archive's own `ref`).
192
+ * archive recorded; microsandbox: the loaded artifact's own path `snapshot
193
+ * load` actually assigned it — never necessarily the archive's own `ref`).
194
194
  *
195
195
  * A NAMED archive (`name` non-null) gets replace semantics matching
196
196
  * `checkpoint(name)`: if a registry entry already exists for that name under
@@ -12,8 +12,20 @@ import type { ContainerSpec } from "../model.js";
12
12
  export interface CheckpointRegistrySpec {
13
13
  readonly env: Record<string, string>;
14
14
  readonly command: ReadonlyArray<string> | null;
15
+ /** TCP-exposed guest ports only — unchanged shape/name from before UDP exposure existed. */
15
16
  readonly exposedPorts: ReadonlyArray<number>;
16
17
  readonly memoryLimitMb: number | null;
18
+ /**
19
+ * UDP-exposed guest ports (`withExposedUdpPorts`), kept as a SEPARATE list
20
+ * from `exposedPorts` so a restore can split them back into the right
21
+ * builder field (`fromCheckpoint` calls `withExposedPorts` for one list and
22
+ * `withExposedUdpPorts` for the other) rather than guessing protocol from a
23
+ * merged list of bare numbers. ADDITIVE and OPTIONAL: absent on every entry
24
+ * written before UDP exposure existed — a deserializer/validator reading an
25
+ * old entry treats a missing value as "no UDP ports were ever exposed"
26
+ * (normalizes to `[]`), never as corrupt.
27
+ */
28
+ readonly exposedUdpPorts?: ReadonlyArray<number>;
17
29
  }
18
30
  /**
19
31
  * One `checkpoints/<name>.json` record: written atomically only after the
@@ -30,6 +42,28 @@ export interface CheckpointRegistryEntry {
30
42
  readonly backend: string;
31
43
  readonly createdIso: string;
32
44
  readonly spec: CheckpointRegistrySpec;
45
+ /**
46
+ * The workload argv `GenericContainer.checkpoint()` captured from the
47
+ * guest at checkpoint time (via `SandboxBackend.capturedWorkloadCommand`),
48
+ * for a source container whose own `spec.command` was `undefined` — the
49
+ * image's default entrypoint was running, so there is no explicit command
50
+ * to fall back on at restore time. msb-only in practice today: `msb
51
+ * restore` boots a restored sandbox with only its guest agent inside and
52
+ * never re-runs a captured workload on its own (EMPIRICALLY VERIFIED
53
+ * against msb 0.7.1 — see `MsbCliBackend.bootRestoreOnce`'s own doc), so
54
+ * this library restarts it itself, using this field as the argv source
55
+ * when the checkpoint carries no explicit `spec.command`.
56
+ *
57
+ * ADDITIVE and OPTIONAL — deliberately NOT part of the pinned, cross-
58
+ * language `CheckpointRegistrySpec` shape `spec` above carries: absent on
59
+ * every entry written before this field existed, and on any entry whose
60
+ * source container already had an explicit `spec.command` (nothing to
61
+ * capture). Reading an old entry without it is not an error — only
62
+ * restoring FROM one, when the entry also has no explicit `spec.command`,
63
+ * throws `CheckpointWorkloadCommandMissingError` rather than booting a
64
+ * workload-less sandbox silently (see `fromCheckpointRegistryEntry` below).
65
+ */
66
+ readonly capturedCommand?: ReadonlyArray<string>;
33
67
  }
34
68
  /** `<cacheDir>/checkpoints` — the directory every named checkpoint's registry file lives under. */
35
69
  export declare function checkpointsDir(cacheDir: string): string;
@@ -106,6 +140,18 @@ export declare function toCheckpointRegistrySpec(spec: ContainerSpec): Checkpoin
106
140
  * pointing at itself. `diskLimitMb`/`tmpfsRootMb`/`networkDisabled` are
107
141
  * placeholders too — the registry's pinned `CheckpointRegistrySpec` shape
108
142
  * doesn't carry them, same as it never carried `keepAlive`.
143
+ *
144
+ * `command` resolves with `entry.capturedCommand` as its fallback: when the
145
+ * source container had an explicit command, `entry.spec.command` already
146
+ * carries it and `capturedCommand` (never set for that case) never enters
147
+ * into it; when it did not, this substitutes whatever guest cmdline
148
+ * `checkpoint()` captured, so the restored `ContainerSpec`'s `command` is
149
+ * already the fully-resolved workload argv a restore-side backend (msb)
150
+ * needs to revive it, with no separate lookup needed at restore time. When
151
+ * NEITHER is present (an entry written before capture existed, or one whose
152
+ * capture attempt itself failed), `command` stays `undefined` exactly as
153
+ * before, and it is the restoring backend's own job to refuse rather than
154
+ * boot that sandbox silently idle (see `MsbCliBackend.bootRestoreOnce`).
109
155
  */
110
156
  export declare function fromCheckpointRegistryEntry(entry: CheckpointRegistryEntry): ContainerSpec;
111
157
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/checkpoint/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mLAAmL;IACnL,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;CACvC;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7E;AAED,wKAAwK;AACxK,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CA8BxF;AAkBD,sLAAsL;AACtL,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAExE;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAkBlH;AAED;;;;;;;GAOG;AACH,wBAAsB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOjI;AAED,4FAA4F;AAC5F,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhG;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ7E;AAOD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,sBAAsB,CAWpF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,uBAAuB,GAAG,aAAa,CAkBzF"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/checkpoint/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC/C,4FAA4F;IAC5F,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;;;;;;;;OASG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAClD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mLAAmL;IACnL,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAClD;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7E;AAED,wKAAwK;AACxK,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAuCxF;AAyBD,sLAAsL;AACtL,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAExE;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAkBlH;AAED;;;;;;;GAOG;AACH,wBAAsB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOjI;AAED,4FAA4F;AAC5F,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhG;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ7E;AAOD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,sBAAsB,CAgBpF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,uBAAuB,GAAG,aAAa,CA2BzF"}