rightsize 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +36 -26
  2. package/dist/backend-docker/backend.d.ts +41 -4
  3. package/dist/backend-docker/backend.d.ts.map +1 -1
  4. package/dist/backend-docker/backend.js +84 -6
  5. package/dist/backend-docker/backend.js.map +1 -1
  6. package/dist/backend-docker/cli.d.ts +29 -0
  7. package/dist/backend-docker/cli.d.ts.map +1 -0
  8. package/dist/backend-docker/cli.js +72 -0
  9. package/dist/backend-docker/cli.js.map +1 -0
  10. package/dist/backend-msb/backend.d.ts +91 -7
  11. package/dist/backend-msb/backend.d.ts.map +1 -1
  12. package/dist/backend-msb/backend.js +185 -11
  13. package/dist/backend-msb/backend.js.map +1 -1
  14. package/dist/backend-msb/commands.d.ts +16 -0
  15. package/dist/backend-msb/commands.d.ts.map +1 -1
  16. package/dist/backend-msb/commands.js +41 -1
  17. package/dist/backend-msb/commands.js.map +1 -1
  18. package/dist/backend-msb/snapshot-import.d.ts +33 -0
  19. package/dist/backend-msb/snapshot-import.d.ts.map +1 -0
  20. package/dist/backend-msb/snapshot-import.js +48 -0
  21. package/dist/backend-msb/snapshot-import.js.map +1 -0
  22. package/dist/backend-msb/snapshot-list.d.ts +43 -0
  23. package/dist/backend-msb/snapshot-list.d.ts.map +1 -0
  24. package/dist/backend-msb/snapshot-list.js +53 -0
  25. package/dist/backend-msb/snapshot-list.js.map +1 -0
  26. package/dist/backend-msb/snapshot-not-found.d.ts +25 -0
  27. package/dist/backend-msb/snapshot-not-found.d.ts.map +1 -0
  28. package/dist/backend-msb/snapshot-not-found.js +27 -0
  29. package/dist/backend-msb/snapshot-not-found.js.map +1 -0
  30. package/dist/core/backend.d.ts +86 -6
  31. package/dist/core/backend.d.ts.map +1 -1
  32. package/dist/core/checkpoint/api.d.ts +129 -0
  33. package/dist/core/checkpoint/api.d.ts.map +1 -0
  34. package/dist/core/checkpoint/api.js +261 -0
  35. package/dist/core/checkpoint/api.js.map +1 -0
  36. package/dist/core/checkpoint/archive.d.ts +52 -0
  37. package/dist/core/checkpoint/archive.d.ts.map +1 -0
  38. package/dist/core/checkpoint/archive.js +134 -0
  39. package/dist/core/checkpoint/archive.js.map +1 -0
  40. package/dist/core/checkpoint/name.d.ts +12 -0
  41. package/dist/core/checkpoint/name.d.ts.map +1 -0
  42. package/dist/core/checkpoint/name.js +17 -0
  43. package/dist/core/checkpoint/name.js.map +1 -0
  44. package/dist/core/checkpoint/ref.d.ts +12 -0
  45. package/dist/core/checkpoint/ref.d.ts.map +1 -0
  46. package/dist/core/checkpoint/ref.js +16 -0
  47. package/dist/core/checkpoint/ref.js.map +1 -0
  48. package/dist/core/checkpoint/registry.d.ts +109 -0
  49. package/dist/core/checkpoint/registry.d.ts.map +1 -0
  50. package/dist/core/checkpoint/registry.js +181 -0
  51. package/dist/core/checkpoint/registry.js.map +1 -0
  52. package/dist/core/checkpoint/tar-cli.d.ts +45 -0
  53. package/dist/core/checkpoint/tar-cli.d.ts.map +1 -0
  54. package/dist/core/checkpoint/tar-cli.js +86 -0
  55. package/dist/core/checkpoint/tar-cli.js.map +1 -0
  56. package/dist/core/errors.d.ts +97 -4
  57. package/dist/core/errors.d.ts.map +1 -1
  58. package/dist/core/errors.js +124 -7
  59. package/dist/core/errors.js.map +1 -1
  60. package/dist/core/generic-container.d.ts +87 -18
  61. package/dist/core/generic-container.d.ts.map +1 -1
  62. package/dist/core/generic-container.js +171 -22
  63. package/dist/core/generic-container.js.map +1 -1
  64. package/dist/core/model.d.ts +25 -8
  65. package/dist/core/model.d.ts.map +1 -1
  66. package/dist/index.d.ts +4 -2
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +4 -2
  69. package/dist/index.js.map +1 -1
  70. package/dist/modules/keycloak.js +1 -1
  71. package/dist/modules/mysql.d.ts.map +1 -1
  72. package/dist/modules/mysql.js +4 -3
  73. package/dist/modules/mysql.js.map +1 -1
  74. package/package.json +1 -1
