@cotal-ai/cli 0.16.0 → 0.17.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.
- package/dist/command.d.ts.map +1 -1
- package/dist/command.js +13 -0
- package/dist/command.js.map +1 -1
- package/dist/commands/agents.d.ts +5 -15
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +133 -72
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/clean.d.ts.map +1 -1
- package/dist/commands/clean.js +4 -3
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/describe.d.ts +72 -0
- package/dist/commands/describe.d.ts.map +1 -0
- package/dist/commands/describe.js +148 -0
- package/dist/commands/describe.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +27 -8
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/down-manifest.d.ts.map +1 -1
- package/dist/commands/down-manifest.js +38 -18
- package/dist/commands/down-manifest.js.map +1 -1
- package/dist/commands/down.d.ts +9 -0
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +38 -10
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/ext.d.ts.map +1 -1
- package/dist/commands/ext.js +16 -10
- package/dist/commands/ext.js.map +1 -1
- package/dist/commands/join.d.ts.map +1 -1
- package/dist/commands/join.js +2 -4
- package/dist/commands/join.js.map +1 -1
- package/dist/commands/meshes-add.d.ts.map +1 -1
- package/dist/commands/meshes-add.js +23 -0
- package/dist/commands/meshes-add.js.map +1 -1
- package/dist/commands/models.d.ts.map +1 -1
- package/dist/commands/models.js +2 -2
- package/dist/commands/models.js.map +1 -1
- package/dist/commands/spawn-manifest.d.ts.map +1 -1
- package/dist/commands/spawn-manifest.js +22 -12
- package/dist/commands/spawn-manifest.js.map +1 -1
- package/dist/commands/spawn.d.ts +5 -0
- package/dist/commands/spawn.d.ts.map +1 -1
- package/dist/commands/spawn.js +4 -2
- package/dist/commands/spawn.js.map +1 -1
- package/dist/commands/status.js +25 -5
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/up.d.ts +17 -2
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +640 -49
- package/dist/commands/up.js.map +1 -1
- package/dist/console/app.d.ts +1 -1
- package/dist/console/app.d.ts.map +1 -1
- package/dist/console/app.js +16 -5
- package/dist/console/app.js.map +1 -1
- package/dist/console/commands.d.ts.map +1 -1
- package/dist/console/commands.js +5 -5
- package/dist/console/commands.js.map +1 -1
- package/dist/console/root.d.ts.map +1 -1
- package/dist/console/root.js +6 -1
- package/dist/console/root.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/attach-client.d.ts +37 -4
- package/dist/lib/attach-client.d.ts.map +1 -1
- package/dist/lib/attach-client.js +88 -18
- package/dist/lib/attach-client.js.map +1 -1
- package/dist/lib/auth-proc.d.ts +3 -1
- package/dist/lib/auth-proc.d.ts.map +1 -1
- package/dist/lib/auth-proc.js +15 -4
- package/dist/lib/auth-proc.js.map +1 -1
- package/dist/lib/connect.d.ts +1 -1
- package/dist/lib/connect.d.ts.map +1 -1
- package/dist/lib/connect.js +1 -1
- package/dist/lib/connect.js.map +1 -1
- package/dist/lib/control.d.ts +42 -11
- package/dist/lib/control.d.ts.map +1 -1
- package/dist/lib/control.js +251 -44
- package/dist/lib/control.js.map +1 -1
- package/dist/lib/delivery-proc.d.ts +19 -4
- package/dist/lib/delivery-proc.d.ts.map +1 -1
- package/dist/lib/delivery-proc.js +129 -43
- package/dist/lib/delivery-proc.js.map +1 -1
- package/dist/lib/manager-proc.d.ts +48 -5
- package/dist/lib/manager-proc.d.ts.map +1 -1
- package/dist/lib/manager-proc.js +131 -30
- package/dist/lib/manager-proc.js.map +1 -1
- package/dist/lib/manifest/ledger.d.ts +52 -8
- package/dist/lib/manifest/ledger.d.ts.map +1 -1
- package/dist/lib/manifest/ledger.js +77 -19
- package/dist/lib/manifest/ledger.js.map +1 -1
- package/dist/lib/manifest/live.d.ts +21 -16
- package/dist/lib/manifest/live.d.ts.map +1 -1
- package/dist/lib/manifest/live.js +33 -20
- package/dist/lib/manifest/live.js.map +1 -1
- package/dist/lib/restore.d.ts.map +1 -1
- package/dist/lib/restore.js +21 -3
- package/dist/lib/restore.js.map +1 -1
- package/dist/view/mesh-view.js +2 -2
- package/dist/view/mesh-view.js.map +1 -1
- package/package.json +4 -3
- package/dist/lib/pid.d.ts +0 -23
- package/dist/lib/pid.d.ts.map +0 -1
- package/dist/lib/pid.js +0 -39
- package/dist/lib/pid.js.map +0 -1
|
@@ -5,6 +5,7 @@ declare const LedgerAgentSchema: z.ZodObject<{
|
|
|
5
5
|
name: z.ZodString;
|
|
6
6
|
id: z.ZodString;
|
|
7
7
|
hash: z.ZodString;
|
|
8
|
+
lifecycleUid: z.ZodOptional<z.ZodString>;
|
|
8
9
|
}, z.core.$strict>;
|
|
9
10
|
declare const LedgerSchema: z.ZodObject<{
|
|
10
11
|
apiVersion: z.ZodLiteral<"cotal-ledger/v1">;
|
|
@@ -22,6 +23,7 @@ declare const LedgerSchema: z.ZodObject<{
|
|
|
22
23
|
name: z.ZodString;
|
|
23
24
|
id: z.ZodString;
|
|
24
25
|
hash: z.ZodString;
|
|
26
|
+
lifecycleUid: z.ZodOptional<z.ZodString>;
|
|
25
27
|
}, z.core.$strict>>;
|
|
26
28
|
}, z.core.$strict>;
|
|
27
29
|
}, z.core.$strict>;
|
|
@@ -54,13 +56,54 @@ export declare function writeLedger(root: string, ledger: MeshLedger, opts?: {
|
|
|
54
56
|
* ledger is proven before the caller deletes anything (no partial "validated the class I'm about to
|
|
55
57
|
* delete" flow). Throws on any deviation. */
|
|
56
58
|
export declare function loadLedger(path: string): MeshLedger;
|
|
57
|
-
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
59
|
+
/** Build the ledger row for ONE launched agent, and PARSE it rather than assert it.
|
|
60
|
+
*
|
|
61
|
+
* WHICH SIDE EACH FIELD COMES FROM IS THE WHOLE POINT. `requested` and `hash` are the DEPLOY
|
|
62
|
+
* CALLER'S OWN inputs — it submitted the manifest key and resolved the drift hash before it ever
|
|
63
|
+
* called the manager — so they are read from the plan. Only the SPAWNED identity (`name`, `id`,
|
|
64
|
+
* `lifecycleUid`) can come from the reply, and that is exactly what the v0.4 action acceptance
|
|
65
|
+
* floor carries (P2 item 2 ruling 3: the manifest details are deliberately NOT in the launch
|
|
66
|
+
* output contract, because the caller can re-derive them). Reaching across the wire for a value
|
|
67
|
+
* already in local scope is what broke this: the reply stopped carrying them, `as` could not warn,
|
|
68
|
+
* `JSON.stringify` dropped the undefined keys, and the row only failed months later at teardown.
|
|
69
|
+
*
|
|
70
|
+
* PARSE, NEVER CAST. A cast is a claim about a shape the compiler then stops checking; the whole
|
|
71
|
+
* defect lived in the gap between that claim and the wire. This throws at WRITE time, naming the
|
|
72
|
+
* field, instead of persisting a record the reader will refuse. */
|
|
73
|
+
export declare function buildLedgerAgentRow(planned: {
|
|
74
|
+
requested: string;
|
|
75
|
+
hash: string;
|
|
76
|
+
}, spawned: {
|
|
77
|
+
name?: unknown;
|
|
78
|
+
id?: unknown;
|
|
79
|
+
lifecycleUid?: unknown;
|
|
80
|
+
}): LedgerAgent;
|
|
81
|
+
/** Every valid ledger under `<root>/.cotal/manifests/`. Foreign files are skipped (a targeted
|
|
82
|
+
* `down -f --run <id>` names one directly); used to resolve a `down -f cotal.yaml` to its run by
|
|
83
|
+
* `manifestHash`.
|
|
84
|
+
*
|
|
85
|
+
* A REFUSED file is NOT the same as an absent one, and collapsing the two cost a release. When a
|
|
86
|
+
* file under this root is named for its own `runId` but fails validation, it is OURS and broken,
|
|
87
|
+
* not somebody else's: swallowing that turned a zod error NAMING the missing fields into
|
|
88
|
+
* `findLedgerByHash`'s "was it edited since `spawn -f`?", which accuses the operator of editing a
|
|
89
|
+
* manifest they never touched. So refusals are RETURNED alongside the valid rows and the caller
|
|
90
|
+
* decides; the message that already existed is surfaced rather than replaced. */
|
|
60
91
|
export declare function listLedgers(root: string): Array<{
|
|
61
92
|
path: string;
|
|
62
93
|
ledger: MeshLedger;
|
|
63
94
|
}>;
|
|
95
|
+
/** {@link listLedgers} plus the files this root REFUSED, so a caller can tell "no ledger here" from
|
|
96
|
+
* "a ledger I could not read". `refused` carries the validator's own message verbatim. */
|
|
97
|
+
export declare function listLedgerFiles(root: string): {
|
|
98
|
+
valid: Array<{
|
|
99
|
+
path: string;
|
|
100
|
+
ledger: MeshLedger;
|
|
101
|
+
}>;
|
|
102
|
+
refused: Array<{
|
|
103
|
+
path: string;
|
|
104
|
+
why: string;
|
|
105
|
+
}>;
|
|
106
|
+
};
|
|
64
107
|
/** Resolve a `down -f cotal.yaml` to its ledger by the manifest's content hash. Fails (never
|
|
65
108
|
* guesses) when nothing matches (edited file) or more than one does — `--run <id>` is the escape. */
|
|
66
109
|
export declare function findLedgerByHash(root: string, manifestHash: string): {
|
|
@@ -73,11 +116,12 @@ export declare function findLedgerByRun(root: string, runId: string): {
|
|
|
73
116
|
path: string;
|
|
74
117
|
ledger: MeshLedger;
|
|
75
118
|
};
|
|
76
|
-
/** Derive an owned agent's cred path under the known auth root
|
|
77
|
-
*
|
|
78
|
-
* the workspace's single filename source for the kind (
|
|
119
|
+
/** Derive an owned agent's cred path under the known auth root from the SPAWNED name (+ the
|
|
120
|
+
* recorded lifecycle uid when the row carries one). The ledger never stores a cred path; teardown
|
|
121
|
+
* derives it here through the workspace's single filename source for the kind (the guarded
|
|
79
122
|
* segment refuses any name that could escape the creds dir), so teardown can never derive a
|
|
80
|
-
* DIFFERENT path than provisioning wrote
|
|
81
|
-
|
|
123
|
+
* DIFFERENT path than provisioning wrote: a uid-carrying row maps to the lifecycle-keyed file its
|
|
124
|
+
* spawn materialized, a pre-split row to the legacy name-keyed one. */
|
|
125
|
+
export declare function ownedCredPath(root: string, spawnedName: string, lifecycleUid?: string): string;
|
|
82
126
|
export {};
|
|
83
127
|
//# sourceMappingURL=ledger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../../src/lib/manifest/ledger.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAOhD,QAAA,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../../src/lib/manifest/ledger.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAOhD,QAAA,MAAM,iBAAiB;;;;;;kBAcrB,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;kBAgBhB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AACtD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D;;sCAEsC;AACtC,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,GAAG,UAAU,CAYb;AAED;;6FAE6F;AAC7F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;0EAE0E;AAC1E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAcrG;AAED;;;8CAG8C;AAC9C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAmCnD;AAED;;;;;;;;;;;;;oEAaoE;AACpE,wBAAgB,mBAAmB,CACjC,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC5C,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,WAAW,CAab;AAED;;;;;;;;;kFASkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAErF;AAED;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG;IAC7C,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACnD,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C,CA4BA;AAED;sGACsG;AACtG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAezG;AAED;gCACgC;AAChC,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAUjG;AAED;;;;;wEAKwE;AACxE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9F"}
|
|
@@ -18,7 +18,7 @@ import { readFileSync, writeFileSync, readdirSync, renameSync, lstatSync } from
|
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
import { assertValidChannel, assertValidName, ensureDirNoSymlink, isConcreteChannel, realDirNoSymlink } from "@cotal-ai/core";
|
|
21
|
-
import { agentSecretFilePaths } from "@cotal-ai/workspace";
|
|
21
|
+
import { agentLifecycleSecretFilePaths, agentSecretFilePaths } from "@cotal-ai/workspace";
|
|
22
22
|
export const LEDGER_VERSION = "cotal-ledger/v1";
|
|
23
23
|
// Path-/route-safe token (run id, agent name) and an alphanumeric content hash — same shapes the
|
|
24
24
|
// launch spec uses, so the ledger can't smuggle a traversal/injection string into a derived path.
|
|
@@ -35,6 +35,9 @@ const LedgerAgentSchema = z.strictObject({
|
|
|
35
35
|
id: z.string().min(1),
|
|
36
36
|
/** The resolved hash at spawn (drift/stale detection on re-apply). */
|
|
37
37
|
hash: z.string().regex(HASH, "hash must be alphanumeric"),
|
|
38
|
+
/** The incarnation's lifecycle UID from the spawn reply (SPEC 13.1). Optional: rows written by a
|
|
39
|
+
* pre-split generation carry none, and their creds stay filed under the name-keyed path. */
|
|
40
|
+
lifecycleUid: z.string().regex(/^[a-z0-9]{26,32}$/, "lifecycleUid must be a lifecycle uid token").optional(),
|
|
38
41
|
});
|
|
39
42
|
const LedgerSchema = z.strictObject({
|
|
40
43
|
apiVersion: z.literal(LEDGER_VERSION),
|
|
@@ -141,23 +144,64 @@ export function loadLedger(path) {
|
|
|
141
144
|
}
|
|
142
145
|
return led;
|
|
143
146
|
}
|
|
144
|
-
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
+
/** Build the ledger row for ONE launched agent, and PARSE it rather than assert it.
|
|
148
|
+
*
|
|
149
|
+
* WHICH SIDE EACH FIELD COMES FROM IS THE WHOLE POINT. `requested` and `hash` are the DEPLOY
|
|
150
|
+
* CALLER'S OWN inputs — it submitted the manifest key and resolved the drift hash before it ever
|
|
151
|
+
* called the manager — so they are read from the plan. Only the SPAWNED identity (`name`, `id`,
|
|
152
|
+
* `lifecycleUid`) can come from the reply, and that is exactly what the v0.4 action acceptance
|
|
153
|
+
* floor carries (P2 item 2 ruling 3: the manifest details are deliberately NOT in the launch
|
|
154
|
+
* output contract, because the caller can re-derive them). Reaching across the wire for a value
|
|
155
|
+
* already in local scope is what broke this: the reply stopped carrying them, `as` could not warn,
|
|
156
|
+
* `JSON.stringify` dropped the undefined keys, and the row only failed months later at teardown.
|
|
157
|
+
*
|
|
158
|
+
* PARSE, NEVER CAST. A cast is a claim about a shape the compiler then stops checking; the whole
|
|
159
|
+
* defect lived in the gap between that claim and the wire. This throws at WRITE time, naming the
|
|
160
|
+
* field, instead of persisting a record the reader will refuse. */
|
|
161
|
+
export function buildLedgerAgentRow(planned, spawned) {
|
|
162
|
+
const parsed = LedgerAgentSchema.safeParse({
|
|
163
|
+
requested: planned.requested,
|
|
164
|
+
hash: planned.hash,
|
|
165
|
+
name: spawned.name,
|
|
166
|
+
id: spawned.id,
|
|
167
|
+
// Omit rather than pass undefined: a pre-split manager's reply carries no uid, and the row must
|
|
168
|
+
// stay name-keyed in that case rather than carry an explicit empty.
|
|
169
|
+
...(spawned.lifecycleUid !== undefined ? { lifecycleUid: spawned.lifecycleUid } : {}),
|
|
170
|
+
});
|
|
171
|
+
if (!parsed.success)
|
|
172
|
+
throw new Error(`refusing to record an unreadable ledger row for "${planned.requested}": ${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`);
|
|
173
|
+
return parsed.data;
|
|
174
|
+
}
|
|
175
|
+
/** Every valid ledger under `<root>/.cotal/manifests/`. Foreign files are skipped (a targeted
|
|
176
|
+
* `down -f --run <id>` names one directly); used to resolve a `down -f cotal.yaml` to its run by
|
|
177
|
+
* `manifestHash`.
|
|
178
|
+
*
|
|
179
|
+
* A REFUSED file is NOT the same as an absent one, and collapsing the two cost a release. When a
|
|
180
|
+
* file under this root is named for its own `runId` but fails validation, it is OURS and broken,
|
|
181
|
+
* not somebody else's: swallowing that turned a zod error NAMING the missing fields into
|
|
182
|
+
* `findLedgerByHash`'s "was it edited since `spawn -f`?", which accuses the operator of editing a
|
|
183
|
+
* manifest they never touched. So refusals are RETURNED alongside the valid rows and the caller
|
|
184
|
+
* decides; the message that already existed is surfaced rather than replaced. */
|
|
147
185
|
export function listLedgers(root) {
|
|
186
|
+
return listLedgerFiles(root).valid;
|
|
187
|
+
}
|
|
188
|
+
/** {@link listLedgers} plus the files this root REFUSED, so a caller can tell "no ledger here" from
|
|
189
|
+
* "a ledger I could not read". `refused` carries the validator's own message verbatim. */
|
|
190
|
+
export function listLedgerFiles(root) {
|
|
148
191
|
// Prove `.cotal/manifests` is a real (non-symlink) directory chain before reading under it — a
|
|
149
192
|
// symlinked parent could redirect `down -f` to attacker-chosen ledgers.
|
|
150
193
|
const dir = realDirNoSymlink(root, ".cotal", "manifests");
|
|
151
194
|
if (!dir)
|
|
152
|
-
return [];
|
|
195
|
+
return { valid: [], refused: [] };
|
|
153
196
|
let names;
|
|
154
197
|
try {
|
|
155
198
|
names = readdirSync(dir);
|
|
156
199
|
}
|
|
157
200
|
catch {
|
|
158
|
-
return [];
|
|
201
|
+
return { valid: [], refused: [] };
|
|
159
202
|
}
|
|
160
|
-
const
|
|
203
|
+
const valid = [];
|
|
204
|
+
const refused = [];
|
|
161
205
|
for (const n of names) {
|
|
162
206
|
if (!n.endsWith(".json") || n.startsWith("."))
|
|
163
207
|
continue;
|
|
@@ -166,20 +210,31 @@ export function listLedgers(root) {
|
|
|
166
210
|
const ledger = loadLedger(p);
|
|
167
211
|
if (`${ledger.runId}.json` !== n)
|
|
168
212
|
continue; // filename must match the declared runId (no spoofed authority)
|
|
169
|
-
|
|
213
|
+
valid.push({ path: p, ledger });
|
|
170
214
|
}
|
|
171
|
-
catch {
|
|
172
|
-
|
|
215
|
+
catch (e) {
|
|
216
|
+
// A file named `<runId>.json` is a ledger THIS root wrote; a validation failure on it is our
|
|
217
|
+
// own bad record, not a foreign file. Keep the validator's message: it names the offending
|
|
218
|
+
// field, which is the whole diagnosis.
|
|
219
|
+
refused.push({ path: p, why: e.message });
|
|
173
220
|
}
|
|
174
221
|
}
|
|
175
|
-
return
|
|
222
|
+
return { valid, refused };
|
|
176
223
|
}
|
|
177
224
|
/** Resolve a `down -f cotal.yaml` to its ledger by the manifest's content hash. Fails (never
|
|
178
225
|
* guesses) when nothing matches (edited file) or more than one does — `--run <id>` is the escape. */
|
|
179
226
|
export function findLedgerByHash(root, manifestHash) {
|
|
180
|
-
const
|
|
181
|
-
|
|
227
|
+
const { valid, refused } = listLedgerFiles(root);
|
|
228
|
+
const matches = valid.filter((l) => l.ledger.manifestHash === manifestHash);
|
|
229
|
+
if (matches.length === 0) {
|
|
230
|
+
// A REFUSED ledger is not an absent one. Reporting "was it edited?" while holding a validator
|
|
231
|
+
// error that names the offending field sends the operator to look at a file that is fine, and
|
|
232
|
+
// hides the record that is not. Report what we actually know, and never let the accusation
|
|
233
|
+
// stand in for a diagnosis we already have.
|
|
234
|
+
if (refused.length)
|
|
235
|
+
throw new Error(`this root has ${refused.length} ledger(s) it cannot read, so a matching run may exist but be unreadable - fix or remove them, then retry:\n${refused.map((r) => ` ${r.path}: ${r.why}`).join("\n")}`);
|
|
182
236
|
throw new Error(`no ledger matches this manifest's current contents (was it edited since \`spawn -f\`?) - tear down by run id: \`cotal down -f <file> --run <id>\``);
|
|
237
|
+
}
|
|
183
238
|
if (matches.length > 1)
|
|
184
239
|
throw new Error(`${matches.length} runs share this manifest - name one: ${matches.map((m) => m.ledger.runId).join(", ")} (\`--run <id>\`)`);
|
|
185
240
|
return matches[0];
|
|
@@ -199,13 +254,16 @@ export function findLedgerByRun(root, runId) {
|
|
|
199
254
|
throw new Error(`ledger ${path}: declares runId "${ledger.runId}", not "${runId}" - refusing`);
|
|
200
255
|
return { path, ledger };
|
|
201
256
|
}
|
|
202
|
-
/** Derive an owned agent's cred path under the known auth root
|
|
203
|
-
*
|
|
204
|
-
* the workspace's single filename source for the kind (
|
|
257
|
+
/** Derive an owned agent's cred path under the known auth root from the SPAWNED name (+ the
|
|
258
|
+
* recorded lifecycle uid when the row carries one). The ledger never stores a cred path; teardown
|
|
259
|
+
* derives it here through the workspace's single filename source for the kind (the guarded
|
|
205
260
|
* segment refuses any name that could escape the creds dir), so teardown can never derive a
|
|
206
|
-
* DIFFERENT path than provisioning wrote
|
|
207
|
-
|
|
261
|
+
* DIFFERENT path than provisioning wrote: a uid-carrying row maps to the lifecycle-keyed file its
|
|
262
|
+
* spawn materialized, a pre-split row to the legacy name-keyed one. */
|
|
263
|
+
export function ownedCredPath(root, spawnedName, lifecycleUid) {
|
|
208
264
|
assertValidName(spawnedName); // manifest-level refusal first, with the ledger's own phrasing
|
|
209
|
-
return
|
|
265
|
+
return lifecycleUid
|
|
266
|
+
? agentLifecycleSecretFilePaths(root, spawnedName, lifecycleUid).creds
|
|
267
|
+
: agentSecretFilePaths(root, spawnedName).creds;
|
|
210
268
|
}
|
|
211
269
|
//# sourceMappingURL=ledger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../src/lib/manifest/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC9H,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../src/lib/manifest/ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Live-mesh helpers for `cotal spawn -f` — the network half: a transient, invisible probe endpoint
|
|
3
|
-
* for reading the roster + membership feed, and the
|
|
4
|
-
* `launch`
|
|
5
|
-
*
|
|
3
|
+
* for reading the roster + membership feed, and the manager calls that drive the running manager's
|
|
4
|
+
* `launch`/`ps` — over the v0.4 ep rails (1c.2c): the deployer credential/view carries the
|
|
5
|
+
* tier-matched instrument rows (static = admin set; user-mode deployer view = privileged set + an
|
|
6
|
+
* owner-equality `launch` row, the manager's ledger-derived admin flag governs). (Channel-registry
|
|
6
7
|
* reads use `readChannelRegistry`, which connects itself.)
|
|
7
8
|
*/
|
|
8
|
-
import { CotalEndpoint, type ControlReply, type
|
|
9
|
+
import { CotalEndpoint, type ControlReply, type MeshLaunchSpec, type Presence } from "@cotal-ai/core";
|
|
9
10
|
export interface MeshConn {
|
|
10
11
|
space: string;
|
|
11
12
|
server: string;
|
|
12
13
|
creds?: string;
|
|
14
|
+
/** The deploy credential's v0.4 lifecycle uid (static: the instrument mint's; user: the
|
|
15
|
+
* bearer's ledger claim) — the probe endpoint's caller triple is keyed on it. */
|
|
16
|
+
lifecycleUid?: string;
|
|
13
17
|
/** User mode: the "deployer" VIEW material — a bearer SOURCE (a deploy spans several ≤5-min
|
|
14
18
|
* token lives across launch readiness waits) + sentinel + the pinned principal a source-mode
|
|
15
19
|
* endpoint requires. */
|
|
@@ -26,20 +30,21 @@ export declare function connectProbe(conn: MeshConn): Promise<CotalEndpoint>;
|
|
|
26
30
|
/** Let the presence KV replay settle (roster count steady across two polls, ≤1s), then snapshot the
|
|
27
31
|
* live peers — mirrors the dedup probe in `cotal spawn`. */
|
|
28
32
|
export declare function settleRoster(ep: CotalEndpoint): Promise<Presence[]>;
|
|
29
|
-
/** Poll the manager
|
|
30
|
-
* so it needs a moment to connect
|
|
31
|
-
* deploy credential
|
|
32
|
-
export declare function waitManagerReady(ep: CotalEndpoint, timeoutMs?: number
|
|
33
|
+
/** Poll the manager until it answers `ps` on the ep rails — it may have just been started
|
|
34
|
+
* detached, so it needs a moment to connect, register its service, and come up. Returns false on
|
|
35
|
+
* timeout. The deploy credential's instrument rows carry the read regardless of tier. */
|
|
36
|
+
export declare function waitManagerReady(ep: CotalEndpoint, timeoutMs?: number): Promise<boolean>;
|
|
33
37
|
/** Poll until the manager lease for this space is GONE (a crashed holder's key lingers until the bucket
|
|
34
38
|
* TTL). Returns true once absent, false on timeout. `spawn -f` uses this to wait out a STALE lease
|
|
35
39
|
* before standing up a replacement — a held lease alone is not proof a manager is alive. */
|
|
36
40
|
export declare function waitLeaseGone(ep: CotalEndpoint, timeoutMs: number): Promise<boolean>;
|
|
37
|
-
/** Ask the running manager to launch one resolved agent from the run spec —
|
|
38
|
-
* a static
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* we pass the runId, never a path. When the
|
|
42
|
-
* `spec` and the resolved spec rides the
|
|
43
|
-
* untrusted input and persists it under its own
|
|
44
|
-
|
|
41
|
+
/** Ask the running manager to launch one resolved agent from the run spec — the v0.4 `launch`
|
|
42
|
+
* command, capability-only: a static deploy credential holds it via the admin instrument set (a
|
|
43
|
+
* spawn-capable agent holds no row at all), a user-mode deployer view holds the owner-equality
|
|
44
|
+
* variant (the manager's ledger-derived admin flag keeps spec-owner === caller-owner there). The
|
|
45
|
+
* manager derives `.cotal/run/<runId>.json` itself; we pass the runId, never a path. When the
|
|
46
|
+
* serving manager lives in ANOTHER checkout/host, pass `spec` and the resolved spec rides the
|
|
47
|
+
* control plane inline — the manager validates it as untrusted input and persists it under its own
|
|
48
|
+
* run tree before launching. */
|
|
49
|
+
export declare function launchAgent(ep: CotalEndpoint, runId: string, name: string, spec?: MeshLaunchSpec): Promise<ControlReply>;
|
|
45
50
|
//# sourceMappingURL=live.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/lib/manifest/live.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/lib/manifest/live.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,aAAa,EAAmB,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAGvH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;sFACkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;6BAEyB;IACzB,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/F;AAID;4EAC4E;AAC5E,wBAAsB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAoBzE;AAED;6DAC6D;AAC7D,wBAAsB,YAAY,CAAC,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CASzE;AAED;;0FAE0F;AAC1F,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,aAAa,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAY9F;AAED;;6FAE6F;AAC7F,wBAAsB,aAAa,CAAC,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO1F;AAED;;;;;;;iCAOiC;AACjC,wBAAsB,WAAW,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAY9H"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Live-mesh helpers for `cotal spawn -f` — the network half: a transient, invisible probe endpoint
|
|
3
|
-
* for reading the roster + membership feed, and the
|
|
4
|
-
* `launch`
|
|
5
|
-
*
|
|
3
|
+
* for reading the roster + membership feed, and the manager calls that drive the running manager's
|
|
4
|
+
* `launch`/`ps` — over the v0.4 ep rails (1c.2c): the deployer credential/view carries the
|
|
5
|
+
* tier-matched instrument rows (static = admin set; user-mode deployer view = privileged set + an
|
|
6
|
+
* owner-equality `launch` row, the manager's ledger-derived admin flag governs). (Channel-registry
|
|
6
7
|
* reads use `readChannelRegistry`, which connects itself.)
|
|
7
8
|
*/
|
|
8
|
-
import { CotalEndpoint,
|
|
9
|
+
import { CotalEndpoint, EpEnvelopeError } from "@cotal-ai/core";
|
|
9
10
|
import { START_TIMEOUT_MS } from "../control.js";
|
|
10
11
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
11
12
|
/** Connect a transient, presence-invisible endpoint (it watches the roster but doesn't register
|
|
@@ -21,6 +22,7 @@ export async function connectProbe(conn) {
|
|
|
21
22
|
card: { owner: conn.user.owner, actor: conn.user.actor, name: "spawn-f", kind: "endpoint" },
|
|
22
23
|
}
|
|
23
24
|
: { creds: conn.creds, card: { name: "spawn-f", kind: "endpoint" } }),
|
|
25
|
+
lifecycleUid: conn.lifecycleUid,
|
|
24
26
|
channels: [],
|
|
25
27
|
consume: false,
|
|
26
28
|
registerPresence: false, // an invisible probe — don't add ourselves to the roster we read
|
|
@@ -43,19 +45,19 @@ export async function settleRoster(ep) {
|
|
|
43
45
|
}
|
|
44
46
|
return ep.getRoster();
|
|
45
47
|
}
|
|
46
|
-
/** Poll the manager
|
|
47
|
-
* so it needs a moment to connect
|
|
48
|
-
* deploy credential
|
|
49
|
-
export async function waitManagerReady(ep, timeoutMs = 20_000
|
|
48
|
+
/** Poll the manager until it answers `ps` on the ep rails — it may have just been started
|
|
49
|
+
* detached, so it needs a moment to connect, register its service, and come up. Returns false on
|
|
50
|
+
* timeout. The deploy credential's instrument rows carry the read regardless of tier. */
|
|
51
|
+
export async function waitManagerReady(ep, timeoutMs = 20_000) {
|
|
50
52
|
const deadline = Date.now() + timeoutMs;
|
|
51
53
|
while (Date.now() < deadline) {
|
|
52
54
|
try {
|
|
53
|
-
const r = await ep.
|
|
54
|
-
if (r.ok)
|
|
55
|
+
const r = await ep.invokeService("manager", "ps", undefined, { deadlineMs: 4_000 });
|
|
56
|
+
if (r.reply.ok === true)
|
|
55
57
|
return true;
|
|
56
58
|
}
|
|
57
59
|
catch {
|
|
58
|
-
/* manager not answering yet */
|
|
60
|
+
/* manager not answering / not registered yet */
|
|
59
61
|
}
|
|
60
62
|
await sleep(500);
|
|
61
63
|
}
|
|
@@ -73,16 +75,27 @@ export async function waitLeaseGone(ep, timeoutMs) {
|
|
|
73
75
|
}
|
|
74
76
|
return !(await ep.readManagerLease());
|
|
75
77
|
}
|
|
76
|
-
/** Ask the running manager to launch one resolved agent from the run spec —
|
|
77
|
-
* a static
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* we pass the runId, never a path. When the
|
|
81
|
-
* `spec` and the resolved spec rides the
|
|
82
|
-
* untrusted input and persists it under its own
|
|
83
|
-
|
|
78
|
+
/** Ask the running manager to launch one resolved agent from the run spec — the v0.4 `launch`
|
|
79
|
+
* command, capability-only: a static deploy credential holds it via the admin instrument set (a
|
|
80
|
+
* spawn-capable agent holds no row at all), a user-mode deployer view holds the owner-equality
|
|
81
|
+
* variant (the manager's ledger-derived admin flag keeps spec-owner === caller-owner there). The
|
|
82
|
+
* manager derives `.cotal/run/<runId>.json` itself; we pass the runId, never a path. When the
|
|
83
|
+
* serving manager lives in ANOTHER checkout/host, pass `spec` and the resolved spec rides the
|
|
84
|
+
* control plane inline — the manager validates it as untrusted input and persists it under its own
|
|
85
|
+
* run tree before launching. */
|
|
86
|
+
export async function launchAgent(ep, runId, name, spec) {
|
|
84
87
|
// #159 B1: `launch` funnels into the same startAgent readiness wait as `start` — the manager
|
|
85
88
|
// replies only on a real outcome (join / exit / ~30s backstop), so the request must outlive it.
|
|
86
|
-
|
|
89
|
+
try {
|
|
90
|
+
// P2 item 2 (2b): launch is an ACTION — follow the acceptance to the terminal so `up -f` /
|
|
91
|
+
// `spawn -f` still returns on the real outcome (join / exit / ~30s uncertain), UX unchanged.
|
|
92
|
+
const r = await ep.invokeService("manager", "launch", { runId, name, ...(spec ? { spec } : {}) }, { deadlineMs: START_TIMEOUT_MS, follow: true });
|
|
93
|
+
if (r.reply.ok !== true)
|
|
94
|
+
return { ok: false, error: r.reply.error?.message ?? r.reply.error?.code ?? "launch failed" };
|
|
95
|
+
return { ok: true, ...(r.reply.data !== undefined ? { data: r.reply.data } : {}) };
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
return { ok: false, error: e instanceof EpEnvelopeError ? `${e.code}: ${e.message}` : e.message };
|
|
99
|
+
}
|
|
87
100
|
}
|
|
88
101
|
//# sourceMappingURL=live.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../../src/lib/manifest/live.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../../src/lib/manifest/live.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/lib/restore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/lib/restore.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/restore.js
CHANGED
|
@@ -4,7 +4,7 @@ import { hostname } from "node:os";
|
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
5
5
|
import { jetstreamManager } from "@nats-io/jetstream";
|
|
6
6
|
import { Kvm } from "@nats-io/kv";
|
|
7
|
-
import { canonicalBackupStreamConfig, consumerConfigFromCheckpoint, deliveryBucket, downloadStreamSnapshot, finalizeStreamRestore, hardenPrivate, initiateStreamRestore, LEASE_TTL_MS, managerBucket, MANAGER_LEASE_TTL_MS, membershipBucket, MEMBERSHIP_MAX_BYTES, presenceBucket, recreateConsumerCheckpoint, spaceBackupInventory, uploadStreamRestoreChunk, validateSpaceAuth, validateSpaceBackupInventory, validateBackupStreamState, validateCanonicalBackupStreamConfig, } from "@cotal-ai/core";
|
|
7
|
+
import { canonicalBackupStreamConfig, consumerConfigFromCheckpoint, deliveryBucket, downloadStreamSnapshot, finalizeStreamRestore, hardenPrivate, initiateStreamRestore, LEASE_TTL_MS, managerBucket, MANAGER_LEASE_TTL_MS, membershipBucket, MEMBERSHIP_MAX_BYTES, presenceBucket, recreateConsumerCheckpoint, spaceBackupInventory, uploadStreamRestoreChunk, validateSpaceAuth, validateSpaceBackupInventory, validateBackupStreamState, validateCanonicalBackupStreamConfig, ensureArtifactStore, } from "@cotal-ai/core";
|
|
8
8
|
import { acquireMaintenanceLock, assessRestoreClaim, bindRestoreListener, bindRestoreTarget, getSpaceAuth, markRestoreActive, markRestoreDegraded, moveSamePathRestoreSource, prepareAlternateRestore, prepareMissingSourceRestore, prepareSamePathRestore, readMaintenanceJournal, readMaintenanceResumeDocument, recordRestoreAttemptResources, recordRestoreManagerCommit, replaceDeadRestoreListener, repairRestoreDegradedToActive, releaseMaintenanceLock, rollbackRestore, workspaceSecretStore, writeRestoreCommitIntent, } from "@cotal-ai/workspace";
|
|
9
9
|
import { readStagedCheckpoints, stageArtifact } from "./backup-artifact.js";
|
|
10
10
|
import { authorityFingerprint } from "./maintenance-files.js";
|
|
@@ -210,8 +210,18 @@ async function validateManifest(manifest, flags, ready, currentAuthority) {
|
|
|
210
210
|
validateBackupStreamState(record.state);
|
|
211
211
|
}
|
|
212
212
|
if (manifest.selection === "full" && flags["restore-only"] !== "registry") {
|
|
213
|
-
if (!manifest.authority || JSON.stringify(manifest.authority) !== JSON.stringify(currentAuthority))
|
|
214
|
-
|
|
213
|
+
if (!manifest.authority || JSON.stringify(manifest.authority) !== JSON.stringify(currentAuthority)) {
|
|
214
|
+
// Name the LIKELIEST drift instead of leaving a bare hash mismatch. The commitment covers the
|
|
215
|
+
// operator JWT, the system account and the data account; when the DATA account still matches,
|
|
216
|
+
// what moved is the broker half, and since `cotal up --rotate-sys` re-issues exactly those two
|
|
217
|
+
// on a 30-day cadence, "you rotated after taking this backup" is the common case, not an exotic
|
|
218
|
+
// one. Without this the operator sees an opaque fingerprint mismatch on the artifact they were
|
|
219
|
+
// counting on during a disaster.
|
|
220
|
+
const sameAccount = manifest.authority?.account !== undefined && manifest.authority.account === currentAuthority.account;
|
|
221
|
+
throw new Error(sameAccount
|
|
222
|
+
? "backup authority fingerprint does not match current trust state: the data account is unchanged, so the OPERATOR/SYSTEM half of the trust chain moved - this artifact predates a system-account rotation (`cotal up --rotate-sys`) and is bound to the retired chain. Restore it into a root holding that chain, or use a backup taken after the rotation."
|
|
223
|
+
: "backup authority fingerprint does not match current trust state");
|
|
224
|
+
}
|
|
215
225
|
}
|
|
216
226
|
}
|
|
217
227
|
/** Smoke hook: `COTAL_SMOKE_FAIL_RESTORE_STREAM=<stream>` fires on any pass; `<pass>:<stream>`
|
|
@@ -366,6 +376,14 @@ async function createOmittedInfrastructure(broker, space, registryOnly) {
|
|
|
366
376
|
await kvm.create(membershipBucket(space), { history: 1, max_bytes: MEMBERSHIP_MAX_BYTES });
|
|
367
377
|
await kvm.create(deliveryBucket(space), { ttl: LEASE_TTL_MS });
|
|
368
378
|
await kvm.create(managerBucket(space), { ttl: MANAGER_LEASE_TTL_MS });
|
|
379
|
+
// The artifact Object Store is EXCLUDED from the backup artifact, which does not mean restore
|
|
380
|
+
// ignores it: the assertion below covers `excluded` too, so a restored space must come back
|
|
381
|
+
// with an EMPTY store rather than none. Excluding a stream and forgetting to recreate it is the
|
|
382
|
+
// failure that only appears at restore - the one moment nobody is watching for a new defect.
|
|
383
|
+
// Create-or-verify (not a bare create): a restore target that already holds a drifted store must
|
|
384
|
+
// refuse rather than adopt it, which matters more here than at setup - a restore is exactly when
|
|
385
|
+
// an operator is least able to tell an inherited config from a fresh one.
|
|
386
|
+
await ensureArtifactStore(nc, space);
|
|
369
387
|
for (const stream of [...create, ...excluded])
|
|
370
388
|
await jsm.streams.info(stream);
|
|
371
389
|
// The normal listener is exposed only over a complete space: assert the exact stream inventory
|