@cotal-ai/cli 0.50.1 → 0.51.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 (88) hide show
  1. package/dist/command.d.ts.map +1 -1
  2. package/dist/command.js +24 -1
  3. package/dist/command.js.map +1 -1
  4. package/dist/commands/agents.d.ts.map +1 -1
  5. package/dist/commands/agents.js +18 -1
  6. package/dist/commands/agents.js.map +1 -1
  7. package/dist/commands/down.d.ts.map +1 -1
  8. package/dist/commands/down.js +114 -5
  9. package/dist/commands/down.js.map +1 -1
  10. package/dist/commands/endpoints.d.ts.map +1 -1
  11. package/dist/commands/endpoints.js +2 -1
  12. package/dist/commands/endpoints.js.map +1 -1
  13. package/dist/commands/join.d.ts.map +1 -1
  14. package/dist/commands/join.js +25 -0
  15. package/dist/commands/join.js.map +1 -1
  16. package/dist/commands/meshes-add.d.ts +2 -54
  17. package/dist/commands/meshes-add.d.ts.map +1 -1
  18. package/dist/commands/meshes-add.js +20 -105
  19. package/dist/commands/meshes-add.js.map +1 -1
  20. package/dist/commands/meshes.d.ts.map +1 -1
  21. package/dist/commands/meshes.js +5 -2
  22. package/dist/commands/meshes.js.map +1 -1
  23. package/dist/commands/service.d.ts +17 -0
  24. package/dist/commands/service.d.ts.map +1 -0
  25. package/dist/commands/service.js +541 -0
  26. package/dist/commands/service.js.map +1 -0
  27. package/dist/commands/spawn.d.ts +44 -2
  28. package/dist/commands/spawn.d.ts.map +1 -1
  29. package/dist/commands/spawn.js +292 -45
  30. package/dist/commands/spawn.js.map +1 -1
  31. package/dist/commands/status.d.ts.map +1 -1
  32. package/dist/commands/status.js +11 -4
  33. package/dist/commands/status.js.map +1 -1
  34. package/dist/commands/sync.d.ts +50 -0
  35. package/dist/commands/sync.d.ts.map +1 -0
  36. package/dist/commands/sync.js +284 -0
  37. package/dist/commands/sync.js.map +1 -0
  38. package/dist/commands/up.d.ts.map +1 -1
  39. package/dist/commands/up.js +71 -13
  40. package/dist/commands/up.js.map +1 -1
  41. package/dist/commands/update.d.ts.map +1 -1
  42. package/dist/commands/update.js +26 -5
  43. package/dist/commands/update.js.map +1 -1
  44. package/dist/commands/use.js +1 -1
  45. package/dist/commands/use.js.map +1 -1
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +27 -0
  48. package/dist/index.js.map +1 -1
  49. package/dist/lib/manifest/apply.d.ts.map +1 -1
  50. package/dist/lib/manifest/apply.js +2 -0
  51. package/dist/lib/manifest/apply.js.map +1 -1
  52. package/dist/lib/manifest/model.d.ts +2 -0
  53. package/dist/lib/manifest/model.d.ts.map +1 -1
  54. package/dist/lib/manifest/prepare.d.ts +2 -0
  55. package/dist/lib/manifest/prepare.d.ts.map +1 -1
  56. package/dist/lib/manifest/prepare.js +1 -0
  57. package/dist/lib/manifest/prepare.js.map +1 -1
  58. package/dist/lib/manifest/resolve.js +1 -0
  59. package/dist/lib/manifest/resolve.js.map +1 -1
  60. package/dist/lib/manifest/schema.d.ts +2 -0
  61. package/dist/lib/manifest/schema.d.ts.map +1 -1
  62. package/dist/lib/manifest/schema.js +2 -0
  63. package/dist/lib/manifest/schema.js.map +1 -1
  64. package/dist/lib/restore.d.ts +3 -0
  65. package/dist/lib/restore.d.ts.map +1 -1
  66. package/dist/lib/restore.js +17 -0
  67. package/dist/lib/restore.js.map +1 -1
  68. package/dist/lib/seat-admission.d.ts +51 -0
  69. package/dist/lib/seat-admission.d.ts.map +1 -0
  70. package/dist/lib/seat-admission.js +81 -0
  71. package/dist/lib/seat-admission.js.map +1 -0
  72. package/dist/lib/seat-capture.d.ts +47 -0
  73. package/dist/lib/seat-capture.d.ts.map +1 -0
  74. package/dist/lib/seat-capture.js +195 -0
  75. package/dist/lib/seat-capture.js.map +1 -0
  76. package/dist/lib/seat-restore.d.ts +39 -0
  77. package/dist/lib/seat-restore.d.ts.map +1 -0
  78. package/dist/lib/seat-restore.js +249 -0
  79. package/dist/lib/seat-restore.js.map +1 -0
  80. package/dist/lib/seat-resume.d.ts +24 -0
  81. package/dist/lib/seat-resume.d.ts.map +1 -0
  82. package/dist/lib/seat-resume.js +127 -0
  83. package/dist/lib/seat-resume.js.map +1 -0
  84. package/package.json +5 -5
  85. package/dist/lib/join-target.d.ts +0 -173
  86. package/dist/lib/join-target.d.ts.map +0 -1
  87. package/dist/lib/join-target.js +0 -335
  88. package/dist/lib/join-target.js.map +0 -1