@@ -0,0 +1,48 @@
1
+ import * as path from "node:path";
2
+ /**
3
+ * True if `stderr` (an `msb snapshot import` non-zero exit) names msb's own
4
+ * "this digest is already imported" signal, as opposed to some other import
5
+ * failure. Observed verbatim against the real msb 0.6.6 binary:
6
+ *
7
+ * ```
8
+ * error: snapshot already exists: <path>
9
+ * ```
10
+ *
11
+ * For a content-addressed archive this IS success — the artifact is already
12
+ * present under that digest either way — so `importCheckpoint` treats it as
13
+ * one rather than surfacing it. Deliberately a substring match on the stable
14
+ * prefix, the same reasoning `isSnapshotNotFoundError` applies to its own
15
+ * wording: the trailing path varies per host and msb has no structured/typed
16
+ * error for this.
17
+ */
18
+ export function isSnapshotAlreadyExistsError(stderr) {
19
+ return stderr.includes("snapshot already exists");
20
+ }
21
+ /**
22
+ * Extracts the digest-dir basename from one `msb snapshot import`
23
+ * invocation's output. Verified against the real msb 0.6.6 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.
34
+ */
35
+ export function parseImportedDigestDirName(output) {
36
+ const lines = output
37
+ .split("\n")
38
+ .map((line) => line.trim())
39
+ .filter((line) => line.length > 0);
40
+ const lastLine = lines.at(-1);
41
+ if (lastLine === undefined) {
42
+ return undefined;
43
+ }
44
+ const match = /(\S+)\s*$/.exec(lastLine);
45
+ const artifactPath = match?.[1];
46
+ return artifactPath === undefined ? undefined : path.basename(artifactPath);
47
+ }
48
+ //# sourceMappingURL=snapshot-import.js.map
@@ -0,0 +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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * One `msb snapshot list --format json` entry, the fields
3
+ * `importCheckpoint`'s presence check actually reads. The current msb
4
+ * release's shape carries more fields than this (created/size/...); only
5
+ * `digest`, `name`, and `artifact_path` (snake_case on the wire) matter
6
+ * here, so everything else is ignored rather than modeled. `digest` itself
7
+ * is never returned as an effective ref (see `confirmDigestDirNamePresent`)
8
+ * — it is read only to skip a malformed/empty entry.
9
+ */
10
+ export interface SnapshotListEntry {
11
+ readonly digest: string | undefined;
12
+ readonly name: string | undefined;
13
+ readonly artifactPath: string | undefined;
14
+ }
15
+ /**
16
+ * Parses `msb snapshot list --format json`'s array-of-objects output.
17
+ * Malformed/non-array JSON resolves to an empty list rather than throwing —
18
+ * the caller (`importCheckpoint`) already turns "digest not found" into its
19
+ * own actionable `BackendError`, so a parse failure here degrading to "found
20
+ * nothing" produces the same class of error rather than a confusing crash
21
+ * one level removed from the actual msb output.
22
+ */
23
+ export declare function parseSnapshotList(json: string): SnapshotListEntry[];
24
+ /**
25
+ * Confirms an imported snapshot's digest-dir basename (e.g.
26
+ * `sha256-b9c0448ee9d54e33`, parsed from `msb snapshot import`'s own
27
+ * output — see `snapshot-import.ts`) actually appears in `msb snapshot
28
+ * list`: an entry whose `name` equals `digestDirName` outright, or whose
29
+ * `artifact_path`'s basename does (`msb snapshot list` was verified to
30
+ * report both shapes depending on how the snapshot was created).
31
+ *
32
+ * Returns `digestDirName` itself once confirmed present — NOT the entry's
33
+ * `digest` field. Live-verified against msb 0.6.6: the full
34
+ * `sha256:<64hex>` digest does not resolve as a snapshot ref at all (`msb
35
+ * snapshot inspect sha256:<full>` fails "snapshot not found" — msb treats
36
+ * it as a literal path). Only the digest-dir name resolves for
37
+ * `inspect`/`rm`/`run --snapshot`, so it — not the `digest` field — is the
38
+ * effective ref `importCheckpoint` must hand back. `undefined` means no
39
+ * entry matched — the caller throws rather than returning an unconfirmed
40
+ * ref.
41
+ */
42
+ export declare function confirmDigestDirNamePresent(entries: readonly SnapshotListEntry[], digestDirName: string): string | undefined;
43
+ //# sourceMappingURL=snapshot-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-list.d.ts","sourceRoot":"","sources":["../../src/backend-msb/snapshot-list.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAkBnE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO5H"}
@@ -0,0 +1,53 @@
1
+ import * as path from "node:path";
2
+ /**
3
+ * Parses `msb snapshot list --format json`'s array-of-objects output.
4
+ * Malformed/non-array JSON resolves to an empty list rather than throwing —
5
+ * the caller (`importCheckpoint`) already turns "digest not found" into its
6
+ * own actionable `BackendError`, so a parse failure here degrading to "found
7
+ * nothing" produces the same class of error rather than a confusing crash
8
+ * one level removed from the actual msb output.
9
+ */
10
+ export function parseSnapshotList(json) {
11
+ let parsed;
12
+ try {
13
+ parsed = JSON.parse(json);
14
+ }
15
+ catch {
16
+ return [];
17
+ }
18
+ if (!Array.isArray(parsed)) {
19
+ return [];
20
+ }
21
+ return parsed.map((raw) => {
22
+ const rec = (typeof raw === "object" && raw !== null ? raw : {});
23
+ return {
24
+ digest: typeof rec["digest"] === "string" ? rec["digest"] : undefined,
25
+ name: typeof rec["name"] === "string" ? rec["name"] : undefined,
26
+ artifactPath: typeof rec["artifact_path"] === "string" ? rec["artifact_path"] : undefined,
27
+ };
28
+ });
29
+ }
30
+ /**
31
+ * Confirms an imported snapshot's digest-dir basename (e.g.
32
+ * `sha256-b9c0448ee9d54e33`, parsed from `msb snapshot import`'s own
33
+ * output — see `snapshot-import.ts`) actually appears in `msb snapshot
34
+ * list`: an entry whose `name` equals `digestDirName` outright, or whose
35
+ * `artifact_path`'s basename does (`msb snapshot list` was verified to
36
+ * report both shapes depending on how the snapshot was created).
37
+ *
38
+ * Returns `digestDirName` itself once confirmed present — NOT the entry's
39
+ * `digest` field. Live-verified against msb 0.6.6: the full
40
+ * `sha256:<64hex>` digest does not resolve as a snapshot ref at all (`msb
41
+ * snapshot inspect sha256:<full>` fails "snapshot not found" — msb treats
42
+ * it as a literal path). Only the digest-dir name resolves for
43
+ * `inspect`/`rm`/`run --snapshot`, so it — not the `digest` field — is the
44
+ * effective ref `importCheckpoint` must hand back. `undefined` means no
45
+ * entry matched — the caller throws rather than returning an unconfirmed
46
+ * ref.
47
+ */
48
+ export function confirmDigestDirNamePresent(entries, digestDirName) {
49
+ const present = entries.some((entry) => entry.digest !== undefined &&
50
+ (entry.name === digestDirName || (entry.artifactPath !== undefined && path.basename(entry.artifactPath) === digestDirName)));
51
+ return present ? digestDirName : undefined;
52
+ }
53
+ //# sourceMappingURL=snapshot-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-list.js","sourceRoot":"","sources":["../../src/backend-msb/snapshot-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAiBlC;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAqB,EAAE;QAC3C,MAAM,GAAG,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAC;QAC5F,OAAO;YACL,MAAM,EAAE,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;YACrE,IAAI,EAAE,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;YAC/D,YAAY,EAAE,OAAO,GAAG,CAAC,eAAe,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS;SAC1F,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,2BAA2B,CAAC,OAAqC,EAAE,aAAqB;IACtG,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAC1B,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,MAAM,KAAK,SAAS;QAC1B,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,aAAa,CAAC,CAAC,CAC9H,CAAC;IACF,OAAO,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * True if `output` (an `msb snapshot inspect <ref>` non-zero exit's stderr)
3
+ * names msb's own "this snapshot does not exist" signal, as opposed to some
4
+ * other probe failure. Observed verbatim against the real msb 0.6.6 binary:
5
+ *
6
+ * ```
7
+ * error: snapshot not found: <path>
8
+ * ```
9
+ *
10
+ * Only this exact framing may resolve `hasCheckpoint` to `false` — every
11
+ * other non-zero exit (a corrupted state db, a permission error, a
12
+ * malformed argument, an msb crash) must propagate as a thrown error
13
+ * instead. `Checkpoints.find` reacts to a `false` probe by best-effort
14
+ * deleting the registry entry as stale, so collapsing an unrelated,
15
+ * possibly transient msb failure into `false` here would silently evict a
16
+ * perfectly valid named checkpoint from the registry — exactly the
17
+ * "best-effort false on probe errors" the SPI's own contract forbids.
18
+ *
19
+ * Deliberately a substring match on the stable prefix rather than the full
20
+ * sentence — the trailing path varies per host, and msb has no structured/
21
+ * typed error for this, the same reasoning `isImageCacheCorruption` and
22
+ * `isMsbStateDbError` apply to their own wordings.
23
+ */
24
+ export declare function isSnapshotNotFoundError(output: string): boolean;
25
+ //# sourceMappingURL=snapshot-not-found.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-not-found.d.ts","sourceRoot":"","sources":["../../src/backend-msb/snapshot-not-found.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE/D"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * True if `output` (an `msb snapshot inspect <ref>` non-zero exit's stderr)
3
+ * names msb's own "this snapshot does not exist" signal, as opposed to some
4
+ * other probe failure. Observed verbatim against the real msb 0.6.6 binary:
5
+ *
6
+ * ```
7
+ * error: snapshot not found: <path>
8
+ * ```
9
+ *
10
+ * Only this exact framing may resolve `hasCheckpoint` to `false` — every
11
+ * other non-zero exit (a corrupted state db, a permission error, a
12
+ * malformed argument, an msb crash) must propagate as a thrown error
13
+ * instead. `Checkpoints.find` reacts to a `false` probe by best-effort
14
+ * deleting the registry entry as stale, so collapsing an unrelated,
15
+ * possibly transient msb failure into `false` here would silently evict a
16
+ * perfectly valid named checkpoint from the registry — exactly the
17
+ * "best-effort false on probe errors" the SPI's own contract forbids.
18
+ *
19
+ * Deliberately a substring match on the stable prefix rather than the full
20
+ * sentence — the trailing path varies per host, and msb has no structured/
21
+ * typed error for this, the same reasoning `isImageCacheCorruption` and
22
+ * `isMsbStateDbError` apply to their own wordings.
23
+ */
24
+ export function isSnapshotNotFoundError(output) {
25
+ return output.includes("snapshot not found");
26
+ }
27
+ //# sourceMappingURL=snapshot-not-found.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-not-found.js","sourceRoot":"","sources":["../../src/backend-msb/snapshot-not-found.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAC/C,CAAC"}
@@ -64,10 +64,20 @@ export interface BackendCapabilities {
64
64
  readonly hardwareIsolated: boolean;
65
65
  /**
66
66
  * `true` when the backend can checkpoint/restore a sandbox's state
67
- * (docker: commit-to-image; msb: no upstream microVM snapshot support
68
- * yet). `GenericContainer.checkpoint()` demands `true`.
67
+ * (docker: commit-to-image; msb: disk snapshot via `msb snapshot`).
68
+ * `GenericContainer.checkpoint()` demands `true`.
69
69
  */
70
70
  readonly checkpoint: boolean;
71
+ /**
72
+ * `true` when a `checkpoint()` call on this backend restarts the
73
+ * sandbox's workload as a side effect of capturing state (msb: the
74
+ * stop/snapshot/reboot cycle boots a fresh microVM) — `false` when the
75
+ * sandbox is undisturbed (docker: commit-to-image never touches the
76
+ * running container). `GenericContainer.checkpoint()` re-runs the
77
+ * container's own wait strategy before returning exactly when this is
78
+ * `true`, so a caller never gets back a false-ready container.
79
+ */
80
+ readonly checkpointRestartsWorkload: boolean;
71
81
  }
