@camstack/system 1.2.434 → 1.2.436

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.
Files changed (103) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/autotrack/index.js +1 -1
  8. package/dist/builtins/autotrack/index.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  11. package/dist/builtins/calendars/calendars.addon.js +1 -1
  12. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  13. package/dist/builtins/camera-grid/index.js +1 -1
  14. package/dist/builtins/camera-grid/index.mjs +1 -1
  15. package/dist/builtins/composer/composer.addon.js +2 -2
  16. package/dist/builtins/composer/composer.addon.mjs +2 -2
  17. package/dist/builtins/console-logging/index.js +1 -1
  18. package/dist/builtins/console-logging/index.mjs +1 -1
  19. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  20. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  21. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  22. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  23. package/dist/builtins/hub-forwarder/index.js +1 -1
  24. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  25. package/dist/builtins/keychain/index.js +6 -7
  26. package/dist/builtins/keychain/index.mjs +6 -7
  27. package/dist/builtins/keychain/keychain-service.d.ts +1 -2
  28. package/dist/builtins/keychain/system-held-secrets.d.ts +5 -5
  29. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  30. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  31. package/dist/builtins/local-auth/local-auth.addon.js +2 -2
  32. package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
  33. package/dist/builtins/local-network/local-network.addon.d.ts +4 -2
  34. package/dist/builtins/local-network/local-network.addon.js +23 -13
  35. package/dist/builtins/local-network/local-network.addon.mjs +23 -13
  36. package/dist/builtins/loki-logging/index.js +1 -1
  37. package/dist/builtins/loki-logging/index.mjs +1 -1
  38. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  39. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  40. package/dist/builtins/platform-probe/index.js +1 -1
  41. package/dist/builtins/platform-probe/index.mjs +1 -1
  42. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  43. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  44. package/dist/builtins/snapshot/index.js +1 -1
  45. package/dist/builtins/snapshot/index.mjs +1 -1
  46. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  47. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  48. package/dist/builtins/sqlite-storage/index.js +1 -1
  49. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  50. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +3 -3
  51. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +3 -3
  52. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  53. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  54. package/dist/builtins/system-config/system-config.addon.d.ts +3 -24
  55. package/dist/builtins/system-config/system-config.addon.js +105 -1410
  56. package/dist/builtins/system-config/system-config.addon.mjs +108 -1402
  57. package/dist/builtins/winston-logging/index.js +1 -1
  58. package/dist/builtins/winston-logging/index.mjs +1 -1
  59. package/dist/{composition-sources-B7R1oQnY.js → composition-sources-BAOlCu4j.js} +1 -1
  60. package/dist/{composition-sources-CqrDyHM1.mjs → composition-sources-gN_BWUKp.mjs} +1 -1
  61. package/dist/constants-BFpowodq.mjs +20 -0
  62. package/dist/constants-GENKqk9k.js +66 -0
  63. package/dist/{device-ca-CDjGQQPd.mjs → device-ca-BNM5ai4t.mjs} +1 -1
  64. package/dist/{device-ca-D21ZP00q.js → device-ca-CuWuRW9N.js} +1 -1
  65. package/dist/{dist-CCH3XPqO.js → dist-DVe0Nsp8.js} +48 -16
  66. package/dist/{dist-CYcBqnXk.mjs → dist-DjD2M79P.mjs} +43 -5
  67. package/dist/file-host-worker.js +1 -1
  68. package/dist/file-host-worker.mjs +1 -1
  69. package/dist/index.js +132 -795
  70. package/dist/index.mjs +133 -753
  71. package/dist/kernel/index.d.ts +7 -21
  72. package/dist/kernel/moleculer/agent-ui-unlock.d.ts +7 -32
  73. package/dist/kernel/moleculer/broker-factory.d.ts +3 -9
  74. package/dist/kernel/moleculer/broker-transport-swap.d.ts +17 -0
  75. package/dist/kernel/moleculer/hub-service.d.ts +6 -16
  76. package/dist/kernel/moleculer/mesh-access-middleware.d.ts +7 -17
  77. package/dist/kernel/moleculer/mesh-identity.d.ts +57 -0
  78. package/dist/kernel/moleculer/mesh-mtls/constants.d.ts +1 -4
  79. package/dist/kernel/moleculer/mesh-mtls/index.d.ts +1 -4
  80. package/dist/kernel/moleculer/mesh-mtls/mesh-ca.d.ts +1 -1
  81. package/dist/kernel/moleculer/mesh-mtls/mesh-renewal.d.ts +1 -1
  82. package/dist/kernel/moleculer/node-registry.d.ts +0 -6
  83. package/dist/kernel/moleculer/register-node-client.d.ts +9 -7
  84. package/dist/{restore-archive-5ml7uYMf.mjs → restore-archive-BxmP1ChO.mjs} +1 -1
  85. package/dist/{restore-archive-Do0QwAik.js → restore-archive-D4h904rb.js} +1 -1
  86. package/dist/{retired-settings-keys-CyDdyjLP.mjs → retired-settings-keys-CQaknvx1.mjs} +1 -1
  87. package/dist/{retired-settings-keys-CEiCaI_j.js → retired-settings-keys-CYP5IZJ5.js} +1 -1
  88. package/dist/{wal-maintenance-LZYd8iT-.js → wal-maintenance-Br60onAQ.js} +0 -0
  89. package/dist/{wal-maintenance-DgLLPK14.mjs → wal-maintenance-CaDsrJM_.mjs} +0 -0
  90. package/package.json +1 -1
  91. package/dist/builtins/system-config/cluster-secret-keeper.d.ts +0 -63
  92. package/dist/constants-CrMPWOug.mjs +0 -102
  93. package/dist/constants-CuOfMdYe.js +0 -221
  94. package/dist/kernel/moleculer/agent-mesh-authenticator.d.ts +0 -91
  95. package/dist/kernel/moleculer/cluster-secret.d.ts +0 -46
  96. package/dist/kernel/moleculer/mesh-auth-mode.d.ts +0 -58
  97. package/dist/kernel/moleculer/mesh-authenticator.d.ts +0 -77
  98. package/dist/kernel/moleculer/mesh-auto-enforce.d.ts +0 -46
  99. package/dist/kernel/moleculer/mesh-join-client.d.ts +0 -73
  100. package/dist/kernel/moleculer/mesh-join-hold.d.ts +0 -85
  101. package/dist/kernel/moleculer/mesh-join-proof.d.ts +0 -39
  102. package/dist/kernel/moleculer/mesh-mtls/mesh-enroll.d.ts +0 -34
  103. package/dist/kernel/moleculer/mesh-mtls/mesh-join-token.d.ts +0 -56
