@cotal-ai/cli 0.11.6 → 0.12.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 (58) hide show
  1. package/dist/commands/backup.d.ts +13 -0
  2. package/dist/commands/backup.d.ts.map +1 -0
  3. package/dist/commands/backup.js +443 -0
  4. package/dist/commands/backup.js.map +1 -0
  5. package/dist/commands/channels.d.ts +10 -0
  6. package/dist/commands/channels.d.ts.map +1 -1
  7. package/dist/commands/channels.js.map +1 -1
  8. package/dist/commands/clean.d.ts +12 -2
  9. package/dist/commands/clean.d.ts.map +1 -1
  10. package/dist/commands/clean.js +161 -28
  11. package/dist/commands/clean.js.map +1 -1
  12. package/dist/commands/down.d.ts +5 -0
  13. package/dist/commands/down.d.ts.map +1 -1
  14. package/dist/commands/down.js +323 -5
  15. package/dist/commands/down.js.map +1 -1
  16. package/dist/commands/spawn.d.ts +4 -0
  17. package/dist/commands/spawn.d.ts.map +1 -1
  18. package/dist/commands/spawn.js +43 -23
  19. package/dist/commands/spawn.js.map +1 -1
  20. package/dist/commands/status.d.ts.map +1 -1
  21. package/dist/commands/status.js +3 -2
  22. package/dist/commands/status.js.map +1 -1
  23. package/dist/commands/up.d.ts +12 -0
  24. package/dist/commands/up.d.ts.map +1 -1
  25. package/dist/commands/up.js +1149 -193
  26. package/dist/commands/up.js.map +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +19 -4
  29. package/dist/index.js.map +1 -1
  30. package/dist/lib/backup-artifact.d.ts +50 -0
  31. package/dist/lib/backup-artifact.d.ts.map +1 -0
  32. package/dist/lib/backup-artifact.js +290 -0
  33. package/dist/lib/backup-artifact.js.map +1 -0
  34. package/dist/lib/delivery-proc.d.ts +7 -2
  35. package/dist/lib/delivery-proc.d.ts.map +1 -1
  36. package/dist/lib/delivery-proc.js +29 -19
  37. package/dist/lib/delivery-proc.js.map +1 -1
  38. package/dist/lib/endpoint-cut.d.ts +5 -0
  39. package/dist/lib/endpoint-cut.d.ts.map +1 -0
  40. package/dist/lib/endpoint-cut.js +53 -0
  41. package/dist/lib/endpoint-cut.js.map +1 -0
  42. package/dist/lib/isolated-broker.d.ts +70 -0
  43. package/dist/lib/isolated-broker.d.ts.map +1 -0
  44. package/dist/lib/isolated-broker.js +427 -0
  45. package/dist/lib/isolated-broker.js.map +1 -0
  46. package/dist/lib/maintenance-files.d.ts +10 -0
  47. package/dist/lib/maintenance-files.d.ts.map +1 -0
  48. package/dist/lib/maintenance-files.js +60 -0
  49. package/dist/lib/maintenance-files.js.map +1 -0
  50. package/dist/lib/manager-proc.d.ts +4 -0
  51. package/dist/lib/manager-proc.d.ts.map +1 -1
  52. package/dist/lib/manager-proc.js +2 -0
  53. package/dist/lib/manager-proc.js.map +1 -1
  54. package/dist/lib/restore.d.ts +52 -0
  55. package/dist/lib/restore.d.ts.map +1 -0
  56. package/dist/lib/restore.js +797 -0
  57. package/dist/lib/restore.js.map +1 -0
  58. package/package.json +7 -4
