@camstack/system 1.2.377 → 1.2.379
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/addon-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/addon-utils.js +1 -1
- package/dist/addon-utils.mjs +1 -1
- package/dist/auth/auth-manager.d.ts +10 -2
- package/dist/auth/jwt-signing-key.d.ts +42 -0
- package/dist/auth/user-manager.d.ts +19 -19
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +67 -11
- package/dist/builtins/keychain/index.mjs +67 -11
- package/dist/builtins/keychain/keychain-service.d.ts +14 -2
- package/dist/builtins/keychain/system-held-secrets.d.ts +11 -0
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/admin-account-boot.d.ts +1 -1
- package/dist/builtins/local-auth/auth-config-reader.d.ts +9 -7
- package/dist/builtins/local-auth/jwt-signing-key-keeper.d.ts +30 -0
- package/dist/builtins/local-auth/local-auth.addon.d.ts +2 -6
- package/dist/builtins/local-auth/local-auth.addon.js +127 -221
- package/dist/builtins/local-auth/local-auth.addon.mjs +126 -220
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/cluster-secret-keeper.d.ts +36 -0
- package/dist/builtins/system-config/system-config.addon.d.ts +13 -0
- package/dist/builtins/system-config/system-config.addon.js +244 -53
- package/dist/builtins/system-config/system-config.addon.mjs +244 -54
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{child-cap-dispatch-DlDSoqm1.js → child-cap-dispatch-CZeRUgYF.js} +1 -1
- package/dist/{child-cap-dispatch-CgmOo0yl.mjs → child-cap-dispatch-CpjohToR.mjs} +1 -1
- package/dist/cluster-secret-BDue-uJj.mjs +83 -0
- package/dist/cluster-secret-Dg0OOOSr.js +148 -0
- package/dist/{composition-sources-BNyXPSs_.js → composition-sources-CHvLMrFI.js} +1 -1
- package/dist/{composition-sources-D39bl0nP.mjs → composition-sources-DT_uJwI3.mjs} +1 -1
- package/dist/{dist-BWNoS-1S.mjs → dist-B9oFw2jh.mjs} +200 -3
- package/dist/{dist-D_a9mUiM.js → dist-Cc6KOdY-.js} +211 -2
- package/dist/{event-loop-stall-monitor-ClPhfx7Y.mjs → event-loop-stall-monitor-anUH2IE1.mjs} +21 -20
- package/dist/{event-loop-stall-monitor-DuOn8H1n.js → event-loop-stall-monitor-mk6WGxir.js} +21 -20
- package/dist/index.d.ts +4 -2
- package/dist/index.js +192 -62
- package/dist/index.mjs +171 -55
- package/dist/jwt-signing-key-C2rE3wH6.js +174 -0
- package/dist/jwt-signing-key-Qhde8r82.mjs +127 -0
- package/dist/kernel/config-manager.d.ts +1 -1
- package/dist/kernel/config-schema.d.ts +4 -11
- package/dist/kernel/index.d.ts +2 -1
- package/dist/kernel/moleculer/broker-factory.d.ts +0 -2
- package/dist/kernel/moleculer/cluster-secret.d.ts +31 -0
- package/dist/kernel/moleculer/hub-service.d.ts +7 -4
- package/dist/kernel/moleculer/node-registry.d.ts +1 -1
- package/dist/kernel/system-settings-policy.d.ts +7 -9
- package/dist/{retired-settings-keys-iGcmzwLV.mjs → retired-settings-keys-DlZ3VV6x.mjs} +1 -1
- package/dist/{retired-settings-keys-CDyOGAje.js → retired-settings-keys-YOOKLA3v.js} +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dr as formatSecretScope, Gt as keychainCapability, Ir as parseSecretRef, Nr as normalizeSecretOwner, Wt as keychainAdminCapability, lr as BaseAddon, qr as EventCategory } from "../../dist-B9oFw2jh.mjs";
|
|
2
|
+
import { r as SYSTEM_SECRET_OWNER, t as JWT_SIGNING_KEY_REF } from "../../jwt-signing-key-Qhde8r82.mjs";
|
|
3
|
+
import { i as CLUSTER_SECRET_SETTINGS_KEY } from "../../cluster-secret-BDue-uJj.mjs";
|
|
2
4
|
import { n as getPlatformKeychainKey } from "../../platform-key-source-BWlq0jjn.mjs";
|
|
3
5
|
import { createCipheriv, createDecipheriv, createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
4
6
|
import * as path$1 from "node:path";
|
|
@@ -197,6 +199,13 @@ function buildKeySourceCandidates(opts) {
|
|
|
197
199
|
*/
|
|
198
200
|
async function writeDefaultKeyFile(dataDir, key, opts) {
|
|
199
201
|
const file = defaultKeyFilePath(dataDir);
|
|
202
|
+
try {
|
|
203
|
+
return await writeKeyFileAt(file, key, opts);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
throw new Error(`could not write the master key at ${file}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async function writeKeyFileAt(file, key, opts) {
|
|
200
209
|
const dir = path$1.dirname(file);
|
|
201
210
|
await promises.mkdir(dir, {
|
|
202
211
|
recursive: true,
|
|
@@ -217,6 +226,8 @@ async function writeDefaultKeyFile(dataDir, key, opts) {
|
|
|
217
226
|
await promises.writeFile(tmp, `${encodeKeyMaterial(key)}\n`, { mode: 384 });
|
|
218
227
|
await promises.rename(tmp, file);
|
|
219
228
|
await promises.chmod(file, 384);
|
|
229
|
+
const back = await loadKeyFile(file);
|
|
230
|
+
if (back.kind !== "loaded" || !back.key.equals(key)) throw new Error("the written key file does not read back as the generated key");
|
|
220
231
|
return movedAside;
|
|
221
232
|
}
|
|
222
233
|
//#endregion
|
|
@@ -620,6 +631,14 @@ var KeychainRepository = class {
|
|
|
620
631
|
return rows.length;
|
|
621
632
|
}
|
|
622
633
|
};
|
|
634
|
+
//#endregion
|
|
635
|
+
//#region src/builtins/keychain/system-held-secrets.ts
|
|
636
|
+
/** The refs `keychain-admin.setSystemSecret` may write, by name. */
|
|
637
|
+
var SYSTEM_HELD_SECRET_REFS = { "jwt-signing-key": JWT_SIGNING_KEY_REF };
|
|
638
|
+
/** System refs no blob points at — in use for as long as they exist. */
|
|
639
|
+
var PROCESS_HELD_SECRET_REFS = new Set([JWT_SIGNING_KEY_REF]);
|
|
640
|
+
/** `system-settings` keys that may hold a system-owned secret's marker. */
|
|
641
|
+
var SYSTEM_SECRET_SETTINGS_KEYS = [CLUSTER_SECRET_SETTINGS_KEY];
|
|
623
642
|
var KeychainLockedError = class extends Error {
|
|
624
643
|
reason;
|
|
625
644
|
constructor(reason) {
|
|
@@ -664,10 +683,14 @@ var KeychainService = class {
|
|
|
664
683
|
this.unlock = await this.computeUnlock();
|
|
665
684
|
if (this.unlock.state === "ready") this.deps.logger.info("keychain unlocked", {
|
|
666
685
|
source: this.unlock.source.kind,
|
|
686
|
+
path: this.unlock.source.path,
|
|
667
687
|
fingerprint: shortFingerprint(this.unlock.fingerprint),
|
|
668
688
|
rotationPending: this.unlock.rotationPending
|
|
669
689
|
});
|
|
670
|
-
else this.deps.logger.error("keychain LOCKED — every secret resolves unavailable", {
|
|
690
|
+
else this.deps.logger.error("keychain LOCKED — every secret resolves unavailable", {
|
|
691
|
+
reason: this.unlock.reason,
|
|
692
|
+
path: this.configuredSource?.path
|
|
693
|
+
});
|
|
671
694
|
try {
|
|
672
695
|
await this.deps.repo.pruneAudit(this.now());
|
|
673
696
|
} catch (err) {
|
|
@@ -759,10 +782,19 @@ var KeychainService = class {
|
|
|
759
782
|
};
|
|
760
783
|
else if (primary.source.kind === "default-file") {
|
|
761
784
|
kek = generateKey();
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
785
|
+
try {
|
|
786
|
+
await writeDefaultKeyFile(this.deps.dataDir, kek, {
|
|
787
|
+
replace: false,
|
|
788
|
+
nowMs: this.now()
|
|
789
|
+
});
|
|
790
|
+
} catch (err) {
|
|
791
|
+
this.deps.logger.error("keychain master key could NOT be generated — no key stored", {
|
|
792
|
+
path: primary.source.path,
|
|
793
|
+
error: errMsg(err)
|
|
794
|
+
});
|
|
795
|
+
throw err;
|
|
796
|
+
}
|
|
797
|
+
this.deps.logger.info("keychain master key generated", { path: primary.source.path });
|
|
766
798
|
} else return {
|
|
767
799
|
state: "locked",
|
|
768
800
|
reason: "key-missing"
|
|
@@ -817,7 +849,11 @@ var KeychainService = class {
|
|
|
817
849
|
if (parts === null || !this.owns(caller, parts.owner)) throw new KeychainForbiddenError(ref, caller);
|
|
818
850
|
return parts.owner;
|
|
819
851
|
}
|
|
820
|
-
|
|
852
|
+
/**
|
|
853
|
+
* @param actor who the audit names — the owner addon by default; the
|
|
854
|
+
* operator (`user:<id>`) for {@link setSystemSecret}.
|
|
855
|
+
*/
|
|
856
|
+
async put(caller, ref, value, actor = actorOfAddon(caller)) {
|
|
821
857
|
const owner = this.ownerOf(ref, caller);
|
|
822
858
|
const unlocked = this.requireReady();
|
|
823
859
|
if (value.length === 0) throw new Error("keychain.put: an empty value is not stored — delete the ref");
|
|
@@ -843,10 +879,10 @@ var KeychainService = class {
|
|
|
843
879
|
version,
|
|
844
880
|
createdAt: existing?.createdAt ?? t,
|
|
845
881
|
updatedAt: t,
|
|
846
|
-
updatedBy:
|
|
882
|
+
updatedBy: actor,
|
|
847
883
|
lastReadAt: existing?.lastReadAt ?? null
|
|
848
884
|
});
|
|
849
|
-
await this.audit("put",
|
|
885
|
+
await this.audit("put", actor, ref, `version=${version}`);
|
|
850
886
|
this.deps.events.emit({
|
|
851
887
|
ref,
|
|
852
888
|
owner,
|
|
@@ -976,6 +1012,14 @@ var KeychainService = class {
|
|
|
976
1012
|
usage: usage.get(row.ref) ?? "unknown"
|
|
977
1013
|
}));
|
|
978
1014
|
}
|
|
1015
|
+
/**
|
|
1016
|
+
* The operator replaces a system-held secret no form edits (D797) — the
|
|
1017
|
+
* session signing key. Stored under owner `system`, audited as the user.
|
|
1018
|
+
*/
|
|
1019
|
+
async setSystemSecret(userId, name, value) {
|
|
1020
|
+
const ref = SYSTEM_HELD_SECRET_REFS[name];
|
|
1021
|
+
return this.put(SYSTEM_SECRET_OWNER, ref, value, `user:${userId}`);
|
|
1022
|
+
}
|
|
979
1023
|
async listAudit(limit) {
|
|
980
1024
|
return this.deps.repo.listAudit(limit);
|
|
981
1025
|
}
|
|
@@ -1215,6 +1259,13 @@ async function prefixRows(door, collection, prefix) {
|
|
|
1215
1259
|
}
|
|
1216
1260
|
/** The blobs that may hold the marker of a ref in `scope`; `null` = cannot tell. */
|
|
1217
1261
|
async function blobsFor(door, owner, scope) {
|
|
1262
|
+
if (owner === "system" && scope.kind === "global") return [[...PROCESS_HELD_SECRET_REFS].map((ref) => ({
|
|
1263
|
+
$secret: ref,
|
|
1264
|
+
v: 1
|
|
1265
|
+
})), ...await Promise.all(SYSTEM_SECRET_SETTINGS_KEYS.map((key) => door.get({
|
|
1266
|
+
collection: "system-settings",
|
|
1267
|
+
key
|
|
1268
|
+
})))];
|
|
1218
1269
|
switch (scope.kind) {
|
|
1219
1270
|
case "global":
|
|
1220
1271
|
case "node": {
|
|
@@ -1303,8 +1354,12 @@ function createKeychainUsageCheck(door) {
|
|
|
1303
1354
|
* orphans, rotation, recovery key, reset. Every method admin; the four
|
|
1304
1355
|
* that change or hand out material take the session's user for the audit.
|
|
1305
1356
|
*
|
|
1306
|
-
* It does not run on agents:
|
|
1307
|
-
*
|
|
1357
|
+
* It does not run on agents: an agent's Phase 1 drops `keychain` from its infra
|
|
1358
|
+
* list (`server/backend/src/agent/agent-infra-capabilities.ts`), and an agent
|
|
1359
|
+
* addon reaches it through `$hub-cap-fwd` like every other hub cap. Until
|
|
1360
|
+
* 2026-10-08 agents DID boot it — their store door forwards to the hub, so an
|
|
1361
|
+
* agent wrote the hub's `keychain:keys` row with a key file on its own disk.
|
|
1362
|
+
* Booting first, it left the hub locked `key-missing`.
|
|
1308
1363
|
*/
|
|
1309
1364
|
var DAY_MS = 1440 * 6e4;
|
|
1310
1365
|
/** The caller the transport stamped (or an in-process caller stated). */
|
|
@@ -1392,6 +1447,7 @@ var KeychainAddon = class extends BaseAddon {
|
|
|
1392
1447
|
listSecrets: () => service.listSecrets(),
|
|
1393
1448
|
listAudit: (input) => service.listAudit(input.limit ?? 100),
|
|
1394
1449
|
reveal: (input) => service.reveal(input.caller.userId, input.ref),
|
|
1450
|
+
setSystemSecret: (input) => service.setSystemSecret(input.caller.userId, input.name, input.value),
|
|
1395
1451
|
deleteOrphans: (input) => service.deleteOrphans(input.caller.userId, input.refs),
|
|
1396
1452
|
rotateMasterKey: (input) => service.rotateMasterKey(input.caller.userId),
|
|
1397
1453
|
purgeRetiredKeys: async (input) => ({ purged: await service.purgeRetiredKeys(input.caller.userId) }),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventCategory, KeychainAuditEntry, KeychainKeySource, KeychainResolveResult, KeychainSecretMeta, KeychainSecretUsage, KeychainState, KeychainStatus, KeychainUnavailableReason } from '@camstack/types';
|
|
1
|
+
import { EventCategory, KeychainAuditEntry, KeychainKeySource, KeychainResolveResult, KeychainSecretMeta, KeychainSecretUsage, KeychainState, KeychainStatus, KeychainUnavailableReason, SystemHeldSecretName } from '@camstack/types';
|
|
2
2
|
import { KeychainRepository, KeychainSecretRow } from './keychain-store.js';
|
|
3
3
|
import { KeySourceCandidate } from './key-sources.js';
|
|
4
4
|
/** `lastReadAt` is written at most this often per ref (hub I/O is the bottleneck). */
|
|
@@ -54,7 +54,11 @@ export declare class KeychainService {
|
|
|
54
54
|
/** May `caller` touch values owned by `owner`? */
|
|
55
55
|
owns(caller: string | null, owner: string): boolean;
|
|
56
56
|
private ownerOf;
|
|
57
|
-
|
|
57
|
+
/**
|
|
58
|
+
* @param actor who the audit names — the owner addon by default; the
|
|
59
|
+
* operator (`user:<id>`) for {@link setSystemSecret}.
|
|
60
|
+
*/
|
|
61
|
+
put(caller: string | null, ref: string, value: string, actor?: string): Promise<{
|
|
58
62
|
ref: string;
|
|
59
63
|
version: number;
|
|
60
64
|
}>;
|
|
@@ -66,6 +70,14 @@ export declare class KeychainService {
|
|
|
66
70
|
listSecrets(): Promise<readonly (KeychainSecretMeta & {
|
|
67
71
|
usage: KeychainSecretUsage;
|
|
68
72
|
})[]>;
|
|
73
|
+
/**
|
|
74
|
+
* The operator replaces a system-held secret no form edits (D797) — the
|
|
75
|
+
* session signing key. Stored under owner `system`, audited as the user.
|
|
76
|
+
*/
|
|
77
|
+
setSystemSecret(userId: string, name: SystemHeldSecretName, value: string): Promise<{
|
|
78
|
+
ref: string;
|
|
79
|
+
version: number;
|
|
80
|
+
}>;
|
|
69
81
|
listAudit(limit: number): Promise<readonly KeychainAuditEntry[]>;
|
|
70
82
|
reveal(userId: string, ref: string): Promise<{
|
|
71
83
|
value: string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SystemHeldSecretName } from '@camstack/types';
|
|
2
|
+
import { SYSTEM_SECRET_OWNER } from '../../auth/jwt-signing-key.js';
|
|
3
|
+
import { CLUSTER_SECRET_REF } from '../../kernel/moleculer/cluster-secret.js';
|
|
4
|
+
export { SYSTEM_SECRET_OWNER };
|
|
5
|
+
/** The refs `keychain-admin.setSystemSecret` may write, by name. */
|
|
6
|
+
export declare const SYSTEM_HELD_SECRET_REFS: Readonly<Record<SystemHeldSecretName, string>>;
|
|
7
|
+
/** System refs no blob points at — in use for as long as they exist. */
|
|
8
|
+
export declare const PROCESS_HELD_SECRET_REFS: ReadonlySet<string>;
|
|
9
|
+
/** `system-settings` keys that may hold a system-owned secret's marker. */
|
|
10
|
+
export declare const SYSTEM_SECRET_SETTINGS_KEYS: readonly string[];
|
|
11
|
+
export { CLUSTER_SECRET_REF };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-Cc6KOdY-.js");
|
|
4
4
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
5
5
|
var NO_DEVICES = "liveness:no-devices";
|
|
6
6
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Cr as createEvent, F as RecordingStatusSchema, N as RECORDING_SOURCE_CAMSTACK_ADDON, cr as errMsg, lr as BaseAddon, qr as EventCategory } from "../../dist-B9oFw2jh.mjs";
|
|
2
2
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
3
3
|
var NO_DEVICES = "liveness:no-devices";
|
|
4
4
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -21,7 +21,7 @@ export interface AdminAccountBootInput {
|
|
|
21
21
|
}
|
|
22
22
|
export interface AdminAccountBootResult {
|
|
23
23
|
readonly outcome: AdminSeedOutcome;
|
|
24
|
-
/** The admin still signs in with {@link
|
|
24
|
+
/** The admin still signs in with {@link FIRST_BOOT_ADMIN_PASSWORD}. */
|
|
25
25
|
readonly usesDefaultPassword: boolean;
|
|
26
26
|
}
|
|
27
27
|
export declare function reconcileAdminAccountAtBoot(input: AdminAccountBootInput): Promise<AdminAccountBootResult>;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { AuthConfigReader } from '../../auth/auth-manager.js';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The values `local-auth` pre-resolves before constructing its AuthManager.
|
|
4
|
+
*
|
|
5
|
+
* No credential is among them (D797): the session signing key lives in the
|
|
6
|
+
* keychain (`jwt-signing-key.ts`) and the first-boot admin is fixed
|
|
7
|
+
* (`admin` / `changeme`), so `auth.jwtSecret`, `auth.adminUsername` and
|
|
8
|
+
* `auth.adminPassword` are answered by nothing.
|
|
9
|
+
*/
|
|
3
10
|
export interface ResolvedAuthConfig {
|
|
4
|
-
readonly jwtSecret: string;
|
|
5
|
-
readonly adminUsername: string;
|
|
6
|
-
readonly adminPassword: string;
|
|
7
11
|
/**
|
|
8
12
|
* Operator-configured session lifetime. `undefined` when the `auth` section
|
|
9
13
|
* carries no value — the signer then applies `DEFAULT_TOKEN_EXPIRY`, which
|
|
@@ -11,10 +15,8 @@ export interface ResolvedAuthConfig {
|
|
|
11
15
|
*/
|
|
12
16
|
readonly tokenExpiry: string | undefined;
|
|
13
17
|
}
|
|
14
|
-
/** Persist the generated JWT secret. Called by AuthManager on first boot. */
|
|
15
|
-
export type AuthSectionWriter = (patch: Record<string, unknown>) => void;
|
|
16
18
|
/**
|
|
17
19
|
* Every config path this reader can answer. Anything else resolves to
|
|
18
20
|
* `undefined` by construction — see the module docblock.
|
|
19
21
|
*/
|
|
20
|
-
export declare function createAuthConfigReader(resolved: ResolvedAuthConfig
|
|
22
|
+
export declare function createAuthConfigReader(resolved: ResolvedAuthConfig): AuthConfigReader;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SecretsAccess } from '@camstack/types';
|
|
2
|
+
/** How often a locked keychain is asked again. */
|
|
3
|
+
export declare const SIGNING_KEY_RETRY_MS = 30000;
|
|
4
|
+
interface KeeperLogger {
|
|
5
|
+
info(message: string, meta?: {
|
|
6
|
+
meta?: Record<string, unknown>;
|
|
7
|
+
}): void;
|
|
8
|
+
error(message: string, meta?: {
|
|
9
|
+
meta?: Record<string, unknown>;
|
|
10
|
+
}): void;
|
|
11
|
+
}
|
|
12
|
+
export interface JwtSigningKeyKeeperDeps {
|
|
13
|
+
/** A keychain handle for owner `system`; `null` when this process has no keychain door. */
|
|
14
|
+
readonly secrets: SecretsAccess | null;
|
|
15
|
+
readonly logger: KeeperLogger;
|
|
16
|
+
readonly retryMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare class JwtSigningKeyKeeper {
|
|
19
|
+
private readonly deps;
|
|
20
|
+
private retryTimer;
|
|
21
|
+
private unsubscribe;
|
|
22
|
+
private stopped;
|
|
23
|
+
constructor(deps: JwtSigningKeyKeeperDeps);
|
|
24
|
+
start(): Promise<void>;
|
|
25
|
+
stop(): void;
|
|
26
|
+
private load;
|
|
27
|
+
private apply;
|
|
28
|
+
private scheduleRetry;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { ProviderRegistration, BaseAddon } from '@camstack/types';
|
|
2
|
-
|
|
3
|
-
jwtSecret?: string;
|
|
4
|
-
adminUsername?: string;
|
|
5
|
-
adminPassword?: string;
|
|
6
|
-
}
|
|
7
|
-
export declare class LocalAuthAddon extends BaseAddon<LocalAuthConfig> {
|
|
2
|
+
export declare class LocalAuthAddon extends BaseAddon {
|
|
8
3
|
private authManager;
|
|
9
4
|
private userManager;
|
|
10
5
|
private apiKeyManager;
|
|
@@ -13,6 +8,7 @@ export declare class LocalAuthAddon extends BaseAddon<LocalAuthConfig> {
|
|
|
13
8
|
private reapTimer;
|
|
14
9
|
private totpManager;
|
|
15
10
|
private externalIdentities;
|
|
11
|
+
private signingKeyKeeper;
|
|
16
12
|
constructor();
|
|
17
13
|
protected onInitialize(): Promise<ProviderRegistration[]>;
|
|
18
14
|
/**
|