@@ -1,221 +0,0 @@
1
- const require_dist = require("./dist-CCH3XPqO.js");
2
- let node_crypto = require("node:crypto");
3
- //#region src/kernel/moleculer/cluster-secret.ts
4
- /**
5
- * Cluster-secret registration gate (opt-in). A registering node sends a
6
- * SHA-256 hash of its cluster secret; the receiver of a `registerNode` RPC
7
- * verifies it. The raw secret is never transmitted.
8
- *
9
- * Where the secret lives (D797) — never in an environment variable:
10
- * - the HUB: the keychain, owner `system` ({@link CLUSTER_SECRET_REF}), set
11
- * from System → Cluster (a `password` field of `system-config`, whose
12
- * `system-settings` row {@link CLUSTER_SECRET_SETTINGS_KEY} holds the
13
- * marker). Empty = the gate is off, exactly as a hub without a secret
14
- * always was;
15
- * - an AGENT: its bootstrap credential, entered at pairing / first run and
16
- * kept in its own `agent.json` (0600) — or, in the desktop app, in the OS
17
- * keychain — because it needs it before it can reach the hub.
18
- */
19
- /** The keychain ref of the hub's cluster secret: `secret://system/global/clusterSecret`. */
20
- var CLUSTER_SECRET_REF = require_dist.buildSecretRef({
21
- owner: "system",
22
- scope: { kind: "global" },
23
- fieldPath: "clusterSecret"
24
- });
25
- /** The `system-settings` key whose value is the cluster secret's keychain marker. */
26
- var CLUSTER_SECRET_SETTINGS_KEY = "cluster.clusterSecret";
27
- /** Moleculer error `type` marking a registration rejected for a bad cluster secret. */
28
- var CLUSTER_SECRET_MISMATCH_TYPE = "CLUSTER_SECRET_MISMATCH";
29
- /** Process exit code a runner uses when its registration is rejected for a bad secret. */
30
- var CLUSTER_SECRET_REJECTED_EXIT_CODE = 78;
31
- /** SHA-256 hex digest of a cluster secret. Never transmit or log the raw secret. */
32
- function hashClusterSecret(secret) {
33
- return (0, node_crypto.createHash)("sha256").update(secret, "utf8").digest("hex");
34
- }
35
- /**
36
- * True if a registration carrying `presentedHash` is allowed against a
37
- * receiver whose own secret hashes to `expectedHash`.
38
- * - `expectedHash` undefined → the gate is OFF; everything is allowed.
39
- * - otherwise `presentedHash` must be present and equal (constant-time).
40
- */
41
- function clusterSecretMatches(expectedHash, presentedHash) {
42
- if (expectedHash === void 0) return true;
43
- if (presentedHash === void 0 || presentedHash.length !== expectedHash.length) return false;
44
- return (0, node_crypto.timingSafeEqual)(Buffer.from(expectedHash), Buffer.from(presentedHash));
45
- }
46
- /** Recognises a cluster-secret rejection, including after a Moleculer RPC round-trip. */
47
- function isClusterSecretMismatchError(err) {
48
- if (typeof err !== "object" || err === null || !("type" in err)) return false;
49
- const { type } = err;
50
- return type === CLUSTER_SECRET_MISMATCH_TYPE;
51
- }
52
- /** Moleculer error `type` of a registration refused because the hub cannot read its own secret yet. */
53
- var CLUSTER_SECRET_UNAVAILABLE_TYPE = "CLUSTER_SECRET_UNAVAILABLE";
54
- function checkClusterSecret(gate, presentedHash) {
55
- switch (gate.kind) {
56
- case "off": return "allow";
57
- case "unknown": return "unavailable";
58
- case "on": return clusterSecretMatches(gate.hash, presentedHash) ? "allow" : "mismatch";
59
- }
60
- }
61
- var GATE_SLOT = Symbol.for("camstack.cluster.secret-gate");
62
- var NOT_LOADED = {
63
- kind: "unknown",
64
- reason: "not-loaded"
65
- };
66
- function isGate(value) {
67
- if (value === null || typeof value !== "object") return false;
68
- const kind = Reflect.get(value, "kind");
69
- if (kind === "off") return true;
70
- if (kind === "on") return typeof Reflect.get(value, "hash") === "string";
71
- return kind === "unknown" && typeof Reflect.get(value, "reason") === "string";
72
- }
73
- /** Register the hub's gate. Called by `system-config`, which owns the field. */
74
- function setProcessClusterSecretGate(gate) {
75
- Reflect.set(globalThis, GATE_SLOT, gate);
76
- }
77
- /** The hub's gate; `unknown` until `system-config` loaded it. */
78
- function getProcessClusterSecretGate() {
79
- const value = Reflect.get(globalThis, GATE_SLOT);
80
- return isGate(value) ? value : NOT_LOADED;
81
- }
82
- /** `secret://system/global/meshCaKey` — EC P-256 PKCS#8 PEM of the hub mesh CA. */
83
- var MESH_CA_KEY_REF = require_dist.buildSecretRef({
84
- owner: "system",
85
- scope: { kind: "global" },
86
- fieldPath: "meshCaKey"
87
- });
88
- /** `system-settings` key holding the public CA certificate PEM. */
89
- var MESH_CA_SETTINGS_KEY = "cluster.meshCa";
90
- /** Field inside the `cluster` section. */
91
- var MESH_CA_FIELD = "meshCa";
92
- /** Join-token / leaf lifetimes. */
93
- var MESH_JOIN_TOKEN_MAX_TTL_SEC = 3600;
94
- var MESH_CA_VALIDITY_DAYS = 3650;
95
- var DEFAULT_HUB_TLS_TCP_PORT = 6443;
96
- /** Subject of the mesh root. Distinct from the HTTPS local CA. */
97
- var MESH_CA_COMMON_NAME = "CamStack Mesh CA";
98
- /** Client + server auth EKU OIDs (mutual TLS). */
99
- var SERVER_AUTH_OID = "1.3.6.1.5.5.7.3.1";
100
- var CLIENT_AUTH_OID = "1.3.6.1.5.5.7.3.2";
101
- //#endregion
102
- Object.defineProperty(exports, "CLIENT_AUTH_OID", {
103
- enumerable: true,
104
- get: function() {
105
- return CLIENT_AUTH_OID;
106
- }
107
- });
108
- Object.defineProperty(exports, "CLUSTER_SECRET_MISMATCH_TYPE", {
109
- enumerable: true,
110
- get: function() {
111
- return CLUSTER_SECRET_MISMATCH_TYPE;
112
- }
113
- });
114
- Object.defineProperty(exports, "CLUSTER_SECRET_REF", {
115
- enumerable: true,
116
- get: function() {
117
- return CLUSTER_SECRET_REF;
118
- }
119
- });
120
- Object.defineProperty(exports, "CLUSTER_SECRET_REJECTED_EXIT_CODE", {
121
- enumerable: true,
122
- get: function() {
123
- return CLUSTER_SECRET_REJECTED_EXIT_CODE;
124
- }
125
- });
126
- Object.defineProperty(exports, "CLUSTER_SECRET_SETTINGS_KEY", {
127
- enumerable: true,
128
- get: function() {
129
- return CLUSTER_SECRET_SETTINGS_KEY;
130
- }
131
- });
132
- Object.defineProperty(exports, "CLUSTER_SECRET_UNAVAILABLE_TYPE", {
133
- enumerable: true,
134
- get: function() {
135
- return CLUSTER_SECRET_UNAVAILABLE_TYPE;
136
- }
137
- });
138
- Object.defineProperty(exports, "DEFAULT_HUB_TLS_TCP_PORT", {
139
- enumerable: true,
140
- get: function() {
141
- return DEFAULT_HUB_TLS_TCP_PORT;
142
- }
143
- });
144
- Object.defineProperty(exports, "MESH_CA_COMMON_NAME", {
145
- enumerable: true,
146
- get: function() {
147
- return MESH_CA_COMMON_NAME;
148
- }
149
- });
150
- Object.defineProperty(exports, "MESH_CA_FIELD", {
151
- enumerable: true,
152
- get: function() {
153
- return MESH_CA_FIELD;
154
- }
155
- });
156
- Object.defineProperty(exports, "MESH_CA_KEY_REF", {
157
- enumerable: true,
158
- get: function() {
159
- return MESH_CA_KEY_REF;
160
- }
161
- });
162
- Object.defineProperty(exports, "MESH_CA_SETTINGS_KEY", {
163
- enumerable: true,
164
- get: function() {
165
- return MESH_CA_SETTINGS_KEY;
166
- }
167
- });
168
- Object.defineProperty(exports, "MESH_CA_VALIDITY_DAYS", {
169
- enumerable: true,
170
- get: function() {
171
- return MESH_CA_VALIDITY_DAYS;
172
- }
173
- });
174
- Object.defineProperty(exports, "MESH_JOIN_TOKEN_MAX_TTL_SEC", {
175
- enumerable: true,
176
- get: function() {
177
- return MESH_JOIN_TOKEN_MAX_TTL_SEC;
178
- }
179
- });
180
- Object.defineProperty(exports, "SERVER_AUTH_OID", {
181
- enumerable: true,
182
- get: function() {
183
- return SERVER_AUTH_OID;
184
- }
185
- });
186
- Object.defineProperty(exports, "checkClusterSecret", {
187
- enumerable: true,
188
- get: function() {
189
- return checkClusterSecret;
190
- }
191
- });
192
- Object.defineProperty(exports, "clusterSecretMatches", {
193
- enumerable: true,
194
- get: function() {
195
- return clusterSecretMatches;
196
- }
197
- });
198
- Object.defineProperty(exports, "getProcessClusterSecretGate", {
199
- enumerable: true,
200
- get: function() {
201
- return getProcessClusterSecretGate;
202
- }
203
- });
204
- Object.defineProperty(exports, "hashClusterSecret", {
205
- enumerable: true,
206
- get: function() {
207
- return hashClusterSecret;
208
- }
209
- });
210
- Object.defineProperty(exports, "isClusterSecretMismatchError", {
211
- enumerable: true,
212
- get: function() {
213
- return isClusterSecretMismatchError;
214
- }
215
- });
216
- Object.defineProperty(exports, "setProcessClusterSecretGate", {
217
- enumerable: true,
218
- get: function() {
219
- return setProcessClusterSecretGate;
220
- }
221
- });
@@ -1,91 +0,0 @@
1
- /**
2
- * AgentMeshAuthenticator — which peer may call THIS agent over the mesh
3
- * (D802 residual: agent inbound).
4
- *
5
- * The hub gate (`MeshAuthenticator`) is the other half of the same
6
- * containment. An agent reuses {@link createMeshAccessMiddleware} with this
7
- * admit policy:
8
- *
9
- * 1. **Hub.** Marked `authenticated` when {@link MeshJoinClient} settles a
10
- * mutual challenge–response (`noteHubJoinState`). Forgotten on disconnect.
11
- * 2. **Own children** (`${ownNodeId}/…`). May call `$agent.registerNode`
12
- * before they are authenticated (that call IS the proof — the handler
13
- * checks the cluster-secret hash). A successful register marks them
14
- * authenticated until disconnect.
15
- * 3. **Everyone else.** Refused in `enforced`, tolerated (with a warning
16
- * hook) in `transition`. Mode is `enforced` when this agent holds a
17
- * cluster secret, `transition` when it does not — so an upgrading agent
18
- * without a secret still serves the hub.
19
- *
20
- * The hub's requests that arrive while a join is in flight are HELD, not
21
- * refused (D848 §3, {@link MeshJoinHold}): delivered when the join proves the
22
- * hub, refused and reported when it fails or the bound runs out.
23
- *
24
- * Unlike the hub gate, `$process.*` is allowed from an authenticated hub:
25
- * the hub polls `$process.list` on agents. `$node.*` stays forbidden from
26
- * every remote peer. Forged `caller` / `callerAddonId` are stripped by the
27
- * shared middleware.
28
- *
29
- * Spoofing of a declared node id on clear-text Moleculer remains until mTLS
30
- * (`docs/design/2026-10-09-mesh-mtls-plan.md`) — same residual as the hub.
31
- */
32
- import type { MeshAuthMode, MeshNodeAuthState } from "./mesh-auth-mode.js";
33
- import type { MeshJoinState } from "./mesh-join-client.js";
34
- import { type MeshGateVerdict, type MeshJoinHoldReport } from "./mesh-join-hold.js";
35
- /** The child's register action on its parent agent. */
36
- export declare const AGENT_REGISTER_NODE_ACTION = "$agent.registerNode";
37
- export declare function isRemoteForbiddenOnAgent(action: string): boolean;
38
- export declare function isOwnChildNodeId(ownNodeId: string, sender: string): boolean;
39
- export interface AgentMeshAuthenticatorDeps {
40
- readonly ownNodeId: string;
41
- readonly hubNodeId?: string;
42
- /** True when `agent.json` holds a cluster secret. */
43
- readonly hasSecret: () => boolean;
44
- /**
45
- * D857 (transition release): the hub is accepted when its mutual-TLS leaf chained to the CA
46
- * this agent pinned, its CN is the hub's node id and it is not revoked — in ADDITION to the
47
- * mutual join. A hub that no longer answers the join (the removal release) is served at once.
48
- */
49
- readonly isVerifiedPeer?: (nodeId: string) => boolean;
50
- /**
51
- * True when `agent.json` holds mesh material. A paired agent is `enforced` even with no cluster
52
- * secret (D857): without this, an agent paired by certificate would tolerate strangers.
53
- */
54
- readonly isPaired?: () => boolean;
55
- readonly now?: () => number;
56
- /** First time a peer is tolerated without proof on this connection. */
57
- readonly onTolerated?: (nodeId: string, action: string) => void;
58
- /** Every decision about the hub's requests held before the join settled. */
59
- readonly onHoldReport?: (report: MeshJoinHoldReport) => void;
60
- /** Bounds of that hold (defaults: 1000 items, 15 s). */
61
- readonly maxHeld?: number;
62
- readonly maxHoldMs?: number;
63
- }
64
- export declare class AgentMeshAuthenticator {
65
- private readonly deps;
66
- private readonly nodes;
67
- private readonly hubNodeId;
68
- private readonly now;
69
- private readonly hold;
70
- constructor(deps: AgentMeshAuthenticatorDeps);
71
- /** How many of the hub's requests wait for the join right now. */
72
- heldCount(): number;
73
- /** Current mode: a secret OR a certificate → enforce; else tolerate (upgrade path). */
74
- mode(): MeshAuthMode;
75
- /**
76
- * Reflect a settled mesh join. `authenticated` stamps the hub; a blocking
77
- * failure forgets it so an impostor cannot call in; transitional states
78
- * leave the hub unmarked (calls are tolerated while mode is `transition`).
79
- */
80
- noteHubJoinState(state: MeshJoinState): void;
81
- /** A child's `$agent.registerNode` was accepted (secret hash matched or none required). */
82
- noteChildRegistered(sender: string, proof?: "authenticated" | "legacy"): void;
83
- /** The peer's connection dropped. */
84
- forget(nodeId: string): void;
85
- admitCall(sender: string, action: string): MeshGateVerdict;
86
- admitEvent(sender: string, eventName: string): MeshGateVerdict;
87
- stateOf(nodeId: string): MeshNodeAuthState;
88
- authenticatedNodeIds(): readonly string[];
89
- private admitSender;
90
- private record;
91
- }
@@ -1,46 +0,0 @@
1
- /** The keychain ref of the hub's cluster secret: `secret://system/global/clusterSecret`. */
2
- export declare const CLUSTER_SECRET_REF: string;
3
- /** The `system-settings` key whose value is the cluster secret's keychain marker. */
4
- export declare const CLUSTER_SECRET_SETTINGS_KEY = "cluster.clusterSecret";
5
- /** Moleculer error `type` marking a registration rejected for a bad cluster secret. */
6
- export declare const CLUSTER_SECRET_MISMATCH_TYPE = "CLUSTER_SECRET_MISMATCH";
7
- /** Process exit code a runner uses when its registration is rejected for a bad secret. */
8
- export declare const CLUSTER_SECRET_REJECTED_EXIT_CODE = 78;
9
- /** SHA-256 hex digest of a cluster secret. Never transmit or log the raw secret. */
10
- export declare function hashClusterSecret(secret: string): string;
11
- /**
12
- * True if a registration carrying `presentedHash` is allowed against a
13
- * receiver whose own secret hashes to `expectedHash`.
14
- * - `expectedHash` undefined → the gate is OFF; everything is allowed.
15
- * - otherwise `presentedHash` must be present and equal (constant-time).
16
- */
17
- export declare function clusterSecretMatches(expectedHash: string | undefined, presentedHash: string | undefined): boolean;
18
- /** Recognises a cluster-secret rejection, including after a Moleculer RPC round-trip. */
19
- export declare function isClusterSecretMismatchError(err: unknown): boolean;
20
- /** Moleculer error `type` of a registration refused because the hub cannot read its own secret yet. */
21
- export declare const CLUSTER_SECRET_UNAVAILABLE_TYPE = "CLUSTER_SECRET_UNAVAILABLE";
22
- /**
23
- * What the hub knows about its own cluster secret:
24
- * - `off`: none is set — every node may register (the behaviour of a hub
25
- * that never had a secret);
26
- * - `on`: set — a node must present the matching hash;
27
- * - `unknown`: one is set (the marker exists) but the keychain cannot answer
28
- * yet — registrations are refused with a RETRYABLE error until it does.
29
- * Fail closed: a locked keychain never opens the gate.
30
- */
31
- export type ClusterSecretGate = {
32
- readonly kind: "off";
33
- } | {
34
- readonly kind: "on";
35
- readonly hash: string;
36
- } | {
37
- readonly kind: "unknown";
38
- readonly reason: string;
39
- };
40
- export type ClusterSecretVerdict = "allow" | "mismatch" | "unavailable";
41
- export declare function checkClusterSecret(gate: ClusterSecretGate, presentedHash: string | undefined): ClusterSecretVerdict;
42
- /** Register the hub's gate. Called by `system-config`, which owns the field. */
43
- export declare function setProcessClusterSecretGate(gate: ClusterSecretGate): void;
44
- export declare function clearProcessClusterSecretGate(): void;
45
- /** The hub's gate; `unknown` until `system-config` loaded it. */
46
- export declare function getProcessClusterSecretGate(): ClusterSecretGate;
@@ -1,58 +0,0 @@
1
- /**
2
- * How strictly the hub holds other nodes to the mesh join (D802).
3
- *
4
- * - `transition`: a node that has not authenticated is TOLERATED — its calls
5
- * run, a warning names it, and System → Cluster lists it as "not
6
- * authenticated". This is how an existing cluster upgrades without
7
- * splitting: the hub generates its secret, the operator copies it into each
8
- * agent, and nothing is refused meanwhile.
9
- * - `enforced`: a node that has not authenticated is refused on every action
10
- * and its events are dropped. The D797 hash in `registerNode` is no longer
11
- * accepted either — only the challenge–response.
12
- *
13
- * `transition` ends by itself once EVERY node the hub has ever seen (the
14
- * cluster-node history) has authenticated with the challenge–response
15
- * (`MeshAuthenticator.onAuthenticated` → `requestProcessMeshEnforcement`).
16
- * The operator can also switch it in System → Cluster, in both directions.
17
- *
18
- * The mode lives in the `cluster` section of `system-settings`
19
- * (`cluster.meshAuth`), owned by `system-config`, published here as a process
20
- * slot the hub's broker reads on every call — the same pattern as the cluster
21
- * secret gate (`cluster-secret.ts`).
22
- */
23
- export type MeshAuthMode = "transition" | "enforced";
24
- /** The field key inside the `cluster` section. */
25
- export declare const MESH_AUTH_MODE_FIELD = "meshAuth";
26
- export declare function isMeshAuthMode(value: unknown): value is MeshAuthMode;
27
- /** A stored value that is not a mode reads as `transition`: never refuse on a typo. */
28
- export declare function parseMeshAuthMode(value: unknown): MeshAuthMode;
29
- /** How a node stands with the hub right now. */
30
- export type MeshNodeAuthState = "authenticated" | "legacy" | "unauthenticated";
31
- export interface MeshNodeAuthEntry {
32
- readonly nodeId: string;
33
- readonly state: MeshNodeAuthState;
34
- /** Epoch ms of the last change. */
35
- readonly since: number;
36
- }
37
- /** What System → Cluster shows. */
38
- export interface MeshAuthStatus {
39
- readonly mode: MeshAuthMode;
40
- readonly nodes: readonly MeshNodeAuthEntry[];
41
- }
42
- /** Published by `system-config` whenever the stored mode is (re)read. */
43
- export declare function setProcessMeshAuthMode(mode: MeshAuthMode): void;
44
- /**
45
- * The hub's mode. Until `system-config` has read it: `transition` — the safe
46
- * side for an upgrading cluster (nothing that worked before is refused), and
47
- * exactly what an unread setting means.
48
- */
49
- export declare function getProcessMeshAuthMode(): MeshAuthMode;
50
- export declare function clearProcessMeshAuthMode(): void;
51
- /** Persists `enforced`; installed by `system-config`, which owns the setting. */
52
- export type MeshEnforcer = (reason: string) => Promise<void>;
53
- export declare function setProcessMeshEnforcer(enforcer: MeshEnforcer | null): void;
54
- /** Ask the owner of the setting to switch to `enforced`. `false` when nobody can. */
55
- export declare function requestProcessMeshEnforcement(reason: string): Promise<boolean>;
56
- /** Published by the hub's broker; read by System → Cluster. */
57
- export declare function setProcessMeshAuthStatusSource(source: (() => MeshAuthStatus) | null): void;
58
- export declare function getProcessMeshAuthStatus(): MeshAuthStatus | null;
@@ -1,77 +0,0 @@
1
- import { type ClusterSecretGate } from "./cluster-secret.js";
2
- import type { MeshAuthMode, MeshAuthStatus, MeshNodeAuthState } from "./mesh-auth-mode.js";
3
- import { type MeshJoinAuthenticateParams, type MeshJoinAuthenticateResult, type MeshJoinChallenge } from "./mesh-join-proof.js";
4
- /** A challenge is answered within this window or not at all. */
5
- export declare const MESH_JOIN_CHALLENGE_TTL_MS = 6e4;
6
- export declare function isRemoteForbiddenAction(action: string): boolean;
7
- export type MeshCallVerdict = {
8
- readonly verdict: "allow";
9
- readonly errorType?: undefined;
10
- } | {
11
- readonly verdict: "tolerate";
12
- readonly errorType?: undefined;
13
- } | {
14
- readonly verdict: "deny";
15
- readonly errorType: string;
16
- readonly message: string;
17
- };
18
- export interface MeshAuthenticatorDeps {
19
- /** The hub's own node id — its local calls never pass through here. */
20
- readonly ownNodeId: string;
21
- /** The cluster secret as the keychain answers it now (D797). */
22
- readonly gate: () => ClusterSecretGate;
23
- readonly mode: () => MeshAuthMode;
24
- /**
25
- * D857 (transition release): a node whose mutual-TLS handshake chained to the mesh CA, whose CN
26
- * is its node id and whose leaf is not revoked is admitted WITHOUT the challenge–response. The
27
- * join stays answered for agents that still need it.
28
- */
29
- readonly isVerifiedPeer?: (nodeId: string) => boolean;
30
- readonly now?: () => number;
31
- /** A node completed the challenge–response. */
32
- readonly onAuthenticated?: (nodeId: string) => void;
33
- /** First time a node is tolerated without proof on this connection. */
34
- readonly onTolerated?: (nodeId: string, action: string) => void;
35
- }
36
- interface RegistrationLike {
37
- readonly nodeId: string;
38
- readonly clusterSecretHash?: string;
39
- }
40
- export declare class MeshAuthenticator {
41
- private readonly deps;
42
- private readonly challenges;
43
- private readonly nodes;
44
- /** Completed the challenge–response at least once since the hub started. */
45
- private readonly everAuthenticated;
46
- /** Let in WITHOUT the challenge–response at least once since the hub started. */
47
- private readonly everTolerated;
48
- private readonly now;
49
- constructor(deps: MeshAuthenticatorDeps);
50
- issueChallenge(sender: string): MeshJoinChallenge;
51
- authenticate(sender: string, params: MeshJoinAuthenticateParams): MeshJoinAuthenticateResult;
52
- /** The node's connection dropped: it authenticates again when it returns. */
53
- forget(nodeId: string): void;
54
- admitCall(sender: string, action: string): MeshCallVerdict;
55
- /** Same rule as a call, for an inbound event. */
56
- admitEvent(sender: string, eventName: string): MeshCallVerdict;
57
- private admitSender;
58
- /** Throws when `sender` may not register `params`; returns when it may. */
59
- admitRegistration(sender: string, params: RegistrationLike): void;
60
- private noteTolerated;
61
- stateOf(nodeId: string): MeshNodeAuthState;
62
- /** Node ids that completed the challenge–response on their current connection. */
63
- authenticatedNodeIds(): readonly string[];
64
- /** Node ids that ever completed the challenge–response since the hub started. */
65
- everAuthenticatedNodeIds(): ReadonlySet<string>;
66
- /**
67
- * Node ids let in without the challenge–response since the hub started.
68
- * Bounded: past {@link MAX_TRACKED_NODES} a flood of fake ids stops adding,
69
- * and the ones already here keep the transition open (the operator can still
70
- * switch to `enforced` by hand).
71
- */
72
- everToleratedNodeIds(): readonly string[];
73
- snapshot(): MeshAuthStatus;
74
- private record;
75
- private secretHashOrThrow;
76
- }
77
- export {};
@@ -1,46 +0,0 @@
1
- /**
2
- * When `transition` may end by itself (D802).
3
- *
4
- * The rule the operator chose: enforce once EVERY known agent has presented
5
- * the secret. "Known" is deliberately wide, so the switch can never cut off an
6
- * agent the hub merely forgot about:
7
- * - every node in the durable cluster-node history (offline ones included —
8
- * an agent that is down today still holds no secret tomorrow);
9
- * - every node connected right now;
10
- * - every node tolerated without proof since the hub started.
11
- *
12
- * and it waits:
13
- * - for the history to ANSWER (an unanswered read is never "no agents");
14
- * - for a grace period after boot, so agents restarting with the hub are
15
- * back before an empty roster is taken at its word;
16
- * - for the secret to exist (`on`) — nothing can authenticate without it.
17
- *
18
- * "Presented" means completed the challenge–response at least once since the
19
- * hub started. The D797 hash does not count: it is what `enforced` refuses.
20
- */
21
- import type { ClusterSecretGate } from "./cluster-secret.js";
22
- import type { MeshAuthMode } from "./mesh-auth-mode.js";
23
- /** Boot grace before an empty or partial roster can end the transition. */
24
- export declare const MESH_AUTO_ENFORCE_GRACE_MS: number;
25
- export interface MeshAutoEnforceInput {
26
- readonly mode: MeshAuthMode;
27
- readonly gate: ClusterSecretGate["kind"];
28
- readonly uptimeMs: number;
29
- readonly graceMs?: number;
30
- /** Agent node ids from the cluster-node history; `null` = the store did not answer. */
31
- readonly knownAgents: readonly string[] | null;
32
- readonly connected: readonly string[];
33
- readonly toleratedEver: readonly string[];
34
- readonly authenticatedEver: ReadonlySet<string>;
35
- /** The hub's own id and its local children (`hub/<runner>`) are not agents. */
36
- readonly ownNodeId: string;
37
- }
38
- export type MeshAutoEnforceDecision = {
39
- readonly enforce: true;
40
- readonly reason: string;
41
- } | {
42
- readonly enforce: false;
43
- readonly waitingFor: readonly string[];
44
- readonly why: string;
45
- };
46
- export declare function decideMeshAutoEnforce(input: MeshAutoEnforceInput): MeshAutoEnforceDecision;
@@ -1,73 +0,0 @@
1
- /**
2
- * MeshJoinClient — the agent half of the mesh join (D802).
3
- *
4
- * On every connection to the hub the agent runs the challenge–response
5
- * (`mesh-join-proof.ts`) BEFORE anything else reaches the hub: the broker
6
- * middleware from {@link MeshJoinClient.middleware} holds every call to the
7
- * hub node until the join has settled. The agent also checks the hub's proof,
8
- * so a node answering to `hub` without the secret is refused.
9
- *
10
- * Settled states, and what a call to the hub does in each:
11
- * - `authenticated` — mutual proof done → calls flow;
12
- * - `no-secret` — this agent holds no secret → calls flow and the hub
13
- * decides (tolerated in `transition`, refused in
14
- * `enforced`);
15
- * - `unsupported` — the hub predates D802 → calls flow; the agent falls
16
- * back to the D797 hash in `registerNode` (one release);
17
- * - `unavailable` — the hub cannot read its secret yet, or did not answer
18
- * → calls flow (the hub decides) and the owner retries
19
- * the join;
20
- * - `secret-mismatch` — the hub refused our proof → calls are REJECTED;
21
- * - `hub-unverified` — the hub could not prove the secret → REJECTED.
22
- */
23
- import type { Middleware } from "moleculer";
24
- export type MeshJoinState = "pending" | "authenticated" | "no-secret" | "unsupported" | "unavailable" | "secret-mismatch" | "hub-unverified";
25
- export type MeshJoinCall = (action: string, params: unknown, opts?: {
26
- nodeID?: string;
27
- timeout?: number;
28
- }) => Promise<unknown>;
29
- export interface MeshJoinClientOptions {
30
- readonly nodeId: string;
31
- /** The agent's cluster secret, read at each join (the operator may enter it at runtime). */
32
- readonly secret: () => string | null;
33
- readonly call: MeshJoinCall;
34
- readonly hubNodeId?: string;
35
- readonly maxAttempts?: number;
36
- readonly retryDelayMs?: number;
37
- readonly callTimeoutMs?: number;
38
- /** How long a call waits for a pending join before it fails (default 30 s). */
39
- readonly pendingWaitMs?: number;
40
- readonly log?: (message: string) => void;
41
- /** Told about every settled state. */
42
- readonly onSettled?: (state: MeshJoinState) => void;
43
- }
44
- export declare class MeshJoinClient {
45
- private readonly opts;
46
- private current;
47
- private settledWaiters;
48
- private inFlight;
49
- private readonly hubNodeId;
50
- constructor(opts: MeshJoinClientOptions);
51
- get state(): MeshJoinState;
52
- /** Did this agent prove itself on the current connection? */
53
- get authenticated(): boolean;
54
- /**
55
- * Run the join. Concurrent callers share one attempt. Resolves with the
56
- * settled state; never rejects.
57
- */
58
- join(): Promise<MeshJoinState>;
59
- /** The hub connection dropped: the next connection authenticates again. */
60
- reset(): void;
61
- /** Resolves when a call to the hub may go out; rejects when it must not. */
62
- whenCallable(): Promise<void>;
63
- /**
64
- * Moleculer middleware for the AGENT broker: every call to the hub node waits
65
- * for the join; a hub answer "not authenticated" (the hub restarted and lost
66
- * us) triggers a new join.
67
- */
68
- middleware(onUnauthenticated?: () => void): Middleware;
69
- private secretPresent;
70
- private settle;
71
- private runJoin;
72
- private attempt;
73
- }