@kitsy/cnos 1.2.0 → 1.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.
Files changed (65) hide show
  1. package/README.md +3 -3
  2. package/dist/build/index.cjs +1003 -121
  3. package/dist/build/index.d.cts +1 -1
  4. package/dist/build/index.d.ts +1 -1
  5. package/dist/build/index.js +22 -10
  6. package/dist/{chunk-APCTXRUN.js → chunk-APIU4GTB.js} +1012 -195
  7. package/dist/chunk-EQSKV3DP.js +105 -0
  8. package/dist/{chunk-MLQGYCO7.js → chunk-FWJC4Y2D.js} +1 -1
  9. package/dist/{chunk-RD5WMHPM.js → chunk-HMM76UYZ.js} +1 -1
  10. package/dist/{chunk-EIN55XXA.js → chunk-J4K4JUJL.js} +1 -1
  11. package/dist/{chunk-SO5XREEU.js → chunk-JSBVYK2T.js} +32 -11
  12. package/dist/chunk-LJD4SM32.js +189 -0
  13. package/dist/{chunk-SXTMTACL.js → chunk-T6Y57KTT.js} +20 -31
  14. package/dist/chunk-WCHX2QFY.js +115 -0
  15. package/dist/{chunk-ZA74BO47.js → chunk-ZTPSFXWP.js} +1 -1
  16. package/dist/configure/index.cjs +3021 -0
  17. package/dist/configure/index.d.cts +12 -0
  18. package/dist/configure/index.d.ts +12 -0
  19. package/dist/configure/index.js +24 -0
  20. package/dist/{envNaming-CcsqAel3.d.ts → envNaming-Dvm_LP2D.d.ts} +1 -1
  21. package/dist/{envNaming-BTJpH93W.d.cts → envNaming-S4B-dHUx.d.cts} +1 -1
  22. package/dist/index.cjs +1243 -186
  23. package/dist/index.d.cts +2 -13
  24. package/dist/index.d.ts +2 -13
  25. package/dist/index.js +13 -25
  26. package/dist/internal.cjs +1525 -81
  27. package/dist/internal.d.cts +171 -14
  28. package/dist/internal.d.ts +171 -14
  29. package/dist/internal.js +652 -5
  30. package/dist/plugin/basic-schema.cjs +29 -2
  31. package/dist/plugin/basic-schema.d.cts +1 -1
  32. package/dist/plugin/basic-schema.d.ts +1 -1
  33. package/dist/plugin/basic-schema.js +2 -2
  34. package/dist/plugin/cli-args.cjs +29 -2
  35. package/dist/plugin/cli-args.d.cts +1 -1
  36. package/dist/plugin/cli-args.d.ts +1 -1
  37. package/dist/plugin/cli-args.js +2 -2
  38. package/dist/plugin/dotenv.cjs +36 -9
  39. package/dist/plugin/dotenv.d.cts +2 -2
  40. package/dist/plugin/dotenv.d.ts +2 -2
  41. package/dist/plugin/dotenv.js +2 -2
  42. package/dist/plugin/env-export.cjs +31 -2
  43. package/dist/plugin/env-export.d.cts +2 -2
  44. package/dist/plugin/env-export.d.ts +2 -2
  45. package/dist/plugin/env-export.js +2 -2
  46. package/dist/plugin/filesystem.cjs +65 -91
  47. package/dist/plugin/filesystem.d.cts +1 -1
  48. package/dist/plugin/filesystem.d.ts +1 -1
  49. package/dist/plugin/filesystem.js +2 -2
  50. package/dist/plugin/process-env.cjs +105 -11
  51. package/dist/plugin/process-env.d.cts +4 -3
  52. package/dist/plugin/process-env.d.ts +4 -3
  53. package/dist/plugin/process-env.js +6 -4
  54. package/dist/{plugin-DkOIT5uI.d.cts → plugin-B4xwySxw.d.cts} +15 -2
  55. package/dist/{plugin-DkOIT5uI.d.ts → plugin-B4xwySxw.d.ts} +15 -2
  56. package/dist/runtime/index.cjs +1057 -136
  57. package/dist/runtime/index.d.cts +1 -1
  58. package/dist/runtime/index.d.ts +1 -1
  59. package/dist/runtime/index.js +11 -186
  60. package/dist/{toPublicEnv-C9clvXLo.d.ts → toPublicEnv-CvhGAfsB.d.ts} +1 -1
  61. package/dist/{toPublicEnv-DvFeV3qG.d.cts → toPublicEnv-ggmphZFs.d.cts} +1 -1
  62. package/package.json +11 -1
  63. package/dist/chunk-JUHPBAEH.js +0 -20
  64. package/dist/chunk-PQ4KSV76.js +0 -50
  65. package/dist/chunk-WHUGFPE4.js +0 -49