@@ -0,0 +1,284 @@
1
+ import { join } from "node:path";
2
+ import { mkSecretDir, registry, resolveAuthProvider, writeSecretFileAtomic } from "@cotal-ai/core";
3
+ import { clearCurrent, findCotalRoot, findMesh, getCurrent, homeCotalDir, loadMeshes, meshesForRoot, recordMesh, removeMesh, userAuthStateDir, } from "@cotal-ai/workspace";
4
+ import { checkUserBundle } from "./meshes-add.js";
5
+ import { c } from "../ui.js";
6
+ const syncFlags = [
7
+ { name: "idp", type: "string", value: "<auth base URL>", description: "refresh only this signed-in IdP account" },
8
+ ];
9
+ export { syncFlags };
10
+ function isRecord(value) {
11
+ return value !== null && typeof value === "object" && !Array.isArray(value);
12
+ }
13
+ /** Canonicalize an IdP identity for account binding with the same URL shape the stock provider
14
+ * accepts: HTTPS, or loopback HTTP; no credentials, query, fragment, or trailing slash. This is not
15
+ * a bundle validator. It compares already-validated registration trust to the proved account. */
16
+ function canonicalIdpUrl(raw, what) {
17
+ let url;
18
+ try {
19
+ url = new URL(raw);
20
+ }
21
+ catch {
22
+ throw new Error(`${what} is not a valid URL`);
23
+ }
24
+ const loopback = url.hostname === "127.0.0.1" || url.hostname === "[::1]" || url.hostname === "localhost";
25
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback))
26
+ throw new Error(`${what} must be https (or loopback http for local development)`);
27
+ if (url.username || url.password || url.search || url.hash)
28
+ throw new Error(`${what} must not contain credentials, a query, or a fragment`);
29
+ return `${url.origin}${url.pathname.replace(/\/$/, "")}`;
30
+ }
31
+ function assertRegistrationAccountBinding(bundle, account, label) {
32
+ const accountIdp = canonicalIdpUrl(account.idpUrl, "the proved account IdP URL");
33
+ const registrationIdp = canonicalIdpUrl(bundle.userAuth.idp.url, `${label} IdP URL`);
34
+ if (registrationIdp !== accountIdp || bundle.userAuth.idp.issuer !== account.issuer)
35
+ throw new Error(`${label} names IdP trust that differs from the proved catalog account`);
36
+ const accountOrigin = new URL(accountIdp).origin;
37
+ for (const [name, raw] of [
38
+ ["exchange endpoint", bundle.userAuth.endpoints?.url],
39
+ ["agent-provisioning endpoint", bundle.userAuth.endpoints?.agentProvisioningUrl],
40
+ ["manager-authority endpoint", bundle.userAuth.endpoints?.managerAuthorityUrl],
41
+ ]) {
42
+ if (!raw)
43
+ continue;
44
+ let endpoint;
45
+ try {
46
+ endpoint = new URL(raw);
47
+ }
48
+ catch {
49
+ throw new Error(`${label} ${name} is not a valid URL`);
50
+ }
51
+ if (endpoint.username || endpoint.password || endpoint.origin !== accountOrigin)
52
+ throw new Error(`${label} ${name} is not same-origin with the proved catalog account`);
53
+ }
54
+ }
55
+ export function validateCatalogSnapshot(value, account) {
56
+ if (!isRecord(value) || value.v !== 1 || !isRecord(value.account) || !Array.isArray(value.spaces))
57
+ throw new Error("the space catalog is not a v1 snapshot");
58
+ if (value.account.idpUrl !== account.idpUrl || value.account.issuer !== account.issuer || value.account.sub !== account.sub)
59
+ throw new Error("the space catalog account does not match the proved login");
60
+ const slugs = new Set();
61
+ for (let i = 0; i < value.spaces.length; i++) {
62
+ const row = value.spaces[i];
63
+ if (!isRecord(row))
64
+ throw new Error(`space catalog entry ${i + 1} is not an object`);
65
+ for (const key of ["id", "slug", "name", "kind", "role"])
66
+ if (typeof row[key] !== "string" || row[key].length === 0)
67
+ throw new Error(`space catalog entry ${i + 1} has no ${key}`);
68
+ const checked = checkUserBundle(JSON.stringify(row.registration));
69
+ if (!checked.ok)
70
+ throw new Error(`space catalog entry "${row.name}": ${checked.message.replace(/^✗ /, "")}`);
71
+ assertRegistrationAccountBinding(checked.value, account, `space catalog entry "${row.name}"`);
72
+ if (checked.value.space !== row.slug)
73
+ throw new Error(`space catalog entry "${row.name}" (${row.slug}) registration names space "${checked.value.space}"`);
74
+ if (slugs.has(row.slug))
75
+ throw new Error(`space catalog repeats the slug "${row.slug}"`);
76
+ slugs.add(row.slug);
77
+ row.registration = checked.value;
78
+ }
79
+ }
80
+ function catalogRoot(ownerKey, space) {
81
+ return join(homeCotalDir(), "catalog", ownerKey, encodeURIComponent(space));
82
+ }
83
+ function entryFor(account, row, fetchedAt, error) {
84
+ const root = catalogRoot(account.ownerKey, row.slug);
85
+ const dir = userAuthStateDir(root, row.slug);
86
+ const sentinelCredsPath = join(dir, "sentinel.creds");
87
+ return {
88
+ space: row.slug,
89
+ server: row.registration.server,
90
+ root,
91
+ mode: "user",
92
+ origin: "catalog",
93
+ catalogOwner: account.ownerKey,
94
+ catalogId: row.id,
95
+ catalogSlug: row.slug,
96
+ catalogName: row.name,
97
+ catalogKind: row.kind,
98
+ catalogRole: row.role,
99
+ ...(fetchedAt ? { catalogFetchedAt: fetchedAt } : {}),
100
+ ...(error ? { catalogError: error } : {}),
101
+ ...(row.registration.tlsRequired ? { tlsRequired: true } : {}),
102
+ ...(row.registration.policy ? { policy: row.registration.policy } : {}),
103
+ userAuth: { ...row.registration.userAuth, remote: true, sentinelCredsPath },
104
+ ts: new Date().toISOString(),
105
+ };
106
+ }
107
+ function writeCatalogCredential(entry, row) {
108
+ const path = entry.userAuth?.sentinelCredsPath;
109
+ if (!path)
110
+ throw new Error(`catalog registration for "${entry.space}" has no sentinel credential path`);
111
+ mkSecretDir(userAuthStateDir(entry.root, entry.space));
112
+ writeSecretFileAtomic(path, row.registration.sentinelCreds);
113
+ }
114
+ function sameEntry(a, b) {
115
+ const clean = (m) => ({ ...m, ts: undefined, catalogFetchedAt: undefined, catalogError: undefined });
116
+ return JSON.stringify(clean(a)) === JSON.stringify(clean(b));
117
+ }
118
+ const emptyDiff = () => ({ added: [], changed: [], removed: [], unchanged: [], collisions: [] });
119
+ /** One account can be applied twice in one preparation: a repair of an interrupted application,
120
+ * then the refreshed snapshot. Report each slug against the registry the command started from, so
121
+ * the first classification of a slug stands. */
122
+ function mergeDiff(prior, next) {
123
+ if (!prior)
124
+ return next;
125
+ const lists = ["added", "changed", "removed", "unchanged"];
126
+ const seen = new Set(lists.flatMap((k) => prior[k]));
127
+ const merged = { ...prior, collisions: [...new Set([...prior.collisions, ...next.collisions])].sort() };
128
+ for (const k of lists)
129
+ merged[k] = [...prior[k], ...next[k].filter((s) => !seen.has(s))].sort();
130
+ if (!merged.selectionInvalidated && next.selectionInvalidated)
131
+ merged.selectionInvalidated = next.selectionInvalidated;
132
+ return merged;
133
+ }
134
+ /** Reconcile the registry with one account's result. The provider calls this under its catalog
135
+ * lock, so no other preparation reads or writes discovered entries while it runs, and it is
136
+ * idempotent: the provider applies a cached snapshot again when an earlier application never
137
+ * finished. An unforced fresh or not-modified result is already applied and writes nothing. */
138
+ function consume(result, force) {
139
+ return result.state === "updated" || result.state === "failed" || force ? applyResult(result) : emptyDiff();
140
+ }
141
+ function applyResult(result) {
142
+ const before = loadMeshes().filter((m) => m.origin === "catalog" && m.catalogOwner === result.account.ownerKey);
143
+ const priorByName = new Map(before.map((m) => [m.space, m]));
144
+ const diff = emptyDiff();
145
+ if (result.state === "failed") {
146
+ for (const old of before)
147
+ recordMesh({ ...old, ...(result.fetchedAt ? { catalogFetchedAt: result.fetchedAt } : {}), catalogError: result.error ?? "refresh failed" });
148
+ return diff;
149
+ }
150
+ if (result.snapshot === undefined)
151
+ return diff;
152
+ validateCatalogSnapshot(result.snapshot, result.account);
153
+ const snapshot = result.snapshot;
154
+ const nextSlugs = new Set(snapshot.spaces.map((s) => s.slug));
155
+ // Invalidate the selection BEFORE the first registry write. Once an entry is removed, a later
156
+ // application (after a death here) can no longer tell that the selected name belonged to this
157
+ // account, and the selection would outlive its entry.
158
+ const current = getCurrent();
159
+ if (current && priorByName.has(current) && !nextSlugs.has(current)) {
160
+ clearCurrent();
161
+ diff.selectionInvalidated = current;
162
+ }
163
+ for (const old of before) {
164
+ if (nextSlugs.has(old.space))
165
+ continue;
166
+ removeMesh(old.space);
167
+ diff.removed.push(old.space);
168
+ }
169
+ for (const row of snapshot.spaces) {
170
+ const existing = findMesh(row.slug);
171
+ if (existing && (existing.origin !== "catalog" || existing.catalogOwner !== result.account.ownerKey)) {
172
+ diff.collisions.push(row.slug);
173
+ continue;
174
+ }
175
+ const next = entryFor(result.account, row, result.fetchedAt);
176
+ const prior = priorByName.get(row.slug);
177
+ writeCatalogCredential(next, row);
178
+ recordMesh(next);
179
+ if (!prior)
180
+ diff.added.push(row.slug);
181
+ else if (sameEntry(prior, next))
182
+ diff.unchanged.push(row.slug);
183
+ else
184
+ diff.changed.push(row.slug);
185
+ }
186
+ for (const list of [diff.added, diff.changed, diff.removed, diff.unchanged, diff.collisions])
187
+ list.sort();
188
+ return diff;
189
+ }
190
+ export async function prepareCatalogTargets(opts = {}) {
191
+ const provider = resolveAuthProvider();
192
+ if (!provider.prepareSpaceCatalogs)
193
+ throw new Error(`auth provider "${provider.name}" does not support space catalogs`);
194
+ const applied = new Map();
195
+ const results = await provider.prepareSpaceCatalogs({
196
+ dir: homeCotalDir(),
197
+ ...(opts.idpUrl ? { idpUrl: opts.idpUrl } : {}),
198
+ ...(opts.force ? { force: true } : {}),
199
+ validate: validateCatalogSnapshot,
200
+ apply: (result) => void applied.set(result.account.ownerKey, mergeDiff(applied.get(result.account.ownerKey), consume(result, Boolean(opts.force)))),
201
+ });
202
+ return { results, diffs: results.map((result) => applied.get(result.account.ownerKey) ?? emptyDiff()) };
203
+ }
204
+ /** Shared once-per-command preparation. A named manual/local entry never depends on discovery and
205
+ * makes no request here: a manual entry's policy refresh runs where a launch, join, or manager start
206
+ * consumes it. Unknown names force one refresh even inside the freshness window. `status` keeps a
207
+ * failed stale snapshot only as timestamped diagnostics; operational commands refuse before target
208
+ * resolution. */
209
+ export async function prepareCatalogCommand(args, diagnostics = false, command) {
210
+ const values = args.values;
211
+ const requested = values.space ?? (command === "use" ? args.positionals[0] : undefined);
212
+ const named = requested ? findMesh(requested) : undefined;
213
+ if (named && named.origin !== "catalog")
214
+ return;
215
+ if (!requested && command !== "meshes") {
216
+ const current = getCurrent();
217
+ const selected = current ? findMesh(current) : undefined;
218
+ if (selected && selected.origin !== "catalog")
219
+ return;
220
+ const local = meshesForRoot(findCotalRoot()).filter((m) => m.origin !== "catalog");
221
+ if (local.length > 0)
222
+ return;
223
+ const registered = loadMeshes();
224
+ if (registered.length === 1 && registered[0].origin !== "catalog")
225
+ return;
226
+ }
227
+ const force = Boolean(requested && !named);
228
+ if (registry.all("auth-provider").length === 0)
229
+ return;
230
+ const provider = resolveAuthProvider();
231
+ if (!provider.prepareSpaceCatalogs)
232
+ return;
233
+ const diffs = [];
234
+ const results = await provider.prepareSpaceCatalogs({
235
+ dir: homeCotalDir(),
236
+ ...(named?.origin === "catalog" && named.userAuth?.idp.url ? { idpUrl: named.userAuth.idp.url } : {}),
237
+ ...(force ? { force: true } : {}),
238
+ validate: validateCatalogSnapshot,
239
+ apply: (result) => void diffs.push(consume(result, force)),
240
+ });
241
+ if (results.every((r) => r.state === "no-catalog" && r.snapshot === undefined))
242
+ return;
243
+ const vanished = diffs.map((d) => d.selectionInvalidated).filter((s) => Boolean(s));
244
+ if (vanished.length) {
245
+ const message = `selected space "${vanished.join("\", \"")}" vanished from its account catalog; no default mesh is selected`;
246
+ if (diagnostics)
247
+ console.error(c.yellow(message));
248
+ else
249
+ throw new Error(message);
250
+ }
251
+ if (diagnostics)
252
+ return;
253
+ const failures = results.filter((r) => r.state === "failed");
254
+ if (failures.length)
255
+ throw new Error(failures.map((r) => `space catalog for ${r.account.idpUrl} failed: ${r.error}`).join("; "));
256
+ }
257
+ export async function sync(args) {
258
+ const values = args.values;
259
+ const { results, diffs } = await prepareCatalogTargets({ idpUrl: values.idp, force: true });
260
+ if (results.length === 0) {
261
+ console.log(c.dim("no signed-in IdP accounts"));
262
+ return;
263
+ }
264
+ results.forEach((result, i) => {
265
+ const d = diffs[i];
266
+ const catalog = result.account.catalogUrl ? result.account.catalogUrl : "no catalog advertised";
267
+ console.log(`${result.account.idpUrl} ${result.state} ${catalog}`);
268
+ for (const [label, names] of [["added", d.added], ["changed", d.changed], ["removed", d.removed], ["unchanged", d.unchanged], ["collisions", d.collisions]])
269
+ console.log(` ${label.padEnd(10)} ${names.length ? names.join(", ") : "-"}`);
270
+ if (d.selectionInvalidated)
271
+ console.log(c.yellow(` selected space "${d.selectionInvalidated}" vanished; no default mesh is selected`));
272
+ });
273
+ const failures = results.filter((r) => r.state === "failed");
274
+ if (failures.length)
275
+ throw new Error(failures.map((r) => `space catalog for ${r.account.idpUrl} failed: ${r.error}`).join("; "));
276
+ }
277
+ const spaceCatalogConsumer = {
278
+ kind: "space-catalog-consumer",
279
+ name: "workspace",
280
+ validate: validateCatalogSnapshot,
281
+ apply: (result) => void consume(result, true),
282
+ };
283
+ registry.register(spaceCatalogConsumer);
284
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,16 @@
1
1
  import { spawn } from "node:child_process";
