@cotal-ai/cli 0.36.0 → 0.38.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/commands/agents.js +1 -1
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +4 -1
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/clean.d.ts +1 -1
- package/dist/commands/clean.d.ts.map +1 -1
- package/dist/commands/clean.js +8 -7
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/down.d.ts +10 -2
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +21 -10
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/endpoints.d.ts +1 -1
- package/dist/commands/endpoints.d.ts.map +1 -1
- package/dist/commands/endpoints.js +1 -0
- package/dist/commands/endpoints.js.map +1 -1
- package/dist/commands/ext.d.ts.map +1 -1
- package/dist/commands/ext.js +3 -1
- package/dist/commands/ext.js.map +1 -1
- package/dist/commands/join.d.ts.map +1 -1
- package/dist/commands/join.js +5 -1
- package/dist/commands/join.js.map +1 -1
- package/dist/commands/setup.d.ts +34 -8
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +130 -267
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/spawn-manifest.js +5 -5
- package/dist/commands/spawn-manifest.js.map +1 -1
- package/dist/commands/spawn.d.ts +1 -1
- package/dist/commands/spawn.d.ts.map +1 -1
- package/dist/commands/spawn.js +8 -2
- package/dist/commands/spawn.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +44 -18
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/up.js +10 -10
- package/dist/commands/up.js.map +1 -1
- package/dist/console/ui/Detail.js +1 -1
- package/dist/console/ui/Detail.js.map +1 -1
- package/dist/console/ui/Roster.d.ts.map +1 -1
- package/dist/console/ui/Roster.js +9 -2
- package/dist/console/ui/Roster.js.map +1 -1
- package/dist/console/ui/StatusBar.d.ts.map +1 -1
- package/dist/console/ui/StatusBar.js +1 -1
- package/dist/console/ui/StatusBar.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-skills.d.ts +4 -4
- package/dist/lib/agent-skills.js +4 -4
- package/dist/lib/control.d.ts.map +1 -1
- package/dist/lib/control.js +3 -2
- package/dist/lib/control.js.map +1 -1
- package/dist/lib/delivery-proc.d.ts +8 -7
- package/dist/lib/delivery-proc.d.ts.map +1 -1
- package/dist/lib/delivery-proc.js +51 -36
- package/dist/lib/delivery-proc.js.map +1 -1
- package/dist/lib/manager-proc.d.ts +16 -10
- package/dist/lib/manager-proc.d.ts.map +1 -1
- package/dist/lib/manager-proc.js +65 -36
- package/dist/lib/manager-proc.js.map +1 -1
- package/dist/lib/manifest/live.d.ts.map +1 -1
- package/dist/lib/manifest/live.js +3 -0
- package/dist/lib/manifest/live.js.map +1 -1
- package/dist/lib/status.d.ts +5 -2
- package/dist/lib/status.d.ts.map +1 -1
- package/dist/lib/status.js +8 -5
- package/dist/lib/status.js.map +1 -1
- package/dist/lib/transient.d.ts.map +1 -1
- package/dist/lib/transient.js +1 -0
- package/dist/lib/transient.js.map +1 -1
- package/dist/lib/version.d.ts +6 -0
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +14 -0
- package/dist/lib/version.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +1 -0
- package/dist/render.js.map +1 -1
- package/dist/seed/authority.d.ts +5 -1
- package/dist/seed/authority.d.ts.map +1 -1
- package/dist/seed/authority.js +10 -3
- package/dist/seed/authority.js.map +1 -1
- package/dist/seed/paths.d.ts +6 -0
- package/dist/seed/paths.d.ts.map +1 -1
- package/dist/seed/paths.js +21 -15
- package/dist/seed/paths.js.map +1 -1
- package/dist/seed/reconcile.d.ts.map +1 -1
- package/dist/seed/reconcile.js +37 -5
- package/dist/seed/reconcile.js.map +1 -1
- package/dist/ui.js +1 -1
- package/dist/ui.js.map +1 -1
- package/dist/view/mesh-view.d.ts +4 -0
- package/dist/view/mesh-view.d.ts.map +1 -1
- package/dist/view/mesh-view.js +10 -0
- package/dist/view/mesh-view.js.map +1 -1
- package/package.json +5 -4
- package/cotal-skills/.claude-plugin/plugin.json +0 -6
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { existsSync, openSync, closeSync, writeFileSync, readFileSync, rmSync } from "node:fs";
|
|
3
3
|
import { DEFAULT_SERVER, LEASE_TTL_MS, mintCreds, newIdentity, waitForDeliveryLease, } from "@cotal-ai/core";
|
|
4
|
-
import { DELIVERY_CREDS_KIND, authDir, deliveryCredsKey, findCotalRoot, getSoleSpaceAuth, listSpaceAccounts, parsePid, probeLiveness, segmentedKey, workspaceSecretStore } from "@cotal-ai/workspace";
|
|
4
|
+
import { DELIVERY_CREDS_KIND, DELIVERY_LOGFILE, DELIVERY_PIDFILE, authDir, canonicalLocalProcessPath, deliveryCredsKey, findCotalRoot, getSoleSpaceAuth, listSpaceAccounts, localProcessPath, parsePid, probeLiveness, reclaimDeadPreUpgradeRecord, segmentedKey, workspaceSecretStore } from "@cotal-ai/workspace";
|
|
5
5
|
import { selfArgv } from "./self-exec.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { resolveRuntimeSpace } from "./status.js";
|
|
7
|
+
import { cotalRoot } from "./paths.js";
|
|
8
8
|
import { MANAGER_PID_PATH, ensureManager, managerHasDeliveryMarker, managerLiveness, stopManager } from "./manager-proc.js";
|
|
9
|
-
|
|
9
|
+
/** The space this folder's commands mean, and the per-space record paths over it. The daemon is
|
|
10
|
+
* minted a space-scoped cred and binds that space's durables, so a root-scoped record gave one root
|
|
11
|
+
* one daemon by filename; every helper below therefore takes the space it is answering about. */
|
|
12
|
+
const folderSpace = () => resolveRuntimeSpace(process.cwd());
|
|
13
|
+
const ctx = (space) => ({ root: cotalRoot(), space });
|
|
14
|
+
/** READ-resolving: also names a pre-segmentation `delivery.pid` when that is what is on disk. */
|
|
15
|
+
const PID_PATH = (space = folderSpace()) => localProcessPath(DELIVERY_PIDFILE, ctx(space));
|
|
10
16
|
// The daemon's cred goes through the secret-store seam; its key comes from workspace's per-kind
|
|
11
17
|
// resolver (P7 §2 rule 1) — never a hand-composed path or a copied literal. The kind is per-SPACE
|
|
12
18
|
// now, so the file is `.cotal/space.<hex>/delivery.creds`.
|
|
@@ -19,8 +25,8 @@ const deliveryCredsKeysToClear = (space) => [segmentedKey(DELIVERY_CREDS_KIND, s
|
|
|
19
25
|
* boolean collapse is the defect: `unknown` is reachable on a real kernel (a seccomp
|
|
20
26
|
* `SECCOMP_RET_ERRNO` filter or an LSM policy answers `kill(pid, 0)` with an arbitrary errno and
|
|
21
27
|
* libuv preserves it), and both ways of folding it into a boolean fail silently. */
|
|
22
|
-
export function deliveryLiveness(probe = probeLiveness) {
|
|
23
|
-
const p = PID_PATH();
|
|
28
|
+
export function deliveryLiveness(probe = probeLiveness, space = folderSpace()) {
|
|
29
|
+
const p = PID_PATH(space);
|
|
24
30
|
if (!existsSync(p))
|
|
25
31
|
return "absent";
|
|
26
32
|
const raw = readFileSync(p, "utf8").trim();
|
|
@@ -33,8 +39,8 @@ export function deliveryLiveness(probe = probeLiveness) {
|
|
|
33
39
|
}
|
|
34
40
|
/** True only if the daemon is PROVABLY running. Callers that ACT on the answer take
|
|
35
41
|
* {@link deliveryLiveness} instead; this cannot express "cannot tell". */
|
|
36
|
-
export function deliveryUp() {
|
|
37
|
-
return deliveryLiveness() === "alive";
|
|
42
|
+
export function deliveryUp(space = folderSpace()) {
|
|
43
|
+
return deliveryLiveness(probeLiveness, space) === "alive";
|
|
38
44
|
}
|
|
39
45
|
/** True when this folder runs an authed mesh — the only mode with a delivery daemon (Plane-3 needs the
|
|
40
46
|
* trusted reader; open dev mode is live-only). */
|
|
@@ -53,43 +59,48 @@ function hasAuth() {
|
|
|
53
59
|
*
|
|
54
60
|
* A guard that runs after the work is not a guard, so this one reads the tri-state directly and the
|
|
55
61
|
* caller refuses BEFORE anything is minted, written or started. */
|
|
56
|
-
function oldHostingManagerVerdict(probe = probeLiveness) {
|
|
57
|
-
const state = managerLiveness(probe);
|
|
62
|
+
function oldHostingManagerVerdict(probe = probeLiveness, space = folderSpace()) {
|
|
63
|
+
const state = managerLiveness(probe, undefined, space);
|
|
58
64
|
if (state === "unknown" || state === "unattributable")
|
|
59
65
|
return "indeterminate";
|
|
60
66
|
if (state !== "alive")
|
|
61
67
|
return "proceed"; // dead or absent: nothing is hosting Plane 3
|
|
62
|
-
return managerHasDeliveryMarker() ? "proceed" : "stop-it"; // alive: the marker decides
|
|
68
|
+
return managerHasDeliveryMarker(space) ? "proceed" : "stop-it"; // alive: the marker decides
|
|
63
69
|
}
|
|
64
70
|
/** Cutover preflight — the FIRST action, BEFORE the daemon can bind: stop any old Plane-3-hosting
|
|
65
71
|
* manager (live `manager.pid` without the delivery-aware marker) so it never double-binds the
|
|
66
72
|
* daemon's durables. A delivery-aware (this-build) manager is left running. No-op on a fresh install. */
|
|
67
|
-
export async function stopOldHostingManagerIfPresent(probe = probeLiveness, signal) {
|
|
68
|
-
const verdict = oldHostingManagerVerdict(probe);
|
|
73
|
+
export async function stopOldHostingManagerIfPresent(probe = probeLiveness, signal, space = folderSpace()) {
|
|
74
|
+
const verdict = oldHostingManagerVerdict(probe, space);
|
|
69
75
|
// FIRST action, before any mint/write/start, so the refusal actually fences the daemon.
|
|
70
76
|
if (verdict === "indeterminate")
|
|
71
|
-
throw new Error(`the recorded manager pid (${readFileSync(MANAGER_PID_PATH(), "utf8").trim()}) cannot be attributed, so the delivery cutover preflight cannot run: the kernel answered neither "running" nor "no such process" (a seccomp filter or LSM policy does this inside some sandboxes).\n` +
|
|
77
|
+
throw new Error(`the recorded manager pid (${readFileSync(MANAGER_PID_PATH(space), "utf8").trim()}) cannot be attributed, so the delivery cutover preflight cannot run: the kernel answered neither "running" nor "no such process" (a seccomp filter or LSM policy does this inside some sandboxes).\n` +
|
|
72
78
|
`Refusing before the daemon starts. If that manager is an old Plane-3-hosting one it is still bound to fanout/reader, and starting the daemon anyway would double-bind them; the daemon's own lease cannot detect that.\n` +
|
|
73
|
-
`NEXT: verify the process yourself (\`ps -p <pid>\`). If it is gone, remove
|
|
79
|
+
`NEXT: verify the process yourself (\`ps -p <pid>\`). If it is gone, remove \`${MANAGER_PID_PATH(space)}\` and re-run. If it is running, stop it with \`cotal down\` first.`);
|
|
74
80
|
if (verdict === "stop-it") {
|
|
75
81
|
console.error("• stopping an old Plane-3-hosting manager before starting the delivery daemon (cutover preflight)");
|
|
76
82
|
// stopManager THROWS rather than reporting a stop it did not achieve (EPERM, or a process that
|
|
77
83
|
// outlived SIGTERM), so reaching the next line is the proof the old manager is gone. Letting that
|
|
78
84
|
// throw propagate is the point: the daemon must not start beside a manager still bound to Plane 3.
|
|
79
|
-
await stopManager(probe, signal);
|
|
85
|
+
await stopManager(probe, signal, undefined, space);
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
|
-
/** Start the delivery daemon detached (pid in `.cotal/delivery
|
|
83
|
-
* stopped by `cotal down`. Re-execs this CLI's `deliver` command;
|
|
84
|
-
* scoped `delivery.creds` (written by {@link ensureDelivery}) — it
|
|
88
|
+
/** Start the delivery daemon detached (pid in `.cotal/delivery.<spaceKey>.pid`, output to
|
|
89
|
+
* `.cotal/delivery.<spaceKey>.log`), stopped by `cotal down`. Re-execs this CLI's `deliver` command;
|
|
90
|
+
* the daemon loads the pre-minted scoped `delivery.creds` (written by {@link ensureDelivery}) — it
|
|
91
|
+
* never sees the signer. */
|
|
85
92
|
export function startDeliveryDetached(o = {}) {
|
|
86
|
-
const
|
|
93
|
+
const space = o.space ?? folderSpace();
|
|
94
|
+
// See startManagerDetached: reclaim a provably dead pre-upgrade record before claiming the
|
|
95
|
+
// canonical slot, and refuse rather than start a second daemon beside a live one.
|
|
96
|
+
reclaimDeadPreUpgradeRecord(DELIVERY_PIDFILE, ctx(space));
|
|
97
|
+
const fd = openSync(canonicalLocalProcessPath(DELIVERY_LOGFILE, ctx(space)), "a");
|
|
87
98
|
const [node, ...self] = selfArgv();
|
|
88
99
|
const args = [
|
|
89
100
|
...self,
|
|
90
101
|
"deliver",
|
|
91
102
|
"--space",
|
|
92
|
-
|
|
103
|
+
space,
|
|
93
104
|
"--server",
|
|
94
105
|
o.server ?? DEFAULT_SERVER,
|
|
95
106
|
// Propagate the broker's transport decision. The daemon cannot derive it: it learns everything
|
|
@@ -107,7 +118,7 @@ export function startDeliveryDetached(o = {}) {
|
|
|
107
118
|
const child = spawn(node, args, { detached: true, stdio: ["ignore", fd, fd], env: { ...process.env, COTAL_SKIP_CONNECTOR_SEED: "1" } });
|
|
108
119
|
closeSync(fd);
|
|
109
120
|
child.unref();
|
|
110
|
-
writeFileSync(
|
|
121
|
+
writeFileSync(canonicalLocalProcessPath(DELIVERY_PIDFILE, ctx(space)), String(child.pid)); // canonical, never a pre-upgrade name
|
|
111
122
|
return child.pid ?? 0;
|
|
112
123
|
}
|
|
113
124
|
/** Make the server-side delivery daemon available (auth mode only). FAILS CLOSED: refuses to launch
|
|
@@ -118,7 +129,8 @@ export function startDeliveryDetached(o = {}) {
|
|
|
118
129
|
export async function ensureDelivery(o = {}, probe = probeLiveness) {
|
|
119
130
|
if (!hasAuth())
|
|
120
131
|
return { running: false }; // open dev mode — no daemon, agents are live-only
|
|
121
|
-
|
|
132
|
+
const space = o.space ?? folderSpace();
|
|
133
|
+
if (oldHostingManagerVerdict(probe, space) === "stop-it") {
|
|
122
134
|
console.error("✗ delivery: an old Plane-3-hosting manager is still live (no delivery-aware marker). Refusing to start the daemon - run `cotal down` first, then retry.");
|
|
123
135
|
return { running: false };
|
|
124
136
|
}
|
|
@@ -129,16 +141,15 @@ export async function ensureDelivery(o = {}, probe = probeLiveness) {
|
|
|
129
141
|
const auth = (await getSoleSpaceAuth(credsStore(), authDir(findCotalRoot())));
|
|
130
142
|
const id = newIdentity();
|
|
131
143
|
const creds = await mintCreds(auth, id, "delivery");
|
|
132
|
-
const space = o.space ?? resolveSpace(process.cwd());
|
|
133
144
|
const server = o.server ?? DEFAULT_SERVER;
|
|
134
|
-
const deliveryState = deliveryLiveness(probe);
|
|
145
|
+
const deliveryState = deliveryLiveness(probe, space);
|
|
135
146
|
// Same refusal as the manager: an unattributable pid must not be silently reused (a daemon
|
|
136
147
|
// reported running that is not there) nor silently replaced (two daemons on one fanout).
|
|
137
148
|
if (deliveryState === "unknown" || deliveryState === "unattributable")
|
|
138
|
-
throw new Error(`the recorded delivery daemon pid (${readFileSync(PID_PATH(), "utf8").trim()}) cannot be attributed: the kernel answered neither "running" nor "no such process".\n` +
|
|
149
|
+
throw new Error(`the recorded delivery daemon pid (${readFileSync(PID_PATH(space), "utf8").trim()}) cannot be attributed: the kernel answered neither "running" nor "no such process".\n` +
|
|
139
150
|
`A seccomp filter or LSM policy that intercepts \`kill(pid, 0)\` does this, so it is expected inside some sandboxes and containers.\n` +
|
|
140
151
|
`Cotal will not guess: reusing it would report a daemon that is not there, and starting a second would put two daemons on one fanout.\n` +
|
|
141
|
-
`NEXT: verify the process yourself (\`ps -p <pid>\`). If it is gone, remove
|
|
152
|
+
`NEXT: verify the process yourself (\`ps -p <pid>\`). If it is gone, remove \`${PID_PATH(space)}\` and re-run. If it is running, use it or stop it.`);
|
|
142
153
|
let launched;
|
|
143
154
|
if (deliveryState !== "alive") {
|
|
144
155
|
// The store's put hardens `.cotal/` first (the cred is born under a private ACL, no race) and
|
|
@@ -167,7 +178,7 @@ export async function ensureDelivery(o = {}, probe = probeLiveness) {
|
|
|
167
178
|
if (!ready && launched !== undefined && probe(launched) === "dead")
|
|
168
179
|
throw new Error(`the delivery daemon started for space "${space}" (pid ${launched}) exited without becoming ready, and the shard-0 lease is not held by it.\n` +
|
|
169
180
|
`That is what a lost single-flight CAS looks like: another daemon holds the lease, or a crashed holder's lease has not yet expired (it does after ${LEASE_TTL_MS / 1000}s).\n` +
|
|
170
|
-
`Refusing to report a daemon that is not running. The daemon logged its own reason to ${
|
|
181
|
+
`Refusing to report a daemon that is not running. The daemon logged its own reason to ${canonicalLocalProcessPath(DELIVERY_LOGFILE, ctx(space))}.\n` +
|
|
171
182
|
`NEXT: read that log; if no other daemon is running, wait for the stale lease to expire and re-run.`);
|
|
172
183
|
if (!ready)
|
|
173
184
|
console.error("• delivery daemon not yet ready (responder not bound) - boot durable joins will reconcile when it is");
|
|
@@ -177,9 +188,9 @@ export async function ensureDelivery(o = {}, probe = probeLiveness) {
|
|
|
177
188
|
* kill runs even if the creds delete fails (finally) — a delete error must never leave the daemon
|
|
178
189
|
* alive to outlive the teardown and reattach to a restarted broker; the error still propagates
|
|
179
190
|
* after the kill so the caller can surface it. */
|
|
180
|
-
export async function stopDelivery(probe = probeLiveness, signal) {
|
|
191
|
+
export async function stopDelivery(probe = probeLiveness, signal, space = folderSpace()) {
|
|
181
192
|
const send = signal ?? ((pid, sig) => process.kill(pid, sig));
|
|
182
|
-
const p = PID_PATH();
|
|
193
|
+
const p = PID_PATH(space);
|
|
183
194
|
// ORDER MATTERS, AND IT USED TO BE BACKWARDS. The credential was deleted FIRST, in a try whose
|
|
184
195
|
// finally then signalled and removed the pidfile unconditionally. Under a refused signal that left
|
|
185
196
|
// a LIVE daemon with no pidfile and no standing credential: still connected, still serving, and its
|
|
@@ -189,7 +200,7 @@ export async function stopDelivery(probe = probeLiveness, signal) {
|
|
|
189
200
|
// (a blocked path, a store error) must still propagate loudly, but it must not leave behind a
|
|
190
201
|
// pidfile for a process that is definitely gone. delivery-teardown.smoke.ts pins exactly that
|
|
191
202
|
// combination, and caught this when the first version of this fix ordered them the other way.
|
|
192
|
-
const keys = deliveryCredsKeysToClear(
|
|
203
|
+
const keys = deliveryCredsKeysToClear(space);
|
|
193
204
|
const dropCreds = async () => {
|
|
194
205
|
for (const k of keys)
|
|
195
206
|
await credsStore().delete(k);
|
|
@@ -223,7 +234,7 @@ export async function stopDelivery(probe = probeLiveness, signal) {
|
|
|
223
234
|
if (before === "unknown")
|
|
224
235
|
throw new Error(`refusing to stop the delivery daemon (pid ${pid}): its liveness cannot be determined (a seccomp filter or LSM policy answers kill(pid,0) with an arbitrary errno).\n` +
|
|
225
236
|
`The pidfile and standing credential are LEFT IN PLACE: removing them would strand a daemon that may still be connected, with its renewal source gone.\n` +
|
|
226
|
-
`NEXT: verify with \`ps -p ${pid}\`, then stop it yourself or remove
|
|
237
|
+
`NEXT: verify with \`ps -p ${pid}\`, then stop it yourself or remove \`${p}\` if it is gone.`);
|
|
227
238
|
try {
|
|
228
239
|
send(pid, "SIGTERM");
|
|
229
240
|
}
|
|
@@ -235,7 +246,7 @@ export async function stopDelivery(probe = probeLiveness, signal) {
|
|
|
235
246
|
}
|
|
236
247
|
throw new Error(`refusing to stop the delivery daemon (pid ${pid}): the signal was rejected (${code ?? "unknown error"}).\n` +
|
|
237
248
|
`EPERM means it belongs to another user, so it is running and not ours to stop. The pidfile and standing credential are LEFT IN PLACE.\n` +
|
|
238
|
-
`NEXT: stop it as its owner, or remove
|
|
249
|
+
`NEXT: stop it as its owner, or remove \`${p}\` if you are certain it is gone.`);
|
|
239
250
|
}
|
|
240
251
|
const deadline = Date.now() + 15_000;
|
|
241
252
|
while (probe(pid) !== "dead" && Date.now() < deadline)
|
|
@@ -250,8 +261,12 @@ export async function stopDelivery(probe = probeLiveness, signal) {
|
|
|
250
261
|
* first only to close the old-manager double-bind window and so freshly-spawned agents find the
|
|
251
262
|
* `ctl.delivery` responder for their boot self-join (a miss honest-degrades to live-only). */
|
|
252
263
|
export async function ensureControlPlane(o = {}) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
264
|
+
// One space for all three steps. The preflight used to resolve its own from the cwd while the two
|
|
265
|
+
// ensures took `o.space`; with per-space records that would preflight one tenant's manager and then
|
|
266
|
+
// start another's.
|
|
267
|
+
const space = o.space ?? folderSpace();
|
|
268
|
+
await stopOldHostingManagerIfPresent(probeLiveness, undefined, space);
|
|
269
|
+
await ensureDelivery({ ...o, space });
|
|
270
|
+
return ensureManager({ ...o, space });
|
|
256
271
|
}
|
|
257
272
|
//# sourceMappingURL=delivery-proc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delivery-proc.js","sourceRoot":"","sources":["../../src/lib/delivery-proc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/F,OAAO,EACL,cAAc,EACd,YAAY,EACZ,SAAS,EACT,WAAW,EACX,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"delivery-proc.js","sourceRoot":"","sources":["../../src/lib/delivery-proc.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { type CommandReader, type LivenessProbe } from "@cotal-ai/workspace";
|
|
2
|
+
/** The exact logfile the detached-manager writer opens. Exported so operator guidance names the
|
|
3
|
+
* writer-owned path instead of copying its filename template into command output. */
|
|
4
|
+
export declare const managerLogPath: (space: string, root?: string) => string;
|
|
5
|
+
/** The manager logfile as an operator-facing path relative to the selected mesh root. */
|
|
6
|
+
export declare const managerLogDisplayPath: (space: string, root?: string) => string;
|
|
2
7
|
/** Exported so the delivery cutover preflight can NAME the pid it refused on: an error that says
|
|
3
|
-
* "cannot be attributed" without saying which pid is not actionable.
|
|
4
|
-
|
|
8
|
+
* "cannot be attributed" without saying which pid is not actionable. READ-resolving, so it also
|
|
9
|
+
* names a pre-segmentation `manager.pid` when that is the record actually on disk. */
|
|
10
|
+
export declare const MANAGER_PID_PATH: (space?: string) => string;
|
|
5
11
|
/** The recorded manager's state. THREE-VALUED liveness plus absent, because collapsing it to a
|
|
6
12
|
* boolean is what made this dangerous. Both collapses are silent and both are wrong:
|
|
7
13
|
* `!== "dead"` -> an `unknown` reports UP forever; no retry clears it and nothing starts.
|
|
@@ -33,9 +39,9 @@ export interface ManagerRecord {
|
|
|
33
39
|
* argument, and it is the same one the liveness probe makes: absence of evidence must fail toward
|
|
34
40
|
* the old behaviour (trust the record), because the opposite error starts a second manager on top
|
|
35
41
|
* of a live one. */
|
|
36
|
-
export declare function managerRecordState(probe?: LivenessProbe, readCommand?: CommandReader): ManagerRecord;
|
|
42
|
+
export declare function managerRecordState(probe?: LivenessProbe, readCommand?: CommandReader, space?: string): ManagerRecord;
|
|
37
43
|
/** {@link managerRecordState}'s verdict alone, for the callers that only branch on it. */
|
|
38
|
-
export declare function managerLiveness(probe?: LivenessProbe, readCommand?: CommandReader): ManagerRecordState;
|
|
44
|
+
export declare function managerLiveness(probe?: LivenessProbe, readCommand?: CommandReader, space?: string): ManagerRecordState;
|
|
39
45
|
/** One line describing what was found behind the record, for a caller that has to explain itself. */
|
|
40
46
|
export declare function describeManagerRecord(r: ManagerRecord): string;
|
|
41
47
|
/** True only if the manager is PROVABLY running. `unknown` is not up, and neither is `foreign` — a
|
|
@@ -43,15 +49,15 @@ export declare function describeManagerRecord(r: ManagerRecord): string;
|
|
|
43
49
|
* answer must use {@link managerRecordState} instead: this boolean cannot express the difference
|
|
44
50
|
* between "not running", "cannot tell" and "someone else's process", and acting on the difference
|
|
45
51
|
* is the whole point. */
|
|
46
|
-
export declare function managerUp(): boolean;
|
|
52
|
+
export declare function managerUp(space?: string): boolean;
|
|
47
53
|
/** True if the live manager carries a delivery-aware marker BOUND to its current pid (i.e. it's THIS
|
|
48
54
|
* build, non-hosting). Fail-closed: the marker stores the pid it was written for, and this requires it
|
|
49
55
|
* to equal the live `manager.pid` — a stale marker left by a crash, a mismatch, or an unparseable file
|
|
50
56
|
* all read as NOT delivery-aware, so a live old hosting `manager.pid` can't be mistaken for non-hosting
|
|
51
57
|
* and the delivery preflight stops it. */
|
|
52
|
-
export declare function managerHasDeliveryMarker(): boolean;
|
|
53
|
-
/** Start the control-plane manager detached (pid in `.cotal/manager
|
|
54
|
-
* `.cotal/manager
|
|
58
|
+
export declare function managerHasDeliveryMarker(space?: string): boolean;
|
|
59
|
+
/** Start the control-plane manager detached (pid in `.cotal/manager.<spaceKey>.pid`, output to
|
|
60
|
+
* `.cotal/manager.<spaceKey>.log`), stopped by `cotal down`. Re-execs this same CLI's `supervise` — the
|
|
55
61
|
* composed `cotal` binary registers it; `process.execArgv` carries the tsx loader in dev and is
|
|
56
62
|
* empty in prod. `supervise`'s auto runtime resolves to pty when detached, which answers the
|
|
57
63
|
* control plane (`cotal_spawn`/`despawn`/`purge`/`persona`) with no tmux/cmux needed. */
|
|
@@ -77,7 +83,7 @@ export declare function startManagerDetached(o?: {
|
|
|
77
83
|
* says nobody is ANSWERING; it does not say the recorded pid is dead. Overwriting an unknown or
|
|
78
84
|
* unattributable record is the same defect as deleting it, reached through a different verb, which
|
|
79
85
|
* is the third time that shape has appeared in this change. Any future starter calls this first. */
|
|
80
|
-
export declare function assertManagerRecordReplaceable(probe?: LivenessProbe, readCommand?: CommandReader): void;
|
|
86
|
+
export declare function assertManagerRecordReplaceable(probe?: LivenessProbe, readCommand?: CommandReader, space?: string): void;
|
|
81
87
|
export declare function ensureManager(o?: {
|
|
82
88
|
space?: string;
|
|
83
89
|
server?: string;
|
|
@@ -111,5 +117,5 @@ export type StopVerdict = "stopped" | "already-gone";
|
|
|
111
117
|
* A correct fix upstream reaching a latent destructive bug downstream is the worst shape available,
|
|
112
118
|
* so this refuses instead: records are removed only on proven death, never on a signal we could not
|
|
113
119
|
* send or a death we could not confirm. Found by review, with a kernel seccomp proof. */
|
|
114
|
-
export declare function stopManager(probe?: LivenessProbe, signal?: SignalFn | undefined, readCommand?: CommandReader): Promise<StopVerdict>;
|
|
120
|
+
export declare function stopManager(probe?: LivenessProbe, signal?: SignalFn | undefined, readCommand?: CommandReader, space?: string): Promise<StopVerdict>;
|
|
115
121
|
//# sourceMappingURL=manager-proc.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager-proc.d.ts","sourceRoot":"","sources":["../../src/lib/manager-proc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manager-proc.d.ts","sourceRoot":"","sources":["../../src/lib/manager-proc.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/manager-proc.js
CHANGED
|
@@ -1,20 +1,36 @@
|
|
|
1
1
|
import { spawn, spawnSync } from "node:child_process";
|
|
2
2
|
import { existsSync, openSync, closeSync, chmodSync, writeFileSync, readFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { relative } from "node:path";
|
|
3
4
|
import { DEFAULT_SERVER } from "@cotal-ai/core";
|
|
4
5
|
import { selfArgv } from "./self-exec.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { commandIsCotalSupervisor, parsePid, probeLiveness, readProcessCommand, MANAGER_DELIVERY_AWARE_MARKER, MANAGER_PIDFILE, } from "@cotal-ai/workspace";
|
|
6
|
+
import { resolveRuntimeSpace } from "./status.js";
|
|
7
|
+
import { cotalRoot } from "./paths.js";
|
|
8
|
+
import { canonicalLocalProcessPath, commandIsCotalSupervisor, localProcessPath, parsePid, probeLiveness, readProcessCommand, reclaimDeadPreUpgradeRecord, MANAGER_DELIVERY_AWARE_MARKER, MANAGER_LOGFILE, MANAGER_PIDFILE, } from "@cotal-ai/workspace";
|
|
9
|
+
/** The space whose manager this folder's commands mean. Every helper below defaults to it, and the
|
|
10
|
+
* ones a caller reaches with an explicit `--space` take it as their last argument: the records are
|
|
11
|
+
* per-space now, so a helper that assumed the folder's space would answer about a sibling tenant's
|
|
12
|
+
* manager on a root that hosts more than one. Resolved from the folder's own RECORDS first: an open
|
|
13
|
+
* mesh has no account record to name its space, and answering with the default there is how a
|
|
14
|
+
* space-less read reports "absent" over a live manager. */
|
|
15
|
+
const folderSpace = () => resolveRuntimeSpace(process.cwd());
|
|
16
|
+
const ctx = (space) => ({ root: cotalRoot(), space });
|
|
17
|
+
/** The exact logfile the detached-manager writer opens. Exported so operator guidance names the
|
|
18
|
+
* writer-owned path instead of copying its filename template into command output. */
|
|
19
|
+
export const managerLogPath = (space, root = cotalRoot()) => canonicalLocalProcessPath(MANAGER_LOGFILE, { root, space });
|
|
20
|
+
/** The manager logfile as an operator-facing path relative to the selected mesh root. */
|
|
21
|
+
export const managerLogDisplayPath = (space, root = cotalRoot()) => relative(root, managerLogPath(space, root));
|
|
8
22
|
/** Exported so the delivery cutover preflight can NAME the pid it refused on: an error that says
|
|
9
|
-
* "cannot be attributed" without saying which pid is not actionable.
|
|
10
|
-
|
|
23
|
+
* "cannot be attributed" without saying which pid is not actionable. READ-resolving, so it also
|
|
24
|
+
* names a pre-segmentation `manager.pid` when that is the record actually on disk. */
|
|
25
|
+
export const MANAGER_PID_PATH = (space = folderSpace()) => localProcessPath(MANAGER_PIDFILE, ctx(space));
|
|
11
26
|
const PID_PATH = MANAGER_PID_PATH;
|
|
12
27
|
/** Sibling marker of `manager.pid`: written by THIS build's manager (which no longer hosts Plane-3 —
|
|
13
28
|
* the server-side delivery daemon does). Its presence beside a live `manager.pid` proves the manager is
|
|
14
29
|
* "delivery-aware" / non-hosting. A live `manager.pid` WITHOUT this marker is an OLD (pre-delivery-daemon)
|
|
15
30
|
* manager that still calls `startPlane3` — the delivery preflight stops it before the daemon binds, so an
|
|
16
|
-
* old hosting manager never double-binds `fanout`/`reader` against the new daemon.
|
|
17
|
-
|
|
31
|
+
* old hosting manager never double-binds `fanout`/`reader` against the new daemon. Per-space and
|
|
32
|
+
* READ-resolving, exactly like the pidfile it is a sibling of. */
|
|
33
|
+
const DELIVERY_AWARE_MARKER = (space = folderSpace()) => localProcessPath(MANAGER_DELIVERY_AWARE_MARKER, ctx(space));
|
|
18
34
|
/** Read + attribute the manager record in one place, so every caller decides on the same evidence.
|
|
19
35
|
*
|
|
20
36
|
* ATTRIBUTION MAY ONLY DOWNGRADE ON PROOF. A live pid is demoted to `foreign` when its command line
|
|
@@ -23,8 +39,8 @@ const DELIVERY_AWARE_MARKER = () => cotalPath(MANAGER_DELIVERY_AWARE_MARKER);
|
|
|
23
39
|
* argument, and it is the same one the liveness probe makes: absence of evidence must fail toward
|
|
24
40
|
* the old behaviour (trust the record), because the opposite error starts a second manager on top
|
|
25
41
|
* of a live one. */
|
|
26
|
-
export function managerRecordState(probe = probeLiveness, readCommand = readProcessCommand) {
|
|
27
|
-
const p = PID_PATH();
|
|
42
|
+
export function managerRecordState(probe = probeLiveness, readCommand = readProcessCommand, space = folderSpace()) {
|
|
43
|
+
const p = PID_PATH(space);
|
|
28
44
|
if (!existsSync(p))
|
|
29
45
|
return { state: "absent" };
|
|
30
46
|
const raw = readFileSync(p, "utf8").trim();
|
|
@@ -46,8 +62,8 @@ export function managerRecordState(probe = probeLiveness, readCommand = readProc
|
|
|
46
62
|
return { state: commandIsCotalSupervisor(cmd.command) ? "alive" : "foreign", pid, command: cmd.command };
|
|
47
63
|
}
|
|
48
64
|
/** {@link managerRecordState}'s verdict alone, for the callers that only branch on it. */
|
|
49
|
-
export function managerLiveness(probe = probeLiveness, readCommand = readProcessCommand) {
|
|
50
|
-
return managerRecordState(probe, readCommand).state;
|
|
65
|
+
export function managerLiveness(probe = probeLiveness, readCommand = readProcessCommand, space = folderSpace()) {
|
|
66
|
+
return managerRecordState(probe, readCommand, space).state;
|
|
51
67
|
}
|
|
52
68
|
/** One line describing what was found behind the record, for a caller that has to explain itself. */
|
|
53
69
|
export function describeManagerRecord(r) {
|
|
@@ -63,40 +79,47 @@ export function describeManagerRecord(r) {
|
|
|
63
79
|
* answer must use {@link managerRecordState} instead: this boolean cannot express the difference
|
|
64
80
|
* between "not running", "cannot tell" and "someone else's process", and acting on the difference
|
|
65
81
|
* is the whole point. */
|
|
66
|
-
export function managerUp() {
|
|
67
|
-
return managerLiveness() === "alive";
|
|
82
|
+
export function managerUp(space = folderSpace()) {
|
|
83
|
+
return managerLiveness(probeLiveness, readProcessCommand, space) === "alive";
|
|
68
84
|
}
|
|
69
85
|
/** True if the live manager carries a delivery-aware marker BOUND to its current pid (i.e. it's THIS
|
|
70
86
|
* build, non-hosting). Fail-closed: the marker stores the pid it was written for, and this requires it
|
|
71
87
|
* to equal the live `manager.pid` — a stale marker left by a crash, a mismatch, or an unparseable file
|
|
72
88
|
* all read as NOT delivery-aware, so a live old hosting `manager.pid` can't be mistaken for non-hosting
|
|
73
89
|
* and the delivery preflight stops it. */
|
|
74
|
-
export function managerHasDeliveryMarker() {
|
|
75
|
-
const markerPath = DELIVERY_AWARE_MARKER();
|
|
76
|
-
const pidPath = PID_PATH();
|
|
90
|
+
export function managerHasDeliveryMarker(space = folderSpace()) {
|
|
91
|
+
const markerPath = DELIVERY_AWARE_MARKER(space);
|
|
92
|
+
const pidPath = PID_PATH(space);
|
|
77
93
|
if (!existsSync(markerPath) || !existsSync(pidPath))
|
|
78
94
|
return false;
|
|
79
95
|
const markerPid = Number(readFileSync(markerPath, "utf8").trim());
|
|
80
96
|
const livePid = Number(readFileSync(pidPath, "utf8").trim());
|
|
81
97
|
return Number.isFinite(markerPid) && Number.isFinite(livePid) && markerPid === livePid;
|
|
82
98
|
}
|
|
83
|
-
/** Start the control-plane manager detached (pid in `.cotal/manager
|
|
84
|
-
* `.cotal/manager
|
|
99
|
+
/** Start the control-plane manager detached (pid in `.cotal/manager.<spaceKey>.pid`, output to
|
|
100
|
+
* `.cotal/manager.<spaceKey>.log`), stopped by `cotal down`. Re-execs this same CLI's `supervise` — the
|
|
85
101
|
* composed `cotal` binary registers it; `process.execArgv` carries the tsx loader in dev and is
|
|
86
102
|
* empty in prod. `supervise`'s auto runtime resolves to pty when detached, which answers the
|
|
87
103
|
* control plane (`cotal_spawn`/`despawn`/`purge`/`persona`) with no tmux/cmux needed. */
|
|
88
104
|
export function startManagerDetached(o = {}) {
|
|
105
|
+
const space = o.space ?? folderSpace();
|
|
106
|
+
// Clear a provably dead PRE-UPGRADE record before claiming the canonical slot, so an upgraded root
|
|
107
|
+
// does not end up holding both names and failing every later read as ambiguous. It refuses (throws)
|
|
108
|
+
// on a live or unattributable one rather than orphaning the daemon behind it.
|
|
109
|
+
reclaimDeadPreUpgradeRecord(MANAGER_PIDFILE, ctx(space));
|
|
110
|
+
reclaimDeadPreUpgradeRecord(MANAGER_DELIVERY_AWARE_MARKER, ctx(space));
|
|
111
|
+
const logPath = managerLogPath(space);
|
|
89
112
|
// 0600: the manager prints its console URL here, and that URL carries the console token — a
|
|
90
113
|
// standing credential for every agent's terminal on this mesh, at rest for the life of the file.
|
|
91
114
|
// `.cotal` is already 0700, so this is defence in depth rather than the boundary, but a log the
|
|
92
115
|
// group/world can read is a needless second copy of that credential.
|
|
93
|
-
const fd = openSync(
|
|
116
|
+
const fd = openSync(logPath, "a", 0o600);
|
|
94
117
|
// The mode above only applies when the file is CREATED, so every log that already exists from an
|
|
95
118
|
// earlier version would keep its 0644. Narrow those too. Best-effort: a filesystem that cannot
|
|
96
119
|
// represent the mode (or a Windows volume, where `.cotal`'s ACL is the real control) is not a
|
|
97
120
|
// reason to refuse to start the manager.
|
|
98
121
|
try {
|
|
99
|
-
chmodSync(
|
|
122
|
+
chmodSync(logPath, 0o600);
|
|
100
123
|
}
|
|
101
124
|
catch { /* mode is defence in depth, not the boundary */ }
|
|
102
125
|
const [node, ...self] = selfArgv();
|
|
@@ -104,7 +127,7 @@ export function startManagerDetached(o = {}) {
|
|
|
104
127
|
...self,
|
|
105
128
|
"supervise",
|
|
106
129
|
"--space",
|
|
107
|
-
|
|
130
|
+
space,
|
|
108
131
|
"--server",
|
|
109
132
|
o.server ?? DEFAULT_SERVER,
|
|
110
133
|
...(o.runtime ? ["--runtime", o.runtime] : []),
|
|
@@ -125,10 +148,12 @@ export function startManagerDetached(o = {}) {
|
|
|
125
148
|
const child = spawn(node, args, { detached: true, stdio: ["ignore", fd, fd], env: { ...process.env, COTAL_SKIP_CONNECTOR_SEED: "1" } });
|
|
126
149
|
closeSync(fd);
|
|
127
150
|
child.unref();
|
|
128
|
-
|
|
151
|
+
// CANONICAL path, never a pre-upgrade one: a start that kept writing the root-scoped name would
|
|
152
|
+
// keep minting the very records this change ends.
|
|
153
|
+
writeFileSync(canonicalLocalProcessPath(MANAGER_PIDFILE, ctx(space)), String(child.pid));
|
|
129
154
|
// Mark this manager as delivery-aware (non-hosting) so the delivery preflight can tell it apart from
|
|
130
155
|
// an old Plane-3-hosting manager. Written next to the pid, removed together in stopManager / down.
|
|
131
|
-
writeFileSync(
|
|
156
|
+
writeFileSync(canonicalLocalProcessPath(MANAGER_DELIVERY_AWARE_MARKER, ctx(space)), String(child.pid));
|
|
132
157
|
return child.pid ?? 0;
|
|
133
158
|
}
|
|
134
159
|
/** Make the control plane available: reuse a manager already running for this folder, else start
|
|
@@ -142,9 +167,12 @@ export function startManagerDetached(o = {}) {
|
|
|
142
167
|
* says nobody is ANSWERING; it does not say the recorded pid is dead. Overwriting an unknown or
|
|
143
168
|
* unattributable record is the same defect as deleting it, reached through a different verb, which
|
|
144
169
|
* is the third time that shape has appeared in this change. Any future starter calls this first. */
|
|
145
|
-
export function assertManagerRecordReplaceable(probe = probeLiveness, readCommand = readProcessCommand) {
|
|
146
|
-
const record = managerRecordState(probe, readCommand);
|
|
170
|
+
export function assertManagerRecordReplaceable(probe = probeLiveness, readCommand = readProcessCommand, space = folderSpace()) {
|
|
171
|
+
const record = managerRecordState(probe, readCommand, space);
|
|
147
172
|
const state = record.state;
|
|
173
|
+
// The record this is about, named in full: on a root that hosts two spaces "the manager pidfile"
|
|
174
|
+
// is not a location an operator can act on, and on an un-upgraded one it is not even this name.
|
|
175
|
+
const p = PID_PATH(space);
|
|
148
176
|
// A FOREIGN record is replaceable, and saying what was found is the point of allowing it. The pid
|
|
149
177
|
// is alive, so `probeLiveness` alone would have called this a healthy manager and every start
|
|
150
178
|
// path would have skipped forever; it is provably not a manager, so nothing is orphaned by
|
|
@@ -153,19 +181,20 @@ export function assertManagerRecordReplaceable(probe = probeLiveness, readComman
|
|
|
153
181
|
if (state === "foreign")
|
|
154
182
|
console.error(`! ${describeManagerRecord(record)} - that is not a manager, so the record is stale (its process exited and the pid was reused). Replacing it.`);
|
|
155
183
|
if (state === "unattributable")
|
|
156
|
-
throw new Error(`the manager pidfile at ${
|
|
184
|
+
throw new Error(`the manager pidfile at ${p} holds content that is not a pid (${JSON.stringify(readFileSync(p, "utf8").trim())}).\n` +
|
|
157
185
|
`Refusing to start a manager over it: that record may front a live process nobody can identify, and overwriting it would orphan the process while reporting a healthy control plane.\n` +
|
|
158
|
-
`NEXT: find and stop that process, then remove
|
|
186
|
+
`NEXT: find and stop that process, then remove \`${p}\` by hand.`);
|
|
159
187
|
if (state === "unknown")
|
|
160
|
-
throw new Error(`the recorded manager pid (${readFileSync(
|
|
188
|
+
throw new Error(`the recorded manager pid (${readFileSync(p, "utf8").trim()}) cannot be attributed: the kernel answered neither "running" nor "no such process" (a seccomp filter or LSM policy does this inside some sandboxes).\n` +
|
|
161
189
|
`Refusing to start a manager over it: it may still be running and bound to the control plane.\n` +
|
|
162
|
-
`NEXT: verify with \`ps -p <pid>\`. If it is gone, remove
|
|
190
|
+
`NEXT: verify with \`ps -p <pid>\`. If it is gone, remove \`${p}\` and re-run.`);
|
|
163
191
|
}
|
|
164
192
|
export function ensureManager(o = {}, probe = probeLiveness, readCommand = readProcessCommand) {
|
|
165
|
-
const
|
|
193
|
+
const space = o.space ?? folderSpace();
|
|
194
|
+
const state = managerLiveness(probe, readCommand, space);
|
|
166
195
|
if (state === "alive")
|
|
167
196
|
return { running: true };
|
|
168
|
-
assertManagerRecordReplaceable(probe, readCommand); // refuses on unknown / unattributable, reports foreign
|
|
197
|
+
assertManagerRecordReplaceable(probe, readCommand, space); // refuses on unknown / unattributable, reports foreign
|
|
169
198
|
startManagerDetached(o);
|
|
170
199
|
return { running: true };
|
|
171
200
|
}
|
|
@@ -184,10 +213,10 @@ export function ensureManager(o = {}, probe = probeLiveness, readCommand = readP
|
|
|
184
213
|
* A correct fix upstream reaching a latent destructive bug downstream is the worst shape available,
|
|
185
214
|
* so this refuses instead: records are removed only on proven death, never on a signal we could not
|
|
186
215
|
* send or a death we could not confirm. Found by review, with a kernel seccomp proof. */
|
|
187
|
-
export async function stopManager(probe = probeLiveness, signal = undefined, readCommand = readProcessCommand) {
|
|
216
|
+
export async function stopManager(probe = probeLiveness, signal = undefined, readCommand = readProcessCommand, space = folderSpace()) {
|
|
188
217
|
const send = signal ?? ((pid, sig) => process.kill(pid, sig));
|
|
189
|
-
const p = PID_PATH();
|
|
190
|
-
const marker = DELIVERY_AWARE_MARKER();
|
|
218
|
+
const p = PID_PATH(space);
|
|
219
|
+
const marker = DELIVERY_AWARE_MARKER(space);
|
|
191
220
|
const clear = () => {
|
|
192
221
|
rmSync(marker, { force: true });
|
|
193
222
|
rmSync(p, { force: true });
|
|
@@ -234,7 +263,7 @@ export async function stopManager(probe = probeLiveness, signal = undefined, rea
|
|
|
234
263
|
if (before === "unknown")
|
|
235
264
|
throw new Error(`refusing to stop manager pid ${pid}: its liveness cannot be determined (the kernel answered neither "running" nor "no such process"; a seccomp filter or LSM policy does this).\n` +
|
|
236
265
|
`The pidfile and delivery-aware marker are LEFT IN PLACE: deleting them would orphan a process that may still be bound to the control plane.\n` +
|
|
237
|
-
`NEXT: verify with \`ps -p ${pid}\`, then stop it yourself or remove
|
|
266
|
+
`NEXT: verify with \`ps -p ${pid}\`, then stop it yourself or remove \`${p}\` if it is gone.`);
|
|
238
267
|
try {
|
|
239
268
|
send(pid, "SIGTERM");
|
|
240
269
|
}
|
|
@@ -246,7 +275,7 @@ export async function stopManager(probe = probeLiveness, signal = undefined, rea
|
|
|
246
275
|
}
|
|
247
276
|
throw new Error(`refusing to stop manager pid ${pid}: the signal was rejected (${code ?? "unknown error"}).\n` +
|
|
248
277
|
`EPERM here means the process belongs to another user, so it is running and NOT ours to stop. The pidfile and marker are LEFT IN PLACE.\n` +
|
|
249
|
-
`NEXT: stop it as its owner, or remove
|
|
278
|
+
`NEXT: stop it as its owner, or remove \`${p}\` if you are certain it is gone.`);
|
|
250
279
|
}
|
|
251
280
|
// The signal was accepted, which is not the same as the process being gone. Prove it before
|
|
252
281
|
// removing the record, bounded, because a record deleted while its process lives is the defect.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager-proc.js","sourceRoot":"","sources":["../../src/lib/manager-proc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC1G,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"manager-proc.js","sourceRoot":"","sources":["../../src/lib/manager-proc.ts"],"names":[],"mappings":"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"}
|