@camstack/system 1.2.386 → 1.2.387
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/builtins/system-config/mesh-actions.d.ts +12 -0
- package/dist/builtins/system-config/system-config.addon.d.ts +25 -5
- package/dist/builtins/system-config/system-config.addon.js +264 -53
- package/dist/builtins/system-config/system-config.addon.mjs +257 -55
- package/dist/index.js +9 -0
- package/dist/index.mjs +2 -2
- package/dist/kernel/index.d.ts +2 -0
- package/dist/kernel/moleculer/agent-ui-unlock.d.ts +52 -0
- package/package.json +1 -1
|
@@ -15,5 +15,17 @@ export declare const systemConfigMeshActions: {
|
|
|
15
15
|
}, z.core.$strip>, "mutation", "admin", {
|
|
16
16
|
readonly kind: "system";
|
|
17
17
|
}>;
|
|
18
|
+
/** Hub admin → short-lived ticket the agent redeems for a tab session (D821). */
|
|
19
|
+
mintAgentUiUnlockTicket: import('@camstack/types').CustomActionSpec<z.ZodObject<{
|
|
20
|
+
nodeId: z.ZodString;
|
|
21
|
+
dashboardBaseUrl: z.ZodOptional<z.ZodString>;
|
|
22
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
23
|
+
ticket: z.ZodString;
|
|
24
|
+
exp: z.ZodNumber;
|
|
25
|
+
nodeId: z.ZodString;
|
|
26
|
+
dashboardUrl: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, z.core.$strip>, "mutation", "admin", {
|
|
28
|
+
readonly kind: "system";
|
|
29
|
+
}>;
|
|
18
30
|
};
|
|
19
31
|
export type SystemConfigMeshActions = typeof systemConfigMeshActions;
|
|
@@ -23,6 +23,17 @@ export declare class SystemConfigAddon extends BaseAddon {
|
|
|
23
23
|
}, import('zod/v4/core').$strip>, "mutation", "admin", {
|
|
24
24
|
readonly kind: "system";
|
|
25
25
|
}>;
|
|
26
|
+
mintAgentUiUnlockTicket: import('@camstack/types').CustomActionSpec<import('zod').ZodObject<{
|
|
27
|
+
nodeId: import('zod').ZodString;
|
|
28
|
+
dashboardBaseUrl: import('zod').ZodOptional<import('zod').ZodString>;
|
|
29
|
+
}, import('zod/v4/core').$strip>, import('zod').ZodObject<{
|
|
30
|
+
ticket: import('zod').ZodString;
|
|
31
|
+
exp: import('zod').ZodNumber;
|
|
32
|
+
nodeId: import('zod').ZodString;
|
|
33
|
+
dashboardUrl: import('zod').ZodOptional<import('zod').ZodString>;
|
|
34
|
+
}, import('zod/v4/core').$strip>, "mutation", "admin", {
|
|
35
|
+
readonly kind: "system";
|
|
36
|
+
}>;
|
|
26
37
|
};
|
|
27
38
|
actionHandlers: {
|
|
28
39
|
mintJoinToken: (input: unknown) => Promise<{
|
|
@@ -33,6 +44,12 @@ export declare class SystemConfigAddon extends BaseAddon {
|
|
|
33
44
|
caFingerprint: string;
|
|
34
45
|
nodeId?: string;
|
|
35
46
|
}>;
|
|
47
|
+
mintAgentUiUnlockTicket: (input: unknown) => Promise<{
|
|
48
|
+
ticket: string;
|
|
49
|
+
exp: number;
|
|
50
|
+
nodeId: string;
|
|
51
|
+
dashboardUrl?: string;
|
|
52
|
+
}>;
|
|
36
53
|
};
|
|
37
54
|
}>;
|
|
38
55
|
protected onShutdown(): Promise<void>;
|
|
@@ -44,6 +61,9 @@ export declare class SystemConfigAddon extends BaseAddon {
|
|
|
44
61
|
private applyStoredClearPort;
|
|
45
62
|
private onMeshCaReady;
|
|
46
63
|
private mintJoinToken;
|
|
64
|
+
/** D821 — short-lived ticket for the agent's `:4444` unlock session. */
|
|
65
|
+
private mintAgentUiUnlock;
|
|
66
|
+
private readAgentDashboardOrigins;
|
|
47
67
|
private resolveHubUrl;
|
|
48
68
|
private resolveHubMeshAddress;
|
|
49
69
|
/** The keychain handle for owner `system`; `null` where there is no door. */
|
|
@@ -55,7 +75,8 @@ export declare class SystemConfigAddon extends BaseAddon {
|
|
|
55
75
|
* The cluster secret's save path: the value goes to the keychain (owner
|
|
56
76
|
* `system`), the row gets the marker; `''` / a view keeps. `$secretClear` is
|
|
57
77
|
* REFUSED: the secret is mandatory (D802). A value the keychain cannot store
|
|
58
|
-
* is REFUSED — never written inline (D787, P5).
|
|
78
|
+
* is REFUSED — never written inline (D787, P5). Mesh auth mode is always
|
|
79
|
+
* enforced (D821) — a legacy `meshAuth` in the patch is ignored.
|
|
59
80
|
*/
|
|
60
81
|
private writeClusterSection;
|
|
61
82
|
/**
|
|
@@ -64,13 +85,12 @@ export declare class SystemConfigAddon extends BaseAddon {
|
|
|
64
85
|
* Persist, then apply — an `on` save always passes.
|
|
65
86
|
*/
|
|
66
87
|
private writeMeshClearPort;
|
|
67
|
-
/**
|
|
88
|
+
/** Persist + publish mesh auth mode (always `enforced` after D821). */
|
|
68
89
|
private writeMeshAuthMode;
|
|
69
90
|
/**
|
|
70
91
|
* First boot, or a keychain reset that cleared the marker (D802): a fresh
|
|
71
|
-
* random secret, stored like an operator save.
|
|
72
|
-
*
|
|
73
|
-
* with no agent yet, the hub's auto-enforce ends it at once.
|
|
92
|
+
* random secret, stored like an operator save. Mesh auth stays enforced
|
|
93
|
+
* (D821) — every agent must present the secret; there is no transition window.
|
|
74
94
|
*/
|
|
75
95
|
private generateClusterSecret;
|
|
76
96
|
private storeClusterSecret;
|
|
@@ -150,6 +150,145 @@ function getProcessMeshAuthStatus() {
|
|
|
150
150
|
return typeof source === "function" ? source() : null;
|
|
151
151
|
}
|
|
152
152
|
//#endregion
|
|
153
|
+
//#region src/kernel/moleculer/agent-ui-unlock.ts
|
|
154
|
+
/**
|
|
155
|
+
* Agent UI remote unlock tickets (D821).
|
|
156
|
+
*
|
|
157
|
+
* A hub admin mints a short-lived HMAC ticket bound to one agent `nodeId`.
|
|
158
|
+
* The agent redeems it once for a tab session Bearer — the cluster secret
|
|
159
|
+
* stays a mesh / pairing credential and is not pasted into the browser for
|
|
160
|
+
* daily unlock.
|
|
161
|
+
*
|
|
162
|
+
* K = SHA-256(cluster secret) — same as mesh join (D802)
|
|
163
|
+
* ticket = base64url(JSON payload) + '.' + base64url(HMAC-SHA256(K, DOMAIN|payloadB64))
|
|
164
|
+
* payload = { v: 1, nodeId, exp (ms), jti }
|
|
165
|
+
*/
|
|
166
|
+
var AGENT_UI_UNLOCK_DOMAIN = "camstack-agent-ui-unlock/v1";
|
|
167
|
+
var AGENT_UI_UNLOCK_VERSION = 1;
|
|
168
|
+
/** Ticket lifetime — long enough for a redirect hop, short enough to steal poorly. */
|
|
169
|
+
var AGENT_UI_UNLOCK_TTL_MS = 5 * 6e4;
|
|
170
|
+
/**
|
|
171
|
+
* Cluster settings key: extra origins allowed as `returnTo` for Continue-with-hub
|
|
172
|
+
* (NPM hostnames that are not `:4444` on a LAN IP). Comma-separated origins.
|
|
173
|
+
*/
|
|
174
|
+
var AGENT_DASHBOARD_ORIGINS_FIELD = "agentDashboardOrigins";
|
|
175
|
+
/** In-memory spent `jti` until `exp` (ms). */
|
|
176
|
+
var UnlockTicketJtiStore = class {
|
|
177
|
+
spent = /* @__PURE__ */ new Map();
|
|
178
|
+
isSpent(jti, nowMs = Date.now()) {
|
|
179
|
+
this.gc(nowMs);
|
|
180
|
+
return this.spent.has(jti);
|
|
181
|
+
}
|
|
182
|
+
/** Record a jti as used until `exp`. Returns false if already spent. */
|
|
183
|
+
consume(jti, exp, nowMs = Date.now()) {
|
|
184
|
+
this.gc(nowMs);
|
|
185
|
+
if (this.spent.has(jti)) return false;
|
|
186
|
+
this.spent.set(jti, exp);
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
/** Test helper. */
|
|
190
|
+
size() {
|
|
191
|
+
return this.spent.size;
|
|
192
|
+
}
|
|
193
|
+
gc(nowMs) {
|
|
194
|
+
for (const [jti, exp] of this.spent) if (exp <= nowMs) this.spent.delete(jti);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
function mintAgentUiUnlockTicket(input) {
|
|
198
|
+
const nowMs = input.nowMs ?? Date.now();
|
|
199
|
+
const ttl = Math.min(Math.max(1e3, input.ttlMs ?? 3e5), AGENT_UI_UNLOCK_TTL_MS);
|
|
200
|
+
const payload = {
|
|
201
|
+
v: 1,
|
|
202
|
+
nodeId: input.nodeId,
|
|
203
|
+
exp: nowMs + ttl,
|
|
204
|
+
jti: input.jti ?? (0, node_crypto.randomBytes)(16).toString("base64url")
|
|
205
|
+
};
|
|
206
|
+
const payloadB64 = Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
207
|
+
return `${payloadB64}.${sign(input.secretHash, payloadB64)}`;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Verify a ticket under `secretHash`. Returns the payload, or `null` when the
|
|
211
|
+
* signature, shape, expiry or nodeId fails (no reason string — refuse quietly).
|
|
212
|
+
*/
|
|
213
|
+
function verifyAgentUiUnlockTicket(secretHash, ticket, options) {
|
|
214
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
215
|
+
const dot = ticket.indexOf(".");
|
|
216
|
+
if (dot <= 0 || dot === ticket.length - 1) return null;
|
|
217
|
+
const payloadB64 = ticket.slice(0, dot);
|
|
218
|
+
const sig = ticket.slice(dot + 1);
|
|
219
|
+
if (!sigsEqual(sign(secretHash, payloadB64), sig)) return null;
|
|
220
|
+
let parsed;
|
|
221
|
+
try {
|
|
222
|
+
parsed = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf8"));
|
|
223
|
+
} catch {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
const payload = parsePayload(parsed);
|
|
227
|
+
if (payload === null) return null;
|
|
228
|
+
if (payload.exp <= nowMs) return null;
|
|
229
|
+
if (payload.nodeId !== options.expectedNodeId) return null;
|
|
230
|
+
return payload;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* True when `returnTo` may receive a ticket redirect. Default: any http(s)
|
|
234
|
+
* origin whose port is 4444. Extra origins come from
|
|
235
|
+
* {@link AGENT_DASHBOARD_ORIGINS_FIELD} (exact origin match).
|
|
236
|
+
*/
|
|
237
|
+
function isAllowedAgentDashboardReturnTo(returnTo, extraOrigins = []) {
|
|
238
|
+
let url;
|
|
239
|
+
try {
|
|
240
|
+
url = new URL(returnTo);
|
|
241
|
+
} catch {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
245
|
+
if (url.username !== "" || url.password !== "") return false;
|
|
246
|
+
if (url.pathname !== "/" && url.pathname !== "") return false;
|
|
247
|
+
if (url.port === "4444") return true;
|
|
248
|
+
const origin = url.origin;
|
|
249
|
+
return extraOrigins.some((o) => o === origin);
|
|
250
|
+
}
|
|
251
|
+
/** Parse a stored comma/whitespace-separated origins list. */
|
|
252
|
+
function parseAgentDashboardOrigins(stored) {
|
|
253
|
+
if (typeof stored !== "string" || stored.trim().length === 0) return [];
|
|
254
|
+
const out = [];
|
|
255
|
+
for (const part of stored.split(/[,\s]+/)) {
|
|
256
|
+
const t = part.trim();
|
|
257
|
+
if (t.length === 0) continue;
|
|
258
|
+
try {
|
|
259
|
+
const u = new URL(t);
|
|
260
|
+
if (u.protocol === "http:" || u.protocol === "https:") out.push(u.origin);
|
|
261
|
+
} catch {}
|
|
262
|
+
}
|
|
263
|
+
return out;
|
|
264
|
+
}
|
|
265
|
+
function sign(secretHash, payloadB64) {
|
|
266
|
+
return (0, node_crypto.createHmac)("sha256", Buffer.from(secretHash, "utf8")).update(`${AGENT_UI_UNLOCK_DOMAIN}|${payloadB64}`, "utf8").digest("base64url");
|
|
267
|
+
}
|
|
268
|
+
function sigsEqual(expected, presented) {
|
|
269
|
+
const a = Buffer.from(expected, "utf8");
|
|
270
|
+
const b = Buffer.from(presented, "utf8");
|
|
271
|
+
if (a.length !== b.length) return false;
|
|
272
|
+
return (0, node_crypto.timingSafeEqual)(a, b);
|
|
273
|
+
}
|
|
274
|
+
function parsePayload(value) {
|
|
275
|
+
if (typeof value !== "object" || value === null) return null;
|
|
276
|
+
const rec = value;
|
|
277
|
+
if (rec["v"] !== 1) return null;
|
|
278
|
+
const nodeId = rec["nodeId"];
|
|
279
|
+
const exp = rec["exp"];
|
|
280
|
+
const jti = rec["jti"];
|
|
281
|
+
if (typeof nodeId !== "string" || nodeId.length === 0) return null;
|
|
282
|
+
if (typeof exp !== "number" || !Number.isFinite(exp)) return null;
|
|
283
|
+
if (typeof jti !== "string" || jti.length === 0) return null;
|
|
284
|
+
return {
|
|
285
|
+
v: 1,
|
|
286
|
+
nodeId,
|
|
287
|
+
exp,
|
|
288
|
+
jti
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//#endregion
|
|
153
292
|
//#region src/kernel/moleculer/mesh-mtls/mesh-ca.ts
|
|
154
293
|
require_x509_es.cryptoProvider.set(node_crypto.webcrypto);
|
|
155
294
|
var MS_PER_DAY = 864e5;
|
|
@@ -87660,7 +87799,7 @@ function isTlsSocket(socket) {
|
|
|
87660
87799
|
* - no marker → the secret is MANDATORY (D802): the keeper asks
|
|
87661
87800
|
* its owner to generate one (`generateSecret`), and
|
|
87662
87801
|
* until that succeeds the gate is `off` — no node can
|
|
87663
|
-
* authenticate
|
|
87802
|
+
* authenticate (mesh auth is always enforced, D821);
|
|
87664
87803
|
* - marker + value → `on` — nodes prove the secret;
|
|
87665
87804
|
* - marker, no answer → `unknown` — refused, retryably, and retried here.
|
|
87666
87805
|
* A locked keychain or a value lost to a reset NEVER opens the gate, and
|
|
@@ -87723,7 +87862,7 @@ var ClusterSecretKeeper = class {
|
|
|
87723
87862
|
reason: `settings unreadable: ${errText(err)}`
|
|
87724
87863
|
};
|
|
87725
87864
|
}
|
|
87726
|
-
setProcessMeshAuthMode(
|
|
87865
|
+
setProcessMeshAuthMode("enforced");
|
|
87727
87866
|
const stored = section[CLUSTER_SECRET_FIELD];
|
|
87728
87867
|
if (stored === void 0 || stored === null || stored === "") return { kind: "off" };
|
|
87729
87868
|
if (!require_dist.isSecretMarker(stored)) return {
|
|
@@ -87791,28 +87930,48 @@ function errText(err) {
|
|
|
87791
87930
|
//#endregion
|
|
87792
87931
|
//#region src/builtins/system-config/mesh-actions.ts
|
|
87793
87932
|
/**
|
|
87794
|
-
* System → Cluster — mint a single-use mesh join token (Release A)
|
|
87933
|
+
* System → Cluster — mint a single-use mesh join token (Release A) and
|
|
87934
|
+
* agent-ui unlock tickets (D821).
|
|
87795
87935
|
*/
|
|
87796
|
-
var systemConfigMeshActions = require_dist.defineCustomActions({
|
|
87797
|
-
|
|
87798
|
-
|
|
87799
|
-
|
|
87800
|
-
|
|
87801
|
-
|
|
87802
|
-
|
|
87803
|
-
|
|
87804
|
-
|
|
87805
|
-
|
|
87806
|
-
|
|
87807
|
-
|
|
87808
|
-
|
|
87809
|
-
|
|
87810
|
-
|
|
87811
|
-
|
|
87812
|
-
|
|
87813
|
-
|
|
87814
|
-
|
|
87815
|
-
|
|
87936
|
+
var systemConfigMeshActions = require_dist.defineCustomActions({
|
|
87937
|
+
mintJoinToken: require_dist.customAction(zod.z.object({
|
|
87938
|
+
/** Optional pinned node id for the CSR CN. */
|
|
87939
|
+
nodeId: zod.z.string().min(1).optional(),
|
|
87940
|
+
/** Override hub HTTPS base (default: local-network publicEndpoint). */
|
|
87941
|
+
hubUrl: zod.z.string().url().optional(),
|
|
87942
|
+
/** Override `host:6000` clear mesh address carried in the token. */
|
|
87943
|
+
hubMeshAddress: zod.z.string().min(3).optional(),
|
|
87944
|
+
/** Seconds until expiry; capped at 1 h. */
|
|
87945
|
+
ttlSec: zod.z.number().int().positive().max(3600).optional()
|
|
87946
|
+
}).optional(), zod.z.object({
|
|
87947
|
+
token: zod.z.string().min(1),
|
|
87948
|
+
exp: zod.z.number().int(),
|
|
87949
|
+
hubUrl: zod.z.string(),
|
|
87950
|
+
hubMeshAddress: zod.z.string(),
|
|
87951
|
+
caFingerprint: zod.z.string(),
|
|
87952
|
+
nodeId: zod.z.string().optional()
|
|
87953
|
+
}), {
|
|
87954
|
+
kind: "mutation",
|
|
87955
|
+
auth: "admin"
|
|
87956
|
+
}),
|
|
87957
|
+
/** Hub admin → short-lived ticket the agent redeems for a tab session (D821). */
|
|
87958
|
+
mintAgentUiUnlockTicket: require_dist.customAction(zod.z.object({
|
|
87959
|
+
nodeId: zod.z.string().min(1),
|
|
87960
|
+
/**
|
|
87961
|
+
* Preferred agent dashboard base (`http://host:4444`). When set, the
|
|
87962
|
+
* answer includes `dashboardUrl` with `?ticket=` already attached.
|
|
87963
|
+
*/
|
|
87964
|
+
dashboardBaseUrl: zod.z.string().url().optional()
|
|
87965
|
+
}), zod.z.object({
|
|
87966
|
+
ticket: zod.z.string().min(1),
|
|
87967
|
+
exp: zod.z.number().int(),
|
|
87968
|
+
nodeId: zod.z.string().min(1),
|
|
87969
|
+
dashboardUrl: zod.z.string().url().optional()
|
|
87970
|
+
}), {
|
|
87971
|
+
kind: "mutation",
|
|
87972
|
+
auth: "admin"
|
|
87973
|
+
})
|
|
87974
|
+
});
|
|
87816
87975
|
//#endregion
|
|
87817
87976
|
//#region src/builtins/system-config/system-config.addon.ts
|
|
87818
87977
|
/**
|
|
@@ -87877,7 +88036,8 @@ var KEY_TO_SECTION = {
|
|
|
87877
88036
|
trustedNetworks: "auth",
|
|
87878
88037
|
[CLUSTER_SECRET_FIELD]: "cluster",
|
|
87879
88038
|
[MESH_AUTH_MODE_FIELD]: "cluster",
|
|
87880
|
-
[MESH_CLEAR_PORT_FIELD]: "cluster"
|
|
88039
|
+
[MESH_CLEAR_PORT_FIELD]: "cluster",
|
|
88040
|
+
[AGENT_DASHBOARD_ORIGINS_FIELD]: "cluster"
|
|
87881
88041
|
};
|
|
87882
88042
|
/** Bytes of a generated cluster secret (D802) — 256 bits, base64url (43 chars). */
|
|
87883
88043
|
var GENERATED_SECRET_BYTES = 32;
|
|
@@ -87886,10 +88046,10 @@ var STATE_LABELS = {
|
|
|
87886
88046
|
legacy: "legacy hash only — update the agent",
|
|
87887
88047
|
unauthenticated: "not authenticated — enter the cluster secret in this agent"
|
|
87888
88048
|
};
|
|
87889
|
-
/** The Cluster page's live line per node (D802). */
|
|
88049
|
+
/** The Cluster page's live line per node (D802). Mode is always enforced (D821). */
|
|
87890
88050
|
function describeMeshStatus(status) {
|
|
87891
88051
|
if (status === null) return "The mesh status is available on the hub only.";
|
|
87892
|
-
const head =
|
|
88052
|
+
const head = "Enforced: a node that has not authenticated is refused.";
|
|
87893
88053
|
if (status.nodes.length === 0) return `${head}\nNo other node is connected.`;
|
|
87894
88054
|
return `${head}\n${status.nodes.map((n) => `• ${n.nodeId}: ${STATE_LABELS[n.state] ?? n.state}`).join("\n")}`;
|
|
87895
88055
|
}
|
|
@@ -87920,6 +88080,9 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
87920
88080
|
this.ctx.logger.info("Mesh authentication is now ENFORCED", { meta: { reason } });
|
|
87921
88081
|
});
|
|
87922
88082
|
await this.clusterSecretKeeper.start();
|
|
88083
|
+
try {
|
|
88084
|
+
await this.writeMeshAuthMode("enforced");
|
|
88085
|
+
} catch {}
|
|
87923
88086
|
this.meshCaKeeper = new MeshCaKeeper({
|
|
87924
88087
|
secrets: this.systemSecrets(),
|
|
87925
88088
|
readClusterSection: async () => await this.ctx.settings?.getSection("cluster") ?? {},
|
|
@@ -87934,7 +88097,10 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
87934
88097
|
this.ctx.logger.info("Initialized — exposes yml-backed sections via getGlobalSettings");
|
|
87935
88098
|
return {
|
|
87936
88099
|
customActions: systemConfigMeshActions,
|
|
87937
|
-
actionHandlers: {
|
|
88100
|
+
actionHandlers: {
|
|
88101
|
+
mintJoinToken: async (input) => this.mintJoinToken(parseMintJoinTokenInput(input)),
|
|
88102
|
+
mintAgentUiUnlockTicket: async (input) => this.mintAgentUiUnlock(parseMintUnlockInput(input))
|
|
88103
|
+
}
|
|
87938
88104
|
};
|
|
87939
88105
|
}
|
|
87940
88106
|
async onShutdown() {
|
|
@@ -87987,6 +88153,41 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
87987
88153
|
...input.nodeId !== void 0 ? { nodeId: input.nodeId } : {}
|
|
87988
88154
|
};
|
|
87989
88155
|
}
|
|
88156
|
+
/** D821 — short-lived ticket for the agent's `:4444` unlock session. */
|
|
88157
|
+
async mintAgentUiUnlock(input) {
|
|
88158
|
+
const secrets = this.systemSecrets();
|
|
88159
|
+
if (secrets === null) throw new Error("system-config: no keychain door — cannot mint an unlock ticket");
|
|
88160
|
+
const entry = (await secrets.resolve([require_constants$8.CLUSTER_SECRET_REF]))[require_constants$8.CLUSTER_SECRET_REF];
|
|
88161
|
+
if (entry?.kind !== "value") throw new Error("system-config: cluster secret is not available — cannot mint an unlock ticket");
|
|
88162
|
+
if (input.dashboardBaseUrl !== void 0) {
|
|
88163
|
+
const origins = await this.readAgentDashboardOrigins();
|
|
88164
|
+
if (!isAllowedAgentDashboardReturnTo(input.dashboardBaseUrl, origins)) throw new Error("dashboardBaseUrl is not an allowed agent dashboard origin (:4444 or agentDashboardOrigins)");
|
|
88165
|
+
}
|
|
88166
|
+
const ticket = mintAgentUiUnlockTicket({
|
|
88167
|
+
secretHash: require_constants$8.hashClusterSecret(entry.value),
|
|
88168
|
+
nodeId: input.nodeId
|
|
88169
|
+
});
|
|
88170
|
+
const payloadJson = Buffer.from(ticket.split(".")[0] ?? "", "base64url").toString("utf8");
|
|
88171
|
+
const exp = JSON.parse(payloadJson).exp ?? 0;
|
|
88172
|
+
const dashboardUrl = input.dashboardBaseUrl === void 0 ? void 0 : (() => {
|
|
88173
|
+
const u = new URL(input.dashboardBaseUrl);
|
|
88174
|
+
u.searchParams.set("ticket", ticket);
|
|
88175
|
+
return u.toString();
|
|
88176
|
+
})();
|
|
88177
|
+
return {
|
|
88178
|
+
ticket,
|
|
88179
|
+
exp,
|
|
88180
|
+
nodeId: input.nodeId,
|
|
88181
|
+
...dashboardUrl !== void 0 ? { dashboardUrl } : {}
|
|
88182
|
+
};
|
|
88183
|
+
}
|
|
88184
|
+
async readAgentDashboardOrigins() {
|
|
88185
|
+
try {
|
|
88186
|
+
return parseAgentDashboardOrigins((await this.ctx.settings?.getSection("cluster"))?.[AGENT_DASHBOARD_ORIGINS_FIELD]);
|
|
88187
|
+
} catch {
|
|
88188
|
+
return [];
|
|
88189
|
+
}
|
|
88190
|
+
}
|
|
87990
88191
|
async resolveHubUrl() {
|
|
87991
88192
|
try {
|
|
87992
88193
|
const book = await this.ctx.api?.localNetwork?.getAddresses?.query({ scheme: "https" });
|
|
@@ -88106,20 +88307,6 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
88106
88307
|
label: "Cluster secret",
|
|
88107
88308
|
description: "Mandatory — generated by the hub at first boot and stored in the keychain. To pair an agent: Reveal and copy it here, then enter it in the agent (its status page, or the desktop setup window). Saving a new value rotates it: every agent must then be given the new one."
|
|
88108
88309
|
},
|
|
88109
|
-
{
|
|
88110
|
-
type: "select",
|
|
88111
|
-
key: MESH_AUTH_MODE_FIELD,
|
|
88112
|
-
label: "Agents without the secret",
|
|
88113
|
-
description: "Transition lets an agent that has not authenticated keep working (with a warning) while you give each agent the secret; it ends by itself once every known agent has authenticated. Enforced refuses it.",
|
|
88114
|
-
default: "transition",
|
|
88115
|
-
options: [{
|
|
88116
|
-
value: "transition",
|
|
88117
|
-
label: "Transition — allow, warn"
|
|
88118
|
-
}, {
|
|
88119
|
-
value: "enforced",
|
|
88120
|
-
label: "Enforced — refuse"
|
|
88121
|
-
}]
|
|
88122
|
-
},
|
|
88123
88310
|
{
|
|
88124
88311
|
type: "select",
|
|
88125
88312
|
key: MESH_CLEAR_PORT_FIELD,
|
|
@@ -88141,6 +88328,12 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
88141
88328
|
content: describeMeshStatus(getProcessMeshAuthStatus()),
|
|
88142
88329
|
variant: "info"
|
|
88143
88330
|
},
|
|
88331
|
+
{
|
|
88332
|
+
type: "string",
|
|
88333
|
+
key: AGENT_DASHBOARD_ORIGINS_FIELD,
|
|
88334
|
+
label: "Agent dashboard origins (NPM)",
|
|
88335
|
+
description: "Extra origins allowed for Continue-with-hub unlock redirects (comma-separated), e.g. https://agent.example.com. LAN agents on :4444 are always allowed."
|
|
88336
|
+
},
|
|
88144
88337
|
{
|
|
88145
88338
|
type: "addon-action-button",
|
|
88146
88339
|
key: "mintJoinTokenAction",
|
|
@@ -88213,15 +88406,14 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
88213
88406
|
* The cluster secret's save path: the value goes to the keychain (owner
|
|
88214
88407
|
* `system`), the row gets the marker; `''` / a view keeps. `$secretClear` is
|
|
88215
88408
|
* REFUSED: the secret is mandatory (D802). A value the keychain cannot store
|
|
88216
|
-
* is REFUSED — never written inline (D787, P5).
|
|
88409
|
+
* is REFUSED — never written inline (D787, P5). Mesh auth mode is always
|
|
88410
|
+
* enforced (D821) — a legacy `meshAuth` in the patch is ignored.
|
|
88217
88411
|
*/
|
|
88218
88412
|
async writeClusterSection(patch) {
|
|
88219
|
-
const { [MESH_AUTH_MODE_FIELD]:
|
|
88413
|
+
const { [MESH_AUTH_MODE_FIELD]: _legacyMode, [MESH_CLEAR_PORT_FIELD]: clearPort, [AGENT_DASHBOARD_ORIGINS_FIELD]: dashboardOrigins, ...secretPatch } = patch;
|
|
88220
88414
|
if (clearPort !== void 0) await this.writeMeshClearPort(clearPort);
|
|
88221
|
-
if (
|
|
88222
|
-
|
|
88223
|
-
await this.writeMeshAuthMode(mode);
|
|
88224
|
-
}
|
|
88415
|
+
if (dashboardOrigins !== void 0) await this.ctx.settings.setSection("cluster", { [AGENT_DASHBOARD_ORIGINS_FIELD]: typeof dashboardOrigins === "string" ? dashboardOrigins : "" });
|
|
88416
|
+
await this.writeMeshAuthMode("enforced");
|
|
88225
88417
|
if (Object.keys(secretPatch).length === 0) return;
|
|
88226
88418
|
if (require_dist.isSecretClear(secretPatch["clusterSecret"])) throw new Error("The cluster secret is mandatory and cannot be cleared — save a new value to rotate it");
|
|
88227
88419
|
await this.storeClusterSecret(secretPatch);
|
|
@@ -88249,16 +88441,15 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
88249
88441
|
await applyProcessMeshClearPort(value);
|
|
88250
88442
|
this.ctx.logger.info("Mesh clear port switched", { meta: { mode: value } });
|
|
88251
88443
|
}
|
|
88252
|
-
/**
|
|
88444
|
+
/** Persist + publish mesh auth mode (always `enforced` after D821). */
|
|
88253
88445
|
async writeMeshAuthMode(mode) {
|
|
88254
88446
|
await this.ctx.settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: mode });
|
|
88255
|
-
|
|
88447
|
+
setProcessMeshAuthMode(mode);
|
|
88256
88448
|
}
|
|
88257
88449
|
/**
|
|
88258
88450
|
* First boot, or a keychain reset that cleared the marker (D802): a fresh
|
|
88259
|
-
* random secret, stored like an operator save.
|
|
88260
|
-
*
|
|
88261
|
-
* with no agent yet, the hub's auto-enforce ends it at once.
|
|
88451
|
+
* random secret, stored like an operator save. Mesh auth stays enforced
|
|
88452
|
+
* (D821) — every agent must present the secret; there is no transition window.
|
|
88262
88453
|
*/
|
|
88263
88454
|
async generateClusterSecret() {
|
|
88264
88455
|
const settings = this.ctx.settings;
|
|
@@ -88273,7 +88464,8 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
|
|
|
88273
88464
|
if (existing?.kind !== "missing") throw new Error(`the keychain cannot answer for the cluster secret (${existing?.kind ?? "no answer"})`);
|
|
88274
88465
|
const value = (0, node_crypto.randomBytes)(GENERATED_SECRET_BYTES).toString("base64url");
|
|
88275
88466
|
await this.storeClusterSecret({ [CLUSTER_SECRET_FIELD]: value });
|
|
88276
|
-
await settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: "
|
|
88467
|
+
await settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: "enforced" });
|
|
88468
|
+
setProcessMeshAuthMode("enforced");
|
|
88277
88469
|
}
|
|
88278
88470
|
async storeClusterSecret(patch) {
|
|
88279
88471
|
const settings = this.ctx.settings;
|
|
@@ -88306,6 +88498,16 @@ function parseMintJoinTokenInput(input) {
|
|
|
88306
88498
|
if (typeof ttlSec === "number") out.ttlSec = ttlSec;
|
|
88307
88499
|
return out;
|
|
88308
88500
|
}
|
|
88501
|
+
function parseMintUnlockInput(input) {
|
|
88502
|
+
if (input === null || typeof input !== "object") throw new Error("system-config: mintAgentUiUnlockTicket requires { nodeId }");
|
|
88503
|
+
const nodeId = Reflect.get(input, "nodeId");
|
|
88504
|
+
if (typeof nodeId !== "string" || nodeId.length === 0) throw new Error("system-config: mintAgentUiUnlockTicket requires { nodeId }");
|
|
88505
|
+
const dashboardBaseUrl = Reflect.get(input, "dashboardBaseUrl");
|
|
88506
|
+
return {
|
|
88507
|
+
nodeId,
|
|
88508
|
+
...typeof dashboardBaseUrl === "string" ? { dashboardBaseUrl } : {}
|
|
88509
|
+
};
|
|
88510
|
+
}
|
|
88309
88511
|
/** Read `exp` from an unencrypted JWT payload (no verify — already minted here). */
|
|
88310
88512
|
function readJwtExp(token) {
|
|
88311
88513
|
const parts = token.split(".");
|
|
@@ -88317,6 +88519,10 @@ function readJwtExp(token) {
|
|
|
88317
88519
|
return typeof exp === "number" ? exp : 0;
|
|
88318
88520
|
}
|
|
88319
88521
|
//#endregion
|
|
88522
|
+
exports.AGENT_DASHBOARD_ORIGINS_FIELD = AGENT_DASHBOARD_ORIGINS_FIELD;
|
|
88523
|
+
exports.AGENT_UI_UNLOCK_DOMAIN = AGENT_UI_UNLOCK_DOMAIN;
|
|
88524
|
+
exports.AGENT_UI_UNLOCK_TTL_MS = AGENT_UI_UNLOCK_TTL_MS;
|
|
88525
|
+
exports.AGENT_UI_UNLOCK_VERSION = AGENT_UI_UNLOCK_VERSION;
|
|
88320
88526
|
exports.Errors = Errors;
|
|
88321
88527
|
exports.JoinTokenJtiStore = JoinTokenJtiStore;
|
|
88322
88528
|
exports.MESH_AUTH_MODE_FIELD = MESH_AUTH_MODE_FIELD;
|
|
@@ -88328,6 +88534,7 @@ exports.ServiceBroker = ServiceBroker;
|
|
|
88328
88534
|
exports.SystemConfigAddon = SystemConfigAddon;
|
|
88329
88535
|
exports.default = SystemConfigAddon;
|
|
88330
88536
|
exports.TlsTcpTransporter = TlsTcpTransporter;
|
|
88537
|
+
exports.UnlockTicketJtiStore = UnlockTicketJtiStore;
|
|
88331
88538
|
exports.applyProcessMeshClearPort = applyProcessMeshClearPort;
|
|
88332
88539
|
exports.caFingerprint = caFingerprint;
|
|
88333
88540
|
exports.caFingerprintCompact = caFingerprintCompact;
|
|
@@ -88343,12 +88550,15 @@ exports.getProcessMeshAuthMode = getProcessMeshAuthMode;
|
|
|
88343
88550
|
exports.getProcessMeshAuthStatus = getProcessMeshAuthStatus;
|
|
88344
88551
|
exports.getProcessMeshCaState = getProcessMeshCaState;
|
|
88345
88552
|
exports.getProcessNodeMeshTransport = getProcessNodeMeshTransport;
|
|
88553
|
+
exports.isAllowedAgentDashboardReturnTo = isAllowedAgentDashboardReturnTo;
|
|
88346
88554
|
exports.isMeshAuthMode = isMeshAuthMode;
|
|
88347
88555
|
exports.issueMeshLeafForNode = issueMeshLeafForNode;
|
|
88348
88556
|
exports.issueMeshLeafFromCsr = issueMeshLeafFromCsr;
|
|
88349
88557
|
exports.loadMeshCa = loadMeshCa;
|
|
88558
|
+
exports.mintAgentUiUnlockTicket = mintAgentUiUnlockTicket;
|
|
88350
88559
|
exports.mintMeshJoinToken = mintMeshJoinToken;
|
|
88351
88560
|
exports.normalizeIp = normalizeIp;
|
|
88561
|
+
exports.parseAgentDashboardOrigins = parseAgentDashboardOrigins;
|
|
88352
88562
|
exports.parseCidrList = parseCidrList;
|
|
88353
88563
|
exports.parseMeshAuthMode = parseMeshAuthMode;
|
|
88354
88564
|
exports.processJoinTokenJtiStore = processJoinTokenJtiStore;
|
|
@@ -88362,4 +88572,5 @@ exports.setProcessMeshClearPortControl = setProcessMeshClearPortControl;
|
|
|
88362
88572
|
exports.setProcessMeshEnforcer = setProcessMeshEnforcer;
|
|
88363
88573
|
exports.setProcessMeshTlsEnabler = setProcessMeshTlsEnabler;
|
|
88364
88574
|
exports.systemConfigMeshActions = systemConfigMeshActions;
|
|
88575
|
+
exports.verifyAgentUiUnlockTicket = verifyAgentUiUnlockTicket;
|
|
88365
88576
|
exports.verifyMeshJoinToken = verifyMeshJoinToken;
|
|
@@ -4,7 +4,7 @@ import { n as require_safe_buffer, t as require_ms } from "../../ms-DlIWNkkk.mjs
|
|
|
4
4
|
import { a as MESH_CA_FIELD, c as MESH_CA_VALIDITY_DAYS, f as CLUSTER_SECRET_REF, i as MESH_CA_COMMON_NAME, l as MESH_JOIN_TOKEN_MAX_TTL_SEC, n as DEFAULT_HUB_TCP_PORT, o as MESH_CA_KEY_REF, r as DEFAULT_HUB_TLS_TCP_PORT, s as MESH_CA_SETTINGS_KEY, t as CLIENT_AUTH_OID, u as SERVER_AUTH_OID, x as setProcessClusterSecretGate, y as hashClusterSecret } from "../../constants-D5z4EwY8.mjs";
|
|
5
5
|
import { a as KeyUsagesExtension, c as Pkcs10CertificateRequestGenerator, d as X509Certificate$1, f as X509CertificateGenerator, i as KeyUsageFlags, n as BasicConstraintsExtension, o as PemConverter, p as cryptoProvider, r as ExtendedKeyUsageExtension, s as Pkcs10CertificateRequest, t as AuthorityKeyIdentifierExtension, u as SubjectKeyIdentifierExtension } from "../../x509.es-Xf3K_brW.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
-
import { X509Certificate, createHash, randomBytes, webcrypto } from "node:crypto";
|
|
7
|
+
import { X509Certificate, createHash, createHmac, randomBytes, timingSafeEqual, webcrypto } from "node:crypto";
|
|
8
8
|
import { BlockList, isIP } from "node:net";
|
|
9
9
|
import { lstat, readdir, readlink, realpath } from "node:fs/promises";
|
|
10
10
|
import { posix, win32 } from "node:path";
|
|
@@ -141,6 +141,145 @@ function getProcessMeshAuthStatus() {
|
|
|
141
141
|
return typeof source === "function" ? source() : null;
|
|
142
142
|
}
|
|
143
143
|
//#endregion
|
|
144
|
+
//#region src/kernel/moleculer/agent-ui-unlock.ts
|
|
145
|
+
/**
|
|
146
|
+
* Agent UI remote unlock tickets (D821).
|
|
147
|
+
*
|
|
148
|
+
* A hub admin mints a short-lived HMAC ticket bound to one agent `nodeId`.
|
|
149
|
+
* The agent redeems it once for a tab session Bearer — the cluster secret
|
|
150
|
+
* stays a mesh / pairing credential and is not pasted into the browser for
|
|
151
|
+
* daily unlock.
|
|
152
|
+
*
|
|
153
|
+
* K = SHA-256(cluster secret) — same as mesh join (D802)
|
|
154
|
+
* ticket = base64url(JSON payload) + '.' + base64url(HMAC-SHA256(K, DOMAIN|payloadB64))
|
|
155
|
+
* payload = { v: 1, nodeId, exp (ms), jti }
|
|
156
|
+
*/
|
|
157
|
+
var AGENT_UI_UNLOCK_DOMAIN = "camstack-agent-ui-unlock/v1";
|
|
158
|
+
var AGENT_UI_UNLOCK_VERSION = 1;
|
|
159
|
+
/** Ticket lifetime — long enough for a redirect hop, short enough to steal poorly. */
|
|
160
|
+
var AGENT_UI_UNLOCK_TTL_MS = 5 * 6e4;
|
|
161
|
+
/**
|
|
162
|
+
* Cluster settings key: extra origins allowed as `returnTo` for Continue-with-hub
|
|
163
|
+
* (NPM hostnames that are not `:4444` on a LAN IP). Comma-separated origins.
|
|
164
|
+
*/
|
|
165
|
+
var AGENT_DASHBOARD_ORIGINS_FIELD = "agentDashboardOrigins";
|
|
166
|
+
/** In-memory spent `jti` until `exp` (ms). */
|
|
167
|
+
var UnlockTicketJtiStore = class {
|
|
168
|
+
spent = /* @__PURE__ */ new Map();
|
|
169
|
+
isSpent(jti, nowMs = Date.now()) {
|
|
170
|
+
this.gc(nowMs);
|
|
171
|
+
return this.spent.has(jti);
|
|
172
|
+
}
|
|
173
|
+
/** Record a jti as used until `exp`. Returns false if already spent. */
|
|
174
|
+
consume(jti, exp, nowMs = Date.now()) {
|
|
175
|
+
this.gc(nowMs);
|
|
176
|
+
if (this.spent.has(jti)) return false;
|
|
177
|
+
this.spent.set(jti, exp);
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
/** Test helper. */
|
|
181
|
+
size() {
|
|
182
|
+
return this.spent.size;
|
|
183
|
+
}
|
|
184
|
+
gc(nowMs) {
|
|
185
|
+
for (const [jti, exp] of this.spent) if (exp <= nowMs) this.spent.delete(jti);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
function mintAgentUiUnlockTicket(input) {
|
|
189
|
+
const nowMs = input.nowMs ?? Date.now();
|
|
190
|
+
const ttl = Math.min(Math.max(1e3, input.ttlMs ?? 3e5), AGENT_UI_UNLOCK_TTL_MS);
|
|
191
|
+
const payload = {
|
|
192
|
+
v: 1,
|
|
193
|
+
nodeId: input.nodeId,
|
|
194
|
+
exp: nowMs + ttl,
|
|
195
|
+
jti: input.jti ?? randomBytes(16).toString("base64url")
|
|
196
|
+
};
|
|
197
|
+
const payloadB64 = Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
198
|
+
return `${payloadB64}.${sign(input.secretHash, payloadB64)}`;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Verify a ticket under `secretHash`. Returns the payload, or `null` when the
|
|
202
|
+
* signature, shape, expiry or nodeId fails (no reason string — refuse quietly).
|
|
203
|
+
*/
|
|
204
|
+
function verifyAgentUiUnlockTicket(secretHash, ticket, options) {
|
|
205
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
206
|
+
const dot = ticket.indexOf(".");
|
|
207
|
+
if (dot <= 0 || dot === ticket.length - 1) return null;
|
|
208
|
+
const payloadB64 = ticket.slice(0, dot);
|
|
209
|
+
const sig = ticket.slice(dot + 1);
|
|
210
|
+
if (!sigsEqual(sign(secretHash, payloadB64), sig)) return null;
|
|
211
|
+
let parsed;
|
|
212
|
+
try {
|
|
213
|
+
parsed = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf8"));
|
|
214
|
+
} catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const payload = parsePayload(parsed);
|
|
218
|
+
if (payload === null) return null;
|
|
219
|
+
if (payload.exp <= nowMs) return null;
|
|
220
|
+
if (payload.nodeId !== options.expectedNodeId) return null;
|
|
221
|
+
return payload;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* True when `returnTo` may receive a ticket redirect. Default: any http(s)
|
|
225
|
+
* origin whose port is 4444. Extra origins come from
|
|
226
|
+
* {@link AGENT_DASHBOARD_ORIGINS_FIELD} (exact origin match).
|
|
227
|
+
*/
|
|
228
|
+
function isAllowedAgentDashboardReturnTo(returnTo, extraOrigins = []) {
|
|
229
|
+
let url;
|
|
230
|
+
try {
|
|
231
|
+
url = new URL(returnTo);
|
|
232
|
+
} catch {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
236
|
+
if (url.username !== "" || url.password !== "") return false;
|
|
237
|
+
if (url.pathname !== "/" && url.pathname !== "") return false;
|
|
238
|
+
if (url.port === "4444") return true;
|
|
239
|
+
const origin = url.origin;
|
|
240
|
+
return extraOrigins.some((o) => o === origin);
|
|
241
|
+
}
|
|
242
|
+
/** Parse a stored comma/whitespace-separated origins list. */
|
|
243
|
+
function parseAgentDashboardOrigins(stored) {
|
|
244
|
+
if (typeof stored !== "string" || stored.trim().length === 0) return [];
|
|
245
|
+
const out = [];
|
|
246
|
+
for (const part of stored.split(/[,\s]+/)) {
|
|
247
|
+
const t = part.trim();
|
|
248
|
+
if (t.length === 0) continue;
|
|
249
|
+
try {
|
|
250
|
+
const u = new URL(t);
|
|
251
|
+
if (u.protocol === "http:" || u.protocol === "https:") out.push(u.origin);
|
|
252
|
+
} catch {}
|
|
253
|
+
}
|
|
254
|
+
return out;
|
|
255
|
+
}
|
|
256
|
+
function sign(secretHash, payloadB64) {
|
|
257
|
+
return createHmac("sha256", Buffer.from(secretHash, "utf8")).update(`${AGENT_UI_UNLOCK_DOMAIN}|${payloadB64}`, "utf8").digest("base64url");
|
|
258
|
+
}
|
|
259
|
+
function sigsEqual(expected, presented) {
|
|
260
|
+
const a = Buffer.from(expected, "utf8");
|
|
261
|
+
const b = Buffer.from(presented, "utf8");
|
|
262
|
+
if (a.length !== b.length) return false;
|
|
263
|
+
return timingSafeEqual(a, b);
|
|
264
|
+
}
|
|
265
|
+
function parsePayload(value) {
|
|
266
|
+
if (typeof value !== "object" || value === null) return null;
|
|
267
|
+
const rec = value;
|
|
268
|
+
if (rec["v"] !== 1) return null;
|
|
269
|
+
const nodeId = rec["nodeId"];
|
|
270
|
+
const exp = rec["exp"];
|
|
271
|
+
const jti = rec["jti"];
|
|
272
|
+
if (typeof nodeId !== "string" || nodeId.length === 0) return null;
|
|
273
|
+
if (typeof exp !== "number" || !Number.isFinite(exp)) return null;
|
|
274
|
+
if (typeof jti !== "string" || jti.length === 0) return null;
|
|
275
|
+
return {
|
|
276
|
+
v: 1,
|
|
277
|
+
nodeId,
|
|
278
|
+
exp,
|
|
279
|
+
jti
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
//#endregion
|
|
144
283
|
//#region src/kernel/moleculer/mesh-mtls/mesh-ca.ts
|
|
145
284
|
cryptoProvider.set(webcrypto);
|
|
146
285
|
var MS_PER_DAY = 864e5;
|
|
@@ -87650,7 +87789,7 @@ function isTlsSocket(socket) {
|
|
|
87650
87789
|
* - no marker → the secret is MANDATORY (D802): the keeper asks
|
|
87651
87790
|
* its owner to generate one (`generateSecret`), and
|
|
87652
87791
|
* until that succeeds the gate is `off` — no node can
|
|
87653
|
-
* authenticate
|
|
87792
|
+
* authenticate (mesh auth is always enforced, D821);
|
|
87654
87793
|
* - marker + value → `on` — nodes prove the secret;
|
|
87655
87794
|
* - marker, no answer → `unknown` — refused, retryably, and retried here.
|
|
87656
87795
|
* A locked keychain or a value lost to a reset NEVER opens the gate, and
|
|
@@ -87713,7 +87852,7 @@ var ClusterSecretKeeper = class {
|
|
|
87713
87852
|
reason: `settings unreadable: ${errText(err)}`
|
|
87714
87853
|
};
|
|
87715
87854
|
}
|
|
87716
|
-
setProcessMeshAuthMode(
|
|
87855
|
+
setProcessMeshAuthMode("enforced");
|
|
87717
87856
|
const stored = section[CLUSTER_SECRET_FIELD];
|
|
87718
87857
|
if (stored === void 0 || stored === null || stored === "") return { kind: "off" };
|
|
87719
87858
|
if (!isSecretMarker(stored)) return {
|
|
@@ -87781,28 +87920,48 @@ function errText(err) {
|
|
|
87781
87920
|
//#endregion
|
|
87782
87921
|
//#region src/builtins/system-config/mesh-actions.ts
|
|
87783
87922
|
/**
|
|
87784
|
-
* System → Cluster — mint a single-use mesh join token (Release A)
|
|
87923
|
+
* System → Cluster — mint a single-use mesh join token (Release A) and
|
|
87924
|
+
* agent-ui unlock tickets (D821).
|
|
87785
87925
|
*/
|
|
87786
|
-
var systemConfigMeshActions = defineCustomActions({
|
|
87787
|
-
|
|
87788
|
-
|
|
87789
|
-
|
|
87790
|
-
|
|
87791
|
-
|
|
87792
|
-
|
|
87793
|
-
|
|
87794
|
-
|
|
87795
|
-
|
|
87796
|
-
|
|
87797
|
-
|
|
87798
|
-
|
|
87799
|
-
|
|
87800
|
-
|
|
87801
|
-
|
|
87802
|
-
|
|
87803
|
-
|
|
87804
|
-
|
|
87805
|
-
|
|
87926
|
+
var systemConfigMeshActions = defineCustomActions({
|
|
87927
|
+
mintJoinToken: customAction(z.object({
|
|
87928
|
+
/** Optional pinned node id for the CSR CN. */
|
|
87929
|
+
nodeId: z.string().min(1).optional(),
|
|
87930
|
+
/** Override hub HTTPS base (default: local-network publicEndpoint). */
|
|
87931
|
+
hubUrl: z.string().url().optional(),
|
|
87932
|
+
/** Override `host:6000` clear mesh address carried in the token. */
|
|
87933
|
+
hubMeshAddress: z.string().min(3).optional(),
|
|
87934
|
+
/** Seconds until expiry; capped at 1 h. */
|
|
87935
|
+
ttlSec: z.number().int().positive().max(3600).optional()
|
|
87936
|
+
}).optional(), z.object({
|
|
87937
|
+
token: z.string().min(1),
|
|
87938
|
+
exp: z.number().int(),
|
|
87939
|
+
hubUrl: z.string(),
|
|
87940
|
+
hubMeshAddress: z.string(),
|
|
87941
|
+
caFingerprint: z.string(),
|
|
87942
|
+
nodeId: z.string().optional()
|
|
87943
|
+
}), {
|
|
87944
|
+
kind: "mutation",
|
|
87945
|
+
auth: "admin"
|
|
87946
|
+
}),
|
|
87947
|
+
/** Hub admin → short-lived ticket the agent redeems for a tab session (D821). */
|
|
87948
|
+
mintAgentUiUnlockTicket: customAction(z.object({
|
|
87949
|
+
nodeId: z.string().min(1),
|
|
87950
|
+
/**
|
|
87951
|
+
* Preferred agent dashboard base (`http://host:4444`). When set, the
|
|
87952
|
+
* answer includes `dashboardUrl` with `?ticket=` already attached.
|
|
87953
|
+
*/
|
|
87954
|
+
dashboardBaseUrl: z.string().url().optional()
|
|
87955
|
+
}), z.object({
|
|
87956
|
+
ticket: z.string().min(1),
|
|
87957
|
+
exp: z.number().int(),
|
|
87958
|
+
nodeId: z.string().min(1),
|
|
87959
|
+
dashboardUrl: z.string().url().optional()
|
|
87960
|
+
}), {
|
|
87961
|
+
kind: "mutation",
|
|
87962
|
+
auth: "admin"
|
|
87963
|
+
})
|
|
87964
|
+
});
|
|
87806
87965
|
//#endregion
|
|
87807
87966
|
//#region src/builtins/system-config/system-config.addon.ts
|
|
87808
87967
|
/**
|
|
@@ -87867,7 +88026,8 @@ var KEY_TO_SECTION = {
|
|
|
87867
88026
|
trustedNetworks: "auth",
|
|
87868
88027
|
[CLUSTER_SECRET_FIELD]: "cluster",
|
|
87869
88028
|
[MESH_AUTH_MODE_FIELD]: "cluster",
|
|
87870
|
-
[MESH_CLEAR_PORT_FIELD]: "cluster"
|
|
88029
|
+
[MESH_CLEAR_PORT_FIELD]: "cluster",
|
|
88030
|
+
[AGENT_DASHBOARD_ORIGINS_FIELD]: "cluster"
|
|
87871
88031
|
};
|
|
87872
88032
|
/** Bytes of a generated cluster secret (D802) — 256 bits, base64url (43 chars). */
|
|
87873
88033
|
var GENERATED_SECRET_BYTES = 32;
|
|
@@ -87876,10 +88036,10 @@ var STATE_LABELS = {
|
|
|
87876
88036
|
legacy: "legacy hash only — update the agent",
|
|
87877
88037
|
unauthenticated: "not authenticated — enter the cluster secret in this agent"
|
|
87878
88038
|
};
|
|
87879
|
-
/** The Cluster page's live line per node (D802). */
|
|
88039
|
+
/** The Cluster page's live line per node (D802). Mode is always enforced (D821). */
|
|
87880
88040
|
function describeMeshStatus(status) {
|
|
87881
88041
|
if (status === null) return "The mesh status is available on the hub only.";
|
|
87882
|
-
const head =
|
|
88042
|
+
const head = "Enforced: a node that has not authenticated is refused.";
|
|
87883
88043
|
if (status.nodes.length === 0) return `${head}\nNo other node is connected.`;
|
|
87884
88044
|
return `${head}\n${status.nodes.map((n) => `• ${n.nodeId}: ${STATE_LABELS[n.state] ?? n.state}`).join("\n")}`;
|
|
87885
88045
|
}
|
|
@@ -87910,6 +88070,9 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
87910
88070
|
this.ctx.logger.info("Mesh authentication is now ENFORCED", { meta: { reason } });
|
|
87911
88071
|
});
|
|
87912
88072
|
await this.clusterSecretKeeper.start();
|
|
88073
|
+
try {
|
|
88074
|
+
await this.writeMeshAuthMode("enforced");
|
|
88075
|
+
} catch {}
|
|
87913
88076
|
this.meshCaKeeper = new MeshCaKeeper({
|
|
87914
88077
|
secrets: this.systemSecrets(),
|
|
87915
88078
|
readClusterSection: async () => await this.ctx.settings?.getSection("cluster") ?? {},
|
|
@@ -87924,7 +88087,10 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
87924
88087
|
this.ctx.logger.info("Initialized — exposes yml-backed sections via getGlobalSettings");
|
|
87925
88088
|
return {
|
|
87926
88089
|
customActions: systemConfigMeshActions,
|
|
87927
|
-
actionHandlers: {
|
|
88090
|
+
actionHandlers: {
|
|
88091
|
+
mintJoinToken: async (input) => this.mintJoinToken(parseMintJoinTokenInput(input)),
|
|
88092
|
+
mintAgentUiUnlockTicket: async (input) => this.mintAgentUiUnlock(parseMintUnlockInput(input))
|
|
88093
|
+
}
|
|
87928
88094
|
};
|
|
87929
88095
|
}
|
|
87930
88096
|
async onShutdown() {
|
|
@@ -87977,6 +88143,41 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
87977
88143
|
...input.nodeId !== void 0 ? { nodeId: input.nodeId } : {}
|
|
87978
88144
|
};
|
|
87979
88145
|
}
|
|
88146
|
+
/** D821 — short-lived ticket for the agent's `:4444` unlock session. */
|
|
88147
|
+
async mintAgentUiUnlock(input) {
|
|
88148
|
+
const secrets = this.systemSecrets();
|
|
88149
|
+
if (secrets === null) throw new Error("system-config: no keychain door — cannot mint an unlock ticket");
|
|
88150
|
+
const entry = (await secrets.resolve([CLUSTER_SECRET_REF]))[CLUSTER_SECRET_REF];
|
|
88151
|
+
if (entry?.kind !== "value") throw new Error("system-config: cluster secret is not available — cannot mint an unlock ticket");
|
|
88152
|
+
if (input.dashboardBaseUrl !== void 0) {
|
|
88153
|
+
const origins = await this.readAgentDashboardOrigins();
|
|
88154
|
+
if (!isAllowedAgentDashboardReturnTo(input.dashboardBaseUrl, origins)) throw new Error("dashboardBaseUrl is not an allowed agent dashboard origin (:4444 or agentDashboardOrigins)");
|
|
88155
|
+
}
|
|
88156
|
+
const ticket = mintAgentUiUnlockTicket({
|
|
88157
|
+
secretHash: hashClusterSecret(entry.value),
|
|
88158
|
+
nodeId: input.nodeId
|
|
88159
|
+
});
|
|
88160
|
+
const payloadJson = Buffer.from(ticket.split(".")[0] ?? "", "base64url").toString("utf8");
|
|
88161
|
+
const exp = JSON.parse(payloadJson).exp ?? 0;
|
|
88162
|
+
const dashboardUrl = input.dashboardBaseUrl === void 0 ? void 0 : (() => {
|
|
88163
|
+
const u = new URL(input.dashboardBaseUrl);
|
|
88164
|
+
u.searchParams.set("ticket", ticket);
|
|
88165
|
+
return u.toString();
|
|
88166
|
+
})();
|
|
88167
|
+
return {
|
|
88168
|
+
ticket,
|
|
88169
|
+
exp,
|
|
88170
|
+
nodeId: input.nodeId,
|
|
88171
|
+
...dashboardUrl !== void 0 ? { dashboardUrl } : {}
|
|
88172
|
+
};
|
|
88173
|
+
}
|
|
88174
|
+
async readAgentDashboardOrigins() {
|
|
88175
|
+
try {
|
|
88176
|
+
return parseAgentDashboardOrigins((await this.ctx.settings?.getSection("cluster"))?.[AGENT_DASHBOARD_ORIGINS_FIELD]);
|
|
88177
|
+
} catch {
|
|
88178
|
+
return [];
|
|
88179
|
+
}
|
|
88180
|
+
}
|
|
87980
88181
|
async resolveHubUrl() {
|
|
87981
88182
|
try {
|
|
87982
88183
|
const book = await this.ctx.api?.localNetwork?.getAddresses?.query({ scheme: "https" });
|
|
@@ -88096,20 +88297,6 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
88096
88297
|
label: "Cluster secret",
|
|
88097
88298
|
description: "Mandatory — generated by the hub at first boot and stored in the keychain. To pair an agent: Reveal and copy it here, then enter it in the agent (its status page, or the desktop setup window). Saving a new value rotates it: every agent must then be given the new one."
|
|
88098
88299
|
},
|
|
88099
|
-
{
|
|
88100
|
-
type: "select",
|
|
88101
|
-
key: MESH_AUTH_MODE_FIELD,
|
|
88102
|
-
label: "Agents without the secret",
|
|
88103
|
-
description: "Transition lets an agent that has not authenticated keep working (with a warning) while you give each agent the secret; it ends by itself once every known agent has authenticated. Enforced refuses it.",
|
|
88104
|
-
default: "transition",
|
|
88105
|
-
options: [{
|
|
88106
|
-
value: "transition",
|
|
88107
|
-
label: "Transition — allow, warn"
|
|
88108
|
-
}, {
|
|
88109
|
-
value: "enforced",
|
|
88110
|
-
label: "Enforced — refuse"
|
|
88111
|
-
}]
|
|
88112
|
-
},
|
|
88113
88300
|
{
|
|
88114
88301
|
type: "select",
|
|
88115
88302
|
key: MESH_CLEAR_PORT_FIELD,
|
|
@@ -88131,6 +88318,12 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
88131
88318
|
content: describeMeshStatus(getProcessMeshAuthStatus()),
|
|
88132
88319
|
variant: "info"
|
|
88133
88320
|
},
|
|
88321
|
+
{
|
|
88322
|
+
type: "string",
|
|
88323
|
+
key: AGENT_DASHBOARD_ORIGINS_FIELD,
|
|
88324
|
+
label: "Agent dashboard origins (NPM)",
|
|
88325
|
+
description: "Extra origins allowed for Continue-with-hub unlock redirects (comma-separated), e.g. https://agent.example.com. LAN agents on :4444 are always allowed."
|
|
88326
|
+
},
|
|
88134
88327
|
{
|
|
88135
88328
|
type: "addon-action-button",
|
|
88136
88329
|
key: "mintJoinTokenAction",
|
|
@@ -88203,15 +88396,14 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
88203
88396
|
* The cluster secret's save path: the value goes to the keychain (owner
|
|
88204
88397
|
* `system`), the row gets the marker; `''` / a view keeps. `$secretClear` is
|
|
88205
88398
|
* REFUSED: the secret is mandatory (D802). A value the keychain cannot store
|
|
88206
|
-
* is REFUSED — never written inline (D787, P5).
|
|
88399
|
+
* is REFUSED — never written inline (D787, P5). Mesh auth mode is always
|
|
88400
|
+
* enforced (D821) — a legacy `meshAuth` in the patch is ignored.
|
|
88207
88401
|
*/
|
|
88208
88402
|
async writeClusterSection(patch) {
|
|
88209
|
-
const { [MESH_AUTH_MODE_FIELD]:
|
|
88403
|
+
const { [MESH_AUTH_MODE_FIELD]: _legacyMode, [MESH_CLEAR_PORT_FIELD]: clearPort, [AGENT_DASHBOARD_ORIGINS_FIELD]: dashboardOrigins, ...secretPatch } = patch;
|
|
88210
88404
|
if (clearPort !== void 0) await this.writeMeshClearPort(clearPort);
|
|
88211
|
-
if (
|
|
88212
|
-
|
|
88213
|
-
await this.writeMeshAuthMode(mode);
|
|
88214
|
-
}
|
|
88405
|
+
if (dashboardOrigins !== void 0) await this.ctx.settings.setSection("cluster", { [AGENT_DASHBOARD_ORIGINS_FIELD]: typeof dashboardOrigins === "string" ? dashboardOrigins : "" });
|
|
88406
|
+
await this.writeMeshAuthMode("enforced");
|
|
88215
88407
|
if (Object.keys(secretPatch).length === 0) return;
|
|
88216
88408
|
if (isSecretClear(secretPatch["clusterSecret"])) throw new Error("The cluster secret is mandatory and cannot be cleared — save a new value to rotate it");
|
|
88217
88409
|
await this.storeClusterSecret(secretPatch);
|
|
@@ -88239,16 +88431,15 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
88239
88431
|
await applyProcessMeshClearPort(value);
|
|
88240
88432
|
this.ctx.logger.info("Mesh clear port switched", { meta: { mode: value } });
|
|
88241
88433
|
}
|
|
88242
|
-
/**
|
|
88434
|
+
/** Persist + publish mesh auth mode (always `enforced` after D821). */
|
|
88243
88435
|
async writeMeshAuthMode(mode) {
|
|
88244
88436
|
await this.ctx.settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: mode });
|
|
88245
|
-
|
|
88437
|
+
setProcessMeshAuthMode(mode);
|
|
88246
88438
|
}
|
|
88247
88439
|
/**
|
|
88248
88440
|
* First boot, or a keychain reset that cleared the marker (D802): a fresh
|
|
88249
|
-
* random secret, stored like an operator save.
|
|
88250
|
-
*
|
|
88251
|
-
* with no agent yet, the hub's auto-enforce ends it at once.
|
|
88441
|
+
* random secret, stored like an operator save. Mesh auth stays enforced
|
|
88442
|
+
* (D821) — every agent must present the secret; there is no transition window.
|
|
88252
88443
|
*/
|
|
88253
88444
|
async generateClusterSecret() {
|
|
88254
88445
|
const settings = this.ctx.settings;
|
|
@@ -88263,7 +88454,8 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
88263
88454
|
if (existing?.kind !== "missing") throw new Error(`the keychain cannot answer for the cluster secret (${existing?.kind ?? "no answer"})`);
|
|
88264
88455
|
const value = randomBytes(GENERATED_SECRET_BYTES).toString("base64url");
|
|
88265
88456
|
await this.storeClusterSecret({ [CLUSTER_SECRET_FIELD]: value });
|
|
88266
|
-
await settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: "
|
|
88457
|
+
await settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: "enforced" });
|
|
88458
|
+
setProcessMeshAuthMode("enforced");
|
|
88267
88459
|
}
|
|
88268
88460
|
async storeClusterSecret(patch) {
|
|
88269
88461
|
const settings = this.ctx.settings;
|
|
@@ -88296,6 +88488,16 @@ function parseMintJoinTokenInput(input) {
|
|
|
88296
88488
|
if (typeof ttlSec === "number") out.ttlSec = ttlSec;
|
|
88297
88489
|
return out;
|
|
88298
88490
|
}
|
|
88491
|
+
function parseMintUnlockInput(input) {
|
|
88492
|
+
if (input === null || typeof input !== "object") throw new Error("system-config: mintAgentUiUnlockTicket requires { nodeId }");
|
|
88493
|
+
const nodeId = Reflect.get(input, "nodeId");
|
|
88494
|
+
if (typeof nodeId !== "string" || nodeId.length === 0) throw new Error("system-config: mintAgentUiUnlockTicket requires { nodeId }");
|
|
88495
|
+
const dashboardBaseUrl = Reflect.get(input, "dashboardBaseUrl");
|
|
88496
|
+
return {
|
|
88497
|
+
nodeId,
|
|
88498
|
+
...typeof dashboardBaseUrl === "string" ? { dashboardBaseUrl } : {}
|
|
88499
|
+
};
|
|
88500
|
+
}
|
|
88299
88501
|
/** Read `exp` from an unencrypted JWT payload (no verify — already minted here). */
|
|
88300
88502
|
function readJwtExp(token) {
|
|
88301
88503
|
const parts = token.split(".");
|
|
@@ -88307,4 +88509,4 @@ function readJwtExp(token) {
|
|
|
88307
88509
|
return typeof exp === "number" ? exp : 0;
|
|
88308
88510
|
}
|
|
88309
88511
|
//#endregion
|
|
88310
|
-
export { loadMeshCa as A,
|
|
88512
|
+
export { loadMeshCa as A, MESH_AUTH_MODE_FIELD as B, caFingerprintCompact as C, generateMeshKeyPair as D, generateMeshCa as E, UnlockTicketJtiStore as F, requestProcessMeshEnforcement as G, getProcessMeshAuthStatus as H, isAllowedAgentDashboardReturnTo as I, setProcessMeshEnforcer as J, setProcessMeshAuthMode as K, mintAgentUiUnlockTicket as L, AGENT_UI_UNLOCK_DOMAIN as M, AGENT_UI_UNLOCK_TTL_MS as N, issueMeshLeafForNode as O, AGENT_UI_UNLOCK_VERSION as P, readCidrSetting as Q, parseAgentDashboardOrigins as R, caFingerprint as S, SYSTEM_CONFIG_CLUSTER_SECTION_ID, SystemConfigAddon, SystemConfigAddon as default, exportMeshPrivateKeyPem as T, isMeshAuthMode as U, getProcessMeshAuthMode as V, parseMeshAuthMode as W, normalizeIp as X, createCidrMatcher as Y, parseCidrList as Z, MeshCrl as _, setProcessMeshTlsEnabler as a, getProcessMeshCaState as b, mintMeshJoinToken as c, MESH_CLEAR_PORT_FIELD as d, applyProcessMeshClearPort as f, setProcessMeshClearPortControl as g, getProcessNodeMeshTransport as h, ServiceBroker as i, AGENT_DASHBOARD_ORIGINS_FIELD as j, issueMeshLeafFromCsr as k, processJoinTokenJtiStore as l, decideMeshClearPortOff as m, TlsTcpTransporter as n, enrollMeshNode as o, checkProcessMeshClearPort as p, setProcessMeshAuthStatusSource as q, Errors as r, JoinTokenJtiStore as s, systemConfigMeshActions as t, verifyMeshJoinToken as u, processMeshCrl as v, createMeshCsrPem as w, requireProcessMeshCa as x, MeshCaKeeper as y, verifyAgentUiUnlockTicket as z };
|
package/dist/index.js
CHANGED
|
@@ -13863,8 +13863,12 @@ exports.ADMIN_TOKEN_MAX_LIFETIME_MS = require_builtins_local_auth_local_auth_add
|
|
|
13863
13863
|
exports.ADMIN_TOKEN_PREFIX = require_builtins_local_auth_local_auth_addon.ADMIN_TOKEN_PREFIX;
|
|
13864
13864
|
exports.AGENT_CAP_FWD_ACTION = require_child_cap_dispatch.AGENT_CAP_FWD_ACTION;
|
|
13865
13865
|
exports.AGENT_CAP_FWD_SERVICE = require_child_cap_dispatch.AGENT_CAP_FWD_SERVICE;
|
|
13866
|
+
exports.AGENT_DASHBOARD_ORIGINS_FIELD = require_builtins_system_config_system_config_addon.AGENT_DASHBOARD_ORIGINS_FIELD;
|
|
13866
13867
|
exports.AGENT_READINESS_SERVICE_NAME = AGENT_READINESS_SERVICE_NAME;
|
|
13867
13868
|
exports.AGENT_REGISTER_NODE_ACTION = AGENT_REGISTER_NODE_ACTION;
|
|
13869
|
+
exports.AGENT_UI_UNLOCK_DOMAIN = require_builtins_system_config_system_config_addon.AGENT_UI_UNLOCK_DOMAIN;
|
|
13870
|
+
exports.AGENT_UI_UNLOCK_TTL_MS = require_builtins_system_config_system_config_addon.AGENT_UI_UNLOCK_TTL_MS;
|
|
13871
|
+
exports.AGENT_UI_UNLOCK_VERSION = require_builtins_system_config_system_config_addon.AGENT_UI_UNLOCK_VERSION;
|
|
13868
13872
|
exports.ALL_CAPABILITY_DEFINITIONS = require_dist.ALL_CAPABILITY_DEFINITIONS;
|
|
13869
13873
|
exports.ARRAY_BUFFER_CENSUS_COOLDOWN_MS = require_child_cap_dispatch.ARRAY_BUFFER_CENSUS_COOLDOWN_MS;
|
|
13870
13874
|
exports.ARRAY_BUFFER_CENSUS_SUSTAIN_MS = require_child_cap_dispatch.ARRAY_BUFFER_CENSUS_SUSTAIN_MS;
|
|
@@ -14060,6 +14064,7 @@ exports.UPLOADED_CA_FILE = require_tls.UPLOADED_CA_FILE;
|
|
|
14060
14064
|
exports.USER_MANAGEMENT_INTERNAL = require_builtins_local_auth_local_auth_addon.USER_MANAGEMENT_INTERNAL;
|
|
14061
14065
|
exports.UdsLocalTransportClient = require_child_cap_dispatch.UdsLocalTransportClient;
|
|
14062
14066
|
exports.UdsLocalTransportServer = require_child_cap_dispatch.UdsLocalTransportServer;
|
|
14067
|
+
exports.UnlockTicketJtiStore = require_builtins_system_config_system_config_addon.UnlockTicketJtiStore;
|
|
14063
14068
|
exports.UserManager = require_builtins_local_auth_local_auth_addon.UserManager;
|
|
14064
14069
|
exports.WinstonDestination = require_builtins_winston_logging_index.WinstonDestination$1;
|
|
14065
14070
|
exports.WinstonLoggingAddon = require_builtins_winston_logging_index.WinstonLoggingAddon$1;
|
|
@@ -14292,6 +14297,7 @@ Object.defineProperty(exports, "installPythonRequirements", {
|
|
|
14292
14297
|
});
|
|
14293
14298
|
exports.ipcParentLink = require_child_cap_dispatch.ipcParentLink;
|
|
14294
14299
|
exports.isAddonDeploySource = isAddonDeploySource;
|
|
14300
|
+
exports.isAllowedAgentDashboardReturnTo = require_builtins_system_config_system_config_addon.isAllowedAgentDashboardReturnTo;
|
|
14295
14301
|
exports.isArrayBufferCensusReport = require_child_cap_dispatch.isArrayBufferCensusReport;
|
|
14296
14302
|
exports.isArrayOutputSchema = require_dist.isArrayOutputSchema;
|
|
14297
14303
|
exports.isClusterSecretMismatchError = require_constants.isClusterSecretMismatchError;
|
|
@@ -14314,11 +14320,13 @@ exports.loadTlsCert = require_tls.loadTlsCert;
|
|
|
14314
14320
|
exports.localEndpointPath = require_child_cap_dispatch.localEndpointPath;
|
|
14315
14321
|
exports.localProviderLink = require_child_cap_dispatch.localProviderLink;
|
|
14316
14322
|
exports.meshErrorType = meshErrorType;
|
|
14323
|
+
exports.mintAgentUiUnlockTicket = require_builtins_system_config_system_config_addon.mintAgentUiUnlockTicket;
|
|
14317
14324
|
exports.mintMeshJoinToken = require_builtins_system_config_system_config_addon.mintMeshJoinToken;
|
|
14318
14325
|
exports.mountNativeCapService = require_child_cap_dispatch.mountNativeCapService;
|
|
14319
14326
|
exports.nextRssBudgetState = require_child_cap_dispatch.nextRssBudgetState;
|
|
14320
14327
|
exports.normalizeIp = require_builtins_system_config_system_config_addon.normalizeIp;
|
|
14321
14328
|
exports.overlayGetStatus = overlayGetStatus;
|
|
14329
|
+
exports.parseAgentDashboardOrigins = require_builtins_system_config_system_config_addon.parseAgentDashboardOrigins;
|
|
14322
14330
|
exports.parseCapAction = require_child_cap_dispatch.parseCapAction;
|
|
14323
14331
|
exports.parseCidrList = require_builtins_system_config_system_config_addon.parseCidrList;
|
|
14324
14332
|
exports.parseMeshAuthMode = require_builtins_system_config_system_config_addon.parseMeshAuthMode;
|
|
@@ -14404,6 +14412,7 @@ exports.subscribePassthrough = require_child_cap_dispatch.subscribePassthrough;
|
|
|
14404
14412
|
exports.udsChildLogToWorkerEntry = require_child_cap_dispatch.udsChildLogToWorkerEntry;
|
|
14405
14413
|
exports.validateProviderRegistrations = require_child_cap_dispatch.validateProviderRegistrations;
|
|
14406
14414
|
exports.validateUploadedTls = require_tls.validateUploadedTls;
|
|
14415
|
+
exports.verifyAgentUiUnlockTicket = require_builtins_system_config_system_config_addon.verifyAgentUiUnlockTicket;
|
|
14407
14416
|
exports.verifyMeshJoinToken = require_builtins_system_config_system_config_addon.verifyMeshJoinToken;
|
|
14408
14417
|
exports.waitUntilReady = waitUntilReady;
|
|
14409
14418
|
exports.writeExtraSans = require_tls.writeExtraSans;
|
package/dist/index.mjs
CHANGED
|
@@ -27,7 +27,7 @@ import { i as stripForwardedCaller, n as HUB_CAP_FWD_SERVICE, r as createHubCapF
|
|
|
27
27
|
import { StorageOrchestratorAddon, n as buildStorageLocationRegistry, t as StorageOrchestratorService } from "./builtins/storage-orchestrator/storage-orchestrator.addon.mjs";
|
|
28
28
|
import "./builtins/storage-orchestrator/index.mjs";
|
|
29
29
|
import { _ as clusterSecretMatches, a as MESH_CA_FIELD, b as isClusterSecretMismatchError, d as CLUSTER_SECRET_MISMATCH_TYPE, f as CLUSTER_SECRET_REF, g as checkClusterSecret, h as CLUSTER_SECRET_UNAVAILABLE_TYPE, m as CLUSTER_SECRET_SETTINGS_KEY, o as MESH_CA_KEY_REF, p as CLUSTER_SECRET_REJECTED_EXIT_CODE, r as DEFAULT_HUB_TLS_TCP_PORT, s as MESH_CA_SETTINGS_KEY, v as getProcessClusterSecretGate, x as setProcessClusterSecretGate, y as hashClusterSecret } from "./constants-D5z4EwY8.mjs";
|
|
30
|
-
import { A as loadMeshCa, B as
|
|
30
|
+
import { A as loadMeshCa, B as MESH_AUTH_MODE_FIELD, C as caFingerprintCompact, D as generateMeshKeyPair, E as generateMeshCa, F as UnlockTicketJtiStore, G as requestProcessMeshEnforcement, H as getProcessMeshAuthStatus, I as isAllowedAgentDashboardReturnTo, J as setProcessMeshEnforcer, K as setProcessMeshAuthMode, L as mintAgentUiUnlockTicket, M as AGENT_UI_UNLOCK_DOMAIN, N as AGENT_UI_UNLOCK_TTL_MS, O as issueMeshLeafForNode, P as AGENT_UI_UNLOCK_VERSION, Q as readCidrSetting, R as parseAgentDashboardOrigins, S as caFingerprint, SystemConfigAddon, T as exportMeshPrivateKeyPem, U as isMeshAuthMode, V as getProcessMeshAuthMode, W as parseMeshAuthMode, X as normalizeIp, Y as createCidrMatcher, Z as parseCidrList, _ as MeshCrl, a as setProcessMeshTlsEnabler, b as getProcessMeshCaState, c as mintMeshJoinToken, d as MESH_CLEAR_PORT_FIELD, f as applyProcessMeshClearPort, g as setProcessMeshClearPortControl, h as getProcessNodeMeshTransport, i as ServiceBroker, j as AGENT_DASHBOARD_ORIGINS_FIELD, k as issueMeshLeafFromCsr, l as processJoinTokenJtiStore, m as decideMeshClearPortOff, n as TlsTcpTransporter, o as enrollMeshNode, p as checkProcessMeshClearPort, q as setProcessMeshAuthStatusSource, r as Errors, s as JoinTokenJtiStore, u as verifyMeshJoinToken, v as processMeshCrl, w as createMeshCsrPem, x as requireProcessMeshCa, y as MeshCaKeeper, z as verifyAgentUiUnlockTicket } from "./builtins/system-config/system-config.addon.mjs";
|
|
31
31
|
import "./builtins/system-config/index.mjs";
|
|
32
32
|
import { WinstonDestination, WinstonLoggingAddon } from "./builtins/winston-logging/index.mjs";
|
|
33
33
|
import { C as resolveFormatRevision, S as isModelDownloaded, _ as downloadModel, a as createFileDataPlaneHandler, b as getModelFilePath, c as parseRangeHeader, d as ModelDownloadService, g as downloadFile, h as deleteModelFromDisk, i as startEventLoopStallMonitor, l as parseTokenizedUrl, m as collectModelFiles, n as STALL_TICK_MS, o as contentTypeFor, p as adoptModelRevisions, r as attributeStall, s as createAuthenticatedFileServer, t as STALL_REPORT_MS, u as resolveFilePath, v as ensureModel, w as revisionWeightUrl, y as fetchJson } from "./event-loop-stall-monitor-BtK_0Pjc.mjs";
|
|
@@ -13856,4 +13856,4 @@ var LifecycleJobEngine = class {
|
|
|
13856
13856
|
}
|
|
13857
13857
|
};
|
|
13858
13858
|
//#endregion
|
|
13859
|
-
export { ADMIN_TOKEN_MAX_LIFETIME_MS, ADMIN_TOKEN_PREFIX, AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, AGENT_REGISTER_NODE_ACTION, ALL_CAPABILITY_DEFINITIONS, ARRAY_BUFFER_CENSUS_COOLDOWN_MS, ARRAY_BUFFER_CENSUS_SUSTAIN_MS, ARRAY_BUFFER_CENSUS_THRESHOLD_MB, ARRAY_BUFFER_RELEASE_MIN_DROP_RATIO, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AdminTokenManager, AgentMeshAuthenticator, AlertCenterAddon, ApiKeyManager, AuthAuditLog, AuthManager, BackupDecryptError, BackupKeyFormatError, BackupKeyMismatchError, BackupKeyRequiredError, CAP_ACTION_OVERFLOW_LABEL, CAP_ACTION_UNLABELLED, CAP_METHOD_NOT_IMPLEMENTED, CA_COMMON_NAME, CA_VALIDITY_DAYS, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REF, CLUSTER_SECRET_REJECTED_EXIT_CODE, CLUSTER_SECRET_SETTINGS_KEY, CLUSTER_SECRET_UNAVAILABLE_TYPE, CORE_CAP_SERVICE_NAME, CalendarsAddon, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ComposerAddon, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CoreBlocksAddon, CustomActionRegistry, DECISIVE_HEAP_SPACES, DEFAULT_DATA_PATH, DEFAULT_HUB_TLS_TCP_PORT, DEFAULT_LAN_HTTP_PORT, DEFAULT_LOG_LEVEL, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EMPTY_CAP_ACTION_READING, EMPTY_SOCKET_DIRECTION, EMPTY_SOCKET_PLANE_BASELINE, EVENT_PLANE_TOP_N, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FIRST_BOOT_ADMIN_PASSWORD, FIRST_BOOT_ADMIN_USERNAME, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, GET_STATUS_METHOD, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HEAP_RECLAIM_MIN_INTERVAL_MS, HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, HEAP_RECLAIM_TRIGGER_MB, HEAP_SPACE_REPORT_MIN_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HUB_MAIN_HEAP_WATCH_LABEL, HUB_MAIN_RSS_BUDGET_MB, HUB_RSS_BUDGET_ENV, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JWT_SIGNING_KEY_REF, JobJournal, JoinTokenJtiStore, JwtSigningKeyUnavailableError, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LoggingGate, LoginSessionManager, LokiDestination, LokiLoggingAddon, MAX_CAP_ACTIONS_PER_PEER, MAX_LEAF_VALIDITY_DAYS, MESH_ACTION_FORBIDDEN_TYPE, MESH_AUTH_MODE_FIELD, MESH_AUTO_ENFORCE_GRACE_MS, MESH_CA_FIELD, MESH_CA_KEY_REF, MESH_CA_SETTINGS_KEY, MESH_CLEAR_PORT_FIELD, MESH_JOIN_AUTHENTICATE_ACTION, MESH_JOIN_CHALLENGE_ACTION, MESH_JOIN_CHALLENGE_INVALID_TYPE, MESH_JOIN_CHALLENGE_TTL_MS, MESH_JOIN_PROTOCOL, MESH_NODE_UNAUTHENTICATED_TYPE, MESH_QUEUE_TOP_N, METHOD_ACCESS_MAP, MeshAuthenticator, MeshCaKeeper, MeshCrl, MeshJoinClient, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, OUTBOUND_QUEUE_COOLDOWN_MS, OUTBOUND_QUEUE_SUSTAIN_MS, OUTBOUND_QUEUE_THRESHOLD_BYTES, PARENT_ROUTED_PROVIDER_ADDON_ID, PYTHON_VERSION, PeerAnsweredError, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, REFRESH_TOKEN_PREFIX, RESTART_MARKER_FILE, RSS_BUDGET_REANNOUNCE_MIN_MS, RSS_BUDGET_RELEASE_RATIO, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNNER_RSS_BUDGET_ENV, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, SOCKET_PLANE_TOP_N, SOCKET_QUEUE_TOP_N, STALL_REPORT_MS, STALL_TICK_MS, STORE_READABLE_BOOTSTRAP_KEYS, SYSTEM_SECRET_OWNER, ScopedLogger, ScopedTokenManager, SettingsReadUnavailableError, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemBackupService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, TlsTcpTransporter, ToastService, UDS_NO_ROUTE_PREFIX, UNCLAIMED, UPLOADED_CA_FILE, USER_MANAGEMENT_INTERNAL, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, ZERO_LOOP_DELAY, __resetCapUsageRegistryForTests, __resetLoggingGateForTests, adaptBrokerToCluster, addonSettingsCapability, adoptModelRevisions, afterWorkerOnlineAnnounce, allFamiliesListenHost, answerClaimedGetStatus, applyCertificateToListener, applyLanHttp, applyProcessMeshClearPort, attachUserManagementInternal, attributeStall, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildNpmChildEnv, buildStorageLocationRegistry, builderMountedCapNames, caFingerprint, caFingerprintCompact, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionLabel, capActionName, capActionSuffix, capBareAction, capServiceName, checkClusterSecret, checkProcessMeshClearPort, classifyAddonDir, classifyCapRoute, clearHttpsListener, clearPendingRestart, clearPlatformKeychainKey, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, computeHubJoinProof, computeNodeJoinProof, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonPeerBytesFacility, createAddonService, createArrayBufferCensusGate, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCapActionCensus, createCidrMatcher, createCoreCapService, createDeferredHeapWatchSink, createDoorSettingsView, createEventPlaneMeter, createEventPlaneReader, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createInspectorArrayBufferCensus, createKernelHwAccel, createLocalTransport, createLoopDelayMeter, createMeshAccessMiddleware, createMeshCsrPem, createMeshQueueReader, createOutboundQueueGate, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createSocketDirectionCounters, createSocketPlaneMeter, createSocketPlaneReader, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, decideMeshAutoEnforce, decideMeshClearPortOff, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, describeRss, detectWorkspacePackagesDir, deviceCapResolverLink, deviceOfGetStatus, diffCapActionCensus, diffEventPlane, diffSocketPlane, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, emitHeapDiagnosticReport, encodeFrame, enrollMeshNode, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, exportMeshPrivateKeyPem, fetchJson, findInPath, formatArrayBufferCensus, formatEventPlane, formatHeapSpaces, formatLogLine, formatMeshQueue, formatOutboundQueueVerdict, formatSocketPlane, generateBackupKeyPair, generateMeshCa, generateMeshKeyPair, getBrokerEventBus, getBrokerTlsTransporter, getCapUsageRegistry, getFfmpegDownloadUrl, getLoggingGate, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPlatformKeychainKey, getProcessClusterSecretGate, getProcessJwtSigningKeyState, getProcessMeshAuthMode, getProcessMeshAuthStatus, getProcessMeshCaState, getProcessNodeMeshTransport, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getUserManagementInternal, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, heapSpaceField, hostNodeIdOf, hubMainRssBudget, installManifestNativeDeps, installManifestPythonDeps, installManifestSystemDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isArrayBufferCensusReport, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isCredentialKeyName, isInfraCapability, isMeshAuthMode, isModelDownloaded, isOwnChildNodeId, isRemoteForbiddenAction, isRemoteForbiddenOnAgent, isSettingsReadUnavailable, isSourceNewer, isolatedBuiltinPhase, issueMeshLeafForNode, issueMeshLeafFromCsr, leafFingerprintOf, loadMeshCa, loadTlsCert, localEndpointPath, localProviderLink, meshErrorType, mintMeshJoinToken, mountNativeCapService, nextRssBudgetState, normalizeIp, overlayGetStatus, parseCapAction, parseCidrList, parseMeshAuthMode, parseRangeHeader, parseRssBudgetMb, parseTokenExpiry, parseTokenizedUrl, partitionIsolatedBuiltinIds, prepareBootTls, prepareRestoreArchive, processJoinTokenJtiStore, processJwtSigningKey, processMeshCrl, proxyToUpstream, quarantineAddonResidue, readBackupEncryptionHeader, readCidrSetting, readExtraSans, readHeapSpaces, readLanHttpState, readPendingRestart, readSocketQueues, readTlsAccessStatus, readTlsMode, readinessKey, reclaimIntervalMs, recordSocketFrame, redactLogEntry, redactLogMeta, redactLogText, regenerateCertificate, registerEventBusService, registerHttpsListener, registerLanHttpHandler, reissueTlsLeaf, reloadHttpsListener, requestProcessMeshEnforcement, requireProcessMeshCa, resolveFilePath, resolveFormatRevision, resolveHwAccel, resolveNpmInvocation, revertToGeneratedCertificate, revisionWeightUrl, runHubAddonBoot, runNpm, sampleSocketDirection, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, selectReportedSpaces, serializeTypedArrays, servedHttpsLeafFingerprint, setHubConnected, setNodeEventInterest, setPlatformKeychainKey, setProcessClusterSecretGate, setProcessMeshAuthMode, setProcessMeshAuthStatusSource, setProcessMeshClearPortControl, setProcessMeshEnforcer, setProcessMeshTlsEnabler, setWrapperActive, shouldReclaim, signalAllRunnerGroups, socketDirectionBytes, socketDirectionMessages, splitPemCertificates, stampCallerAddonId, startEventLoopStallMonitor, startHeapWatch, startRunnerHeapWatch, staticJwtSigningKey, storeMayAnswer, storeUploadedCertificate, strandedMb, stripCamstackDeps, stripForgedIdentity, stripForwardedCaller, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, verifyMeshJoinToken, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
|
13859
|
+
export { ADMIN_TOKEN_MAX_LIFETIME_MS, ADMIN_TOKEN_PREFIX, AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_DASHBOARD_ORIGINS_FIELD, AGENT_READINESS_SERVICE_NAME, AGENT_REGISTER_NODE_ACTION, AGENT_UI_UNLOCK_DOMAIN, AGENT_UI_UNLOCK_TTL_MS, AGENT_UI_UNLOCK_VERSION, ALL_CAPABILITY_DEFINITIONS, ARRAY_BUFFER_CENSUS_COOLDOWN_MS, ARRAY_BUFFER_CENSUS_SUSTAIN_MS, ARRAY_BUFFER_CENSUS_THRESHOLD_MB, ARRAY_BUFFER_RELEASE_MIN_DROP_RATIO, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AdminTokenManager, AgentMeshAuthenticator, AlertCenterAddon, ApiKeyManager, AuthAuditLog, AuthManager, BackupDecryptError, BackupKeyFormatError, BackupKeyMismatchError, BackupKeyRequiredError, CAP_ACTION_OVERFLOW_LABEL, CAP_ACTION_UNLABELLED, CAP_METHOD_NOT_IMPLEMENTED, CA_COMMON_NAME, CA_VALIDITY_DAYS, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REF, CLUSTER_SECRET_REJECTED_EXIT_CODE, CLUSTER_SECRET_SETTINGS_KEY, CLUSTER_SECRET_UNAVAILABLE_TYPE, CORE_CAP_SERVICE_NAME, CalendarsAddon, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ComposerAddon, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CoreBlocksAddon, CustomActionRegistry, DECISIVE_HEAP_SPACES, DEFAULT_DATA_PATH, DEFAULT_HUB_TLS_TCP_PORT, DEFAULT_LAN_HTTP_PORT, DEFAULT_LOG_LEVEL, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EMPTY_CAP_ACTION_READING, EMPTY_SOCKET_DIRECTION, EMPTY_SOCKET_PLANE_BASELINE, EVENT_PLANE_TOP_N, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FIRST_BOOT_ADMIN_PASSWORD, FIRST_BOOT_ADMIN_USERNAME, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, GET_STATUS_METHOD, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HEAP_RECLAIM_MIN_INTERVAL_MS, HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, HEAP_RECLAIM_TRIGGER_MB, HEAP_SPACE_REPORT_MIN_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HUB_MAIN_HEAP_WATCH_LABEL, HUB_MAIN_RSS_BUDGET_MB, HUB_RSS_BUDGET_ENV, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JWT_SIGNING_KEY_REF, JobJournal, JoinTokenJtiStore, JwtSigningKeyUnavailableError, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LoggingGate, LoginSessionManager, LokiDestination, LokiLoggingAddon, MAX_CAP_ACTIONS_PER_PEER, MAX_LEAF_VALIDITY_DAYS, MESH_ACTION_FORBIDDEN_TYPE, MESH_AUTH_MODE_FIELD, MESH_AUTO_ENFORCE_GRACE_MS, MESH_CA_FIELD, MESH_CA_KEY_REF, MESH_CA_SETTINGS_KEY, MESH_CLEAR_PORT_FIELD, MESH_JOIN_AUTHENTICATE_ACTION, MESH_JOIN_CHALLENGE_ACTION, MESH_JOIN_CHALLENGE_INVALID_TYPE, MESH_JOIN_CHALLENGE_TTL_MS, MESH_JOIN_PROTOCOL, MESH_NODE_UNAUTHENTICATED_TYPE, MESH_QUEUE_TOP_N, METHOD_ACCESS_MAP, MeshAuthenticator, MeshCaKeeper, MeshCrl, MeshJoinClient, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, OUTBOUND_QUEUE_COOLDOWN_MS, OUTBOUND_QUEUE_SUSTAIN_MS, OUTBOUND_QUEUE_THRESHOLD_BYTES, PARENT_ROUTED_PROVIDER_ADDON_ID, PYTHON_VERSION, PeerAnsweredError, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, REFRESH_TOKEN_PREFIX, RESTART_MARKER_FILE, RSS_BUDGET_REANNOUNCE_MIN_MS, RSS_BUDGET_RELEASE_RATIO, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNNER_RSS_BUDGET_ENV, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, SOCKET_PLANE_TOP_N, SOCKET_QUEUE_TOP_N, STALL_REPORT_MS, STALL_TICK_MS, STORE_READABLE_BOOTSTRAP_KEYS, SYSTEM_SECRET_OWNER, ScopedLogger, ScopedTokenManager, SettingsReadUnavailableError, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemBackupService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, TlsTcpTransporter, ToastService, UDS_NO_ROUTE_PREFIX, UNCLAIMED, UPLOADED_CA_FILE, USER_MANAGEMENT_INTERNAL, UdsLocalTransportClient, UdsLocalTransportServer, UnlockTicketJtiStore, UserManager, WinstonDestination, WinstonLoggingAddon, ZERO_LOOP_DELAY, __resetCapUsageRegistryForTests, __resetLoggingGateForTests, adaptBrokerToCluster, addonSettingsCapability, adoptModelRevisions, afterWorkerOnlineAnnounce, allFamiliesListenHost, answerClaimedGetStatus, applyCertificateToListener, applyLanHttp, applyProcessMeshClearPort, attachUserManagementInternal, attributeStall, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildNpmChildEnv, buildStorageLocationRegistry, builderMountedCapNames, caFingerprint, caFingerprintCompact, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionLabel, capActionName, capActionSuffix, capBareAction, capServiceName, checkClusterSecret, checkProcessMeshClearPort, classifyAddonDir, classifyCapRoute, clearHttpsListener, clearPendingRestart, clearPlatformKeychainKey, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, computeHubJoinProof, computeNodeJoinProof, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonPeerBytesFacility, createAddonService, createArrayBufferCensusGate, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCapActionCensus, createCidrMatcher, createCoreCapService, createDeferredHeapWatchSink, createDoorSettingsView, createEventPlaneMeter, createEventPlaneReader, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createInspectorArrayBufferCensus, createKernelHwAccel, createLocalTransport, createLoopDelayMeter, createMeshAccessMiddleware, createMeshCsrPem, createMeshQueueReader, createOutboundQueueGate, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createSocketDirectionCounters, createSocketPlaneMeter, createSocketPlaneReader, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, decideMeshAutoEnforce, decideMeshClearPortOff, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, describeRss, detectWorkspacePackagesDir, deviceCapResolverLink, deviceOfGetStatus, diffCapActionCensus, diffEventPlane, diffSocketPlane, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, emitHeapDiagnosticReport, encodeFrame, enrollMeshNode, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, exportMeshPrivateKeyPem, fetchJson, findInPath, formatArrayBufferCensus, formatEventPlane, formatHeapSpaces, formatLogLine, formatMeshQueue, formatOutboundQueueVerdict, formatSocketPlane, generateBackupKeyPair, generateMeshCa, generateMeshKeyPair, getBrokerEventBus, getBrokerTlsTransporter, getCapUsageRegistry, getFfmpegDownloadUrl, getLoggingGate, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPlatformKeychainKey, getProcessClusterSecretGate, getProcessJwtSigningKeyState, getProcessMeshAuthMode, getProcessMeshAuthStatus, getProcessMeshCaState, getProcessNodeMeshTransport, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getUserManagementInternal, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, heapSpaceField, hostNodeIdOf, hubMainRssBudget, installManifestNativeDeps, installManifestPythonDeps, installManifestSystemDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isAllowedAgentDashboardReturnTo, isArrayBufferCensusReport, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isCredentialKeyName, isInfraCapability, isMeshAuthMode, isModelDownloaded, isOwnChildNodeId, isRemoteForbiddenAction, isRemoteForbiddenOnAgent, isSettingsReadUnavailable, isSourceNewer, isolatedBuiltinPhase, issueMeshLeafForNode, issueMeshLeafFromCsr, leafFingerprintOf, loadMeshCa, loadTlsCert, localEndpointPath, localProviderLink, meshErrorType, mintAgentUiUnlockTicket, mintMeshJoinToken, mountNativeCapService, nextRssBudgetState, normalizeIp, overlayGetStatus, parseAgentDashboardOrigins, parseCapAction, parseCidrList, parseMeshAuthMode, parseRangeHeader, parseRssBudgetMb, parseTokenExpiry, parseTokenizedUrl, partitionIsolatedBuiltinIds, prepareBootTls, prepareRestoreArchive, processJoinTokenJtiStore, processJwtSigningKey, processMeshCrl, proxyToUpstream, quarantineAddonResidue, readBackupEncryptionHeader, readCidrSetting, readExtraSans, readHeapSpaces, readLanHttpState, readPendingRestart, readSocketQueues, readTlsAccessStatus, readTlsMode, readinessKey, reclaimIntervalMs, recordSocketFrame, redactLogEntry, redactLogMeta, redactLogText, regenerateCertificate, registerEventBusService, registerHttpsListener, registerLanHttpHandler, reissueTlsLeaf, reloadHttpsListener, requestProcessMeshEnforcement, requireProcessMeshCa, resolveFilePath, resolveFormatRevision, resolveHwAccel, resolveNpmInvocation, revertToGeneratedCertificate, revisionWeightUrl, runHubAddonBoot, runNpm, sampleSocketDirection, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, selectReportedSpaces, serializeTypedArrays, servedHttpsLeafFingerprint, setHubConnected, setNodeEventInterest, setPlatformKeychainKey, setProcessClusterSecretGate, setProcessMeshAuthMode, setProcessMeshAuthStatusSource, setProcessMeshClearPortControl, setProcessMeshEnforcer, setProcessMeshTlsEnabler, setWrapperActive, shouldReclaim, signalAllRunnerGroups, socketDirectionBytes, socketDirectionMessages, splitPemCertificates, stampCallerAddonId, startEventLoopStallMonitor, startHeapWatch, startRunnerHeapWatch, staticJwtSigningKey, storeMayAnswer, storeUploadedCertificate, strandedMb, stripCamstackDeps, stripForgedIdentity, stripForwardedCaller, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, verifyAgentUiUnlockTicket, verifyMeshJoinToken, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -69,6 +69,8 @@ export type { MeshJoinAuthenticateParams, MeshJoinAuthenticateResult, MeshJoinCh
|
|
|
69
69
|
export { getProcessMeshAuthMode, getProcessMeshAuthStatus, isMeshAuthMode, MESH_AUTH_MODE_FIELD, parseMeshAuthMode, requestProcessMeshEnforcement, setProcessMeshAuthMode, setProcessMeshAuthStatusSource, setProcessMeshEnforcer, } from './moleculer/mesh-auth-mode.js';
|
|
70
70
|
export { decideMeshAutoEnforce, MESH_AUTO_ENFORCE_GRACE_MS, } from './moleculer/mesh-auto-enforce.js';
|
|
71
71
|
export type { MeshAutoEnforceDecision, MeshAutoEnforceInput, } from './moleculer/mesh-auto-enforce.js';
|
|
72
|
+
export { AGENT_DASHBOARD_ORIGINS_FIELD, AGENT_UI_UNLOCK_DOMAIN, AGENT_UI_UNLOCK_TTL_MS, AGENT_UI_UNLOCK_VERSION, isAllowedAgentDashboardReturnTo, mintAgentUiUnlockTicket, parseAgentDashboardOrigins, UnlockTicketJtiStore, verifyAgentUiUnlockTicket, } from './moleculer/agent-ui-unlock.js';
|
|
73
|
+
export type { AgentUiUnlockPayload, MintAgentUiUnlockTicketInput, VerifyAgentUiUnlockTicketOptions, } from './moleculer/agent-ui-unlock.js';
|
|
72
74
|
export type { MeshAuthMode, MeshAuthStatus, MeshEnforcer, MeshNodeAuthEntry, MeshNodeAuthState, } from './moleculer/mesh-auth-mode.js';
|
|
73
75
|
export { serializeTypedArrays } from './moleculer/typed-array-serde.js';
|
|
74
76
|
export { createReadinessService, createReadinessServiceForRegistry, AGENT_READINESS_SERVICE_NAME, } from './moleculer/readiness-service.js';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const AGENT_UI_UNLOCK_DOMAIN = "camstack-agent-ui-unlock/v1";
|
|
2
|
+
export declare const AGENT_UI_UNLOCK_VERSION: 1;
|
|
3
|
+
/** Ticket lifetime — long enough for a redirect hop, short enough to steal poorly. */
|
|
4
|
+
export declare const AGENT_UI_UNLOCK_TTL_MS: number;
|
|
5
|
+
/**
|
|
6
|
+
* Cluster settings key: extra origins allowed as `returnTo` for Continue-with-hub
|
|
7
|
+
* (NPM hostnames that are not `:4444` on a LAN IP). Comma-separated origins.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AGENT_DASHBOARD_ORIGINS_FIELD = "agentDashboardOrigins";
|
|
10
|
+
export interface AgentUiUnlockPayload {
|
|
11
|
+
readonly v: typeof AGENT_UI_UNLOCK_VERSION;
|
|
12
|
+
readonly nodeId: string;
|
|
13
|
+
/** Epoch ms. */
|
|
14
|
+
readonly exp: number;
|
|
15
|
+
readonly jti: string;
|
|
16
|
+
}
|
|
17
|
+
/** In-memory spent `jti` until `exp` (ms). */
|
|
18
|
+
export declare class UnlockTicketJtiStore {
|
|
19
|
+
private readonly spent;
|
|
20
|
+
isSpent(jti: string, nowMs?: number): boolean;
|
|
21
|
+
/** Record a jti as used until `exp`. Returns false if already spent. */
|
|
22
|
+
consume(jti: string, exp: number, nowMs?: number): boolean;
|
|
23
|
+
/** Test helper. */
|
|
24
|
+
size(): number;
|
|
25
|
+
private gc;
|
|
26
|
+
}
|
|
27
|
+
export interface MintAgentUiUnlockTicketInput {
|
|
28
|
+
/** `hashClusterSecret(secret)` — never the raw secret. */
|
|
29
|
+
readonly secretHash: string;
|
|
30
|
+
readonly nodeId: string;
|
|
31
|
+
readonly ttlMs?: number;
|
|
32
|
+
readonly nowMs?: number;
|
|
33
|
+
readonly jti?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function mintAgentUiUnlockTicket(input: MintAgentUiUnlockTicketInput): string;
|
|
36
|
+
export interface VerifyAgentUiUnlockTicketOptions {
|
|
37
|
+
readonly expectedNodeId: string;
|
|
38
|
+
readonly nowMs?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Verify a ticket under `secretHash`. Returns the payload, or `null` when the
|
|
42
|
+
* signature, shape, expiry or nodeId fails (no reason string — refuse quietly).
|
|
43
|
+
*/
|
|
44
|
+
export declare function verifyAgentUiUnlockTicket(secretHash: string, ticket: string, options: VerifyAgentUiUnlockTicketOptions): AgentUiUnlockPayload | null;
|
|
45
|
+
/**
|
|
46
|
+
* True when `returnTo` may receive a ticket redirect. Default: any http(s)
|
|
47
|
+
* origin whose port is 4444. Extra origins come from
|
|
48
|
+
* {@link AGENT_DASHBOARD_ORIGINS_FIELD} (exact origin match).
|
|
49
|
+
*/
|
|
50
|
+
export declare function isAllowedAgentDashboardReturnTo(returnTo: string, extraOrigins?: readonly string[]): boolean;
|
|
51
|
+
/** Parse a stored comma/whitespace-separated origins list. */
|
|
52
|
+
export declare function parseAgentDashboardOrigins(stored: unknown): readonly string[];
|