@corenel/config 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,11 @@ export interface DaemonConfig {
17
17
  endpoint?: string;
18
18
  allowShell?: boolean;
19
19
  keepTranscripts?: boolean;
20
+ /** The daemon's operating mode, matching `--mode <name>`. Only `'team'` is
21
+ * known; anything else is ignored with a warning rather than coerced, since
22
+ * this setting changes WHO is asked for permission and a typo that silently
23
+ * left the daemon fanning out looks exactly like it working. */
24
+ mode?: string;
20
25
  isolation?: string;
21
26
  msbBin?: string;
22
27
  guestImage?: string;
@@ -37,6 +42,33 @@ export interface DaemonConfig {
37
42
  * down as one that predates the key. A plain `string[]`, not its own
38
43
  * command, so `corenel config add|remove|list mcpAllow` work for free. */
39
44
  mcpAllow?: string[];
45
+ /** OIDC issuer whose session tokens prove who a paired browser is (spec
46
+ * 2026-09-25-verified-identity), matching `--identity-issuer <url>`. */
47
+ identityIssuer?: string;
48
+ /** Verification on/off, matching `--no-identity` inverted: `false` disables
49
+ * it. Strict boolean -- anything else is ignored with a warning, never
50
+ * coerced (see config/layer.ts). */
51
+ identity?: boolean;
52
+ /** Web push on/off, matching `--no-push` inverted: `false` disables it
53
+ * (the PHI/self-host story -- see 2026-09-25-web-push-bcd Task 12). Strict
54
+ * boolean, same reasoning as `identity` above -- a non-boolean value is
55
+ * ignored with a warning, never coerced (see config/layer.ts). */
56
+ push?: boolean;
57
+ /** Write the local audit log for crew runs. Absent means on. Strict boolean
58
+ * -- a non-boolean is ignored with a warning, never coerced (see
59
+ * config/layer.ts). Security state: daemon.json only, never a workspace
60
+ * file. */
61
+ audit?: boolean;
62
+ /** "Send telemetry" (spec 2026-09-26-audit-log §6). Absent means off.
63
+ * Strict boolean, same reasoning as `audit`. */
64
+ sendTelemetry?: boolean;
65
+ /** Human allows of one tool before the daemon offers a standing approval; 0
66
+ * turns suggestions off. An integer >= 0, anything else is ignored with a
67
+ * warning. Security state: daemon.json only. */
68
+ approvalsThreshold?: number;
69
+ /** Keep full tool arguments (each <= 2 KB) in the daemon's local decision
70
+ * log. Absent means off. Strict boolean. Security state: daemon.json only. */
71
+ approvalsCaptureRawArgs?: boolean;
40
72
  }
41
73
  /** Keys this file must never carry. `--acp-auth` and tunnel credentials belong
42
74
  * in auth.json: daemon.json is meant to be safe to paste into a support thread
@@ -52,5 +84,77 @@ export declare function readDaemonConfig(stateDir: string): Promise<{
52
84
  unknown: Record<string, unknown>;
53
85
  corrupt: boolean;
54
86
  }>;
87
+ export declare function isValidConfigEnvName(name: string): boolean;
88
+ /** Thrown for anything wrong with a NAMED environment: an invalid name, a
89
+ * missing overlay file, a corrupt one, or one that carries a credential.
90
+ * Every one of these means "do not start", never "fall back to the base
91
+ * file quietly" -- see the module comment above. */
92
+ export declare class DaemonConfigEnvError extends Error {
93
+ }
94
+ /**
95
+ * `source` names where `name` actually came from, in the error text -- a
96
+ * value read from `CORENEL_ENV` that fails validation must say so,
97
+ * not blame `--env`, or an operator debugging an exported env var
98
+ * goes looking at the wrong thing. Defaults to `--env` for every
99
+ * caller that validates a value it did not itself resolve from a source
100
+ * (the overlay reader below, `readDaemonConfigLayered`'s eager checks in
101
+ * `configCmd.ts`/`mcpCmd.ts`/`setup.ts`/`pathList.ts`), all of which receive
102
+ * an ALREADY-SELECTED env with no record of which of the two named it.
103
+ */
104
+ export declare function assertValidConfigEnvName(name: string, source?: string): void;
105
+ export declare function daemonEnvConfigPath(stateDir: string, env: string): string;
106
+ export declare function readDaemonConfigOverlay(stateDir: string, env: string): Promise<{
107
+ config: DaemonConfig;
108
+ unknown: Record<string, unknown>;
109
+ }>;
110
+ /**
111
+ * The same read as `readDaemonConfigOverlay`, for the ONE caller that means
112
+ * to CREATE the overlay rather than consume an existing one: an explicit
113
+ * `corenel config set|unset|add|remove ... --env <name>` (brief.md section
114
+ * 2). Every other reader of a named environment asked to consume a SPECIFIC
115
+ * file and must fail loudly when it is missing (see the module comment
116
+ * above); this one is how an operator brings that file into existence, so a
117
+ * missing overlay returns the SAME empty shape `readDaemonConfig` returns for
118
+ * a missing `daemon.json` -- `existed: false` -- rather than throwing. It
119
+ * still throws for a file that EXISTS but cannot be trusted: corrupt JSON,
120
+ * JSON that isn't an object, or one that carries a SECRET_KEYS entry -- an
121
+ * unusable overlay must never be silently overwritten.
122
+ */
123
+ export declare function readDaemonConfigOverlayForWrite(stateDir: string, env: string): Promise<{
124
+ config: DaemonConfig;
125
+ unknown: Record<string, unknown>;
126
+ existed: boolean;
127
+ }>;
128
+ /**
129
+ * Write `daemon.<env>.json`, the same shape and same atomicity `writeDaemonConfig`
130
+ * uses for the base file (whole-file overwrite via `writeFile`, directory
131
+ * created if needed). Key typing, SECRET_KEYS refusal and unknown-key
132
+ * preservation are the CALLER's job (`configCmd.ts`'s `keyOrReason`/`commit`),
133
+ * exactly as they are for the base file -- this function only persists what
134
+ * it is given.
135
+ */
136
+ export declare function writeDaemonConfigOverlay(stateDir: string, env: string, next: DaemonConfig, unknown?: Record<string, unknown>): Promise<void>;
137
+ /**
138
+ * The EFFECTIVE file config a daemon would actually layer under its flags:
139
+ * `daemon.json`, with every key PRESENT in `daemon.<env>.json` (when `env` is
140
+ * given) replacing the base value WHOLESALE -- an overlay `roots` array
141
+ * replaces the base array outright, never merges element-by-element.
142
+ *
143
+ * `overlayKeys` names exactly which keys came from the overlay, not the base
144
+ * file -- `layer.ts`'s provenance ('default' | 'file' | 'overlay' | 'flag')
145
+ * and its per-key warning wording both need that distinction, and it is lost
146
+ * the moment the two objects are merged into one if it is not carried
147
+ * alongside.
148
+ *
149
+ * No `env` (the ordinary case): identical to `readDaemonConfig` plus an empty
150
+ * `overlayKeys`, so every caller can use this unconditionally rather than
151
+ * branching on whether an environment is active.
152
+ */
153
+ export declare function readDaemonConfigLayered(stateDir: string, env?: string): Promise<{
154
+ config: DaemonConfig;
155
+ unknown: Record<string, unknown>;
156
+ corrupt: boolean;
157
+ overlayKeys: Set<string>;
158
+ }>;
55
159
  export declare function writeDaemonConfig(stateDir: string, next: DaemonConfig, unknown?: Record<string, unknown>): Promise<void>;
56
160
  //# sourceMappingURL=daemonConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"daemonConfig.d.ts","sourceRoot":"","sources":["../src/daemonConfig.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C;;;;;;8EAM0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;iBAGiB;AACjB,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAAwC,CAAC;AAElF;8CAC8C;AAC9C,eAAO,MAAM,UAAU,EAAE,SAAS,CAAC,MAAM,YAAY,CAAC,EAMrD,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAiCvF;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACpC,OAAO,CAAC,IAAI,CAAC,CAKf"}
1
+ {"version":3,"file":"daemonConfig.d.ts","sourceRoot":"","sources":["../src/daemonConfig.ts"],"names":[],"mappings":"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"}
@@ -11,8 +11,59 @@
11
11
  * exactly as it was, because a command that silently drops last month's
12
12
  * settings is worse than the flag wall it replaces.
13
13
  */
14
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
15
- import { dirname, join } from 'node:path';
14
+ import { readFile, writeFile, mkdir, rename, unlink } from 'node:fs/promises';
15
+ import { basename, dirname, join } from 'node:path';
16
+ import { randomBytes } from 'node:crypto';
17
+ /**
18
+ * Write `body` to `path` ATOMICALLY: a temp file in the SAME directory (so
19
+ * the rename is on one filesystem, never a cross-device copy), then
20
+ * `rename()` over the real path. `rename()` on both POSIX and Windows
21
+ * replaces the destination in one filesystem operation -- a reader never
22
+ * observes a partially-written file, and a process that dies mid-write
23
+ * leaves the OLD file intact rather than a truncated or half-flushed one.
24
+ * The temp name carries a random suffix so two concurrent writers (an
25
+ * operator running `config set` twice at once, or a CLI write racing the
26
+ * daemon's own `roots add`) never collide on the same temp path.
27
+ */
28
+ /** Windows refuses to rename over a file another process holds open (the
29
+ * running daemon, an editor, antivirus) with one of these codes. The lock is
30
+ * usually momentary, so retry briefly; if it persists, fall back to writing the
31
+ * target in place -- exactly what this module did before writes were atomic --
32
+ * rather than failing a save that used to succeed. */
33
+ const RENAME_BUSY_CODES = new Set(['EPERM', 'EBUSY', 'EACCES']);
34
+ const RENAME_RETRY_DELAYS_MS = [50, 100, 200];
35
+ function errCode(e) {
36
+ return e && typeof e === 'object' && 'code' in e && typeof e.code === 'string'
37
+ ? e.code
38
+ : undefined;
39
+ }
40
+ async function writeFileAtomic(path, body) {
41
+ await mkdir(dirname(path), { recursive: true });
42
+ const tmp = join(dirname(path), `.${basename(path)}.${randomBytes(6).toString('hex')}.tmp`);
43
+ try {
44
+ await writeFile(tmp, body, 'utf8');
45
+ for (let attempt = 0;; attempt++) {
46
+ try {
47
+ await rename(tmp, path);
48
+ return;
49
+ }
50
+ catch (e) {
51
+ const code = errCode(e);
52
+ if (!code || !RENAME_BUSY_CODES.has(code))
53
+ throw e;
54
+ if (attempt >= RENAME_RETRY_DELAYS_MS.length)
55
+ break;
56
+ await new Promise((r) => setTimeout(r, RENAME_RETRY_DELAYS_MS[attempt]));
57
+ }
58
+ }
59
+ await writeFile(path, body, 'utf8');
60
+ }
61
+ finally {
62
+ // The temp file is gone after a successful rename; after any failure or the
63
+ // in-place fallback it is an orphan -- never leave one beside daemon.json.
64
+ await unlink(tmp).catch(() => { });
65
+ }
66
+ }
16
67
  export const DAEMON_CONFIG_VERSION = 1;
17
68
  /** Keys this file must never carry. `--acp-auth` and tunnel credentials belong
18
69
  * in auth.json: daemon.json is meant to be safe to paste into a support thread
@@ -25,8 +76,9 @@ export const KNOWN_KEYS = [
25
76
  'version', 'port', 'host', 'roots', 'addUnder', 'cloneUnder', 'allowLan',
26
77
  'allowOrigins', 'tlsCert', 'tlsKey', 'selfSigned', 'tunnel', 'tunnelName',
27
78
  'tunnelHostname', 'endpoint', 'allowShell', 'keepTranscripts', 'isolation',
28
- 'msbBin', 'guestImage', 'maxChainDepth', 'name', 'appUrl',
29
- 'defaultModel', 'mcpServers', 'mcpAllow',
79
+ 'msbBin', 'guestImage', 'maxChainDepth', 'name', 'appUrl', 'mode',
80
+ 'defaultModel', 'mcpServers', 'mcpAllow', 'identityIssuer', 'identity', 'push',
81
+ 'audit', 'sendTelemetry', 'approvalsThreshold', 'approvalsCaptureRawArgs',
30
82
  ];
31
83
  export function daemonConfigPath(stateDir) {
32
84
  return join(stateDir, 'daemon.json');
@@ -69,10 +121,184 @@ export async function readDaemonConfig(stateDir) {
69
121
  }
70
122
  return { config, unknown, corrupt: false };
71
123
  }
124
+ /* NAMED CONFIG ENVIRONMENTS: defaults < daemon.json < daemon.<name>.json < flags.
125
+ *
126
+ * `--env local` (or `CORENEL_ENV=local`) layers `daemon.local.json`
127
+ * on top of the base file, in the SAME state dir. The first use is pointing
128
+ * `identityIssuer` at a local corenel-api without hand-editing daemon.json back
129
+ * and forth between a real deployment and a laptop.
130
+ *
131
+ * The name is restricted to `^[a-z0-9-]{1,32}$` for one reason: this string
132
+ * becomes a filename (`daemon.<name>.json`). Anything else -- `../x`, `a/b`, an
133
+ * empty string, uppercase -- either could not be a path segment safely or is not
134
+ * a name anyone meant to type, so it is refused rather than resolved.
135
+ *
136
+ * An overlay is requested BY NAME, unlike the base file: a machine with no
137
+ * daemon.json quietly runs on defaults (the ordinary fresh-machine case), but
138
+ * an operator who typed `--env qa` asked for a SPECIFIC file. Starting
139
+ * without it, or on a corrupt or unusable one, would run the wrong config
140
+ * silently -- worse than refusing to start. `DaemonConfigEnvError` is how every
141
+ * caller (cli.ts's own try/catches, or the top-level `main().catch`) turns that
142
+ * into the same non-zero exit + message every other bad flag already gets.
143
+ */
144
+ const CONFIG_ENV_NAME_RE = /^[a-z0-9-]{1,32}$/;
145
+ export function isValidConfigEnvName(name) {
146
+ return CONFIG_ENV_NAME_RE.test(name);
147
+ }
148
+ /** Thrown for anything wrong with a NAMED environment: an invalid name, a
149
+ * missing overlay file, a corrupt one, or one that carries a credential.
150
+ * Every one of these means "do not start", never "fall back to the base
151
+ * file quietly" -- see the module comment above. */
152
+ export class DaemonConfigEnvError extends Error {
153
+ }
154
+ /**
155
+ * `source` names where `name` actually came from, in the error text -- a
156
+ * value read from `CORENEL_ENV` that fails validation must say so,
157
+ * not blame `--env`, or an operator debugging an exported env var
158
+ * goes looking at the wrong thing. Defaults to `--env` for every
159
+ * caller that validates a value it did not itself resolve from a source
160
+ * (the overlay reader below, `readDaemonConfigLayered`'s eager checks in
161
+ * `configCmd.ts`/`mcpCmd.ts`/`setup.ts`/`pathList.ts`), all of which receive
162
+ * an ALREADY-SELECTED env with no record of which of the two named it.
163
+ */
164
+ export function assertValidConfigEnvName(name, source = '--env') {
165
+ if (!isValidConfigEnvName(name)) {
166
+ throw new DaemonConfigEnvError(`${source} "${name}" is not a valid environment name (lowercase letters, digits and hyphens, 1-32 characters)`);
167
+ }
168
+ }
169
+ export function daemonEnvConfigPath(stateDir, env) {
170
+ return join(stateDir, `daemon.${env}.json`);
171
+ }
172
+ /**
173
+ * Read ONE overlay file, `daemon.<env>.json`, with the SAME parsing rules as
174
+ * `readDaemonConfig` -- same KNOWN_KEYS split, same unknown-keys bucket -- but
175
+ * where the base file never throws, this one does, for every way it could be
176
+ * unusable: missing, corrupt JSON, JSON that isn't an object, or one that
177
+ * carries a SECRET_KEYS entry (a credential does not belong in EITHER file,
178
+ * and here it makes the whole overlay unusable rather than just being ignored
179
+ * as an unknown key the way it silently would be in the base file today).
180
+ */
181
+ /** Shared by `readDaemonConfigOverlay` and `readDaemonConfigOverlayForWrite`:
182
+ * turn ALREADY-READ file text into `{ config, unknown }`, or throw for every
183
+ * way the text itself is unusable (corrupt JSON, JSON that isn't an object,
184
+ * or a SECRET_KEYS entry). Missing-file handling differs between the two
185
+ * callers, so it stays out of this function entirely. */
186
+ function parseOverlaySource(env, path, raw) {
187
+ let parsed;
188
+ try {
189
+ parsed = JSON.parse(raw);
190
+ }
191
+ catch {
192
+ throw new DaemonConfigEnvError(`env "${env}": ${basename(path)} is not valid JSON`);
193
+ }
194
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
195
+ throw new DaemonConfigEnvError(`env "${env}": ${basename(path)} is not a JSON object`);
196
+ }
197
+ const src = parsed;
198
+ for (const secret of SECRET_KEYS) {
199
+ if (secret in src) {
200
+ throw new DaemonConfigEnvError(`env "${env}": ${basename(path)} contains "${secret}", a credential that does not belong in a daemon config file (it goes in auth.json)`);
201
+ }
202
+ }
203
+ const config = { version: DAEMON_CONFIG_VERSION };
204
+ const unknown = {};
205
+ for (const [k, v] of Object.entries(src)) {
206
+ if (k === 'version')
207
+ continue;
208
+ if (KNOWN_KEYS.includes(k)) {
209
+ config[k] = v;
210
+ }
211
+ else {
212
+ unknown[k] = v;
213
+ }
214
+ }
215
+ return { config, unknown };
216
+ }
217
+ export async function readDaemonConfigOverlay(stateDir, env) {
218
+ assertValidConfigEnvName(env);
219
+ const path = daemonEnvConfigPath(stateDir, env);
220
+ let raw;
221
+ try {
222
+ raw = await readFile(path, 'utf8');
223
+ }
224
+ catch {
225
+ throw new DaemonConfigEnvError(`env "${env}": ${basename(path)} not found in ${stateDir}`);
226
+ }
227
+ return parseOverlaySource(env, path, raw);
228
+ }
229
+ /**
230
+ * The same read as `readDaemonConfigOverlay`, for the ONE caller that means
231
+ * to CREATE the overlay rather than consume an existing one: an explicit
232
+ * `corenel config set|unset|add|remove ... --env <name>` (brief.md section
233
+ * 2). Every other reader of a named environment asked to consume a SPECIFIC
234
+ * file and must fail loudly when it is missing (see the module comment
235
+ * above); this one is how an operator brings that file into existence, so a
236
+ * missing overlay returns the SAME empty shape `readDaemonConfig` returns for
237
+ * a missing `daemon.json` -- `existed: false` -- rather than throwing. It
238
+ * still throws for a file that EXISTS but cannot be trusted: corrupt JSON,
239
+ * JSON that isn't an object, or one that carries a SECRET_KEYS entry -- an
240
+ * unusable overlay must never be silently overwritten.
241
+ */
242
+ export async function readDaemonConfigOverlayForWrite(stateDir, env) {
243
+ assertValidConfigEnvName(env);
244
+ const path = daemonEnvConfigPath(stateDir, env);
245
+ let raw;
246
+ try {
247
+ raw = await readFile(path, 'utf8');
248
+ }
249
+ catch {
250
+ return { config: { version: DAEMON_CONFIG_VERSION }, unknown: {}, existed: false };
251
+ }
252
+ return { ...parseOverlaySource(env, path, raw), existed: true };
253
+ }
254
+ /**
255
+ * Write `daemon.<env>.json`, the same shape and same atomicity `writeDaemonConfig`
256
+ * uses for the base file (whole-file overwrite via `writeFile`, directory
257
+ * created if needed). Key typing, SECRET_KEYS refusal and unknown-key
258
+ * preservation are the CALLER's job (`configCmd.ts`'s `keyOrReason`/`commit`),
259
+ * exactly as they are for the base file -- this function only persists what
260
+ * it is given.
261
+ */
262
+ export async function writeDaemonConfigOverlay(stateDir, env, next, unknown = {}) {
263
+ assertValidConfigEnvName(env);
264
+ const body = { ...unknown, ...next, version: DAEMON_CONFIG_VERSION };
265
+ const path = daemonEnvConfigPath(stateDir, env);
266
+ await writeFileAtomic(path, `${JSON.stringify(body, null, 2)}\n`);
267
+ }
268
+ /**
269
+ * The EFFECTIVE file config a daemon would actually layer under its flags:
270
+ * `daemon.json`, with every key PRESENT in `daemon.<env>.json` (when `env` is
271
+ * given) replacing the base value WHOLESALE -- an overlay `roots` array
272
+ * replaces the base array outright, never merges element-by-element.
273
+ *
274
+ * `overlayKeys` names exactly which keys came from the overlay, not the base
275
+ * file -- `layer.ts`'s provenance ('default' | 'file' | 'overlay' | 'flag')
276
+ * and its per-key warning wording both need that distinction, and it is lost
277
+ * the moment the two objects are merged into one if it is not carried
278
+ * alongside.
279
+ *
280
+ * No `env` (the ordinary case): identical to `readDaemonConfig` plus an empty
281
+ * `overlayKeys`, so every caller can use this unconditionally rather than
282
+ * branching on whether an environment is active.
283
+ */
284
+ export async function readDaemonConfigLayered(stateDir, env) {
285
+ const base = await readDaemonConfig(stateDir);
286
+ if (!env)
287
+ return { ...base, overlayKeys: new Set() };
288
+ const overlay = await readDaemonConfigOverlay(stateDir, env);
289
+ const config = { ...base.config };
290
+ const overlayKeys = new Set();
291
+ for (const [k, v] of Object.entries(overlay.config)) {
292
+ if (k === 'version')
293
+ continue;
294
+ config[k] = v;
295
+ overlayKeys.add(k);
296
+ }
297
+ return { config, unknown: base.unknown, corrupt: base.corrupt, overlayKeys };
298
+ }
72
299
  export async function writeDaemonConfig(stateDir, next, unknown = {}) {
73
300
  const body = { ...unknown, ...next, version: DAEMON_CONFIG_VERSION };
74
301
  const path = daemonConfigPath(stateDir);
75
- await mkdir(dirname(path), { recursive: true });
76
- await writeFile(path, `${JSON.stringify(body, null, 2)}\n`, 'utf8');
302
+ await writeFileAtomic(path, `${JSON.stringify(body, null, 2)}\n`);
77
303
  }
78
304
  //# sourceMappingURL=daemonConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"daemonConfig.js","sourceRoot":"","sources":["../src/daemonConfig.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemonConfig.js","sourceRoot":"","sources":["../src/daemonConfig.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corenel/config",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "description": "Corenel config — the single reader and writer of the dot-dir's daemon.json and auth.json. Two independent readers of one file drift, and the symptom is silence.",
@@ -18,7 +18,7 @@
18
18
  "dist"
19
19
  ],
20
20
  "dependencies": {
21
- "@corenel/tools-node": "0.5.0"
21
+ "@corenel/tools-node": "0.5.1"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^24.13.1",