@cotal-ai/workspace 0.10.0 → 0.11.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/agent-health.d.ts +20 -0
- package/dist/agent-health.d.ts.map +1 -0
- package/dist/agent-health.js +40 -0
- package/dist/agent-health.js.map +1 -0
- package/dist/auth-paths.d.ts +6 -0
- package/dist/auth-paths.d.ts.map +1 -1
- package/dist/auth-paths.js +8 -0
- package/dist/auth-paths.js.map +1 -1
- package/dist/colors.d.ts +1 -1
- package/dist/colors.js +1 -1
- package/dist/connect.d.ts +49 -4
- package/dist/connect.d.ts.map +1 -1
- package/dist/connect.js +155 -7
- package/dist/connect.js.map +1 -1
- package/dist/extensions.js +1 -1
- package/dist/flags.d.ts +20 -0
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +32 -0
- package/dist/flags.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mesh-registry.d.ts +32 -1
- package/dist/mesh-registry.d.ts.map +1 -1
- package/dist/mesh-registry.js +16 -0
- package/dist/mesh-registry.js.map +1 -1
- package/dist/mesh-target.d.ts +10 -2
- package/dist/mesh-target.d.ts.map +1 -1
- package/dist/mesh-target.js +45 -4
- package/dist/mesh-target.js.map +1 -1
- package/dist/preflight.d.ts +2 -2
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +11 -0
- package/dist/preflight.js.map +1 -1
- package/dist/render.d.ts +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +21 -12
- package/dist/render.js.map +1 -1
- package/dist/renewal.d.ts +46 -0
- package/dist/renewal.d.ts.map +1 -0
- package/dist/renewal.js +61 -0
- package/dist/renewal.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface AgentAuthHealth {
|
|
2
|
+
state: "ok" | "failed";
|
|
3
|
+
/** The operator-exact failure sentence (the bearer command's own copy), when failed. */
|
|
4
|
+
reason?: string;
|
|
5
|
+
/** ISO timestamp of the attempt. */
|
|
6
|
+
at: string;
|
|
7
|
+
}
|
|
8
|
+
/** A live managed agent's health, as `ps` should render it. Absence/malformation is AMBIGUOUS, not
|
|
9
|
+
* healthy (the preflight writes the first `ok` record before launch, so a live agent always has
|
|
10
|
+
* one — a missing file means someone removed it or the record never landed): `auth-unknown`.
|
|
11
|
+
* A record past `staleMs` on a live agent means refreshes stopped happening at all (the refresh
|
|
12
|
+
* cadence is a few minutes): `auth-stale`. Never silent-healthy. */
|
|
13
|
+
export declare function agentAuthState(path: string, staleMs?: number): {
|
|
14
|
+
state: "ok" | "auth-renewal-failed" | "auth-unknown" | "auth-stale";
|
|
15
|
+
reason?: string;
|
|
16
|
+
};
|
|
17
|
+
/** Read + validate an {@link AgentAuthHealth} file. Undefined when absent (no attempt yet) or
|
|
18
|
+
* unreadable/malformed (surfaced as unknown by {@link agentAuthState}, never a crash in `ps`). */
|
|
19
|
+
export declare function readAgentAuthHealth(path: string): AgentAuthHealth | undefined;
|
|
20
|
+
//# sourceMappingURL=agent-health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-health.d.ts","sourceRoot":"","sources":["../src/agent-health.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,IAAI,GAAG,QAAQ,CAAC;IACvB,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;qEAIqE;AACrE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,SAAc,GACpB;IAAE,KAAK,EAAE,IAAI,GAAG,qBAAqB,GAAG,cAAc,GAAG,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAQ1F;AAED;mGACmG;AACnG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAS7E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A managed user-mode agent's last bearer-refresh outcome — written by the auth provider's bearer
|
|
3
|
+
* command after EVERY attempt (`--health-file <path>`, the path composed by the manager), read by
|
|
4
|
+
* the manager's `ps` path. WORKSTATION-layer state (this module is exactly why the workspace tier
|
|
5
|
+
* exists): the auth implementation writes it, the manager renders it, neither may import the
|
|
6
|
+
* other, and it is not wire/protocol substance — so it lives here, not in core. A detached agent's
|
|
7
|
+
* silent bearer death has exactly one operator window — `ps` — and this file is what makes that
|
|
8
|
+
* window see it.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
/** A live managed agent's health, as `ps` should render it. Absence/malformation is AMBIGUOUS, not
|
|
12
|
+
* healthy (the preflight writes the first `ok` record before launch, so a live agent always has
|
|
13
|
+
* one — a missing file means someone removed it or the record never landed): `auth-unknown`.
|
|
14
|
+
* A record past `staleMs` on a live agent means refreshes stopped happening at all (the refresh
|
|
15
|
+
* cadence is a few minutes): `auth-stale`. Never silent-healthy. */
|
|
16
|
+
export function agentAuthState(path, staleMs = 15 * 60_000) {
|
|
17
|
+
const rec = readAgentAuthHealth(path);
|
|
18
|
+
if (!rec)
|
|
19
|
+
return { state: "auth-unknown", reason: "no readable bearer-refresh record - if this persists, respawn the agent" };
|
|
20
|
+
if (rec.state === "failed")
|
|
21
|
+
return { state: "auth-renewal-failed", ...(rec.reason ? { reason: rec.reason } : {}) };
|
|
22
|
+
const age = Date.now() - Date.parse(rec.at);
|
|
23
|
+
if (!Number.isFinite(age) || age > staleMs)
|
|
24
|
+
return { state: "auth-stale", reason: `last successful bearer refresh was ${Number.isFinite(age) ? Math.round(age / 60_000) + " min" : "an unreadable time"} ago - the agent may be wedged; respawn it` };
|
|
25
|
+
return { state: "ok" };
|
|
26
|
+
}
|
|
27
|
+
/** Read + validate an {@link AgentAuthHealth} file. Undefined when absent (no attempt yet) or
|
|
28
|
+
* unreadable/malformed (surfaced as unknown by {@link agentAuthState}, never a crash in `ps`). */
|
|
29
|
+
export function readAgentAuthHealth(path) {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
32
|
+
if ((parsed.state === "ok" || parsed.state === "failed") && typeof parsed.at === "string")
|
|
33
|
+
return { state: parsed.state, at: parsed.at, ...(typeof parsed.reason === "string" ? { reason: parsed.reason } : {}) };
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=agent-health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-health.js","sourceRoot":"","sources":["../src/agent-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAUvC;;;;qEAIqE;AACrE,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,OAAO,GAAG,EAAE,GAAG,MAAM;IAErB,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,yEAAyE,EAAE,CAAC;IAC9H,IAAI,GAAG,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,qBAAqB,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACnH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,OAAO;QACxC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,sCAAsC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,oBAAoB,4CAA4C,EAAE,CAAC;IAC5M,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;mGACmG;AACnG,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAoB,CAAC;QACzE,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ;YACvF,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QACzH,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
package/dist/auth-paths.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { type SpaceAuth } from "@cotal-ai/core";
|
|
2
2
|
export declare function authDir(root: string): string;
|
|
3
|
+
/** The SPACE-SCOPED user-auth state dir (`<root>/.cotal/auth/<space>`) — the one layout fact the
|
|
4
|
+
* workstation layer owns about user auth: the auth provider persists its material under this dir
|
|
5
|
+
* (opaque to us), and its EXISTENCE marks the space as user-auth-enabled on disk. Space-keyed now
|
|
6
|
+
* so multi-space-per-root is a caller change, never an on-disk migration; a (broker, space) key
|
|
7
|
+
* later extends the same shape. */
|
|
8
|
+
export declare function userAuthStateDir(root: string, space: string): string;
|
|
3
9
|
/** Find the project's `.cotal/` by walking up from `start` (like git finds `.git`), returning the
|
|
4
10
|
* directory that *contains* `.cotal/`. Falls back to `start` when none is found up the tree (a
|
|
5
11
|
* fresh setup creates `.cotal/` there). Lets `cotal` run from any subdirectory of a project. */
|
package/dist/auth-paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-paths.d.ts","sourceRoot":"","sources":["../src/auth-paths.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAe9E,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;iGAEiG;AACjG,wBAAgB,aAAa,CAAC,KAAK,GAAE,MAAsB,GAAG,MAAM,CAQnE;AAED;;iGAEiG;AACjG,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAIhE;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAIhE"}
|
|
1
|
+
{"version":3,"file":"auth-paths.d.ts","sourceRoot":"","sources":["../src/auth-paths.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAe9E,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;oCAIoC;AACpC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;iGAEiG;AACjG,wBAAgB,aAAa,CAAC,KAAK,GAAE,MAAsB,GAAG,MAAM,CAQnE;AAED;;iGAEiG;AACjG,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAIhE;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAIhE"}
|
package/dist/auth-paths.js
CHANGED
|
@@ -15,6 +15,14 @@ const AUTH_FILE = "auth.json";
|
|
|
15
15
|
export function authDir(root) {
|
|
16
16
|
return join(root, ".cotal", "auth");
|
|
17
17
|
}
|
|
18
|
+
/** The SPACE-SCOPED user-auth state dir (`<root>/.cotal/auth/<space>`) — the one layout fact the
|
|
19
|
+
* workstation layer owns about user auth: the auth provider persists its material under this dir
|
|
20
|
+
* (opaque to us), and its EXISTENCE marks the space as user-auth-enabled on disk. Space-keyed now
|
|
21
|
+
* so multi-space-per-root is a caller change, never an on-disk migration; a (broker, space) key
|
|
22
|
+
* later extends the same shape. */
|
|
23
|
+
export function userAuthStateDir(root, space) {
|
|
24
|
+
return join(authDir(root), encodeURIComponent(space));
|
|
25
|
+
}
|
|
18
26
|
/** Find the project's `.cotal/` by walking up from `start` (like git finds `.git`), returning the
|
|
19
27
|
* directory that *contains* `.cotal/`. Falls back to `start` when none is found up the tree (a
|
|
20
28
|
* fresh setup creates `.cotal/` there). Lets `cotal` run from any subdirectory of a project. */
|
package/dist/auth-paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-paths.js","sourceRoot":"","sources":["../src/auth-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAkB,MAAM,gBAAgB,CAAC;AAE9E;;;;;;;;;GASG;AAEH,MAAM,SAAS,GAAG,WAAW,CAAC;AAE9B,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;AAED;;iGAEiG;AACjG,MAAM,UAAU,aAAa,CAAC,QAAgB,OAAO,CAAC,GAAG,EAAE;IACzD,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACzB,SAAS,CAAC;QACR,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;iGAEiG;AACjG,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAe;IACxD,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,iFAAiF;IACnG,MAAM,MAAM,GAAc,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC;IACrF,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAc,CAAC;AAC1D,CAAC"}
|
|
1
|
+
{"version":3,"file":"auth-paths.js","sourceRoot":"","sources":["../src/auth-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAkB,MAAM,gBAAgB,CAAC;AAE9E;;;;;;;;;GASG;AAEH,MAAM,SAAS,GAAG,WAAW,CAAC;AAE9B,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;AAED;;;;oCAIoC;AACpC,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,KAAa;IAC1D,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;iGAEiG;AACjG,MAAM,UAAU,aAAa,CAAC,QAAgB,OAAO,CAAC,GAAG,EAAE;IACzD,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACzB,SAAS,CAAC;QACR,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;iGAEiG;AACjG,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAe;IACxD,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,iFAAiF;IACnG,MAAM,MAAM,GAAc,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC;IACrF,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAc,CAAC;AAC1D,CAAC"}
|
package/dist/colors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** ANSI color helpers for operator-facing terminal output — shared by every command surface
|
|
2
|
-
* (@cotal-ai/cli, cotal-web) so they render identically. Workstation-layer
|
|
2
|
+
* (@cotal-ai/cli, @cotal-ai/web) so they render identically. Workstation-layer
|
|
3
3
|
* concern: the wire protocol in core never prints. */
|
|
4
4
|
export declare const c: {
|
|
5
5
|
dim: (s: string) => string;
|
package/dist/colors.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** ANSI color helpers for operator-facing terminal output — shared by every command surface
|
|
2
|
-
* (@cotal-ai/cli, cotal-web) so they render identically. Workstation-layer
|
|
2
|
+
* (@cotal-ai/cli, @cotal-ai/web) so they render identically. Workstation-layer
|
|
3
3
|
* concern: the wire protocol in core never prints. */
|
|
4
4
|
export const c = {
|
|
5
5
|
dim: (s) => `\x1b[2m${s}\x1b[0m`,
|
package/dist/connect.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type Profile, type SpaceAuth } from "@cotal-ai/core";
|
|
2
|
+
import { type UserAuthInfo } from "./mesh-registry.js";
|
|
2
3
|
import { type MeshTarget } from "./mesh-target.js";
|
|
3
4
|
/**
|
|
4
5
|
* The one way every command that touches a running mesh figures out WHICH mesh + with what creds,
|
|
5
|
-
* and confirms it's actually up — shared by every command surface (@cotal-ai/cli, cotal-web)
|
|
6
|
+
* and confirms it's actually up — shared by every command surface (@cotal-ai/cli, @cotal-ai/web)
|
|
6
7
|
* so `spawn`, `send`, `console`, `web`, … all behave identically from any
|
|
7
8
|
* directory. The pure resolution/probe/classify/render steps live beside this file; these wrappers
|
|
8
9
|
* own the OPERATOR I/O — they colour, print the command-copy line, and exit the process. That is
|
|
@@ -30,6 +31,13 @@ export interface Connection {
|
|
|
30
31
|
server: string;
|
|
31
32
|
space: string;
|
|
32
33
|
creds?: string;
|
|
34
|
+
/** USER-MODE connect material (mode `"user"` only): the Cotal user bearer + the deny-all
|
|
35
|
+
* sentinel creds, exactly what `EndpointOptions.bearer`/`sentinelCreds` consume. Mutually
|
|
36
|
+
* exclusive with `creds` — spread {@link endpointAuth} instead of reading either directly. */
|
|
37
|
+
bearer?: string;
|
|
38
|
+
sentinelCreds?: string;
|
|
39
|
+
/** The user-auth registry metadata, when this is a user-mode connection. */
|
|
40
|
+
userAuth?: UserAuthInfo;
|
|
33
41
|
/** The mesh's trust material when resolved from the registry on an auth mesh — undefined for an
|
|
34
42
|
* open mesh or a raw off-registry connection (`--creds` or `--server`+unregistered `--space`).
|
|
35
43
|
* (web keeps it for its per-delete manager mint.) */
|
|
@@ -42,11 +50,48 @@ export interface Connection {
|
|
|
42
50
|
/** How the target was resolved (registry / current / flag-space / …) — undefined for raw. */
|
|
43
51
|
source?: MeshTarget["source"];
|
|
44
52
|
}
|
|
53
|
+
/** The one way a command turns a {@link Connection} into endpoint auth options — spread this into
|
|
54
|
+
* `new CotalEndpoint({...})` instead of passing `creds:` directly, so a user-mode connection
|
|
55
|
+
* (bearer + sentinel) and a static/raw one (creds) ride the same call sites without each command
|
|
56
|
+
* re-learning the mode split. */
|
|
57
|
+
export declare function endpointAuth(conn: Connection): {
|
|
58
|
+
creds?: string;
|
|
59
|
+
bearer?: string;
|
|
60
|
+
sentinelCreds?: string;
|
|
61
|
+
};
|
|
62
|
+
/** The ledger actor a HUMAN CLI connect runs as on a user-auth space (v1: one well-known name).
|
|
63
|
+
* Grant it once per user: `cotal actor grant cli --sub <your IdP subject>`. */
|
|
64
|
+
export declare const CLI_USER_ACTOR = "cli";
|
|
65
|
+
/** The auth material for one ELEVATED user-mode connection (a "view"): bearer + sentinel for the
|
|
66
|
+
* endpoint or a standalone helper, the bearer's own principal (a bearer-SOURCE endpoint needs it
|
|
67
|
+
* pinned up front), and a fresh-mint source for standing taps (each call is a full login→exchange
|
|
68
|
+
* round, so every refresh is a fresh ledger check). */
|
|
69
|
+
export interface UserViewAuth {
|
|
70
|
+
bearer: string;
|
|
71
|
+
sentinelCreds: string;
|
|
72
|
+
owner: string;
|
|
73
|
+
actor: string;
|
|
74
|
+
source: () => Promise<string>;
|
|
75
|
+
}
|
|
76
|
+
/** Mint an elevated-view bearer over an existing user-mode {@link Connection} — the user-mode
|
|
77
|
+
* path for the operator surfaces (`web`, `console`, `history clear`, `channels`, `spawn -f`).
|
|
78
|
+
* The view is authorized server-side against the fresh ledger row; a refusal THROWS the exact
|
|
79
|
+
* re-grant sentence. Call ONLY with a user-mode connection (`conn.bearer` set) — anything else
|
|
80
|
+
* is a caller bug. Long-running servers (the web delete handler) call THIS and surface the
|
|
81
|
+
* thrown sentence; CLI startup paths use {@link userViewAuthOrExit}. */
|
|
82
|
+
export declare function userViewAuth(conn: Connection, view: string): Promise<UserViewAuth>;
|
|
83
|
+
/** {@link userViewAuth}, workstation-flavoured: colour the thrown sentence and exit. */
|
|
84
|
+
export declare function userViewAuthOrExit(conn: Connection, view: string): Promise<UserViewAuth>;
|
|
85
|
+
/** Fail-closed guard for the flip: explicit raw creds are still useful for true off-registry/static
|
|
86
|
+
* meshes, but not for a user-auth mesh this machine KNOWS about. Otherwise an old static
|
|
87
|
+
* `local.<nkey>` creds file can bypass the user-mode branch and publish/join through raw `--creds`.
|
|
88
|
+
* Registry match covers cross-directory use; the on-disk marker covers a lost/stale registry. */
|
|
89
|
+
export declare function refuseStaticCredsForKnownUserAuthOrExit(space: string, server: string | undefined, what: string): void;
|
|
45
90
|
/**
|
|
46
91
|
* Resolve where a mesh-touching command connects + with what creds.
|
|
47
|
-
* • Explicit `--creds` → a RAW off-registry connection
|
|
48
|
-
*
|
|
49
|
-
*
|
|
92
|
+
* • Explicit `--creds` → a RAW off-registry connection, except when the target is a known
|
|
93
|
+
* per-user-auth mesh. Those refuse static creds fail-closed because old local creds remain
|
|
94
|
+
* broker-valid but are the wrong identity plane after the flip.
|
|
50
95
|
* • Otherwise → resolve the running mesh from the registry (works from any dir), mint `role` creds
|
|
51
96
|
* on an auth mesh, and preflight with the registry's stale-prune.
|
|
52
97
|
*/
|
package/dist/connect.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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"}
|
package/dist/connect.js
CHANGED
|
@@ -1,22 +1,109 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { DEFAULT_SERVER, DEFAULT_SPACE, mintCreds, newIdentity, probeConnect, } from "@cotal-ai/core";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { DEFAULT_SERVER, DEFAULT_SPACE, isReachable, mintCreds, newIdentity, probeConnect, registry, } from "@cotal-ai/core";
|
|
3
3
|
import { c } from "./colors.js";
|
|
4
|
+
import { findCotalRoot, userAuthStateDir } from "./auth-paths.js";
|
|
4
5
|
import { findMesh, getCurrent, removeMesh } from "./mesh-registry.js";
|
|
5
6
|
import { isWorkspaceTargetError, resolveMeshTarget } from "./mesh-target.js";
|
|
6
7
|
import { preflightTarget, pruneStaleMeshes } from "./preflight.js";
|
|
7
8
|
import { renderWorkspaceError } from "./render.js";
|
|
9
|
+
/** The one way a command turns a {@link Connection} into endpoint auth options — spread this into
|
|
10
|
+
* `new CotalEndpoint({...})` instead of passing `creds:` directly, so a user-mode connection
|
|
11
|
+
* (bearer + sentinel) and a static/raw one (creds) ride the same call sites without each command
|
|
12
|
+
* re-learning the mode split. */
|
|
13
|
+
export function endpointAuth(conn) {
|
|
14
|
+
if (conn.bearer && conn.sentinelCreds)
|
|
15
|
+
return { bearer: conn.bearer, sentinelCreds: conn.sentinelCreds };
|
|
16
|
+
return conn.creds !== undefined ? { creds: conn.creds } : {};
|
|
17
|
+
}
|
|
18
|
+
/** The ledger actor a HUMAN CLI connect runs as on a user-auth space (v1: one well-known name).
|
|
19
|
+
* Grant it once per user: `cotal actor grant cli --sub <your IdP subject>`. */
|
|
20
|
+
export const CLI_USER_ACTOR = "cli";
|
|
21
|
+
/** Mint an elevated-view bearer over an existing user-mode {@link Connection} — the user-mode
|
|
22
|
+
* path for the operator surfaces (`web`, `console`, `history clear`, `channels`, `spawn -f`).
|
|
23
|
+
* The view is authorized server-side against the fresh ledger row; a refusal THROWS the exact
|
|
24
|
+
* re-grant sentence. Call ONLY with a user-mode connection (`conn.bearer` set) — anything else
|
|
25
|
+
* is a caller bug. Long-running servers (the web delete handler) call THIS and surface the
|
|
26
|
+
* thrown sentence; CLI startup paths use {@link userViewAuthOrExit}. */
|
|
27
|
+
export async function userViewAuth(conn, view) {
|
|
28
|
+
if (!conn.bearer || !conn.userAuth || !conn.root)
|
|
29
|
+
throw new Error(`userViewAuth: not a user-mode registry connection (view "${view}")`);
|
|
30
|
+
const ua = conn.userAuth;
|
|
31
|
+
let provider;
|
|
32
|
+
try {
|
|
33
|
+
provider = registry.resolve("auth-provider", ua.provider);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
throw new Error(`space "${conn.space}" uses the "${ua.provider}" auth provider, which this build does not register - user-auth spaces need it (the official cotal binary includes @cotal-ai/auth)`);
|
|
37
|
+
}
|
|
38
|
+
const dir = userAuthStateDir(conn.root, conn.space);
|
|
39
|
+
const mint = () => provider.userCredentials({ dir, space: conn.space, actor: CLI_USER_ACTOR, view });
|
|
40
|
+
const { bearer, sentinelCreds } = await mint();
|
|
41
|
+
const { owner, actor } = principalFromBearer(bearer);
|
|
42
|
+
return { bearer, sentinelCreds, owner, actor, source: () => mint().then((r) => r.bearer) };
|
|
43
|
+
}
|
|
44
|
+
/** {@link userViewAuth}, workstation-flavoured: colour the thrown sentence and exit. */
|
|
45
|
+
export async function userViewAuthOrExit(conn, view) {
|
|
46
|
+
try {
|
|
47
|
+
return await userViewAuth(conn, view);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
console.error(c.red(`✗ ${e instanceof Error ? e.message : String(e)}`));
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** The (owner, actor) principal a minted bearer is bound to — read from the JWT payload WITHOUT
|
|
55
|
+
* verification (client side; the broker verifies). A bearer-source endpoint requires the principal
|
|
56
|
+
* pinned at construction, and the bearer is the one authoritative place it lives. */
|
|
57
|
+
function principalFromBearer(bearer) {
|
|
58
|
+
try {
|
|
59
|
+
const mid = bearer.split(".")[1];
|
|
60
|
+
if (!mid)
|
|
61
|
+
throw new Error("not a compact JWS");
|
|
62
|
+
const payload = JSON.parse(Buffer.from(mid, "base64url").toString("utf8"));
|
|
63
|
+
if (typeof payload.sub !== "string" || !payload.sub || typeof payload.act?.actor !== "string" || !payload.act.actor)
|
|
64
|
+
throw new Error("missing sub/act.actor");
|
|
65
|
+
return { owner: payload.sub, actor: payload.act.actor };
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
throw new Error(`could not read the principal from the minted bearer (${e instanceof Error ? e.message : String(e)}) - the auth service's build may be stale; restart it with \`cotal up\``);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Fail-closed guard for the flip: explicit raw creds are still useful for true off-registry/static
|
|
72
|
+
* meshes, but not for a user-auth mesh this machine KNOWS about. Otherwise an old static
|
|
73
|
+
* `local.<nkey>` creds file can bypass the user-mode branch and publish/join through raw `--creds`.
|
|
74
|
+
* Registry match covers cross-directory use; the on-disk marker covers a lost/stale registry. */
|
|
75
|
+
export function refuseStaticCredsForKnownUserAuthOrExit(space, server, what) {
|
|
76
|
+
const recorded = findMesh(space);
|
|
77
|
+
const knownRecordedUser = recorded?.mode === "user" && (server === undefined || recorded.server === server);
|
|
78
|
+
const knownLocalUser = existsSync(userAuthStateDir(findCotalRoot(), space));
|
|
79
|
+
if (!knownRecordedUser && !knownLocalUser)
|
|
80
|
+
return;
|
|
81
|
+
console.error(c.red(`✗ ${what} tried to authenticate with a static creds file, but space "${space}" is a per-user-auth mesh - old --creds files are refused here so they can't bypass user accounts.`));
|
|
82
|
+
console.error(c.dim(` Sign in with \`cotal login\` and use the user-mode path instead (for agents: \`cotal spawn\`).`));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
8
85
|
/**
|
|
9
86
|
* Resolve where a mesh-touching command connects + with what creds.
|
|
10
|
-
* • Explicit `--creds` → a RAW off-registry connection
|
|
11
|
-
*
|
|
12
|
-
*
|
|
87
|
+
* • Explicit `--creds` → a RAW off-registry connection, except when the target is a known
|
|
88
|
+
* per-user-auth mesh. Those refuse static creds fail-closed because old local creds remain
|
|
89
|
+
* broker-valid but are the wrong identity plane after the flip.
|
|
13
90
|
* • Otherwise → resolve the running mesh from the registry (works from any dir), mint `role` creds
|
|
14
91
|
* on an auth mesh, and preflight with the registry's stale-prune.
|
|
15
92
|
*/
|
|
16
93
|
export async function connectOrExit(flags, role) {
|
|
17
94
|
if (flags.creds) {
|
|
18
|
-
const server = flags.server ?? DEFAULT_SERVER;
|
|
19
95
|
const space = flags.space ?? DEFAULT_SPACE;
|
|
96
|
+
// Run the flip guard with the RAW `--server` (may be undefined). The guard treats "no --server"
|
|
97
|
+
// as "any recorded server for this space", so a user mesh on a NON-default port is still
|
|
98
|
+
// recognized when the caller omits --server. Defaulting the server BEFORE the guard would make
|
|
99
|
+
// its `recorded.server === server` match miss every non-4222 user mesh, letting a static --creds
|
|
100
|
+
// slip past the flip.
|
|
101
|
+
refuseStaticCredsForKnownUserAuthOrExit(space, flags.server, "--creds");
|
|
102
|
+
const server = flags.server ?? DEFAULT_SERVER;
|
|
103
|
+
if (!existsSync(flags.creds)) {
|
|
104
|
+
console.error(c.red(`✗ creds file not found: ${flags.creds}`));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
20
107
|
const creds = readFileSync(flags.creds, "utf8");
|
|
21
108
|
await reachableOrExit(server, { creds });
|
|
22
109
|
return { server, space, creds };
|
|
@@ -26,14 +113,64 @@ export async function connectOrExit(flags, role) {
|
|
|
26
113
|
// off-registry (no registry lookup, no prune). A registered `--space` still goes through the
|
|
27
114
|
// resolver below (which honors `--server` as an override); `--server` alone resolves there too.
|
|
28
115
|
if (flags.server && flags.space && !findMesh(flags.space)) {
|
|
116
|
+
// Fail-closed marker, same posture as the resolver's: this machine may hold USER-AUTH state
|
|
117
|
+
// for that very space even when the registry lost (or never had) the entry — treating it as an
|
|
118
|
+
// open broker would credless-connect into a callout denial whose copy sends the operator
|
|
119
|
+
// port-hunting. Name the real state and the recovery instead.
|
|
120
|
+
if (existsSync(userAuthStateDir(findCotalRoot(), flags.space))) {
|
|
121
|
+
console.error(c.red(`✗ space "${flags.space}" has user auth enabled on disk but no usable registry entry - re-record it with \`cotal up\` from its project folder, then sign in (\`cotal login\`)`));
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
29
124
|
await reachableOrExit(flags.server, {});
|
|
30
125
|
return { server: flags.server, space: flags.space };
|
|
31
126
|
}
|
|
32
127
|
const target = await resolveTargetOrExit({ server: flags.server, space: flags.space });
|
|
128
|
+
// USER MODE is a HARD branch: it never mints from on-disk trust material (static creds DO work
|
|
129
|
+
// on a user-auth broker — minting here would silently connect the operator on the wrong identity
|
|
130
|
+
// plane) and never connects credlessly. Everything it needs comes from the login cache + the
|
|
131
|
+
// provider's space-scoped state; every failure is one sentence with the exact operator action.
|
|
132
|
+
if (target.mode === "user")
|
|
133
|
+
return userConnectOrExit(target);
|
|
33
134
|
const creds = target.auth ? await mintCreds(target.auth, newIdentity(), role) : undefined;
|
|
34
135
|
await preflightOrExit(target, creds);
|
|
35
136
|
return { server: target.server, space: target.space, creds, auth: target.auth, root: target.root, source: target.source };
|
|
36
137
|
}
|
|
138
|
+
/** The user-mode connect: resolve the space's auth provider from the registry (composition-root
|
|
139
|
+
* supplied — never imported here), exchange this machine's login session for a bearer, and hand
|
|
140
|
+
* back bearer + sentinel. The provider owns the failure copy for its own steps (not logged in,
|
|
141
|
+
* service down, actor ungranted) — each is already an exact recovery sentence; this wrapper only
|
|
142
|
+
* colours and exits (the workstation-layer contract). */
|
|
143
|
+
async function userConnectOrExit(target) {
|
|
144
|
+
const ua = target.userAuth; // mode "user" guarantees it (targetFromEntry throws otherwise)
|
|
145
|
+
let provider;
|
|
146
|
+
try {
|
|
147
|
+
provider = registry.resolve("auth-provider", ua.provider);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
console.error(c.red(`✗ space "${target.space}" uses the "${ua.provider}" auth provider, which this build does not register - user-auth spaces need it (the official cotal binary includes @cotal-ai/auth)`));
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const { bearer, sentinelCreds } = await provider.userCredentials({
|
|
155
|
+
dir: userAuthStateDir(target.root, target.space),
|
|
156
|
+
space: target.space,
|
|
157
|
+
actor: CLI_USER_ACTOR,
|
|
158
|
+
});
|
|
159
|
+
return {
|
|
160
|
+
server: target.server,
|
|
161
|
+
space: target.space,
|
|
162
|
+
bearer,
|
|
163
|
+
sentinelCreds,
|
|
164
|
+
userAuth: ua,
|
|
165
|
+
root: target.root,
|
|
166
|
+
source: target.source,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
console.error(c.red(`✗ ${e instanceof Error ? e.message : String(e)}`));
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
37
174
|
/** Reachability check for a RAW (off-registry) connection — one plain sentence, never a registry/
|
|
38
175
|
* stale-entry message and never a prune. Used by the `--creds` escape hatch and `join`'s explicit
|
|
39
176
|
* (link/token/creds) path, both of which connect to a broker the user named, not the registry. */
|
|
@@ -69,7 +206,7 @@ export async function resolveTargetOrExit(flags) {
|
|
|
69
206
|
// otherwise quietly redirect a stale default.
|
|
70
207
|
const cur = getCurrent();
|
|
71
208
|
if (cur && !findMesh(cur) && target.source === "registry")
|
|
72
|
-
console.error(c.dim(`note: default mesh "${cur}" is down
|
|
209
|
+
console.error(c.dim(`note: default mesh "${cur}" is down - using "${target.space}"`));
|
|
73
210
|
return target;
|
|
74
211
|
}
|
|
75
212
|
/** Confirm the resolved mesh is up and accepts these creds — replaces the raw NATS "Authorization
|
|
@@ -79,6 +216,17 @@ export async function resolveTargetOrExit(flags) {
|
|
|
79
216
|
* caller's `--creds`/minted creds); otherwise a throwaway identity is minted from the target's
|
|
80
217
|
* own trust material. */
|
|
81
218
|
export async function preflightOrExit(target, probeCreds) {
|
|
219
|
+
// USER-mode targets are never credless-probed here: the callout denies a bare connect, the
|
|
220
|
+
// classifier reads that as a stale registry entry, and the PRUNE deletes a healthy mesh's
|
|
221
|
+
// record (found live: foreground `spawn` did exactly this and every later command fell into
|
|
222
|
+
// raw-path copy). Liveness is the only mode-blind read; the real auth preflight for a user
|
|
223
|
+
// target is the user connect / bearer chain itself.
|
|
224
|
+
if (target.mode === "user") {
|
|
225
|
+
if (await isReachable(target.server))
|
|
226
|
+
return;
|
|
227
|
+
console.error(c.red(`✗ mesh "${target.space}" at ${target.server} is not reachable - start it with \`cotal up\` from its project folder`));
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
82
230
|
const r = await preflightTarget(target, probeCreds);
|
|
83
231
|
if (r.ok)
|
|
84
232
|
return;
|
package/dist/connect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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"}
|
package/dist/extensions.js
CHANGED
|
@@ -19,7 +19,7 @@ export function loadExtensionsManifest() {
|
|
|
19
19
|
parsed = JSON.parse(readFileSync(p, "utf8"));
|
|
20
20
|
}
|
|
21
21
|
catch (e) {
|
|
22
|
-
throw new Error(`corrupt extensions manifest ${p}: ${e.message}
|
|
22
|
+
throw new Error(`corrupt extensions manifest ${p}: ${e.message} - fix or delete it, then \`cotal ext add\` again`);
|
|
23
23
|
}
|
|
24
24
|
const m = parsed;
|
|
25
25
|
if (!Array.isArray(m.extensions))
|
package/dist/flags.d.ts
CHANGED
|
@@ -74,6 +74,17 @@ export declare const launchFlags: readonly [{
|
|
|
74
74
|
readonly type: "string";
|
|
75
75
|
readonly value: "<m>";
|
|
76
76
|
readonly description: "model override (wins over the agent file's model:)";
|
|
77
|
+
}, {
|
|
78
|
+
readonly name: "variant";
|
|
79
|
+
readonly type: "string";
|
|
80
|
+
readonly value: "<v>";
|
|
81
|
+
readonly description: "model variant override (connector-defined; wins over the agent file's variant:)";
|
|
82
|
+
}, {
|
|
83
|
+
readonly name: "opt";
|
|
84
|
+
readonly type: "string";
|
|
85
|
+
readonly multiple: true;
|
|
86
|
+
readonly value: "<k=v>";
|
|
87
|
+
readonly description: "connector-specific launch option (repeatable); wins per-key over the agent file's launchOptions:";
|
|
77
88
|
}, {
|
|
78
89
|
readonly name: "cwd";
|
|
79
90
|
readonly type: "string";
|
|
@@ -118,4 +129,13 @@ export declare const launchFlags: readonly [{
|
|
|
118
129
|
readonly value: "<a,b>";
|
|
119
130
|
readonly description: "post ACL override";
|
|
120
131
|
}];
|
|
132
|
+
/** Parse repeated `--opt key=value` pairs into the opaque launch-options map. The key is the text
|
|
133
|
+
* before the first `=`; the value is the remainder (may itself contain `=`). Fails loud on a
|
|
134
|
+
* missing `=`, an empty key, or a duplicate key — never silent last-wins. Values are strings (the
|
|
135
|
+
* CLI has no types); the consuming connector coerces. Returns undefined when there are none. */
|
|
136
|
+
export declare function parseLaunchOptions(pairs: string[] | undefined): Record<string, string> | undefined;
|
|
137
|
+
/** Merge two opaque launch-option maps per key — `override` (e.g. a `--opt` flag) wins over `base`
|
|
138
|
+
* (e.g. the persona file's `launchOptions:`), mirroring how `--model`/`--variant` beat the file.
|
|
139
|
+
* Returns undefined when the result is empty, so an absent bag never becomes an empty object. */
|
|
140
|
+
export declare function mergeLaunchOptions(base: Record<string, unknown> | undefined, override: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
|
|
121
141
|
//# sourceMappingURL=flags.d.ts.map
|
package/dist/flags.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;;;;;CAAwI,CAAC;AAC/J,eAAO,MAAM,UAAU;;;;;CAAgJ,CAAC;AACxK,eAAO,MAAM,SAAS;;;;;CAA2I,CAAC;AAElK;;+BAE+B;AAC/B,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;EAA4E,CAAC;AAErG;;;;;;GAMG;AACH,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;;;;;CAAwI,CAAC;AAC/J,eAAO,MAAM,UAAU;;;;;CAAgJ,CAAC;AACxK,eAAO,MAAM,SAAS;;;;;CAA2I,CAAC;AAElK;;+BAE+B;AAC/B,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;EAA4E,CAAC;AAErG;;;;;;GAMG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBgB,CAAC;AAEzC;;;iGAGiG;AACjG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAYlG;AAED;;kGAEkG;AAClG,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC5C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAIrC"}
|
package/dist/flags.js
CHANGED
|
@@ -25,6 +25,8 @@ export const launchFlags = [
|
|
|
25
25
|
{ name: "agent", type: "string", value: "<a>", description: "connector type (claude, opencode, hermes …); defaults from COTAL_DEFAULT_AGENT" },
|
|
26
26
|
{ name: "role", type: "string", value: "<r>", description: "role override (wins over the agent file's role:)" },
|
|
27
27
|
{ name: "model", type: "string", value: "<m>", description: "model override (wins over the agent file's model:)" },
|
|
28
|
+
{ name: "variant", type: "string", value: "<v>", description: "model variant override (connector-defined; wins over the agent file's variant:)" },
|
|
29
|
+
{ name: "opt", type: "string", multiple: true, value: "<k=v>", description: "connector-specific launch option (repeatable); wins per-key over the agent file's launchOptions:" },
|
|
28
30
|
{ name: "cwd", type: "string", value: "<dir>", description: "working directory to root the agent at" },
|
|
29
31
|
{ name: "prompt", type: "string", value: "<text>", description: "initial prompt auto-submitted at start" },
|
|
30
32
|
{ name: "resume", type: "string", value: "<id>", description: "fork an existing session id into the mesh (claude only; detached: pair with --cwd)" },
|
|
@@ -35,4 +37,34 @@ export const launchFlags = [
|
|
|
35
37
|
{ name: "allow-subscribe", type: "string", value: "<a,b>", description: "read ACL override" },
|
|
36
38
|
{ name: "allow-publish", type: "string", value: "<a,b>", description: "post ACL override" },
|
|
37
39
|
];
|
|
40
|
+
/** Parse repeated `--opt key=value` pairs into the opaque launch-options map. The key is the text
|
|
41
|
+
* before the first `=`; the value is the remainder (may itself contain `=`). Fails loud on a
|
|
42
|
+
* missing `=`, an empty key, or a duplicate key — never silent last-wins. Values are strings (the
|
|
43
|
+
* CLI has no types); the consuming connector coerces. Returns undefined when there are none. */
|
|
44
|
+
export function parseLaunchOptions(pairs) {
|
|
45
|
+
if (!pairs?.length)
|
|
46
|
+
return undefined;
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const raw of pairs) {
|
|
49
|
+
const eq = raw.indexOf("=");
|
|
50
|
+
if (eq === -1)
|
|
51
|
+
throw new Error(`--opt must be key=value (got "${raw}")`);
|
|
52
|
+
const key = raw.slice(0, eq).trim();
|
|
53
|
+
if (!key)
|
|
54
|
+
throw new Error(`--opt has an empty key (got "${raw}")`);
|
|
55
|
+
if (key in out)
|
|
56
|
+
throw new Error(`--opt "${key}" given more than once`);
|
|
57
|
+
out[key] = raw.slice(eq + 1);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
/** Merge two opaque launch-option maps per key — `override` (e.g. a `--opt` flag) wins over `base`
|
|
62
|
+
* (e.g. the persona file's `launchOptions:`), mirroring how `--model`/`--variant` beat the file.
|
|
63
|
+
* Returns undefined when the result is empty, so an absent bag never becomes an empty object. */
|
|
64
|
+
export function mergeLaunchOptions(base, override) {
|
|
65
|
+
if (!base && !override)
|
|
66
|
+
return undefined;
|
|
67
|
+
const merged = { ...base, ...override };
|
|
68
|
+
return Object.keys(merged).length ? merged : undefined;
|
|
69
|
+
}
|
|
38
70
|
//# sourceMappingURL=flags.js.map
|
package/dist/flags.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,2CAA2C,EAA8B,CAAC;AAC/J,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,gDAAgD,EAA8B,CAAC;AACxK,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,2CAA2C,EAA8B,CAAC;AAElK;;+BAE+B;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAwC,CAAC;AAErG;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,qDAAqD,EAAE;IAClH,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,wEAAwE,EAAE;IACrJ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,gFAAgF,EAAE;IAC9I,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,kDAAkD,EAAE;IAC/G,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,oDAAoD,EAAE;IAClH,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,wCAAwC,EAAE;IACtG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,wCAAwC,EAAE;IAC1G,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,oFAAoF,EAAE;IACpJ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,4CAA4C,EAAE;IAClG,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,wCAAwC,EAAE;IACjG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,iDAAiD,EAAE;IACvH,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,2BAA2B,EAAE;IAC/F,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAC7F,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;CACrD,CAAC"}
|
|
1
|
+
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./auth-paths.js";
|
|
2
|
+
export * from "./agent-health.js";
|
|
2
3
|
export * from "./bin-path.js";
|
|
3
4
|
export * from "./colors.js";
|
|
4
5
|
export * from "./connect.js";
|
|
@@ -10,5 +11,6 @@ export * from "./mesh-registry.js";
|
|
|
10
11
|
export * from "./mesh-target.js";
|
|
11
12
|
export * from "./preflight.js";
|
|
12
13
|
export * from "./render.js";
|
|
14
|
+
export * from "./renewal.js";
|
|
13
15
|
export * from "./space.js";
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./auth-paths.js";
|
|
2
|
+
export * from "./agent-health.js";
|
|
2
3
|
export * from "./bin-path.js";
|
|
3
4
|
export * from "./colors.js";
|
|
4
5
|
export * from "./connect.js";
|
|
@@ -10,5 +11,6 @@ export * from "./mesh-registry.js";
|
|
|
10
11
|
export * from "./mesh-target.js";
|
|
11
12
|
export * from "./preflight.js";
|
|
12
13
|
export * from "./render.js";
|
|
14
|
+
export * from "./renewal.js";
|
|
13
15
|
export * from "./space.js";
|
|
14
16
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
|
package/dist/mesh-registry.d.ts
CHANGED
|
@@ -18,10 +18,41 @@ export interface MeshEntry {
|
|
|
18
18
|
server: string;
|
|
19
19
|
/** Absolute path whose `.cotal/{auth,agents}` hold this mesh's trust material + personas. */
|
|
20
20
|
root: string;
|
|
21
|
-
|
|
21
|
+
/** How the broker authenticates: static per-agent JWT creds (`auth`), none (`open`), or
|
|
22
|
+
* per-USER auth (`user`) — login + bearer through the space's auth service. `user` is its own
|
|
23
|
+
* connect path: it must never be treated as `auth` with missing creds, nor as `open`. */
|
|
24
|
+
mode: "auth" | "open" | "user";
|
|
25
|
+
/** The user-auth client metadata, present iff `mode === "user"` — how a connect from any
|
|
26
|
+
* directory on THIS machine finds the login target and exchange. Local operator config, not
|
|
27
|
+
* broker truth: it lives under the user's protected registry dir and is trusted the way the
|
|
28
|
+
* registry itself is; remote/cross-machine discovery is explicitly out of its scope. */
|
|
29
|
+
userAuth?: UserAuthInfo;
|
|
22
30
|
/** ISO timestamp of when the record was written. */
|
|
23
31
|
ts: string;
|
|
24
32
|
}
|
|
33
|
+
/** Non-secret user-auth metadata on a {@link MeshEntry}. TRUST PINS and CONVENIENCE ENDPOINTS are
|
|
34
|
+
* deliberately separate fields: `idp` is what the operator pinned at `up --user-auth` time (the
|
|
35
|
+
* login/exchange trust config — error messages and login guidance use THIS); `endpoints` is where
|
|
36
|
+
* the local auth service happened to bind (runtime, may change across restarts, re-recorded by
|
|
37
|
+
* `up`). Nothing here is ever taken from a presented token or an unauthenticated response. */
|
|
38
|
+
export interface UserAuthInfo {
|
|
39
|
+
/** The registered auth provider's name (registry key, e.g. `"cotal"`). */
|
|
40
|
+
provider: string;
|
|
41
|
+
/** The pinned IdP: the login target (`cotal login --idp <url>`) + exact issuer/audience pins. */
|
|
42
|
+
idp: {
|
|
43
|
+
url: string;
|
|
44
|
+
issuer: string;
|
|
45
|
+
audience: string;
|
|
46
|
+
};
|
|
47
|
+
/** The local auth service's runtime endpoints (exchange/JWKS base URL). Convenience, not trust. */
|
|
48
|
+
endpoints?: {
|
|
49
|
+
url?: string;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Runtime-validate a provider's opaque `publicAuth` blob into a {@link UserAuthInfo} — the
|
|
53
|
+
* workstation layer owns this shape (core stays IdP-agnostic), so the boundary where an
|
|
54
|
+
* arbitrary provider's metadata enters the registry is checked here, fail-loud. */
|
|
55
|
+
export declare function assertUserAuthInfo(v: unknown): UserAuthInfo;
|
|
25
56
|
/** The cotal machine-home dir, overridable via `COTAL_HOME` so tests sandbox it and never touch the
|
|
26
57
|
* real one. POSIX: `~/.cotal`. Windows: `%LOCALAPPDATA%\Cotal` — the platform's place for per-user
|
|
27
58
|
* app state (a dotdir in the profile root is a Unix idiom; `%LOCALAPPDATA%` is already a per-user
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mesh-registry.d.ts","sourceRoot":"","sources":["../src/mesh-registry.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"mesh-registry.d.ts","sourceRoot":"","sources":["../src/mesh-registry.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb;;8FAE0F;IAC1F,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B;;;6FAGyF;IACzF,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;+FAI+F;AAC/F,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,GAAG,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,mGAAmG;IACnG,SAAS,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AAED;;oFAEoF;AACpF,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,YAAY,CAY3D;AAED;;;;6DAI6D;AAC7D,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,yEAAyE;AACzE,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAUD,kGAAkG;AAClG,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,CAW7C;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED;2CAC2C;AAC3C,wBAAgB,UAAU,IAAI,SAAS,EAAE,CAgBxC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE7D;AAED;;oBAEoB;AACpB,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAM/C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG9C;AAED,wBAAgB,YAAY,IAAI,IAAI,CAEnC"}
|
package/dist/mesh-registry.js
CHANGED
|
@@ -2,6 +2,22 @@ import { readFileSync, readdirSync, renameSync, rmSync } from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { mkSecretDir, writeSecretFile } from "@cotal-ai/core";
|
|
5
|
+
/** Runtime-validate a provider's opaque `publicAuth` blob into a {@link UserAuthInfo} — the
|
|
6
|
+
* workstation layer owns this shape (core stays IdP-agnostic), so the boundary where an
|
|
7
|
+
* arbitrary provider's metadata enters the registry is checked here, fail-loud. */
|
|
8
|
+
export function assertUserAuthInfo(v) {
|
|
9
|
+
const o = v;
|
|
10
|
+
if (o === null || typeof o !== "object" || typeof o.provider !== "string" || !o.provider)
|
|
11
|
+
throw new Error("auth provider publicAuth: a provider name is required");
|
|
12
|
+
if (o.idp === null || typeof o.idp !== "object" || typeof o.idp.url !== "string" || !o.idp.url ||
|
|
13
|
+
typeof o.idp.issuer !== "string" || !o.idp.issuer || typeof o.idp.audience !== "string" || !o.idp.audience)
|
|
14
|
+
throw new Error("auth provider publicAuth: idp { url, issuer, audience } trust pins are required");
|
|
15
|
+
if (o.endpoints !== undefined && (o.endpoints === null || typeof o.endpoints !== "object" ||
|
|
16
|
+
(o.endpoints.url !== undefined && typeof o.endpoints.url !== "string")))
|
|
17
|
+
throw new Error("auth provider publicAuth: endpoints, when present, must be { url?: string }");
|
|
18
|
+
return { provider: o.provider, idp: { url: o.idp.url, issuer: o.idp.issuer, audience: o.idp.audience },
|
|
19
|
+
...(o.endpoints ? { endpoints: { ...(o.endpoints.url ? { url: o.endpoints.url } : {}) } } : {}) };
|
|
20
|
+
}
|
|
5
21
|
/** The cotal machine-home dir, overridable via `COTAL_HOME` so tests sandbox it and never touch the
|
|
6
22
|
* real one. POSIX: `~/.cotal`. Windows: `%LOCALAPPDATA%\Cotal` — the platform's place for per-user
|
|
7
23
|
* app state (a dotdir in the profile root is a Unix idiom; `%LOCALAPPDATA%` is already a per-user
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mesh-registry.js","sourceRoot":"","sources":["../src/mesh-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"mesh-registry.js","sourceRoot":"","sources":["../src/mesh-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/mesh-target.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type SpaceAuth } from "@cotal-ai/core";
|
|
2
|
+
import { type MeshEntry, type UserAuthInfo } from "./mesh-registry.js";
|
|
2
3
|
/**
|
|
3
4
|
* One coherent answer to "which mesh does this command act on, and where do its creds + personas
|
|
4
5
|
* live" — resolved identically for both, so a spawn can never authenticate to mesh A while loading
|
|
@@ -13,8 +14,15 @@ export interface MeshTarget {
|
|
|
13
14
|
root: string;
|
|
14
15
|
server: string;
|
|
15
16
|
space: string;
|
|
16
|
-
/**
|
|
17
|
+
/** The mesh's auth mode — `user` is its OWN connect path (login + bearer), a hard branch:
|
|
18
|
+
* it never static-mints from `auth` and never connects credlessly like `open`. */
|
|
19
|
+
mode: MeshEntry["mode"];
|
|
20
|
+
/** Trust material, for a STATIC-auth mesh only — undefined for open AND for user mode (a
|
|
21
|
+
* user-mode root may still hold `auth.json` on disk; deliberately not loaded here so no caller
|
|
22
|
+
* can drift into minting static creds for a user-auth space). */
|
|
17
23
|
auth?: SpaceAuth;
|
|
24
|
+
/** User-auth client metadata (from the registry entry), present iff `mode === "user"`. */
|
|
25
|
+
userAuth?: UserAuthInfo;
|
|
18
26
|
/** `<root>/.cotal/agents` — the persona catalog for this mesh. */
|
|
19
27
|
personaRoot: string;
|
|
20
28
|
/** Where the target came from — this also carries OWNERSHIP for pruning. `registry`/`current`/
|
|
@@ -35,7 +43,7 @@ export interface ResolveFlags {
|
|
|
35
43
|
/** The distinct, command-agnostic reasons {@link resolveMeshTarget} can't pick a single mesh. Each
|
|
36
44
|
* maps 1:1 to a former prose-throw; the recovery copy (`cotal up`/`meshes`/`use`) is the renderer's
|
|
37
45
|
* job ({@link renderWorkspaceError}), not the protocol's. */
|
|
38
|
-
export type MeshTargetErrorCode = "no-meshes" | "unknown-space" | "ambiguous-target" | "default-occupied" | "stale-auth-root";
|
|
46
|
+
export type MeshTargetErrorCode = "no-meshes" | "unknown-space" | "ambiguous-target" | "default-occupied" | "stale-auth-root" | "user-auth-unrecorded";
|
|
39
47
|
/** Structured context for a {@link MeshTargetError} — enough for any surface to render its own
|
|
40
48
|
* recovery affordance (a CLI sentence, a web button, an SDK embed that wants no command at all). */
|
|
41
49
|
export interface MeshTargetErrorDetails {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mesh-target.d.ts","sourceRoot":"","sources":["../src/mesh-target.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"mesh-target.d.ts","sourceRoot":"","sources":["../src/mesh-target.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,EAML,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd;uFACmF;IACnF,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACxB;;sEAEkE;IAClE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;4GAMwG;IACxG,MAAM,EACF,aAAa,GACb,YAAY,GACZ,qBAAqB,GACrB,aAAa,GACb,gBAAgB,GAChB,UAAU,GACV,SAAS,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;8DAE8D;AAC9D,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,eAAe,GACf,kBAAkB,GAClB,kBAAkB,GAClB,iBAAiB,GACjB,sBAAsB,CAAC;AAE3B;qGACqG;AACrG,MAAM,WAAW,sBAAsB;IACrC,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,mFAAmF;IACnF,QAAQ,CAAC,KAAK,uCAA0B;IACxC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;gBAEvC,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,sBAA2B,EACpC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAOhC;AAED;uGACuG;AACvG,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,eAAe,CAMvE;AAmGD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,YAAiB,GAAG,UAAU,CAyDnF"}
|
package/dist/mesh-target.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import { DEFAULT_SERVER, DEFAULT_SPACE } from "@cotal-ai/core";
|
|
4
|
-
import { authDir, findCotalRoot, loadSpaceAuth } from "./auth-paths.js";
|
|
4
|
+
import { authDir, findCotalRoot, loadSpaceAuth, userAuthStateDir } from "./auth-paths.js";
|
|
5
5
|
import { findMesh, getCurrent, homeCotalDir, loadMeshes, removeMesh, } from "./mesh-registry.js";
|
|
6
6
|
const WORKSPACE_TARGET_ERROR = "cotal:workspace:mesh-target-error";
|
|
7
7
|
/**
|
|
@@ -34,8 +34,10 @@ function personaRoot(root) {
|
|
|
34
34
|
function targetFromEntry(m, server, source) {
|
|
35
35
|
// Honor the recorded mode: an OPEN mesh connects credlessly even if its root still has auth
|
|
36
36
|
// material on disk (e.g. a root that once ran auth mode). Loading it would make `spawn` mint
|
|
37
|
-
// creds against a broker that takes none.
|
|
37
|
+
// creds against a broker that takes none. A USER mesh loads NO static auth either — its connect
|
|
38
|
+
// material comes from the login/bearer path; the entry's `userAuth` metadata rides the target.
|
|
38
39
|
let auth;
|
|
40
|
+
let userAuth;
|
|
39
41
|
if (m.mode === "auth") {
|
|
40
42
|
auth = loadSpaceAuth(authDir(m.root));
|
|
41
43
|
// Defense in depth: the root's on-disk auth must still be for THIS space. A divergence (the root
|
|
@@ -46,18 +48,57 @@ function targetFromEntry(m, server, source) {
|
|
|
46
48
|
throw new MeshTargetError("stale-auth-root", `registry entry "${m.space}" points at ${m.root}, whose on-disk auth is now for "${auth.space}"`, { space: m.space, root: m.root, found: auth.space });
|
|
47
49
|
}
|
|
48
50
|
}
|
|
51
|
+
else if (m.mode === "user") {
|
|
52
|
+
// A user entry without its metadata cannot produce an actionable login line — treat it as the
|
|
53
|
+
// unrecorded case (re-`up` rewrites the entry) rather than half-connecting.
|
|
54
|
+
if (!m.userAuth)
|
|
55
|
+
throw new MeshTargetError("user-auth-unrecorded", `registry entry "${m.space}" is user-auth but carries no IdP metadata`, { space: m.space, root: m.root });
|
|
56
|
+
userAuth = m.userAuth;
|
|
57
|
+
}
|
|
49
58
|
return {
|
|
50
59
|
root: m.root,
|
|
51
60
|
server,
|
|
52
61
|
space: m.space,
|
|
62
|
+
mode: m.mode,
|
|
53
63
|
auth,
|
|
64
|
+
...(userAuth ? { userAuth } : {}),
|
|
54
65
|
personaRoot: personaRoot(m.root),
|
|
55
66
|
source,
|
|
56
67
|
};
|
|
57
68
|
}
|
|
58
69
|
function localTarget(root, server, source) {
|
|
59
70
|
const auth = loadSpaceAuth(authDir(root));
|
|
60
|
-
|
|
71
|
+
const space = auth?.space ?? DEFAULT_SPACE;
|
|
72
|
+
// U10 guard: a user-auth space resolved WITHOUT its registry entry (pruned/never recorded) must
|
|
73
|
+
// not silently static-mint — static creds DO work on a user-auth broker, which would connect the
|
|
74
|
+
// operator on the wrong identity plane. The on-disk marker is the space-scoped user-auth state
|
|
75
|
+
// dir; the recovery (re-`cotal up` in that root) rewrites the registry entry with the IdP pins.
|
|
76
|
+
// The marker binds even when `auth.json` itself is missing/corrupt — a surviving state dir alone
|
|
77
|
+
// proves user auth was enabled here, and the alternative would classify the root "open" and
|
|
78
|
+
// connect credlessly toward a user-auth broker. Fail closed on the marker, whichever half died.
|
|
79
|
+
const userSpace = auth
|
|
80
|
+
? existsSync(userAuthStateDir(root, space))
|
|
81
|
+
? space
|
|
82
|
+
: undefined
|
|
83
|
+
: userAuthSpacesOnDisk(authDir(root))[0];
|
|
84
|
+
if (userSpace !== undefined)
|
|
85
|
+
throw new MeshTargetError("user-auth-unrecorded", `space "${userSpace}" has user auth enabled on disk but no usable registry entry`, { space: userSpace, root });
|
|
86
|
+
return { root, server, space, mode: auth ? "auth" : "open", auth, personaRoot: personaRoot(root), source };
|
|
87
|
+
}
|
|
88
|
+
/** Space names with user-auth state under a root's auth dir, detectable WITHOUT `auth.json`: each
|
|
89
|
+
* enabled space is a subdirectory (encodeURIComponent(space)) holding the provider's pinned
|
|
90
|
+
* material — `idp.json` is written first at enable, `callout.json` right after, so either one
|
|
91
|
+
* marks the dir as user-auth state (never confusable with a stray empty folder). */
|
|
92
|
+
function userAuthSpacesOnDisk(dir) {
|
|
93
|
+
try {
|
|
94
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
95
|
+
.filter((e) => e.isDirectory() &&
|
|
96
|
+
(existsSync(join(dir, e.name, "idp.json")) || existsSync(join(dir, e.name, "callout.json"))))
|
|
97
|
+
.map((e) => decodeURIComponent(e.name));
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return []; // no auth dir at all — nothing user-auth here
|
|
101
|
+
}
|
|
61
102
|
}
|
|
62
103
|
/** A `.cotal/` that a user actually created here — not the machine-home dir the cwd walk-up lands on
|
|
63
104
|
* from outside any project (which has no space, just the daemon's pid/onboard files). */
|
package/dist/mesh-target.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mesh-target.js","sourceRoot":"","sources":["../src/mesh-target.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"mesh-target.js","sourceRoot":"","sources":["../src/mesh-target.ts"],"names":[],"mappings":"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"}
|
package/dist/preflight.d.ts
CHANGED
|
@@ -13,14 +13,14 @@ import type { MeshTarget } from "./mesh-target.js";
|
|
|
13
13
|
/** The five distinct ways a preflight fails. Each also carries whether the target OWNS its registry
|
|
14
14
|
* entry (→ prune): `fromRegistry` means the server+mode came from a registry record (incl. a
|
|
15
15
|
* `local-recorded` project matched by root), so a definitive failure is a stale-entry signal. */
|
|
16
|
-
export type PreflightFailure = "unreachable" | "registry-creds-rejected" | "registry-open-now-auth" | "creds-rejected" | "open-wants-auth";
|
|
16
|
+
export type PreflightFailure = "unreachable" | "registry-creds-rejected" | "registry-open-now-auth" | "creds-rejected" | "open-wants-auth" | "stale-auth";
|
|
17
17
|
/** Pure decision tree — separated from I/O so the whole branch tree is unit-testable (it's the
|
|
18
18
|
* riskiest logic: a wrong branch prunes a LIVE registry entry). Only a registry-OWNED source
|
|
19
19
|
* (`registry`/`current`/`flag-space`/`local-recorded`) is ever pruned. A non-registry source —
|
|
20
20
|
* `flag-server`/`local-space`, a raw `--creds` connection, or `flag-space-override` (a `--space`
|
|
21
21
|
* whose `--server` overrides the recorded broker) — is NEVER pruned: the probed endpoint is
|
|
22
22
|
* operator-supplied, so a failure there is the user's to diagnose, not a stale-registry signal. */
|
|
23
|
-
export declare function classifyPreflightFailure(source: MeshTarget["source"], reason: "auth-required" | "unreachable", hasAuth: boolean): {
|
|
23
|
+
export declare function classifyPreflightFailure(source: MeshTarget["source"], reason: "auth-required" | "stale-auth" | "unreachable", hasAuth: boolean): {
|
|
24
24
|
prune: boolean;
|
|
25
25
|
kind: PreflightFailure;
|
|
26
26
|
};
|
package/dist/preflight.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;;;;;GAUG;AAEH;;kGAEkG;AAClG,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,yBAAyB,GACzB,wBAAwB,GACxB,gBAAgB,GAChB,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;;;;;GAUG;AAEH;;kGAEkG;AAClG,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,yBAAyB,GACzB,wBAAwB,GACxB,gBAAgB,GAChB,iBAAiB,GACjB,YAAY,CAAC;AAEjB;;;;;oGAKoG;AACpG,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,EAC5B,MAAM,EAAE,eAAe,GAAG,YAAY,GAAG,aAAa,EACtD,OAAO,EAAE,OAAO,GACf;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAkB5C;AAED;;;uFAGuF;AACvF,wBAAsB,eAAe,CACnC,MAAM,EAAE,UAAU,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAY/E;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD"}
|
package/dist/preflight.js
CHANGED
|
@@ -15,6 +15,12 @@ export function classifyPreflightFailure(source, reason, hasAuth) {
|
|
|
15
15
|
source === "local-recorded";
|
|
16
16
|
if (reason === "unreachable")
|
|
17
17
|
return { prune: fromRegistry, kind: "unreachable" };
|
|
18
|
+
// STALE-AUTH (D5 slice 6): the broker is UP and answered — only the presented CREDENTIAL is dead
|
|
19
|
+
// (bounded lifetime / credential death). NEVER a prune signal, whatever the source: deleting a
|
|
20
|
+
// live mesh's registry entry because a cred expired would misdirect the repair (the fix is
|
|
21
|
+
// `doctor auth`, not re-registration) — the same misdiagnosis class as the gate-1 prune bug.
|
|
22
|
+
if (reason === "stale-auth")
|
|
23
|
+
return { prune: false, kind: "stale-auth" };
|
|
18
24
|
if (fromRegistry && hasAuth)
|
|
19
25
|
return { prune: true, kind: "registry-creds-rejected" };
|
|
20
26
|
if (fromRegistry)
|
|
@@ -28,6 +34,11 @@ export function classifyPreflightFailure(source, reason, hasAuth) {
|
|
|
28
34
|
* exit. Probes with `probeCreds` when given (the caller's `--creds`/minted creds); otherwise mints
|
|
29
35
|
* a throwaway identity from the target's own trust material to test mere liveness. */
|
|
30
36
|
export async function preflightTarget(target, probeCreds) {
|
|
37
|
+
// A user-mode target has no probe credential by design (its auth is a per-connect bearer) — a
|
|
38
|
+
// credless probe would be DENIED by the callout and misclassified as a stale registry entry
|
|
39
|
+
// (prune:true). Callers own the user connect; reaching here with one is a caller bug, fail loud.
|
|
40
|
+
if (target.mode === "user")
|
|
41
|
+
throw new Error("preflightTarget: a user-mode target cannot be credless-probed - the caller owns the user connect (see preflightOrExit's user branch)");
|
|
31
42
|
const creds = probeCreds ?? (target.auth ? await mintCreds(target.auth, newIdentity(), "probe") : undefined);
|
|
32
43
|
const probe = await probeConnect(target.server, creds ? { creds } : {});
|
|
33
44
|
if (probe.ok)
|
package/dist/preflight.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AA0B5D;;;;;oGAKoG;AACpG,MAAM,UAAU,wBAAwB,CACtC,MAA4B,EAC5B,MAAsD,EACtD,OAAgB;IAEhB,mGAAmG;IACnG,iGAAiG;IACjG,MAAM,YAAY,GAChB,MAAM,KAAK,UAAU;QACrB,MAAM,KAAK,SAAS;QACpB,MAAM,KAAK,YAAY;QACvB,MAAM,KAAK,gBAAgB,CAAC;IAC9B,IAAI,MAAM,KAAK,aAAa;QAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IAClF,iGAAiG;IACjG,+FAA+F;IAC/F,2FAA2F;IAC3F,6FAA6F;IAC7F,IAAI,MAAM,KAAK,YAAY;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACzE,IAAI,YAAY,IAAI,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC;IACrF,IAAI,YAAY;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC;IACzE,IAAI,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;IAC7D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;AACnD,CAAC;AAED;;;uFAGuF;AACvF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAkB,EAClB,UAAmB;IAEnB,8FAA8F;IAC9F,4FAA4F;IAC5F,iGAAiG;IACjG,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM;QACxB,MAAM,IAAI,KAAK,CAAC,sIAAsI,CAAC,CAAC;IAC1J,MAAM,KAAK,GACT,UAAU,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACjG,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxE,IAAI,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAClC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,wBAAwB,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACpG,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACpC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,OAAO,CAAC,GAAG,CACf,UAAU,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC3B,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
|
package/dist/render.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export type WorkspaceError = {
|
|
|
21
21
|
pruned: boolean;
|
|
22
22
|
} | {
|
|
23
23
|
kind: "reachable";
|
|
24
|
-
reason: "auth-required" | "unreachable";
|
|
24
|
+
reason: "auth-required" | "stale-auth" | "unreachable";
|
|
25
25
|
server: string;
|
|
26
26
|
};
|
|
27
27
|
/** Render a workspace failure as the canonical one-line `cotal …` sentence. */
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACrF;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACrF;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,YAAY,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElG,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAS9D"}
|
package/dist/render.js
CHANGED
|
@@ -14,37 +14,46 @@ function renderTargetError(err) {
|
|
|
14
14
|
const d = err.details;
|
|
15
15
|
switch (err.code) {
|
|
16
16
|
case "no-meshes":
|
|
17
|
-
return "✗ no mesh running
|
|
17
|
+
return "✗ no mesh running - run `cotal up` in a project, or pass `--server`";
|
|
18
18
|
case "unknown-space":
|
|
19
|
-
return `✗ no mesh named "${d.requested}" is running
|
|
19
|
+
return `✗ no mesh named "${d.requested}" is running - see \`cotal meshes\``;
|
|
20
20
|
case "ambiguous-target":
|
|
21
|
-
return `✗ multiple meshes running
|
|
21
|
+
return `✗ multiple meshes running - ${(d.available ?? []).join(", ")}. Pick one with \`--space <name>\` or set a default with \`cotal use <name>\`.`;
|
|
22
22
|
case "default-occupied":
|
|
23
|
-
return `✗ another mesh ("${d.space}") is running at ${d.server}
|
|
23
|
+
return `✗ another mesh ("${d.space}") is running at ${d.server} - run \`cotal up\` here to start yours, or \`--space ${d.space}\` to join it`;
|
|
24
24
|
case "stale-auth-root":
|
|
25
|
-
return `✗ registry entry "${d.space}" points at ${d.root}, whose auth is now for "${d.found}"
|
|
25
|
+
return `✗ registry entry "${d.space}" points at ${d.root}, whose auth is now for "${d.found}" - stale entry removed; re-run \`cotal up\` or check \`cotal meshes\``;
|
|
26
|
+
case "user-auth-unrecorded":
|
|
27
|
+
// U11: without a TRUSTED local record of the space's IdP there is no actionable
|
|
28
|
+
// `cotal login --idp <?>` line to print — the honest recovery is re-registering the mesh
|
|
29
|
+
// where its user-auth state lives, and remote discovery is explicitly not supported yet.
|
|
30
|
+
return `✗ space "${d.space}" requires user auth, but no trusted IdP config for it is registered on this machine - re-run \`cotal up --user-auth\` in ${d.root ?? "its broker root"} to re-register it (user-auth spaces are configured where their broker runs; remote discovery is not supported yet)`;
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
33
|
/** "Is it live" failures on a registry-resolved target — the classified preflight sentence. */
|
|
29
34
|
function renderPreflightFailure(kind, t, pruned) {
|
|
30
35
|
switch (kind) {
|
|
31
36
|
case "unreachable":
|
|
32
|
-
return `✗ no mesh running at ${t.server}${pruned ? " (stale registry entry
|
|
37
|
+
return `✗ no mesh running at ${t.server}${pruned ? " (stale registry entry - removed)" : ""} - run \`cotal up\``;
|
|
33
38
|
case "registry-creds-rejected":
|
|
34
|
-
return `✗ mesh "${t.space}" at ${t.server} no longer matches its registry entry (credentials rejected
|
|
39
|
+
return `✗ mesh "${t.space}" at ${t.server} no longer matches its registry entry (credentials rejected - port reused?) - re-run \`cotal up\` from ${t.root}, or \`cotal meshes\` to see what's live`;
|
|
35
40
|
case "registry-open-now-auth":
|
|
36
|
-
return `✗ open mesh "${t.space}" at ${t.server} no longer matches its registry entry (broker now requires auth
|
|
41
|
+
return `✗ open mesh "${t.space}" at ${t.server} no longer matches its registry entry (broker now requires auth - port reused?) - re-run \`cotal up\` from ${t.root}, or \`cotal meshes\` to see what's live`;
|
|
37
42
|
case "creds-rejected":
|
|
38
|
-
return `✗ credentials for "${t.space}" were rejected at ${t.server}
|
|
43
|
+
return `✗ credentials for "${t.space}" were rejected at ${t.server} - a different mesh may be running there. Run \`cotal meshes\` to check, or \`cotal up\` here to start yours`;
|
|
39
44
|
case "open-wants-auth":
|
|
40
|
-
return `✗ broker at ${t.server} requires auth, but this mesh is open (no trust material)
|
|
45
|
+
return `✗ broker at ${t.server} requires auth, but this mesh is open (no trust material) - use \`--space <name>\` for an auth mesh, or run \`cotal up\` here without \`--open\``;
|
|
46
|
+
case "stale-auth":
|
|
47
|
+
return `✗ credentials for "${t.space}" have EXPIRED - this mesh enforces bounded credential lifetimes; run \`cotal doctor auth\` in ${t.root} for the diagnosis + exact repair (the mesh itself is up)`;
|
|
41
48
|
}
|
|
42
49
|
}
|
|
43
50
|
/** Plain reachability for a RAW (off-registry) probe — the `--creds` / `--server`+unregistered-`--space`
|
|
44
51
|
* escape hatch, which never touches the registry (no prune, no stale-entry wording). */
|
|
45
52
|
function renderReachable(reason, server) {
|
|
53
|
+
if (reason === "stale-auth")
|
|
54
|
+
return `✗ credential EXPIRED at ${server} - bounded lifetime reached (credential death); run \`cotal doctor auth\` where the mesh runs, or re-mint the credential`;
|
|
46
55
|
return reason === "auth-required"
|
|
47
|
-
? `✗ credentials rejected at ${server}
|
|
48
|
-
: `✗ can't reach a broker at ${server}
|
|
56
|
+
? `✗ credentials rejected at ${server} - check your creds, or the broker wants different auth`
|
|
57
|
+
: `✗ can't reach a broker at ${server} - is it running? (\`cotal up\`)`;
|
|
49
58
|
}
|
|
50
59
|
//# sourceMappingURL=render.js.map
|
package/dist/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAmBA,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,CAAiB;IACpD,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACpC,KAAK,WAAW;YACd,OAAO,sBAAsB,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAC/D,KAAK,WAAW;YACd,OAAO,eAAe,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,SAAS,iBAAiB,CAAC,GAAoB;IAC7C,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;IACtB,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,WAAW;YACd,OAAO,qEAAqE,CAAC;QAC/E,KAAK,eAAe;YAClB,OAAO,oBAAoB,CAAC,CAAC,SAAS,qCAAqC,CAAC;QAC9E,KAAK,kBAAkB;YACrB,OAAO,+BAA+B,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gFAAgF,CAAC;QACvJ,KAAK,kBAAkB;YACrB,OAAO,oBAAoB,CAAC,CAAC,KAAK,oBAAoB,CAAC,CAAC,MAAM,yDAAyD,CAAC,CAAC,KAAK,eAAe,CAAC;QAChJ,KAAK,iBAAiB;YACpB,OAAO,qBAAqB,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,IAAI,4BAA4B,CAAC,CAAC,KAAK,wEAAwE,CAAC;
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAmBA,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,CAAiB;IACpD,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACpC,KAAK,WAAW;YACd,OAAO,sBAAsB,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAC/D,KAAK,WAAW;YACd,OAAO,eAAe,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,SAAS,iBAAiB,CAAC,GAAoB;IAC7C,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;IACtB,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,WAAW;YACd,OAAO,qEAAqE,CAAC;QAC/E,KAAK,eAAe;YAClB,OAAO,oBAAoB,CAAC,CAAC,SAAS,qCAAqC,CAAC;QAC9E,KAAK,kBAAkB;YACrB,OAAO,+BAA+B,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gFAAgF,CAAC;QACvJ,KAAK,kBAAkB;YACrB,OAAO,oBAAoB,CAAC,CAAC,KAAK,oBAAoB,CAAC,CAAC,MAAM,yDAAyD,CAAC,CAAC,KAAK,eAAe,CAAC;QAChJ,KAAK,iBAAiB;YACpB,OAAO,qBAAqB,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,IAAI,4BAA4B,CAAC,CAAC,KAAK,wEAAwE,CAAC;QACtK,KAAK,sBAAsB;YACzB,gFAAgF;YAChF,yFAAyF;YACzF,yFAAyF;YACzF,OAAO,YAAY,CAAC,CAAC,KAAK,6HAA6H,CAAC,CAAC,IAAI,IAAI,iBAAiB,qHAAqH,CAAC;IAC5S,CAAC;AACH,CAAC;AAED,+FAA+F;AAC/F,SAAS,sBAAsB,CAAC,IAAsB,EAAE,CAAa,EAAE,MAAe;IACpF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa;YAChB,OAAO,wBAAwB,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,EAAE,qBAAqB,CAAC;QACnH,KAAK,yBAAyB;YAC5B,OAAO,WAAW,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,MAAM,0GAA0G,CAAC,CAAC,IAAI,0CAA0C,CAAC;QACtM,KAAK,wBAAwB;YAC3B,OAAO,gBAAgB,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,MAAM,8GAA8G,CAAC,CAAC,IAAI,0CAA0C,CAAC;QAC/M,KAAK,gBAAgB;YACnB,OAAO,sBAAsB,CAAC,CAAC,KAAK,sBAAsB,CAAC,CAAC,MAAM,8GAA8G,CAAC;QACnL,KAAK,iBAAiB;YACpB,OAAO,eAAe,CAAC,CAAC,MAAM,kJAAkJ,CAAC;QACnL,KAAK,YAAY;YACf,OAAO,sBAAsB,CAAC,CAAC,KAAK,kGAAkG,CAAC,CAAC,IAAI,2DAA2D,CAAC;IAC5M,CAAC;AACH,CAAC;AAED;yFACyF;AACzF,SAAS,eAAe,CAAC,MAAsD,EAAE,MAAc;IAC7F,IAAI,MAAM,KAAK,YAAY;QACzB,OAAO,2BAA2B,MAAM,0HAA0H,CAAC;IACrK,OAAO,MAAM,KAAK,eAAe;QAC/B,CAAC,CAAC,6BAA6B,MAAM,yDAAyD;QAC9F,CAAC,CAAC,6BAA6B,MAAM,kCAAkC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Profile } from "@cotal-ai/core";
|
|
2
|
+
/**
|
|
3
|
+
* D5 slice 5 class-2 standing renewal — the RENEWAL OWNER'S half, shared by the manager (the
|
|
4
|
+
* resident owner in every mesh mode) and `cotal doctor auth --fix` (the operator repair). The
|
|
5
|
+
* daemon's half is the explicit `reloadCreds` adoption op on the delivery-admin rail (plus the
|
|
6
|
+
* passive 75% source re-read as backstop). Machine-local file work lives here in the workspace
|
|
7
|
+
* layer: implementations never import each other.
|
|
8
|
+
*/
|
|
9
|
+
/** The seed-less daemon creds files a renewal owner re-signs. The $SYS files
|
|
10
|
+
* (membership-observer, connection-evictor) are deliberately ABSENT: they are rotation-renewed —
|
|
11
|
+
* no persisted seed can re-sign them, by design. */
|
|
12
|
+
export declare const REMINTABLE_DAEMON_CREDS: ReadonlyArray<{
|
|
13
|
+
file: string;
|
|
14
|
+
profile: Profile;
|
|
15
|
+
}>;
|
|
16
|
+
export interface RemintResult {
|
|
17
|
+
file: string;
|
|
18
|
+
/** true = re-signed; false = failed (see error); undefined ok with `skipped` = file absent. */
|
|
19
|
+
ok: boolean;
|
|
20
|
+
skipped?: "missing-file" | "no-auth";
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Re-sign the daemon creds files for their EXISTING nkeys (a renewal must never swap a daemon's
|
|
24
|
+
* identity — the daemon side pins it). Structured per-file results, never throws: a failed remint
|
|
25
|
+
* leaves the old cred running toward its loud expiry and the caller records/reports the failure. */
|
|
26
|
+
export declare function remintDaemonCreds(root: string): Promise<RemintResult[]>;
|
|
27
|
+
/** The renewal owner's audit record — what `cotal doctor auth` renders so "file re-signed" and
|
|
28
|
+
* "daemon adopted" are distinguishable states, per the D5 panel gate. One file, overwritten per
|
|
29
|
+
* pass: the CURRENT renewal state, not a log (history is the git/ops layer's job). */
|
|
30
|
+
export interface RenewalRecord {
|
|
31
|
+
/** ISO timestamp of the renewal pass. */
|
|
32
|
+
ts: string;
|
|
33
|
+
/** Who ran the pass (e.g. "manager", "doctor --fix"). */
|
|
34
|
+
owner: string;
|
|
35
|
+
results: RemintResult[];
|
|
36
|
+
/** The daemon's explicit reloadCreds adoption outcome; absent when nothing was re-signed. */
|
|
37
|
+
adoption?: {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
detail?: unknown;
|
|
40
|
+
error?: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export declare function renewalRecordPath(root: string): string;
|
|
44
|
+
export declare function writeRenewalRecord(root: string, record: RenewalRecord): void;
|
|
45
|
+
export declare function readRenewalRecord(root: string): RenewalRecord | undefined;
|
|
46
|
+
//# sourceMappingURL=renewal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renewal.d.ts","sourceRoot":"","sources":["../src/renewal.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,gBAAgB,CAAC;AAGxB;;;;;;GAMG;AAEH;;qDAEqD;AACrD,eAAO,MAAM,uBAAuB,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAGrF,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;qGAEqG;AACrG,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAmB7E;AAED;;uFAEuF;AACvF,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAE5E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAQzE"}
|
package/dist/renewal.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { identityFromCreds, mintCreds, writeSecretFile, } from "@cotal-ai/core";
|
|
4
|
+
import { authDir, loadSpaceAuth } from "./auth-paths.js";
|
|
5
|
+
/**
|
|
6
|
+
* D5 slice 5 class-2 standing renewal — the RENEWAL OWNER'S half, shared by the manager (the
|
|
7
|
+
* resident owner in every mesh mode) and `cotal doctor auth --fix` (the operator repair). The
|
|
8
|
+
* daemon's half is the explicit `reloadCreds` adoption op on the delivery-admin rail (plus the
|
|
9
|
+
* passive 75% source re-read as backstop). Machine-local file work lives here in the workspace
|
|
10
|
+
* layer: implementations never import each other.
|
|
11
|
+
*/
|
|
12
|
+
/** The seed-less daemon creds files a renewal owner re-signs. The $SYS files
|
|
13
|
+
* (membership-observer, connection-evictor) are deliberately ABSENT: they are rotation-renewed —
|
|
14
|
+
* no persisted seed can re-sign them, by design. */
|
|
15
|
+
export const REMINTABLE_DAEMON_CREDS = [
|
|
16
|
+
{ file: "delivery.creds", profile: "delivery" },
|
|
17
|
+
{ file: "membership-rw.creds", profile: "membership-rw" },
|
|
18
|
+
];
|
|
19
|
+
/** Re-sign the daemon creds files for their EXISTING nkeys (a renewal must never swap a daemon's
|
|
20
|
+
* identity — the daemon side pins it). Structured per-file results, never throws: a failed remint
|
|
21
|
+
* leaves the old cred running toward its loud expiry and the caller records/reports the failure. */
|
|
22
|
+
export async function remintDaemonCreds(root) {
|
|
23
|
+
const auth = loadSpaceAuth(authDir(root));
|
|
24
|
+
if (!auth)
|
|
25
|
+
return REMINTABLE_DAEMON_CREDS.map(({ file }) => ({ file, ok: false, skipped: "no-auth" }));
|
|
26
|
+
const results = [];
|
|
27
|
+
for (const { file, profile } of REMINTABLE_DAEMON_CREDS) {
|
|
28
|
+
const path = join(root, ".cotal", file);
|
|
29
|
+
if (!existsSync(path)) {
|
|
30
|
+
results.push({ file, ok: false, skipped: "missing-file" });
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const identity = identityFromCreds(readFileSync(path, "utf8"));
|
|
35
|
+
writeSecretFile(path, await mintCreds(auth, identity, profile));
|
|
36
|
+
results.push({ file, ok: true });
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
results.push({ file, ok: false, error: e.message });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
export function renewalRecordPath(root) {
|
|
45
|
+
return join(root, ".cotal", "renewal.json");
|
|
46
|
+
}
|
|
47
|
+
export function writeRenewalRecord(root, record) {
|
|
48
|
+
writeSecretFile(renewalRecordPath(root), JSON.stringify(record, null, 2));
|
|
49
|
+
}
|
|
50
|
+
export function readRenewalRecord(root) {
|
|
51
|
+
const p = renewalRecordPath(root);
|
|
52
|
+
if (!existsSync(p))
|
|
53
|
+
return undefined;
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined; // a corrupt record is rendered as "no renewal record", never a crash
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=renewal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renewal.js","sourceRoot":"","sources":["../src/renewal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,eAAe,GAEhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEzD;;;;;;GAMG;AAEH;;qDAEqD;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAAsD;IACxF,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,UAAU,EAAE;IAC/C,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,eAAe,EAAE;CAC1D,CAAC;AAUF;;qGAEqG;AACrG,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY;IAClD,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI;QAAE,OAAO,uBAAuB,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,SAAkB,EAAE,CAAC,CAAC,CAAC;IAChH,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,uBAAuB,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YAC3D,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,iBAAiB,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YAC/D,eAAe,CAAC,IAAI,EAAE,MAAM,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAeD,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,MAAqB;IACpE,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAkB,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,CAAC,qEAAqE;IACzF,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cotal-ai/workspace",
|
|
3
3
|
"description": "Cotal machine-local workstation layer: the ~/.cotal mesh registry, target resolution, preflight, on-disk auth-path I/O, and the command-copy renderer — operator concerns over a local checkout, kept separate from the wire protocol in @cotal-ai/core.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@cotal-ai/core": "0.
|
|
21
|
+
"@cotal-ai/core": "0.11.0"
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"dist"
|