72
82
  /**
73
83
  * The one interface every container backend implements. Host ports arrive
@@ -90,14 +100,70 @@ export interface SandboxBackend {
90
100
  /** Best-effort removal of the backend-native resource; callers swallow failures during teardown. */
91
101
  remove(handle: SandboxHandle): Promise<void>;
92
102
  /**
93
- * Commits `handle`'s current filesystem to a new image tagged `imageRef` —
103
+ * Captures `handle`'s current state under `ref` —
94
104
  * `GenericContainer.checkpoint()`'s backend call, gated on
95
105
  * `capabilities.checkpoint` BEFORE this is ever reached, so an
96
106
  * unsupported backend never has to implement this for real (it may throw
97
- * defensively). Docker: the engine's commit endpoint. Never called on a
98
- * backend whose `capabilities.checkpoint` is `false`.
107
+ * defensively). Docker: commits the running container to image `ref`,
108
+ * undisturbed. Microsandbox: stop the sandbox, `msb snapshot create` a
109
+ * disk snapshot named `ref`, then start the sandbox back up — the
110
+ * workload restarts, which is why `capabilities.checkpointRestartsWorkload`
111
+ * exists. Never called on a backend whose `capabilities.checkpoint` is
112
+ * `false`.
113
+ */
114
+ createCheckpoint(handle: SandboxHandle, ref: string): Promise<void>;
115
+ /**
116
+ * Best-effort removal of a checkpoint identified by `ref` (docker: `rmi`;
117
+ * microsandbox: `msb snapshot rm`) — "not found" is success, the same
118
+ * contract as `removeByName`. SPI-only: there is no public
119
+ * `GenericContainer` method for this, only documented CLI one-liners for
120
+ * end users; it exists so tests can keep shared CI state clean.
121
+ */
122
+ removeCheckpoint(ref: string): Promise<void>;
123
+ /**
124
+ * Probes whether a checkpoint artifact identified by `ref` still exists —
125
+ * docker: image inspect; microsandbox: `msb snapshot inspect <ref>` exit
126
+ * code. `Checkpoints.find`'s only caller: it never probes an entry
127
+ * recorded under a DIFFERENT backend than the one this is called on, so in
128
+ * practice this is only ever invoked on a backend whose
129
+ * `capabilities.checkpoint` is `true`. A backend that never supports
130
+ * checkpoints at all may implement this by throwing
131
+ * `UnsupportedByBackendError`, the same defensive-throw convention
132
+ * `createCheckpoint` documents for that case. A probe FAILURE (the
133
+ * underlying call itself errors) must propagate — only a confirmed
134
+ * "does not exist" may resolve `false`; best-effort `false` on an error is
135
+ * not allowed.
99
136
  */
