@kitsy/cnos 1.5.1 → 1.6.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 (62) hide show
  1. package/dist/build/index.cjs +325 -113
  2. package/dist/build/index.d.cts +3 -2
  3. package/dist/build/index.d.ts +3 -2
  4. package/dist/build/index.js +13 -8
  5. package/dist/{chunk-UWFE4JE2.js → chunk-BMAD24KC.js} +1 -1
  6. package/dist/{chunk-7EI3RFUE.js → chunk-JYWQFMW5.js} +1 -1
  7. package/dist/{chunk-F2ZAIZNH.js → chunk-MW4OVAT3.js} +1 -1
  8. package/dist/chunk-QU5CXL47.js +577 -0
  9. package/dist/{chunk-BS33AW4Y.js → chunk-S7H2UULC.js} +307 -103
  10. package/dist/{chunk-H53ZRQLX.js → chunk-UJBQS7CJ.js} +1 -1
  11. package/dist/{chunk-CMQK2AEF.js → chunk-UOKVLCFL.js} +10 -10
  12. package/dist/{chunk-EJAXWFNT.js → chunk-UR7CHHNN.js} +1 -1
  13. package/dist/{chunk-SZKQVA2M.js → chunk-VGZREX5D.js} +1 -1
  14. package/dist/{chunk-5F2OFKND.js → chunk-XSUP7JKH.js} +23 -1
  15. package/dist/configure/index.cjs +324 -118
  16. package/dist/configure/index.d.cts +3 -3
  17. package/dist/configure/index.d.ts +3 -3
  18. package/dist/configure/index.js +8 -8
  19. package/dist/{envNaming-Dvm_LP2D.d.ts → envNaming-B7Mztkcf.d.ts} +1 -1
  20. package/dist/{envNaming-S4B-dHUx.d.cts → envNaming-gMVnPOfe.d.cts} +1 -1
  21. package/dist/index.cjs +698 -136
  22. package/dist/index.d.cts +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +10 -10
  25. package/dist/internal.cjs +227 -102
  26. package/dist/internal.d.cts +16 -28
  27. package/dist/internal.d.ts +16 -28
  28. package/dist/internal.js +11 -3
  29. package/dist/plugin/basic-schema.cjs +22 -15
  30. package/dist/plugin/basic-schema.d.cts +1 -1
  31. package/dist/plugin/basic-schema.d.ts +1 -1
  32. package/dist/plugin/basic-schema.js +2 -2
  33. package/dist/plugin/cli-args.cjs +27 -18
  34. package/dist/plugin/cli-args.d.cts +1 -1
  35. package/dist/plugin/cli-args.d.ts +1 -1
  36. package/dist/plugin/cli-args.js +2 -2
  37. package/dist/plugin/dotenv.cjs +35 -26
  38. package/dist/plugin/dotenv.d.cts +2 -2
  39. package/dist/plugin/dotenv.d.ts +2 -2
  40. package/dist/plugin/dotenv.js +2 -2
  41. package/dist/plugin/env-export.cjs +28 -19
  42. package/dist/plugin/env-export.d.cts +2 -2
  43. package/dist/plugin/env-export.d.ts +2 -2
  44. package/dist/plugin/env-export.js +2 -2
  45. package/dist/plugin/filesystem.cjs +42 -33
  46. package/dist/plugin/filesystem.d.cts +1 -1
  47. package/dist/plugin/filesystem.d.ts +1 -1
  48. package/dist/plugin/filesystem.js +2 -2
  49. package/dist/plugin/process-env.cjs +24 -17
  50. package/dist/plugin/process-env.d.cts +2 -2
  51. package/dist/plugin/process-env.d.ts +2 -2
  52. package/dist/plugin/process-env.js +2 -2
  53. package/dist/{plugin-B4xwySxw.d.cts → plugin-CKrBlWGI.d.cts} +52 -3
  54. package/dist/{plugin-B4xwySxw.d.ts → plugin-CKrBlWGI.d.ts} +52 -3
  55. package/dist/runtime/index.cjs +696 -136
  56. package/dist/runtime/index.d.cts +7 -1
  57. package/dist/runtime/index.d.ts +7 -1
  58. package/dist/runtime/index.js +10 -10
  59. package/dist/{toPublicEnv-ggmphZFs.d.cts → toPublicEnv-CmBsy53P.d.cts} +1 -1
  60. package/dist/{toPublicEnv-CvhGAfsB.d.ts → toPublicEnv-q6VwWxXZ.d.ts} +1 -1
  61. package/package.json +1 -1
  62. package/dist/chunk-TUMR7JA3.js +0 -234
@@ -33,6 +33,8 @@ __export(runtime_exports, {
33
33
  default: () => runtime_default
34
34
  });
35
35
  module.exports = __toCommonJS(runtime_exports);
36
+ var import_node_fs = require("fs");
37
+ var import_node_path13 = __toESM(require("path"), 1);
36
38
 
37
39
  // ../core/src/errors.ts
38
40
  var CnosError = class extends Error {
@@ -48,6 +50,11 @@ var CnosManifestError = class extends CnosError {
48
50
  }
49
51
  manifestPath;
50
52
  };
53
+ var CnosDiscoveryError = class extends CnosError {
54
+ constructor(message) {
55
+ super(message);
56
+ }
57
+ };
51
58
  var CnosSecurityError = class extends CnosError {
52
59
  constructor(message) {
53
60
  super(message);
@@ -173,32 +180,110 @@ async function readKeychain(entry) {
173
180
  }
174
181
 
175
182
  // ../core/src/manifest/loadManifest.ts
183
+ var import_promises3 = require("fs/promises");
184
+ var import_node_path3 = __toESM(require("path"), 1);
185
+
186
+ // ../core/src/utils/path.ts
176
187
  var import_promises2 = require("fs/promises");
188
+ var import_node_os = __toESM(require("os"), 1);
177
189
  var import_node_path2 = __toESM(require("path"), 1);
178
190
 
179
- // ../core/src/utils/path.ts
191
+ // ../core/src/discovery/findCnosrc.ts
180
192
  var import_promises = require("fs/promises");
181
- var import_node_os = __toESM(require("os"), 1);
182
193
  var import_node_path = __toESM(require("path"), 1);
194
+
195
+ // ../core/src/utils/yaml.ts
196
+ var import_yaml = require("yaml");
197
+ function parseYaml(source) {
198
+ return (0, import_yaml.parse)(source);
199
+ }
200
+ function stringifyYaml(value) {
201
+ return (0, import_yaml.stringify)(value);
202
+ }
203
+
204
+ // ../core/src/discovery/findCnosrc.ts
205
+ async function exists(targetPath) {
206
+ try {
207
+ await (0, import_promises.access)(targetPath);
208
+ return true;
209
+ } catch {
210
+ return false;
211
+ }
212
+ }
213
+ function validateCnosrc(value, filePath) {
214
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
215
+ throw new CnosManifestError(".cnosrc.yml must be a YAML object", filePath);
216
+ }
217
+ const root = typeof value.root === "string" ? value.root.trim() : "";
218
+ const workspace = typeof value.workspace === "string" ? value.workspace.trim() : void 0;
219
+ if (!root) {
220
+ throw new CnosManifestError(".cnosrc.yml requires root", filePath);
221
+ }
222
+ return {
223
+ root,
224
+ ...workspace ? { workspace } : {}
225
+ };
226
+ }
227
+ async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
228
+ let current = import_node_path.default.resolve(startDir);
229
+ for (let depth = 0; depth <= maxLevels; depth += 1) {
230
+ const candidate = import_node_path.default.join(current, ".cnosrc.yml");
231
+ if (await exists(candidate)) {
232
+ return candidate;
233
+ }
234
+ const parent = import_node_path.default.dirname(current);
235
+ if (parent === current) {
236
+ break;
237
+ }
238
+ current = parent;
239
+ }
240
+ return void 0;
241
+ }
242
+ async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3) {
243
+ const anchorPath = await findCnosrc(startDir, maxLevels);
244
+ if (!anchorPath) {
245
+ throw new CnosDiscoveryError(
246
+ "No .cnosrc.yml found. Run cnos init or create .cnosrc.yml in your package root."
247
+ );
248
+ }
249
+ const source = await (0, import_promises.readFile)(anchorPath, "utf8");
250
+ const parsed = validateCnosrc(parseYaml(source), anchorPath);
251
+ const consumerRoot = import_node_path.default.dirname(anchorPath);
252
+ const manifestRoot = import_node_path.default.resolve(consumerRoot, parsed.root);
253
+ const manifestPath = import_node_path.default.join(manifestRoot, "cnos.yml");
254
+ if (!await exists(manifestPath)) {
255
+ throw new CnosDiscoveryError(
256
+ `.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`
257
+ );
258
+ }
259
+ return {
260
+ anchorPath,
261
+ consumerRoot,
262
+ manifestRoot,
263
+ ...parsed.workspace ? { workspace: parsed.workspace } : {}
264
+ };
265
+ }
266
+
267
+ // ../core/src/utils/path.ts
183
268
  var PRIMARY_CNOS_DIR = ".cnos";