2
- import { randomUUID } from "node:crypto";
2
+ import { createHash, randomUUID } from "node:crypto";
3
3
  import { createConnection, createServer } from "node:net";
4
4
  import { hostname } from "node:os";
5
5
  import { mkdirSync, writeFileSync, readFileSync, existsSync, openSync, statSync, readSync, closeSync, lstatSync, rmSync, realpathSync, } from "node:fs";
6
6
  import { dirname, join, resolve } from "node:path";
7
7
  import { isReachable, DEFAULT_SERVER, createSpaceAuth, serverConfig, openServerConfig, validateTlsMaterial, mintCreds, mintLifecycleUid, DEV_OWNER, mintConnectionEvictorCreds, mintMembershipObserverCreds, newIdentity, setupSpaceStreams, reconcileSpaceTtls, standaloneConnectOpts, seedChannelRegistry, ensureDefaultDeliveryClass, mkSecretDir, writeSecretFile, } from "@cotal-ai/core";
8
8
  import { connect } from "@nats-io/transport-node";
9
- import { assertSingleSpaceBroker, assertUserAuthInfo, authDir, getSoleSpaceAuth, getSpaceAuth, hasUserAuthState, listSpaceAccounts, preloadSpaceAccounts, putSpaceAuth, clearCurrent, findMesh, getCurrent, loadMeshes, connectionEvictorCredsKey, membershipConfigPath, membershipObserverCredsKey, membershipRwCredsKey, MEMBERSHIP_CONFIG_KIND, MEMBERSHIP_RW_CREDS_KIND, parsePositiveIntegerFlag, recordMesh, meshesForRoot, removeMesh, rotateSystemCreds, setCurrent, staleSystemCreds, SYSTEM_CREDS_FILES, userAuthStateDir, workspaceSecretStore, acquireMaintenanceLock, assertStoreIdentity, assessRestoreClaim, beginOrdinaryResume, bindOrdinaryResumeListener, consumeRetiredMaintenance, markOrdinaryResumeActive, markOrdinaryResumeDegraded, replaceDeadOrdinaryResumeListener, localProcessOwnerStatus, readMaintenanceJournal, readMaintenanceResumeDocument, readStoreIdentity, recordOrdinaryResumeManagerCommit, releaseMaintenanceLock, retireOrdinaryResume, sameStoreIdentity, readBrokerPolicy, writeBrokerPolicy, removeIdentityPin, writeIdentityPin, } from "@cotal-ai/workspace";
9
+ import { assertSingleSpaceBroker, assertUserAuthInfo, authDir, getSoleSpaceAuth, getSpaceAuth, hasUserAuthState, listSpaceAccounts, preloadSpaceAccounts, putSpaceAuth, clearCurrent, findMesh, getCurrent, loadMeshes, connectionEvictorCredsKey, membershipConfigPath, membershipObserverCredsKey, membershipRwCredsKey, MEMBERSHIP_CONFIG_KIND, MEMBERSHIP_RW_CREDS_KIND, parsePositiveIntegerFlag, recordMesh, meshesForRoot, removeMesh, rotateSystemCreds, setCurrent, staleSystemCreds, SYSTEM_CREDS_FILES, userAuthStateDir, userAuthSpacesOnDisk, workspaceSecretStore, acquireMaintenanceLock, assertStoreIdentity, assessRestoreClaim, beginOrdinaryResume, bindOrdinaryResumeListener, consumeRetiredMaintenance, markOrdinaryResumeActive, markOrdinaryResumeDegraded, replaceDeadOrdinaryResumeListener, localProcessOwnerStatus, readMaintenanceJournal, readMaintenanceResumeDocument, seatCheckpointDir, readStoreIdentity, recordOrdinaryResumeManagerCommit, releaseMaintenanceLock, retireOrdinaryResume, sameStoreIdentity, readBrokerPolicy, writeBrokerPolicy, removeIdentityPin, writeIdentityPin, } from "@cotal-ai/workspace";
10
10
  import { ensureAuthService, resolveAuthProvider, stopAuthService } from "../lib/auth-proc.js";