100
- commitToImage(handle: SandboxHandle, imageRef: string): Promise<void>;
137
+ hasCheckpoint(ref: string): Promise<boolean>;
138
+ /**
139
+ * Writes this checkpoint's backend payload to `destFile` — the artifact
140
+ * step of `Checkpoints.exportTo`, byte-for-byte what the backend's own CLI
141
+ * produces (docker: `docker save -o <destFile> <ref>`; microsandbox:
142
+ * `msb snapshot export <ref> <destFile>`, never `--with-image` — see the
143
+ * checkpoints guide for why). Only ever called once the generic layer has
144
+ * already confirmed `ref` belongs to the ACTIVE backend and probed it
145
+ * exists via `hasCheckpoint`; a failure surfaces the underlying tool's
146
+ * stderr in a `BackendError`, the same convention `copyToContainer` uses.
147
+ */
148
+ exportCheckpoint(ref: string, destFile: string): Promise<void>;
149
+ /**
150
+ * Materializes an exported archive's backend payload from `srcFile` and
151
+ * returns the EFFECTIVE ref to use from here on — not necessarily `ref`
152
+ * itself. docker preserves the original tag on `docker load`, so its
153
+ * effective ref IS `ref`; microsandbox's `snapshot import` writes under a
154
+ * digest-derived DIRECTORY NAME (e.g. `sha256-b9c0448ee9d54e33`) it never
155
+ * lets the caller choose, so its effective ref is that directory name,
156
+ * confirmed present via `snapshot list --format json` — never the full
157
+ * `sha256:<64hex>` digest, which does not resolve as a snapshot ref at
158
+ * all. An already-exists failure for a content-addressed archive is
159
+ * treated as success. `ref` is the archive's own recorded ref (from
160
+ * `checkpoint.json`), passed through for backends (docker) that have no
161
+ * new ref to derive. Only ever called once the generic layer has already
162
+ * validated the archive's `checkpoint.json` (version, name, backend)
163
+ * against the active backend; any failure other than "already imported"
164
+ * surfaces the underlying tool's stderr in a `BackendError`.
165
+ */
166
+ importCheckpoint(srcFile: string, ref: string): Promise<string>;
101
167
  /**
102
168
  * Best-effort stop+remove of a sandbox identified by NAME rather than a
103
169
  * `SandboxHandle` — the reaping ledger only ever stores names (it must be
@@ -137,6 +203,20 @@ export interface SandboxBackend {
137
203
  removeNetwork(networkId: string): Promise<void>;
138
204
  /** Default no-op: docker relies on native networks. Only an emulating backend overrides it. */
