@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.
- package/dist/daemonConfig.d.ts +104 -0
- package/dist/daemonConfig.d.ts.map +1 -1
- package/dist/daemonConfig.js +232 -6
- package/dist/daemonConfig.js.map +1 -1
- package/package.json +2 -2
package/dist/daemonConfig.d.ts
CHANGED
|
@@ -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":"
|
|
1
|
+
{"version":3,"file":"daemonConfig.d.ts","sourceRoot":"","sources":["../src/daemonConfig.ts"],"names":[],"mappings":"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"}
|
package/dist/daemonConfig.js
CHANGED
|
@@ -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
|
|
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
|
package/dist/daemonConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemonConfig.js","sourceRoot":"","sources":["../src/daemonConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;
|
|
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.
|
|
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.
|
|
21
|
+
"@corenel/tools-node": "0.5.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/node": "^24.13.1",
|