11
11
  import { resolveSpace } from "../lib/status.js";
12
12
  import { c } from "../ui.js";
13
+ import { admitAndRestoreSeatCheckpoints } from "../lib/seat-resume.js";
13
14
  import { resolveNatsServer } from "../lib/nats-bin.js";
14
15
  import { cotalPath, cotalRoot } from "../lib/paths.js";
15
16
  import { renderDetachedSummary } from "../lib/up-report.js";
@@ -31,7 +32,7 @@ const pendingOrdinaryResumes = new Map();
31
32
  /** `cotal up` flags — colocated with the command (like `spawnFlags`) so its completion can read them. */
32
33
  export const upFlags = [
33
34
  { name: "server", type: "string", value: "<url>", description: "listen URL override" },
34
- { name: "host", type: "string", value: "<host>", description: "bind host override" },
35
+ { name: "host", type: "string", value: "<host>", description: "bind host override (an IP/hostname, not a URL; the URL is --server)" },
35
36
  { name: "space", type: "string", value: "<s>", description: "space name (default: the folder's)" },
36
37
  { name: "store-dir", type: "string", value: "<dir>", description: "JetStream store directory" },
37
38
  { name: "channels", type: "string", value: "<path>", description: "channel-registry seed file (JSON; default .cotal/channels.json)" },
@@ -40,6 +41,7 @@ export const upFlags = [
40
41
  { name: "restore", type: "string", value: "<dir>", description: "restore an offline backup before exposing the normal listener" },
41
42
  { name: "restore-only", type: "string", value: "<registry>", description: "restore only the registry component" },
42
43
  { name: "accept-missing-source", type: "boolean", description: "explicit disaster consent when the inode-bound preserved source is absent" },
44
+ { name: "accept-stale-checkpoint", type: "boolean", description: "explicit consent to resume a seat checkpoint captured outside its recorded recency horizon" },
43
45
  { name: "open", type: "boolean", description: "unauthenticated dev mesh (no JWT/ACLs)" },
44
46
  { name: "user-auth", type: "boolean", description: "per-USER auth: login + bearer through the space's auth service" },
45
47
  { name: "idp", type: "string", value: "<url>", description: "with --user-auth: the IdP auth base URL to pin (first enable)" },
@@ -206,6 +208,10 @@ async function runUp(args, inheritedLock, onAdopt) {
206
208
  if (values.runtime && runtimes[0] && values.runtime !== runtimes[0])
207
209
  throw new Error(`--runtime ${values.runtime} contradicts the preserved agent runtime ${runtimes[0]}; omit it to resume the same principals`);
208
210
  const resumeRuntime = values.runtime ?? runtimes[0] ?? "pty";
211
+ // Admit every seat checkpoint the cut wrote and take custody, BEFORE the resume attempt is
212
+ // journalled and long before a manager starts. A refusal here costs nothing because
213
+ // nothing has been started; the same refusal after a launch would be a second writer.
214
+ const staleConsent = admitAndRestoreSeatCheckpoints(root, journal.space, journal.cut.attemptId, values, resume.inventory);
209
215
  const serverNonce = randomUUID().replaceAll("-", "");
210
216
  const serverName = `${attemptId}-${serverNonce}`;
211
217
  beginOrdinaryResume(lock, {
@@ -217,6 +223,12 @@ async function runUp(args, inheritedLock, onAdopt) {
217
223
  detached: Boolean(values.detach),
218
224
  serverName,
219
225
  serverNonce,
226
+ // Durable evidence of consent, not a print. An operator asking later why a seat resumed
227
+ // from a checkpoint past its horizon must be able to read that it was admitted, for
228
+ // which seat, and by how far, from the journal rather than from a lost terminal.
229
+ ...(staleConsent.length
230
+ ? { acceptedStaleCheckpoints: staleConsent.map((seat) => ({ ...seat })) }
231
+ : {}),
220
232
  },
221
233
  });
222
234
  pending = {
@@ -1671,7 +1683,7 @@ async function upManifest(file, opts) {
1671
1683
  const host = m.broker?.host ?? "127.0.0.1";
1672
1684
  // Same bind-vs-probe reconciliation as the flag path: a manifest that sets `broker.host` without
1673
1685
  // an explicit `broker.servers` would otherwise bind one address and be probed at another.
1674
- const server = m.broker?.host ? reconcileHostAndServer(m.broker.host, m.broker?.servers) : (m.broker?.servers ?? DEFAULT_SERVER);
1686
+ const server = m.broker?.host ? reconcileHostAndServer(m.broker.host, m.broker?.servers, "broker.host", "broker.servers") : (m.broker?.servers ?? DEFAULT_SERVER);
1675
1687
  const open = m.broker?.auth === false; // default is auth
1676
1688
  const userAuth = m.broker?.auth === "user" ? { idpUrl: opts.idp ?? m.broker?.idp } : undefined; // flag > manifest
1677
1689
  const runtime = m.runtime ?? "pty";
@@ -2073,8 +2085,8 @@ export async function claimSpace(space, server, root) {
2073
2085
  // reclaimed: unreachable is not proof the mesh is gone (the record describes a broker on another
2074
2086
  // machine), the reclaim runs BEFORE this launch starts anything, and `cotal down` — what the
2075
2087
  // liveness branch below would advise — cannot stop a mesh this machine does not run.
2076
- if (existing.origin === "manual")
2077
- throw new Error(`space "${space}" is registered to a mesh at ${existing.server} (${existing.root}) - it was registered by hand, so \`cotal up\` neither takes it over nor reclaims the name: \`cotal meshes rm ${space}\` to drop that record first, or start this one under a different \`--space\``);
2088
+ if (existing.origin === "manual" || existing.origin === "catalog")
2089
+ throw new Error(`space "${space}" is registered to a mesh at ${existing.server} (${existing.root}) - it is ${existing.origin === "catalog" ? "owned by a signed-in space catalog" : "registered by hand"}, so \`cotal up\` neither takes it over nor reclaims the name: ${existing.origin === "catalog" ? "use a different `--space`, or remove access at the IdP and run `cotal sync`" : `\`cotal meshes rm ${space}\` to drop that record first, or start this one under a different \`--space\``}`);
2078
2090
  if (await isReachable(existing.server)) {
2079
2091
  throw new Error(`space "${space}" is already in use by a mesh at ${existing.server} (${existing.root}) - pick a different \`--space\`, or \`cotal down\` it first`);
2080
2092
  }
@@ -2117,7 +2129,7 @@ function recordOurMesh(m, provenance) {
2117
2129
  const cur = getCurrent();
2118
2130
  const usableCurrent = cur && findMesh(cur) ? cur : undefined; // compute before recording m
2119
2131
  const prior = findMesh(m.space);
2120
- const origin = provenance === "refresh" && prior?.origin === "manual" ? "manual" : "up";
2132
+ const origin = provenance === "refresh" && (prior?.origin === "manual" || prior?.origin === "catalog") ? prior.origin : "up";
2121
2133
  // A REFRESH starts nothing: it concluded the mesh is up from reachability alone, and rebuilds `m`
2122
2134
  // from what THIS launch knows, which is never the operator's past decisions. `origin` was already
2123
2135
  // carried across for that reason; the overlay acceptance is the same class and was not, so a
@@ -2170,6 +2182,36 @@ async function waitReady(server, creds) {
2170
2182
  * the probe/registry URL stays whatever it already is (loopback by default), which the wildcard
2171
2183
  * bind necessarily covers. */
2172
2184
  const WILDCARD_HOSTS = new Set(["0.0.0.0", "::", "[::]"]);
2185
+ /** Establish that a bind-host value IS a host, BEFORE anything brackets it, and return the
2186
+ * bracketed literal a URL can hold (#1697).
2187
+ *
2188
+ * `--host` is the bind address; its sibling `--server` takes a URL, the registry stores and prints
2189
+ * URLs, and every message in this area shows one — so an operator plausibly types the URL here
2190
+ * (the manifest's `broker.host` carries the same ambiguity against `broker.servers`). Unrejected,
2191
+ * the IPv6 bracketing wrapped it into `nats://[nats://127.0.0.1:4222]:4222`, which is not a URL at
2192
+ * all. Nothing checked the derived string: the first code to look at it compared it with the
2193
+ * space's registry record, failed for a reason unrelated to what was typed, and showed the
2194
+ * operator the "registered by hand" refusal whose remedy de-registers a live mesh. Refused by name
2195
+ * here instead — pointing at the URL-carrying sibling — and a value that still cannot serve as a
2196
+ * URL host (a `host:port` spelling, say) is refused rather than reaching that comparison as a
2197
+ * silently wrong server string. Never rewritten: a value this flag cannot use is an error, not a
2198
+ * URL to derive from. */
2199
+ function assertBindableHost(host, source, urlSource) {
2200
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(host)) {
2201
+ console.error(c.red(`✗ ${source} ${host} looks like a URL - it takes a bind host only (an IP or hostname, no scheme); pass the broker URL with ${urlSource} instead`));
2202
+ process.exit(1);
2203
+ }
2204
+ const literal = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
2205
+ try {
2206
+ // ONE parse, both consumers served from it: `literal` builds the derived URL (a URL host needs
2207
+ // the brackets), `hostname` compares against the explicit server's (the URL API strips them).
2208
+ return { literal, hostname: new URL(`nats://${literal}:1`).hostname };
2209
+ }
2210
+ catch {
2211
+ console.error(c.red(`✗ ${source} ${host} is not a valid bind host - an IP or hostname only, with no port; the port comes from ${urlSource} (or its default), never from the bind host`));
2212
+ process.exit(1);
2213
+ }
2214
+ }
2173
2215
  /**
2174
2216
  * Reconcile the bind address (`--host`, manifest `broker.host`) with the broker URL the readiness
2175
2217
  * probe, the mesh registry, and every later client use.
@@ -2180,16 +2222,19 @@ const WILDCARD_HOSTS = new Set(["0.0.0.0", "::", "[::]"]);
2180
2222
  * derive one from the host (keeping the URL's port); with both, refuse a contradicting pair rather
2181
2223
  * than starting a broker that nothing can reach.
2182
2224
  */
2183
- function reconcileHostAndServer(host, explicitServer) {
2225
+ function reconcileHostAndServer(host, explicitServer, source = "--host", urlSource = "--server") {
2184
2226
  const url = new URL(explicitServer ?? DEFAULT_SERVER);
2185
2227
  if (WILDCARD_HOSTS.has(host))
2186
2228
  return explicitServer ?? DEFAULT_SERVER;
2187
- // An unbracketed IPv6 literal cannot be assigned to a URL host — bracket it so the URL parses.
2188
- const literal = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
2229
+ const { literal, hostname } = assertBindableHost(host, source, urlSource);
2189
2230
  if (!explicitServer)
2190
2231
  return `nats://${literal}:${url.port || "4222"}`;
2191
- if (url.hostname !== new URL(`nats://${literal}:1`).hostname) {
2192
- console.error(c.red(`✗ --host ${host} and --server ${explicitServer} name different addresses - the broker would bind ${host} but be probed at ${url.hostname}. Pass one, or make them agree.`));
2232
+ // NO parse on this path: `assertBindableHost` just parsed the identical literal above, so the
2233
+ // mismatch check compares two parsed hostnames and can only ever print its diagnostic and exit 1
2234
+ // — the "never throw a raw Invalid URL" requirement (#1697) holds by construction, not by a
2235
+ // second guard that no input could reach.
2236
+ if (url.hostname !== hostname) {
2237
+ console.error(c.red(`✗ ${source} ${host} and ${urlSource} ${explicitServer} name different addresses - the broker would bind ${host} but be probed at ${url.hostname}. Pass one, or make them agree.`));
2193
2238
  process.exit(1);
2194
2239
  }
2195
2240
  return explicitServer;
@@ -2569,7 +2614,20 @@ transport, rotateSys = false) {
2569
2614
  // map, so a config rendered from one space evicts the rest silently. `auth` leads the list because
2570
2615
  // this function's copy can be fresher than the disk (a space created above, or one whose trust
2571
2616
  // record `--rotate-sys` just replaced). Refuses on an unreadable record rather than dropping it.
2572
- writeFileSync(confPath, serverConfig(auth, preloadSpaceAccounts(dir, auth), { transport, port, storeDir, host, wsPort, wsHost: host, ...(prepared ? { extraAccounts: prepared.extraAccounts } : {}) }));
2617
+ const spaces = preloadSpaceAccounts(dir, auth);
2618
+ const enabled = userAuthSpacesOnDisk(dir);
2619
+ for (const enabledSpace of enabled) {
2620
+ if (!spaces.some((s) => s.space === enabledSpace))
2621
+ throw new Error(`space "${enabledSpace}" has user auth enabled but no data account record - refusing to render an incomplete broker resolver`);
2622
+ }
2623
+ const extraAccounts = [];
2624
+ for (const enabledSpace of enabled) {
2625
+ const accounts = enabledSpace === space && prepared
2626
+ ? prepared.extraAccounts
2627
+ : await resolveAuthProvider().preloadAccounts({ store, space: enabledSpace });
2628
+ extraAccounts.push(...accounts);
2629
+ }
2630
+ writeFileSync(confPath, serverConfig(auth, spaces, { transport, port, storeDir, host, wsPort, wsHost: host, extraAccounts }));
2573
2631
  // Ephemeral setup cred: used only to probe reachability, pre-create the space streams/buckets
2574
2632
  // (setupSpaceStreams) and seed the channel registry (seedChannelRegistry) — all within the
2575
2633
  // enumerated `provisioner` scope. No broad `manager` residual for the up path.