@@ -0,0 +1,290 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { closeSync, constants, fstatSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, readSync, readdirSync, renameSync, rmSync, statSync, writeFileSync, writeSync, } from "node:fs";
3
+ import { dirname, isAbsolute, join, resolve } from "node:path";
4
+ import { hardenPrivate, } from "@cotal-ai/core";
5
+ export const BACKUP_MANIFEST_FORMAT = "cotal-space-backup/v1";
6
+ const MAX_MANIFEST_BYTES = 1024 * 1024;
7
+ const MAX_CHECKPOINT_BYTES = 16 * 1024 * 1024;
8
+ const COPY_BUFFER_BYTES = 1024 * 1024;
9
+ function fsyncDirectory(path) {
10
+ let fd;
11
+ try {
12
+ fd = openSync(path, constants.O_RDONLY);
13
+ fsyncSync(fd);
14
+ }
15
+ catch (error) {
16
+ if (process.platform !== "win32")
17
+ throw error;
18
+ }
19
+ finally {
20
+ if (fd !== undefined)
21
+ closeSync(fd);
22
+ }
23
+ }
24
+ function safeFileName(name) {
25
+ if (!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,200}$/.test(name) || name === "manifest.json")
26
+ throw new Error(`invalid backup artifact file name ${JSON.stringify(name)}`);
27
+ }
28
+ function writeAll(fd, chunk) {
29
+ let offset = 0;
30
+ while (offset < chunk.byteLength) {
31
+ const written = writeSync(fd, chunk, offset, chunk.byteLength - offset);
32
+ if (written <= 0)
33
+ throw new Error("backup artifact write made no progress");
34
+ offset += written;
35
+ }
36
+ }
37
+ function sameDirectoryIdentity(path, identity) {
38
+ try {
39
+ const stat = lstatSync(path, { bigint: true });
40
+ return stat.isDirectory() && !stat.isSymbolicLink() && stat.dev === identity.dev && stat.ino === identity.ino;
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ }
46
+ export function createArtifactWriter(destination) {
47
+ const directory = resolve(destination);
48
+ try {
49
+ mkdirSync(directory, { mode: 0o700 });
50
+ }
51
+ catch (error) {
52
+ if (error.code === "EEXIST")
53
+ throw new Error(`backup destination already exists: ${directory}`);
54
+ throw error;
55
+ }
56
+ let identity;
57
+ try {
58
+ // The artifact holds whole-stream snapshots (chat, DMs) — the most sensitive bytes we write.
59
+ // `hardenPrivate` reasserts 0700 on POSIX and sets the win32 ACL, where the create mode above is
60
+ // a no-op; the dir grant is inheritable, so every file written below is born private too.
61
+ hardenPrivate(directory, "dir");
62
+ fsyncDirectory(dirname(directory));
63
+ const stat = lstatSync(directory, { bigint: true });
64
+ identity = { dev: stat.dev, ino: stat.ino };
65
+ }
66
+ catch (error) {
67
+ // The directory was exclusively created by this call and nothing has been written into it:
68
+ // a failed post-create step must not leak it and block a same-destination retry.
69
+ try {
70
+ const current = lstatSync(directory, { bigint: true });
71
+ if (current.isDirectory() && !current.isSymbolicLink())
72
+ rmSync(directory, { recursive: true });
73
+ }
74
+ catch { /* already absent */ }
75
+ throw error;
76
+ }
77
+ let published = false;
78
+ return {
79
+ directory,
80
+ identity,
81
+ async writeFile(name, kind, source, stream) {
82
+ if (published)
83
+ throw new Error("backup manifest is already published");
84
+ safeFileName(name);
85
+ const path = join(directory, name);
86
+ const fd = openSync(path, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
87
+ const hash = createHash("sha256");
88
+ let size = 0;
89
+ try {
90
+ const write = (chunk) => {
91
+ writeAll(fd, chunk);
92
+ hash.update(chunk);
93
+ size += chunk.byteLength;
94
+ };
95
+ if (typeof source === "string")
96
+ write(Buffer.from(source));
97
+ else if (source instanceof Uint8Array)
98
+ write(source);
99
+ else
100
+ for await (const chunk of source)
101
+ write(chunk);
102
+ fsyncSync(fd);
103
+ if (fstatSync(fd).size !== size)
104
+ throw new Error(`backup artifact size mismatch after writing ${name}`);
105
+ }
106
+ finally {
107
+ closeSync(fd);
108
+ }
109
+ return { path: name, size, sha256: hash.digest("hex"), kind, ...(stream ? { stream } : {}) };
110
+ },
111
+ publish(input, files) {
112
+ if (published)
113
+ throw new Error("backup manifest is already published");
114
+ const manifest = {
115
+ format: BACKUP_MANIFEST_FORMAT,
116
+ createdAt: new Date().toISOString(),
117
+ ...input,
118
+ files: [...files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0),
119
+ };
120
+ // The manifest is the completion marker, so it must appear ATOMICALLY: durable bytes first
121
+ // at a temp name, then one rename. A crash can never leave a truncated manifest.json.
122
+ const path = join(directory, "manifest.json");
123
+ const tmp = join(directory, `manifest.json.${process.pid}.${randomUUID()}.tmp`);
124
+ const fd = openSync(tmp, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
125
+ try {
126
+ writeFileSync(fd, `${JSON.stringify(manifest, null, 2)}\n`);
127
+ fsyncSync(fd);
128
+ closeSync(fd);
129
+ }
130
+ catch (error) {
131
+ try {
132
+ closeSync(fd);
133
+ }
134
+ catch { /* already closed */ }
135
+ try {
136
+ rmSync(tmp);
137
+ }
138
+ catch { /* best effort for the exclusively-created temp */ }
139
+ throw error;
140
+ }
141
+ renameSync(tmp, path);
142
+ fsyncDirectory(directory);
143
+ published = true;
144
+ return manifest;
145
+ },
146
+ cleanup() {
147
+ if (published || !sameDirectoryIdentity(directory, identity))
148
+ return;
149
+ rmSync(directory, { recursive: true });
150
+ fsyncDirectory(dirname(directory));
151
+ },
152
+ };
153
+ }
154
+ function parseManifest(path) {
155
+ const stat = lstatSync(path);
156
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_MANIFEST_BYTES)
157
+ throw new Error(`backup manifest is not a bounded regular file: ${path}`);
158
+ const value = JSON.parse(readFileSync(path, "utf8"));
159
+ if (value.format !== BACKUP_MANIFEST_FORMAT)
160
+ throw new Error(`unsupported backup format ${JSON.stringify(value.format)}`);
161
+ if (!value.space || !["full", "registry"].includes(value.selection) || !["auth", "open", "user"].includes(value.mode))
162
+ throw new Error("backup manifest has invalid space, selection, or mode");
163
+ if (!Array.isArray(value.files) || !Array.isArray(value.streams) || typeof value.checkpoints !== "string")
164
+ throw new Error("backup manifest has invalid inventory");
165
+ safeFileName(value.checkpoints);
166
+ for (const stream of value.streams) {
167
+ if (!stream || typeof stream !== "object" || typeof stream.stream !== "string" || typeof stream.snapshot !== "string")
168
+ throw new Error("backup manifest has an invalid stream record");
169
+ safeFileName(stream.snapshot);
170
+ }
171
+ const keys = Object.keys(value).sort().join(",");
172
+ const expectedKeys = ["authority", "checkpoints", "createdAt", "files", "format", "mode", "selection", "source", "space", "streams"]
173
+ .filter((key) => key !== "authority" || value.authority !== undefined).sort().join(",");
174
+ if (keys !== expectedKeys || !Number.isFinite(Date.parse(value.createdAt)))
175
+ throw new Error("backup manifest has unknown fields or an invalid timestamp");
176
+ if (!value.source || typeof value.source.path !== "string" || !isAbsolute(value.source.path) ||
177
+ !/^\d+$/.test(value.source.dev) || !/^\d+$/.test(value.source.ino) ||
178
+ !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value.source.generation))
179
+ throw new Error("backup manifest has an invalid source identity");
180
+ return value;
181
+ }
182
+ function copyPinnedFile(source, destination, expected) {
183
+ const pathStat = lstatSync(source);
184
+ if (!pathStat.isFile() || pathStat.isSymbolicLink())
185
+ throw new Error(`backup input is not a real file: ${source}`);
186
+ const noFollow = process.platform === "win32" ? 0 : constants.O_NOFOLLOW;
187
+ const sourceFd = openSync(source, constants.O_RDONLY | noFollow);
188
+ let destinationFd;
189
+ const hash = createHash("sha256");
190
+ let size = 0;
191
+ try {
192
+ const before = fstatSync(sourceFd, { bigint: true });
193
+ if (!before.isFile())
194
+ throw new Error(`backup input is not a regular file: ${source}`);
195
+ destinationFd = openSync(destination, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
196
+ const buffer = Buffer.allocUnsafe(COPY_BUFFER_BYTES);
197
+ for (;;) {
198
+ const count = readSync(sourceFd, buffer, 0, buffer.length, null);
199
+ if (count === 0)
200
+ break;
201
+ const chunk = buffer.subarray(0, count);
202
+ writeAll(destinationFd, chunk);
203
+ hash.update(chunk);
204
+ size += count;
205
+ if (size > expected.size)
206
+ throw new Error(`backup input grew while staging: ${source}`);
207
+ }
208
+ const after = fstatSync(sourceFd, { bigint: true });
209
+ if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs)
210
+ throw new Error(`backup input changed while staging: ${source}`);
211
+ if (size !== expected.size || hash.digest("hex") !== expected.sha256)
212
+ throw new Error(`backup input size or SHA-256 mismatch: ${source}`);
213
+ fsyncSync(destinationFd);
214
+ if (fstatSync(destinationFd).size !== size)
215
+ throw new Error(`staged backup size mismatch after writing ${destination}`);
216
+ }
217
+ finally {
218
+ if (destinationFd !== undefined)
219
+ closeSync(destinationFd);
220
+ closeSync(sourceFd);
221
+ }
222
+ }
223
+ /** Validate exact names and pin verified bytes into a private attempt directory before any mutation. */
224
+ export function stageArtifact(artifactPath, parent) {
225
+ const artifact = resolve(artifactPath);
226
+ const artifactStat = lstatSync(artifact);
227
+ if (!artifactStat.isDirectory() || artifactStat.isSymbolicLink())
228
+ throw new Error(`backup artifact is not a real directory: ${artifact}`);
229
+ const manifest = parseManifest(join(artifact, "manifest.json"));
230
+ const expected = new Set(["manifest.json", ...manifest.files.map((file) => file.path)]);
231
+ const actual = readdirSync(artifact);
232
+ if (new Set(actual).size !== actual.length || actual.some((name) => !expected.has(name)) || actual.length !== expected.size)
233
+ throw new Error("backup artifact contains extra, duplicate, or missing files");
234
+ if (new Set(manifest.files.map((file) => file.path)).size !== manifest.files.length)
235
+ throw new Error("backup artifact file inventory contains duplicate paths");
236
+ for (const file of manifest.files) {
237
+ safeFileName(file.path);
238
+ if (!Number.isSafeInteger(file.size) || file.size < 0 || !/^[0-9a-f]{64}$/.test(file.sha256) ||
239
+ !["snapshot", "checkpoints"].includes(file.kind) ||
240
+ (file.kind === "snapshot") !== (typeof file.stream === "string"))
241
+ throw new Error(`backup file metadata is invalid: ${file.path}`);
242
+ if (file.kind === "checkpoints" && file.size > MAX_CHECKPOINT_BYTES)
243
+ throw new Error(`backup checkpoints exceed ${MAX_CHECKPOINT_BYTES} bytes`);
244
+ }
245
+ const checkpointFiles = manifest.files.filter((file) => file.kind === "checkpoints");
246
+ if (checkpointFiles.length !== 1 || checkpointFiles[0].path !== manifest.checkpoints)
247
+ throw new Error("backup manifest must name exactly one checkpoints file");
248
+ const snapshotFiles = new Map(manifest.files.filter((file) => file.kind === "snapshot").map((file) => [file.path, file.stream]));
249
+ if (snapshotFiles.size !== manifest.streams.length || manifest.streams.some((stream) => snapshotFiles.get(stream.snapshot) !== stream.stream))
250
+ throw new Error("backup stream records do not match snapshot file metadata");
251
+ const parentPath = realpathSync.native(resolve(parent));
252
+ const parentStat = lstatSync(parentPath, { bigint: true });
253
+ if (!parentStat.isDirectory() || parentStat.isSymbolicLink())
254
+ throw new Error(`restore staging parent is not a real directory: ${parentPath}`);
255
+ const parentIdentity = { dev: parentStat.dev, ino: parentStat.ino };
256
+ const directory = join(parentPath, `.cotal-restore-stage-${randomUUID()}`);
257
+ mkdirSync(directory, { mode: 0o700 });
258
+ hardenPrivate(directory, "dir"); // staged snapshots are the same secret bytes — private on win32 too
259
+ const identityStat = lstatSync(directory, { bigint: true });
260
+ const identity = { dev: identityStat.dev, ino: identityStat.ino };
261
+ try {
262
+ for (const file of manifest.files)
263
+ copyPinnedFile(join(artifact, file.path), join(directory, file.path), file);
264
+ writeFileSync(join(directory, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`, { flag: "wx", mode: 0o600 });
265
+ fsyncDirectory(directory);
266
+ }
267
+ catch (error) {
268
+ if (sameDirectoryIdentity(parentPath, parentIdentity) && sameDirectoryIdentity(directory, identity))
269
+ rmSync(directory, { recursive: true });
270
+ throw error;
271
+ }
272
+ return {
273
+ manifest,
274
+ directory,
275
+ cleanup() {
276
+ if (sameDirectoryIdentity(parentPath, parentIdentity) && sameDirectoryIdentity(directory, identity))
277
+ rmSync(directory, { recursive: true });
278
+ },
279
+ };
280
+ }
281
+ export function readStagedCheckpoints(staged) {
282
+ const value = JSON.parse(readFileSync(join(staged.directory, staged.manifest.checkpoints), "utf8"));
283
+ if (!Array.isArray(value))
284
+ throw new Error("backup checkpoints must be an array");
285
+ return value;
286
+ }
287
+ export function snapshotFileName(stream) {
288
+ return `stream-${createHash("sha256").update(stream).digest("hex").slice(0, 24)}.snap`;
289
+ }
290
+ //# sourceMappingURL=backup-artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup-artifact.js","sourceRoot":"","sources":["../../src/lib/backup-artifact.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@ type Opts = {
4
4
  spawn?: string[];
5
5
  runtime?: string;
6
6
  launch?: string;
7
+ resumeAttempt?: string;
8
+ resumeCommitToken?: string;
7
9
  };
8
10
  /** True if the delivery daemon we started for this folder is still running (pid file + liveness). */
9
11
  export declare function deliveryUp(): boolean;
@@ -23,8 +25,11 @@ export declare function startDeliveryDetached(o?: Opts): number;
23
25
  export declare function ensureDelivery(o?: Opts): Promise<{
24
26
  running: boolean;
25
27
  }>;
26
- /** Stop the detached delivery daemon if we started one, and drop its creds file. */
27
- export declare function stopDelivery(): void;
28
+ /** Stop the detached delivery daemon if we started one, and drop its creds from the store. The pid
29
+ * kill runs even if the creds delete fails (finally) — a delete error must never leave the daemon
30
+ * alive to outlive the teardown and reattach to a restarted broker; the error still propagates
31
+ * after the kill so the caller can surface it. */
32
+ export declare function stopDelivery(): Promise<void>;
28
33
  /** Bring up the control plane in the correct cutover order: OLD-manager preflight → delivery daemon
29
34
  * (auth only, fails closed on a live old manager) → manager (lifecycle, writes the delivery-aware
30
35
  * marker). The manager no longer depends on the daemon (it hosts no Plane-3), so the daemon is started
@@ -1 +1 @@
1
- {"version":3,"file":"delivery-proc.d.ts","sourceRoot":"","sources":["../../src/lib/delivery-proc.ts"],"names":[],"mappings":"AAmBA,KAAK,IAAI,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAWrG,qGAAqG;AACrG,wBAAgB,UAAU,IAAI,OAAO,CAKpC;AAeD;;0GAE0G;AAC1G,wBAAgB,8BAA8B,IAAI,IAAI,CAKrD;AAED;;8FAE8F;AAC9F,wBAAgB,qBAAqB,CAAC,CAAC,GAAE,IAAS,GAAG,MAAM,CAkB1D;AAED;;;;sFAIsF;AACtF,wBAAsB,cAAc,CAAC,CAAC,GAAE,IAAS,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA8BhF;AAED,oFAAoF;AACpF,wBAAgB,YAAY,IAAI,IAAI,CAanC;AAED;;;;+FAI+F;AAC/F,wBAAsB,kBAAkB,CAAC,CAAC,GAAE,IAAS,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAIpF"}
1
+ {"version":3,"file":"delivery-proc.d.ts","sourceRoot":"","sources":["../../src/lib/delivery-proc.ts"],"names":[],"mappings":"AAmBA,KAAK,IAAI,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAWzJ,qGAAqG;AACrG,wBAAgB,UAAU,IAAI,OAAO,CAKpC;AAeD;;0GAE0G;AAC1G,wBAAgB,8BAA8B,IAAI,IAAI,CAKrD;AAED;;8FAE8F;AAC9F,wBAAgB,qBAAqB,CAAC,CAAC,GAAE,IAAS,GAAG,MAAM,CAkB1D;AAED;;;;sFAIsF;AACtF,wBAAsB,cAAc,CAAC,CAAC,GAAE,IAAS,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA+BhF;AAED;;;mDAGmD;AACnD,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBlD;AAED;;;;+FAI+F;AAC/F,wBAAsB,kBAAkB,CAAC,CAAC,GAAE,IAAS,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAIpF"}
@@ -1,13 +1,15 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { existsSync, openSync, closeSync, writeFileSync, readFileSync, rmSync } from "node:fs";
3
- import { DEFAULT_SERVER, mintCreds, mkSecretDir, newIdentity, waitForDeliveryLease, writeSecretFile, } from "@cotal-ai/core";
4
- import { authDir, findCotalRoot, loadSpaceAuth } from "@cotal-ai/workspace";
3
+ import { DEFAULT_SERVER, mintCreds, newIdentity, waitForDeliveryLease, } from "@cotal-ai/core";
4
+ import { DELIVERY_CREDS_KEY, authDir, findCotalRoot, loadSpaceAuth, workspaceSecretStore } from "@cotal-ai/workspace";
5
5
  import { selfArgv } from "./self-exec.js";
6
6
  import { resolveSpace } from "./status.js";
7
7
  import { cotalPath } from "./paths.js";
8
8
  import { ensureManager, managerHasDeliveryMarker, managerUp, stopManager } from "./manager-proc.js";
9
9
  const PID_PATH = () => cotalPath("delivery.pid");
10
- const CREDS_PATH = () => cotalPath("delivery.creds");
10
+ // The daemon's cred goes through the secret-store seam; the shared key (== the filename, so the
11
+ // file stays `.cotal/delivery.creds`) comes from workspace — never a hand-copied literal.
12
+ const credsStore = () => workspaceSecretStore(findCotalRoot());
11
13
  function alive(pid) {
12
14
  try {
13
15
  process.kill(pid, 0);
@@ -89,8 +91,9 @@ export async function ensureDelivery(o = {}) {
89
91
  const space = o.space ?? resolveSpace(process.cwd());
90
92
  const server = o.server ?? DEFAULT_SERVER;
91
93
  if (!deliveryUp()) {
92
- mkSecretDir(cotalPath()); // harden .cotal/ before the cred lands (born under a private ACL, no race)
93
- writeSecretFile(CREDS_PATH(), creds);
94
+ // The store's put hardens `.cotal/` first (the cred is born under a private ACL, no race) and
95
+ // lands it atomically — same path and bytes as before the seam.
96
+ await credsStore().put(DELIVERY_CREDS_KEY, creds);
94
97
  startDeliveryDetached({ ...o, space, server });
95
98
  }
96
99
  // ALWAYS wait for the daemon to be READY (lease flipped ready AFTER it bound ctl.delivery) before
@@ -102,22 +105,29 @@ export async function ensureDelivery(o = {}) {
102
105
  console.error("• delivery daemon not yet ready (responder not bound) - boot durable joins will reconcile when it is");
103
106
  return { running: true };
104
107
  }
105
- /** Stop the detached delivery daemon if we started one, and drop its creds file. */
106
- export function stopDelivery() {
107
- rmSync(CREDS_PATH(), { force: true });
108
- const p = PID_PATH();
109
- if (!existsSync(p))
110
- return;
111
- const pid = Number(readFileSync(p, "utf8").trim());
112
- if (Number.isFinite(pid)) {
113
- try {
114
- process.kill(pid, "SIGTERM");
115
- }
116
- catch {
117
- /* already gone */
108
+ /** Stop the detached delivery daemon if we started one, and drop its creds from the store. The pid
109
+ * kill runs even if the creds delete fails (finally) — a delete error must never leave the daemon
110
+ * alive to outlive the teardown and reattach to a restarted broker; the error still propagates
111
+ * after the kill so the caller can surface it. */
112
+ export async function stopDelivery() {
113
+ try {
114
+ await credsStore().delete(DELIVERY_CREDS_KEY);
115
+ }
116
+ finally {
117
+ const p = PID_PATH();
118
+ if (existsSync(p)) {
119
+ const pid = Number(readFileSync(p, "utf8").trim());
120
+ if (Number.isFinite(pid)) {
121
+ try {
122
+ process.kill(pid, "SIGTERM");
123
+ }
124
+ catch {
125
+ /* already gone */
126
+ }
127
+ }
128
+ rmSync(p);
118
129
  }
119
130
  }
120
- rmSync(p);
121
131
  }
122
132
  /** Bring up the control plane in the correct cutover order: OLD-manager preflight → delivery daemon
123
133
  * (auth only, fails closed on a live old manager) → manager (lifecycle, writes the delivery-aware
@@ -1 +1 @@
1
- {"version":3,"file":"delivery-proc.js","sourceRoot":"","sources":["../../src/lib/delivery-proc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"delivery-proc.js","sourceRoot":"","sources":["../../src/lib/delivery-proc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Refuse every positive listener signal, including auth rejection from an otherwise live broker. */
2
+ export declare function assertEndpointUnreachable(server: string): Promise<void>;
3
+ /** Allow normal shutdown latency, but publish no cut while the exact recorded endpoint still answers. */
4
+ export declare function waitForEndpointUnreachable(server: string, timeoutMs?: number): Promise<void>;
5
+ //# sourceMappingURL=endpoint-cut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint-cut.d.ts","sourceRoot":"","sources":["../../src/lib/endpoint-cut.ts"],"names":[],"mappings":"AAIA,qGAAqG;AACrG,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B7E;AAED,yGAAyG;AACzG,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAWlG"}
@@ -0,0 +1,53 @@
1
+ import { createConnection } from "node:net";
2
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3
+ /** Refuse every positive listener signal, including auth rejection from an otherwise live broker. */
4
+ export async function assertEndpointUnreachable(server) {
5
+ let endpoint;
6
+ try {
7
+ endpoint = new URL(server);
8
+ }
9
+ catch {
10
+ throw new Error(`maintenance cannot prove invalid recorded NATS endpoint ${server} unreachable`);
11
+ }
12
+ if (!endpoint.hostname || !["nats:", "tls:"].includes(endpoint.protocol))
13
+ throw new Error(`maintenance cannot prove invalid recorded NATS endpoint ${server} unreachable`);
14
+ await new Promise((resolve, reject) => {
15
+ const socket = createConnection({ host: endpoint.hostname, port: Number(endpoint.port) || 4222 });
16
+ let settled = false;
17
+ const finish = (error) => {
18
+ if (settled)
19
+ return;
20
+ settled = true;
21
+ socket.destroy();
22
+ if (error)
23
+ reject(error);
24
+ else
25
+ resolve();
26
+ };
27
+ socket.setTimeout(500);
28
+ socket.once("connect", () => finish(new Error(`maintenance requires the recorded NATS endpoint ${server} to have no listener`)));
29
+ socket.once("timeout", () => finish(new Error(`maintenance could not prove the recorded NATS endpoint ${server} unreachable`)));
30
+ socket.once("error", (error) => {
31
+ if (error.code === "ECONNREFUSED")
32
+ finish();
33
+ else
34
+ finish(new Error(`maintenance could not prove the recorded NATS endpoint ${server} unreachable: ${error.message}`));
35
+ });
36
+ });
37
+ }
38
+ /** Allow normal shutdown latency, but publish no cut while the exact recorded endpoint still answers. */
39
+ export async function waitForEndpointUnreachable(server, timeoutMs = 20_000) {
40
+ const deadline = Date.now() + timeoutMs;
41
+ for (;;) {
42
+ try {
43
+ await assertEndpointUnreachable(server);
44
+ return;
45
+ }
46
+ catch (error) {
47
+ if (Date.now() >= deadline)
48
+ throw error;
49
+ }
50
+ await sleep(100);
51
+ }
52
+ }
53
+ //# sourceMappingURL=endpoint-cut.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint-cut.js","sourceRoot":"","sources":["../../src/lib/endpoint-cut.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEhF,qGAAqG;AACrG,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,MAAc;IAC5D,IAAI,QAAa,CAAC;IAClB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,2DAA2D,MAAM,cAAc,CAAC,CAAC;IACnG,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,2DAA2D,MAAM,cAAc,CAAC,CAAC;IACnG,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAClG,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,KAAK;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAC;;gBACpB,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mDAAmD,MAAM,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACjI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0DAA0D,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC;QAChI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAA4B,EAAE,EAAE;YACpD,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;gBAAE,MAAM,EAAE,CAAC;;gBACvC,MAAM,CAAC,IAAI,KAAK,CAAC,0DAA0D,MAAM,iBAAiB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC3H,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,yGAAyG;AACzG,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,MAAc,EAAE,SAAS,GAAG,MAAM;IACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,SAAS,CAAC;QACR,IAAI,CAAC;YACH,MAAM,yBAAyB,CAAC,MAAM,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ;gBAAE,MAAM,KAAK,CAAC;QAC1C,CAAC;QACD,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,70 @@
1
+ import { type NatsConnection } from "@nats-io/transport-node";
2
+ import { type BackupPermissionScope, type RestorePermissionScope, type SpaceAuth } from "@cotal-ai/core";
3
+ import type { MaintenanceAuthMode, ProcessOwner } from "@cotal-ai/workspace";
4
+ export interface PrivateAttemptsDirectory {
5
+ path: string;
6
+ identity: {
7
+ dev: bigint;
8
+ ino: bigint;
9
+ };
10
+ }
11
+ export declare function ensurePrivateAttemptsDir(root: string): PrivateAttemptsDirectory;
12
+ /** With the maintenance journal at `ready` and no live claim, nothing may legitimately live in the
13
+ * private attempts directory: every entry is residue of a dead attempt (staging, clones, broker
14
+ * run files) and is removed before new maintenance work begins. Strict — a failed removal aborts
15
+ * the caller rather than proceeding over unowned residue. */
16
+ export declare function sweepAttemptResidue(root: string): void;
17
+ export interface AttemptDirectory {
18
+ path: string;
19
+ identity: {
20
+ dev: bigint;
21
+ ino: bigint;
22
+ };
23
+ cleanup(): void;
24
+ }
25
+ export declare function createAttemptClone(root: string, sourceStore: string, attemptId: string): AttemptDirectory;
26
+ export interface IsolatedRunFile {
27
+ path: string;
28
+ dev: string;
29
+ ino: string;
30
+ }
31
+ export interface IsolatedBroker {
32
+ server: string;
33
+ initialLogin: IsolatedMaintenanceLogin;
34
+ brokerOwner: ProcessOwner;
35
+ watchdogOwner: ProcessOwner;
36
+ /** Attempt-owned run files (config, broker log, pid handshake) for claim journaling. */
37
+ runFiles: readonly IsolatedRunFile[];
38
+ addLogin(scope: IsolatedMaintenanceScope | ((connId: string) => IsolatedMaintenanceScope)): Promise<IsolatedMaintenanceLogin>;
39
+ stop(): Promise<void>;
40
+ }
41
+ export type IsolatedMaintenanceScope = {
42
+ profile: "backup";
43
+ scope: BackupPermissionScope;
44
+ } | {
45
+ profile: "restore";
46
+ scope: RestorePermissionScope;
47
+ } | {
48
+ profile: "infrastructure";
49
+ streams: readonly string[];
50
+ };
51
+ export interface IsolatedMaintenanceLogin {
52
+ readonly user: string;
53
+ readonly pass: string;
54
+ readonly connId: string;
55
+ readonly scope: IsolatedMaintenanceScope;
56
+ }
57
+ export declare function connectIsolatedBroker(broker: Pick<IsolatedBroker, "server">, login: IsolatedMaintenanceLogin): Promise<NatsConnection>;
58
+ export declare function startIsolatedBroker(options: {
59
+ root: string;
60
+ storeDir: string;
61
+ space: string;
62
+ mode: MaintenanceAuthMode;
63
+ auth?: SpaceAuth;
64
+ deadline: Date;
65
+ label: "backup" | "restore" | "quarantine";
66
+ initialScope: IsolatedMaintenanceScope;
67
+ /** Attempt id prefixing the run files, tying them to the journaled maintenance attempt. */
68
+ attemptId?: string;
69
+ }): Promise<IsolatedBroker>;
70
+ //# sourceMappingURL=isolated-broker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isolated-broker.d.ts","sourceRoot":"","sources":["../../src/lib/isolated-broker.ts"],"names":[],"mappings":"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"}