139
205
  installNetworkLinks(handle: SandboxHandle, links: ReadonlyArray<NetworkLink>): Promise<void>;
206
+ /**
207
+ * Copies a host file or directory into the guest at `containerPath` — the
208
+ * TRANSFER step only. `GenericContainer.copyFileToContainer()` owns the
209
+ * running-check, the absolute-path check, and the `mkdir -p` pre-step (via
210
+ * `exec`) before this is ever called; this method does only the copy
211
+ * itself. `cp -r`-style destination naming: copying a directory to an
212
+ * absent destination path produces that path as a copy of the source's
213
+ * CONTENTS, not the source nested one level down — both backends' own
214
+ * copy tools already behave this way. A failure must carry the
215
+ * underlying tool's stderr in a `BackendError`, never a silent success.
216
+ */
217
+ copyToContainer(handle: SandboxHandle, hostPath: string, containerPath: string): Promise<void>;
218
+ /** The reverse direction of `copyToContainer` — see its own doc for the shared contract (transfer only, `cp -r`-style naming, stderr on failure). */
219
+ copyFromContainer(handle: SandboxHandle, containerPath: string, hostPath: string): Promise<void>;
140
220
  /** Best-effort teardown of backend-owned resources (sockets, child processes). */
141
221
  close(): Promise<void>;