@@ -0,0 +1,3021 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/configure/index.ts
31
+ var configure_exports = {};
32
+ __export(configure_exports, {
33
+ createCnos: () => createCnos2,
34
+ defaultPlugins: () => defaultPlugins,
35
+ planDump: () => planDump,
36
+ toEnv: () => toEnv,
37
+ toPublicEnv: () => toPublicEnv,
38
+ writeDump: () => writeDump
39
+ });
40
+ module.exports = __toCommonJS(configure_exports);
41
+
42
+ // ../core/src/errors.ts
43
+ var CnosError = class extends Error {
44
+ constructor(message) {
45
+ super(message);
46
+ this.name = new.target.name;
47
+ }
48
+ };
49
+ var CnosManifestError = class extends CnosError {
50
+ constructor(message, manifestPath) {
51
+ super(manifestPath ? `${message} (${manifestPath})` : message);
52
+ this.manifestPath = manifestPath;
53
+ }
54
+ manifestPath;
55
+ };
56
+ var CnosSecurityError = class extends CnosError {
57
+ constructor(message) {
58
+ super(message);
59
+ }
60
+ };
61
+ var CnosAuthenticationError = class extends CnosError {
62
+ constructor(message) {
63
+ super(message);
64
+ }
65
+ };
66
+ var CnosKeyNotFoundError = class extends CnosError {
67
+ constructor(key) {
68
+ super(`Missing required CNOS config key: ${key}`);
69
+ this.key = key;
70
+ }
71
+ key;
72
+ };
73
+
74
+ // ../core/src/runtime/inspect.ts
75
+ function inspectValue(graph, key) {
76
+ const entry = graph.entries.get(key);
77
+ if (!entry) {
78
+ throw new CnosKeyNotFoundError(key);
79
+ }
80
+ return {
81
+ key: entry.key,
82
+ value: entry.value,
83
+ namespace: entry.namespace,
84
+ profile: graph.profile,
85
+ profileSource: graph.profileSource,
86
+ workspace: {
87
+ id: graph.workspace.workspaceId,
88
+ source: graph.workspace.workspaceSource,
89
+ chain: graph.workspace.workspaceChain
90
+ },
91
+ winner: {
92
+ sourceId: entry.winner.sourceId,
93
+ pluginId: entry.winner.pluginId,
94
+ workspaceId: entry.winner.workspaceId,
95
+ ...entry.winner.origin ? { origin: entry.winner.origin } : {}
96
+ },
97
+ overridden: entry.overridden.map((override) => ({
98
+ sourceId: override.sourceId,
99
+ pluginId: override.pluginId,
100
+ workspaceId: override.workspaceId,
101
+ value: override.value,
102
+ ...override.origin ? { origin: override.origin } : {}
103
+ }))
104
+ };
105
+ }
106
+
107
+ // ../core/src/inspectors/provenance.ts
108
+ function createProvenanceInspector() {
109
+ return {
110
+ id: "provenance",
111
+ kind: "inspector",
112
+ async inspect(key, graph) {
113
+ return inspectValue(graph, key);
114
+ }
115
+ };
116
+ }
117
+
118
+ // ../core/src/keychain/linux.ts
119
+ var import_node_child_process = require("child_process");
120
+ var import_node_util = require("util");
121
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
122
+ async function readLinuxKeychain(entry) {
123
+ try {
124
+ const { stdout } = await execFileAsync("secret-tool", ["lookup", "service", "cnos", "account", entry]);
125
+ const value = stdout.trim();
126
+ return value.length > 0 ? value : void 0;
127
+ } catch {
128
+ return void 0;
129
+ }
130
+ }
131
+
132
+ // ../core/src/keychain/macos.ts
133
+ var import_node_child_process2 = require("child_process");
134
+ var import_node_util2 = require("util");
135
+ var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
136
+ async function readMacosKeychain(entry) {
137
+ try {
138
+ const { stdout } = await execFileAsync2("security", ["find-generic-password", "-a", "cnos", "-s", entry, "-w"]);
139
+ const value = stdout.trim();
140
+ return value.length > 0 ? value : void 0;
141
+ } catch {
142
+ return void 0;
143
+ }
144
+ }
145
+
146
+ // ../core/src/keychain/windows.ts
147
+ var import_node_child_process3 = require("child_process");
148
+ var import_node_util3 = require("util");
149
+ var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process3.execFile);
150
+ function wrap(script) {
151
+ return ["-NoProfile", "-Command", script];
152
+ }
153
+ async function readWindowsKeychain(entry) {
154
+ try {
155
+ const { stdout } = await execFileAsync3(
156
+ "powershell",
157
+ wrap(`Add-Type -AssemblyName System.Runtime.WindowsRuntime; [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime] > $null; $vault = New-Object Windows.Security.Credentials.PasswordVault; $credential = $vault.Retrieve('cnos','${entry}'); $credential.RetrievePassword(); Write-Output $credential.Password`)
158
+ );
159
+ const value = stdout.trim();
160
+ return value.length > 0 ? value : void 0;
161
+ } catch {
162
+ return void 0;
163
+ }
164
+ }
165
+
166
+ // ../core/src/keychain/index.ts
167
+ async function readKeychain(entry) {
168
+ if (process.platform === "win32") {
169
+ return readWindowsKeychain(entry);
170
+ }
171
+ if (process.platform === "darwin") {
172
+ return readMacosKeychain(entry);
173
+ }
174
+ if (process.platform === "linux") {
175
+ return readLinuxKeychain(entry);
176
+ }
177
+ return void 0;
178
+ }
179
+
180
+ // ../core/src/manifest/loadManifest.ts
181
+ var import_promises2 = require("fs/promises");
182
+ var import_node_path2 = __toESM(require("path"), 1);
183
+
184
+ // ../core/src/utils/path.ts
185
+ var import_promises = require("fs/promises");
186
+ var import_node_os = __toESM(require("os"), 1);
187
+ var import_node_path = __toESM(require("path"), 1);
188
+ var PRIMARY_CNOS_DIR = ".cnos";
189
+ var LEGACY_CNOS_DIR = "cnos";
190
+ async function exists(filePath) {
191
+ try {
192
+ await (0, import_promises.access)(filePath);
193
+ return true;
194
+ } catch {
195
+ return false;
196
+ }
197
+ }
198
+ async function resolveCnosRoot(root = process.cwd()) {
199
+ const basePath = import_node_path.default.resolve(root);
200
+ const candidates = [
201
+ import_node_path.default.join(basePath, PRIMARY_CNOS_DIR),
202
+ import_node_path.default.join(basePath, LEGACY_CNOS_DIR),
203
+ basePath
204
+ ];
205
+ for (const candidate of candidates) {
206
+ if (await exists(import_node_path.default.join(candidate, "cnos.yml"))) {
207
+ return candidate;
208
+ }
209
+ }
210
+ throw new CnosManifestError(
211
+ `Could not locate .cnos/cnos.yml or cnos/cnos.yml from root: ${basePath}`
212
+ );
213
+ }
214
+ async function resolveManifestRoot(root = process.cwd()) {
215
+ return resolveCnosRoot(root);
216
+ }
217
+ function interpolatePathTemplate(template, tokens) {
218
+ return Object.entries(tokens).reduce(
219
+ (result, [token, value]) => result.replaceAll(`{${token}}`, value),
220
+ template
221
+ );
222
+ }
223
+ function expandHomePath(targetPath) {
224
+ if (targetPath === "~") {
225
+ return import_node_os.default.homedir();
226
+ }
227
+ if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
228
+ return import_node_path.default.join(import_node_os.default.homedir(), targetPath.slice(2));
229
+ }
230
+ return targetPath;
231
+ }
232
+ function stripWorkspaceTemplatePrefix(template) {
233
+ const normalized = template.replace(/\\/g, "/").replace(/^\.\//, "");
234
+ const marker = "workspaces/{workspace}";
235
+ if (normalized === marker) {
236
+ return ".";
237
+ }
238
+ if (normalized.startsWith(`${marker}/`)) {
239
+ return normalized.slice(marker.length + 1);
240
+ }
241
+ return template;
242
+ }
243
+ function resolveWorkspaceScopedPath(workspaceRoot, template, tokens) {
244
+ const relativeTemplate = stripWorkspaceTemplatePrefix(template);
245
+ const interpolated = interpolatePathTemplate(relativeTemplate, tokens);
246
+ return import_node_path.default.resolve(workspaceRoot, interpolated);
247
+ }
248
+ function toPortablePath(targetPath) {
249
+ return targetPath.replace(/\\/g, "/");
250
+ }
251
+ function joinConfigPath(...parts) {
252
+ return parts.flatMap((part) => part.split(".")).map((part) => part.trim()).filter(Boolean).join(".");
253
+ }
254
+ function toLogicalKey(namespace, valuePath) {
255
+ return `${namespace}.${joinConfigPath(valuePath)}`;
256
+ }
257
+ function stripNamespace(key) {
258
+ return key.split(".").slice(1).join(".");
259
+ }
260
+
261
+ // ../core/src/utils/yaml.ts
262
+ var import_yaml = require("yaml");
263
+ function parseYaml(source) {
264
+ return (0, import_yaml.parse)(source);
265
+ }
266
+ function stringifyYaml(value) {
267
+ return (0, import_yaml.stringify)(value);
268
+ }
269
+
270
+ // ../core/src/manifest/normalizeManifest.ts
271
+ var DEFAULT_RESOLVE_FROM = ["cli.profile", "env.CNOS_PROFILE", "default"];
272
+ var DEFAULT_LOADERS = [
273
+ "filesystem-values",
274
+ "filesystem-secrets",
275
+ "dotenv",
276
+ "process-env",
277
+ "cli-args"
278
+ ];
279
+ var DEFAULT_VALIDATORS = ["basic-schema"];
280
+ var DEFAULT_EXPORTERS = ["env", "public-env"];
281
+ var DEFAULT_INSPECTORS = ["provenance"];
282
+ var DEFAULT_FRAMEWORK_PREFIXES = {
283
+ next: "NEXT_PUBLIC_",
284
+ vite: "VITE_",
285
+ nuxt: "NUXT_PUBLIC_"
286
+ };
287
+ var DEFAULT_NAMESPACES = {
288
+ value: {
289
+ kind: "data",
290
+ shareable: true
291
+ },
292
+ secret: {
293
+ kind: "data",
294
+ shareable: false,
295
+ sensitive: true
296
+ },
297
+ meta: {
298
+ kind: "system",
299
+ shareable: false,
300
+ readonly: true
301
+ },
302
+ process: {
303
+ kind: "system",
304
+ shareable: false,
305
+ readonly: true
306
+ },
307
+ public: {
308
+ kind: "projection",
309
+ source: "promote",
310
+ shareable: true,
311
+ readonly: true
312
+ },
313
+ env: {
314
+ kind: "projection",
315
+ source: "envMapping",
316
+ shareable: true,
317
+ readonly: true
318
+ }
319
+ };
320
+ function validateResolveFrom(resolveFrom) {
321
+ const validValues = ["cli.profile", "env.CNOS_PROFILE", "default"];
322
+ for (const entry of resolveFrom) {
323
+ if (!validValues.includes(entry)) {
324
+ throw new CnosManifestError(`Unsupported profiles.resolveFrom entry: ${entry}`);
325
+ }
326
+ }
327
+ return resolveFrom;
328
+ }
329
+ function normalizeWorkspaceItems(items) {
330
+ return Object.fromEntries(
331
+ Object.entries(items ?? {}).map(([workspaceId, item]) => [
332
+ workspaceId,
333
+ {
334
+ extends: Array.isArray(item?.extends) ? item.extends.map((entry) => entry.trim()).filter(Boolean) : item?.extends ? [item.extends.trim()].filter(Boolean) : [],
335
+ ...item?.globalId?.trim() ? { globalId: item.globalId.trim() } : {}
336
+ }
337
+ ])
338
+ );
339
+ }
340
+ function normalizeNamespaces(namespaces) {
341
+ const normalized = Object.fromEntries(
342
+ Object.entries(namespaces ?? {}).map(([namespace, definition]) => [
343
+ namespace,
344
+ {
345
+ kind: definition.kind ?? "data",
346
+ shareable: definition.shareable ?? false,
347
+ ...definition.sensitive !== void 0 ? { sensitive: definition.sensitive } : {},
348
+ ...definition.readonly !== void 0 ? { readonly: definition.readonly } : {},
349
+ ...definition.source ? { source: definition.source } : {}
350
+ }
351
+ ])
352
+ );
353
+ return {
354
+ ...DEFAULT_NAMESPACES,
355
+ ...normalized
356
+ };
357
+ }
358
+ function normalizeVaults(vaults) {
359
+ return Object.fromEntries(
360
+ Object.entries(vaults ?? {}).map(([name, definition]) => {
361
+ const legacyPassphrase = definition.passphrase;
362
+ if (legacyPassphrase !== void 0) {
363
+ throw new CnosManifestError(
364
+ `Vault "${name}" uses legacy passphrase configuration. Use vaults.${name}.auth instead.`
365
+ );
366
+ }
367
+ const provider = definition.provider?.trim();
368
+ if (!provider) {
369
+ throw new CnosManifestError(`Vault "${name}" requires a provider`);
370
+ }
371
+ const normalizedAuth = normalizeVaultAuth(name, provider, definition.auth);
372
+ const normalizedMapping = Object.fromEntries(
373
+ Object.entries(definition.mapping ?? {}).filter(
374
+ (entry) => typeof entry[0] === "string" && typeof entry[1] === "string"
375
+ ).map(([envVar, logicalRef]) => [envVar.trim(), logicalRef.trim()]).filter(([envVar, logicalRef]) => envVar.length > 0 && logicalRef.length > 0)
376
+ );
377
+ return [
378
+ name,
379
+ {
380
+ provider,
381
+ auth: normalizedAuth,
382
+ ...Object.keys(normalizedMapping).length > 0 ? {
383
+ mapping: normalizedMapping
384
+ } : {}
385
+ }
386
+ ];
387
+ })
388
+ );
389
+ }
390
+ function normalizeAuthSources(value) {
391
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
392
+ return void 0;
393
+ }
394
+ const sources = Array.isArray(value.from) ? value.from : void 0;
395
+ const normalized = (sources ?? []).map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
396
+ return normalized.length > 0 ? normalized : void 0;
397
+ }
398
+ function normalizeVaultAuth(vaultName, provider, auth) {
399
+ if (provider === "local") {
400
+ const passphraseSources = normalizeAuthSources(auth?.passphrase);
401
+ const defaultToken = vaultName.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
402
+ const defaultSources = [
403
+ ...defaultToken ? [`env:CNOS_SECRET_PASSPHRASE_${defaultToken}`] : [],
404
+ "env:CNOS_SECRET_PASSPHRASE",
405
+ `keychain:cnos/${vaultName}`,
406
+ "prompt"
407
+ ];
408
+ return {
409
+ method: auth?.method ?? "passphrase",
410
+ passphrase: {
411
+ from: passphraseSources ?? defaultSources
412
+ },
413
+ ...auth?.config ? { config: auth.config } : {}
414
+ };
415
+ }
416
+ if (provider === "github-secrets") {
417
+ return {
418
+ method: auth?.method ?? "environment",
419
+ ...auth?.config ? { config: auth.config } : {}
420
+ };
421
+ }
422
+ return {
423
+ ...auth?.method ? { method: auth.method } : {},
424
+ ...normalizeAuthSources(auth?.passphrase) ? {
425
+ passphrase: {
426
+ from: normalizeAuthSources(auth?.passphrase) ?? []
427
+ }
428
+ } : {},
429
+ ...normalizeAuthSources(auth?.token) ? {
430
+ token: {
431
+ from: normalizeAuthSources(auth?.token) ?? []
432
+ }
433
+ } : {},
434
+ ...auth?.config ? { config: auth.config } : {}
435
+ };
436
+ }
437
+ function normalizeManifest(manifest) {
438
+ const version = manifest.version ?? 1;
439
+ if (version !== 1) {
440
+ throw new CnosManifestError(`Unsupported CNOS manifest version: ${version}`);
441
+ }
442
+ const projectName = manifest.project?.name?.trim();
443
+ if (!projectName) {
444
+ throw new CnosManifestError("Manifest requires project.name");
445
+ }
446
+ const defaultProfile = manifest.profiles?.default?.trim() || "base";
447
+ const workspaceItems = normalizeWorkspaceItems(manifest.workspaces?.items);
448
+ const resolveFrom = validateResolveFrom(manifest.profiles?.resolveFrom ?? DEFAULT_RESOLVE_FROM);
449
+ const filesystemValues = {
450
+ root: "./",
451
+ format: "yaml",
452
+ ...manifest.sources?.["filesystem-values"] ?? {}
453
+ };
454
+ const filesystemSecrets = {
455
+ root: "./",
456
+ format: "yaml",
457
+ ...manifest.sources?.["filesystem-secrets"] ?? {}
458
+ };
459
+ const dotenv = {
460
+ root: "./env",
461
+ ...manifest.sources?.dotenv ?? {}
462
+ };
463
+ return {
464
+ version: 1,
465
+ project: {
466
+ name: projectName
467
+ },
468
+ workspaces: {
469
+ ...manifest.workspaces?.default?.trim() ? {
470
+ default: manifest.workspaces.default.trim()
471
+ } : {},
472
+ global: {
473
+ enabled: manifest.workspaces?.global?.enabled ?? false,
474
+ ...manifest.workspaces?.global?.root?.trim() ? {
475
+ root: manifest.workspaces.global.root.trim()
476
+ } : {},
477
+ allowWrite: manifest.workspaces?.global?.allowWrite ?? false
478
+ },
479
+ items: workspaceItems
480
+ },
481
+ profiles: {
482
+ default: defaultProfile,
483
+ resolveFrom
484
+ },
485
+ plugins: {
486
+ loaders: manifest.plugins?.loaders ?? DEFAULT_LOADERS,
487
+ resolver: manifest.plugins?.resolver ?? "profile-aware",
488
+ validators: manifest.plugins?.validators ?? DEFAULT_VALIDATORS,
489
+ exporters: manifest.plugins?.exporters ?? DEFAULT_EXPORTERS,
490
+ inspectors: manifest.plugins?.inspectors ?? DEFAULT_INSPECTORS
491
+ },
492
+ sources: {
493
+ ...manifest.sources ?? {},
494
+ "filesystem-values": filesystemValues,
495
+ "filesystem-secrets": filesystemSecrets,
496
+ dotenv
497
+ },
498
+ resolution: {
499
+ precedence: manifest.resolution?.precedence ?? [
500
+ "filesystem-values",
501
+ "filesystem-secrets",
502
+ "dotenv",
503
+ "process-env",
504
+ "cli-args"
505
+ ],
506
+ arrayPolicy: manifest.resolution?.arrayPolicy ?? "replace"
507
+ },
508
+ envMapping: {
509
+ ...manifest.envMapping?.convention ? {
510
+ convention: manifest.envMapping.convention
511
+ } : {},
512
+ explicit: manifest.envMapping?.explicit ?? {}
513
+ },
514
+ public: {
515
+ promote: manifest.public?.promote ?? [],
516
+ frameworks: {
517
+ ...DEFAULT_FRAMEWORK_PREFIXES,
518
+ ...manifest.public?.frameworks ?? {}
519
+ }
520
+ },
521
+ namespaces: normalizeNamespaces(manifest.namespaces),
522
+ vaults: normalizeVaults(manifest.vaults),
523
+ writePolicy: {
524
+ define: {
525
+ defaultProfile: manifest.writePolicy?.define?.defaultProfile ?? defaultProfile,
526
+ targets: {
527
+ value: manifest.writePolicy?.define?.targets?.value ?? "./values/app.yml",
528
+ secret: manifest.writePolicy?.define?.targets?.secret ?? "./secrets/app.yml"
529
+ }
530
+ }
531
+ },
532
+ schema: manifest.schema ?? {}
533
+ };
534
+ }
535
+
536
+ // ../core/src/manifest/loadManifest.ts
537
+ async function loadManifest(options = {}) {
538
+ const manifestRoot = await resolveManifestRoot(options.root);
539
+ const manifestPath = import_node_path2.default.join(manifestRoot, "cnos.yml");
540
+ let source;
541
+ try {
542
+ source = await (0, import_promises2.readFile)(manifestPath, "utf8");
543
+ } catch {
544
+ throw new CnosManifestError("Unable to read CNOS manifest", manifestPath);
545
+ }
546
+ const rawManifest = parseYaml(source);
547
+ if (!rawManifest || typeof rawManifest !== "object") {
548
+ throw new CnosManifestError("CNOS manifest must be a YAML object", manifestPath);
549
+ }
550
+ return {
551
+ manifestRoot,
552
+ repoRoot: import_node_path2.default.dirname(manifestRoot),
553
+ manifestPath,
554
+ manifest: normalizeManifest(rawManifest),
555
+ rawManifest
556
+ };
557
+ }
558
+
559
+ // ../core/src/manifest/loadWorkspaceFile.ts
560
+ var import_promises3 = require("fs/promises");
561
+ var import_node_path3 = __toESM(require("path"), 1);
562
+ async function loadWorkspaceFile(repoRoot) {
563
+ const workspaceFilePath = import_node_path3.default.join(repoRoot, ".cnos-workspace.yml");
564
+ try {
565
+ const source = await (0, import_promises3.readFile)(workspaceFilePath, "utf8");
566
+ const parsed = parseYaml(source);
567
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
568
+ throw new CnosManifestError(".cnos-workspace.yml must be a YAML object", workspaceFilePath);
569
+ }
570
+ const config = parsed;
571
+ return {
572
+ path: workspaceFilePath,
573
+ config: {
574
+ ...config.workspace ? { workspace: config.workspace.trim() } : {},
575
+ ...config.profile ? { profile: config.profile.trim() } : {},
576
+ ...config.globalRoot ? { globalRoot: config.globalRoot.trim() } : {}
577
+ }
578
+ };
579
+ } catch (error) {
580
+ if (error.code === "ENOENT") {
581
+ return void 0;
582
+ }
583
+ throw error;
584
+ }
585
+ }
586
+
587
+ // ../core/src/profiles/expandProfileChain.ts
588
+ var import_promises4 = require("fs/promises");
589
+ var import_node_path4 = __toESM(require("path"), 1);
590
+ async function fileExists(targetPath) {
591
+ try {
592
+ await (0, import_promises4.access)(targetPath);
593
+ return true;
594
+ } catch {
595
+ return false;
596
+ }
597
+ }
598
+ function normalizeProfileDefinition(profileName, rawDefinition, filePath) {
599
+ const normalizeActivationLayer = (entry, namespace) => {
600
+ const normalized = entry.trim();
601
+ if (!normalized) {
602
+ return normalized;
603
+ }
604
+ if (normalized.includes("/") || normalized.includes("\\") || normalized.startsWith(".")) {
605
+ return normalized.replace(/\\/g, "/");
606
+ }
607
+ return `${namespace}/${normalized}`;
608
+ };
609
+ return {
610
+ name: rawDefinition?.name?.trim() || profileName,
611
+ extends: Array.isArray(rawDefinition?.extends) ? rawDefinition.extends.map((entry) => entry.trim()).filter(Boolean) : rawDefinition?.extends ? [rawDefinition.extends.trim()].filter(Boolean) : [],
612
+ activate: {
613
+ values: rawDefinition?.activate?.values?.map((entry) => normalizeActivationLayer(entry, "values")).filter(Boolean) ?? [],
614
+ secrets: rawDefinition?.activate?.secrets?.map((entry) => normalizeActivationLayer(entry, "secrets")).filter(Boolean) ?? [],
615
+ envFiles: rawDefinition?.activate?.envFiles?.map((entry) => entry.trim()).filter(Boolean) ?? []
616
+ },
617
+ ...filePath ? { filePath } : {}
618
+ };
619
+ }
620
+ async function loadProfileDefinition(profileName, options) {
621
+ const workspaceRoots = options.workspace?.workspaceRoots ?? [];
622
+ if (workspaceRoots.length === 0) {
623
+ return normalizeProfileDefinition(profileName, void 0);
624
+ }
625
+ for (const workspaceRoot of [...workspaceRoots].reverse()) {
626
+ const profilePath = import_node_path4.default.join(workspaceRoot.path, "profiles", `${profileName}.yml`);
627
+ if (!await fileExists(profilePath)) {
628
+ continue;
629
+ }
630
+ const document = await (0, import_promises4.readFile)(profilePath, "utf8");
631
+ const parsed = parseYaml(document);
632
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
633
+ throw new CnosManifestError("Profile definition must be a YAML object", profilePath);
634
+ }
635
+ const definition = normalizeProfileDefinition(
636
+ profileName,
637
+ parsed,
638
+ options.manifestRoot ? toPortablePath(import_node_path4.default.relative(import_node_path4.default.dirname(options.manifestRoot), profilePath)) : toPortablePath(profilePath)
639
+ );
640
+ if (definition.name !== profileName) {
641
+ throw new CnosManifestError(
642
+ `Profile file name mismatch: expected "${profileName}" but found "${definition.name}"`,
643
+ profilePath
644
+ );
645
+ }
646
+ return definition;
647
+ }
648
+ return normalizeProfileDefinition(profileName, void 0);
649
+ }
650
+ function pushUnique(target, values) {
651
+ for (const value of values) {
652
+ if (!target.includes(value)) {
653
+ target.push(value);
654
+ }
655
+ }
656
+ }
657
+ function buildFallbackActivation(activeProfile, orderedProfiles) {
658
+ const overlayProfiles = orderedProfiles.filter((profile) => profile !== "base");
659
+ return {
660
+ values: [
661
+ "values",
662
+ ...activeProfile !== "base" ? ["values/base"] : [],
663
+ ...overlayProfiles.flatMap((profile) => [`profiles/${profile}/values`, `values/${profile}`])
664
+ ],
665
+ secrets: [
666
+ "secrets",
667
+ ...overlayProfiles.flatMap((profile) => [`profiles/${profile}/secrets`, `secrets/${profile}`])
668
+ ],
669
+ envFiles: activeProfile === "base" ? [".env"] : [".env", `.env.${activeProfile}`]
670
+ };
671
+ }
672
+ async function expandProfileChain(activeProfile, options = {}) {
673
+ const visiting = /* @__PURE__ */ new Set();
674
+ const resolved = /* @__PURE__ */ new Set();
675
+ const orderedProfiles = [];
676
+ const definitions = /* @__PURE__ */ new Map();
677
+ const visit = async (profileName) => {
678
+ if (resolved.has(profileName)) {
679
+ return;
680
+ }
681
+ if (visiting.has(profileName)) {
682
+ throw new CnosManifestError(`Detected profile inheritance cycle involving "${profileName}"`);
683
+ }
684
+ visiting.add(profileName);
685
+ const definition = await loadProfileDefinition(profileName, options);
686
+ definitions.set(profileName, definition);
687
+ for (const parent of definition.extends) {
688
+ await visit(parent);
689
+ }
690
+ visiting.delete(profileName);
691
+ resolved.add(profileName);
692
+ orderedProfiles.push(profileName);
693
+ };
694
+ await visit(activeProfile);
695
+ const activation = {
696
+ values: [],
697
+ secrets: [],
698
+ envFiles: []
699
+ };
700
+ for (const profileName of orderedProfiles) {
701
+ const definition = definitions.get(profileName);
702
+ if (!definition) {
703
+ continue;
704
+ }
705
+ pushUnique(activation.values, definition.activate.values);
706
+ pushUnique(activation.secrets, definition.activate.secrets);
707
+ pushUnique(activation.envFiles, definition.activate.envFiles);
708
+ }
709
+ const fallback = buildFallbackActivation(activeProfile, orderedProfiles);
710
+ if (activation.values.length === 0) {
711
+ activation.values = fallback.values;
712
+ }
713
+ if (activation.secrets.length === 0) {
714
+ activation.secrets = fallback.secrets;
715
+ }
716
+ if (activation.envFiles.length === 0) {
717
+ activation.envFiles = fallback.envFiles;
718
+ }
719
+ return {
720
+ activeProfile,
721
+ profiles: orderedProfiles,
722
+ activation
723
+ };
724
+ }
725
+
726
+ // ../core/src/promotions/validatePromotion.ts
727
+ var DEFAULT_DATA_NAMESPACE = {
728
+ kind: "data",
729
+ shareable: false
730
+ };
731
+ function getNamespaceNameForKey(key) {
732
+ const [namespace] = key.split(".");
733
+ if (!namespace || !key.includes(".")) {
734
+ throw new CnosManifestError(`Logical key must be namespace-qualified: ${key}`);
735
+ }
736
+ return namespace;
737
+ }
738
+ function getNamespaceDefinition(manifest, namespaceOrKey) {
739
+ const namespace = namespaceOrKey.includes(".") ? getNamespaceNameForKey(namespaceOrKey) : namespaceOrKey;
740
+ return manifest.namespaces[namespace] ?? DEFAULT_DATA_NAMESPACE;
741
+ }
742
+ function ensureProjectionAllowed(manifest, key, target) {
743
+ const namespace = getNamespaceNameForKey(key);
744
+ const definition = getNamespaceDefinition(manifest, namespace);
745
+ if (definition.kind !== "data") {
746
+ throw new CnosManifestError(
747
+ `Cannot promote ${key} to ${target} because namespace "${namespace}" is not a data namespace.`
748
+ );
749
+ }
750
+ if (definition.sensitive) {
751
+ throw new CnosSecurityError(
752
+ `Cannot promote ${key} to ${target} because namespace "${namespace}" is sensitive.`
753
+ );
754
+ }
755
+ if (!definition.shareable) {
756
+ throw new CnosSecurityError(
757
+ `Cannot promote ${key} to ${target} because namespace "${namespace}" is not shareable.`
758
+ );
759
+ }
760
+ }
761
+
762
+ // ../core/src/promotions/promoteToPublic.ts
763
+ function toPublicKey(key) {
764
+ const namespace = getNamespaceNameForKey(key);
765
+ return namespace === "value" ? `public.${stripNamespace(key)}` : `public.${key}`;
766
+ }
767
+ function toPromotedConfigEntry(entry, key, promotedFrom) {
768
+ return {
769
+ ...entry,
770
+ key,
771
+ namespace: "public",
772
+ sourceId: "public-promote",
773
+ pluginId: "core",
774
+ metadata: {
775
+ ...entry.metadata ?? {},
776
+ promotedFrom
777
+ }
778
+ };
779
+ }
780
+ function toPromotedResolvedEntry(entry) {
781
+ const key = toPublicKey(entry.key);
782
+ return {
783
+ key,
784
+ value: entry.value,
785
+ namespace: "public",
786
+ winner: toPromotedConfigEntry(entry.winner, key, entry.key),
787
+ overridden: entry.overridden.map((override) => toPromotedConfigEntry(override, key, entry.key))
788
+ };
789
+ }
790
+ function promoteToPublic(graph, manifest) {
791
+ const entries = new Map(graph.entries);
792
+ for (const key of manifest.public.promote) {
793
+ ensureProjectionAllowed(manifest, key, "public");
794
+ const resolved = graph.entries.get(key);
795
+ if (!resolved) {
796
+ continue;
797
+ }
798
+ entries.set(toPublicKey(key), toPromotedResolvedEntry(resolved));
799
+ }
800
+ return {
801
+ ...graph,
802
+ entries
803
+ };
804
+ }
805
+
806
+ // ../core/src/profiles/resolveActiveProfile.ts
807
+ function resolveActiveProfile(manifest, options = {}) {
808
+ for (const source of manifest.profiles.resolveFrom) {
809
+ if (source === "cli.profile" && options.profile) {
810
+ return {
811
+ profile: options.profile,
812
+ source: "cli"
813
+ };
814
+ }
815
+ if (source === "env.CNOS_PROFILE") {
816
+ if (options.workspaceFile?.profile) {
817
+ return {
818
+ profile: options.workspaceFile.profile,
819
+ source: "workspace-file"
820
+ };
821
+ }
822
+ const envProfile = options.processEnv?.CNOS_PROFILE;
823
+ if (envProfile) {
824
+ return {
825
+ profile: envProfile,
826
+ source: "env"
827
+ };
828
+ }
829
+ }
830
+ if (source === "default") {
831
+ return {
832
+ profile: manifest.profiles.default,
833
+ source: "manifest-default"
834
+ };
835
+ }
836
+ }
837
+ return {
838
+ profile: manifest.profiles.default,
839
+ source: "manifest-default"
840
+ };
841
+ }
842
+
843
+ // ../core/src/utils/deepMerge.ts
844
+ function isPlainObject(value) {
845
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
846
+ }
847
+ function deepMerge(base, override) {
848
+ const merged = { ...base };
849
+ for (const [key, value] of Object.entries(override)) {
850
+ const currentValue = merged[key];
851
+ if (isPlainObject(currentValue) && isPlainObject(value)) {
852
+ merged[key] = deepMerge(currentValue, value);
853
+ continue;
854
+ }
855
+ merged[key] = value;
856
+ }
857
+ return merged;
858
+ }
859
+
860
+ // ../core/src/resolvers/profileAwareResolver.ts
861
+ function mergeResolvedValue(currentValue, nextValue, arrayPolicy) {
862
+ if (Array.isArray(currentValue) && Array.isArray(nextValue)) {
863
+ if (arrayPolicy === "append") {
864
+ return [...currentValue, ...nextValue];
865
+ }
866
+ if (arrayPolicy === "unique-append") {
867
+ return [.../* @__PURE__ */ new Set([...currentValue, ...nextValue])];
868
+ }
869
+ return [...nextValue];
870
+ }
871
+ if (isPlainObject(currentValue) && isPlainObject(nextValue)) {
872
+ return deepMerge(currentValue, nextValue);
873
+ }
874
+ return nextValue;
875
+ }
876
+ function createProfileAwareResolver() {
877
+ return {
878
+ id: "profile-aware",
879
+ kind: "resolver",
880
+ async resolve(entries, context) {
881
+ const precedence = new Map(context.precedenceOrder.map((sourceId, index) => [sourceId, index]));
882
+ const sortedEntries = entries.map((entry, index) => ({
883
+ entry,
884
+ index,
885
+ precedence: precedence.get(entry.sourceId) ?? context.precedenceOrder.length
886
+ })).sort((left, right) => left.precedence - right.precedence || left.index - right.index);
887
+ const resolvedEntries = /* @__PURE__ */ new Map();
888
+ for (const { entry } of sortedEntries) {
889
+ const current = resolvedEntries.get(entry.key);
890
+ if (!current) {
891
+ resolvedEntries.set(entry.key, {
892
+ key: entry.key,
893
+ value: entry.value,
894
+ namespace: entry.namespace,
895
+ winner: entry,
896
+ overridden: []
897
+ });
898
+ continue;
899
+ }
900
+ resolvedEntries.set(entry.key, {
901
+ key: entry.key,
902
+ value: mergeResolvedValue(current.value, entry.value, context.manifest.resolution.arrayPolicy),
903
+ namespace: current.namespace,
904
+ winner: entry,
905
+ overridden: [...current.overridden, current.winner]
906
+ });
907
+ }
908
+ return {
909
+ entries: resolvedEntries,
910
+ profile: context.profile,
911
+ resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
912
+ profileSource: "manifest-default",
913
+ workspace: context.workspace
914
+ };
915
+ }
916
+ };
917
+ }
918
+
919
+ // ../core/src/workspaces/resolveWorkspaceContext.ts
920
+ var import_promises5 = require("fs/promises");
921
+ var import_node_path5 = __toESM(require("path"), 1);
922
+
923
+ // ../core/src/workspaces/expandWorkspaceChain.ts
924
+ function expandWorkspaceChain(workspaceId, items) {
925
+ if (Object.keys(items).length === 0) {
926
+ return [workspaceId];
927
+ }
928
+ if (!items[workspaceId]) {
929
+ throw new CnosManifestError(`Unknown workspace "${workspaceId}"`);
930
+ }
931
+ const visiting = /* @__PURE__ */ new Set();
932
+ const resolved = /* @__PURE__ */ new Set();
933
+ const chain = [];
934
+ const visit = (currentWorkspaceId) => {
935
+ if (resolved.has(currentWorkspaceId)) {
936
+ return;
937
+ }
938
+ if (visiting.has(currentWorkspaceId)) {
939
+ throw new CnosManifestError(`Detected workspace inheritance cycle involving "${currentWorkspaceId}"`);
940
+ }
941
+ const item = items[currentWorkspaceId];
942
+ if (!item) {
943
+ throw new CnosManifestError(`Unknown workspace "${currentWorkspaceId}"`);
944
+ }
945
+ visiting.add(currentWorkspaceId);
946
+ for (const parentWorkspaceId of item.extends) {
947
+ visit(parentWorkspaceId);
948
+ }
949
+ visiting.delete(currentWorkspaceId);
950
+ resolved.add(currentWorkspaceId);
951
+ chain.push(currentWorkspaceId);
952
+ };
953
+ visit(workspaceId);
954
+ return chain;
955
+ }
956
+
957
+ // ../core/src/workspaces/resolveWorkspaceContext.ts
958
+ async function exists2(targetPath) {
959
+ try {
960
+ await (0, import_promises5.access)(targetPath);
961
+ return true;
962
+ } catch {
963
+ return false;
964
+ }
965
+ }
966
+ async function resolveLocalWorkspaceRoot(manifestRoot, workspaceId, manifest) {
967
+ const workspaceRoot = import_node_path5.default.join(manifestRoot, "workspaces", workspaceId);
968
+ if (await exists2(workspaceRoot)) {
969
+ return workspaceRoot;
970
+ }
971
+ const customDataNamespaceRoots = Object.entries(manifest.namespaces).filter(
972
+ ([namespace, definition]) => namespace !== "value" && namespace !== "secret" && definition.kind === "data" && !definition.sensitive
973
+ ).map(([namespace]) => namespace);
974
+ const legacyMarkers = ["values", "secrets", "env", "profiles", ...customDataNamespaceRoots].map(
975
+ (segment) => import_node_path5.default.join(manifestRoot, segment)
976
+ );
977
+ if ((await Promise.all(legacyMarkers.map((marker) => exists2(marker)))).some(Boolean)) {
978
+ return manifestRoot;
979
+ }
980
+ return workspaceRoot;
981
+ }
982
+ function resolveWorkspaceSelection(manifest, workspaceFile, workspaceOption) {
983
+ if (workspaceOption) {
984
+ return {
985
+ workspaceId: workspaceOption,
986
+ source: "cli"
987
+ };
988
+ }
989
+ if (workspaceFile?.workspace) {
990
+ return {
991
+ workspaceId: workspaceFile.workspace,
992
+ source: "workspace-file"
993
+ };
994
+ }
995
+ if (manifest.workspaces.default) {
996
+ return {
997
+ workspaceId: manifest.workspaces.default,
998
+ source: "manifest-default"
999
+ };
1000
+ }
1001
+ if (Object.keys(manifest.workspaces.items).length === 0) {
1002
+ return {
1003
+ workspaceId: "default",
1004
+ source: "implicit"
1005
+ };
1006
+ }
1007
+ throw new CnosManifestError(
1008
+ "Workspace selection requires --workspace, .cnos-workspace.yml, or workspaces.default when workspaces.items are defined"
1009
+ );
1010
+ }
1011
+ function resolveGlobalRoot(manifest, workspaceFile, options) {
1012
+ if (!manifest.workspaces.global.enabled) {
1013
+ return {};
1014
+ }
1015
+ if (options.globalRoot) {
1016
+ return {
1017
+ value: import_node_path5.default.resolve(expandHomePath(options.globalRoot)),
1018
+ source: "cli"
1019
+ };
1020
+ }
1021
+ if (workspaceFile?.globalRoot) {
1022
+ return {
1023
+ value: import_node_path5.default.resolve(expandHomePath(workspaceFile.globalRoot)),
1024
+ source: "workspace-file"
1025
+ };
1026
+ }
1027
+ if (manifest.workspaces.global.root) {
1028
+ return {
1029
+ value: import_node_path5.default.resolve(expandHomePath(manifest.workspaces.global.root)),
1030
+ source: "manifest"
1031
+ };
1032
+ }
1033
+ const cnosHome = options.processEnv?.CNOS_HOME;
1034
+ if (cnosHome) {
1035
+ return {
1036
+ value: import_node_path5.default.resolve(expandHomePath(cnosHome)),
1037
+ source: "CNOS_HOME"
1038
+ };
1039
+ }
1040
+ return {};
1041
+ }
1042
+ async function resolveWorkspaceContext(manifest, options) {
1043
+ const selectedWorkspace = resolveWorkspaceSelection(manifest, options.workspaceFile, options.workspace);
1044
+ const workspaceChain = expandWorkspaceChain(selectedWorkspace.workspaceId, manifest.workspaces.items);
1045
+ const globalRoot = resolveGlobalRoot(manifest, options.workspaceFile, options);
1046
+ const workspaceRoots = [];
1047
+ if (globalRoot.value) {
1048
+ for (const chainWorkspaceId of workspaceChain) {
1049
+ const globalWorkspaceId = manifest.workspaces.items[chainWorkspaceId]?.globalId ?? chainWorkspaceId;
1050
+ workspaceRoots.push({
1051
+ scope: "global",
1052
+ workspaceId: chainWorkspaceId,
1053
+ path: import_node_path5.default.join(globalRoot.value, "workspaces", globalWorkspaceId)
1054
+ });
1055
+ }
1056
+ }
1057
+ for (const chainWorkspaceId of workspaceChain) {
1058
+ workspaceRoots.push({
1059
+ scope: "local",
1060
+ workspaceId: chainWorkspaceId,
1061
+ path: await resolveLocalWorkspaceRoot(options.manifestRoot, chainWorkspaceId, manifest)
1062
+ });
1063
+ }
1064
+ return {
1065
+ workspaceId: selectedWorkspace.workspaceId,
1066
+ workspaceSource: selectedWorkspace.source,
1067
+ ...globalRoot.value ? { globalRoot: globalRoot.value } : {},
1068
+ ...globalRoot.source ? { globalRootSource: globalRoot.source } : {},
1069
+ workspaceChain,
1070
+ workspaceRoots
1071
+ };
1072
+ }
1073
+
1074
+ // ../core/src/validation/basicSchema.ts
1075
+ function describeValueType(value) {
1076
+ if (Array.isArray(value)) {
1077
+ return "array";
1078
+ }
1079
+ if (value === null) {
1080
+ return "null";
1081
+ }
1082
+ return typeof value;
1083
+ }
1084
+ function coerceBoolean(value) {
1085
+ if (value === "true") {
1086
+ return true;
1087
+ }
1088
+ if (value === "false") {
1089
+ return false;
1090
+ }
1091
+ return void 0;
1092
+ }
1093
+ function coerceValue(value, rule) {
1094
+ if (typeof value !== "string" || !rule.type) {
1095
+ return value;
1096
+ }
1097
+ switch (rule.type) {
1098
+ case "number": {
1099
+ const parsed = Number(value);
1100
+ return Number.isNaN(parsed) ? value : parsed;
1101
+ }
1102
+ case "boolean":
1103
+ return coerceBoolean(value) ?? value;
1104
+ case "object":
1105
+ case "array": {
1106
+ try {
1107
+ const parsed = JSON.parse(value);
1108
+ if (rule.type === "array" && Array.isArray(parsed)) {
1109
+ return parsed;
1110
+ }
1111
+ if (rule.type === "object" && parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1112
+ return parsed;
1113
+ }
1114
+ return value;
1115
+ } catch {
1116
+ return value;
1117
+ }
1118
+ }
1119
+ default:
1120
+ return value;
1121
+ }
1122
+ }
1123
+ function matchesType(value, type) {
1124
+ if (!type) {
1125
+ return true;
1126
+ }
1127
+ switch (type) {
1128
+ case "array":
1129
+ return Array.isArray(value);
1130
+ case "object":
1131
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1132
+ default:
1133
+ return typeof value === type;
1134
+ }
1135
+ }
1136
+ function enumMatches(value, allowed) {
1137
+ const serialized = JSON.stringify(value);
1138
+ return allowed.some((candidate) => JSON.stringify(candidate) === serialized);
1139
+ }
1140
+ function applySchemaRules(graph, schema) {
1141
+ const nextEntries = new Map(graph.entries);
1142
+ const issues = [];
1143
+ for (const [key, rule] of Object.entries(schema).sort(([left], [right]) => left.localeCompare(right))) {
1144
+ const resolvedEntry = nextEntries.get(key);
1145
+ if (!resolvedEntry) {
1146
+ if (rule.default !== void 0) {
1147
+ const defaultEntry = {
1148
+ key,
1149
+ value: rule.default,
1150
+ namespace: key.startsWith("secret.") ? "secret" : key.startsWith("meta.") ? "meta" : "value",
1151
+ sourceId: "schema-default",
1152
+ pluginId: "basic-schema",
1153
+ workspaceId: graph.workspace.workspaceId,
1154
+ metadata: {
1155
+ schemaDefault: true
1156
+ }
1157
+ };
1158
+ nextEntries.set(key, {
1159
+ key,
1160
+ value: rule.default,
1161
+ namespace: defaultEntry.namespace,
1162
+ winner: defaultEntry,
1163
+ overridden: []
1164
+ });
1165
+ continue;
1166
+ }
1167
+ if (rule.required) {
1168
+ issues.push({
1169
+ code: "schema.required",
1170
+ key,
1171
+ message: `Missing required config key: ${key}`
1172
+ });
1173
+ }
1174
+ continue;
1175
+ }
1176
+ const coercedValue = coerceValue(resolvedEntry.value, rule);
1177
+ const nextResolvedEntry = coercedValue === resolvedEntry.value ? resolvedEntry : {
1178
+ ...resolvedEntry,
1179
+ value: coercedValue
1180
+ };
1181
+ if (!matchesType(coercedValue, rule.type)) {
1182
+ issues.push({
1183
+ code: "schema.type",
1184
+ key,
1185
+ message: `Config key ${key} expected type ${rule.type} but got ${describeValueType(coercedValue)}`
1186
+ });
1187
+ }
1188
+ if (rule.enum && !enumMatches(coercedValue, rule.enum)) {
1189
+ issues.push({
1190
+ code: "schema.enum",
1191
+ key,
1192
+ message: `Config key ${key} must be one of ${rule.enum.map((entry) => JSON.stringify(entry)).join(", ")}`
1193
+ });
1194
+ }
1195
+ if (rule.pattern) {
1196
+ if (typeof coercedValue !== "string") {
1197
+ issues.push({
1198
+ code: "schema.pattern",
1199
+ key,
1200
+ message: `Config key ${key} must be a string to match pattern ${rule.pattern}`
1201
+ });
1202
+ } else if (!new RegExp(rule.pattern).test(coercedValue)) {
1203
+ issues.push({
1204
+ code: "schema.pattern",
1205
+ key,
1206
+ message: `Config key ${key} does not match pattern ${rule.pattern}`
1207
+ });
1208
+ }
1209
+ }
1210
+ nextEntries.set(key, nextResolvedEntry);
1211
+ }
1212
+ return {
1213
+ graph: {
1214
+ ...graph,
1215
+ entries: nextEntries
1216
+ },
1217
+ issues
1218
+ };
1219
+ }
1220
+
1221
+ // ../core/src/orchestrator/pipeline.ts
1222
+ async function runPipeline(options) {
1223
+ const collectedEntries = await Promise.all(
1224
+ options.plugins.map(
1225
+ (plugin) => plugin.load({
1226
+ manifest: options.manifest,
1227
+ manifestConfig: {
1228
+ ...options.manifest.sources[plugin.id] ?? {},
1229
+ envMapping: options.manifest.envMapping
1230
+ },
1231
+ profile: options.profile,
1232
+ profileChain: options.profileChain,
1233
+ profileActivation: options.profileActivation,
1234
+ manifestRoot: options.manifestRoot,
1235
+ workspace: options.workspace,
1236
+ ...options.cliArgs ? { cliArgs: options.cliArgs } : {},
1237
+ ...options.processEnv ? { processEnv: options.processEnv } : {}
1238
+ })
1239
+ )
1240
+ );
1241
+ return collectedEntries.flat();
1242
+ }
1243
+
1244
+ // ../core/src/secrets/auditLog.ts
1245
+ var import_promises8 = require("fs/promises");
1246
+ var import_node_path8 = __toESM(require("path"), 1);
1247
+
1248
+ // ../core/src/utils/secretStore.ts
1249
+ var import_node_crypto = require("crypto");
1250
+ var import_promises7 = require("fs/promises");
1251
+ var import_node_path7 = __toESM(require("path"), 1);
1252
+
1253
+ // ../core/src/secrets/sessionStore.ts
1254
+ var import_promises6 = require("fs/promises");
1255
+ var import_node_path6 = __toESM(require("path"), 1);
1256
+ function buildSessionRoot(processEnv = process.env) {
1257
+ return import_node_path6.default.join(import_node_path6.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
1258
+ }
1259
+ function buildSessionPath(vault, processEnv) {
1260
+ return import_node_path6.default.join(buildSessionRoot(processEnv), `${vault}.json`);
1261
+ }
1262
+ async function readVaultSessionKey(vault, processEnv) {
1263
+ try {
1264
+ const source = await (0, import_promises6.readFile)(buildSessionPath(vault, processEnv), "utf8");
1265
+ const document = JSON.parse(source);
1266
+ if (document.version !== 1 || typeof document.derivedKey !== "string") {
1267
+ return void 0;
1268
+ }
1269
+ const key = Buffer.from(document.derivedKey, "hex");
1270
+ return key.length > 0 ? key : void 0;
1271
+ } catch {
1272
+ return void 0;
1273
+ }
1274
+ }
1275
+
1276
+ // ../core/src/utils/secretStore.ts
1277
+ var KEY_LENGTH = 32;
1278
+ var SALT_LENGTH = 32;
1279
+ var IV_LENGTH = 12;
1280
+ var AUTH_TAG_LENGTH = 16;
1281
+ var PBKDF2_ITERATIONS = 6e5;
1282
+ var KEYSTORE_VERSION = 1;
1283
+ var METADATA_VERSION = 1;
1284
+ var META_FILENAME = "meta.yml";
1285
+ var KEYSTORE_FILENAME = "keystore.enc";
1286
+ function isObject(value) {
1287
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1288
+ }
1289
+ function isSecretReference(value) {
1290
+ return isObject(value) && typeof value.provider === "string" && value.provider.trim().length > 0 && typeof value.ref === "string" && value.ref.trim().length > 0 && (value.vault === void 0 && true || typeof value.vault === "string" && value.vault.trim().length > 0) && Object.keys(value).every((key) => ["provider", "ref", "vault"].includes(key));
1291
+ }
1292
+ function resolveSecretStoreRoot(processEnv = process.env) {
1293
+ return import_node_path7.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
1294
+ }
1295
+ function normalizeVaultToken(vault = "default") {
1296
+ return vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1297
+ }
1298
+ function getVaultPassphraseEnvVar(vault = "default") {
1299
+ const vaultToken = normalizeVaultToken(vault);
1300
+ return vaultToken && vaultToken !== "DEFAULT" ? `CNOS_SECRET_PASSPHRASE_${vaultToken}` : "CNOS_SECRET_PASSPHRASE";
1301
+ }
1302
+ function getVaultSessionKeyEnvVar(vault = "default") {
1303
+ const vaultToken = normalizeVaultToken(vault);
1304
+ return `__CNOS_VAULT_KEY_${vaultToken || "DEFAULT"}__`;
1305
+ }
1306
+ function resolveSecretPassphrase(vault = "default", processEnv = process.env) {
1307
+ return processEnv[getVaultPassphraseEnvVar(vault)] ?? processEnv.CNOS_SECRET_PASSPHRASE;
1308
+ }
1309
+ function resolveVaultSessionKey(vault = "default", processEnv = process.env) {
1310
+ const encoded = processEnv[getVaultSessionKeyEnvVar(vault)];
1311
+ if (!encoded) {
1312
+ return readVaultSessionKey(vault, processEnv);
1313
+ }
1314
+ try {
1315
+ const key = Buffer.from(encoded, "hex");
1316
+ return key.length === KEY_LENGTH ? key : void 0;
1317
+ } catch {
1318
+ return void 0;
1319
+ }
1320
+ }
1321
+ function deriveVaultKey(passphrase, salt, iterations = PBKDF2_ITERATIONS) {
1322
+ return (0, import_node_crypto.pbkdf2Sync)(passphrase, salt, iterations, KEY_LENGTH, "sha512");
1323
+ }
1324
+ function buildMetaPath(storeRoot, vault = "default") {
1325
+ return import_node_path7.default.join(storeRoot, "vaults", vault, META_FILENAME);
1326
+ }
1327
+ function buildKeystorePath(storeRoot, vault = "default") {
1328
+ return import_node_path7.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
1329
+ }
1330
+ function buildLegacyVaultFile(storeRoot, vault = "default") {
1331
+ return import_node_path7.default.join(storeRoot, "vaults", `${vault}.json`);
1332
+ }
1333
+ function buildLegacyVaultStoreRoot(storeRoot, vault = "default") {
1334
+ return import_node_path7.default.join(storeRoot, "vaults", vault, "store");
1335
+ }
1336
+ function assertVaultMetadata(value, filePath) {
1337
+ if (!isObject(value)) {
1338
+ throw new CnosManifestError("Invalid CNOS vault metadata", filePath);
1339
+ }
1340
+ if (value.version !== METADATA_VERSION || value.algorithm !== "aes-256-gcm" || value.kdf !== "pbkdf2-sha512" || typeof value.iterations !== "number" || typeof value.salt !== "string" || typeof value.createdAt !== "string" || typeof value.secretCount !== "number") {
1341
+ throw new CnosManifestError("Invalid CNOS vault metadata", filePath);
1342
+ }
1343
+ return value;
1344
+ }
1345
+ async function exists3(targetPath) {
1346
+ try {
1347
+ await (0, import_promises7.stat)(targetPath);
1348
+ return true;
1349
+ } catch {
1350
+ return false;
1351
+ }
1352
+ }
1353
+ async function detectLegacyVaultFormat(storeRoot, vault = "default") {
1354
+ const legacyFile = buildLegacyVaultFile(storeRoot, vault);
1355
+ const legacyStore = buildLegacyVaultStoreRoot(storeRoot, vault);
1356
+ if (await exists3(legacyFile)) {
1357
+ return legacyFile;
1358
+ }
1359
+ if (await exists3(legacyStore)) {
1360
+ return legacyStore;
1361
+ }
1362
+ return void 0;
1363
+ }
1364
+ async function assertNoLegacyVaultFormat(storeRoot, vault = "default") {
1365
+ const legacyPath = await detectLegacyVaultFormat(storeRoot, vault);
1366
+ if (!legacyPath) {
1367
+ return;
1368
+ }
1369
+ throw new CnosSecurityError(
1370
+ `Legacy CNOS local vault format detected for vault "${vault}" at ${legacyPath}. CNOS 1.4 requires the new keystore format. Remove and recreate the vault.`
1371
+ );
1372
+ }
1373
+ function encryptPayload(payload, key) {
1374
+ const iv = (0, import_node_crypto.randomBytes)(IV_LENGTH);
1375
+ const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", key, iv);
1376
+ const plaintext = Buffer.from(JSON.stringify(payload), "utf8");
1377
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
1378
+ const tag = cipher.getAuthTag();
1379
+ return Buffer.concat([
1380
+ Buffer.from(Uint32Array.of(KEYSTORE_VERSION).buffer),
1381
+ iv,
1382
+ tag,
1383
+ ciphertext
1384
+ ]);
1385
+ }
1386
+ function decryptPayload(buffer, key) {
1387
+ if (buffer.length < 4 + IV_LENGTH + AUTH_TAG_LENGTH) {
1388
+ throw new CnosSecurityError("Invalid CNOS local vault keystore");
1389
+ }
1390
+ const version = buffer.readUInt32LE(0);
1391
+ if (version !== KEYSTORE_VERSION) {
1392
+ throw new CnosSecurityError(`Unsupported CNOS local vault keystore version: ${version}`);
1393
+ }
1394
+ const ivOffset = 4;
1395
+ const tagOffset = ivOffset + IV_LENGTH;
1396
+ const cipherOffset = tagOffset + AUTH_TAG_LENGTH;
1397
+ const iv = buffer.subarray(ivOffset, tagOffset);
1398
+ const tag = buffer.subarray(tagOffset, cipherOffset);
1399
+ const ciphertext = buffer.subarray(cipherOffset);
1400
+ const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", key, iv);
1401
+ decipher.setAuthTag(tag);
1402
+ try {
1403
+ const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
1404
+ const payload = JSON.parse(plaintext);
1405
+ if (!payload || !isObject(payload.secrets) || !isObject(payload.metadata)) {
1406
+ throw new Error("invalid");
1407
+ }
1408
+ return {
1409
+ secrets: Object.fromEntries(
1410
+ Object.entries(payload.secrets).filter((entry) => typeof entry[1] === "string")
1411
+ ),
1412
+ metadata: Object.fromEntries(
1413
+ Object.entries(payload.metadata).filter(
1414
+ (entry) => isObject(entry[1]) && typeof entry[1].createdAt === "string" && typeof entry[1].updatedAt === "string"
1415
+ )
1416
+ )
1417
+ };
1418
+ } catch {
1419
+ throw new CnosAuthenticationError("Failed to decrypt CNOS local vault. Check vault authentication.");
1420
+ }
1421
+ }
1422
+ function buildInitialPayload() {
1423
+ return {
1424
+ secrets: {},
1425
+ metadata: {}
1426
+ };
1427
+ }
1428
+ async function writeVaultFiles(storeRoot, vault, meta, payload, key) {
1429
+ const metaPath = buildMetaPath(storeRoot, vault);
1430
+ const keystorePath = buildKeystorePath(storeRoot, vault);
1431
+ await (0, import_promises7.mkdir)(import_node_path7.default.dirname(metaPath), { recursive: true });
1432
+ await (0, import_promises7.writeFile)(metaPath, stringifyYaml(meta), "utf8");
1433
+ await (0, import_promises7.writeFile)(keystorePath, encryptPayload(payload, key));
1434
+ }
1435
+ async function readVaultMetadata(storeRoot, vault = "default") {
1436
+ await assertNoLegacyVaultFormat(storeRoot, vault);
1437
+ const metaPath = buildMetaPath(storeRoot, vault);
1438
+ try {
1439
+ const source = await (0, import_promises7.readFile)(metaPath, "utf8");
1440
+ return assertVaultMetadata(parseYaml(source), metaPath);
1441
+ } catch (error) {
1442
+ if (error.code === "ENOENT") {
1443
+ return void 0;
1444
+ }
1445
+ throw error;
1446
+ }
1447
+ }
1448
+ async function createSecretVault(storeRoot, vault, passphrase) {
1449
+ const normalizedVault = vault.trim() || "default";
1450
+ await assertNoLegacyVaultFormat(storeRoot, normalizedVault);
1451
+ const salt = (0, import_node_crypto.randomBytes)(SALT_LENGTH);
1452
+ const key = deriveVaultKey(passphrase, salt, PBKDF2_ITERATIONS);
1453
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
1454
+ const meta = {
1455
+ version: METADATA_VERSION,
1456
+ algorithm: "aes-256-gcm",
1457
+ kdf: "pbkdf2-sha512",
1458
+ iterations: PBKDF2_ITERATIONS,
1459
+ salt: salt.toString("base64"),
1460
+ createdAt,
1461
+ secretCount: 0
1462
+ };
1463
+ await writeVaultFiles(storeRoot, normalizedVault, meta, buildInitialPayload(), key);
1464
+ return buildMetaPath(storeRoot, normalizedVault);
1465
+ }
1466
+ async function ensureSecretVault(storeRoot, vault, passphrase) {
1467
+ const normalizedVault = vault.trim() || "default";
1468
+ const meta = await readVaultMetadata(storeRoot, normalizedVault);
1469
+ if (meta) {
1470
+ return buildMetaPath(storeRoot, normalizedVault);
1471
+ }
1472
+ return createSecretVault(storeRoot, normalizedVault, passphrase);
1473
+ }
1474
+ function resolveConfiguredVaultPassphrase(definition, vault = "default", processEnv = process.env) {
1475
+ if (definition?.provider !== "local") {
1476
+ return void 0;
1477
+ }
1478
+ const configuredSources = definition.auth?.passphrase?.from ?? [];
1479
+ for (const source of configuredSources) {
1480
+ if (source.startsWith("env:")) {
1481
+ const value = processEnv[source.slice(4)];
1482
+ if (value) {
1483
+ return value;
1484
+ }
1485
+ }
1486
+ }
1487
+ return resolveSecretPassphrase(vault, processEnv);
1488
+ }
1489
+ async function resolveVaultAccessKey(storeRoot, definition, vault = "default", processEnv = process.env) {
1490
+ if (definition?.provider !== "local") {
1491
+ return definition?.provider === "github-secrets" ? {
1492
+ method: definition.auth?.method ?? "environment",
1493
+ ...definition?.auth?.config ? { config: definition.auth.config } : {}
1494
+ } : void 0;
1495
+ }
1496
+ const sessionKey = await resolveVaultSessionKey(vault, processEnv);
1497
+ if (sessionKey) {
1498
+ return {
1499
+ derivedKey: sessionKey,
1500
+ method: "keychain",
1501
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1502
+ };
1503
+ }
1504
+ const passphrase = resolveConfiguredVaultPassphrase(definition, vault, processEnv);
1505
+ if (passphrase) {
1506
+ return {
1507
+ passphrase,
1508
+ method: "passphrase",
1509
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1510
+ };
1511
+ }
1512
+ const metadata = await readVaultMetadata(storeRoot, vault);
1513
+ if (!metadata) {
1514
+ return void 0;
1515
+ }
1516
+ throw new CnosAuthenticationError(
1517
+ `Cannot authenticate to vault "${vault}". Set ${getVaultPassphraseEnvVar(vault)} or run cnos vault auth ${vault}.`
1518
+ );
1519
+ }
1520
+ async function loadVaultPayload(storeRoot, vault, auth) {
1521
+ const meta = await readVaultMetadata(storeRoot, vault);
1522
+ if (!meta) {
1523
+ throw new CnosManifestError(`Missing CNOS vault metadata for "${vault}"`);
1524
+ }
1525
+ const salt = Buffer.from(meta.salt, "base64");
1526
+ const key = auth.derivedKey ?? (auth.passphrase ? deriveVaultKey(auth.passphrase, salt, meta.iterations) : void 0);
1527
+ if (!key) {
1528
+ throw new CnosAuthenticationError(`Vault "${vault}" requires authentication before access.`);
1529
+ }
1530
+ const buffer = await (0, import_promises7.readFile)(buildKeystorePath(storeRoot, vault));
1531
+ return {
1532
+ meta,
1533
+ payload: decryptPayload(buffer, key),
1534
+ key
1535
+ };
1536
+ }
1537
+ async function writeLocalSecret(storeRoot, ref, value, authOrPassphrase, vault = "default") {
1538
+ const auth = typeof authOrPassphrase === "string" ? {
1539
+ passphrase: authOrPassphrase,
1540
+ method: "passphrase"
1541
+ } : authOrPassphrase;
1542
+ if (auth.passphrase) {
1543
+ await ensureSecretVault(storeRoot, vault, auth.passphrase);
1544
+ } else {
1545
+ const meta2 = await readVaultMetadata(storeRoot, vault);
1546
+ if (!meta2) {
1547
+ throw new CnosAuthenticationError(`Vault "${vault}" requires passphrase-based authentication for initial creation.`);
1548
+ }
1549
+ }
1550
+ const { meta, payload, key } = await loadVaultPayload(storeRoot, vault, auth);
1551
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1552
+ const existing = payload.metadata[ref];
1553
+ payload.secrets[ref] = value;
1554
+ payload.metadata[ref] = {
1555
+ createdAt: existing?.createdAt ?? now,
1556
+ updatedAt: now
1557
+ };
1558
+ const nextMeta = {
1559
+ ...meta,
1560
+ secretCount: Object.keys(payload.secrets).length
1561
+ };
1562
+ await writeVaultFiles(storeRoot, vault, nextMeta, payload, key);
1563
+ return buildKeystorePath(storeRoot, vault);
1564
+ }
1565
+ async function deleteLocalSecret(storeRoot, ref, auth, vault = "default") {
1566
+ const { meta, payload, key } = await loadVaultPayload(storeRoot, vault, auth);
1567
+ if (!(ref in payload.secrets)) {
1568
+ return false;
1569
+ }
1570
+ delete payload.secrets[ref];
1571
+ delete payload.metadata[ref];
1572
+ const nextMeta = {
1573
+ ...meta,
1574
+ secretCount: Object.keys(payload.secrets).length
1575
+ };
1576
+ await writeVaultFiles(storeRoot, vault, nextMeta, payload, key);
1577
+ return true;
1578
+ }
1579
+ async function readLocalSecret(storeRoot, ref, auth, vault = "default") {
1580
+ const { payload } = await loadVaultPayload(storeRoot, vault, auth);
1581
+ const value = payload.secrets[ref];
1582
+ if (value === void 0) {
1583
+ throw new CnosManifestError(`Missing local secret ref "${ref}" in vault "${vault}"`);
1584
+ }
1585
+ return value;
1586
+ }
1587
+ async function listLocalSecrets(storeRoot, auth, vault = "default") {
1588
+ const { payload } = await loadVaultPayload(storeRoot, vault, auth);
1589
+ return Object.keys(payload.secrets).sort((left, right) => left.localeCompare(right));
1590
+ }
1591
+ function resolveVaultDefinition(vaults, vault = "default") {
1592
+ const definition = vaults?.[vault];
1593
+ const provider = definition?.provider ?? "local";
1594
+ return {
1595
+ name: vault,
1596
+ provider,
1597
+ ...definition?.auth ? { auth: definition.auth } : {},
1598
+ ...definition?.mapping ? { mapping: definition.mapping } : {},
1599
+ requiresAuthentication: provider === "local"
1600
+ };
1601
+ }
1602
+
1603
+ // ../core/src/secrets/auditLog.ts
1604
+ async function appendAuditEvent(event, processEnv = process.env) {
1605
+ const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path8.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
1606
+ await (0, import_promises8.mkdir)(import_node_path8.default.dirname(auditFile), { recursive: true });
1607
+ await (0, import_promises8.appendFile)(
1608
+ auditFile,
1609
+ `${JSON.stringify({
1610
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
1611
+ ...event
1612
+ })}
1613
+ `,
1614
+ "utf8"
1615
+ );
1616
+ }
1617
+
1618
+ // ../core/src/secrets/secretCache.ts
1619
+ var SecretCache = class {
1620
+ cache = /* @__PURE__ */ new Map();
1621
+ authenticated = /* @__PURE__ */ new Set();
1622
+ load(vaultId, secrets) {
1623
+ this.authenticated.add(vaultId);
1624
+ for (const [ref, value] of secrets) {
1625
+ this.cache.set(`${vaultId}:${ref}`, value);
1626
+ }
1627
+ }
1628
+ isVaultAuthenticated(vaultId) {
1629
+ return this.authenticated.has(vaultId);
1630
+ }
1631
+ get(vaultId, ref) {
1632
+ return this.cache.get(`${vaultId}:${ref}`);
1633
+ }
1634
+ clear(vaultId) {
1635
+ if (!vaultId) {
1636
+ this.cache.clear();
1637
+ this.authenticated.clear();
1638
+ return;
1639
+ }
1640
+ this.authenticated.delete(vaultId);
1641
+ for (const key of Array.from(this.cache.keys())) {
1642
+ if (key.startsWith(`${vaultId}:`)) {
1643
+ this.cache.delete(key);
1644
+ }
1645
+ }
1646
+ }
1647
+ };
1648
+
1649
+ // ../core/src/secrets/providers/github.ts
1650
+ var GithubSecretsVaultProvider = class {
1651
+ constructor(vaultId, definition, processEnv = process.env) {
1652
+ this.vaultId = vaultId;
1653
+ this.definition = definition;
1654
+ this.processEnv = processEnv;
1655
+ }
1656
+ vaultId;
1657
+ definition;
1658
+ processEnv;
1659
+ authenticated = false;
1660
+ async authenticate(_authConfig) {
1661
+ void _authConfig;
1662
+ this.authenticated = true;
1663
+ }
1664
+ isAuthenticated() {
1665
+ return this.authenticated;
1666
+ }
1667
+ resolveEnvVar(ref) {
1668
+ if (this.processEnv[ref] !== void 0) {
1669
+ return ref;
1670
+ }
1671
+ return Object.entries(this.definition.mapping ?? {}).find(([, logicalRef]) => logicalRef === ref)?.[0];
1672
+ }
1673
+ async batchGet(refs) {
1674
+ this.authenticated = true;
1675
+ const resolved = /* @__PURE__ */ new Map();
1676
+ for (const ref of Array.from(new Set(refs)).sort((left, right) => left.localeCompare(right))) {
1677
+ const envVar = this.resolveEnvVar(ref);
1678
+ const value = envVar ? this.processEnv[envVar] : void 0;
1679
+ if (value !== void 0) {
1680
+ resolved.set(ref, value);
1681
+ }
1682
+ }
1683
+ return resolved;
1684
+ }
1685
+ async get(ref) {
1686
+ const envVar = this.resolveEnvVar(ref);
1687
+ this.authenticated = true;
1688
+ return envVar ? this.processEnv[envVar] : void 0;
1689
+ }
1690
+ async set(ref, value) {
1691
+ void ref;
1692
+ void value;
1693
+ throw new Error(`Vault "${this.vaultId}" is environment-backed and cannot be written by CNOS.`);
1694
+ }
1695
+ async delete(ref) {
1696
+ void ref;
1697
+ throw new Error(`Vault "${this.vaultId}" is environment-backed and cannot be mutated by CNOS.`);
1698
+ }
1699
+ async list() {
1700
+ return Object.values(this.definition.mapping ?? {}).sort((left, right) => left.localeCompare(right));
1701
+ }
1702
+ };
1703
+
1704
+ // ../core/src/secrets/providers/local.ts
1705
+ var LocalSecretVaultProvider = class _LocalSecretVaultProvider {
1706
+ constructor(vaultId, definition, processEnv = process.env, storeRoot = resolveSecretStoreRoot(processEnv)) {
1707
+ this.vaultId = vaultId;
1708
+ this.processEnv = processEnv;
1709
+ this.storeRoot = storeRoot;
1710
+ this.definition = definition;
1711
+ }
1712
+ vaultId;
1713
+ processEnv;
1714
+ storeRoot;
1715
+ authConfig;
1716
+ definition;
1717
+ static fromVaults(vaults, vaultId, processEnv) {
1718
+ const definition = resolveVaultDefinition(vaults, vaultId);
1719
+ return new _LocalSecretVaultProvider(vaultId, definition, processEnv);
1720
+ }
1721
+ async authenticate(authConfig) {
1722
+ this.authConfig = authConfig;
1723
+ await this.list();
1724
+ }
1725
+ isAuthenticated() {
1726
+ return Boolean(this.authConfig);
1727
+ }
1728
+ async requireAuth() {
1729
+ if (this.authConfig) {
1730
+ return this.authConfig;
1731
+ }
1732
+ const resolved = await resolveVaultAccessKey(this.storeRoot, this.definition, this.vaultId, this.processEnv);
1733
+ if (!resolved) {
1734
+ throw new CnosAuthenticationError(
1735
+ `Cannot authenticate to vault "${this.vaultId}". Set the configured passphrase env var or run cnos vault auth ${this.vaultId}.`
1736
+ );
1737
+ }
1738
+ this.authConfig = resolved;
1739
+ return resolved;
1740
+ }
1741
+ async batchGet(refs) {
1742
+ const auth = await this.requireAuth();
1743
+ const entries = await Promise.all(
1744
+ Array.from(new Set(refs)).sort((left, right) => left.localeCompare(right)).map(async (ref) => [ref, await readLocalSecret(this.storeRoot, ref, auth, this.vaultId)])
1745
+ );
1746
+ return new Map(entries);
1747
+ }
1748
+ async get(ref) {
1749
+ const auth = await this.requireAuth();
1750
+ try {
1751
+ return await readLocalSecret(this.storeRoot, ref, auth, this.vaultId);
1752
+ } catch {
1753
+ return void 0;
1754
+ }
1755
+ }
1756
+ async set(ref, value) {
1757
+ const auth = await this.requireAuth();
1758
+ await writeLocalSecret(this.storeRoot, ref, value, auth, this.vaultId);
1759
+ await appendAuditEvent(
1760
+ {
1761
+ action: "write",
1762
+ vault: this.vaultId,
1763
+ ref,
1764
+ caller: "cli"
1765
+ },
1766
+ this.processEnv
1767
+ );
1768
+ }
1769
+ async delete(ref) {
1770
+ const auth = await this.requireAuth();
1771
+ await deleteLocalSecret(this.storeRoot, ref, auth, this.vaultId);
1772
+ await appendAuditEvent(
1773
+ {
1774
+ action: "delete",
1775
+ vault: this.vaultId,
1776
+ ref,
1777
+ caller: "cli"
1778
+ },
1779
+ this.processEnv
1780
+ );
1781
+ }
1782
+ async list() {
1783
+ const auth = this.authConfig ?? await resolveVaultAccessKey(this.storeRoot, this.definition, this.vaultId, this.processEnv);
1784
+ if (!auth) {
1785
+ throw new CnosAuthenticationError(
1786
+ `Cannot authenticate to vault "${this.vaultId}". Set the configured passphrase env var or run cnos vault auth ${this.vaultId}.`
1787
+ );
1788
+ }
1789
+ this.authConfig = auth;
1790
+ return listLocalSecrets(this.storeRoot, auth, this.vaultId);
1791
+ }
1792
+ };
1793
+
1794
+ // ../core/src/secrets/providers/registry.ts
1795
+ function createSecretVaultProvider(vaultId, definition, processEnv) {
1796
+ if (definition.provider === "local") {
1797
+ return new LocalSecretVaultProvider(vaultId, definition, processEnv);
1798
+ }
1799
+ if (definition.provider === "github-secrets") {
1800
+ return new GithubSecretsVaultProvider(vaultId, definition, processEnv);
1801
+ }
1802
+ throw new CnosManifestError(`Unsupported vault provider: ${definition.provider}`);
1803
+ }
1804
+
1805
+ // ../core/src/secrets/prompt.ts
1806
+ var import_node_readline = __toESM(require("readline"), 1);
1807
+ var import_node_stream = require("stream");
1808
+ async function promptHidden(message) {
1809
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
1810
+ return void 0;
1811
+ }
1812
+ const mutableStdout = new WritableMask();
1813
+ const rl = import_node_readline.default.createInterface({
1814
+ input: process.stdin,
1815
+ output: mutableStdout,
1816
+ terminal: true
1817
+ });
1818
+ try {
1819
+ mutableStdout.muted = true;
1820
+ const value = await new Promise((resolve) => {
1821
+ rl.question(message, resolve);
1822
+ });
1823
+ process.stdout.write("\n");
1824
+ return value;
1825
+ } finally {
1826
+ rl.close();
1827
+ }
1828
+ }
1829
+ var WritableMask = class extends import_node_stream.Writable {
1830
+ muted = false;
1831
+ _write(chunk, _encoding, callback) {
1832
+ if (!this.muted) {
1833
+ process.stdout.write(chunk);
1834
+ }
1835
+ callback();
1836
+ }
1837
+ };
1838
+
1839
+ // ../core/src/secrets/resolveAuth.ts
1840
+ function toAuthError(vaultId, sources) {
1841
+ return new CnosAuthenticationError(
1842
+ `Cannot authenticate to vault "${vaultId}". Tried: ${sources.join(", ")}. Set ${getVaultPassphraseEnvVar(vaultId)} or run cnos vault auth ${vaultId}.`
1843
+ );
1844
+ }
1845
+ async function resolveVaultAuth(vaultId, definition, processEnv = process.env) {
1846
+ const sessionKey = await resolveVaultSessionKey(vaultId, processEnv);
1847
+ if (sessionKey) {
1848
+ return {
1849
+ derivedKey: sessionKey,
1850
+ method: "keychain",
1851
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1852
+ };
1853
+ }
1854
+ if (definition.provider === "github-secrets") {
1855
+ return {
1856
+ method: definition.auth?.method ?? "environment",
1857
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1858
+ };
1859
+ }
1860
+ const sources = definition.auth?.passphrase?.from ?? [getVaultPassphraseEnvVar(vaultId)];
1861
+ for (const source of sources) {
1862
+ if (source.startsWith("env:")) {
1863
+ const value = processEnv[source.slice(4)];
1864
+ if (value) {
1865
+ return {
1866
+ passphrase: value,
1867
+ method: "passphrase",
1868
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1869
+ };
1870
+ }
1871
+ }
1872
+ if (source.startsWith("keychain:")) {
1873
+ const value = await readKeychain(source.slice("keychain:".length));
1874
+ if (value) {
1875
+ return {
1876
+ derivedKey: Buffer.from(value, "hex"),
1877
+ method: "keychain",
1878
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1879
+ };
1880
+ }
1881
+ }
1882
+ if (source === "prompt") {
1883
+ const value = await promptHidden(`Enter passphrase for vault "${vaultId}": `);
1884
+ if (value) {
1885
+ return {
1886
+ passphrase: value,
1887
+ method: "passphrase",
1888
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1889
+ };
1890
+ }
1891
+ }
1892
+ }
1893
+ const fallback = resolveSecretPassphrase(vaultId, processEnv);
1894
+ if (fallback) {
1895
+ return {
1896
+ passphrase: fallback,
1897
+ method: "passphrase",
1898
+ ...definition.auth?.config ? { config: definition.auth.config } : {}
1899
+ };
1900
+ }
1901
+ throw toAuthError(vaultId, [getVaultSessionKeyEnvVar(vaultId), ...sources]);
1902
+ }
1903
+
1904
+ // ../core/src/secrets/batchResolve.ts
1905
+ function collectSecretDescriptors(graph) {
1906
+ return Array.from(graph.entries.values()).filter((entry) => entry.namespace === "secret" && isSecretReference(entry.value)).map((entry) => ({
1907
+ logicalKey: entry.key,
1908
+ ref: entry.value
1909
+ }));
1910
+ }
1911
+ async function batchResolveSecrets(graph, manifest, processEnv = process.env) {
1912
+ const cache = new SecretCache();
1913
+ const descriptors = collectSecretDescriptors(graph);
1914
+ const grouped = descriptors.reduce((accumulator, descriptor) => {
1915
+ const vaultId = descriptor.ref.vault ?? "default";
1916
+ const bucket = accumulator.get(vaultId) ?? [];
1917
+ bucket.push(descriptor);
1918
+ accumulator.set(vaultId, bucket);
1919
+ return accumulator;
1920
+ }, /* @__PURE__ */ new Map());
1921
+ for (const [vaultId, refs] of grouped) {
1922
+ const definition = manifest.vaults[vaultId] ?? { provider: "local", auth: { passphrase: { from: [] } } };
1923
+ const provider = createSecretVaultProvider(vaultId, definition, processEnv);
1924
+ const auth = await resolveVaultAuth(vaultId, definition, processEnv);
1925
+ await provider.authenticate(auth);
1926
+ const resolved = await provider.batchGet(refs.map((entry) => entry.ref.ref));
1927
+ cache.load(vaultId, resolved);
1928
+ await appendAuditEvent(
1929
+ {
1930
+ action: "batch_read",
1931
+ vault: vaultId,
1932
+ refs: Array.from(resolved.keys()).sort((left, right) => left.localeCompare(right)),
1933
+ caller: "runtime",
1934
+ workspace: graph.workspace.workspaceId,
1935
+ profile: graph.profile
1936
+ },
1937
+ processEnv
1938
+ );
1939
+ }
1940
+ return cache;
1941
+ }
1942
+ function resolveSecretEntryValue(key, value, cache) {
1943
+ if (!key.startsWith("secret.") || !isSecretReference(value)) {
1944
+ return value;
1945
+ }
1946
+ const vaultId = value.vault ?? "default";
1947
+ return cache.get(vaultId, value.ref) ?? value;
1948
+ }
1949
+
1950
+ // ../core/src/runtime/projection.ts
1951
+ function setNestedValue(target, pathSegments, value) {
1952
+ const [head, ...tail] = pathSegments;
1953
+ if (!head) {
1954
+ return;
1955
+ }
1956
+ if (tail.length === 0) {
1957
+ target[head] = value;
1958
+ return;
1959
+ }
1960
+ const current = target[head];
1961
+ const nextTarget = current && typeof current === "object" && !Array.isArray(current) ? current : {};
1962
+ target[head] = nextTarget;
1963
+ setNestedValue(nextTarget, tail, value);
1964
+ }
1965
+ function toNamespaceObject(graph, namespace) {
1966
+ const output = {};
1967
+ const resolvedEntries = Array.from(graph.entries.values()).sort(
1968
+ (left, right) => left.key.localeCompare(right.key)
1969
+ );
1970
+ for (const entry of resolvedEntries) {
1971
+ if (namespace && entry.namespace !== namespace) {
1972
+ continue;
1973
+ }
1974
+ const valuePath = namespace ? stripNamespace(entry.key) : entry.key;
1975
+ setNestedValue(output, valuePath.split("."), entry.value);
1976
+ }
1977
+ return output;
1978
+ }
1979
+
1980
+ // ../core/src/runtime/read.ts
1981
+ function readValue(graph, key) {
1982
+ return graph.entries.get(key)?.value;
1983
+ }
1984
+
1985
+ // ../core/src/runtime/readOr.ts
1986
+ function readOrValue(graph, key, fallback) {
1987
+ const value = readValue(graph, key);
1988
+ return value === void 0 ? fallback : value;
1989
+ }
1990
+
1991
+ // ../core/src/runtime/require.ts
1992
+ function requireValue(graph, key) {
1993
+ const value = readValue(graph, key);
1994
+ if (value === void 0) {
1995
+ throw new CnosKeyNotFoundError(key);
1996
+ }
1997
+ return value;
1998
+ }
1999
+
2000
+ // ../core/src/runtime/toEnv.ts
2001
+ function normalizeEnvValue(value) {
2002
+ if (value === void 0 || value === null) {
2003
+ return "";
2004
+ }
2005
+ if (typeof value === "string") {
2006
+ return value;
2007
+ }
2008
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
2009
+ return String(value);
2010
+ }
2011
+ return JSON.stringify(value);
2012
+ }
2013
+ function toEnv(graph, manifest, options = {}) {
2014
+ const includeSecrets = options.includeSecrets ?? true;
2015
+ const output = {};
2016
+ const mappedEntries = Object.entries(manifest.envMapping.explicit).sort(
2017
+ ([left], [right]) => left.localeCompare(right)
2018
+ );
2019
+ for (const [envVar, logicalKey] of mappedEntries) {
2020
+ const entry = graph.entries.get(logicalKey);
2021
+ if (!entry) {
2022
+ continue;
2023
+ }
2024
+ const namespaceDefinition = getNamespaceDefinition(manifest, entry.namespace);
2025
+ if (namespaceDefinition.kind !== "data" || !namespaceDefinition.shareable || namespaceDefinition.sensitive) {
2026
+ continue;
2027
+ }
2028
+ if (entry.namespace === "secret" && !includeSecrets) {
2029
+ continue;
2030
+ }
2031
+ if (isSecretReference(entry.value)) {
2032
+ continue;
2033
+ }
2034
+ output[envVar] = normalizeEnvValue(entry.value);
2035
+ }
2036
+ return output;
2037
+ }
2038
+
2039
+ // ../core/src/runtime/toPublicEnv.ts
2040
+ function fallbackPublicEnvVar(valuePath) {
2041
+ return valuePath.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
2042
+ }
2043
+ function normalizeEnvValue2(value) {
2044
+ if (value === void 0 || value === null) {
2045
+ return "";
2046
+ }
2047
+ if (typeof value === "string") {
2048
+ return value;
2049
+ }
2050
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
2051
+ return String(value);
2052
+ }
2053
+ return JSON.stringify(value);
2054
+ }
2055
+ function resolvePublicPrefix(manifest, options) {
2056
+ if (options.prefix) {
2057
+ return options.prefix;
2058
+ }
2059
+ if (!options.framework) {
2060
+ return "";
2061
+ }
2062
+ const configuredPrefix = manifest.public.frameworks[options.framework];
2063
+ if (!configuredPrefix) {
2064
+ throw new CnosManifestError(`Unknown public framework prefix: ${options.framework}`);
2065
+ }
2066
+ return configuredPrefix;
2067
+ }
2068
+ function toPublicEnv(graph, manifest, options = {}) {
2069
+ const prefix = resolvePublicPrefix(manifest, options);
2070
+ const output = {};
2071
+ const promotions = Array.from(graph.entries.values()).filter((entry) => entry.namespace === "public").sort((left, right) => left.key.localeCompare(right.key));
2072
+ for (const resolved of promotions) {
2073
+ const baseEnvVar = fallbackPublicEnvVar(stripNamespace(resolved.key));
2074
+ const envVar = prefix && !baseEnvVar.startsWith(prefix) ? `${prefix}${baseEnvVar}` : baseEnvVar;
2075
+ output[envVar] = normalizeEnvValue2(resolved.value);
2076
+ }
2077
+ return output;
2078
+ }
2079
+
2080
+ // ../core/src/orchestrator/runtime.ts
2081
+ function createRuntime(manifest, graph, plugins = [], secretCache) {
2082
+ function readLogicalKey(key) {
2083
+ const entry = graph.entries.get(key);
2084
+ if (!entry) {
2085
+ return void 0;
2086
+ }
2087
+ if (!secretCache) {
2088
+ return entry.value;
2089
+ }
2090
+ return resolveSecretEntryValue(key, entry.value, secretCache);
2091
+ }
2092
+ return {
2093
+ manifest,
2094
+ plugins,
2095
+ graph,
2096
+ read(key) {
2097
+ return readLogicalKey(key);
2098
+ },
2099
+ require(key) {
2100
+ const value = readLogicalKey(key);
2101
+ if (value === void 0) {
2102
+ return requireValue(graph, key);
2103
+ }
2104
+ return value;
2105
+ },
2106
+ readOr(key, fallback) {
2107
+ return readOrValue(graph, key, fallback);
2108
+ },
2109
+ value(path12) {
2110
+ return readLogicalKey(toLogicalKey("value", path12));
2111
+ },
2112
+ secret(path12) {
2113
+ return readLogicalKey(toLogicalKey("secret", path12));
2114
+ },
2115
+ meta(path12) {
2116
+ return readLogicalKey(toLogicalKey("meta", path12));
2117
+ },
2118
+ inspect(key) {
2119
+ return inspectValue(graph, key);
2120
+ },
2121
+ toObject() {
2122
+ return toNamespaceObject(graph);
2123
+ },
2124
+ toNamespace(namespace) {
2125
+ return toNamespaceObject(graph, namespace);
2126
+ },
2127
+ toEnv(options) {
2128
+ return toEnv(graph, manifest, options);
2129
+ },
2130
+ toPublicEnv(options) {
2131
+ return toPublicEnv(graph, manifest, options);
2132
+ }
2133
+ };
2134
+ }
2135
+
2136
+ // ../core/src/orchestrator/createCnos.ts
2137
+ function buildMetaEntries(graph, cnosVersion) {
2138
+ return [
2139
+ {
2140
+ key: "meta.profile",
2141
+ value: graph.profile,
2142
+ namespace: "meta",
2143
+ sourceId: "profile-resolver",
2144
+ pluginId: "core",
2145
+ workspaceId: graph.workspace.workspaceId
2146
+ },
2147
+ {
2148
+ key: "meta.cnos.version",
2149
+ value: cnosVersion ?? "0.0.0-dev",
2150
+ namespace: "meta",
2151
+ sourceId: "core",
2152
+ pluginId: "core",
2153
+ workspaceId: graph.workspace.workspaceId
2154
+ },
2155
+ {
2156
+ key: "meta.resolved.at",
2157
+ value: graph.resolvedAt,
2158
+ namespace: "meta",
2159
+ sourceId: "core",
2160
+ pluginId: "core",
2161
+ workspaceId: graph.workspace.workspaceId
2162
+ },
2163
+ {
2164
+ key: "meta.resolved.from",
2165
+ value: graph.profileSource,
2166
+ namespace: "meta",
2167
+ sourceId: "profile-resolver",
2168
+ pluginId: "core",
2169
+ workspaceId: graph.workspace.workspaceId
2170
+ },
2171
+ {
2172
+ key: "meta.workspace",
2173
+ value: graph.workspace.workspaceId,
2174
+ namespace: "meta",
2175
+ sourceId: "workspace-resolver",
2176
+ pluginId: "core",
2177
+ workspaceId: graph.workspace.workspaceId
2178
+ },
2179
+ {
2180
+ key: "meta.workspace.source",
2181
+ value: graph.workspace.workspaceSource,
2182
+ namespace: "meta",
2183
+ sourceId: "workspace-resolver",
2184
+ pluginId: "core",
2185
+ workspaceId: graph.workspace.workspaceId
2186
+ },
2187
+ {
2188
+ key: "meta.workspace.chain",
2189
+ value: graph.workspace.workspaceChain,
2190
+ namespace: "meta",
2191
+ sourceId: "workspace-resolver",
2192
+ pluginId: "core",
2193
+ workspaceId: graph.workspace.workspaceId
2194
+ },
2195
+ {
2196
+ key: "meta.globalRoot",
2197
+ value: graph.workspace.globalRoot ?? null,
2198
+ namespace: "meta",
2199
+ sourceId: "workspace-resolver",
2200
+ pluginId: "core",
2201
+ workspaceId: graph.workspace.workspaceId
2202
+ },
2203
+ {
2204
+ key: "meta.global.enabled",
2205
+ value: Boolean(graph.workspace.globalRoot),
2206
+ namespace: "meta",
2207
+ sourceId: "workspace-resolver",
2208
+ pluginId: "core",
2209
+ workspaceId: graph.workspace.workspaceId
2210
+ }
2211
+ ];
2212
+ }
2213
+ function appendMetaEntries(graph, cnosVersion) {
2214
+ const nextEntries = new Map(graph.entries);
2215
+ for (const entry of buildMetaEntries(graph, cnosVersion)) {
2216
+ nextEntries.set(entry.key, {
2217
+ key: entry.key,
2218
+ value: entry.value,
2219
+ namespace: entry.namespace,
2220
+ winner: entry,
2221
+ overridden: []
2222
+ });
2223
+ }
2224
+ return {
2225
+ ...graph,
2226
+ entries: nextEntries
2227
+ };
2228
+ }
2229
+ async function createCnos(options = {}) {
2230
+ const loadedManifest = await loadManifest(options.root ? { root: options.root } : {});
2231
+ for (const key of loadedManifest.manifest.public.promote) {
2232
+ ensureProjectionAllowed(loadedManifest.manifest, key, "public");
2233
+ }
2234
+ const workspaceFile = await loadWorkspaceFile(loadedManifest.repoRoot);
2235
+ const workspace = await resolveWorkspaceContext(loadedManifest.manifest, {
2236
+ manifestRoot: loadedManifest.manifestRoot,
2237
+ ...workspaceFile ? { workspaceFile: workspaceFile.config } : {},
2238
+ ...options.workspace ? { workspace: options.workspace } : {},
2239
+ ...options.globalRoot ? { globalRoot: options.globalRoot } : {},
2240
+ ...options.processEnv ? { processEnv: options.processEnv } : {}
2241
+ });
2242
+ const activeProfile = resolveActiveProfile(loadedManifest.manifest, {
2243
+ ...options.profile ? { profile: options.profile } : {},
2244
+ ...workspaceFile ? { workspaceFile: workspaceFile.config } : {},
2245
+ ...options.processEnv ? { processEnv: options.processEnv } : {}
2246
+ });
2247
+ const profileChain = await expandProfileChain(activeProfile.profile, {
2248
+ manifestRoot: loadedManifest.manifestRoot,
2249
+ workspace
2250
+ });
2251
+ const plugins = options.plugins ?? [];
2252
+ const loaderPlugins = plugins.filter((plugin) => plugin.kind === "loader");
2253
+ const resolverPlugin = plugins.find((plugin) => plugin.kind === "resolver") ?? createProfileAwareResolver();
2254
+ const entries = await runPipeline({
2255
+ manifestRoot: loadedManifest.manifestRoot,
2256
+ manifest: loadedManifest.manifest,
2257
+ profile: activeProfile.profile,
2258
+ profileChain: profileChain.profiles,
2259
+ profileActivation: profileChain.activation,
2260
+ workspace,
2261
+ plugins: loaderPlugins,
2262
+ ...options.cliArgs ? { cliArgs: options.cliArgs } : {},
2263
+ ...options.processEnv ? { processEnv: options.processEnv } : {}
2264
+ });
2265
+ const graph = await resolverPlugin.resolve(entries, {
2266
+ manifest: loadedManifest.manifest,
2267
+ profile: activeProfile.profile,
2268
+ profileChain: profileChain.profiles,
2269
+ precedenceOrder: loadedManifest.manifest.resolution.precedence,
2270
+ workspace
2271
+ });
2272
+ const schemaApplied = applySchemaRules(graph, loadedManifest.manifest.schema);
2273
+ const promotedGraph = promoteToPublic(schemaApplied.graph, loadedManifest.manifest);
2274
+ const secretCache = options.secretResolution === "lazy" ? void 0 : await batchResolveSecrets(promotedGraph, loadedManifest.manifest, options.processEnv);
2275
+ return createRuntime(
2276
+ loadedManifest.manifest,
2277
+ appendMetaEntries({
2278
+ ...promotedGraph,
2279
+ profileSource: activeProfile.source
2280
+ }, options.cnosVersion),
2281
+ plugins,
2282
+ secretCache
2283
+ );
2284
+ }
2285
+
2286
+ // ../core/src/runtime/dump.ts
2287
+ var import_promises9 = require("fs/promises");
2288
+ var import_node_path9 = __toESM(require("path"), 1);
2289
+ function buildDumpFiles(graph, options = {}) {
2290
+ const basePath = options.flatten ? "" : import_node_path9.default.posix.join("workspaces", graph.workspace.workspaceId);
2291
+ const values = toNamespaceObject(graph, "value");
2292
+ const secrets = toNamespaceObject(graph, "secret");
2293
+ const files = [];
2294
+ if (Object.keys(values).length > 0) {
2295
+ files.push({
2296
+ path: import_node_path9.default.posix.join(basePath, "values", graph.profile, "app.yml"),
2297
+ namespace: "value",
2298
+ content: stringifyYaml(values)
2299
+ });
2300
+ }
2301
+ if (Object.keys(secrets).length > 0) {
2302
+ files.push({
2303
+ path: import_node_path9.default.posix.join(basePath, "secrets", graph.profile, "app.yml"),
2304
+ namespace: "secret",
2305
+ content: stringifyYaml(secrets)
2306
+ });
2307
+ }
2308
+ return files.sort((left, right) => left.path.localeCompare(right.path));
2309
+ }
2310
+ function planDump(graph, options = {}) {
2311
+ return {
2312
+ workspaceId: graph.workspace.workspaceId,
2313
+ profile: graph.profile,
2314
+ flatten: options.flatten ?? false,
2315
+ files: buildDumpFiles(graph, options)
2316
+ };
2317
+ }
2318
+ async function writeDump(graph, options) {
2319
+ const root = import_node_path9.default.resolve(options.to);
2320
+ const plan = planDump(graph, options);
2321
+ for (const file of plan.files) {
2322
+ const destination = import_node_path9.default.join(root, file.path);
2323
+ await (0, import_promises9.mkdir)(import_node_path9.default.dirname(destination), { recursive: true });
2324
+ await (0, import_promises9.writeFile)(destination, file.content, "utf8");
2325
+ }
2326
+ return {
2327
+ ...plan,
2328
+ root
2329
+ };
2330
+ }
2331
+
2332
+ // ../core/src/utils/envNaming.ts
2333
+ function normalizeMappingConfig(config = {}) {
2334
+ return {
2335
+ convention: config.convention,
2336
+ explicit: config.explicit ?? {}
2337
+ };
2338
+ }
2339
+ function fromScreamingSnake(path12) {
2340
+ return path12.split("_").map((segment) => segment.trim().toLowerCase()).filter(Boolean).join(".");
2341
+ }
2342
+ function envVarToLogicalKey(envVar, config = {}) {
2343
+ const normalized = normalizeMappingConfig(config);
2344
+ const explicitMatch = normalized.explicit[envVar];
2345
+ if (explicitMatch) {
2346
+ return explicitMatch;
2347
+ }
2348
+ if (normalized.convention !== "SCREAMING_SNAKE") {
2349
+ return void 0;
2350
+ }
2351
+ if (envVar.startsWith("SECRET_")) {
2352
+ const stripped = envVar.slice("SECRET_".length);
2353
+ if (!stripped) {
2354
+ return void 0;
2355
+ }
2356
+ return `secret.${fromScreamingSnake(stripped)}`;
2357
+ }
2358
+ if (!/^[A-Z][A-Z0-9_]*$/.test(envVar)) {
2359
+ return void 0;
2360
+ }
2361
+ return `value.${fromScreamingSnake(envVar)}`;
2362
+ }
2363
+
2364
+ // package.json
2365
+ var package_default = {
2366
+ name: "@kitsy/cnos",
2367
+ version: "1.4.0",
2368
+ description: "Batteries-included CNOS runtime package wired with the official plugins.",
2369
+ type: "module",
2370
+ main: "./dist/index.cjs",
2371
+ module: "./dist/index.js",
2372
+ types: "./dist/index.d.ts",
2373
+ exports: {
2374
+ ".": {
2375
+ types: "./dist/index.d.ts",
2376
+ import: "./dist/index.js",
2377
+ require: "./dist/index.cjs"
2378
+ },
2379
+ "./configure": {
2380
+ types: "./dist/configure/index.d.ts",
2381
+ import: "./dist/configure/index.js",
2382
+ require: "./dist/configure/index.cjs"
2383
+ },
2384
+ "./create": {
2385
+ types: "./dist/configure/index.d.ts",
2386
+ import: "./dist/configure/index.js",
2387
+ require: "./dist/configure/index.cjs"
2388
+ },
2389
+ "./internal": {
2390
+ types: "./dist/internal.d.ts",
2391
+ import: "./dist/internal.js",
2392
+ require: "./dist/internal.cjs"
2393
+ },
2394
+ "./runtime": {
2395
+ types: "./dist/runtime/index.d.ts",
2396
+ import: "./dist/runtime/index.js",
2397
+ require: "./dist/runtime/index.cjs"
2398
+ },
2399
+ "./browser": {
2400
+ types: "./dist/browser/index.d.ts",
2401
+ import: "./dist/browser/index.js",
2402
+ require: "./dist/browser/index.cjs"
2403
+ },
2404
+ "./build": {
2405
+ types: "./dist/build/index.d.ts",
2406
+ import: "./dist/build/index.js",
2407
+ require: "./dist/build/index.cjs"
2408
+ },
2409
+ "./plugins/filesystem": {
2410
+ types: "./dist/plugin/filesystem.d.ts",
2411
+ import: "./dist/plugin/filesystem.js",
2412
+ require: "./dist/plugin/filesystem.cjs"
2413
+ },
2414
+ "./plugins/dotenv": {
2415
+ types: "./dist/plugin/dotenv.d.ts",
2416
+ import: "./dist/plugin/dotenv.js",
2417
+ require: "./dist/plugin/dotenv.cjs"
2418
+ },
2419
+ "./plugins/process-env": {
2420
+ types: "./dist/plugin/process-env.d.ts",
2421
+ import: "./dist/plugin/process-env.js",
2422
+ require: "./dist/plugin/process-env.cjs"
2423
+ },
2424
+ "./plugins/cli-args": {
2425
+ types: "./dist/plugin/cli-args.d.ts",
2426
+ import: "./dist/plugin/cli-args.js",
2427
+ require: "./dist/plugin/cli-args.cjs"
2428
+ },
2429
+ "./plugins/basic-schema": {
2430
+ types: "./dist/plugin/basic-schema.d.ts",
2431
+ import: "./dist/plugin/basic-schema.js",
2432
+ require: "./dist/plugin/basic-schema.cjs"
2433
+ },
2434
+ "./plugins/env-export": {
2435
+ types: "./dist/plugin/env-export.d.ts",
2436
+ import: "./dist/plugin/env-export.js",
2437
+ require: "./dist/plugin/env-export.cjs"
2438
+ }
2439
+ },
2440
+ files: [
2441
+ "dist"
2442
+ ],
2443
+ license: "MIT",
2444
+ repository: {
2445
+ type: "git",
2446
+ url: "https://github.com/kitsyai/cnos.git",
2447
+ directory: "packages/cnos"
2448
+ },
2449
+ homepage: "https://github.com/kitsyai/cnos/tree/main/packages/cnos",
2450
+ bugs: {
2451
+ url: "https://github.com/kitsyai/cnos/issues"
2452
+ },
2453
+ keywords: [
2454
+ "cnos",
2455
+ "config",
2456
+ "runtime"
2457
+ ],
2458
+ publishConfig: {
2459
+ access: "public"
2460
+ },
2461
+ dependencies: {
2462
+ yaml: "^2.8.3"
2463
+ },
2464
+ scripts: {
2465
+ build: "rimraf dist && tsup --config tsup.config.ts",
2466
+ clean: "rimraf dist",
2467
+ dev: "tsup --config tsup.config.ts --watch",
2468
+ lint: "eslint src test",
2469
+ prepack: "pnpm build",
2470
+ test: "vitest run",
2471
+ typecheck: "tsc -p tsconfig.json --noEmit"
2472
+ }
2473
+ };
2474
+
2475
+ // ../../plugins/basic-schema/src/index.ts
2476
+ function createBasicSchemaPlugin() {
2477
+ return {
2478
+ id: "@kitsy/cnos/plugins/basic-schema",
2479
+ kind: "validator",
2480
+ async validate(graph, context) {
2481
+ const result = applySchemaRules(graph, context.schema ?? {});
2482
+ return {
2483
+ pluginId: "@kitsy/cnos/plugins/basic-schema",
2484
+ valid: result.issues.length === 0,
2485
+ issues: result.issues
2486
+ };
2487
+ }
2488
+ };
2489
+ }
2490
+
2491
+ // ../../plugins/cli-args/src/index.ts
2492
+ var CLI_ARGS_PLUGIN_ID = "@kitsy/cnos/plugins/cli-args";
2493
+ function isNamespaceName(value) {
2494
+ return value === "value" || value === "secret";
2495
+ }
2496
+ function parseCliArgs(args) {
2497
+ const parsed = [];
2498
+ for (let index = 0; index < args.length; index += 1) {
2499
+ const arg = args[index];
2500
+ if (!arg?.startsWith("--")) {
2501
+ continue;
2502
+ }
2503
+ if (arg === "--profile") {
2504
+ index += 1;
2505
+ continue;
2506
+ }
2507
+ if (arg.startsWith("--profile=")) {
2508
+ continue;
2509
+ }
2510
+ const body = arg.slice(2);
2511
+ const separatorIndex = body.indexOf("=");
2512
+ if (separatorIndex >= 0) {
2513
+ parsed.push({
2514
+ key: body.slice(0, separatorIndex),
2515
+ value: body.slice(separatorIndex + 1),
2516
+ raw: arg
2517
+ });
2518
+ continue;
2519
+ }
2520
+ const nextValue = args[index + 1];
2521
+ if (nextValue && !nextValue.startsWith("--")) {
2522
+ parsed.push({
2523
+ key: body,
2524
+ value: nextValue,
2525
+ raw: `${arg} ${nextValue}`
2526
+ });
2527
+ index += 1;
2528
+ }
2529
+ }
2530
+ return parsed;
2531
+ }
2532
+ function cliArgEntriesFromArgs(args, workspaceId = "default") {
2533
+ return parseCliArgs(args).flatMap(({ key, value, raw }) => {
2534
+ const [candidateNamespace = "", ...pathSegments] = key.split(".");
2535
+ if (!isNamespaceName(candidateNamespace) || pathSegments.length === 0) {
2536
+ return [];
2537
+ }
2538
+ const namespace = candidateNamespace;
2539
+ const logicalKey = `${namespace}.${joinConfigPath(pathSegments.join("."))}`;
2540
+ return [
2541
+ {
2542
+ key: logicalKey,
2543
+ value,
2544
+ namespace,
2545
+ sourceId: "cli-args",
2546
+ pluginId: CLI_ARGS_PLUGIN_ID,
2547
+ workspaceId,
2548
+ origin: {
2549
+ cliArg: raw
2550
+ }
2551
+ }
2552
+ ];
2553
+ });
2554
+ }
2555
+ function createCliArgsPlugin() {
2556
+ return {
2557
+ id: "cli-args",
2558
+ kind: "loader",
2559
+ async load(context) {
2560
+ return cliArgEntriesFromArgs(context.cliArgs ?? [], context.workspace.workspaceId);
2561
+ }
2562
+ };
2563
+ }
2564
+
2565
+ // ../../plugins/dotenv/src/index.ts
2566
+ var import_promises10 = require("fs/promises");
2567
+ var import_node_path10 = __toESM(require("path"), 1);
2568
+ var DOTENV_PLUGIN_ID = "@kitsy/cnos/plugins/dotenv";
2569
+ function parseDoubleQuoted(value) {
2570
+ return value.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
2571
+ }
2572
+ function parseDotenv(document) {
2573
+ const parsed = {};
2574
+ for (const rawLine of document.split(/\r?\n/)) {
2575
+ const line = rawLine.trim();
2576
+ if (!line || line.startsWith("#")) {
2577
+ continue;
2578
+ }
2579
+ const withoutExport = line.startsWith("export ") ? line.slice("export ".length).trim() : line;
2580
+ const separatorIndex = withoutExport.indexOf("=");
2581
+ if (separatorIndex <= 0) {
2582
+ continue;
2583
+ }
2584
+ const envVar = withoutExport.slice(0, separatorIndex).trim();
2585
+ let value = withoutExport.slice(separatorIndex + 1).trim();
2586
+ if (!envVar) {
2587
+ continue;
2588
+ }
2589
+ if (value.startsWith('"') && value.endsWith('"')) {
2590
+ value = parseDoubleQuoted(value.slice(1, -1));
2591
+ } else if (value.startsWith("'") && value.endsWith("'")) {
2592
+ value = value.slice(1, -1);
2593
+ } else {
2594
+ value = value.replace(/\s+#.*$/, "").trim();
2595
+ }
2596
+ parsed[envVar] = value;
2597
+ }
2598
+ return parsed;
2599
+ }
2600
+ function dotenvEntriesFromObject(values, mapping = {}, originFile, workspaceId = "default") {
2601
+ return Object.entries(values).flatMap(([envVar, value]) => {
2602
+ const logicalKey = envVarToLogicalKey(envVar, mapping);
2603
+ if (!logicalKey) {
2604
+ return [];
2605
+ }
2606
+ return [
2607
+ {
2608
+ key: logicalKey,
2609
+ value,
2610
+ namespace: logicalKey.startsWith("secret.") ? "secret" : "value",
2611
+ sourceId: "dotenv",
2612
+ pluginId: DOTENV_PLUGIN_ID,
2613
+ workspaceId,
2614
+ origin: {
2615
+ envVar,
2616
+ ...originFile ? { file: originFile } : {}
2617
+ }
2618
+ }
2619
+ ];
2620
+ });
2621
+ }
2622
+ async function readIfPresent(filePath) {
2623
+ try {
2624
+ return await (0, import_promises10.readFile)(filePath, "utf8");
2625
+ } catch {
2626
+ return void 0;
2627
+ }
2628
+ }
2629
+ function createDotenvPlugin() {
2630
+ return {
2631
+ id: "dotenv",
2632
+ kind: "loader",
2633
+ async load(context) {
2634
+ const config = context.manifestConfig;
2635
+ const rootTemplate = config.root ?? "./env";
2636
+ const fileNames = context.profileActivation.envFiles;
2637
+ const entries = [];
2638
+ for (const workspaceRoot of context.workspace.workspaceRoots) {
2639
+ const envRoot = resolveWorkspaceScopedPath(workspaceRoot.path, rootTemplate, {
2640
+ workspace: workspaceRoot.workspaceId
2641
+ });
2642
+ for (const fileName of fileNames) {
2643
+ const absolutePath = import_node_path10.default.join(envRoot, fileName);
2644
+ const document = await readIfPresent(absolutePath);
2645
+ if (!document) {
2646
+ continue;
2647
+ }
2648
+ entries.push(
2649
+ ...dotenvEntriesFromObject(
2650
+ parseDotenv(document),
2651
+ config.envMapping,
2652
+ toPortablePath(import_node_path10.default.relative(import_node_path10.default.dirname(context.manifestRoot), absolutePath)),
2653
+ workspaceRoot.workspaceId
2654
+ )
2655
+ );
2656
+ }
2657
+ }
2658
+ return entries;
2659
+ }
2660
+ };
2661
+ }
2662
+
2663
+ // ../../plugins/env-export/src/index.ts
2664
+ function createEnvExportPlugin() {
2665
+ return {
2666
+ id: "@kitsy/cnos/plugins/env-export",
2667
+ kind: "exporter",
2668
+ async export(graph, context) {
2669
+ return {
2670
+ pluginId: "@kitsy/cnos/plugins/env-export",
2671
+ value: toEnv(graph, context.manifest)
2672
+ };
2673
+ }
2674
+ };
2675
+ }
2676
+ function createPublicEnvExportPlugin() {
2677
+ return {
2678
+ id: "@kitsy/cnos/plugins/public-env-export",
2679
+ kind: "exporter",
2680
+ async export(graph, context) {
2681
+ return {
2682
+ pluginId: "@kitsy/cnos/plugins/public-env-export",
2683
+ value: toPublicEnv(graph, context.manifest)
2684
+ };
2685
+ }
2686
+ };
2687
+ }
2688
+
2689
+ // ../../plugins/filesystem/src/filesystemSecretsReader.ts
2690
+ var import_promises12 = require("fs/promises");
2691
+
2692
+ // ../../plugins/filesystem/src/helpers.ts
2693
+ var import_promises11 = require("fs/promises");
2694
+ var import_node_path11 = __toESM(require("path"), 1);
2695
+ var YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yml", ".yaml"]);
2696
+ var FILESYSTEM_PLUGIN_ID = "@kitsy/cnos/plugins/filesystem";
2697
+ async function existsDirectory(targetPath) {
2698
+ try {
2699
+ const stat2 = await (0, import_promises11.readdir)(targetPath);
2700
+ void stat2;
2701
+ return true;
2702
+ } catch {
2703
+ return false;
2704
+ }
2705
+ }
2706
+ async function collectYamlFiles(root) {
2707
+ const entries = await (0, import_promises11.readdir)(root, { withFileTypes: true });
2708
+ const results = [];
2709
+ for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
2710
+ const absolutePath = import_node_path11.default.join(root, entry.name);
2711
+ if (entry.isDirectory()) {
2712
+ results.push(...await collectYamlFiles(absolutePath));
2713
+ continue;
2714
+ }
2715
+ if (entry.isFile() && YAML_EXTENSIONS.has(import_node_path11.default.extname(entry.name).toLowerCase())) {
2716
+ results.push(absolutePath);
2717
+ }
2718
+ }
2719
+ return results;
2720
+ }
2721
+ async function collectFilesystemLayerFiles(manifestRoot, workspaceRoots, sourceRoot, activeLayers) {
2722
+ const files = [];
2723
+ const repoRoot = import_node_path11.default.dirname(manifestRoot);
2724
+ for (const workspaceRoot of workspaceRoots) {
2725
+ const resolvedRoot = import_node_path11.default.resolve(workspaceRoot.path, sourceRoot);
2726
+ for (const layer of activeLayers) {
2727
+ const layerRoot = import_node_path11.default.join(resolvedRoot, layer);
2728
+ if (!await existsDirectory(layerRoot)) {
2729
+ continue;
2730
+ }
2731
+ for (const absolutePath of await collectYamlFiles(layerRoot)) {
2732
+ const relativePath = import_node_path11.default.relative(repoRoot, absolutePath);
2733
+ files.push({
2734
+ absolutePath,
2735
+ relativePath: toPortablePath(relativePath.startsWith("..") ? absolutePath : relativePath),
2736
+ workspaceId: workspaceRoot.workspaceId
2737
+ });
2738
+ }
2739
+ }
2740
+ }
2741
+ return files;
2742
+ }
2743
+ function assertObjectDocument(value, filePath) {
2744
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2745
+ throw new CnosManifestError("Filesystem loader expected a YAML object document", filePath);
2746
+ }
2747
+ return value;
2748
+ }
2749
+ function flattenConfigObject(value, options = {}, prefix = "") {
2750
+ return Object.entries(value).reduce((accumulator, [key, nestedValue]) => {
2751
+ const nextKey = prefix ? `${prefix}.${key}` : key;
2752
+ if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue) && !options.stopAtLeaf?.(nestedValue)) {
2753
+ Object.assign(
2754
+ accumulator,
2755
+ flattenConfigObject(nestedValue, options, nextKey)
2756
+ );
2757
+ return accumulator;
2758
+ }
2759
+ accumulator[nextKey] = nestedValue;
2760
+ return accumulator;
2761
+ }, {});
2762
+ }
2763
+ function yamlObjectToEntries(document, filePath, namespace, sourceId, workspaceId = "default") {
2764
+ const parsed = assertObjectDocument(parseYaml(document), filePath);
2765
+ const flattened = flattenConfigObject(parsed, {
2766
+ ...namespace === "secret" ? {
2767
+ stopAtLeaf: isSecretReference
2768
+ } : {}
2769
+ });
2770
+ return Object.entries(flattened).map(([key, value]) => ({
2771
+ key: `${namespace}.${key}`,
2772
+ value,
2773
+ namespace,
2774
+ sourceId,
2775
+ pluginId: FILESYSTEM_PLUGIN_ID,
2776
+ workspaceId,
2777
+ origin: {
2778
+ file: filePath
2779
+ }
2780
+ }));
2781
+ }
2782
+ function toSecretReferenceMetadata(value) {
2783
+ if (!isSecretReference(value)) {
2784
+ return void 0;
2785
+ }
2786
+ return {
2787
+ secretRef: value
2788
+ };
2789
+ }
2790
+
2791
+ // ../../plugins/filesystem/src/filesystemSecretsReader.ts
2792
+ function filesystemSecretsReader(filePath, document, workspaceId = "default") {
2793
+ return yamlObjectToEntries(document, filePath, "secret", "filesystem-secrets", workspaceId);
2794
+ }
2795
+ function createFilesystemSecretsPlugin() {
2796
+ return {
2797
+ id: "filesystem-secrets",
2798
+ kind: "loader",
2799
+ async load(context) {
2800
+ const sourceRoot = String(context.manifestConfig.root ?? "./");
2801
+ const files = await collectFilesystemLayerFiles(
2802
+ context.manifestRoot,
2803
+ context.workspace.workspaceRoots,
2804
+ sourceRoot,
2805
+ context.profileActivation.secrets
2806
+ );
2807
+ const entries = [];
2808
+ for (const file of files) {
2809
+ const document = await (0, import_promises12.readFile)(file.absolutePath, "utf8");
2810
+ const fileEntries = filesystemSecretsReader(file.relativePath, document, file.workspaceId);
2811
+ for (const entry of fileEntries) {
2812
+ const metadata = toSecretReferenceMetadata(entry.value);
2813
+ entries.push({
2814
+ ...entry,
2815
+ ...metadata ? { metadata } : {}
2816
+ });
2817
+ }
2818
+ }
2819
+ return entries;
2820
+ }
2821
+ };
2822
+ }
2823
+
2824
+ // ../../plugins/filesystem/src/filesystemValuesReader.ts
2825
+ var import_promises13 = require("fs/promises");
2826
+ function filesystemValuesReader(filePath, document, workspaceId = "default") {
2827
+ return yamlObjectToEntries(document, filePath, "value", "filesystem-values", workspaceId);
2828
+ }
2829
+ function createFilesystemValuesPlugin() {
2830
+ return {
2831
+ id: "filesystem-values",
2832
+ kind: "loader",
2833
+ async load(context) {
2834
+ const sourceRoot = String(context.manifestConfig.root ?? "./");
2835
+ const files = await collectFilesystemLayerFiles(
2836
+ context.manifestRoot,
2837
+ context.workspace.workspaceRoots,
2838
+ sourceRoot,
2839
+ context.profileActivation.values
2840
+ );
2841
+ const customNamespaces = Object.entries(context.manifest.namespaces).filter(
2842
+ ([namespace, definition]) => namespace !== "value" && namespace !== "secret" && definition.kind === "data" && !definition.sensitive
2843
+ ).map(([namespace]) => namespace);
2844
+ const entries = [];
2845
+ for (const file of files) {
2846
+ const document = await (0, import_promises13.readFile)(file.absolutePath, "utf8");
2847
+ entries.push(...filesystemValuesReader(file.relativePath, document, file.workspaceId));
2848
+ }
2849
+ for (const namespace of customNamespaces) {
2850
+ const layers = [
2851
+ namespace,
2852
+ ...context.profileChain.filter((profile) => profile !== "base").map((profile) => `profiles/${profile}/${namespace}`)
2853
+ ];
2854
+ const namespaceFiles = await collectFilesystemLayerFiles(
2855
+ context.manifestRoot,
2856
+ context.workspace.workspaceRoots,
2857
+ sourceRoot,
2858
+ layers
2859
+ );
2860
+ for (const file of namespaceFiles) {
2861
+ const document = await (0, import_promises13.readFile)(file.absolutePath, "utf8");
2862
+ entries.push(...yamlObjectToEntries(document, file.relativePath, namespace, "filesystem-values", file.workspaceId));
2863
+ }
2864
+ }
2865
+ return entries;
2866
+ }
2867
+ };
2868
+ }
2869
+
2870
+ // ../../plugins/process-env/src/index.ts
2871
+ var PROCESS_ENV_PLUGIN_ID = "@kitsy/cnos/plugins/process-env";
2872
+ var PROCESS_GRAPH_OMIT = /* @__PURE__ */ new Set([
2873
+ "__CNOS_GRAPH__",
2874
+ "__CNOS_SECRET_PAYLOAD__",
2875
+ "__CNOS_SESSION_KEY__"
2876
+ ]);
2877
+ function processEnvEntriesFromObject(env, mapping = {}, workspaceId = "default") {
2878
+ return Object.entries(env).flatMap(([envVar, value]) => {
2879
+ if (typeof value !== "string") {
2880
+ return [];
2881
+ }
2882
+ const logicalKey = envVarToLogicalKey(envVar, mapping);
2883
+ if (!logicalKey) {
2884
+ return [];
2885
+ }
2886
+ return [
2887
+ {
2888
+ key: logicalKey,
2889
+ value,
2890
+ namespace: logicalKey.startsWith("secret.") ? "secret" : "value",
2891
+ sourceId: "process-env",
2892
+ pluginId: PROCESS_ENV_PLUGIN_ID,
2893
+ workspaceId,
2894
+ origin: {
2895
+ envVar
2896
+ }
2897
+ }
2898
+ ];
2899
+ });
2900
+ }
2901
+ function processNamespaceEntriesFromContext(env, workspaceId = "default") {
2902
+ const envEntries = Object.entries(env).filter((entry) => typeof entry[1] === "string").filter(([envVar]) => !PROCESS_GRAPH_OMIT.has(envVar)).map(([envVar, value]) => ({
2903
+ key: `process.env.${envVar}`,
2904
+ value,
2905
+ namespace: "process",
2906
+ sourceId: "process-runtime",
2907
+ pluginId: PROCESS_ENV_PLUGIN_ID,
2908
+ workspaceId,
2909
+ origin: {
2910
+ envVar
2911
+ }
2912
+ }));
2913
+ const runtimeEntries = [
2914
+ {
2915
+ key: "process.cwd",
2916
+ value: process.cwd(),
2917
+ namespace: "process",
2918
+ sourceId: "process-runtime",
2919
+ pluginId: PROCESS_ENV_PLUGIN_ID,
2920
+ workspaceId
2921
+ },
2922
+ {
2923
+ key: "process.platform",
2924
+ value: process.platform,
2925
+ namespace: "process",
2926
+ sourceId: "process-runtime",
2927
+ pluginId: PROCESS_ENV_PLUGIN_ID,
2928
+ workspaceId
2929
+ },
2930
+ {
2931
+ key: "process.arch",
2932
+ value: process.arch,
2933
+ namespace: "process",
2934
+ sourceId: "process-runtime",
2935
+ pluginId: PROCESS_ENV_PLUGIN_ID,
2936
+ workspaceId
2937
+ },
2938
+ {
2939
+ key: "process.node.version",
2940
+ value: process.version,
2941
+ namespace: "process",
2942
+ sourceId: "process-runtime",
2943
+ pluginId: PROCESS_ENV_PLUGIN_ID,
2944
+ workspaceId
2945
+ },
2946
+ {
2947
+ key: "process.args.raw",
2948
+ value: process.argv.slice(2),
2949
+ namespace: "process",
2950
+ sourceId: "process-runtime",
2951
+ pluginId: PROCESS_ENV_PLUGIN_ID,
2952
+ workspaceId
2953
+ }
2954
+ ];
2955
+ return [...runtimeEntries, ...envEntries];
2956
+ }
2957
+ function createProcessEnvPlugin() {
2958
+ return {
2959
+ id: "process-env",
2960
+ kind: "loader",
2961
+ async load(context) {
2962
+ const config = context.manifestConfig;
2963
+ const env = context.processEnv ?? process.env;
2964
+ return [
2965
+ ...processEnvEntriesFromObject(
2966
+ env,
2967
+ config.envMapping,
2968
+ context.workspace.workspaceId
2969
+ ),
2970
+ ...processNamespaceEntriesFromContext(env, context.workspace.workspaceId)
2971
+ ];
2972
+ }
2973
+ };
2974
+ }
2975
+
2976
+ // src/defaultPlugins.ts
2977
+ function defaultPlugins() {
2978
+ return [
2979
+ createFilesystemValuesPlugin(),
2980
+ createFilesystemSecretsPlugin(),
2981
+ createDotenvPlugin(),
2982
+ createProcessEnvPlugin(),
2983
+ createCliArgsPlugin(),
2984
+ createBasicSchemaPlugin(),
2985
+ createEnvExportPlugin(),
2986
+ createPublicEnvExportPlugin(),
2987
+ createProvenanceInspector()
2988
+ ];
2989
+ }
2990
+
2991
+ // src/runtime/state.ts
2992
+ var singletonRuntime;
2993
+ var singletonReady;
2994
+ var bootstrappedSecretHydrationRequired = false;
2995
+ function setSingletonRuntime(runtime) {
2996
+ singletonRuntime = runtime;
2997
+ singletonReady = Promise.resolve(runtime);
2998
+ bootstrappedSecretHydrationRequired = false;
2999
+ return runtime;
3000
+ }
3001
+
3002
+ // src/createCnos.ts
3003
+ async function createCnos2(options = {}) {
3004
+ const runtime = await createCnos({
3005
+ ...options,
3006
+ processEnv: options.processEnv ?? process.env,
3007
+ cnosVersion: package_default.version,
3008
+ plugins: [...defaultPlugins(), ...options.plugins ?? []]
3009
+ });
3010
+ setSingletonRuntime(runtime);
3011
+ return runtime;
3012
+ }
3013
+ // Annotate the CommonJS export names for ESM import in node:
3014
+ 0 && (module.exports = {
3015
+ createCnos,
3016
+ defaultPlugins,
3017
+ planDump,
3018
+ toEnv,
3019
+ toPublicEnv,
3020
+ writeDump
3021
+ });