@cotal-ai/core 0.10.1 → 0.11.1
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-file.d.ts +10 -1
- package/dist/agent-file.d.ts.map +1 -1
- package/dist/agent-file.js +65 -80
- package/dist/agent-file.js.map +1 -1
- package/dist/auth-provider.d.ts +207 -0
- package/dist/auth-provider.d.ts.map +1 -0
- package/dist/auth-provider.js +13 -0
- package/dist/auth-provider.js.map +1 -0
- package/dist/channels.d.ts +10 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +9 -27
- package/dist/channels.js.map +1 -1
- package/dist/command.d.ts +6 -1
- package/dist/command.d.ts.map +1 -1
- package/dist/command.js +5 -1
- package/dist/command.js.map +1 -1
- package/dist/connector-config.js +1 -1
- package/dist/connector.d.ts +16 -0
- package/dist/connector.d.ts.map +1 -1
- package/dist/endpoint.d.ts +148 -17
- package/dist/endpoint.d.ts.map +1 -1
- package/dist/endpoint.js +470 -97
- package/dist/endpoint.js.map +1 -1
- package/dist/evict.d.ts +87 -0
- package/dist/evict.d.ts.map +1 -0
- package/dist/evict.js +231 -0
- package/dist/evict.js.map +1 -0
- package/dist/identity.d.ts +15 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +26 -2
- package/dist/identity.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/launch.d.ts +6 -0
- package/dist/launch.d.ts.map +1 -1
- package/dist/members.d.ts.map +1 -1
- package/dist/members.js +5 -2
- package/dist/members.js.map +1 -1
- package/dist/membership-feed.d.ts +17 -3
- package/dist/membership-feed.d.ts.map +1 -1
- package/dist/membership-feed.js +41 -13
- package/dist/membership-feed.js.map +1 -1
- package/dist/provision.d.ts +99 -14
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +267 -128
- package/dist/provision.js.map +1 -1
- package/dist/resolve.js +1 -1
- package/dist/secret-fs.d.ts +9 -0
- package/dist/secret-fs.d.ts.map +1 -1
- package/dist/secret-fs.js +26 -2
- package/dist/secret-fs.js.map +1 -1
- package/dist/streams.d.ts +33 -7
- package/dist/streams.d.ts.map +1 -1
- package/dist/streams.js +53 -30
- package/dist/streams.js.map +1 -1
- package/dist/subjects.d.ts +267 -75
- package/dist/subjects.d.ts.map +1 -1
- package/dist/subjects.js +401 -110
- package/dist/subjects.js.map +1 -1
- package/dist/types.d.ts +13 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
package/dist/agent-file.d.ts
CHANGED
|
@@ -28,11 +28,20 @@ export interface AgentDef {
|
|
|
28
28
|
model?: string;
|
|
29
29
|
/** Connector-defined model variant handed to the launcher (e.g. OpenCode reasoning effort). */
|
|
30
30
|
variant?: string;
|
|
31
|
+
/** Opaque, connector-specific launch options — an arbitrary key→value map that core never
|
|
32
|
+
* interprets. Connectors forward well-shaped keys raw into their host form (`claude` flags,
|
|
33
|
+
* OpenCode config); a connector with no option surface fails loud. `--opt k=v` on the CLI, a
|
|
34
|
+
* manifest `launchOptions:`, or a nested `launchOptions:` block here all feed the same bag. */
|
|
35
|
+
launchOptions?: Record<string, unknown>;
|
|
31
36
|
/** Capabilities this agent may exercise on the control plane (auth mode → minted into the
|
|
32
37
|
* cred's publish allow-list). Today `spawn` is the only one: it grants publish to the
|
|
33
38
|
* privileged control subject (start/purge/definePersona/named stop). Default-deny when
|
|
34
39
|
* absent — nats-server, not a handler, is the boundary. Granting authority is operator-level
|
|
35
|
-
* (`definePersona` is itself privileged), so no peer can self-grant via its own agent file.
|
|
40
|
+
* (`definePersona` is itself privileged), so no peer can self-grant via its own agent file.
|
|
41
|
+
* NOTE: because launchOptions is a raw passthrough, `spawn` is HOST-LAUNCH AUTHORITY — its holder
|
|
42
|
+
* can drive the connector's full launch surface on the manager host (Claude `--mcp-config` /
|
|
43
|
+
* `--add-dir` / permission flags, OpenCode agent-config keys). Grant it as host-launch authority,
|
|
44
|
+
* not as a narrow "add a teammate" permission. */
|
|
36
45
|
capabilities?: string[];
|
|
37
46
|
/** Authenticated id of the agent that first defined this persona via `definePersona` (P6). A
|
|
38
47
|
* POLICY field, not content: the privileged tier may *redefine* an existing file only if its
|
package/dist/agent-file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-file.d.ts","sourceRoot":"","sources":["../src/agent-file.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-file.d.ts","sourceRoot":"","sources":["../src/agent-file.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;6GACyG;IACzG,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;yCAGqC;IACrC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;qFAEiF;IACjF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;oFAEgF;IAChF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;0EACsE;IACtE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;oGAGgG;IAChG,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC;;;;;;;;uDAQmD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;oGAIgG;IAChG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;qDACiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAmBD,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAmHpD;AAED;;;8CAG8C;AAC9C,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CA0B/D;AAED;;mDAEmD;AACnD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED;;;kGAGkG;AAClG,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,CAMpF"}
|
package/dist/agent-file.js
CHANGED
|
@@ -25,42 +25,26 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
27
27
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
28
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
28
29
|
import { assertValidName } from "./resolve.js";
|
|
29
30
|
import { assertValidChannel, channelInAllow, isConcreteChannel } from "./subjects.js";
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
for (const raw of src.split("\n")) {
|
|
42
|
-
const line = raw.trim();
|
|
43
|
-
if (!line || line.startsWith("#"))
|
|
44
|
-
continue;
|
|
45
|
-
const colon = line.indexOf(":");
|
|
46
|
-
if (colon < 1)
|
|
47
|
-
throw new Error(`agent file: unparseable frontmatter line "${raw}"`);
|
|
48
|
-
const key = line.slice(0, colon).trim();
|
|
49
|
-
const val = line.slice(colon + 1).trim();
|
|
50
|
-
if (val.startsWith("[")) {
|
|
51
|
-
if (!val.endsWith("]"))
|
|
52
|
-
throw new Error(`agent file: unterminated list for "${key}"`);
|
|
53
|
-
out[key] = val
|
|
54
|
-
.slice(1, -1)
|
|
55
|
-
.split(",")
|
|
56
|
-
.map((s) => unquote(s.trim()))
|
|
57
|
-
.filter(Boolean);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
out[key] = unquote(val);
|
|
61
|
-
}
|
|
31
|
+
/** Parse the frontmatter block as YAML (the `yaml` library — spec-compliant quoting/escaping and
|
|
32
|
+
* safe scalar typing, so a value with a `:`/`#`/quote can't be misread). Must be a mapping; a
|
|
33
|
+
* sequence, scalar, or malformed block fails loud. Values keep their YAML types (string, number,
|
|
34
|
+
* boolean, nested map/list); {@link loadAgentFile} coerces the modelled scalar fields. */
|
|
35
|
+
function parseFrontmatter(src, path) {
|
|
36
|
+
let doc;
|
|
37
|
+
try {
|
|
38
|
+
doc = parseYaml(src);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
throw new Error(`agent file ${path}: invalid YAML frontmatter — ${e.message}`);
|
|
62
42
|
}
|
|
63
|
-
|
|
43
|
+
if (doc === null || doc === undefined)
|
|
44
|
+
return {};
|
|
45
|
+
if (typeof doc !== "object" || Array.isArray(doc))
|
|
46
|
+
throw new Error(`agent file ${path}: frontmatter must be a YAML mapping (key: value pairs)`);
|
|
47
|
+
return doc;
|
|
64
48
|
}
|
|
65
49
|
/** Load and parse an agent definition file (Markdown + `---` frontmatter). */
|
|
66
50
|
export function loadAgentFile(path) {
|
|
@@ -68,19 +52,25 @@ export function loadAgentFile(path) {
|
|
|
68
52
|
const m = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(src);
|
|
69
53
|
if (!m)
|
|
70
54
|
throw new Error(`agent file ${path}: missing "---" frontmatter block`);
|
|
71
|
-
const fm = parseFrontmatter(m[1]);
|
|
55
|
+
const fm = parseFrontmatter(m[1], path);
|
|
72
56
|
const persona = m[2].trim();
|
|
73
57
|
const str = (k) => {
|
|
74
58
|
const v = fm[k];
|
|
75
|
-
if (
|
|
59
|
+
if (v === undefined || v === null)
|
|
60
|
+
return undefined;
|
|
61
|
+
if (typeof v === "object")
|
|
76
62
|
throw new Error(`agent file ${path}: "${k}" must be a scalar`);
|
|
77
|
-
return v;
|
|
63
|
+
return String(v);
|
|
78
64
|
};
|
|
79
65
|
const list = (k) => {
|
|
80
66
|
const v = fm[k];
|
|
81
|
-
if (v === undefined)
|
|
67
|
+
if (v === undefined || v === null)
|
|
82
68
|
return undefined;
|
|
83
|
-
return Array.isArray(v) ? v : [v]
|
|
69
|
+
return (Array.isArray(v) ? v : [v]).map((x) => {
|
|
70
|
+
if (x === null || typeof x === "object")
|
|
71
|
+
throw new Error(`agent file ${path}: "${k}" list items must be scalars`);
|
|
72
|
+
return String(x);
|
|
73
|
+
});
|
|
84
74
|
};
|
|
85
75
|
const name = str("name");
|
|
86
76
|
if (!name)
|
|
@@ -94,7 +84,7 @@ export function loadAgentFile(path) {
|
|
|
94
84
|
// an unmigrated file would otherwise lose its read/post scope without warning (no silent degrade).
|
|
95
85
|
for (const old of ["channels", "publish"])
|
|
96
86
|
if (old in fm)
|
|
97
|
-
throw new Error(`agent file ${path}: "${old}" was renamed
|
|
87
|
+
throw new Error(`agent file ${path}: "${old}" was renamed - use "subscribe"/"allowSubscribe" (read) and "allowPublish" (post)`);
|
|
98
88
|
const subscribe = list("subscribe");
|
|
99
89
|
const allowSubscribe = list("allowSubscribe");
|
|
100
90
|
const allowPublish = list("allowPublish");
|
|
@@ -121,7 +111,7 @@ export function loadAgentFile(path) {
|
|
|
121
111
|
// channel can't be both at once. Fail loud (no silent no-op), matching the checks above.
|
|
122
112
|
const both = (quiet ?? []).filter((c) => (muted ?? []).includes(c));
|
|
123
113
|
if (both.length)
|
|
124
|
-
throw new Error(`agent file ${path}: channel(s) [${both.join(", ")}] are in both quiet and muted
|
|
114
|
+
throw new Error(`agent file ${path}: channel(s) [${both.join(", ")}] are in both quiet and muted - pick one`);
|
|
125
115
|
for (const [field, chans] of [["quiet", quiet], ["muted", muted]])
|
|
126
116
|
for (const ch of chans ?? []) {
|
|
127
117
|
try {
|
|
@@ -135,13 +125,22 @@ export function loadAgentFile(path) {
|
|
|
135
125
|
if (!channelInAllow(effAllow, ch))
|
|
136
126
|
throw new Error(`agent file ${path}: ${field} channel "${ch}" is not within your read ACL / allowSubscribe [${effAllow.join(", ")}]`);
|
|
137
127
|
}
|
|
128
|
+
// Opaque connector-specific launch options — a mapping core never interprets (each connector
|
|
129
|
+
// reads its own keys). A scalar/sequence here is a config error (it must be `key: value` pairs).
|
|
130
|
+
const launchOptionsRaw = fm["launchOptions"];
|
|
131
|
+
let launchOptions;
|
|
132
|
+
if (launchOptionsRaw !== undefined && launchOptionsRaw !== null) {
|
|
133
|
+
if (typeof launchOptionsRaw !== "object" || Array.isArray(launchOptionsRaw))
|
|
134
|
+
throw new Error(`agent file ${path}: "launchOptions" must be a mapping of key: value pairs`);
|
|
135
|
+
launchOptions = launchOptionsRaw;
|
|
136
|
+
}
|
|
138
137
|
// Sweep every scalar frontmatter key we don't model into meta, verbatim — connector launcher
|
|
139
138
|
// hints ride here so core stays ignorant of surface-specific keys.
|
|
140
|
-
const known = new Set(["name", "role", "kind", "description", "tags", "subscribe", "allowSubscribe", "allowPublish", "quiet", "muted", "model", "variant", "capabilities", "owner"]);
|
|
139
|
+
const known = new Set(["name", "role", "kind", "description", "tags", "subscribe", "allowSubscribe", "allowPublish", "quiet", "muted", "model", "variant", "launchOptions", "capabilities", "owner"]);
|
|
141
140
|
const meta = {};
|
|
142
141
|
for (const [k, v] of Object.entries(fm))
|
|
143
|
-
if (!known.has(k) && typeof v
|
|
144
|
-
meta[k] = v;
|
|
142
|
+
if (!known.has(k) && v !== null && typeof v !== "object")
|
|
143
|
+
meta[k] = String(v);
|
|
145
144
|
return {
|
|
146
145
|
name,
|
|
147
146
|
role: str("role"),
|
|
@@ -155,6 +154,7 @@ export function loadAgentFile(path) {
|
|
|
155
154
|
muted,
|
|
156
155
|
model: str("model"),
|
|
157
156
|
variant: str("variant"),
|
|
157
|
+
launchOptions,
|
|
158
158
|
capabilities: list("capabilities"),
|
|
159
159
|
owner: str("owner"),
|
|
160
160
|
meta: Object.keys(meta).length ? meta : undefined,
|
|
@@ -169,60 +169,45 @@ export function saveAgentFile(path, def) {
|
|
|
169
169
|
if (!def.name)
|
|
170
170
|
throw new Error('saveAgentFile: "name" is required');
|
|
171
171
|
assertValidName(def.name);
|
|
172
|
-
|
|
172
|
+
// Build the frontmatter mapping in read order, then serialize with the `yaml` library — it owns
|
|
173
|
+
// all quoting/escaping (a value with a `:`/`#`/`[`/quote round-trips safely, which the old
|
|
174
|
+
// hand-rolled writer had to special-case). `lineWidth: 0` keeps scalars on one line (no folding).
|
|
175
|
+
const fm = { name: def.name };
|
|
173
176
|
if (def.role)
|
|
174
|
-
|
|
177
|
+
fm.role = def.role;
|
|
175
178
|
if (def.kind)
|
|
176
|
-
|
|
179
|
+
fm.kind = def.kind;
|
|
177
180
|
if (def.description)
|
|
178
|
-
|
|
181
|
+
fm.description = def.description;
|
|
179
182
|
if (def.tags?.length)
|
|
180
|
-
|
|
183
|
+
fm.tags = def.tags;
|
|
181
184
|
if (def.subscribe?.length)
|
|
182
|
-
|
|
185
|
+
fm.subscribe = def.subscribe;
|
|
183
186
|
if (def.allowSubscribe?.length)
|
|
184
|
-
|
|
187
|
+
fm.allowSubscribe = def.allowSubscribe;
|
|
185
188
|
if (def.allowPublish?.length)
|
|
186
|
-
|
|
189
|
+
fm.allowPublish = def.allowPublish;
|
|
187
190
|
if (def.quiet?.length)
|
|
188
|
-
|
|
191
|
+
fm.quiet = def.quiet;
|
|
189
192
|
if (def.muted?.length)
|
|
190
|
-
|
|
193
|
+
fm.muted = def.muted;
|
|
191
194
|
if (def.model)
|
|
192
|
-
|
|
195
|
+
fm.model = def.model;
|
|
193
196
|
if (def.variant)
|
|
194
|
-
|
|
197
|
+
fm.variant = def.variant;
|
|
198
|
+
if (def.launchOptions && Object.keys(def.launchOptions).length)
|
|
199
|
+
fm.launchOptions = def.launchOptions;
|
|
195
200
|
if (def.capabilities?.length)
|
|
196
|
-
|
|
201
|
+
fm.capabilities = def.capabilities;
|
|
197
202
|
if (def.owner)
|
|
198
|
-
|
|
203
|
+
fm.owner = def.owner;
|
|
199
204
|
if (def.meta)
|
|
200
205
|
for (const [k, v] of Object.entries(def.meta))
|
|
201
|
-
|
|
202
|
-
|
|
206
|
+
fm[k] = v;
|
|
207
|
+
const frontmatter = stringifyYaml(fm, { lineWidth: 0 }).trimEnd();
|
|
203
208
|
const body = def.persona ? `${def.persona.trim()}\n` : "";
|
|
204
209
|
mkdirSync(dirname(path), { recursive: true });
|
|
205
|
-
writeFileSync(path,
|
|
206
|
-
}
|
|
207
|
-
/** Render a frontmatter scalar so {@link loadAgentFile} reads it back unchanged. Quotes values
|
|
208
|
-
* the parser would otherwise misread (a leading `[`, a `,`/`:`/`#`, edge whitespace, or empty);
|
|
209
|
-
* throws on values the line-based format can't represent (a newline, or both quote styles). */
|
|
210
|
-
function fmScalar(value) {
|
|
211
|
-
if (/[\r\n]/.test(value))
|
|
212
|
-
throw new Error(`saveAgentFile: value cannot contain a newline: ${JSON.stringify(value)}`);
|
|
213
|
-
if (value !== "" && value === value.trim() && !/^[[]/.test(value) && !/[,:#"']/.test(value))
|
|
214
|
-
return value;
|
|
215
|
-
if (!value.includes('"'))
|
|
216
|
-
return `"${value}"`;
|
|
217
|
-
if (!value.includes("'"))
|
|
218
|
-
return `'${value}'`;
|
|
219
|
-
throw new Error(`saveAgentFile: value cannot contain both quote styles: ${JSON.stringify(value)}`);
|
|
220
|
-
}
|
|
221
|
-
/** A list item additionally cannot hold a comma — the parser splits on `,` before unquoting. */
|
|
222
|
-
function fmItem(value) {
|
|
223
|
-
if (value.includes(","))
|
|
224
|
-
throw new Error(`saveAgentFile: list item cannot contain a comma: ${JSON.stringify(value)}`);
|
|
225
|
-
return fmScalar(value);
|
|
210
|
+
writeFileSync(path, `---\n${frontmatter}\n---\n\n${body}`);
|
|
226
211
|
}
|
|
227
212
|
/** Resolve a name-or-path to an agent file. A path (absolute, contains a slash — `/` or, on
|
|
228
213
|
* Windows, `\` — or ends in `.md`) is used as given; a bare name maps to the directory
|
package/dist/agent-file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-file.js","sourceRoot":"","sources":["../src/agent-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-file.js","sourceRoot":"","sources":["../src/agent-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { type Extension } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* The one extension kind an identity/auth implementation registers so a composition root can turn
|
|
4
|
+
* on USER-MODE auth (the human-owner identity plane over per-agent NATS identity) WITHOUT importing
|
|
5
|
+
* that implementation. `@cotal-ai/auth` self-registers one on import; the `cotal` binary pulls the
|
|
6
|
+
* package in, and the CLI resolves it generically (`registry.all<AuthProvider>("auth-provider")`).
|
|
7
|
+
*
|
|
8
|
+
* Guarded core: this seam is IdP-agnostic and knows nothing about callouts, bearers, ledgers, or
|
|
9
|
+
* any concrete IdP. It exchanges a NARROW provisioning input (exactly the signing material the
|
|
10
|
+
* provider's function requires — never the whole space trust bundle) for the operator-signed
|
|
11
|
+
* accounts the broker config preloads, plus opaque client metadata and a service handle. All
|
|
12
|
+
* auth-specific substance stays behind these types.
|
|
13
|
+
*
|
|
14
|
+
* No provider registered ⇒ user-mode auth is unavailable and requesting it MUST fail loud (no
|
|
15
|
+
* static fallback) — a library root that never imports the auth package simply cannot serve a
|
|
16
|
+
* user-auth space.
|
|
17
|
+
*/
|
|
18
|
+
export interface AuthProvider extends Extension {
|
|
19
|
+
readonly kind: "auth-provider";
|
|
20
|
+
/**
|
|
21
|
+
* Ensure this space's user-auth material exists under `input.dir` (generated + persisted on the
|
|
22
|
+
* first call, reused verbatim after — account identities and signing keys MUST be stable across
|
|
23
|
+
* restarts or previously-issued credentials break) and describe what the composition root must
|
|
24
|
+
* wire up. Idempotent. This call may hold the provisioning seeds BRIEFLY; the long-lived service
|
|
25
|
+
* process must load only provider-owned projected files written here, never the space's full
|
|
26
|
+
* trust bundle.
|
|
27
|
+
*/
|
|
28
|
+
prepareServer(input: AuthPrepareInput): Promise<AuthPrepared>;
|
|
29
|
+
/**
|
|
30
|
+
* CLIENT side: produce the connect material for a user-mode space from THIS machine's session
|
|
31
|
+
* state (the login cache + the provider's space-scoped state under `dir`). `actor` is the
|
|
32
|
+
* ledger-granted agent-instance the caller connects as. Returns what {@link EndpointOptions}'
|
|
33
|
+
* user mode consumes (`bearer` + `sentinelCreds`). MUST fail loud with the EXACT operator
|
|
34
|
+
* action when anything is missing — not logged in (`cotal login --idp …`), the auth service
|
|
35
|
+
* down (how to restart it), the actor ungranted (how to grant) — and NEVER falls back to any
|
|
36
|
+
* other auth mode.
|
|
37
|
+
*
|
|
38
|
+
* `view` requests an ELEVATED per-connection profile (opaque to core; the provider validates it
|
|
39
|
+
* against its closed view enum and the fresh ledger grant) — the god-view/purge/registry-write/
|
|
40
|
+
* deploy connections the operator surfaces (`web`, `console`, `history clear`, `channels`,
|
|
41
|
+
* `spawn -f`) ride. An under-scoped or unknown view MUST fail loud with the exact re-grant.
|
|
42
|
+
*/
|
|
43
|
+
userCredentials(opts: {
|
|
44
|
+
dir: string;
|
|
45
|
+
space: string;
|
|
46
|
+
actor: string;
|
|
47
|
+
view?: string;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
bearer: string;
|
|
50
|
+
sentinelCreds: string;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* The derived owner token (`u_…`) of THIS machine's cached login for the given space — resolved
|
|
54
|
+
* offline from the login session + the space's local user-auth material (no IdP round trip).
|
|
55
|
+
* The spawn paths use it to answer "whose agents are these": a foreground/manifest spawn runs
|
|
56
|
+
* the agents under the OPERATOR's owner. MUST fail loud when not logged in (naming the exact
|
|
57
|
+
* `cotal login --idp …` line) or when the space has no user-auth material under `dir`.
|
|
58
|
+
*/
|
|
59
|
+
ownerForLogin(opts: {
|
|
60
|
+
dir: string;
|
|
61
|
+
space: string;
|
|
62
|
+
}): Promise<string>;
|
|
63
|
+
/**
|
|
64
|
+
* Read-only OFFLINE introspection for status surfaces (`cotal status`): this machine's cached
|
|
65
|
+
* login for the space and — where the space's ledger is locally readable — whether that login's
|
|
66
|
+
* `actor` is granted. Never network-bound and never a mint; "not signed in" is a REPORTED state
|
|
67
|
+
* here, not a thrown one. Throws only when the space has no user-auth material under `dir`
|
|
68
|
+
* (there is nothing to report status about).
|
|
69
|
+
*/
|
|
70
|
+
userStatus(opts: {
|
|
71
|
+
dir: string;
|
|
72
|
+
space: string;
|
|
73
|
+
actor: string;
|
|
74
|
+
}): Promise<UserAuthStatus>;
|
|
75
|
+
/**
|
|
76
|
+
* SERVER side, agent lifecycle: author an agent grant for `(owner, actor)` in this space's
|
|
77
|
+
* ledger — the spawn path's half of "actors are server-ledger-authorized, never taken from
|
|
78
|
+
* connect payloads". Returns the ONE-TIME plaintext agent secret (persisted only as a hash;
|
|
79
|
+
* the caller delivers it to the agent process via a 0600 file and never sees it again) plus
|
|
80
|
+
* the sentinel creds the agent presents alongside its bearers. Upsert — re-granting an actor
|
|
81
|
+
* rotates its secret. MUST fail loud when the space has no user-auth material under `dir`.
|
|
82
|
+
*/
|
|
83
|
+
grantAgent(opts: {
|
|
84
|
+
dir: string;
|
|
85
|
+
space: string;
|
|
86
|
+
owner: string;
|
|
87
|
+
actor: string;
|
|
88
|
+
scope: string[];
|
|
89
|
+
allowSubscribe: string[];
|
|
90
|
+
allowPublish: string[];
|
|
91
|
+
role?: string;
|
|
92
|
+
/** The spawning principal (`<owner>.<actor>` dot-form) — the grant's audit link. */
|
|
93
|
+
parent?: string;
|
|
94
|
+
label?: string;
|
|
95
|
+
}): Promise<{
|
|
96
|
+
actorToken: string;
|
|
97
|
+
sentinelCreds: string;
|
|
98
|
+
}>;
|
|
99
|
+
/** Revoke an agent grant. False when there was nothing to revoke. New exchanges and new
|
|
100
|
+
* connects die immediately (both boundaries read the ledger fresh); an already-live
|
|
101
|
+
* connection dies at its bearer-bound JWT expiry (live eviction is a separate lever). */
|
|
102
|
+
revokeAgent(opts: {
|
|
103
|
+
dir: string;
|
|
104
|
+
owner: string;
|
|
105
|
+
actor: string;
|
|
106
|
+
}): Promise<boolean>;
|
|
107
|
+
/**
|
|
108
|
+
* Read-only FRESH capability-scope read for one granted principal — `undefined` when the
|
|
109
|
+
* principal holds no grant (for an authorization read, unknowable is "no grant": fail-closed).
|
|
110
|
+
* Never a mint, never a write. The manager's named-target control authorization (owner-domain
|
|
111
|
+
* stop/attach) consults it for its else-branch — "does the caller hold `admin`?" — reading
|
|
112
|
+
* fresh so a scope edit bites the caller's next control op with no restart or reconnect.
|
|
113
|
+
*/
|
|
114
|
+
actorScope(opts: {
|
|
115
|
+
dir: string;
|
|
116
|
+
owner: string;
|
|
117
|
+
actor: string;
|
|
118
|
+
}): Promise<string[] | undefined>;
|
|
119
|
+
/**
|
|
120
|
+
* Registry name of the provider's self-registered {@link Command} that prints ONE fresh agent
|
|
121
|
+
* bearer to stdout and exits (flags: `--dir <state-dir> --space <space> --owner <o> --actor <a>
|
|
122
|
+
* --token-file <path>`). A long-lived agent endpoint execs it per refresh — the exchange
|
|
123
|
+
* protocol, discovery, and secret handling stay entirely behind the provider; the agent-side
|
|
124
|
+
* runtime only runs an argv and reads a line. */
|
|
125
|
+
readonly agentBearerCommand: string;
|
|
126
|
+
}
|
|
127
|
+
/** The ONE registered auth provider, or a thrown sentence naming the fix. More than one registered
|
|
128
|
+
* is ambiguous and refuses just as loudly — there is no pick-the-first fallback. Lives in core so
|
|
129
|
+
* every surface that resolves the provider generically (CLI, manager) shares one resolution. */
|
|
130
|
+
export declare function resolveAuthProvider(): AuthProvider;
|
|
131
|
+
/** What {@link AuthProvider.userStatus} reports. Fields are absent when locally unknowable —
|
|
132
|
+
* absence is honest ("can't tell from here"), never a guess. */
|
|
133
|
+
export interface UserAuthStatus {
|
|
134
|
+
/** The space's pinned IdP base URL (always known — it is part of the user-auth material). */
|
|
135
|
+
idpUrl: string;
|
|
136
|
+
/** This machine's cached login for that IdP; absent = not signed in. */
|
|
137
|
+
login?: {
|
|
138
|
+
sub: string;
|
|
139
|
+
expiresAt: number;
|
|
140
|
+
};
|
|
141
|
+
/** The login's derived owner token (`u_…`) for this space. */
|
|
142
|
+
owner?: string;
|
|
143
|
+
/** The (owner, actor) interactive ledger row: its lists when granted, `"not-granted"` when the
|
|
144
|
+
* locally-readable ledger has no row. Absent when the ledger is not on this machine. */
|
|
145
|
+
grant?: {
|
|
146
|
+
scope: string[];
|
|
147
|
+
allowSubscribe: string[];
|
|
148
|
+
allowPublish: string[];
|
|
149
|
+
role?: string;
|
|
150
|
+
label?: string;
|
|
151
|
+
} | "not-granted";
|
|
152
|
+
}
|
|
153
|
+
/** The provisioning input — deliberately NARROW (a capability boundary, not a convenience): the
|
|
154
|
+
* operator seed signs the provider's dedicated account(s) once; the data-account signing seed is
|
|
155
|
+
* projected into the service's own key file because minting scoped data-account users at connect
|
|
156
|
+
* time IS the service's function. Nothing else of the space bundle crosses this seam. */
|
|
157
|
+
export interface AuthPrepareInput {
|
|
158
|
+
space: string;
|
|
159
|
+
/** The space operator's signing seed — used once per fresh space, to sign the provider's
|
|
160
|
+
* dedicated account(s) into the operator's trust chain. */
|
|
161
|
+
operatorSeed: string;
|
|
162
|
+
/** The data account users are bound into: its public key + the signing seed that mints its
|
|
163
|
+
* users (projected to the service's key file; the ACCOUNT seed itself never crosses). */
|
|
164
|
+
account: {
|
|
165
|
+
pub: string;
|
|
166
|
+
signingSeed: string;
|
|
167
|
+
};
|
|
168
|
+
/** The provider's OWN state dir. The caller keys it — today `<root>/.cotal/auth/<space>`; a
|
|
169
|
+
* future (broker, space) key is a caller change, never an on-disk format break. */
|
|
170
|
+
dir: string;
|
|
171
|
+
/** The operator's external identity-provider base URL (`up --user-auth --idp <url>`), OPAQUE to
|
|
172
|
+
* core — the provider pins/persists it (first call requires one; a later call must match the
|
|
173
|
+
* persisted pin or omit it; re-pointing an IdP is a migration, never a flag flip). */
|
|
174
|
+
idpUrl?: string;
|
|
175
|
+
}
|
|
176
|
+
/** What `prepareServer` hands back to the composition root. */
|
|
177
|
+
export interface AuthPrepared {
|
|
178
|
+
/** Operator-signed accounts the broker config must preload in its resolver (e.g. a dedicated
|
|
179
|
+
* callout account, which must never share the data account). */
|
|
180
|
+
extraAccounts: Array<{
|
|
181
|
+
pub: string;
|
|
182
|
+
jwt: string;
|
|
183
|
+
}>;
|
|
184
|
+
/** NON-SECRET client-facing metadata (trust pins, provider id) for the workstation layer's mesh
|
|
185
|
+
* registry, so connects from other directories can print exact recovery actions. Opaque to
|
|
186
|
+
* core — the workspace layer owns the concrete shape. */
|
|
187
|
+
publicAuth: Record<string, unknown>;
|
|
188
|
+
/** The long-lived auth service this space needs running alongside its broker. */
|
|
189
|
+
service: AuthServiceSpec;
|
|
190
|
+
}
|
|
191
|
+
/** The provider's daemon, by contract rather than convention: which registered {@link Command} to
|
|
192
|
+
* spawn (the CLI re-execs `cotal <command> --space … --server …` detached, pid/log space-scoped),
|
|
193
|
+
* and how to know it is actually SERVING — so `up` never records a usable user mesh on a
|
|
194
|
+
* half-started service, and never invents ad-hoc readiness sleeps. */
|
|
195
|
+
export interface AuthServiceSpec {
|
|
196
|
+
/** Registry name of the self-registered daemon command (e.g. `"auth-service"`). Resolved through
|
|
197
|
+
* the command registry and exec'd as argv — never shell-interpolated. */
|
|
198
|
+
command: string;
|
|
199
|
+
/** Wait until the running service is READY (every plane bound — e.g. broker subscription AND
|
|
200
|
+
* local endpoints). Resolves with the service's runtime, non-secret endpoint metadata for the
|
|
201
|
+
* mesh registry; THROWS (with the reason) on timeout — the caller surfaces it, loudly. */
|
|
202
|
+
ready(opts: {
|
|
203
|
+
dir: string;
|
|
204
|
+
timeoutMs?: number;
|
|
205
|
+
}): Promise<Record<string, unknown>>;
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=auth-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { registry } from "./registry.js";
|
|
2
|
+
/** The ONE registered auth provider, or a thrown sentence naming the fix. More than one registered
|
|
3
|
+
* is ambiguous and refuses just as loudly — there is no pick-the-first fallback. Lives in core so
|
|
4
|
+
* every surface that resolves the provider generically (CLI, manager) shares one resolution. */
|
|
5
|
+
export function resolveAuthProvider() {
|
|
6
|
+
const providers = registry.all("auth-provider");
|
|
7
|
+
if (providers.length === 0)
|
|
8
|
+
throw new Error("no auth provider is registered in this build - user auth needs one (the `cotal` binary registers @cotal-ai/auth; a custom composition root must import an auth package)");
|
|
9
|
+
if (providers.length > 1)
|
|
10
|
+
throw new Error(`multiple auth providers registered (${providers.map((p) => p.name).join(", ")}) - cannot choose between them`);
|
|
11
|
+
return providers[0];
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=auth-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-provider.js","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,eAAe,CAAC;AAsGzD;;iGAEiG;AACjG,MAAM,UAAU,mBAAmB;IACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAe,eAAe,CAAC,CAAC;IAC9D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,yKAAyK,CAC1K,CAAC;IACJ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,uCAAuC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAClI,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC"}
|
package/dist/channels.d.ts
CHANGED
|
@@ -66,6 +66,9 @@ export declare function seedChannelRegistry(opts: {
|
|
|
66
66
|
servers: string;
|
|
67
67
|
space: string;
|
|
68
68
|
creds?: string;
|
|
69
|
+
/** User mode: a `channel-writer`-view bearer + the space's sentinel creds (instead of a creds file). */
|
|
70
|
+
bearer?: string;
|
|
71
|
+
sentinelCreds?: string;
|
|
69
72
|
file: ChannelRegistryFile;
|
|
70
73
|
}): Promise<void>;
|
|
71
74
|
/** Write the space-wide default delivery class at space creation IF it is not already set (SPEC §4:
|
|
@@ -89,6 +92,9 @@ export declare function deleteChannels(opts: {
|
|
|
89
92
|
servers: string;
|
|
90
93
|
space: string;
|
|
91
94
|
creds?: string;
|
|
95
|
+
/** User mode: a `channel-writer`-view bearer + the space's sentinel creds (instead of a creds file). */
|
|
96
|
+
bearer?: string;
|
|
97
|
+
sentinelCreds?: string;
|
|
92
98
|
channels: string[];
|
|
93
99
|
}): Promise<void>;
|
|
94
100
|
/** Connect, read the whole registry (defaults + every channel entry) into a
|
|
@@ -98,5 +104,9 @@ export declare function readChannelRegistry(opts: {
|
|
|
98
104
|
servers: string;
|
|
99
105
|
space: string;
|
|
100
106
|
creds?: string;
|
|
107
|
+
/** User mode: the caller's OWN agent-view bearer + the space's sentinel creds — the registry is
|
|
108
|
+
* world-readable in-space, so no elevated view is needed for the read side. */
|
|
109
|
+
bearer?: string;
|
|
110
|
+
sentinelCreds?: string;
|
|
101
111
|
}): Promise<ChannelRegistryFile>;
|
|
102
112
|
//# sourceMappingURL=channels.d.ts.map
|
package/dist/channels.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAO,KAAK,EAAE,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"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"}
|