142
222
  /**
@@ -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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"}
@@ -0,0 +1,129 @@
1
+ import type { Checkpoint } from "../model.js";
2
+ /**
3
+ * Rediscovers a named checkpoint written by an earlier `checkpoint(name)`
4
+ * call — in this process or an entirely different one, since the registry
5
+ * lives on disk under the shared rightsize cache directory. No entry for
6
+ * `name` resolves to `undefined`. A corrupt entry is treated the same as
7
+ * absent, with a best-effort delete of the bad file.
8
+ *
9
+ * When the entry's own recorded backend matches the CURRENTLY active
10
+ * backend, the underlying artifact is probed via the backend's
11
+ * `hasCheckpoint` SPI before this resolves — an artifact that's gone (removed
12
+ * by hand, or by something outside this library) makes the entry stale: it's
13
+ * best-effort deleted and this resolves to `undefined`, the same as if it
14
+ * had never existed. A probe FAILURE (the backend call itself throws) is
15
+ * never swallowed into a `false` — only a confirmed "does not exist"
16
+ * resolves that way, so a probe failure propagates out of this call.
17
+ *
18
+ * When the entry's recorded backend DIFFERS from the active one, this
19
+ * returns the entry unprobed — an msb ref means nothing to a docker probe
20
+ * and vice versa. `GenericContainer.fromCheckpoint(cp).start()`'s own
21
+ * `CheckpointBackendMismatchError` gate stays the sole authority for that
22
+ * mismatch; this function must not force-resolve a backend the host may not
23
+ * even have.
24
+ *
25
+ * `name` is validated against `CHECKPOINT_NAME_PATTERN` before anything else
26
+ * — including before the registry file is even looked up — so a `name`
27
+ * carrying `../` segments can never reach path construction; an invalid name
28
+ * throws `InvalidCheckpointNameError` and touches no file.
29
+ */
30
+ export declare function find(name: string): Promise<Checkpoint | undefined>;
31
+ /**
32
+ * Every named checkpoint currently in the registry — registry contents
33
+ * only, never probed against a backend (unlike `find`), so a stale entry
34
+ * whose artifact is gone still appears here until something calls `find` or
35
+ * `remove` on it. A corrupt entry is silently skipped, never removed (only
36
+ * `find`/`remove` clean those up, since `list` never resolves a single name
37
+ * the caller could target for a retry).
38
+ */
39
+ export declare function list(): Promise<Checkpoint[]>;
40
+ /**
41
+ * Deletes a named checkpoint: best-effort removal of the backend artifact
42
+ * (only when the entry's recorded backend matches the currently active
43
+ * one — this call never touches a backend that isn't active) plus the
44
+ * registry file, regardless of order of failure in either. Idempotent and
45
+ * always best-effort: "not found" anywhere (no registry entry at all) is
46
+ * success, reported as `false`; an existing entry — valid or corrupt —
47
+ * reports `true` once its registry file is gone.
48
+ *
49
+ * When the entry's recorded backend DIFFERS from the currently active one,
50
+ * only the registry record is deleted — the underlying artifact (the docker
51
+ * image, or the microsandbox snapshot) is left on disk PERMANENTLY, since
52
+ * this call never touches a backend that isn't active. Nothing in this
53
+ * library reclaims it automatically — and once the record is gone, a later
54
+ * `remove(name)` finds nothing to act on. Remove a checkpoint under its
55
+ * creating backend in the first place, or clean the leftover artifact
56
+ * directly with that backend's own CLI one-liner (see the
57
+ * [checkpoints guide](/guide/checkpoints#cleanup-checkpoints-are-not-auto-reaped)).
58
+ *
59
+ * `name` is validated against `CHECKPOINT_NAME_PATTERN` before anything else
60
+ * — including before the registry file is even looked up — so a `name`
61
+ * carrying `../` segments can never reach path construction; an invalid name
62
+ * throws `InvalidCheckpointNameError` and touches no file.
63
+ */
64
+ export declare function remove(name: string): Promise<boolean>;
65
+ /**
66
+ * Bundles `cp` into a self-describing archive at `destPath`: `checkpoint.json`
67
+ * (the pinned metadata — format version, this checkpoint's name if it was
68
+ * ever registered under one, ref, backend, creation time, and spec) plus an
69
+ * `artifact` member holding the backend's own payload, byte-for-byte what
70
+ * `SandboxBackend.exportCheckpoint` produces. See the
71
+ * [checkpoints guide](/guide/checkpoints#moving-checkpoints-between-machines)
72
+ * for the full CI-cache pattern this exists for.
73
+ *
74
+ * Requires the ACTIVE backend to equal `cp.backend` — the same
75
+ * `CheckpointBackendMismatchError` `fromCheckpoint(cp).start()` throws —
76
+ * before any backend or filesystem work. Then probes the artifact still
77
+ * exists via `hasCheckpoint`: exporting a stale checkpoint throws
78
+ * `CheckpointArtifactMissingError` rather than producing a broken archive.
79
+ * Only once both checks pass does this stage the export in a fresh unique
80
+ * temp directory (removed in a `finally` regardless of outcome) and tar it
81
+ * into `destPath` (parent directories created; a pre-existing file there is
82
+ * overwritten). Works on an ephemeral (unnamed) checkpoint too — the
83
+ * resulting archive just carries `name: null`.
84
+ */
85
+ export declare function exportTo(cp: Checkpoint, destPath: string): Promise<void>;
86
+ /**
87
+ * The inverse of `exportTo`: extracts `srcPath`, validates its
88
+ * `checkpoint.json` (format version, `name` against
89
+ * `CHECKPOINT_NAME_PATTERN` when non-null, backend against the ACTIVE
90
+ * backend — a `MalformedCheckpointArchiveError` or `CheckpointBackendMismatchError`
91
+ * either way, before any backend call or registry write), then hands the
92
+ * extracted `artifact` to `SandboxBackend.importCheckpoint`, which
93
+ * materializes it and returns the EFFECTIVE ref (docker: the same `ref` the
94
+ * archive recorded; microsandbox: the digest `snapshot import` actually
95
+ * assigned it — never necessarily the archive's own `ref`).
96
+ *
97
+ * A NAMED archive (`name` non-null) gets replace semantics matching
98
+ * `checkpoint(name)`: if a registry entry already exists for that name under
99
+ * a DIFFERENT ref and its recorded backend matches the active one, its old
100
+ * artifact is best-effort removed first (never a foreign-backend
101
+ * `removeCheckpoint` call — the same gate `remove()` applies); the registry
102
+ * entry is then written (or overwritten) with the effective ref. A NAMELESS
103
+ * archive writes no registry entry at all — the returned `Checkpoint` is
104
+ * purely ephemeral, the same as an unnamed `checkpoint()` call's result.
105
+ * Either way, the returned `Checkpoint` restores via the existing
106
+ * `fromCheckpoint()` path with zero changes — refs are opaque throughout
107
+ * this library.
108
+ */
109
+ export declare function importFrom(srcPath: string): Promise<Checkpoint>;
110
+ /**
111
+ * The library's entry point for rediscovering NAMED checkpoints across
112
+ * processes — see the [checkpoints guide](/guide/checkpoints#reusing-checkpoints-across-runs)
113
+ * for the `find(...) ?? seed()` first-run/later-run pattern this exists to
114
+ * support. Unnamed `checkpoint()` calls never appear here; only a
115
+ * `checkpoint(name)` call writes a registry entry these functions can find.
116
+ */
117
+ export declare const Checkpoints: {
118
+ /** Rediscovers a named checkpoint — see `find` above. */
119
+ find: typeof find;
120
+ /** Every named checkpoint currently in the registry — see `list` above. */
121
+ list: typeof list;
122
+ /** Deletes a named checkpoint — see `remove` above. */
123
+ remove: typeof remove;
124
+ /** Bundles a checkpoint into a portable archive — see `exportTo` above. */
125
+ exportTo: typeof exportTo;
126
+ /** Materializes a portable archive on this machine — see `importFrom` above. */
127
+ importFrom: typeof importFrom;
128
+ };
129
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/core/checkpoint/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAoB9C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAwBxE;AAED;;;;;;;GAOG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAWlD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB3D;AAqBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB9E;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqCrE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW;IACtB,yDAAyD;;IAEzD,2EAA2E;;IAE3E,uDAAuD;;IAEvD,2EAA2E;;IAE3E,gFAAgF;;CAEjF,CAAC"}