@cotal-ai/core 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-file.d.ts +12 -1
- package/dist/agent-file.d.ts.map +1 -1
- package/dist/agent-file.js +69 -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 +55 -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 +7 -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/evict.js
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D5 slice 4 — BROKER-BACKED LIVE CONNECTION EVICTION.
|
|
3
|
+
*
|
|
4
|
+
* Revocation has two halves. DENY-NEW (ledger revoke, cred expiry, stripped signer, ACL removal)
|
|
5
|
+
* stops the next exchange/connect — but a client that is ALREADY connected with a still-valid JWT
|
|
6
|
+
* keeps its live core subscriptions until that JWT expires. KILL-LIVE closes that window now:
|
|
7
|
+
* `$SYS.REQ.SERVER.<serverID>.KICK {cid}` disconnects one live client by connection id.
|
|
8
|
+
*
|
|
9
|
+
* This module is the kill-live primitive and its two credentials, kept deliberately small (the
|
|
10
|
+
* simplicity-lane shape: one eviction path, not a parallel subsystem):
|
|
11
|
+
* - the OBSERVER read (account CONNZ, `auth:true`) projected to `{cid, serverId, principal}` — a
|
|
12
|
+
* DIFFERENT projection than the membership feed's channel-folding (it keeps cid+serverId, which
|
|
13
|
+
* the feed discards), so it is its own tiny scan, not duplicated filtering;
|
|
14
|
+
* - the kill: `evictPrincipal(observerConn, evictorConn, accountId, principal)` = scan → KICK each
|
|
15
|
+
* matching cid on the SERVER THE CID CAME FROM → re-scan to verify, bounded, structured.
|
|
16
|
+
*
|
|
17
|
+
* Two credentials by design (never one broad sys user that both enumerates and kills):
|
|
18
|
+
* - the existing `membership-observer` (CONNZ-read only) does discovery;
|
|
19
|
+
* - a NEW kick-only evictor (`$SYS.REQ.SERVER.*.KICK` and nothing else) does the kill.
|
|
20
|
+
* Both are system-account users mintable ONLY at the `up` that provisions the account (the $SYS
|
|
21
|
+
* signing seed is never persisted) — so the evictor is a standing, high-power, renewable credential,
|
|
22
|
+
* classified with the observer, surfaced by the stale-auth diagnostics when absent.
|
|
23
|
+
*
|
|
24
|
+
* SEMANTICS, stated in the result (never inferred):
|
|
25
|
+
* - KICK has NO per-cid ack, so success is proven only by a re-scan showing the principal gone.
|
|
26
|
+
* - A PARTIAL/unavailable CONNZ read is `verifiedGone:false` with `scanComplete:false` — NEVER a
|
|
27
|
+
* silent success (the membership feed's truthium rule; a caller/flip gate stays blocked).
|
|
28
|
+
* - "principal not currently live" is a no-op SUCCESS (`kicked:0, remaining:0, verifiedGone:true`)
|
|
29
|
+
* — idempotent, so repair/doctor tooling never needs "already gone" special-casing.
|
|
30
|
+
* - This is ALWAYS paired with a committed deny-new by the caller: a kicked client reconnects with
|
|
31
|
+
* a fresh cid until its cred dies, so an evict-only loop would chase churn. The name says so.
|
|
32
|
+
*/
|
|
33
|
+
import { connect, credsAuthenticator } from "@nats-io/transport-node";
|
|
34
|
+
import { connzRequestSubject, principalFromConnz, serverKickSubject, MEMBERSHIP_INBOX_PREFIX } from "./subjects.js";
|
|
35
|
+
const enc = (s) => new TextEncoder().encode(s);
|
|
36
|
+
const MAX_PAGES = 64; // fan-out pagination guard (mirrors the membership feed's under-report ceiling)
|
|
37
|
+
/** Scan this account's live connections, projected to `{cid, serverId, principal}`. Returns
|
|
38
|
+
* `complete:false` when any round under-reported — zero replies (broker unreachable/denied), a
|
|
39
|
+
* MAX_PAGES truncation, OR a reply that names no server id (its connections can't be routed a
|
|
40
|
+
* KICK, so the scan can't act on what it saw) — so a caller never mistakes a partial read for "no
|
|
41
|
+
* such connection". */
|
|
42
|
+
async function scanLive(observerConn, accountId, opts) {
|
|
43
|
+
const conns = [];
|
|
44
|
+
let gotAnyReply = false;
|
|
45
|
+
let truncated = false;
|
|
46
|
+
let unroutable = false; // a reply named no server id → its conns can't be KICKed → scan is not complete
|
|
47
|
+
let seq = 0;
|
|
48
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
49
|
+
const offset = page * opts.pageLimit;
|
|
50
|
+
const replies = await connzRound(observerConn, accountId, offset, opts, seq++);
|
|
51
|
+
if (replies.length)
|
|
52
|
+
gotAnyReply = true;
|
|
53
|
+
let fullPageSomewhere = false;
|
|
54
|
+
for (const r of replies) {
|
|
55
|
+
const serverId = r.data?.server_id ?? r.server?.id;
|
|
56
|
+
if (!serverId) {
|
|
57
|
+
// KICK is per-server; a reply with no server id can't be routed. Fail CLOSED (mark the whole
|
|
58
|
+
// scan incomplete) so an unroutable-but-live connection is never read as "gone" — even an
|
|
59
|
+
// empty such reply, since it signals a malformed CONNZ round we can't fully trust.
|
|
60
|
+
unroutable = true;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const cs = r.data?.connections ?? [];
|
|
64
|
+
for (const c of cs) {
|
|
65
|
+
// Attribute across BOTH cred shapes — a callout user surfaces its principal as the
|
|
66
|
+
// `authorized_user` name-form (no tags), a static user surfaces the `principal:` tag.
|
|
67
|
+
const principal = principalFromConnz(c);
|
|
68
|
+
if (!principal)
|
|
69
|
+
continue; // un-attributable (infra/open/nkey) — not a target, safe to ignore
|
|
70
|
+
if (typeof c.cid !== "number") {
|
|
71
|
+
// An ATTRIBUTABLE connection with no usable cid can't be KICK-routed — same fail-closed
|
|
72
|
+
// posture as a missing server id: mark the scan incomplete so a still-live-but-unkickable
|
|
73
|
+
// target is never read as "gone". (A non-attributable row without a cid is just infra.)
|
|
74
|
+
unroutable = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
conns.push({ cid: c.cid, serverId, principal });
|
|
78
|
+
}
|
|
79
|
+
const total = r.data?.total ?? 0;
|
|
80
|
+
if (cs.length >= opts.pageLimit && offset + cs.length < total)
|
|
81
|
+
fullPageSomewhere = true;
|
|
82
|
+
}
|
|
83
|
+
if (!fullPageSomewhere)
|
|
84
|
+
break; // no server still has a full page → done
|
|
85
|
+
if (page === MAX_PAGES - 1)
|
|
86
|
+
truncated = true;
|
|
87
|
+
}
|
|
88
|
+
return { conns, complete: gotAnyReply && !truncated && !unroutable };
|
|
89
|
+
}
|
|
90
|
+
/** One CONNZ round: fan out the account request, collect every server's reply within the window. */
|
|
91
|
+
function connzRound(observerConn, accountId, offset, opts, seq) {
|
|
92
|
+
return new Promise((resolve) => {
|
|
93
|
+
// The reply inbox MUST sit under the prefix the observer cred (`membership-observer`) grants sub
|
|
94
|
+
// on — its ACL allows only `${MEMBERSHIP_INBOX_PREFIX}.>`, so a distinct `_INBOX.cotal-evict.*`
|
|
95
|
+
// subject is broker-denied and the scan gets ZERO replies (a fail-closed under-report).
|
|
96
|
+
const inbox = `${MEMBERSHIP_INBOX_PREFIX}.evict.${seq}`;
|
|
97
|
+
const out = [];
|
|
98
|
+
let settle;
|
|
99
|
+
let done = false;
|
|
100
|
+
const finish = () => {
|
|
101
|
+
if (done)
|
|
102
|
+
return;
|
|
103
|
+
done = true;
|
|
104
|
+
if (settle)
|
|
105
|
+
clearTimeout(settle);
|
|
106
|
+
clearTimeout(hard);
|
|
107
|
+
try {
|
|
108
|
+
sub.unsubscribe();
|
|
109
|
+
}
|
|
110
|
+
catch { /* draining */ }
|
|
111
|
+
resolve(out);
|
|
112
|
+
};
|
|
113
|
+
const sub = observerConn.subscribe(inbox, {
|
|
114
|
+
callback: (err, msg) => {
|
|
115
|
+
if (err)
|
|
116
|
+
return;
|
|
117
|
+
try {
|
|
118
|
+
out.push(msg.json());
|
|
119
|
+
}
|
|
120
|
+
catch { /* skip undecodable */ }
|
|
121
|
+
if (settle)
|
|
122
|
+
clearTimeout(settle);
|
|
123
|
+
settle = setTimeout(finish, opts.settleMs);
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
const hard = setTimeout(finish, opts.maxWaitMs);
|
|
127
|
+
observerConn.publish(connzRequestSubject(accountId), enc(JSON.stringify({ subscriptions: false, auth: true, offset, limit: opts.pageLimit })), { reply: inbox });
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/** KICK one connection by cid on the server that reported it. No per-cid ack from the broker; the
|
|
131
|
+
* caller's re-scan is the verification. A publish/permission failure is surfaced (thrown up), so a
|
|
132
|
+
* mis-scoped evictor cred fails loud rather than silently not-kicking. */
|
|
133
|
+
async function kick(evictorConn, conn) {
|
|
134
|
+
// Request/reply so a broker-side error (bad permissions, unknown server) surfaces rather than a
|
|
135
|
+
// fire-and-forget publish that a mis-scoped cred would swallow. The ServerAPIResponse `data` is
|
|
136
|
+
// empty on success; we don't parse it (re-scan verifies) but DO honor an `error` field.
|
|
137
|
+
const res = await evictorConn.request(serverKickSubject(conn.serverId), enc(JSON.stringify({ cid: conn.cid })), { timeout: 2000 });
|
|
138
|
+
const body = res.json();
|
|
139
|
+
if (body?.error)
|
|
140
|
+
throw new Error(`KICK cid ${conn.cid} on ${conn.serverId} refused: ${body.error.description ?? "unknown"}`);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Evict every live connection of one principal — the kill-live half of revocation, to be called
|
|
144
|
+
* ONLY AFTER the deny-new is committed (ledger revoke / cred expiry / ACL removal). Scans, KICKs
|
|
145
|
+
* each matching cid on its own server, then re-scans up to `maxVerifyRounds` to confirm the
|
|
146
|
+
* principal is gone. Fail-closed: a partial scan is `verifiedGone:false, scanComplete:false`, and a
|
|
147
|
+
* principal that was never live is an idempotent success no-op.
|
|
148
|
+
*
|
|
149
|
+
* The name carries the precondition: this is `evictDeniedPrincipal`-shaped — it does NOT deny new
|
|
150
|
+
* connects; without a committed deny-new a kicked client reconnects with a fresh cid.
|
|
151
|
+
*/
|
|
152
|
+
export async function evictDeniedPrincipal(observerConn, evictorConn, accountId, principal, options = {}) {
|
|
153
|
+
const opts = {
|
|
154
|
+
maxVerifyRounds: options.maxVerifyRounds ?? 3,
|
|
155
|
+
settleMs: options.settleMs ?? 250,
|
|
156
|
+
maxWaitMs: options.maxWaitMs ?? 2000,
|
|
157
|
+
pageLimit: options.pageLimit ?? 1024,
|
|
158
|
+
};
|
|
159
|
+
const first = await scanLive(observerConn, accountId, opts);
|
|
160
|
+
if (!first.complete)
|
|
161
|
+
return { principal, kicked: 0, remaining: 0, verifiedGone: false, scanComplete: false, note: "CONNZ scan under-reported (no responder or truncated) - eviction UNKNOWN, not attempted" };
|
|
162
|
+
const targets = first.conns.filter((c) => c.principal === principal);
|
|
163
|
+
if (targets.length === 0)
|
|
164
|
+
return { principal, kicked: 0, remaining: 0, verifiedGone: true, scanComplete: true, note: "principal not currently live - nothing to evict" };
|
|
165
|
+
let kicked = 0;
|
|
166
|
+
let note;
|
|
167
|
+
for (const t of targets) {
|
|
168
|
+
try {
|
|
169
|
+
await kick(evictorConn, t);
|
|
170
|
+
kicked++;
|
|
171
|
+
}
|
|
172
|
+
catch (e) {
|
|
173
|
+
note = e instanceof Error ? e.message : String(e);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Verify by re-scan — a client kicked before deny-new fully propagates can reconnect with a fresh
|
|
177
|
+
// cid, so loop until the principal is gone or the rounds run out (never one snapshot).
|
|
178
|
+
for (let round = 0; round < opts.maxVerifyRounds; round++) {
|
|
179
|
+
const rescan = await scanLive(observerConn, accountId, opts);
|
|
180
|
+
if (!rescan.complete)
|
|
181
|
+
return { principal, kicked, remaining: 0, verifiedGone: false, scanComplete: false, note: note ?? "verify re-scan under-reported - eviction UNKNOWN" };
|
|
182
|
+
const still = rescan.conns.filter((c) => c.principal === principal);
|
|
183
|
+
if (still.length === 0)
|
|
184
|
+
return { principal, kicked, remaining: 0, verifiedGone: true, scanComplete: true, note };
|
|
185
|
+
// Still live — kick the fresh cids and try again (bounded by maxVerifyRounds).
|
|
186
|
+
for (const t of still) {
|
|
187
|
+
try {
|
|
188
|
+
await kick(evictorConn, t);
|
|
189
|
+
kicked++;
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
note = e instanceof Error ? e.message : String(e);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (round === opts.maxVerifyRounds - 1)
|
|
196
|
+
return { principal, kicked, remaining: still.length, verifiedGone: false, scanComplete: true, note: note ?? `${still.length} connection(s) still live after ${opts.maxVerifyRounds} verify rounds - is deny-new committed?` };
|
|
197
|
+
}
|
|
198
|
+
// Unreachable (the loop returns), but satisfies the type checker.
|
|
199
|
+
return { principal, kicked, remaining: 0, verifiedGone: false, scanComplete: true, note };
|
|
200
|
+
}
|
|
201
|
+
/** Creds-level wrapper for composition roots that hold the two $SYS creds as FILES/strings (the
|
|
202
|
+
* delivery daemon's admin-rail executor): open the observer (under its granted inbox prefix) and
|
|
203
|
+
* the kick-only evictor PER CALL, run {@link evictDeniedPrincipal}, and drain both — eviction is a
|
|
204
|
+
* rare repair/flip step, never a standing $SYS connection. Core owns the connection lifecycle
|
|
205
|
+
* (the same placement rule as the membership feed), so edge packages never import the transport. */
|
|
206
|
+
export async function evictDeniedPrincipalWithCreds(opts) {
|
|
207
|
+
const enc = (s) => new TextEncoder().encode(s);
|
|
208
|
+
const observer = await connect({
|
|
209
|
+
servers: opts.servers,
|
|
210
|
+
authenticator: credsAuthenticator(enc(opts.observerCreds)),
|
|
211
|
+
inboxPrefix: MEMBERSHIP_INBOX_PREFIX,
|
|
212
|
+
maxReconnectAttempts: 0,
|
|
213
|
+
});
|
|
214
|
+
try {
|
|
215
|
+
const evictor = await connect({
|
|
216
|
+
servers: opts.servers,
|
|
217
|
+
authenticator: credsAuthenticator(enc(opts.evictorCreds)),
|
|
218
|
+
maxReconnectAttempts: 0,
|
|
219
|
+
});
|
|
220
|
+
try {
|
|
221
|
+
return await evictDeniedPrincipal(observer, evictor, opts.accountId, opts.principal, opts.options ?? {});
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
await evictor.drain().catch(() => { });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
finally {
|
|
228
|
+
await observer.drain().catch(() => { });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=evict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evict.js","sourceRoot":"","sources":["../src/evict.ts"],"names":[],"mappings":"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"}
|
package/dist/identity.d.ts
CHANGED
|
@@ -23,4 +23,19 @@ export declare function newIdentity(): Identity;
|
|
|
23
23
|
* endpoint that authenticates with creds adopt the matching `card.id`, keeping one id
|
|
24
24
|
* everywhere. */
|
|
25
25
|
export declare function idFromCreds(creds: string): string;
|
|
26
|
+
/** The decoded (UNVERIFIED) claims of a creds file's user JWT — shared parse for every local
|
|
27
|
+
* inspector (credential health, renewal scheduling, identity checks). Unverified is correct here:
|
|
28
|
+
* the broker is the enforcement boundary; local readers only need the claims to schedule and
|
|
29
|
+
* diagnose. Throws on a structurally-unusable file (no JWT block / undecodable payload). */
|
|
30
|
+
export declare function credsClaims(creds: string): {
|
|
31
|
+
sub?: string;
|
|
32
|
+
iat?: number;
|
|
33
|
+
exp?: number;
|
|
34
|
+
name?: string;
|
|
35
|
+
};
|
|
36
|
+
/** The full identity (id + seed) carried by a creds file — what a standing-renewal REMINTER needs:
|
|
37
|
+
* re-signing a fresh JWT for the file's EXISTING nkey (never a new one) is what lets the renewed
|
|
38
|
+
* cred pass the endpoint's identity pin, so renewal can never silently swap who a daemon is. Same
|
|
39
|
+
* seed-block parse + JWT-subject cross-check as {@link idFromCreds}. */
|
|
40
|
+
export declare function identityFromCreds(creds: string): Identity;
|
|
26
41
|
//# sourceMappingURL=identity.d.ts.map
|
package/dist/identity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ;IACvB,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;CACd;AAED;oFACoF;AACpF,wBAAgB,WAAW,IAAI,QAAQ,CAItC;AAED;;;;;kBAKkB;AAClB,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ;IACvB,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;CACd;AAED;oFACoF;AACpF,wBAAgB,WAAW,IAAI,QAAQ,CAItC;AAED;;;;;kBAKkB;AAClB,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;6FAG6F;AAC7F,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAStG;AAED;;;yEAGyE;AACzE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAYzD"}
|
package/dist/identity.js
CHANGED
|
@@ -13,10 +13,34 @@ export function newIdentity() {
|
|
|
13
13
|
* endpoint that authenticates with creds adopt the matching `card.id`, keeping one id
|
|
14
14
|
* everywhere. */
|
|
15
15
|
export function idFromCreds(creds) {
|
|
16
|
+
return identityFromCreds(creds).id;
|
|
17
|
+
}
|
|
18
|
+
/** The decoded (UNVERIFIED) claims of a creds file's user JWT — shared parse for every local
|
|
19
|
+
* inspector (credential health, renewal scheduling, identity checks). Unverified is correct here:
|
|
20
|
+
* the broker is the enforcement boundary; local readers only need the claims to schedule and
|
|
21
|
+
* diagnose. Throws on a structurally-unusable file (no JWT block / undecodable payload). */
|
|
22
|
+
export function credsClaims(creds) {
|
|
23
|
+
const jwtM = creds.match(/BEGIN NATS USER JWT-----\s*([\s\S]*?)\s*------END NATS USER JWT/);
|
|
24
|
+
const payload = jwtM?.[1].trim().split(".")[1];
|
|
25
|
+
if (!payload)
|
|
26
|
+
throw new Error("creds: no NATS user JWT block found");
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error("creds: undecodable user JWT payload");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** The full identity (id + seed) carried by a creds file — what a standing-renewal REMINTER needs:
|
|
35
|
+
* re-signing a fresh JWT for the file's EXISTING nkey (never a new one) is what lets the renewed
|
|
36
|
+
* cred pass the endpoint's identity pin, so renewal can never silently swap who a daemon is. Same
|
|
37
|
+
* seed-block parse + JWT-subject cross-check as {@link idFromCreds}. */
|
|
38
|
+
export function identityFromCreds(creds) {
|
|
16
39
|
const seedM = creds.match(/BEGIN USER NKEY SEED-----\s*([\s\S]*?)\s*------END USER NKEY SEED/);
|
|
17
40
|
if (!seedM)
|
|
18
41
|
throw new Error("creds: no user nkey seed block found");
|
|
19
|
-
const
|
|
42
|
+
const seed = seedM[1].trim();
|
|
43
|
+
const id = fromSeed(new TextEncoder().encode(seed)).getPublicKey();
|
|
20
44
|
const jwtM = creds.match(/BEGIN NATS USER JWT-----\s*([\s\S]*?)\s*------END NATS USER JWT/);
|
|
21
45
|
const payload = jwtM?.[1].trim().split(".")[1];
|
|
22
46
|
const sub = payload
|
|
@@ -24,6 +48,6 @@ export function idFromCreds(creds) {
|
|
|
24
48
|
: undefined;
|
|
25
49
|
if (sub && sub !== id)
|
|
26
50
|
throw new Error(`creds: seed identity ${id} != JWT subject ${sub}`);
|
|
27
|
-
return id;
|
|
51
|
+
return { id, seed };
|
|
28
52
|
}
|
|
29
53
|
//# sourceMappingURL=identity.js.map
|
package/dist/identity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAkBtD;oFACoF;AACpF,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC;AACzC,CAAC;AAED;;;;;kBAKkB;AAClB,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAkBtD;oFACoF;AACpF,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC;AACzC,CAAC;AAED;;;;;kBAKkB;AAClB,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;AACrC,CAAC;AAED;;;6FAG6F;AAC7F,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;IAC5F,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAgE,CAAC;IACvI,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;;yEAGyE;AACzE,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IAC/F,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;IAC5F,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,OAAO;QACjB,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAsB,CAAC,GAAG;QAC1F,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,EAAE,mBAAmB,GAAG,EAAE,CAAC,CAAC;IAC3F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./channels.js";
|
|
|
9
9
|
export * from "./members.js";
|
|
10
10
|
export * from "./acls.js";
|
|
11
11
|
export * from "./membership-feed.js";
|
|
12
|
+
export * from "./evict.js";
|
|
12
13
|
export * from "./lease.js";
|
|
13
14
|
export * from "./agent-file.js";
|
|
14
15
|
export * from "./launch.js";
|
|
@@ -22,4 +23,5 @@ export * from "./command.js";
|
|
|
22
23
|
export * from "./runtime.js";
|
|
23
24
|
export * from "./terminal.js";
|
|
24
25
|
export * from "./registry.js";
|
|
26
|
+
export * from "./auth-provider.js";
|
|
25
27
|
//# 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,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./channels.js";
|
|
|
9
9
|
export * from "./members.js";
|
|
10
10
|
export * from "./acls.js";
|
|
11
11
|
export * from "./membership-feed.js";
|
|
12
|
+
export * from "./evict.js";
|
|
12
13
|
export * from "./lease.js";
|
|
13
14
|
export * from "./agent-file.js";
|
|
14
15
|
export * from "./launch.js";
|
|
@@ -22,4 +23,5 @@ export * from "./command.js";
|
|
|
22
23
|
export * from "./runtime.js";
|
|
23
24
|
export * from "./terminal.js";
|
|
24
25
|
export * from "./registry.js";
|
|
26
|
+
export * from "./auth-provider.js";
|
|
25
27
|
//# 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,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
|
package/dist/launch.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ export interface MeshLaunchAgent {
|
|
|
15
15
|
agent: string;
|
|
16
16
|
role?: string;
|
|
17
17
|
model?: string;
|
|
18
|
+
variant?: string;
|
|
19
|
+
/** Opaque connector-specific launch options (see {@link LaunchOpts.launchOptions}). */
|
|
20
|
+
launchOptions?: Record<string, unknown>;
|
|
18
21
|
description?: string;
|
|
19
22
|
/** Persona body — materialized to a transient, non-authoritative file the connector reads. */
|
|
20
23
|
body?: string;
|
|
@@ -36,6 +39,10 @@ export interface MeshLaunchSpec {
|
|
|
36
39
|
space: string;
|
|
37
40
|
/** Identifies this apply run: names the transient `.cotal/run/<runId>/` dir and ties to the ledger. */
|
|
38
41
|
runId: string;
|
|
42
|
+
/** USER-AUTH meshes only: the derived owner (`u_…`) every launched agent runs under — the
|
|
43
|
+
* logged-in operator who applied the manifest, resolved at apply time (`ownerForLogin`). The
|
|
44
|
+
* manager refuses a user-mesh launch spec without one (fail loud, never a guessed owner). */
|
|
45
|
+
owner?: string;
|
|
39
46
|
agents: MeshLaunchAgent[];
|
|
40
47
|
}
|
|
41
48
|
//# sourceMappingURL=launch.d.ts.map
|
package/dist/launch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;0FAC0F;AAC1F,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,wFAAwF;IACxF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iCAAiC;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gDAAgD;IAChD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uGAAuG;IACvG,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mGAAmG;AACnG,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B"}
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;0FAC0F;AAC1F,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,wFAAwF;IACxF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iCAAiC;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gDAAgD;IAChD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uGAAuG;IACvG,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mGAAmG;AACnG,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,KAAK,EAAE,MAAM,CAAC;IACd;;kGAE8F;IAC9F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B"}
|
package/dist/members.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../src/members.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAO,KAAK,EAAE,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;oFACoF;AACpF,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAM/E;AAED;mEACmE;AACnE,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,OAAO,yBAAyB,EAAE,cAAc,EACpD,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9B,OAAO,CAAC,EAAE,CAAC,CAGb;AAED;;gGAEgG;AAChG,wBAAsB,UAAU,CAC9B,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAQrE;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuB5F;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAoBvC;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAoBvC;AAED;;2FAE2F;AAC3F,wBAAsB,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExF;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,EAAE,EACN,MAAM,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,OAAO,CAAC,gBAAgB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../src/members.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAO,KAAK,EAAE,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;oFACoF;AACpF,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAM/E;AAED;mEACmE;AACnE,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,OAAO,yBAAyB,EAAE,cAAc,EACpD,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9B,OAAO,CAAC,EAAE,CAAC,CAGb;AAED;;gGAEgG;AAChG,wBAAsB,UAAU,CAC9B,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAQrE;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuB5F;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAoBvC;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAoBvC;AAED;;2FAE2F;AAC3F,wBAAsB,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExF;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,EAAE,EACN,MAAM,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAc7B;AAED;;;;;;;;;;;;;gEAagE;AAChE,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAI3E"}
|
package/dist/members.js
CHANGED
|
@@ -159,11 +159,14 @@ export async function listMembers(kv, filter = {}) {
|
|
|
159
159
|
const parsed = parseMemberKey(key);
|
|
160
160
|
if (!parsed)
|
|
161
161
|
continue;
|
|
162
|
+
// `parsed.principal` is the member's owner+actor dot-form (membership is per-agent); the
|
|
163
|
+
// members.ts API calls this identity token `owner` throughout — under the owner+actor grammar an
|
|
164
|
+
// "owner" here IS the full principal `<owner>.<actor>`, so `filter.owner` compares to it directly.
|
|
162
165
|
if (filter.channel !== undefined && parsed.channel !== filter.channel)
|
|
163
166
|
continue;
|
|
164
|
-
if (filter.owner !== undefined && parsed.
|
|
167
|
+
if (filter.owner !== undefined && parsed.principal !== filter.owner)
|
|
165
168
|
continue;
|
|
166
|
-
const rec = await readMember(kv, parsed.channel, parsed.
|
|
169
|
+
const rec = await readMember(kv, parsed.channel, parsed.principal);
|
|
167
170
|
if (rec)
|
|
168
171
|
out.push(rec.record);
|
|
169
172
|
}
|
package/dist/members.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"members.js","sourceRoot":"","sources":["../src/members.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"members.js","sourceRoot":"","sources":["../src/members.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,10 +3,16 @@ export interface MembershipFeedOpts {
|
|
|
3
3
|
space: string;
|
|
4
4
|
/** DATA account public key — the CONNZ request + CONNECT/DISCONNECT event subjects pin this account. */
|
|
5
5
|
accountId: string;
|
|
6
|
-
/** Scoped SYSTEM-account observer creds (conn A — CONNZ reader).
|
|
6
|
+
/** Scoped SYSTEM-account observer creds (conn A — CONNZ reader). Always a static string: it is
|
|
7
|
+
* `rotation-renewed` ($SYS seed dies at `up`), so its only renewal is a system-account rotation +
|
|
8
|
+
* broker restart — a new process, never a live reload. */
|
|
7
9
|
observerCreds: string;
|
|
8
|
-
/** Scoped DATA-account read/write creds (conn B — members read + feed write)
|
|
9
|
-
|
|
10
|
+
/** Scoped DATA-account read/write creds (conn B — members read + feed write), or a SOURCE that
|
|
11
|
+
* re-reads them (D5 slice 5 class 2: the manager re-signs the creds file for the SAME nkey; the
|
|
12
|
+
* getter is re-evaluated per (re)connect attempt, so the broker's expiry-close renews the
|
|
13
|
+
* connection from the refreshed file). A read that swaps the nkey fails loud — the feed's identity
|
|
14
|
+
* (inbox scope + self-presence check) is pinned to the first read. */
|
|
15
|
+
rwCreds: string | (() => string);
|
|
10
16
|
/** Safety reconcile interval (ms) — primary signal (no SUB/UNSUB event exists). Default 15000. */
|
|
11
17
|
intervalMs?: number;
|
|
12
18
|
/** Connect/disconnect-event → re-poll debounce (ms); coalesces connect storms. Default 400. */
|
|
@@ -23,6 +29,14 @@ export interface MembershipFeedOpts {
|
|
|
23
29
|
export interface MembershipFeedHandle {
|
|
24
30
|
/** Force an immediate reconcile (also used by tests). Never throws — errors are logged. */
|
|
25
31
|
poll(): Promise<void>;
|
|
32
|
+
/** Explicitly adopt a re-signed rw creds file on conn B (D5 class-2 renewal): validated re-read
|
|
33
|
+
* (pinned nkey) + forced reconnect, returning the adopted JWT window as proof. THROWS when the
|
|
34
|
+
* re-read fails (missing/swapped file) — adoption must never be assumed. */
|
|
35
|
+
reloadRwCreds(): Promise<{
|
|
36
|
+
identity: string;
|
|
37
|
+
iat?: number;
|
|
38
|
+
exp?: number;
|
|
39
|
+
}>;
|
|
26
40
|
stop(): Promise<void>;
|
|
27
41
|
}
|
|
28
42
|
/** Connect, wire the triggers + safety poll, and run an immediate first reconcile. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"membership-feed.d.ts","sourceRoot":"","sources":["../src/membership-feed.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"membership-feed.d.ts","sourceRoot":"","sources":["../src/membership-feed.ts"],"names":[],"mappings":"AA8CA,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,wGAAwG;IACxG,SAAS,EAAE,MAAM,CAAC;IAClB;;+DAE2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB;;;;2EAIuE;IACvE,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACjC,kGAAkG;IAClG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uGAAuG;IACvG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,2FAA2F;IAC3F,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB;;iFAE6E;IAC7E,aAAa,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAKD,sFAAsF;AACtF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4OjG"}
|
package/dist/membership-feed.js
CHANGED
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import { connect, credsAuthenticator } from "@nats-io/transport-node";
|
|
31
31
|
import { Kvm } from "@nats-io/kv";
|
|
32
|
-
import { membershipBucket, membershipKey, MEMBERSHIP_FEED_KEY, MEMBERSHIP_INBOX_PREFIX, connzRequestSubject, accountConnectSubject, accountDisconnectSubject, channelFromChatSubscription, } from "./subjects.js";
|
|
32
|
+
import { membershipBucket, membershipKey, MEMBERSHIP_FEED_KEY, MEMBERSHIP_INBOX_PREFIX, connzRequestSubject, accountConnectSubject, accountDisconnectSubject, channelFromChatSubscription, principalFromConnz, } from "./subjects.js";
|
|
33
33
|
import { openMembersRegistry, listMembers } from "./members.js";
|
|
34
|
-
import { idFromCreds } from "./identity.js";
|
|
34
|
+
import { credsClaims, idFromCreds } from "./identity.js";
|
|
35
35
|
const enc = (s) => new TextEncoder().encode(s);
|
|
36
36
|
const MAX_PAGES = 64; // fan-out pagination guard (64 × 1024 = 65k conns/server before a loud under-report)
|
|
37
37
|
/** Connect, wire the triggers + safety poll, and run an immediate first reconcile. */
|
|
@@ -52,10 +52,22 @@ export async function startMembershipFeed(opts) {
|
|
|
52
52
|
});
|
|
53
53
|
connA.closed().then((err) => { if (err)
|
|
54
54
|
log(`conn A (system) closed: ${err.message}`); });
|
|
55
|
-
const
|
|
55
|
+
const readRw = typeof opts.rwCreds === "function" ? opts.rwCreds : () => opts.rwCreds;
|
|
56
|
+
const rwSelfId = idFromCreds(readRw()); // conn B's own nkey — the data-account self-presence check below
|
|
57
|
+
// Pin every re-read to the first read's nkey: a renewal (manager re-signs the file) keeps the
|
|
58
|
+
// identity; a swapped file would silently break the inbox scope + self-presence check, so it throws
|
|
59
|
+
// inside the authenticator instead (the connect attempt fails loud and retries).
|
|
60
|
+
const rwCredsPinned = () => {
|
|
61
|
+
const creds = readRw();
|
|
62
|
+
const id = idFromCreds(creds);
|
|
63
|
+
if (id !== rwSelfId)
|
|
64
|
+
throw new Error(`membership rw creds re-read returned identity ${id}, expected ${rwSelfId} - a renewal may not swap the feed's nkey`);
|
|
65
|
+
return creds;
|
|
66
|
+
};
|
|
56
67
|
const connB = await connect({
|
|
57
68
|
servers: opts.servers,
|
|
58
|
-
|
|
69
|
+
// Re-wrapped per (re)connect attempt so each attempt signs with the freshest (pinned) file read.
|
|
70
|
+
authenticator: (nonce) => credsAuthenticator(enc(rwCredsPinned()))(nonce),
|
|
59
71
|
name: "cotal-membership-rw",
|
|
60
72
|
// The rw cred's sub.allow is `_INBOX_<id>.>`, so the connection's inbox prefix MUST match it — else
|
|
61
73
|
// every KV reply / ordered-consumer delivery (kv.get/keys/watch) lands on a subject it can't subscribe.
|
|
@@ -124,7 +136,7 @@ export async function startMembershipFeed(opts) {
|
|
|
124
136
|
const replies = await connzRound(offset);
|
|
125
137
|
if (replies.length === 0) {
|
|
126
138
|
if (page === 0)
|
|
127
|
-
log(`CONNZ returned no replies (offset 0)
|
|
139
|
+
log(`CONNZ returned no replies (offset 0) - broker unreachable or cred denied; keeping last membership this tick`);
|
|
128
140
|
break;
|
|
129
141
|
}
|
|
130
142
|
gotReply = true;
|
|
@@ -151,7 +163,7 @@ export async function startMembershipFeed(opts) {
|
|
|
151
163
|
break;
|
|
152
164
|
}
|
|
153
165
|
if (page === MAX_PAGES - 1)
|
|
154
|
-
log(`CONNZ still paginating after ${MAX_PAGES} pages (servers ${[...serverMore].join(",")})
|
|
166
|
+
log(`CONNZ still paginating after ${MAX_PAGES} pages (servers ${[...serverMore].join(",")}) - UNDER-REPORTING; skipping this sweep`);
|
|
155
167
|
}
|
|
156
168
|
// SELF-PRESENCE completeness check (socrates): the data account ALWAYS holds at least conn B, so a
|
|
157
169
|
// sweep that doesn't even include our own rw connection missed connections (a mid-reconnect blip, or
|
|
@@ -162,13 +174,13 @@ export async function startMembershipFeed(opts) {
|
|
|
162
174
|
// == expected server count` (expected set discovered via $SYS.REQ.SERVER.PING); deferred with the rest
|
|
163
175
|
// of multi-broker support — a conscious deferral, not a single-server bake-in.
|
|
164
176
|
if (gotReply && exhausted && !seenSelf)
|
|
165
|
-
log(`CONNZ sweep omitted our own rw connection
|
|
177
|
+
log(`CONNZ sweep omitted our own rw connection - treating as incomplete (keeping last membership)`);
|
|
166
178
|
// NO-SILENT-DEGRADATION (socrates): in a real cluster the conn-B floor only proves conn B's OWN server
|
|
167
179
|
// answered — a DIFFERENT silent server would still pass `complete` yet under-report its agents. Until
|
|
168
180
|
// multi-broker responder-accounting ships, surface that limit LOUDLY (once) rather than degrade quietly.
|
|
169
181
|
if (serversSeen.size > 1 && !clusterWarned) {
|
|
170
182
|
clusterWarned = true;
|
|
171
|
-
log(`multi-server cluster detected (${serversSeen.size} responders)
|
|
183
|
+
log(`multi-server cluster detected (${serversSeen.size} responders) - membership completeness uses the conn-B floor only; a silent peer server can under-report (multi-broker accounting deferred, see core-sub-fabric.md)`);
|
|
172
184
|
}
|
|
173
185
|
return { live, complete: gotReply && exhausted && seenSelf };
|
|
174
186
|
}
|
|
@@ -264,6 +276,15 @@ export async function startMembershipFeed(opts) {
|
|
|
264
276
|
await poll(); // first reconcile now
|
|
265
277
|
return {
|
|
266
278
|
poll,
|
|
279
|
+
async reloadRwCreds() {
|
|
280
|
+
// Explicit class-2 adoption for conn B (D5 slice 5): validate the re-read (the pinned getter
|
|
281
|
+
// throws on a swapped nkey or a missing file) and force a reconnect so the fresh cred is on
|
|
282
|
+
// the wire NOW — never waiting for the broker's expiry-close. The observer conn (A) is
|
|
283
|
+
// rotation-renewed and deliberately not reloadable.
|
|
284
|
+
const { exp, iat } = credsClaims(rwCredsPinned());
|
|
285
|
+
await connB.reconnect().catch(() => { }); // already-reconnecting is a no-op; its loop re-reads the getter
|
|
286
|
+
return { identity: rwSelfId, iat, exp };
|
|
287
|
+
},
|
|
267
288
|
async stop() {
|
|
268
289
|
stopped = true;
|
|
269
290
|
clearInterval(timer);
|
|
@@ -278,23 +299,30 @@ export async function startMembershipFeed(opts) {
|
|
|
278
299
|
},
|
|
279
300
|
};
|
|
280
301
|
}
|
|
281
|
-
/** Fold one CONNZ connection into the live map: keyed by
|
|
282
|
-
*
|
|
302
|
+
/** Fold one CONNZ connection into the live map: keyed by the connection's PRINCIPAL dot-form
|
|
303
|
+
* (`<owner>.<actor>`), recovered via {@link principalFromConnz} — a STATICALLY-minted user surfaces
|
|
304
|
+
* its `principal:` tag, while a CALLOUT-minted (user-mode) connection surfaces the principal
|
|
305
|
+
* NAME-form as `authorized_user` and NO tags (nats-server 2.10/2.14 behavior; the live-eviction
|
|
306
|
+
* work proved a tags-only read misses every user-mode connection — they'd never appear in the
|
|
307
|
+
* graph). Unions its chat-subscription patterns (wildcards kept, e.g. `team.>` or a whole-chat `>`).
|
|
308
|
+
* A STATIC user's raw ephemeral nkey `authorized_user` is NOT a principal name-form, so it stays
|
|
309
|
+
* unattributable — an un-principal connection is DROPPED (fail-closed), never keyed by its nkey,
|
|
310
|
+
* which would fork one agent into two graph nodes.
|
|
283
311
|
*
|
|
284
312
|
* Infra taps SELF-EXCLUDE — no shape heuristic needed (review-general, socrates): the web dashboard taps
|
|
285
313
|
* `cotal.<space>.>` (spaceWildcard) and `cotal console` taps `cotal.<space>.chat.>` (chatWildcard), both
|
|
286
314
|
* of which {@link channelFromChatSubscription} maps to `null` (the former isn't `.chat.`-prefixed; the
|
|
287
315
|
* latter has no channel token after `chat.`), so they contribute zero channels here; conn B / the
|
|
288
316
|
* delivery cred / the manager hold no chat sub at all. The ONLY subscription that yields the whole-chat
|
|
289
|
-
* `>` pattern is an AGENT's own `chat
|
|
317
|
+
* `>` pattern is an AGENT's own `chat.*.*.>` (allowSubscribe `[">"]` — e.g. the default persona), which is
|
|
290
318
|
* a legitimate broad reader the feed MUST surface (the source-of-truth goal), NOT drop. So no shape-based
|
|
291
319
|
* exclusion: a `>` pattern is recorded as-is and the dashboard renders it as a "reads-all" node (a badge,
|
|
292
320
|
* not a spoke to every hub) rather than expanding it. */
|
|
293
321
|
function addConn(space, live, c) {
|
|
294
322
|
const subs = c.subscriptions_list ?? [];
|
|
295
|
-
const id = c
|
|
323
|
+
const id = principalFromConnz(c); // tag (static) OR authorized_user name-form (callout) — see doc above
|
|
296
324
|
if (!id)
|
|
297
|
-
return; // no
|
|
325
|
+
return; // no attributable principal (open mode / legacy / infra) — not a member here
|
|
298
326
|
const patterns = subs
|
|
299
327
|
.map((s) => channelFromChatSubscription(space, s))
|
|
300
328
|
.filter((x) => x !== null);
|