184
269
  var LEGACY_CNOS_DIR = "cnos";
185
- async function exists(filePath) {
270
+ async function exists2(filePath) {
186
271
  try {
187
- await (0, import_promises.access)(filePath);
272
+ await (0, import_promises2.access)(filePath);
188
273
  return true;
189
274
  } catch {
190
275
  return false;
191
276
  }
192
277
  }
193
278
  async function resolveCnosRoot(root = process.cwd()) {
194
- const basePath = import_node_path.default.resolve(root);
279
+ const basePath = import_node_path2.default.resolve(root);
195
280
  const candidates = [
196
- import_node_path.default.join(basePath, PRIMARY_CNOS_DIR),
197
- import_node_path.default.join(basePath, LEGACY_CNOS_DIR),
281
+ import_node_path2.default.join(basePath, PRIMARY_CNOS_DIR),
282
+ import_node_path2.default.join(basePath, LEGACY_CNOS_DIR),
198
283
  basePath
199
284
  ];
200
285
  for (const candidate of candidates) {
201
- if (await exists(import_node_path.default.join(candidate, "cnos.yml"))) {
286
+ if (await exists2(import_node_path2.default.join(candidate, "cnos.yml"))) {
202
287
  return candidate;
203
288
  }
204
289
  }
@@ -206,8 +291,23 @@ async function resolveCnosRoot(root = process.cwd()) {
206
291
  `Could not locate .cnos/cnos.yml or cnos/cnos.yml from root: ${basePath}`
207
292
  );
208
293
  }
209
- async function resolveManifestRoot(root = process.cwd()) {
210
- return resolveCnosRoot(root);
294
+ async function resolveManifestRoot(options = {}) {
295
+ if (options.root) {
296
+ const manifestRoot = await resolveCnosRoot(options.root);
297
+ const resolvedRoot = import_node_path2.default.resolve(options.root);
298
+ const consumerRoot = import_node_path2.default.basename(manifestRoot) === PRIMARY_CNOS_DIR || import_node_path2.default.basename(manifestRoot) === LEGACY_CNOS_DIR ? import_node_path2.default.dirname(manifestRoot) : resolvedRoot;
299
+ return {
300
+ manifestRoot,
301
+ consumerRoot
302
+ };
303
+ }
304
+ const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd());
305
+ return {
306
+ manifestRoot: discovered.manifestRoot,
307
+ consumerRoot: discovered.consumerRoot,
308
+ anchorPath: discovered.anchorPath,
309
+ ...discovered.workspace ? { workspace: discovered.workspace } : {}
310
+ };
211
311
  }
212
312
  function interpolatePathTemplate(template, tokens) {
213
313
  return Object.entries(tokens).reduce(
@@ -220,7 +320,7 @@ function expandHomePath(targetPath) {
220
320
  return import_node_os.default.homedir();
221
321
  }
222
322
  if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
223
- return import_node_path.default.join(import_node_os.default.homedir(), targetPath.slice(2));
323
+ return import_node_path2.default.join(import_node_os.default.homedir(), targetPath.slice(2));
224
324
  }
225
325
  return targetPath;
226
326
  }
@@ -238,7 +338,7 @@ function stripWorkspaceTemplatePrefix(template) {
238
338
  function resolveWorkspaceScopedPath(workspaceRoot, template, tokens) {
239
339
  const relativeTemplate = stripWorkspaceTemplatePrefix(template);
240
340
  const interpolated = interpolatePathTemplate(relativeTemplate, tokens);
241
- return import_node_path.default.resolve(workspaceRoot, interpolated);
341
+ return import_node_path2.default.resolve(workspaceRoot, interpolated);
242
342
  }
243
343
  function toPortablePath(targetPath) {
244
344
  return targetPath.replace(/\\/g, "/");
@@ -253,15 +353,6 @@ function stripNamespace(key) {
253
353
  return key.split(".").slice(1).join(".");
254
354
  }
255
355
 
256
- // ../core/src/utils/yaml.ts
257
- var import_yaml = require("yaml");
258
- function parseYaml(source) {
259
- return (0, import_yaml.parse)(source);
260
- }
261
- function stringifyYaml(value) {
262
- return (0, import_yaml.stringify)(value);
263
- }
264
-
265
356
  // ../core/src/manifest/normalizeManifest.ts
266
357
  var DEFAULT_RESOLVE_FROM = ["cli.profile", "env.CNOS_PROFILE", "default"];
267
358
  var DEFAULT_LOADERS = [
@@ -531,11 +622,15 @@ function normalizeManifest(manifest) {
531
622
 
532
623
  // ../core/src/manifest/loadManifest.ts
533
624
  async function loadManifest(options = {}) {
534
- const manifestRoot = await resolveManifestRoot(options.root);
535
- const manifestPath = import_node_path2.default.join(manifestRoot, "cnos.yml");
625
+ const resolved = await resolveManifestRoot({
626
+ ...options.root ? { root: options.root } : {},
627
+ ...options.cwd ? { cwd: options.cwd } : {}
628
+ });
629
+ const manifestRoot = resolved.manifestRoot;
630
+ const manifestPath = import_node_path3.default.join(manifestRoot, "cnos.yml");
536
631
  let source;
537
632
  try {
538
- source = await (0, import_promises2.readFile)(manifestPath, "utf8");
633
+ source = await (0, import_promises3.readFile)(manifestPath, "utf8");
539
634
  } catch {
540
635
  throw new CnosManifestError("Unable to read CNOS manifest", manifestPath);
541
636
  }
@@ -545,7 +640,10 @@ async function loadManifest(options = {}) {
545
640
  }
546
641
  return {
547
642
  manifestRoot,
548
- repoRoot: import_node_path2.default.dirname(manifestRoot),
643
+ repoRoot: import_node_path3.default.dirname(manifestRoot),
644
+ consumerRoot: resolved.consumerRoot,
645
+ ...resolved.anchorPath ? { anchorPath: resolved.anchorPath } : {},
646
+ ...resolved.workspace ? { anchoredWorkspace: resolved.workspace } : {},
549
647
  manifestPath,
550
648
  manifest: normalizeManifest(rawManifest),
551
649
  rawManifest
@@ -553,12 +651,12 @@ async function loadManifest(options = {}) {
553
651
  }
554
652
 
555
653
  // ../core/src/manifest/loadWorkspaceFile.ts
556
- var import_promises3 = require("fs/promises");
557
- var import_node_path3 = __toESM(require("path"), 1);
654
+ var import_promises4 = require("fs/promises");
655
+ var import_node_path4 = __toESM(require("path"), 1);
558
656
  async function loadWorkspaceFile(repoRoot) {
559
- const workspaceFilePath = import_node_path3.default.join(repoRoot, ".cnos-workspace.yml");
657
+ const workspaceFilePath = import_node_path4.default.join(repoRoot, ".cnos-workspace.yml");
560
658
  try {
561
- const source = await (0, import_promises3.readFile)(workspaceFilePath, "utf8");
659
+ const source = await (0, import_promises4.readFile)(workspaceFilePath, "utf8");
562
660
  const parsed = parseYaml(source);
563
661
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
564
662
  throw new CnosManifestError(".cnos-workspace.yml must be a YAML object", workspaceFilePath);
@@ -581,11 +679,11 @@ async function loadWorkspaceFile(repoRoot) {
581
679
  }
582
680
 
583
681
  // ../core/src/profiles/expandProfileChain.ts
584
- var import_promises4 = require("fs/promises");
585
- var import_node_path4 = __toESM(require("path"), 1);
682
+ var import_promises5 = require("fs/promises");
683
+ var import_node_path5 = __toESM(require("path"), 1);
586
684
  async function fileExists(targetPath) {
587
685
  try {
588
- await (0, import_promises4.access)(targetPath);
686
+ await (0, import_promises5.access)(targetPath);
589
687
  return true;
590
688
  } catch {
591
689
  return false;
@@ -619,11 +717,11 @@ async function loadProfileDefinition(profileName, options) {
619
717
  return normalizeProfileDefinition(profileName, void 0);
620
718
  }
621
719
  for (const workspaceRoot of [...workspaceRoots].reverse()) {
622
- const profilePath = import_node_path4.default.join(workspaceRoot.path, "profiles", `${profileName}.yml`);
720
+ const profilePath = import_node_path5.default.join(workspaceRoot.path, "profiles", `${profileName}.yml`);
623
721
  if (!await fileExists(profilePath)) {
624
722
  continue;
625
723
  }
626
- const document = await (0, import_promises4.readFile)(profilePath, "utf8");
724
+ const document = await (0, import_promises5.readFile)(profilePath, "utf8");
627
725
  const parsed = parseYaml(document);
628
726
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
629
727
  throw new CnosManifestError("Profile definition must be a YAML object", profilePath);
@@ -631,7 +729,7 @@ async function loadProfileDefinition(profileName, options) {
631
729
  const definition = normalizeProfileDefinition(
632
730
  profileName,
633
731
  parsed,
634
- options.manifestRoot ? toPortablePath(import_node_path4.default.relative(import_node_path4.default.dirname(options.manifestRoot), profilePath)) : toPortablePath(profilePath)
732
+ options.manifestRoot ? toPortablePath(import_node_path5.default.relative(import_node_path5.default.dirname(options.manifestRoot), profilePath)) : toPortablePath(profilePath)
635
733
  );
636
734
  if (definition.name !== profileName) {
637
735
  throw new CnosManifestError(
@@ -913,8 +1011,8 @@ function createProfileAwareResolver() {
913
1011
  }
914
1012
 
915
1013
  // ../core/src/workspaces/resolveWorkspaceContext.ts
916
- var import_promises5 = require("fs/promises");
917
- var import_node_path5 = __toESM(require("path"), 1);
1014
+ var import_promises6 = require("fs/promises");
1015
+ var import_node_path6 = __toESM(require("path"), 1);
918
1016
 
919
1017
  // ../core/src/workspaces/expandWorkspaceChain.ts
920
1018
  function expandWorkspaceChain(workspaceId, items) {
@@ -951,31 +1049,31 @@ function expandWorkspaceChain(workspaceId, items) {
951
1049
  }
952
1050
 
953
1051
  // ../core/src/workspaces/resolveWorkspaceContext.ts
954
- async function exists2(targetPath) {
1052
+ async function exists3(targetPath) {
955
1053
  try {
956
- await (0, import_promises5.access)(targetPath);
1054
+ await (0, import_promises6.access)(targetPath);
957
1055
  return true;
958
1056
  } catch {
959
1057
  return false;
960
1058
  }
961
1059
  }
962
1060
  async function resolveLocalWorkspaceRoot(manifestRoot, workspaceId, manifest) {
963
- const workspaceRoot = import_node_path5.default.join(manifestRoot, "workspaces", workspaceId);
964
- if (await exists2(workspaceRoot)) {
1061
+ const workspaceRoot = import_node_path6.default.join(manifestRoot, "workspaces", workspaceId);
1062
+ if (await exists3(workspaceRoot)) {
965
1063
  return workspaceRoot;
966
1064
  }
967
1065
  const customDataNamespaceRoots = Object.entries(manifest.namespaces).filter(
968
1066
  ([namespace, definition]) => namespace !== "value" && namespace !== "secret" && definition.kind === "data" && !definition.sensitive
969
1067
  ).map(([namespace]) => namespace);
970
1068
  const legacyMarkers = ["values", "secrets", "env", "profiles", ...customDataNamespaceRoots].map(
971
- (segment) => import_node_path5.default.join(manifestRoot, segment)
1069
+ (segment) => import_node_path6.default.join(manifestRoot, segment)
972
1070
  );
973
- if ((await Promise.all(legacyMarkers.map((marker) => exists2(marker)))).some(Boolean)) {
1071
+ if ((await Promise.all(legacyMarkers.map((marker) => exists3(marker)))).some(Boolean)) {
974
1072
  return manifestRoot;
975
1073
  }
976
1074
  return workspaceRoot;
977
1075
  }
978
- function resolveWorkspaceSelection(manifest, workspaceFile, workspaceOption) {
1076
+ function resolveWorkspaceSelection(manifest, workspaceFile, anchoredWorkspace, workspaceOption) {
979
1077
  if (workspaceOption) {
980
1078
  return {
981
1079
  workspaceId: workspaceOption,
@@ -988,6 +1086,12 @@ function resolveWorkspaceSelection(manifest, workspaceFile, workspaceOption) {
988
1086
  source: "workspace-file"
989
1087
  };
990
1088
  }
1089
+ if (anchoredWorkspace) {
1090
+ return {
1091
+ workspaceId: anchoredWorkspace,
1092
+ source: "anchor-file"
1093
+ };
1094
+ }
991
1095
  if (manifest.workspaces.default) {
992
1096
  return {
993
1097
  workspaceId: manifest.workspaces.default,
@@ -1010,33 +1114,38 @@ function resolveGlobalRoot(manifest, workspaceFile, options) {
1010
1114
  }
1011
1115
  if (options.globalRoot) {
1012
1116
  return {
1013
- value: import_node_path5.default.resolve(expandHomePath(options.globalRoot)),
1117
+ value: import_node_path6.default.resolve(expandHomePath(options.globalRoot)),
1014
1118
  source: "cli"
1015
1119
  };
1016
1120
  }
1017
1121
  if (workspaceFile?.globalRoot) {
1018
1122
  return {
1019
- value: import_node_path5.default.resolve(expandHomePath(workspaceFile.globalRoot)),
1123
+ value: import_node_path6.default.resolve(expandHomePath(workspaceFile.globalRoot)),
1020
1124
  source: "workspace-file"
1021
1125
  };
1022
1126
  }
1023
1127
  if (manifest.workspaces.global.root) {
1024
1128
  return {
1025
- value: import_node_path5.default.resolve(expandHomePath(manifest.workspaces.global.root)),
1129
+ value: import_node_path6.default.resolve(expandHomePath(manifest.workspaces.global.root)),
1026
1130
  source: "manifest"
1027
1131
  };
1028
1132
  }
1029
1133
  const cnosHome = options.processEnv?.CNOS_HOME;
1030
1134
  if (cnosHome) {
1031
1135
  return {
1032
- value: import_node_path5.default.resolve(expandHomePath(cnosHome)),
1136
+ value: import_node_path6.default.resolve(expandHomePath(cnosHome)),
1033
1137
  source: "CNOS_HOME"
1034
1138
  };
1035
1139
  }
1036
1140
  return {};
1037
1141
  }
1038
1142
  async function resolveWorkspaceContext(manifest, options) {
1039
- const selectedWorkspace = resolveWorkspaceSelection(manifest, options.workspaceFile, options.workspace);
1143
+ const selectedWorkspace = resolveWorkspaceSelection(
1144
+ manifest,
1145
+ options.workspaceFile,
1146
+ options.anchoredWorkspace,
1147
+ options.workspace
1148
+ );
1040
1149
  const workspaceChain = expandWorkspaceChain(selectedWorkspace.workspaceId, manifest.workspaces.items);
1041
1150
  const globalRoot = resolveGlobalRoot(manifest, options.workspaceFile, options);
1042
1151
  const workspaceRoots = [];
@@ -1046,7 +1155,7 @@ async function resolveWorkspaceContext(manifest, options) {
1046
1155
  workspaceRoots.push({
1047
1156
  scope: "global",
1048
1157
  workspaceId: chainWorkspaceId,
1049
- path: import_node_path5.default.join(globalRoot.value, "workspaces", globalWorkspaceId)
1158
+ path: import_node_path6.default.join(globalRoot.value, "workspaces", globalWorkspaceId)
1050
1159
  });
1051
1160
  }
1052
1161
  }
@@ -1238,26 +1347,26 @@ async function runPipeline(options) {
1238
1347
  }
1239
1348
 
1240
1349
  // ../core/src/secrets/auditLog.ts
1241
- var import_promises8 = require("fs/promises");
1242
- var import_node_path8 = __toESM(require("path"), 1);
1350
+ var import_promises9 = require("fs/promises");
1351
+ var import_node_path9 = __toESM(require("path"), 1);
1243
1352
 
1244
1353
  // ../core/src/utils/secretStore.ts
1245
1354
  var import_node_crypto = require("crypto");
1246
- var import_promises7 = require("fs/promises");
1247
- var import_node_path7 = __toESM(require("path"), 1);
1355
+ var import_promises8 = require("fs/promises");
1356
+ var import_node_path8 = __toESM(require("path"), 1);
1248
1357
 
1249
1358
  // ../core/src/secrets/sessionStore.ts
1250
- var import_promises6 = require("fs/promises");
1251
- var import_node_path6 = __toESM(require("path"), 1);
1359
+ var import_promises7 = require("fs/promises");
1360
+ var import_node_path7 = __toESM(require("path"), 1);
1252
1361
  function buildSessionRoot(processEnv = process.env) {
1253
- return import_node_path6.default.join(import_node_path6.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
1362
+ return import_node_path7.default.join(import_node_path7.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
1254
1363
  }
1255
1364
  function buildSessionPath(vault, processEnv) {
1256
- return import_node_path6.default.join(buildSessionRoot(processEnv), `${vault}.json`);
1365
+ return import_node_path7.default.join(buildSessionRoot(processEnv), `${vault}.json`);
1257
1366
  }
1258
1367
  async function readVaultSessionKey(vault, processEnv) {
1259
1368
  try {
1260
- const source = await (0, import_promises6.readFile)(buildSessionPath(vault, processEnv), "utf8");
1369
+ const source = await (0, import_promises7.readFile)(buildSessionPath(vault, processEnv), "utf8");
1261
1370
  const document = JSON.parse(source);
1262
1371
  if (document.version !== 1 || typeof document.derivedKey !== "string") {
1263
1372
  return void 0;
@@ -1286,7 +1395,7 @@ function isSecretReference(value) {
1286
1395
  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));
1287
1396
  }
1288
1397
  function resolveSecretStoreRoot(processEnv = process.env) {
1289
- return import_node_path7.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
1398
+ return import_node_path8.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
1290
1399
  }
1291
1400
  function normalizeVaultToken(vault = "default") {
1292
1401
  return vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
@@ -1318,16 +1427,16 @@ function deriveVaultKey(passphrase, salt, iterations = PBKDF2_ITERATIONS) {
1318
1427
  return (0, import_node_crypto.pbkdf2Sync)(passphrase, salt, iterations, KEY_LENGTH, "sha512");
1319
1428
  }
1320
1429
  function buildMetaPath(storeRoot, vault = "default") {
1321
- return import_node_path7.default.join(storeRoot, "vaults", vault, META_FILENAME);
1430
+ return import_node_path8.default.join(storeRoot, "vaults", vault, META_FILENAME);
1322
1431
  }
1323
1432
  function buildKeystorePath(storeRoot, vault = "default") {
1324
- return import_node_path7.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
1433
+ return import_node_path8.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
1325
1434
  }
1326
1435
  function buildLegacyVaultFile(storeRoot, vault = "default") {
1327
- return import_node_path7.default.join(storeRoot, "vaults", `${vault}.json`);
1436
+ return import_node_path8.default.join(storeRoot, "vaults", `${vault}.json`);
1328
1437
  }
1329
1438
  function buildLegacyVaultStoreRoot(storeRoot, vault = "default") {
1330
- return import_node_path7.default.join(storeRoot, "vaults", vault, "store");
1439
+ return import_node_path8.default.join(storeRoot, "vaults", vault, "store");
1331
1440
  }
1332
1441
  function assertVaultMetadata(value, filePath) {
1333
1442
  if (!isObject(value)) {
@@ -1338,9 +1447,9 @@ function assertVaultMetadata(value, filePath) {
1338
1447
  }
1339
1448
  return value;
1340
1449
  }
1341
- async function exists3(targetPath) {
1450
+ async function exists4(targetPath) {
1342
1451
  try {
1343
- await (0, import_promises7.stat)(targetPath);
1452
+ await (0, import_promises8.stat)(targetPath);
1344
1453
  return true;
1345
1454
  } catch {
1346
1455
  return false;
@@ -1349,10 +1458,10 @@ async function exists3(targetPath) {
1349
1458
  async function detectLegacyVaultFormat(storeRoot, vault = "default") {
1350
1459
  const legacyFile = buildLegacyVaultFile(storeRoot, vault);
1351
1460
  const legacyStore = buildLegacyVaultStoreRoot(storeRoot, vault);
1352
- if (await exists3(legacyFile)) {
1461
+ if (await exists4(legacyFile)) {
1353
1462
  return legacyFile;
1354
1463
  }
1355
- if (await exists3(legacyStore)) {
1464
+ if (await exists4(legacyStore)) {
1356
1465
  return legacyStore;
1357
1466
  }
1358
1467
  return void 0;
@@ -1424,15 +1533,15 @@ function buildInitialPayload() {
1424
1533
  async function writeVaultFiles(storeRoot, vault, meta, payload, key) {
1425
1534
  const metaPath = buildMetaPath(storeRoot, vault);
1426
1535
  const keystorePath = buildKeystorePath(storeRoot, vault);
1427
- await (0, import_promises7.mkdir)(import_node_path7.default.dirname(metaPath), { recursive: true });
1428
- await (0, import_promises7.writeFile)(metaPath, stringifyYaml(meta), "utf8");
1429
- await (0, import_promises7.writeFile)(keystorePath, encryptPayload(payload, key));
1536
+ await (0, import_promises8.mkdir)(import_node_path8.default.dirname(metaPath), { recursive: true });
1537
+ await (0, import_promises8.writeFile)(metaPath, stringifyYaml(meta), "utf8");
1538
+ await (0, import_promises8.writeFile)(keystorePath, encryptPayload(payload, key));
1430
1539
  }
1431
1540
  async function readVaultMetadata(storeRoot, vault = "default") {
1432
1541
  await assertNoLegacyVaultFormat(storeRoot, vault);
1433
1542
  const metaPath = buildMetaPath(storeRoot, vault);
1434
1543
  try {
1435
- const source = await (0, import_promises7.readFile)(metaPath, "utf8");
1544
+ const source = await (0, import_promises8.readFile)(metaPath, "utf8");
1436
1545
  return assertVaultMetadata(parseYaml(source), metaPath);
1437
1546
  } catch (error) {
1438
1547
  if (error.code === "ENOENT") {
@@ -1523,7 +1632,7 @@ async function loadVaultPayload(storeRoot, vault, auth) {
1523
1632
  if (!key) {
1524
1633
  throw new CnosAuthenticationError(`Vault "${vault}" requires authentication before access.`);
1525
1634
  }
1526
- const buffer = await (0, import_promises7.readFile)(buildKeystorePath(storeRoot, vault));
1635
+ const buffer = await (0, import_promises8.readFile)(buildKeystorePath(storeRoot, vault));
1527
1636
  return {
1528
1637
  meta,
1529
1638
  payload: decryptPayload(buffer, key),
@@ -1598,9 +1707,9 @@ function resolveVaultDefinition(vaults, vault = "default") {
1598
1707
 
1599
1708
  // ../core/src/secrets/auditLog.ts
1600
1709
  async function appendAuditEvent(event, processEnv = process.env) {
1601
- const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path8.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
1602
- await (0, import_promises8.mkdir)(import_node_path8.default.dirname(auditFile), { recursive: true });
1603
- await (0, import_promises8.appendFile)(
1710
+ const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path9.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
1711
+ await (0, import_promises9.mkdir)(import_node_path9.default.dirname(auditFile), { recursive: true });
1712
+ await (0, import_promises9.appendFile)(
1604
1713
  auditFile,
1605
1714
  `${JSON.stringify({
1606
1715
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1993,6 +2102,60 @@ function requireValue(graph, key) {
1993
2102
  return value;
1994
2103
  }
1995
2104
 
2105
+ // ../core/src/runtime/toServerProjection.ts
2106
+ var import_node_crypto2 = require("crypto");
2107
+ function stableSortObject(value) {
2108
+ return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)));
2109
+ }
2110
+ function stripValuePrefix(key) {
2111
+ return key.startsWith("value.") ? key.slice("value.".length) : key;
2112
+ }
2113
+ function configHash(values) {
2114
+ const serialized = JSON.stringify(stableSortObject(values));
2115
+ return (0, import_node_crypto2.createHash)("sha256").update(serialized).digest("hex");
2116
+ }
2117
+ function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev") {
2118
+ const values = {};
2119
+ const secretRefs = {};
2120
+ const namespaces = /* @__PURE__ */ new Set();
2121
+ const publicKeys = Array.from(graph.entries.values()).filter((entry) => entry.namespace === "public").map((entry) => entry.key.slice("public.".length)).sort((left, right) => left.localeCompare(right));
2122
+ for (const [key, entry] of graph.entries) {
2123
+ if (entry.namespace === "secret" && isSecretReference(entry.value)) {
2124
+ secretRefs[key.slice("secret.".length)] = {
2125
+ provider: entry.value.provider,
2126
+ vault: entry.value.vault ?? "default",
2127
+ ref: entry.value.ref
2128
+ };
2129
+ continue;
2130
+ }
2131
+ if (entry.namespace === "value") {
2132
+ values[stripValuePrefix(key)] = entry.value;
2133
+ continue;
2134
+ }
2135
+ const namespaceDefinition = manifest.namespaces[entry.namespace];
2136
+ if (namespaceDefinition && namespaceDefinition.kind === "data" && !namespaceDefinition.sensitive && entry.namespace !== "public") {
2137
+ values[key] = entry.value;
2138
+ namespaces.add(entry.namespace);
2139
+ }
2140
+ }
2141
+ return {
2142
+ version: 1,
2143
+ workspace: graph.workspace.workspaceId,
2144
+ profile: graph.profile,
2145
+ resolvedAt: graph.resolvedAt,
2146
+ configHash: configHash(values),
2147
+ values: stableSortObject(values),
2148
+ secretRefs: stableSortObject(secretRefs),
2149
+ publicKeys,
2150
+ meta: {
2151
+ workspace: graph.workspace.workspaceId,
2152
+ profile: graph.profile,
2153
+ cnos_version: cnosVersion,
2154
+ ...namespaces.size > 0 ? { namespaces: Array.from(namespaces).sort((left, right) => left.localeCompare(right)) } : {}
2155
+ }
2156
+ };
2157
+ }
2158
+
1996
2159
  // ../core/src/runtime/toEnv.ts
1997
2160
  function normalizeEnvValue(value) {
1998
2161
  if (value === void 0 || value === null) {
@@ -2077,8 +2240,38 @@ function toPublicEnv(graph, manifest, options = {}) {
2077
2240
  }
2078
2241
 
2079
2242
  // ../core/src/orchestrator/runtime.ts
2080
- function createRuntime(manifest, graph, plugins = [], secretCache) {
2081
- function readLogicalKey(key) {
2243
+ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv = process.env, cnosVersion = "0.0.0-dev") {
2244
+ async function refreshSecretEntry(key) {
2245
+ const entry = graph.entries.get(key);
2246
+ if (!entry || entry.namespace !== "secret" || !isSecretReference(entry.value)) {
2247
+ return;
2248
+ }
2249
+ if (!secretCache) {
2250
+ return;
2251
+ }
2252
+ const vaultId = entry.value.vault ?? "default";
2253
+ const definition = manifest.vaults[vaultId] ?? {
2254
+ provider: entry.value.provider,
2255
+ auth: { passphrase: { from: [] } }
2256
+ };
2257
+ const provider = createSecretVaultProvider(vaultId, definition, processEnv);
2258
+ const auth = await resolveVaultAuth(vaultId, definition, processEnv);
2259
+ await provider.authenticate(auth);
2260
+ const value = await provider.get(entry.value.ref);
2261
+ if (value !== void 0) {
2262
+ secretCache.load(vaultId, /* @__PURE__ */ new Map([[entry.value.ref, value]]));
2263
+ }
2264
+ }
2265
+ async function refreshAllSecrets() {
2266
+ if (!secretCache) {
2267
+ return;
2268
+ }
2269
+ const secretKeys = Array.from(graph.entries.values()).filter((entry) => entry.namespace === "secret" && isSecretReference(entry.value)).map((entry) => entry.key);
2270
+ for (const key of secretKeys) {
2271
+ await refreshSecretEntry(key);
2272
+ }
2273
+ }
2274
+ function readLogicalKey2(key) {
2082
2275
  const entry = graph.entries.get(key);
2083
2276
  if (!entry) {
2084
2277
  return void 0;
@@ -2093,10 +2286,10 @@ function createRuntime(manifest, graph, plugins = [], secretCache) {
2093
2286
  plugins,
2094
2287
  graph,
2095
2288
  read(key) {
2096
- return readLogicalKey(key);
2289
+ return readLogicalKey2(key);
2097
2290
  },
2098
2291
  require(key) {
2099
- const value = readLogicalKey(key);
2292
+ const value = readLogicalKey2(key);
2100
2293
  if (value === void 0) {
2101
2294
  return requireValue(graph, key);
2102
2295
  }
@@ -2105,14 +2298,14 @@ function createRuntime(manifest, graph, plugins = [], secretCache) {
2105
2298
  readOr(key, fallback) {
2106
2299
  return readOrValue(graph, key, fallback);
2107
2300
  },
2108
- value(path12) {
2109
- return readLogicalKey(toLogicalKey("value", path12));
2301
+ value(path14) {
2302
+ return readLogicalKey2(toLogicalKey("value", path14));
2110
2303
  },
2111
- secret(path12) {
2112
- return readLogicalKey(toLogicalKey("secret", path12));
2304
+ secret(path14) {
2305
+ return readLogicalKey2(toLogicalKey("secret", path14));
2113
2306
  },
2114
- meta(path12) {
2115
- return readLogicalKey(toLogicalKey("meta", path12));
2307
+ meta(path14) {
2308
+ return readLogicalKey2(toLogicalKey("meta", path14));
2116
2309
  },
2117
2310
  inspect(key) {
2118
2311
  return inspectValue(graph, key);
@@ -2128,6 +2321,15 @@ function createRuntime(manifest, graph, plugins = [], secretCache) {
2128
2321
  },
2129
2322
  toPublicEnv(options) {
2130
2323
  return toPublicEnv(graph, manifest, options);
2324
+ },
2325
+ toServerProjection() {
2326
+ return toServerProjection(graph, manifest, cnosVersion);
2327
+ },
2328
+ async refreshSecrets() {
2329
+ await refreshAllSecrets();
2330
+ },
2331
+ async refreshSecret(key) {
2332
+ await refreshSecretEntry(key);
2131
2333
  }
2132
2334
  };
2133
2335
  }
@@ -2226,14 +2428,18 @@ function appendMetaEntries(graph, cnosVersion) {
2226
2428
  };
2227
2429
  }
2228
2430
  async function createCnos(options = {}) {
2229
- const loadedManifest = await loadManifest(options.root ? { root: options.root } : {});
2431
+ const loadedManifest = await loadManifest({
2432
+ ...options.root ? { root: options.root } : {},
2433
+ ...options.cwd ? { cwd: options.cwd } : {}
2434
+ });
2230
2435
  for (const key of loadedManifest.manifest.public.promote) {
2231
2436
  ensureProjectionAllowed(loadedManifest.manifest, key, "public");
2232
2437
  }
2233
- const workspaceFile = await loadWorkspaceFile(loadedManifest.repoRoot);
2438
+ const workspaceFile = await loadWorkspaceFile(loadedManifest.consumerRoot);
2234
2439
  const workspace = await resolveWorkspaceContext(loadedManifest.manifest, {
2235
2440
  manifestRoot: loadedManifest.manifestRoot,
2236
2441
  ...workspaceFile ? { workspaceFile: workspaceFile.config } : {},
2442
+ ...loadedManifest.anchoredWorkspace ? { anchoredWorkspace: loadedManifest.anchoredWorkspace } : {},
2237
2443
  ...options.workspace ? { workspace: options.workspace } : {},
2238
2444
  ...options.globalRoot ? { globalRoot: options.globalRoot } : {},
2239
2445
  ...options.processEnv ? { processEnv: options.processEnv } : {}
@@ -2278,13 +2484,15 @@ async function createCnos(options = {}) {
2278
2484
  profileSource: activeProfile.source
2279
2485
  }, options.cnosVersion),
2280
2486
  plugins,
2281
- secretCache
2487
+ secretCache,
2488
+ options.processEnv,
2489
+ options.cnosVersion
2282
2490
  );
2283
2491
  }
2284
2492
 
2285
2493
  // ../core/src/runtime/dump.ts
2286
- var import_promises9 = require("fs/promises");
2287
- var import_node_path9 = __toESM(require("path"), 1);
2494
+ var import_promises10 = require("fs/promises");
2495
+ var import_node_path10 = __toESM(require("path"), 1);
2288
2496
 
2289
2497
  // ../core/src/utils/envNaming.ts
2290
2498
  function normalizeMappingConfig(config = {}) {
@@ -2293,8 +2501,8 @@ function normalizeMappingConfig(config = {}) {
2293
2501
  explicit: config.explicit ?? {}
2294
2502
  };
2295
2503
  }
2296
- function fromScreamingSnake(path12) {
2297
- return path12.split("_").map((segment) => segment.trim().toLowerCase()).filter(Boolean).join(".");
2504
+ function fromScreamingSnake(path14) {
2505
+ return path14.split("_").map((segment) => segment.trim().toLowerCase()).filter(Boolean).join(".");
2298
2506
  }
2299
2507
  function envVarToLogicalKey(envVar, config = {}) {
2300
2508
  const normalized = normalizeMappingConfig(config);
@@ -2321,7 +2529,7 @@ function envVarToLogicalKey(envVar, config = {}) {
2321
2529
  // package.json
2322
2530
  var package_default = {
2323
2531
  name: "@kitsy/cnos",
2324
- version: "1.5.1",
2532
+ version: "1.6.0",
2325
2533
  description: "Batteries-included CNOS runtime package wired with the official plugins.",
2326
2534
  type: "module",
2327
2535
  main: "./dist/index.cjs",
@@ -2520,8 +2728,8 @@ function createCliArgsPlugin() {
2520
2728
  }
2521
2729
 
2522
2730
  // ../../plugins/dotenv/src/index.ts
2523
- var import_promises10 = require("fs/promises");
2524
- var import_node_path10 = __toESM(require("path"), 1);
2731
+ var import_promises11 = require("fs/promises");
2732
+ var import_node_path11 = __toESM(require("path"), 1);
2525
2733
  var DOTENV_PLUGIN_ID = "@kitsy/cnos/plugins/dotenv";
2526
2734
  function parseDoubleQuoted(value) {
2527
2735
  return value.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
@@ -2578,7 +2786,7 @@ function dotenvEntriesFromObject(values, mapping = {}, originFile, workspaceId =
2578
2786
  }
2579
2787
  async function readIfPresent(filePath) {
2580
2788
  try {
2581
- return await (0, import_promises10.readFile)(filePath, "utf8");
2789
+ return await (0, import_promises11.readFile)(filePath, "utf8");
2582
2790
  } catch {
2583
2791
  return void 0;
2584
2792
  }
@@ -2597,7 +2805,7 @@ function createDotenvPlugin() {
2597
2805
  workspace: workspaceRoot.workspaceId
2598
2806
  });
2599
2807
  for (const fileName of fileNames) {
2600
- const absolutePath = import_node_path10.default.join(envRoot, fileName);
2808
+ const absolutePath = import_node_path11.default.join(envRoot, fileName);
2601
2809
  const document = await readIfPresent(absolutePath);
2602
2810
  if (!document) {
2603
2811
  continue;
@@ -2606,7 +2814,7 @@ function createDotenvPlugin() {
2606
2814
  ...dotenvEntriesFromObject(
2607
2815
  parseDotenv(document),
2608
2816
  config.envMapping,
2609
- toPortablePath(import_node_path10.default.relative(import_node_path10.default.dirname(context.manifestRoot), absolutePath)),
2817
+ toPortablePath(import_node_path11.default.relative(import_node_path11.default.dirname(context.manifestRoot), absolutePath)),
2610
2818
  workspaceRoot.workspaceId
2611
2819
  )
2612
2820
  );
@@ -2644,16 +2852,16 @@ function createPublicEnvExportPlugin() {
2644
2852
  }
2645
2853
 
2646
2854
  // ../../plugins/filesystem/src/filesystemSecretsReader.ts
2647
- var import_promises12 = require("fs/promises");
2855
+ var import_promises13 = require("fs/promises");
2648
2856
 
2649
2857
  // ../../plugins/filesystem/src/helpers.ts
2650
- var import_promises11 = require("fs/promises");
2651
- var import_node_path11 = __toESM(require("path"), 1);
2858
+ var import_promises12 = require("fs/promises");
2859
+ var import_node_path12 = __toESM(require("path"), 1);
2652
2860
  var YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yml", ".yaml"]);
2653
2861
  var FILESYSTEM_PLUGIN_ID = "@kitsy/cnos/plugins/filesystem";
2654
2862
  async function existsDirectory(targetPath) {
2655
2863
  try {
2656
- const stat2 = await (0, import_promises11.readdir)(targetPath);
2864
+ const stat2 = await (0, import_promises12.readdir)(targetPath);
2657
2865
  void stat2;
2658
2866
  return true;
2659
2867
  } catch {
@@ -2661,15 +2869,15 @@ async function existsDirectory(targetPath) {
2661
2869
  }
2662
2870
  }
2663
2871
  async function collectYamlFiles(root) {
2664
- const entries = await (0, import_promises11.readdir)(root, { withFileTypes: true });
2872
+ const entries = await (0, import_promises12.readdir)(root, { withFileTypes: true });
2665
2873
  const results = [];
2666
2874
  for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
2667
- const absolutePath = import_node_path11.default.join(root, entry.name);
2875
+ const absolutePath = import_node_path12.default.join(root, entry.name);
2668
2876
  if (entry.isDirectory()) {
2669
2877
  results.push(...await collectYamlFiles(absolutePath));
2670
2878
  continue;
2671
2879
  }
2672
- if (entry.isFile() && YAML_EXTENSIONS.has(import_node_path11.default.extname(entry.name).toLowerCase())) {
2880
+ if (entry.isFile() && YAML_EXTENSIONS.has(import_node_path12.default.extname(entry.name).toLowerCase())) {
2673
2881
  results.push(absolutePath);
2674
2882
  }
2675
2883
  }
@@ -2677,16 +2885,16 @@ async function collectYamlFiles(root) {
2677
2885
  }
2678
2886
  async function collectFilesystemLayerFiles(manifestRoot, workspaceRoots, sourceRoot, activeLayers) {
2679
2887
  const files = [];
2680
- const repoRoot = import_node_path11.default.dirname(manifestRoot);
2888
+ const repoRoot = import_node_path12.default.dirname(manifestRoot);
2681
2889
  for (const workspaceRoot of workspaceRoots) {
2682
- const resolvedRoot = import_node_path11.default.resolve(workspaceRoot.path, sourceRoot);
2890
+ const resolvedRoot = import_node_path12.default.resolve(workspaceRoot.path, sourceRoot);
2683
2891
  for (const layer of activeLayers) {
2684
- const layerRoot = import_node_path11.default.join(resolvedRoot, layer);
2892
+ const layerRoot = import_node_path12.default.join(resolvedRoot, layer);
2685
2893
  if (!await existsDirectory(layerRoot)) {
2686
2894
  continue;
2687
2895
  }
2688
2896
  for (const absolutePath of await collectYamlFiles(layerRoot)) {
2689
- const relativePath = import_node_path11.default.relative(repoRoot, absolutePath);
2897
+ const relativePath = import_node_path12.default.relative(repoRoot, absolutePath);
2690
2898
  files.push({
2691
2899
  absolutePath,
2692
2900
  relativePath: toPortablePath(relativePath.startsWith("..") ? absolutePath : relativePath),
@@ -2763,7 +2971,7 @@ function createFilesystemSecretsPlugin() {
2763
2971
  );
2764
2972
  const entries = [];
2765
2973
  for (const file of files) {
2766
- const document = await (0, import_promises12.readFile)(file.absolutePath, "utf8");
2974
+ const document = await (0, import_promises13.readFile)(file.absolutePath, "utf8");
2767
2975
  const fileEntries = filesystemSecretsReader(file.relativePath, document, file.workspaceId);
2768
2976
  for (const entry of fileEntries) {
2769
2977
  const metadata = toSecretReferenceMetadata(entry.value);
@@ -2779,7 +2987,7 @@ function createFilesystemSecretsPlugin() {
2779
2987
  }
2780
2988
 
2781
2989
  // ../../plugins/filesystem/src/filesystemValuesReader.ts
2782
- var import_promises13 = require("fs/promises");
2990
+ var import_promises14 = require("fs/promises");
2783
2991
  function filesystemValuesReader(filePath, document, workspaceId = "default") {
2784
2992
  return yamlObjectToEntries(document, filePath, "value", "filesystem-values", workspaceId);
2785
2993
  }
@@ -2800,7 +3008,7 @@ function createFilesystemValuesPlugin() {
2800
3008
  ).map(([namespace]) => namespace);
2801
3009
  const entries = [];
2802
3010
  for (const file of files) {
2803
- const document = await (0, import_promises13.readFile)(file.absolutePath, "utf8");
3011
+ const document = await (0, import_promises14.readFile)(file.absolutePath, "utf8");
2804
3012
  entries.push(...filesystemValuesReader(file.relativePath, document, file.workspaceId));
2805
3013
  }
2806
3014
  for (const namespace of customNamespaces) {
@@ -2815,7 +3023,7 @@ function createFilesystemValuesPlugin() {
2815
3023
  layers
2816
3024
  );
2817
3025
  for (const file of namespaceFiles) {
2818
- const document = await (0, import_promises13.readFile)(file.absolutePath, "utf8");
3026
+ const document = await (0, import_promises14.readFile)(file.absolutePath, "utf8");
2819
3027
  entries.push(...yamlObjectToEntries(document, file.relativePath, namespace, "filesystem-values", file.workspaceId));
2820
3028
  }
2821
3029
  }
@@ -2985,10 +3193,18 @@ async function createCnos2(options = {}) {
2985
3193
  }
2986
3194
 
2987
3195
  // src/runtime/bootstrap.ts
2988
- var import_node_crypto2 = require("crypto");
3196
+ var import_node_crypto3 = require("crypto");
2989
3197
  var CNOS_GRAPH_ENV_VAR = "__CNOS_GRAPH__";
3198
+ var CNOS_PROJECTION_ENV_VAR = "__CNOS_PROJECTION__";
2990
3199
  var CNOS_SECRET_PAYLOAD_ENV_VAR = "__CNOS_SECRET_PAYLOAD__";
2991
3200
  var CNOS_SESSION_KEY_ENV_VAR = "__CNOS_SESSION_KEY__";
3201
+ function deserializeServerProjection(source) {
3202
+ const payload = JSON.parse(source);
3203
+ if (!payload || payload.version !== 1 || typeof payload.workspace !== "string" || typeof payload.profile !== "string" || typeof payload.resolvedAt !== "string" || typeof payload.configHash !== "string" || !payload.values || typeof payload.values !== "object" || Array.isArray(payload.values) || !payload.secretRefs || typeof payload.secretRefs !== "object" || Array.isArray(payload.secretRefs) || !Array.isArray(payload.publicKeys) || !payload.meta || typeof payload.meta !== "object") {
3204
+ throw new Error("Invalid CNOS server projection payload");
3205
+ }
3206
+ return payload;
3207
+ }
2992
3208
  function deserializeRuntimeGraph(source) {
2993
3209
  const payload = JSON.parse(source);
2994
3210
  if (!payload || !Array.isArray(payload.entries) || typeof payload.profile !== "string" || typeof payload.resolvedAt !== "string" || !payload.profileSource || !payload.workspace || typeof payload.workspace.workspaceId !== "string" || !Array.isArray(payload.workspace.workspaceChain) || !Array.isArray(payload.workspace.workspaceRoots)) {
@@ -3022,7 +3238,7 @@ function decryptSecretPayload(serialized, sessionKey) {
3022
3238
  const iv = Buffer.from(payload.iv, "base64");
3023
3239
  const tag = Buffer.from(payload.tag, "base64");
3024
3240
  const ciphertext = Buffer.from(payload.ciphertext, "base64");
3025
- const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-gcm", key, iv);
3241
+ const decipher = (0, import_node_crypto3.createDecipheriv)("aes-256-gcm", key, iv);
3026
3242
  decipher.setAuthTag(tag);
3027
3243
  const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
3028
3244
  return JSON.parse(plaintext);
@@ -3046,6 +3262,13 @@ function readRuntimeGraphFromEnv(processEnv = process.env) {
3046
3262
  }
3047
3263
  return graph;
3048
3264
  }
3265
+ function readServerProjectionFromEnv(processEnv = process.env) {
3266
+ const serialized = processEnv[CNOS_PROJECTION_ENV_VAR];
3267
+ if (!serialized) {
3268
+ return void 0;
3269
+ }
3270
+ return deserializeServerProjection(serialized);
3271
+ }
3049
3272
  function graphRequiresSecretHydration(graph) {
3050
3273
  return Array.from(graph.entries.values()).some((entry) => entry.namespace === "secret" && isSecretReference(entry.value));
3051
3274
  }
@@ -3059,6 +3282,12 @@ function getRuntimeOrThrow() {
3059
3282
  }
3060
3283
  return runtime;
3061
3284
  }
3285
+ function requireLogicalKey(runtime, key) {
3286
+ return runtime.require(key);
3287
+ }
3288
+ function readLogicalKey(runtime, key) {
3289
+ return runtime.read(key);
3290
+ }
3062
3291
  function stringifyLogValue(value) {
3063
3292
  if (value === void 0) {
3064
3293
  return "";
@@ -3155,14 +3384,14 @@ function attachBootstrappedGraph(graph) {
3155
3384
  readOr(key, fallback) {
3156
3385
  return readOrValue(graph, key, fallback);
3157
3386
  },
3158
- value(path12) {
3159
- return readValue(graph, toLogicalKey("value", path12));
3387
+ value(path14) {
3388
+ return readValue(graph, toLogicalKey("value", path14));
3160
3389
  },
3161
- secret(path12) {
3162
- return readValue(graph, toLogicalKey("secret", path12));
3390
+ secret(path14) {
3391
+ return readValue(graph, toLogicalKey("secret", path14));
3163
3392
  },
3164
- meta(path12) {
3165
- return readValue(graph, toLogicalKey("meta", path12));
3393
+ meta(path14) {
3394
+ return readValue(graph, toLogicalKey("meta", path14));
3166
3395
  },
3167
3396
  toNamespace(namespace) {
3168
3397
  return toNamespaceObject(graph, namespace);
@@ -3178,11 +3407,275 @@ function attachBootstrappedGraph(graph) {
3178
3407
  },
3179
3408
  toObject() {
3180
3409
  return toNamespaceObject(graph);
3410
+ },
3411
+ toServerProjection() {
3412
+ throw new Error("CNOS graph bootstrap payload does not support server projection export.");
3413
+ },
3414
+ async refreshSecrets() {
3415
+ return;
3416
+ },
3417
+ async refreshSecret() {
3418
+ return;
3181
3419
  }
3182
3420
  };
3183
3421
  setSingletonRuntime(runtime);
3184
3422
  setBootstrappedSecretHydrationRequired(graphRequiresSecretHydration(graph));
3185
3423
  }
3424
+ function toBootstrappedManifest(graph) {
3425
+ return {
3426
+ version: 1,
3427
+ project: {
3428
+ name: "bootstrapped"
3429
+ },
3430
+ workspaces: {
3431
+ global: {
3432
+ enabled: false,
3433
+ allowWrite: false
3434
+ },
3435
+ items: {},
3436
+ ...graph.workspace.workspaceSource === "implicit" ? {} : {
3437
+ default: graph.workspace.workspaceId
3438
+ }
3439
+ },
3440
+ profiles: {
3441
+ default: graph.profile,
3442
+ resolveFrom: ["default"]
3443
+ },
3444
+ plugins: {
3445
+ loaders: [],
3446
+ resolver: "profile-aware",
3447
+ validators: [],
3448
+ exporters: [],
3449
+ inspectors: []
3450
+ },
3451
+ sources: {},
3452
+ resolution: {
3453
+ precedence: [],
3454
+ arrayPolicy: "replace"
3455
+ },
3456
+ envMapping: {
3457
+ explicit: {}
3458
+ },
3459
+ public: {
3460
+ promote: [],
3461
+ frameworks: {}
3462
+ },
3463
+ namespaces: {
3464
+ value: { kind: "data", shareable: true },
3465
+ secret: { kind: "data", shareable: false, sensitive: true },
3466
+ meta: { kind: "system", shareable: false, readonly: true },
3467
+ public: { kind: "projection", shareable: true, readonly: true, source: "promote" }
3468
+ },
3469
+ vaults: {},
3470
+ writePolicy: {
3471
+ define: {
3472
+ defaultProfile: graph.profile,
3473
+ targets: {
3474
+ value: "./values/app.yml",
3475
+ secret: "./secrets/app.yml"
3476
+ }
3477
+ }
3478
+ },
3479
+ schema: {}
3480
+ };
3481
+ }
3482
+ function graphFromProjection(projection) {
3483
+ const entries = /* @__PURE__ */ new Map();
3484
+ const now = projection.resolvedAt;
3485
+ const explicitNamespaces = /* @__PURE__ */ new Set(["flags", "config", "process", ...projection.meta.namespaces ?? []]);
3486
+ for (const [key, value] of Object.entries(projection.values)) {
3487
+ const firstSegment = key.split(".")[0] ?? "";
3488
+ const logicalKey = key.startsWith("value.") || key.startsWith("public.") || explicitNamespaces.has(firstSegment) ? key : `value.${key}`;
3489
+ const namespace = logicalKey.slice(0, logicalKey.indexOf("."));
3490
+ const winner = {
3491
+ key: logicalKey,
3492
+ value,
3493
+ namespace,
3494
+ sourceId: "server-projection",
3495
+ pluginId: "cnos",
3496
+ workspaceId: projection.workspace,
3497
+ profile: projection.profile
3498
+ };
3499
+ entries.set(logicalKey, {
3500
+ key: logicalKey,
3501
+ value,
3502
+ namespace,
3503
+ winner,
3504
+ overridden: []
3505
+ });
3506
+ }
3507
+ for (const [key, ref] of Object.entries(projection.secretRefs)) {
3508
+ const logicalKey = `secret.${key}`;
3509
+ entries.set(logicalKey, {
3510
+ key: logicalKey,
3511
+ value: ref,
3512
+ namespace: "secret",
3513
+ winner: {
3514
+ key: logicalKey,
3515
+ value: ref,
3516
+ namespace: "secret",
3517
+ sourceId: "server-projection",
3518
+ pluginId: "cnos",
3519
+ workspaceId: projection.workspace,
3520
+ profile: projection.profile
3521
+ },
3522
+ overridden: []
3523
+ });
3524
+ }
3525
+ for (const key of projection.publicKeys) {
3526
+ const valueKey = Object.prototype.hasOwnProperty.call(projection.values, key) ? key : `value.${key}`;
3527
+ const publicKey = `public.${key}`;
3528
+ const sourceEntry = entries.get(valueKey);
3529
+ if (!sourceEntry) {
3530
+ continue;
3531
+ }
3532
+ entries.set(publicKey, {
3533
+ key: publicKey,
3534
+ value: sourceEntry.value,
3535
+ namespace: "public",
3536
+ winner: {
3537
+ key: publicKey,
3538
+ value: sourceEntry.value,
3539
+ namespace: "public",
3540
+ sourceId: "server-projection",
3541
+ pluginId: "cnos",
3542
+ workspaceId: projection.workspace,
3543
+ profile: projection.profile
3544
+ },
3545
+ overridden: []
3546
+ });
3547
+ }
3548
+ entries.set("meta.profile", {
3549
+ key: "meta.profile",
3550
+ value: projection.profile,
3551
+ namespace: "meta",
3552
+ winner: {
3553
+ key: "meta.profile",
3554
+ value: projection.profile,
3555
+ namespace: "meta",
3556
+ sourceId: "server-projection",
3557
+ pluginId: "cnos",
3558
+ workspaceId: projection.workspace,
3559
+ profile: projection.profile
3560
+ },
3561
+ overridden: []
3562
+ });
3563
+ return {
3564
+ entries,
3565
+ profile: projection.profile,
3566
+ resolvedAt: now,
3567
+ profileSource: "manifest-default",
3568
+ workspace: {
3569
+ workspaceId: projection.workspace,
3570
+ workspaceSource: "implicit",
3571
+ workspaceChain: [projection.workspace],
3572
+ workspaceRoots: []
3573
+ }
3574
+ };
3575
+ }
3576
+ function attachBootstrappedProjection(projection, force = false) {
3577
+ if (getSingletonRuntime() && !force) {
3578
+ return;
3579
+ }
3580
+ const graph = graphFromProjection(projection);
3581
+ const manifest = toBootstrappedManifest(graph);
3582
+ const hydratedSecrets = /* @__PURE__ */ new Map();
3583
+ const resolveSecretValue = async (key) => {
3584
+ const entry = graph.entries.get(key);
3585
+ if (!entry || entry.namespace !== "secret") {
3586
+ return entry?.value;
3587
+ }
3588
+ if (hydratedSecrets.has(key)) {
3589
+ return hydratedSecrets.get(key);
3590
+ }
3591
+ const ref = projection.secretRefs[key.slice("secret.".length)];
3592
+ if (!ref) {
3593
+ return void 0;
3594
+ }
3595
+ const definition = { provider: ref.provider };
3596
+ const provider = createSecretVaultProvider(ref.vault ?? "default", definition, process.env);
3597
+ const auth = await resolveVaultAuth(ref.vault ?? "default", definition, process.env);
3598
+ await provider.authenticate(auth);
3599
+ const value = await provider.get(ref.ref);
3600
+ hydratedSecrets.set(key, value);
3601
+ return value;
3602
+ };
3603
+ const runtime = {
3604
+ manifest,
3605
+ plugins: [],
3606
+ graph,
3607
+ read(key) {
3608
+ const entry = graph.entries.get(key);
3609
+ if (!entry) {
3610
+ return void 0;
3611
+ }
3612
+ if (entry.namespace === "secret") {
3613
+ return hydratedSecrets.get(key);
3614
+ }
3615
+ return entry.value;
3616
+ },
3617
+ require(key) {
3618
+ const value = this.read(key);
3619
+ if (value === void 0) {
3620
+ throw new Error(`Missing required CNOS config key: ${key}`);
3621
+ }
3622
+ return value;
3623
+ },
3624
+ readOr(key, fallback) {
3625
+ return this.read(key) ?? fallback;
3626
+ },
3627
+ value(segment) {
3628
+ return this.read(toLogicalKey("value", segment));
3629
+ },
3630
+ secret(segment) {
3631
+ return this.read(toLogicalKey("secret", segment));
3632
+ },
3633
+ meta(segment) {
3634
+ return this.read(toLogicalKey("meta", segment));
3635
+ },
3636
+ inspect(key) {
3637
+ return inspectValue(
3638
+ {
3639
+ ...graph,
3640
+ entries: new Map(
3641
+ Array.from(graph.entries.entries()).map(([entryKey, existing]) => [
3642
+ entryKey,
3643
+ entryKey === key && existing.namespace === "secret" && hydratedSecrets.has(entryKey) ? { ...existing, value: hydratedSecrets.get(entryKey) } : existing
3644
+ ])
3645
+ )
3646
+ },
3647
+ key
3648
+ );
3649
+ },
3650
+ toObject() {
3651
+ return toNamespaceObject(graph);
3652
+ },
3653
+ toNamespace(namespace) {
3654
+ return toNamespaceObject(graph, namespace);
3655
+ },
3656
+ toEnv(options) {
3657
+ return toEnv(graph, manifest, options);
3658
+ },
3659
+ toPublicEnv(options) {
3660
+ return toPublicEnv(graph, manifest, options);
3661
+ },
3662
+ toServerProjection() {
3663
+ return projection;
3664
+ },
3665
+ async refreshSecrets() {
3666
+ for (const key of Object.keys(projection.secretRefs).map((segment) => `secret.${segment}`)) {
3667
+ hydratedSecrets.delete(key);
3668
+ await resolveSecretValue(key);
3669
+ }
3670
+ },
3671
+ async refreshSecret(key) {
3672
+ hydratedSecrets.delete(key);
3673
+ await resolveSecretValue(key);
3674
+ }
3675
+ };
3676
+ setSingletonRuntime(runtime);
3677
+ setBootstrappedSecretHydrationRequired(Object.keys(projection.secretRefs).length > 0);
3678
+ }
3186
3679
  function bootstrapFromProcessEnv() {
3187
3680
  if (typeof process === "undefined") {
3188
3681
  return;
@@ -3191,31 +3684,78 @@ function bootstrapFromProcessEnv() {
3191
3684
  const graph = readRuntimeGraphFromEnv(process.env);
3192
3685
  if (graph) {
3193
3686
  attachBootstrappedGraph(graph);
3687
+ return;
3688
+ }
3689
+ const projection = readServerProjectionFromEnv(process.env);
3690
+ if (projection) {
3691
+ attachBootstrappedProjection(projection);
3692
+ }
3693
+ } catch {
3694
+ }
3695
+ }
3696
+ function discoverProjectionPathSync() {
3697
+ const cwd = process.cwd();
3698
+ const directCandidates = [
3699
+ import_node_path13.default.join(cwd, ".cnos-server.json")
3700
+ ];
3701
+ for (const candidate of directCandidates) {
3702
+ if ((0, import_node_fs.existsSync)(candidate)) {
3703
+ return candidate;
3704
+ }
3705
+ }
3706
+ let current = cwd;
3707
+ for (let depth = 0; depth <= 3; depth += 1) {
3708
+ const rcCandidate = import_node_path13.default.join(current, ".cnosrc.yml");
3709
+ if ((0, import_node_fs.existsSync)(rcCandidate)) {
3710
+ const projectionCandidate = import_node_path13.default.join(current, ".cnos-server.json");
3711
+ if ((0, import_node_fs.existsSync)(projectionCandidate)) {
3712
+ return projectionCandidate;
3713
+ }
3714
+ }
3715
+ const parent = import_node_path13.default.dirname(current);
3716
+ if (parent === current) {
3717
+ break;
3718
+ }
3719
+ current = parent;
3720
+ }
3721
+ return void 0;
3722
+ }
3723
+ function bootstrapFromProjectionFile() {
3724
+ if (getSingletonRuntime()) {
3725
+ return;
3726
+ }
3727
+ try {
3728
+ const projectionPath = discoverProjectionPathSync();
3729
+ if (!projectionPath) {
3730
+ return;
3194
3731
  }
3732
+ const projection = deserializeServerProjection((0, import_node_fs.readFileSync)(projectionPath, "utf8"));
3733
+ attachBootstrappedProjection(projection);
3195
3734
  } catch {
3196
3735
  }
3197
3736
  }
3198
3737
  bootstrapFromProcessEnv();
3738
+ bootstrapFromProjectionFile();
3199
3739
  var cnos = Object.assign(
3200
- ((key) => readValue(getRuntimeOrThrow().graph, key)),
3740
+ ((key) => readLogicalKey(getRuntimeOrThrow(), key)),
3201
3741
  {
3202
3742
  read(key) {
3203
- return readValue(getRuntimeOrThrow().graph, key);
3743
+ return readLogicalKey(getRuntimeOrThrow(), key);
3204
3744
  },
3205
3745
  require(key) {
3206
- return requireValue(getRuntimeOrThrow().graph, key);
3746
+ return requireLogicalKey(getRuntimeOrThrow(), key);
3207
3747
  },
3208
3748
  readOr(key, fallback) {
3209
- return readOrValue(getRuntimeOrThrow().graph, key, fallback);
3749
+ return getRuntimeOrThrow().readOr(key, fallback);
3210
3750
  },
3211
- value(path12) {
3212
- return readValue(getRuntimeOrThrow().graph, toLogicalKey("value", path12));
3751
+ value(path14) {
3752
+ return getRuntimeOrThrow().value(path14);
3213
3753
  },
3214
- secret(path12) {
3215
- return readValue(getRuntimeOrThrow().graph, toLogicalKey("secret", path12));
3754
+ secret(path14) {
3755
+ return getRuntimeOrThrow().secret(path14);
3216
3756
  },
3217
- meta(path12) {
3218
- return readValue(getRuntimeOrThrow().graph, toLogicalKey("meta", path12));
3757
+ meta(path14) {
3758
+ return getRuntimeOrThrow().meta(path14);
3219
3759
  },
3220
3760
  inspect(key) {
3221
3761
  return getRuntimeOrThrow().inspect(key);
@@ -3237,8 +3777,27 @@ var cnos = Object.assign(
3237
3777
  console.log(formatted);
3238
3778
  return formatted;
3239
3779
  },
3780
+ async loadProjection(source) {
3781
+ const resolvedSource = import_node_path13.default.resolve(source);
3782
+ const projection = deserializeServerProjection((0, import_node_fs.readFileSync)(resolvedSource, "utf8"));
3783
+ attachBootstrappedProjection(projection, true);
3784
+ setBootstrappedSecretHydrationRequired(Object.keys(projection.secretRefs).length > 0);
3785
+ },
3786
+ async refreshSecrets() {
3787
+ await getRuntimeOrThrow().refreshSecrets();
3788
+ setBootstrappedSecretHydrationRequired(false);
3789
+ },
3790
+ async refreshSecret(key) {
3791
+ await getRuntimeOrThrow().refreshSecret(key);
3792
+ },
3240
3793
  async ready() {
3241
- if (getSingletonRuntime() && !getBootstrappedSecretHydrationRequired()) {
3794
+ const runtime = getSingletonRuntime();
3795
+ if (runtime && getBootstrappedSecretHydrationRequired()) {
3796
+ await runtime.refreshSecrets();
3797
+ setBootstrappedSecretHydrationRequired(false);
3798
+ return;
3799
+ }
3800
+ if (runtime && !getBootstrappedSecretHydrationRequired()) {
3242
3801
  return;
3243
3802
  }
3244
3803
  const existing = getSingletonReady();
@@ -3246,9 +3805,10 @@ var cnos = Object.assign(
3246
3805
  await existing;
3247
3806
  return;
3248
3807
  }
3249
- const readyPromise = createCnos2().then((runtime) => {
3250
- setSingletonRuntime(runtime);
3251
- return runtime;
3808
+ const readyPromise = createCnos2().then((runtime2) => {
3809
+ setSingletonRuntime(runtime2);
3810
+ setBootstrappedSecretHydrationRequired(false);
3811
+ return runtime2;
3252
3812
  });
3253
3813
  setSingletonReady(readyPromise);
3254
3814
  await readyPromise;