@kitsy/cnos 1.6.0 → 1.7.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 (63) hide show
  1. package/dist/build/index.cjs +1332 -156
  2. package/dist/build/index.d.cts +1 -1
  3. package/dist/build/index.d.ts +1 -1
  4. package/dist/build/index.js +36 -14
  5. package/dist/{chunk-JYWQFMW5.js → chunk-2DGT7N7E.js} +1 -1
  6. package/dist/{chunk-S7H2UULC.js → chunk-2TL42I6M.js} +1323 -139
  7. package/dist/{chunk-MW4OVAT3.js → chunk-5KIQCYFH.js} +1 -1
  8. package/dist/{chunk-UOKVLCFL.js → chunk-CV3SLBYZ.js} +10 -10
  9. package/dist/{chunk-XSUP7JKH.js → chunk-GHGJFRDL.js} +6 -2
  10. package/dist/{chunk-BMAD24KC.js → chunk-OA7FQGAG.js} +1 -1
  11. package/dist/{chunk-QU5CXL47.js → chunk-PFT56ID2.js} +195 -28
  12. package/dist/{chunk-VGZREX5D.js → chunk-RYIARE4M.js} +1 -1
  13. package/dist/{chunk-UR7CHHNN.js → chunk-TT4NV56Z.js} +3 -2
  14. package/dist/{chunk-UJBQS7CJ.js → chunk-UL63DFLS.js} +1 -1
  15. package/dist/configure/index.cjs +1309 -155
  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/{plugin-CKrBlWGI.d.cts → core-BJ8xewez.d.cts} +142 -60
  20. package/dist/{plugin-CKrBlWGI.d.ts → core-BJ8xewez.d.ts} +142 -60
  21. package/dist/{envNaming-B7Mztkcf.d.ts → envNaming-BRyiuPoI.d.ts} +1 -1
  22. package/dist/{envNaming-gMVnPOfe.d.cts → envNaming-rx71gpi0.d.cts} +1 -1
  23. package/dist/index.cjs +1548 -227
  24. package/dist/index.d.cts +1 -1
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.js +10 -10
  27. package/dist/internal.cjs +831 -122
  28. package/dist/internal.d.cts +56 -3
  29. package/dist/internal.d.ts +56 -3
  30. package/dist/internal.js +30 -3
  31. package/dist/plugin/basic-schema.cjs +49 -23
  32. package/dist/plugin/basic-schema.d.cts +1 -1
  33. package/dist/plugin/basic-schema.d.ts +1 -1
  34. package/dist/plugin/basic-schema.js +2 -2
  35. package/dist/plugin/cli-args.cjs +38 -23
  36. package/dist/plugin/cli-args.d.cts +1 -1
  37. package/dist/plugin/cli-args.d.ts +1 -1
  38. package/dist/plugin/cli-args.js +2 -2
  39. package/dist/plugin/dotenv.cjs +46 -31
  40. package/dist/plugin/dotenv.d.cts +2 -2
  41. package/dist/plugin/dotenv.d.ts +2 -2
  42. package/dist/plugin/dotenv.js +2 -2
  43. package/dist/plugin/env-export.cjs +56 -27
  44. package/dist/plugin/env-export.d.cts +2 -2
  45. package/dist/plugin/env-export.d.ts +2 -2
  46. package/dist/plugin/env-export.js +2 -2
  47. package/dist/plugin/filesystem.cjs +61 -39
  48. package/dist/plugin/filesystem.d.cts +1 -1
  49. package/dist/plugin/filesystem.d.ts +1 -1
  50. package/dist/plugin/filesystem.js +2 -2
  51. package/dist/plugin/process-env.cjs +40 -25
  52. package/dist/plugin/process-env.d.cts +2 -2
  53. package/dist/plugin/process-env.d.ts +2 -2
  54. package/dist/plugin/process-env.js +2 -2
  55. package/dist/runtime/index.cjs +1548 -227
  56. package/dist/runtime/index.d.cts +3 -1
  57. package/dist/runtime/index.d.ts +3 -1
  58. package/dist/runtime/index.js +10 -10
  59. package/dist/toPublicEnv-CCSgdvI9.d.ts +13 -0
  60. package/dist/toPublicEnv-ivRtLjcw.d.cts +13 -0
  61. package/package.json +1 -1
  62. package/dist/toPublicEnv-CmBsy53P.d.cts +0 -7
  63. package/dist/toPublicEnv-q6VwWxXZ.d.ts +0 -7
package/dist/internal.cjs CHANGED
@@ -40,6 +40,7 @@ __export(internal_exports, {
40
40
  clearAllVaultSessionKeys: () => clearAllVaultSessionKeys,
41
41
  clearVaultSessionKey: () => clearVaultSessionKey,
42
42
  compareSchemaToGraph: () => compareSchemaToGraph,
43
+ createRemoteRootCacheKey: () => createRemoteRootCacheKey,
43
44
  createSecretVault: () => createSecretVault,
44
45
  createSecretVaultProvider: () => createSecretVaultProvider,
45
46
  deleteLocalSecret: () => deleteLocalSecret,
@@ -56,23 +57,32 @@ __export(internal_exports, {
56
57
  getVaultPassphraseEnvVar: () => getVaultPassphraseEnvVar,
57
58
  getVaultSessionKeyEnvVar: () => getVaultSessionKeyEnvVar,
58
59
  graphRequiresSecretHydration: () => graphRequiresSecretHydration,
60
+ isDerivedValue: () => isDerivedValue,
61
+ isImmutableGitRef: () => isImmutableGitRef,
59
62
  isPassphraseEnvRef: () => isPassphraseEnvRef,
60
63
  isSecretReference: () => isSecretReference,
61
64
  listLocalSecrets: () => listLocalSecrets,
62
65
  listSecretVaults: () => listSecretVaults,
63
66
  loadManifest: () => loadManifest,
67
+ normalizeDerivedValue: () => normalizeDerivedValue,
68
+ parseDerivation: () => parseDerivation,
69
+ parseGitUri: () => parseGitUri,
64
70
  parseYaml: () => parseYaml,
65
71
  proposeMapping: () => proposeMapping,
66
72
  readKeychain: () => readKeychain,
67
73
  readLocalSecret: () => readLocalSecret,
74
+ readRemoteRootCacheMetadata: () => readRemoteRootCacheMetadata,
68
75
  readRuntimeGraphFromEnv: () => readRuntimeGraphFromEnv,
69
76
  readServerProjectionFromEnv: () => readServerProjectionFromEnv,
70
77
  readVaultMetadata: () => readVaultMetadata,
71
78
  removeLocalVaultFiles: () => removeLocalVaultFiles,
79
+ resolveCnosCacheRoot: () => resolveCnosCacheRoot,
72
80
  resolveCodegenPaths: () => resolveCodegenPaths,
73
81
  resolveConfigDocumentPath: () => resolveConfigDocumentPath,
74
82
  resolveConfiguredVaultPassphrase: () => resolveConfiguredVaultPassphrase,
75
83
  resolveManifestRoot: () => resolveManifestRoot,
84
+ resolveRemoteRootCachePaths: () => resolveRemoteRootCachePaths,
85
+ resolveRootUri: () => resolveRootUri,
76
86
  resolveSecretPassphrase: () => resolveSecretPassphrase,
77
87
  resolveSecretStoreRoot: () => resolveSecretStoreRoot,
78
88
  resolveSecretVaultFile: () => resolveSecretVaultFile,
@@ -85,12 +95,15 @@ __export(internal_exports, {
85
95
  serializeSecretPayload: () => serializeSecretPayload,
86
96
  serializeServerProjection: () => serializeServerProjection,
87
97
  stringifyYaml: () => stringifyYaml,
98
+ validateDerivedTargetNamespace: () => validateDerivedTargetNamespace,
99
+ validateParsedDerivation: () => validateParsedDerivation,
88
100
  validateRuntime: () => validateRuntime,
89
101
  watchFiles: () => watchFiles,
90
102
  watchSchema: () => watchSchema,
91
103
  writeCodegenOutput: () => writeCodegenOutput,
92
104
  writeKeychain: () => writeKeychain,
93
105
  writeLocalSecret: () => writeLocalSecret,
106
+ writeRemoteRootCacheMetadata: () => writeRemoteRootCacheMetadata,
94
107
  writeVaultSessionKey: () => writeVaultSessionKey
95
108
  });
96
109
  module.exports = __toCommonJS(internal_exports);
@@ -124,6 +137,317 @@ var CnosAuthenticationError = class extends CnosError {
124
137
  super(message);
125
138
  }
126
139
  };
140
+ var CnosDerivedExpressionError = class extends CnosError {
141
+ constructor(message, expression) {
142
+ super(expression ? `${message} (${expression})` : message);
143
+ this.expression = expression;
144
+ }
145
+ expression;
146
+ };
147
+
148
+ // ../core/src/derive/builtins.ts
149
+ function stringify(value) {
150
+ if (value === void 0 || value === null) {
151
+ return "";
152
+ }
153
+ if (typeof value === "string") {
154
+ return value;
155
+ }
156
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
157
+ return String(value);
158
+ }
159
+ return JSON.stringify(value);
160
+ }
161
+ var DERIVE_BUILTINS = {
162
+ concat: (...args) => args.map((value) => stringify(value)).join(""),
163
+ coalesce: (...args) => args.find((value) => value !== void 0 && value !== null),
164
+ when: (condition, whenTrue, whenFalse) => condition ? whenTrue : whenFalse,
165
+ exists: (value) => value !== void 0 && value !== null,
166
+ eq: (left, right) => left === right,
167
+ ne: (left, right) => left !== right
168
+ };
169
+
170
+ // ../core/src/derive/parser.ts
171
+ function isWhitespace(value) {
172
+ return value === " " || value === "\n" || value === "\r" || value === " ";
173
+ }
174
+ function skipWhitespace(state) {
175
+ while (isWhitespace(state.source[state.index])) {
176
+ state.index += 1;
177
+ }
178
+ }
179
+ function isIdentifierStart(value) {
180
+ return typeof value === "string" && /[A-Za-z_]/.test(value);
181
+ }
182
+ function isIdentifierPart(value) {
183
+ return typeof value === "string" && /[A-Za-z0-9_.-]/.test(value);
184
+ }
185
+ function errorAt(state, message) {
186
+ throw new CnosDerivedExpressionError(`${message} at position ${state.index + 1}`, state.source);
187
+ }
188
+ function parseStringLiteral(state) {
189
+ const quote = state.source[state.index];
190
+ if (quote !== "'") {
191
+ errorAt(state, "Expected string literal");
192
+ }
193
+ state.index += 1;
194
+ let value = "";
195
+ while (state.index < state.source.length) {
196
+ const current = state.source[state.index];
197
+ if (current === "\\") {
198
+ const next = state.source[state.index + 1];
199
+ if (next === void 0) {
200
+ errorAt(state, "Unterminated escape sequence");
201
+ }
202
+ value += next;
203
+ state.index += 2;
204
+ continue;
205
+ }
206
+ if (current === "'") {
207
+ state.index += 1;
208
+ return {
209
+ type: "literal",
210
+ value
211
+ };
212
+ }
213
+ value += current;
214
+ state.index += 1;
215
+ }
216
+ errorAt(state, "Unterminated string literal");
217
+ }
218
+ function parseNumberLiteral(state) {
219
+ const start = state.index;
220
+ while (/[0-9]/.test(state.source[state.index] ?? "")) {
221
+ state.index += 1;
222
+ }
223
+ if (state.source[state.index] === ".") {
224
+ state.index += 1;
225
+ while (/[0-9]/.test(state.source[state.index] ?? "")) {
226
+ state.index += 1;
227
+ }
228
+ }
229
+ return {
230
+ type: "literal",
231
+ value: Number(state.source.slice(start, state.index))
232
+ };
233
+ }
234
+ function parseIdentifier(state) {
235
+ if (!isIdentifierStart(state.source[state.index])) {
236
+ errorAt(state, "Expected identifier");
237
+ }
238
+ const start = state.index;
239
+ state.index += 1;
240
+ while (isIdentifierPart(state.source[state.index])) {
241
+ state.index += 1;
242
+ }
243
+ return state.source.slice(start, state.index);
244
+ }
245
+ function parseArguments(state) {
246
+ const args = [];
247
+ skipWhitespace(state);
248
+ if (state.source[state.index] === ")") {
249
+ state.index += 1;
250
+ return args;
251
+ }
252
+ while (state.index < state.source.length) {
253
+ args.push(parseExpressionNode(state));
254
+ skipWhitespace(state);
255
+ const current = state.source[state.index];
256
+ if (current === ",") {
257
+ state.index += 1;
258
+ skipWhitespace(state);
259
+ continue;
260
+ }
261
+ if (current === ")") {
262
+ state.index += 1;
263
+ return args;
264
+ }
265
+ errorAt(state, 'Expected "," or ")"');
266
+ }
267
+ errorAt(state, "Unterminated function call");
268
+ }
269
+ function parseIdentifierOrCall(state) {
270
+ const identifier = parseIdentifier(state);
271
+ skipWhitespace(state);
272
+ if (state.source[state.index] === "(") {
273
+ if (!(identifier in DERIVE_BUILTINS)) {
274
+ throw new CnosDerivedExpressionError(`Unknown derive function: ${identifier}`, state.source);
275
+ }
276
+ state.index += 1;
277
+ return {
278
+ type: "call",
279
+ name: identifier,
280
+ args: parseArguments(state)
281
+ };
282
+ }
283
+ if (identifier === "true" || identifier === "false") {
284
+ return {
285
+ type: "literal",
286
+ value: identifier === "true"
287
+ };
288
+ }
289
+ if (identifier === "null") {
290
+ return {
291
+ type: "literal",
292
+ value: null
293
+ };
294
+ }
295
+ return {
296
+ type: "ref",
297
+ path: identifier
298
+ };
299
+ }
300
+ function parseExpressionNode(state) {
301
+ skipWhitespace(state);
302
+ const current = state.source[state.index];
303
+ if (current === "'") {
304
+ return parseStringLiteral(state);
305
+ }
306
+ if (/[0-9]/.test(current ?? "")) {
307
+ return parseNumberLiteral(state);
308
+ }
309
+ if (isIdentifierStart(current)) {
310
+ return parseIdentifierOrCall(state);
311
+ }
312
+ errorAt(state, "Unexpected token");
313
+ }
314
+ function parseExpression(source) {
315
+ const state = {
316
+ source,
317
+ index: 0
318
+ };
319
+ const ast = parseExpressionNode(state);
320
+ skipWhitespace(state);
321
+ if (state.index !== source.length) {
322
+ errorAt(state, "Unexpected trailing input");
323
+ }
324
+ return ast;
325
+ }
326
+
327
+ // ../core/src/derive/templateParser.ts
328
+ function toLiteral(value) {
329
+ return {
330
+ type: "literal",
331
+ value
332
+ };
333
+ }
334
+ function toRef(path17) {
335
+ return {
336
+ type: "ref",
337
+ path: path17
338
+ };
339
+ }
340
+ function parseTemplate(source) {
341
+ const parts = [];
342
+ let cursor = 0;
343
+ while (cursor < source.length) {
344
+ const start = source.indexOf("${", cursor);
345
+ if (start < 0) {
346
+ if (cursor < source.length) {
347
+ parts.push(toLiteral(source.slice(cursor)));
348
+ }
349
+ break;
350
+ }
351
+ if (start > cursor) {
352
+ parts.push(toLiteral(source.slice(cursor, start)));
353
+ }
354
+ const end = source.indexOf("}", start + 2);
355
+ if (end < 0) {
356
+ throw new CnosDerivedExpressionError(`Invalid derivation template: unclosed \${...} at position ${start + 1}`, source);
357
+ }
358
+ const ref = source.slice(start + 2, end).trim();
359
+ if (!ref) {
360
+ throw new CnosDerivedExpressionError(`Invalid derivation template: empty reference at position ${start + 1}`, source);
361
+ }
362
+ if (!/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(ref)) {
363
+ throw new CnosDerivedExpressionError(`Invalid derivation template reference "${ref}"`, source);
364
+ }
365
+ parts.push(toRef(ref));
366
+ cursor = end + 1;
367
+ }
368
+ if (parts.length === 0) {
369
+ return toLiteral("");
370
+ }
371
+ if (parts.length === 1) {
372
+ return parts[0];
373
+ }
374
+ return {
375
+ type: "call",
376
+ name: "concat",
377
+ args: parts
378
+ };
379
+ }
380
+
381
+ // ../core/src/derive/evaluator.ts
382
+ function isDerivedValue(value) {
383
+ return Boolean(
384
+ value && typeof value === "object" && !Array.isArray(value) && "$derive" in value
385
+ );
386
+ }
387
+ function extractRefs(node, refs = /* @__PURE__ */ new Set()) {
388
+ if (node.type === "ref") {
389
+ refs.add(node.path);
390
+ return refs;
391
+ }
392
+ if (node.type === "call") {
393
+ for (const arg of node.args) {
394
+ extractRefs(arg, refs);
395
+ }
396
+ }
397
+ return refs;
398
+ }
399
+ function parseDerivation(value) {
400
+ const source = typeof value.$derive === "string" ? value.$derive : value.$derive?.expr;
401
+ if (typeof source !== "string") {
402
+ throw new CnosDerivedExpressionError("Derived value requires either a template string or { expr } object");
403
+ }
404
+ const type = typeof value.$derive === "string" ? "template" : "expression";
405
+ const ast = type === "template" ? parseTemplate(source) : parseExpression(source);
406
+ const refs = Array.from(extractRefs(ast)).sort((left, right) => left.localeCompare(right));
407
+ return {
408
+ type,
409
+ raw: source,
410
+ ast,
411
+ refs,
412
+ runtimeRefs: [],
413
+ isRuntimeDependent: false
414
+ };
415
+ }
416
+
417
+ // ../core/src/derive/validate.ts
418
+ var FORBIDDEN_TARGET_NAMESPACES = /* @__PURE__ */ new Set(["public", "meta", "secret"]);
419
+ var FORBIDDEN_REF_NAMESPACES = /* @__PURE__ */ new Set(["public", "secret"]);
420
+ function validateDerivedTargetNamespace(manifest, namespace) {
421
+ if (FORBIDDEN_TARGET_NAMESPACES.has(namespace)) {
422
+ throw new CnosManifestError(`Cannot define derived values under namespace "${namespace}".`);
423
+ }
424
+ if (manifest.runtimeNamespaces[namespace]) {
425
+ throw new CnosManifestError(`Cannot define derived values under runtime namespace "${namespace}".`);
426
+ }
427
+ }
428
+ function validateParsedDerivation(manifest, parsed) {
429
+ for (const ref of parsed.refs) {
430
+ const namespace = ref.split(".")[0] ?? "";
431
+ if (FORBIDDEN_REF_NAMESPACES.has(namespace)) {
432
+ throw new CnosDerivedExpressionError(`Derived expressions cannot reference ${namespace}.* keys.`, parsed.raw);
433
+ }
434
+ if (manifest.runtimeNamespaces[namespace]) {
435
+ continue;
436
+ }
437
+ if (!manifest.namespaces[namespace] && namespace !== "value" && namespace !== "meta") {
438
+ throw new CnosDerivedExpressionError(`Unknown derive reference namespace: ${namespace}`, parsed.raw);
439
+ }
440
+ }
441
+ }
442
+ function normalizeDerivedValue(templateOrExpr, expr = false) {
443
+ return expr ? {
444
+ $derive: {
445
+ expr: templateOrExpr
446
+ }
447
+ } : {
448
+ $derive: templateOrExpr
449
+ };
450
+ }
127
451
 
128
452
  // ../core/src/keychain/linux.ts
129
453
  var import_node_child_process = require("child_process");
@@ -232,17 +556,17 @@ async function writeKeychain(entry, value) {
232
556
  }
233
557
 
234
558
  // ../core/src/manifest/loadManifest.ts
235
- var import_promises3 = require("fs/promises");
236
- var import_node_path3 = __toESM(require("path"), 1);
559
+ var import_promises5 = require("fs/promises");
560
+ var import_node_path6 = __toESM(require("path"), 1);
237
561
 
238
562
  // ../core/src/utils/path.ts
239
- var import_promises2 = require("fs/promises");
240
- var import_node_os = __toESM(require("os"), 1);
241
- var import_node_path2 = __toESM(require("path"), 1);
563
+ var import_promises4 = require("fs/promises");
564
+ var import_node_os3 = __toESM(require("os"), 1);
565
+ var import_node_path5 = __toESM(require("path"), 1);
242
566
 
243
567
  // ../core/src/discovery/findCnosrc.ts
244
- var import_promises = require("fs/promises");
245
- var import_node_path = __toESM(require("path"), 1);
568
+ var import_promises3 = require("fs/promises");
569
+ var import_node_path4 = __toESM(require("path"), 1);
246
570
 
247
571
  // ../core/src/utils/yaml.ts
248
572
  var import_yaml = require("yaml");
@@ -253,10 +577,315 @@ function stringifyYaml(value) {
253
577
  return (0, import_yaml.stringify)(value);
254
578
  }
255
579
 
580
+ // ../core/src/discovery/resolveRoot.ts
581
+ var import_promises2 = require("fs/promises");
582
+ var import_node_path3 = __toESM(require("path"), 1);
583
+ var import_node_child_process4 = require("child_process");
584
+ var import_node_os2 = __toESM(require("os"), 1);
585
+
586
+ // ../core/src/discovery/parseGitUri.ts
587
+ function isGitRootUri(uri) {
588
+ return /^git\+[a-z]+:\/\//i.test(uri);
589
+ }
590
+ function parseGitUri(uri) {
591
+ if (!isGitRootUri(uri)) {
592
+ throw new CnosDiscoveryError(`Unsupported git root URI: ${uri}`);
593
+ }
594
+ const withoutPrefix = uri.slice("git+".length);
595
+ const hashIndex = withoutPrefix.indexOf("#");
596
+ if (hashIndex < 0) {
597
+ throw new CnosDiscoveryError(
598
+ `Git root URI must include a #ref (tag, branch, or commit). Got: ${uri}`
599
+ );
600
+ }
601
+ const cloneUrl = withoutPrefix.slice(0, hashIndex);
602
+ const fragment = withoutPrefix.slice(hashIndex + 1);
603
+ const separatorIndex = fragment.indexOf(":");
604
+ const ref = (separatorIndex >= 0 ? fragment.slice(0, separatorIndex) : fragment).trim();
605
+ const subpath = (separatorIndex >= 0 ? fragment.slice(separatorIndex + 1) : ".cnos").trim() || ".cnos";
606
+ const protocol = cloneUrl.slice(0, cloneUrl.indexOf("://"));
607
+ if (!cloneUrl || !ref) {
608
+ throw new CnosDiscoveryError(
609
+ `Git root URI must include both a clone URL and #ref. Got: ${uri}`
610
+ );
611
+ }
612
+ return {
613
+ uri,
614
+ cloneUrl,
615
+ ref,
616
+ subpath,
617
+ transport: protocol === "https" ? "https" : protocol === "ssh" ? "ssh" : protocol === "file" ? "file" : "custom"
618
+ };
619
+ }
620
+
621
+ // ../core/src/discovery/cache/cacheManager.ts
622
+ var SEMVER_TAG_RE = /^v?\d+\.\d+(?:\.\d+)?(?:[-+][A-Za-z0-9.-]+)?$/;
623
+ var COMMIT_SHA_RE = /^[0-9a-f]{40}$/i;
624
+ function isImmutableGitRef(ref) {
625
+ return SEMVER_TAG_RE.test(ref) || COMMIT_SHA_RE.test(ref);
626
+ }
627
+ function resolveRemoteRootCacheTtlSeconds(mode = "runtime", processEnv = process.env, override) {
628
+ if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
629
+ return override;
630
+ }
631
+ const fromEnv = Number(processEnv.CNOS_CACHE_TTL ?? "");
632
+ if (Number.isFinite(fromEnv) && fromEnv >= 0) {
633
+ return fromEnv;
634
+ }
635
+ switch (mode) {
636
+ case "build":
637
+ return 0;
638
+ case "dev":
639
+ return 30;
640
+ case "runtime":
641
+ default:
642
+ return 300;
643
+ }
644
+ }
645
+ function isRemoteRootCacheFresh(metadata, options) {
646
+ if (!metadata || options.forceRefresh) {
647
+ return false;
648
+ }
649
+ if (metadata.uri !== options.uri || metadata.ref !== options.ref) {
650
+ return false;
651
+ }
652
+ if (metadata.isImmutable) {
653
+ return true;
654
+ }
655
+ const ttlSeconds = resolveRemoteRootCacheTtlSeconds(
656
+ options.mode,
657
+ options.processEnv,
658
+ options.ttlSeconds
659
+ );
660
+ if (ttlSeconds <= 0) {
661
+ return false;
662
+ }
663
+ const cachedAtMs = Date.parse(metadata.cachedAt);
664
+ if (Number.isNaN(cachedAtMs)) {
665
+ return false;
666
+ }
667
+ return Date.now() - cachedAtMs <= ttlSeconds * 1e3;
668
+ }
669
+
670
+ // ../core/src/discovery/cache/cacheMetadata.ts
671
+ var import_promises = require("fs/promises");
672
+ var import_node_path = __toESM(require("path"), 1);
673
+ async function readRemoteRootCacheMetadata(metaPath) {
674
+ try {
675
+ const source = await (0, import_promises.readFile)(metaPath, "utf8");
676
+ const parsed = JSON.parse(source);
677
+ if (!parsed || typeof parsed.uri !== "string" || typeof parsed.cloneUrl !== "string" || typeof parsed.ref !== "string" || typeof parsed.subpath !== "string" || typeof parsed.resolvedCommit !== "string" || typeof parsed.cachedAt !== "string" || typeof parsed.isImmutable !== "boolean") {
678
+ return void 0;
679
+ }
680
+ return parsed;
681
+ } catch {
682
+ return void 0;
683
+ }
684
+ }
685
+ async function writeRemoteRootCacheMetadata(metaPath, metadata) {
686
+ await (0, import_promises.mkdir)(import_node_path.default.dirname(metaPath), { recursive: true });
687
+ await (0, import_promises.writeFile)(metaPath, `${JSON.stringify(metadata, null, 2)}
688
+ `, "utf8");
689
+ }
690
+
691
+ // ../core/src/discovery/cache/cachePaths.ts
692
+ var import_node_crypto = require("crypto");
693
+ var import_node_os = __toESM(require("os"), 1);
694
+ var import_node_path2 = __toESM(require("path"), 1);
695
+ function resolveCnosCacheRoot(processEnv = process.env) {
696
+ return import_node_path2.default.resolve(
697
+ expandHomePath(processEnv.CNOS_CACHE_DIR ?? import_node_path2.default.join(import_node_os.default.homedir(), ".cnos", "cache"))
698
+ );
699
+ }
700
+ function createRemoteRootCacheKey(uri) {
701
+ return (0, import_node_crypto.createHash)("sha256").update(uri).digest("hex");
702
+ }
703
+ function resolveRemoteRootCachePaths(uri, processEnv = process.env) {
704
+ const cacheRoot = resolveCnosCacheRoot(processEnv);
705
+ const cacheDir = import_node_path2.default.join(cacheRoot, "roots", createRemoteRootCacheKey(uri));
706
+ return {
707
+ cacheRoot,
708
+ cacheDir,
709
+ repoDir: import_node_path2.default.join(cacheDir, "repo"),
710
+ metaPath: import_node_path2.default.join(cacheDir, ".cnos-cache-meta.json")
711
+ };
712
+ }
713
+
714
+ // ../core/src/discovery/resolveRoot.ts
715
+ async function pathExists(targetPath) {
716
+ try {
717
+ await (0, import_promises2.access)(targetPath);
718
+ return true;
719
+ } catch {
720
+ return false;
721
+ }
722
+ }
723
+ function expandHomePath2(targetPath) {
724
+ if (targetPath === "~") {
725
+ return import_node_os2.default.homedir();
726
+ }
727
+ if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
728
+ return import_node_path3.default.join(import_node_os2.default.homedir(), targetPath.slice(2));
729
+ }
730
+ return targetPath;
731
+ }
732
+ function isLocalRootUri(rootUri) {
733
+ return !isGitRootUri2(rootUri) && !isCnosHostedRootUri(rootUri);
734
+ }
735
+ function isCnosHostedRootUri(rootUri) {
736
+ return rootUri.startsWith("cnos://");
737
+ }
738
+ function isGitRootUri2(rootUri) {
739
+ return rootUri.startsWith("git+");
740
+ }
741
+ async function runGitCommand(args, options = {}) {
742
+ return new Promise((resolve, reject) => {
743
+ const child = (0, import_node_child_process4.spawn)("git", args, {
744
+ cwd: options.cwd,
745
+ env: options.processEnv ?? process.env,
746
+ shell: process.platform === "win32",
747
+ stdio: ["ignore", "pipe", "pipe"]
748
+ });
749
+ let stdout = "";
750
+ let stderr = "";
751
+ child.stdout.on("data", (chunk) => {
752
+ stdout += chunk.toString();
753
+ });
754
+ child.stderr.on("data", (chunk) => {
755
+ stderr += chunk.toString();
756
+ });
757
+ child.on("error", (error) => {
758
+ reject(
759
+ new CnosDiscoveryError(
760
+ `Failed to run git. Make sure git is installed and available on PATH. ${error.message}`
761
+ )
762
+ );
763
+ });
764
+ child.on("close", (code) => {
765
+ if (code === 0) {
766
+ resolve(stdout.trim());
767
+ return;
768
+ }
769
+ const details = stderr.trim() || stdout.trim();
770
+ reject(
771
+ new CnosDiscoveryError(
772
+ details ? `Git command failed: ${details}` : `Git command failed with exit code ${code ?? 1}`
773
+ )
774
+ );
775
+ });
776
+ });
777
+ }
778
+ async function resolveLocalRoot(rootUri, cnosrcDir) {
779
+ const candidateRoot = rootUri.startsWith("~") ? expandHomePath2(rootUri) : rootUri;
780
+ const manifestRoot = import_node_path3.default.resolve(cnosrcDir, candidateRoot);
781
+ const manifestPath = import_node_path3.default.join(manifestRoot, "cnos.yml");
782
+ if (!await pathExists(manifestPath)) {
783
+ throw new CnosDiscoveryError(`.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`);
784
+ }
785
+ return {
786
+ manifestRoot,
787
+ resolution: {
788
+ rootUri,
789
+ protocol: "local",
790
+ remote: false,
791
+ readOnly: false
792
+ }
793
+ };
794
+ }
795
+ async function ensureGitCheckout(parsed, repoDir, processEnv) {
796
+ const hasRepo = await pathExists(import_node_path3.default.join(repoDir, ".git"));
797
+ if (!hasRepo) {
798
+ await (0, import_promises2.mkdir)(import_node_path3.default.dirname(repoDir), { recursive: true });
799
+ await runGitCommand(["clone", "--no-checkout", parsed.cloneUrl, repoDir], { processEnv });
800
+ } else {
801
+ await runGitCommand(["-C", repoDir, "remote", "set-url", "origin", parsed.cloneUrl], {
802
+ processEnv
803
+ });
804
+ }
805
+ await runGitCommand(["-C", repoDir, "fetch", "--tags", "--force", "origin"], { processEnv });
806
+ await runGitCommand(["-C", repoDir, "checkout", "--force", parsed.ref], { processEnv });
807
+ await runGitCommand(["-C", repoDir, "clean", "-fdx"], { processEnv });
808
+ }
809
+ async function resolveGitRoot(rootUri, options = {}) {
810
+ const processEnv = options.processEnv ?? process.env;
811
+ const parsed = parseGitUri(rootUri);
812
+ const cachePaths = resolveRemoteRootCachePaths(rootUri, processEnv);
813
+ const metadata = await readRemoteRootCacheMetadata(cachePaths.metaPath);
814
+ const immutable = isImmutableGitRef(parsed.ref);
815
+ const cacheFresh = isRemoteRootCacheFresh(metadata, {
816
+ uri: rootUri,
817
+ ref: parsed.ref,
818
+ ...options.cacheMode ? { mode: options.cacheMode } : {},
819
+ processEnv,
820
+ ...typeof options.cacheTtlSeconds === "number" ? { ttlSeconds: options.cacheTtlSeconds } : {},
821
+ ...options.forceRefresh ? { forceRefresh: true } : {}
822
+ });
823
+ if (!cacheFresh) {
824
+ try {
825
+ await ensureGitCheckout(parsed, cachePaths.repoDir, processEnv);
826
+ } catch (error) {
827
+ const message = error instanceof Error ? error.message : String(error);
828
+ const authHint = parsed.transport === "ssh" ? " Check your SSH key and git access." : " Check the URL and your git credential helper or token setup.";
829
+ throw new CnosDiscoveryError(`Failed to resolve remote git root ${rootUri}. ${message}${authHint}`);
830
+ }
831
+ const resolvedCommit = await runGitCommand(["-C", cachePaths.repoDir, "rev-parse", "HEAD"], {
832
+ processEnv
833
+ });
834
+ await writeRemoteRootCacheMetadata(cachePaths.metaPath, {
835
+ uri: rootUri,
836
+ cloneUrl: parsed.cloneUrl,
837
+ ref: parsed.ref,
838
+ subpath: parsed.subpath,
839
+ resolvedCommit,
840
+ cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
841
+ isImmutable: immutable
842
+ });
843
+ }
844
+ const nextMetadata = metadata && cacheFresh ? metadata : await readRemoteRootCacheMetadata(cachePaths.metaPath);
845
+ const manifestRoot = import_node_path3.default.join(cachePaths.repoDir, parsed.subpath);
846
+ if (!await pathExists(import_node_path3.default.join(manifestRoot, "cnos.yml"))) {
847
+ throw new CnosDiscoveryError(
848
+ `Git root ${rootUri} resolved to ${manifestRoot} but no cnos.yml was found there. Check the :subpath segment.`
849
+ );
850
+ }
851
+ return {
852
+ manifestRoot,
853
+ resolution: {
854
+ rootUri,
855
+ protocol: "git",
856
+ remote: true,
857
+ readOnly: true,
858
+ cacheDir: cachePaths.cacheDir,
859
+ cacheMetaPath: cachePaths.metaPath,
860
+ ref: parsed.ref,
861
+ subpath: parsed.subpath,
862
+ immutable,
863
+ ...nextMetadata?.resolvedCommit ? { resolvedCommit: nextMetadata.resolvedCommit } : {},
864
+ ...nextMetadata?.cachedAt ? { cachedAt: nextMetadata.cachedAt } : {}
865
+ }
866
+ };
867
+ }
868
+ async function resolveRootUri(rootUri, cnosrcDir, options = {}) {
869
+ if (isLocalRootUri(rootUri)) {
870
+ return resolveLocalRoot(rootUri, cnosrcDir);
871
+ }
872
+ if (isGitRootUri2(rootUri)) {
873
+ return resolveGitRoot(rootUri, options);
874
+ }
875
+ if (isCnosHostedRootUri(rootUri)) {
876
+ throw new CnosDiscoveryError(
877
+ `The cnos:// remote root protocol is reserved but not implemented yet. Use git+https:// or git+ssh:// for now.`
878
+ );
879
+ }
880
+ throw new CnosDiscoveryError(
881
+ `Unknown root protocol: ${rootUri}. Supported root protocols are local paths, git+https://..., and git+ssh://....`
882
+ );
883
+ }
884
+
256
885
  // ../core/src/discovery/findCnosrc.ts
257
886
  async function exists(targetPath) {
258
887
  try {
259
- await (0, import_promises.access)(targetPath);
888
+ await (0, import_promises3.access)(targetPath);
260
889
  return true;
261
890
  } catch {
262
891
  return false;
@@ -277,13 +906,13 @@ function validateCnosrc(value, filePath) {
277
906
  };
278
907
  }
279
908
  async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
280
- let current = import_node_path.default.resolve(startDir);
909
+ let current = import_node_path4.default.resolve(startDir);
281
910
  for (let depth = 0; depth <= maxLevels; depth += 1) {
282
- const candidate = import_node_path.default.join(current, ".cnosrc.yml");
911
+ const candidate = import_node_path4.default.join(current, ".cnosrc.yml");
283
912
  if (await exists(candidate)) {
284
913
  return candidate;
285
914
  }
286
- const parent = import_node_path.default.dirname(current);
915
+ const parent = import_node_path4.default.dirname(current);
287
916
  if (parent === current) {
288
917
  break;
289
918
  }
@@ -291,27 +920,22 @@ async function findCnosrc(startDir = process.cwd(), maxLevels = 3) {
291
920
  }
292
921
  return void 0;
293
922
  }
294
- async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3) {
923
+ async function discoverCnosAnchor(startDir = process.cwd(), maxLevels = 3, options = {}) {
295
924
  const anchorPath = await findCnosrc(startDir, maxLevels);
296
925
  if (!anchorPath) {
297
926
  throw new CnosDiscoveryError(
298
927
  "No .cnosrc.yml found. Run cnos init or create .cnosrc.yml in your package root."
299
928
  );
300
929
  }
301
- const source = await (0, import_promises.readFile)(anchorPath, "utf8");
930
+ const source = await (0, import_promises3.readFile)(anchorPath, "utf8");
302
931
  const parsed = validateCnosrc(parseYaml(source), anchorPath);
303
- const consumerRoot = import_node_path.default.dirname(anchorPath);
304
- const manifestRoot = import_node_path.default.resolve(consumerRoot, parsed.root);
305
- const manifestPath = import_node_path.default.join(manifestRoot, "cnos.yml");
306
- if (!await exists(manifestPath)) {
307
- throw new CnosDiscoveryError(
308
- `.cnosrc.yml points to ${manifestRoot} but no cnos.yml found there.`
309
- );
310
- }
932
+ const consumerRoot = import_node_path4.default.dirname(anchorPath);
933
+ const resolvedRoot = await resolveRootUri(parsed.root, consumerRoot, options);
311
934
  return {
312
935
  anchorPath,
313
936
  consumerRoot,
314
- manifestRoot,
937
+ manifestRoot: resolvedRoot.manifestRoot,
938
+ rootResolution: resolvedRoot.resolution,
315
939
  ...parsed.workspace ? { workspace: parsed.workspace } : {}
316
940
  };
317
941
  }
@@ -321,21 +945,21 @@ var PRIMARY_CNOS_DIR = ".cnos";
321
945
  var LEGACY_CNOS_DIR = "cnos";
322
946
  async function exists2(filePath) {
323
947
  try {
324
- await (0, import_promises2.access)(filePath);
948
+ await (0, import_promises4.access)(filePath);
325
949
  return true;
326
950
  } catch {
327
951
  return false;
328
952
  }
329
953
  }
330
954
  async function resolveCnosRoot(root = process.cwd()) {
331
- const basePath = import_node_path2.default.resolve(root);
955
+ const basePath = import_node_path5.default.resolve(root);
332
956
  const candidates = [
333
- import_node_path2.default.join(basePath, PRIMARY_CNOS_DIR),
334
- import_node_path2.default.join(basePath, LEGACY_CNOS_DIR),
957
+ import_node_path5.default.join(basePath, PRIMARY_CNOS_DIR),
958
+ import_node_path5.default.join(basePath, LEGACY_CNOS_DIR),
335
959
  basePath
336
960
  ];
337
961
  for (const candidate of candidates) {
338
- if (await exists2(import_node_path2.default.join(candidate, "cnos.yml"))) {
962
+ if (await exists2(import_node_path5.default.join(candidate, "cnos.yml"))) {
339
963
  return candidate;
340
964
  }
341
965
  }
@@ -345,42 +969,68 @@ async function resolveCnosRoot(root = process.cwd()) {
345
969
  }
346
970
  async function resolveManifestRoot(options = {}) {
347
971
  if (options.root) {
972
+ if (options.root.startsWith("git+") || options.root.startsWith("cnos://")) {
973
+ const consumerRoot2 = import_node_path5.default.resolve(options.cwd ?? process.cwd());
974
+ const resolvedRoot2 = await resolveRootUri(options.root, consumerRoot2, {
975
+ ...options.processEnv ? { processEnv: options.processEnv } : {},
976
+ ...options.cacheMode ? { cacheMode: options.cacheMode } : {},
977
+ ...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
978
+ ...options.forceRefresh ? { forceRefresh: true } : {}
979
+ });
980
+ return {
981
+ manifestRoot: resolvedRoot2.manifestRoot,
982
+ consumerRoot: consumerRoot2,
983
+ rootResolution: resolvedRoot2.resolution
984
+ };
985
+ }
348
986
  const manifestRoot = await resolveCnosRoot(options.root);
349
- const resolvedRoot = import_node_path2.default.resolve(options.root);
350
- 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;
987
+ const resolvedRoot = import_node_path5.default.resolve(options.root);
988
+ const consumerRoot = import_node_path5.default.basename(manifestRoot) === PRIMARY_CNOS_DIR || import_node_path5.default.basename(manifestRoot) === LEGACY_CNOS_DIR ? import_node_path5.default.dirname(manifestRoot) : resolvedRoot;
351
989
  return {
352
990
  manifestRoot,
353
- consumerRoot
991
+ consumerRoot,
992
+ rootResolution: {
993
+ rootUri: manifestRoot,
994
+ protocol: "local",
995
+ remote: false,
996
+ readOnly: false
997
+ }
354
998
  };
355
999
  }
356
- const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd());
1000
+ const discovered = await discoverCnosAnchor(options.cwd ?? process.cwd(), 3, {
1001
+ ...options.processEnv ? { processEnv: options.processEnv } : {},
1002
+ ...options.cacheMode ? { cacheMode: options.cacheMode } : {},
1003
+ ...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
1004
+ ...options.forceRefresh ? { forceRefresh: true } : {}
1005
+ });
357
1006
  return {
358
1007
  manifestRoot: discovered.manifestRoot,
359
1008
  consumerRoot: discovered.consumerRoot,
1009
+ rootResolution: discovered.rootResolution,
360
1010
  anchorPath: discovered.anchorPath,
361
1011
  ...discovered.workspace ? { workspace: discovered.workspace } : {}
362
1012
  };
363
1013
  }
364
1014
  function expandHomePath(targetPath) {
365
1015
  if (targetPath === "~") {
366
- return import_node_os.default.homedir();
1016
+ return import_node_os3.default.homedir();
367
1017
  }
368
1018
  if (targetPath.startsWith("~/") || targetPath.startsWith("~\\")) {
369
- return import_node_path2.default.join(import_node_os.default.homedir(), targetPath.slice(2));
1019
+ return import_node_path5.default.join(import_node_os3.default.homedir(), targetPath.slice(2));
370
1020
  }
371
1021
  return targetPath;
372
1022
  }
373
1023
  function resolveNamespaceDirectory(workspaceRoot, namespace, profile) {
374
1024
  const rootFolder = namespace === "value" ? "values" : namespace === "secret" ? "secrets" : namespace;
375
1025
  if (profile && profile !== "base") {
376
- return import_node_path2.default.resolve(workspaceRoot, "profiles", profile, rootFolder);
1026
+ return import_node_path5.default.resolve(workspaceRoot, "profiles", profile, rootFolder);
377
1027
  }
378
- return import_node_path2.default.resolve(workspaceRoot, rootFolder);
1028
+ return import_node_path5.default.resolve(workspaceRoot, rootFolder);
379
1029
  }
380
1030
  function resolveConfigDocumentPath(workspaceRoot, namespace, configPath, profile) {
381
1031
  const namespaceRoot = resolveNamespaceDirectory(workspaceRoot, namespace, profile);
382
1032
  const fileName = `${configPath.split(".").shift() ?? "app"}.yml`;
383
- return import_node_path2.default.resolve(namespaceRoot, fileName);
1033
+ return import_node_path5.default.resolve(namespaceRoot, fileName);
384
1034
  }
385
1035
 
386
1036
  // ../core/src/manifest/normalizeManifest.ts
@@ -434,6 +1084,13 @@ var DEFAULT_NAMESPACES = {
434
1084
  readonly: true
435
1085
  }
436
1086
  };
1087
+ var DEFAULT_RUNTIME_NAMESPACES = {
1088
+ process: {
1089
+ description: "Live process runtime values.",
1090
+ serverOnly: true,
1091
+ builtIn: true
1092
+ }
1093
+ };
437
1094
  function validateResolveFrom(resolveFrom) {
438
1095
  const validValues = ["cli.profile", "env.CNOS_PROFILE", "default"];
439
1096
  for (const entry of resolveFrom) {
@@ -456,7 +1113,7 @@ function normalizeWorkspaceItems(items) {
456
1113
  }
457
1114
  function normalizeNamespaces(namespaces) {
458
1115
  const normalized = Object.fromEntries(
459
- Object.entries(namespaces ?? {}).map(([namespace, definition]) => [
1116
+ Object.entries(namespaces ?? {}).filter(([namespace]) => namespace !== "runtime").map(([namespace, definition]) => [
460
1117
  namespace,
461
1118
  {
462
1119
  kind: definition.kind ?? "data",
@@ -472,6 +1129,29 @@ function normalizeNamespaces(namespaces) {
472
1129
  ...normalized
473
1130
  };
474
1131
  }
1132
+ function normalizeRuntimeNamespaces(namespaces) {
1133
+ const runtimeEntries = namespaces?.runtime ?? {};
1134
+ const normalized = Object.fromEntries(
1135
+ Object.entries(runtimeEntries).map(([namespace, definition]) => [
1136
+ namespace,
1137
+ {
1138
+ ...definition.description?.trim() ? {
1139
+ description: definition.description.trim()
1140
+ } : {},
1141
+ serverOnly: definition.server_only ?? true
1142
+ }
1143
+ ])
1144
+ );
1145
+ for (const namespace of Object.keys(normalized)) {
1146
+ if (DEFAULT_NAMESPACES[namespace] || namespace === "runtime") {
1147
+ throw new CnosManifestError(`Runtime namespace "${namespace}" conflicts with a built-in or reserved namespace.`);
1148
+ }
1149
+ }
1150
+ return {
1151
+ ...DEFAULT_RUNTIME_NAMESPACES,
1152
+ ...normalized
1153
+ };
1154
+ }
475
1155
  function normalizeVaults(vaults) {
476
1156
  return Object.fromEntries(
477
1157
  Object.entries(vaults ?? {}).map(([name, definition]) => {
@@ -563,6 +1243,7 @@ function normalizeManifest(manifest) {
563
1243
  const defaultProfile = manifest.profiles?.default?.trim() || "base";
564
1244
  const workspaceItems = normalizeWorkspaceItems(manifest.workspaces?.items);
565
1245
  const resolveFrom = validateResolveFrom(manifest.profiles?.resolveFrom ?? DEFAULT_RESOLVE_FROM);
1246
+ const runtimeNamespaces = normalizeRuntimeNamespaces(manifest.namespaces);
566
1247
  const filesystemValues = {
567
1248
  root: "./",
568
1249
  format: "yaml",
@@ -636,6 +1317,7 @@ function normalizeManifest(manifest) {
636
1317
  }
637
1318
  },
638
1319
  namespaces: normalizeNamespaces(manifest.namespaces),
1320
+ runtimeNamespaces,
639
1321
  vaults: normalizeVaults(manifest.vaults),
640
1322
  writePolicy: {
641
1323
  define: {
@@ -654,13 +1336,17 @@ function normalizeManifest(manifest) {
654
1336
  async function loadManifest(options = {}) {
655
1337
  const resolved = await resolveManifestRoot({
656
1338
  ...options.root ? { root: options.root } : {},
657
- ...options.cwd ? { cwd: options.cwd } : {}
1339
+ ...options.cwd ? { cwd: options.cwd } : {},
1340
+ ...options.processEnv ? { processEnv: options.processEnv } : {},
1341
+ ...options.cacheMode ? { cacheMode: options.cacheMode } : {},
1342
+ ...typeof options.cacheTtlSeconds === "number" ? { cacheTtlSeconds: options.cacheTtlSeconds } : {},
1343
+ ...options.forceRefresh ? { forceRefresh: true } : {}
658
1344
  });
659
1345
  const manifestRoot = resolved.manifestRoot;
660
- const manifestPath = import_node_path3.default.join(manifestRoot, "cnos.yml");
1346
+ const manifestPath = import_node_path6.default.join(manifestRoot, "cnos.yml");
661
1347
  let source;
662
1348
  try {
663
- source = await (0, import_promises3.readFile)(manifestPath, "utf8");
1349
+ source = await (0, import_promises5.readFile)(manifestPath, "utf8");
664
1350
  } catch {
665
1351
  throw new CnosManifestError("Unable to read CNOS manifest", manifestPath);
666
1352
  }
@@ -670,10 +1356,11 @@ async function loadManifest(options = {}) {
670
1356
  }
671
1357
  return {
672
1358
  manifestRoot,
673
- repoRoot: import_node_path3.default.dirname(manifestRoot),
1359
+ repoRoot: import_node_path6.default.dirname(manifestRoot),
674
1360
  consumerRoot: resolved.consumerRoot,
675
1361
  ...resolved.anchorPath ? { anchorPath: resolved.anchorPath } : {},
676
1362
  ...resolved.workspace ? { anchoredWorkspace: resolved.workspace } : {},
1363
+ rootResolution: resolved.rootResolution,
677
1364
  manifestPath,
678
1365
  manifest: normalizeManifest(rawManifest),
679
1366
  rawManifest
@@ -681,12 +1368,12 @@ async function loadManifest(options = {}) {
681
1368
  }
682
1369
 
683
1370
  // ../core/src/manifest/loadWorkspaceFile.ts
684
- var import_promises4 = require("fs/promises");
685
- var import_node_path4 = __toESM(require("path"), 1);
1371
+ var import_promises6 = require("fs/promises");
1372
+ var import_node_path7 = __toESM(require("path"), 1);
686
1373
 
687
1374
  // ../core/src/profiles/expandProfileChain.ts
688
- var import_promises5 = require("fs/promises");
689
- var import_node_path5 = __toESM(require("path"), 1);
1375
+ var import_promises7 = require("fs/promises");
1376
+ var import_node_path8 = __toESM(require("path"), 1);
690
1377
 
691
1378
  // ../core/src/promotions/validatePromotion.ts
692
1379
  var DEFAULT_DATA_NAMESPACE = {
@@ -737,42 +1424,42 @@ function validateProjectionIssue(manifest, key, target) {
737
1424
  }
738
1425
 
739
1426
  // ../core/src/workspaces/resolveWorkspaceContext.ts
740
- var import_promises6 = require("fs/promises");
741
- var import_node_path6 = __toESM(require("path"), 1);
1427
+ var import_promises8 = require("fs/promises");
1428
+ var import_node_path9 = __toESM(require("path"), 1);
742
1429
 
743
1430
  // ../core/src/secrets/auditLog.ts
744
- var import_promises9 = require("fs/promises");
745
- var import_node_path9 = __toESM(require("path"), 1);
1431
+ var import_promises11 = require("fs/promises");
1432
+ var import_node_path12 = __toESM(require("path"), 1);
746
1433
 
747
1434
  // ../core/src/utils/secretStore.ts
748
- var import_node_crypto = require("crypto");
749
- var import_promises8 = require("fs/promises");
750
- var import_node_path8 = __toESM(require("path"), 1);
1435
+ var import_node_crypto2 = require("crypto");
1436
+ var import_promises10 = require("fs/promises");
1437
+ var import_node_path11 = __toESM(require("path"), 1);
751
1438
 
752
1439
  // ../core/src/secrets/sessionStore.ts
753
- var import_promises7 = require("fs/promises");
754
- var import_node_path7 = __toESM(require("path"), 1);
1440
+ var import_promises9 = require("fs/promises");
1441
+ var import_node_path10 = __toESM(require("path"), 1);
755
1442
  function buildSessionRoot(processEnv = process.env) {
756
- return import_node_path7.default.join(import_node_path7.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
1443
+ return import_node_path10.default.join(import_node_path10.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets")), "sessions");
757
1444
  }
758
1445
  function buildSessionPath(vault, processEnv) {
759
- return import_node_path7.default.join(buildSessionRoot(processEnv), `${vault}.json`);
1446
+ return import_node_path10.default.join(buildSessionRoot(processEnv), `${vault}.json`);
760
1447
  }
761
1448
  async function writeVaultSessionKey(vault, derivedKey, processEnv) {
762
1449
  const filePath = buildSessionPath(vault, processEnv);
763
- await (0, import_promises7.mkdir)(import_node_path7.default.dirname(filePath), { recursive: true });
1450
+ await (0, import_promises9.mkdir)(import_node_path10.default.dirname(filePath), { recursive: true });
764
1451
  const document = {
765
1452
  version: 1,
766
1453
  vault,
767
1454
  derivedKey: derivedKey.toString("hex"),
768
1455
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
769
1456
  };
770
- await (0, import_promises7.writeFile)(filePath, JSON.stringify(document, null, 2), "utf8");
1457
+ await (0, import_promises9.writeFile)(filePath, JSON.stringify(document, null, 2), "utf8");
771
1458
  return filePath;
772
1459
  }
773
1460
  async function readVaultSessionKey(vault, processEnv) {
774
1461
  try {
775
- const source = await (0, import_promises7.readFile)(buildSessionPath(vault, processEnv), "utf8");
1462
+ const source = await (0, import_promises9.readFile)(buildSessionPath(vault, processEnv), "utf8");
776
1463
  const document = JSON.parse(source);
777
1464
  if (document.version !== 1 || typeof document.derivedKey !== "string") {
778
1465
  return void 0;
@@ -784,13 +1471,13 @@ async function readVaultSessionKey(vault, processEnv) {
784
1471
  }
785
1472
  }
786
1473
  async function clearVaultSessionKey(vault, processEnv) {
787
- await (0, import_promises7.rm)(buildSessionPath(vault, processEnv), { force: true });
1474
+ await (0, import_promises9.rm)(buildSessionPath(vault, processEnv), { force: true });
788
1475
  }
789
1476
  async function clearAllVaultSessionKeys(processEnv) {
790
1477
  const root = buildSessionRoot(processEnv);
791
1478
  try {
792
- const entries = await (0, import_promises7.readdir)(root);
793
- await Promise.all(entries.map((entry) => (0, import_promises7.rm)(import_node_path7.default.join(root, entry), { force: true })));
1479
+ const entries = await (0, import_promises9.readdir)(root);
1480
+ await Promise.all(entries.map((entry) => (0, import_promises9.rm)(import_node_path10.default.join(root, entry), { force: true })));
794
1481
  } catch {
795
1482
  }
796
1483
  }
@@ -812,7 +1499,7 @@ function isSecretReference(value) {
812
1499
  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));
813
1500
  }
814
1501
  function resolveSecretStoreRoot(processEnv = process.env) {
815
- return import_node_path8.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
1502
+ return import_node_path11.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
816
1503
  }
817
1504
  function normalizeVaultToken(vault = "default") {
818
1505
  return vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
@@ -844,22 +1531,22 @@ function resolveVaultSessionKey(vault = "default", processEnv = process.env) {
844
1531
  }
845
1532
  }
846
1533
  function deriveVaultKey(passphrase, salt, iterations = PBKDF2_ITERATIONS) {
847
- return (0, import_node_crypto.pbkdf2Sync)(passphrase, salt, iterations, KEY_LENGTH, "sha512");
1534
+ return (0, import_node_crypto2.pbkdf2Sync)(passphrase, salt, iterations, KEY_LENGTH, "sha512");
848
1535
  }
849
1536
  function buildMetaPath(storeRoot, vault = "default") {
850
- return import_node_path8.default.join(storeRoot, "vaults", vault, META_FILENAME);
1537
+ return import_node_path11.default.join(storeRoot, "vaults", vault, META_FILENAME);
851
1538
  }
852
1539
  function resolveSecretVaultFile(storeRoot, vault = "default") {
853
1540
  return buildMetaPath(storeRoot, vault);
854
1541
  }
855
1542
  function buildKeystorePath(storeRoot, vault = "default") {
856
- return import_node_path8.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
1543
+ return import_node_path11.default.join(storeRoot, "vaults", vault, KEYSTORE_FILENAME);
857
1544
  }
858
1545
  function buildLegacyVaultFile(storeRoot, vault = "default") {
859
- return import_node_path8.default.join(storeRoot, "vaults", `${vault}.json`);
1546
+ return import_node_path11.default.join(storeRoot, "vaults", `${vault}.json`);
860
1547
  }
861
1548
  function buildLegacyVaultStoreRoot(storeRoot, vault = "default") {
862
- return import_node_path8.default.join(storeRoot, "vaults", vault, "store");
1549
+ return import_node_path11.default.join(storeRoot, "vaults", vault, "store");
863
1550
  }
864
1551
  function assertVaultMetadata(value, filePath) {
865
1552
  if (!isObject(value)) {
@@ -872,7 +1559,7 @@ function assertVaultMetadata(value, filePath) {
872
1559
  }
873
1560
  async function exists3(targetPath) {
874
1561
  try {
875
- await (0, import_promises8.stat)(targetPath);
1562
+ await (0, import_promises10.stat)(targetPath);
876
1563
  return true;
877
1564
  } catch {
878
1565
  return false;
@@ -899,8 +1586,8 @@ async function assertNoLegacyVaultFormat(storeRoot, vault = "default") {
899
1586
  );
900
1587
  }
901
1588
  function encryptPayload(payload, key) {
902
- const iv = (0, import_node_crypto.randomBytes)(IV_LENGTH);
903
- const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", key, iv);
1589
+ const iv = (0, import_node_crypto2.randomBytes)(IV_LENGTH);
1590
+ const cipher = (0, import_node_crypto2.createCipheriv)("aes-256-gcm", key, iv);
904
1591
  const plaintext = Buffer.from(JSON.stringify(payload), "utf8");
905
1592
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
906
1593
  const tag = cipher.getAuthTag();
@@ -925,7 +1612,7 @@ function decryptPayload(buffer, key) {
925
1612
  const iv = buffer.subarray(ivOffset, tagOffset);
926
1613
  const tag = buffer.subarray(tagOffset, cipherOffset);
927
1614
  const ciphertext = buffer.subarray(cipherOffset);
928
- const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", key, iv);
1615
+ const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-gcm", key, iv);
929
1616
  decipher.setAuthTag(tag);
930
1617
  try {
931
1618
  const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
@@ -956,15 +1643,15 @@ function buildInitialPayload() {
956
1643
  async function writeVaultFiles(storeRoot, vault, meta, payload, key) {
957
1644
  const metaPath = buildMetaPath(storeRoot, vault);
958
1645
  const keystorePath = buildKeystorePath(storeRoot, vault);
959
- await (0, import_promises8.mkdir)(import_node_path8.default.dirname(metaPath), { recursive: true });
960
- await (0, import_promises8.writeFile)(metaPath, stringifyYaml(meta), "utf8");
961
- await (0, import_promises8.writeFile)(keystorePath, encryptPayload(payload, key));
1646
+ await (0, import_promises10.mkdir)(import_node_path11.default.dirname(metaPath), { recursive: true });
1647
+ await (0, import_promises10.writeFile)(metaPath, stringifyYaml(meta), "utf8");
1648
+ await (0, import_promises10.writeFile)(keystorePath, encryptPayload(payload, key));
962
1649
  }
963
1650
  async function readVaultMetadata(storeRoot, vault = "default") {
964
1651
  await assertNoLegacyVaultFormat(storeRoot, vault);
965
1652
  const metaPath = buildMetaPath(storeRoot, vault);
966
1653
  try {
967
- const source = await (0, import_promises8.readFile)(metaPath, "utf8");
1654
+ const source = await (0, import_promises10.readFile)(metaPath, "utf8");
968
1655
  return assertVaultMetadata(parseYaml(source), metaPath);
969
1656
  } catch (error) {
970
1657
  if (error.code === "ENOENT") {
@@ -974,11 +1661,11 @@ async function readVaultMetadata(storeRoot, vault = "default") {
974
1661
  }
975
1662
  }
976
1663
  async function listSecretVaults(storeRoot) {
977
- const vaultRoot = import_node_path8.default.join(storeRoot, "vaults");
1664
+ const vaultRoot = import_node_path11.default.join(storeRoot, "vaults");
978
1665
  try {
979
- const entries = await (0, import_promises8.readdir)(vaultRoot, { withFileTypes: true });
1666
+ const entries = await (0, import_promises10.readdir)(vaultRoot, { withFileTypes: true });
980
1667
  const vaults = await Promise.all(
981
- entries.filter((entry) => entry.isDirectory()).map(async (entry) => await exists3(import_node_path8.default.join(vaultRoot, entry.name, META_FILENAME)) ? entry.name : void 0)
1668
+ entries.filter((entry) => entry.isDirectory()).map(async (entry) => await exists3(import_node_path11.default.join(vaultRoot, entry.name, META_FILENAME)) ? entry.name : void 0)
982
1669
  );
983
1670
  return vaults.filter((value) => Boolean(value)).sort((left, right) => left.localeCompare(right));
984
1671
  } catch {
@@ -988,7 +1675,7 @@ async function listSecretVaults(storeRoot) {
988
1675
  async function createSecretVault(storeRoot, vault, passphrase) {
989
1676
  const normalizedVault = vault.trim() || "default";
990
1677
  await assertNoLegacyVaultFormat(storeRoot, normalizedVault);
991
- const salt = (0, import_node_crypto.randomBytes)(SALT_LENGTH);
1678
+ const salt = (0, import_node_crypto2.randomBytes)(SALT_LENGTH);
992
1679
  const key = deriveVaultKey(passphrase, salt, PBKDF2_ITERATIONS);
993
1680
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
994
1681
  const meta = {
@@ -1067,7 +1754,7 @@ async function loadVaultPayload(storeRoot, vault, auth) {
1067
1754
  if (!key) {
1068
1755
  throw new CnosAuthenticationError(`Vault "${vault}" requires authentication before access.`);
1069
1756
  }
1070
- const buffer = await (0, import_promises8.readFile)(buildKeystorePath(storeRoot, vault));
1757
+ const buffer = await (0, import_promises10.readFile)(buildKeystorePath(storeRoot, vault));
1071
1758
  return {
1072
1759
  meta,
1073
1760
  payload: decryptPayload(buffer, key),
@@ -1140,14 +1827,14 @@ function resolveVaultDefinition(vaults, vault = "default") {
1140
1827
  };
1141
1828
  }
1142
1829
  async function removeLocalVaultFiles(storeRoot, vault = "default") {
1143
- await (0, import_promises8.rm)(import_node_path8.default.join(storeRoot, "vaults", vault), { recursive: true, force: true });
1830
+ await (0, import_promises10.rm)(import_node_path11.default.join(storeRoot, "vaults", vault), { recursive: true, force: true });
1144
1831
  }
1145
1832
 
1146
1833
  // ../core/src/secrets/auditLog.ts
1147
1834
  async function appendAuditEvent(event, processEnv = process.env) {
1148
- const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path9.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
1149
- await (0, import_promises9.mkdir)(import_node_path9.default.dirname(auditFile), { recursive: true });
1150
- await (0, import_promises9.appendFile)(
1835
+ const auditFile = processEnv.CNOS_AUDIT_FILE ?? import_node_path12.default.join(resolveSecretStoreRoot(processEnv), "audit", "access.log");
1836
+ await (0, import_promises11.mkdir)(import_node_path12.default.dirname(auditFile), { recursive: true });
1837
+ await (0, import_promises11.appendFile)(
1151
1838
  auditFile,
1152
1839
  `${JSON.stringify({
1153
1840
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1414,11 +2101,11 @@ async function resolveVaultAuth(vaultId, definition, processEnv = process.env) {
1414
2101
  }
1415
2102
 
1416
2103
  // ../core/src/runtime/toServerProjection.ts
1417
- var import_node_crypto2 = require("crypto");
2104
+ var import_node_crypto3 = require("crypto");
1418
2105
 
1419
2106
  // ../core/src/runtime/dump.ts
1420
- var import_promises10 = require("fs/promises");
1421
- var import_node_path10 = __toESM(require("path"), 1);
2107
+ var import_promises12 = require("fs/promises");
2108
+ var import_node_path13 = __toESM(require("path"), 1);
1422
2109
 
1423
2110
  // ../core/src/utils/envNaming.ts
1424
2111
  function normalizeMappingConfig(config = {}) {
@@ -1430,8 +2117,8 @@ function normalizeMappingConfig(config = {}) {
1430
2117
  function toScreamingSnakeSegment(segment) {
1431
2118
  return segment.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1432
2119
  }
1433
- function toScreamingSnake(path14) {
1434
- return path14.split(".").map((segment) => toScreamingSnakeSegment(segment)).filter(Boolean).join("_");
2120
+ function toScreamingSnake(path17) {
2121
+ return path17.split(".").map((segment) => toScreamingSnakeSegment(segment)).filter(Boolean).join("_");
1435
2122
  }
1436
2123
  function logicalKeyToEnvVar(key, config = {}) {
1437
2124
  const normalized = normalizeMappingConfig(config);
@@ -1455,6 +2142,10 @@ function logicalKeyToEnvVar(key, config = {}) {
1455
2142
  function flattenObject(value, prefix = "") {
1456
2143
  return Object.entries(value).reduce((accumulator, [key, nestedValue]) => {
1457
2144
  const nextKey = prefix ? `${prefix}.${key}` : key;
2145
+ if (isDerivedValue(nestedValue) || isSecretReference(nestedValue)) {
2146
+ accumulator[nextKey] = nestedValue;
2147
+ return accumulator;
2148
+ }
1458
2149
  if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue)) {
1459
2150
  Object.assign(accumulator, flattenObject(nestedValue, nextKey));
1460
2151
  return accumulator;
@@ -1564,7 +2255,7 @@ async function validateRuntime(runtime) {
1564
2255
  }
1565
2256
 
1566
2257
  // src/runtime/bootstrap.ts
1567
- var import_node_crypto3 = require("crypto");
2258
+ var import_node_crypto4 = require("crypto");
1568
2259
  var CNOS_GRAPH_ENV_VAR = "__CNOS_GRAPH__";
1569
2260
  var CNOS_PROJECTION_ENV_VAR = "__CNOS_PROJECTION__";
1570
2261
  var CNOS_SECRET_PAYLOAD_ENV_VAR = "__CNOS_SECRET_PAYLOAD__";
@@ -1577,7 +2268,11 @@ function deserializeServerProjection(source) {
1577
2268
  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") {
1578
2269
  throw new Error("Invalid CNOS server projection payload");
1579
2270
  }
1580
- return payload;
2271
+ return {
2272
+ ...payload,
2273
+ derived: payload.derived && typeof payload.derived === "object" && !Array.isArray(payload.derived) ? payload.derived : {},
2274
+ runtimeNamespaces: Array.isArray(payload.runtimeNamespaces) ? payload.runtimeNamespaces : []
2275
+ };
1581
2276
  }
1582
2277
  function serializeRuntimeGraph(graph) {
1583
2278
  const payload = {
@@ -1622,15 +2317,15 @@ function decryptSecretPayload(serialized, sessionKey) {
1622
2317
  const iv = Buffer.from(payload.iv, "base64");
1623
2318
  const tag = Buffer.from(payload.tag, "base64");
1624
2319
  const ciphertext = Buffer.from(payload.ciphertext, "base64");
1625
- const decipher = (0, import_node_crypto3.createDecipheriv)("aes-256-gcm", key, iv);
2320
+ const decipher = (0, import_node_crypto4.createDecipheriv)("aes-256-gcm", key, iv);
1626
2321
  decipher.setAuthTag(tag);
1627
2322
  const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
1628
2323
  return JSON.parse(plaintext);
1629
2324
  }
1630
2325
  function serializeSecretPayload(values) {
1631
- const key = (0, import_node_crypto3.randomBytes)(32);
1632
- const iv = (0, import_node_crypto3.randomBytes)(12);
1633
- const cipher = (0, import_node_crypto3.createCipheriv)("aes-256-gcm", key, iv);
2326
+ const key = (0, import_node_crypto4.randomBytes)(32);
2327
+ const iv = (0, import_node_crypto4.randomBytes)(12);
2328
+ const cipher = (0, import_node_crypto4.createCipheriv)("aes-256-gcm", key, iv);
1634
2329
  const ciphertext = Buffer.concat([cipher.update(JSON.stringify(values), "utf8"), cipher.final()]);
1635
2330
  const tag = cipher.getAuthTag();
1636
2331
  return {
@@ -1703,10 +2398,10 @@ function buildNamespaceInterfaces(schema) {
1703
2398
  continue;
1704
2399
  }
1705
2400
  const namespace = logicalKey.slice(0, separatorIndex);
1706
- const path14 = logicalKey.slice(separatorIndex + 1);
2401
+ const path17 = logicalKey.slice(separatorIndex + 1);
1707
2402
  const existing = namespaceGroups.get(namespace) ?? [];
1708
2403
  existing.push({
1709
- key: path14,
2404
+ key: path17,
1710
2405
  rule
1711
2406
  });
1712
2407
  namespaceGroups.set(namespace, existing);
@@ -1811,15 +2506,15 @@ function generateCodegenContent(manifest, sourcePath, typeModuleImport = "./cnos
1811
2506
  }
1812
2507
 
1813
2508
  // src/codegen/writeOutput.ts
1814
- var import_promises11 = require("fs/promises");
1815
- var import_node_path11 = __toESM(require("path"), 1);
2509
+ var import_promises13 = require("fs/promises");
2510
+ var import_node_path14 = __toESM(require("path"), 1);
1816
2511
  function stripTsExtension(filePath) {
1817
2512
  return filePath.replace(/(\.d)?\.[cm]?tsx?$/i, "").replace(/\.[cm]?jsx?$/i, "");
1818
2513
  }
1819
2514
  function resolveCodegenPaths(repoRoot, out) {
1820
- const typesPath = out ? import_node_path11.default.resolve(repoRoot, out) : import_node_path11.default.join(repoRoot, ".cnos", "types", "cnos.d.ts");
1821
- const runtimePath = import_node_path11.default.join(import_node_path11.default.dirname(typesPath), "runtime.ts");
1822
- const typeImportPath = `./${import_node_path11.default.basename(stripTsExtension(typesPath))}`;
2515
+ const typesPath = out ? import_node_path14.default.resolve(repoRoot, out) : import_node_path14.default.join(repoRoot, ".cnos", "types", "cnos.d.ts");
2516
+ const runtimePath = import_node_path14.default.join(import_node_path14.default.dirname(typesPath), "runtime.ts");
2517
+ const typeImportPath = `./${import_node_path14.default.basename(stripTsExtension(typesPath))}`;
1823
2518
  return {
1824
2519
  typesPath,
1825
2520
  runtimePath,
@@ -1828,12 +2523,13 @@ function resolveCodegenPaths(repoRoot, out) {
1828
2523
  }
1829
2524
  async function writeCodegenOutput(options = {}) {
1830
2525
  const loadedManifest = await loadManifest(options.root ? { root: options.root } : {});
1831
- const paths = resolveCodegenPaths(loadedManifest.repoRoot, options.out);
2526
+ const outputRoot = loadedManifest.rootResolution.remote ? loadedManifest.consumerRoot : loadedManifest.repoRoot;
2527
+ const paths = resolveCodegenPaths(outputRoot, options.out);
1832
2528
  const generated = generateCodegenContent(loadedManifest.manifest, loadedManifest.manifestPath, paths.typeImportPath);
1833
- await (0, import_promises11.mkdir)(import_node_path11.default.dirname(paths.typesPath), { recursive: true });
1834
- await (0, import_promises11.mkdir)(import_node_path11.default.dirname(paths.runtimePath), { recursive: true });
1835
- await (0, import_promises11.writeFile)(paths.typesPath, generated.typesContent, "utf8");
1836
- await (0, import_promises11.writeFile)(paths.runtimePath, generated.runtimeContent, "utf8");
2529
+ await (0, import_promises13.mkdir)(import_node_path14.default.dirname(paths.typesPath), { recursive: true });
2530
+ await (0, import_promises13.mkdir)(import_node_path14.default.dirname(paths.runtimePath), { recursive: true });
2531
+ await (0, import_promises13.writeFile)(paths.typesPath, generated.typesContent, "utf8");
2532
+ await (0, import_promises13.writeFile)(paths.runtimePath, generated.runtimeContent, "utf8");
1837
2533
  return {
1838
2534
  manifestPath: loadedManifest.manifestPath,
1839
2535
  typesPath: paths.typesPath,
@@ -2019,7 +2715,7 @@ function formatDriftReport(report) {
2019
2715
  }
2020
2716
 
2021
2717
  // src/migrate/applyManifest.ts
2022
- var import_promises12 = require("fs/promises");
2718
+ var import_promises14 = require("fs/promises");
2023
2719
  function sortRecord(record) {
2024
2720
  return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
2025
2721
  }
@@ -2054,7 +2750,7 @@ async function applyManifestMappings(proposals, root) {
2054
2750
  promote: Array.from(promoted).sort((left, right) => left.localeCompare(right))
2055
2751
  };
2056
2752
  }
2057
- await (0, import_promises12.writeFile)(loadedManifest.manifestPath, stringifyYaml(rawManifest), "utf8");
2753
+ await (0, import_promises14.writeFile)(loadedManifest.manifestPath, stringifyYaml(rawManifest), "utf8");
2058
2754
  return {
2059
2755
  manifestPath: loadedManifest.manifestPath,
2060
2756
  appliedMappings,
@@ -2089,7 +2785,7 @@ function proposeMapping(envVar) {
2089
2785
  }
2090
2786
 
2091
2787
  // src/migrate/rewriteSource.ts
2092
- var import_promises13 = require("fs/promises");
2788
+ var import_promises15 = require("fs/promises");
2093
2789
  function importStatementFor(kind) {
2094
2790
  return kind === "import-meta-env" ? "import cnos from '@kitsy/cnos/browser';" : "import cnos from '@kitsy/cnos';";
2095
2791
  }
@@ -2110,7 +2806,7 @@ async function rewriteSourceFiles(usages, proposals) {
2110
2806
  const backupFiles = [];
2111
2807
  const skippedUsages = [];
2112
2808
  for (const [filePath, fileUsages] of fileGroups.entries()) {
2113
- const original = await (0, import_promises13.readFile)(filePath, "utf8");
2809
+ const original = await (0, import_promises15.readFile)(filePath, "utf8");
2114
2810
  let nextSource = original;
2115
2811
  let changed = false;
2116
2812
  const importKinds = /* @__PURE__ */ new Set();
@@ -2137,7 +2833,7 @@ async function rewriteSourceFiles(usages, proposals) {
2137
2833
  continue;
2138
2834
  }
2139
2835
  const backupPath = `${filePath}.bak`;
2140
- await (0, import_promises13.copyFile)(filePath, backupPath);
2836
+ await (0, import_promises15.copyFile)(filePath, backupPath);
2141
2837
  backupFiles.push(backupPath);
2142
2838
  for (const kind of Array.from(importKinds)) {
2143
2839
  const importStatement = importStatementFor(kind);
@@ -2146,7 +2842,7 @@ async function rewriteSourceFiles(usages, proposals) {
2146
2842
  ${nextSource}`;
2147
2843
  }
2148
2844
  }
2149
- await (0, import_promises13.writeFile)(filePath, nextSource, "utf8");
2845
+ await (0, import_promises15.writeFile)(filePath, nextSource, "utf8");
2150
2846
  rewrittenFiles.push(filePath);
2151
2847
  }
2152
2848
  return {
@@ -2157,18 +2853,18 @@ ${nextSource}`;
2157
2853
  }
2158
2854
 
2159
2855
  // src/migrate/scanEnvUsage.ts
2160
- var import_promises14 = require("fs/promises");
2161
- var import_node_path12 = __toESM(require("path"), 1);
2856
+ var import_promises16 = require("fs/promises");
2857
+ var import_node_path15 = __toESM(require("path"), 1);
2162
2858
  var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"]);
2163
2859
  var PROCESS_ENV_DOT = /process\.env\.([A-Z][A-Z0-9_]*)/g;
2164
2860
  var PROCESS_ENV_BRACKET = /process\.env\[['"]([A-Z][A-Z0-9_]*)['"]\]/g;
2165
2861
  var IMPORT_META_ENV_DOT = /import\.meta\.env\.([A-Z][A-Z0-9_]*)/g;
2166
2862
  var IMPORT_META_ENV_BRACKET = /import\.meta\.env\[['"]([A-Z][A-Z0-9_]*)['"]\]/g;
2167
2863
  async function collectFiles(root) {
2168
- const entries = await (0, import_promises14.readdir)(root, { withFileTypes: true });
2864
+ const entries = await (0, import_promises16.readdir)(root, { withFileTypes: true });
2169
2865
  const files = [];
2170
2866
  for (const entry of entries) {
2171
- const filePath = import_node_path12.default.join(root, entry.name);
2867
+ const filePath = import_node_path15.default.join(root, entry.name);
2172
2868
  if (entry.isDirectory()) {
2173
2869
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") {
2174
2870
  continue;
@@ -2176,7 +2872,7 @@ async function collectFiles(root) {
2176
2872
  files.push(...await collectFiles(filePath));
2177
2873
  continue;
2178
2874
  }
2179
- if (SOURCE_EXTENSIONS.has(import_node_path12.default.extname(entry.name))) {
2875
+ if (SOURCE_EXTENSIONS.has(import_node_path15.default.extname(entry.name))) {
2180
2876
  files.push(filePath);
2181
2877
  }
2182
2878
  }
@@ -2202,7 +2898,7 @@ async function scanEnvUsage(scanRoot) {
2202
2898
  const files = await collectFiles(scanRoot);
2203
2899
  const usages = [];
2204
2900
  for (const filePath of files) {
2205
- const source = await (0, import_promises14.readFile)(filePath, "utf8");
2901
+ const source = await (0, import_promises16.readFile)(filePath, "utf8");
2206
2902
  usages.push(...collectMatches(filePath, source, PROCESS_ENV_DOT, "process-env"));
2207
2903
  usages.push(...collectMatches(filePath, source, PROCESS_ENV_BRACKET, "process-env"));
2208
2904
  usages.push(...collectMatches(filePath, source, IMPORT_META_ENV_DOT, "import-meta-env"));
@@ -2243,7 +2939,7 @@ function diffGraphs(previous, next) {
2243
2939
  }
2244
2940
 
2245
2941
  // src/watch/watchFiles.ts
2246
- var import_node_path13 = __toESM(require("path"), 1);
2942
+ var import_node_path16 = __toESM(require("path"), 1);
2247
2943
  async function watchFiles(runtime, root) {
2248
2944
  const manifest = await loadManifest(root ? { root } : {});
2249
2945
  const roots = Array.from(
@@ -2251,7 +2947,7 @@ async function watchFiles(runtime, root) {
2251
2947
  ).sort((left, right) => left.localeCompare(right));
2252
2948
  const files = Array.from(
2253
2949
  new Set(
2254
- Array.from(runtime.graph.entries.values()).map((entry) => entry.winner.origin?.file).filter((file) => Boolean(file)).map((file) => import_node_path13.default.resolve(manifest.repoRoot, file))
2950
+ Array.from(runtime.graph.entries.values()).map((entry) => entry.winner.origin?.file).filter((file) => Boolean(file)).map((file) => import_node_path16.default.resolve(manifest.repoRoot, file))
2255
2951
  )
2256
2952
  ).sort((left, right) => left.localeCompare(right));
2257
2953
  return {
@@ -2272,6 +2968,7 @@ async function watchFiles(runtime, root) {
2272
2968
  clearAllVaultSessionKeys,
2273
2969
  clearVaultSessionKey,
2274
2970
  compareSchemaToGraph,
2971
+ createRemoteRootCacheKey,
2275
2972
  createSecretVault,
2276
2973
  createSecretVaultProvider,
2277
2974
  deleteLocalSecret,
@@ -2288,23 +2985,32 @@ async function watchFiles(runtime, root) {
2288
2985
  getVaultPassphraseEnvVar,
2289
2986
  getVaultSessionKeyEnvVar,
2290
2987
  graphRequiresSecretHydration,
2988
+ isDerivedValue,
2989
+ isImmutableGitRef,
2291
2990
  isPassphraseEnvRef,
2292
2991
  isSecretReference,
2293
2992
  listLocalSecrets,
2294
2993
  listSecretVaults,
2295
2994
  loadManifest,
2995
+ normalizeDerivedValue,
2996
+ parseDerivation,
2997
+ parseGitUri,
2296
2998
  parseYaml,
2297
2999
  proposeMapping,
2298
3000
  readKeychain,
2299
3001
  readLocalSecret,
3002
+ readRemoteRootCacheMetadata,
2300
3003
  readRuntimeGraphFromEnv,
2301
3004
  readServerProjectionFromEnv,
2302
3005
  readVaultMetadata,
2303
3006
  removeLocalVaultFiles,
3007
+ resolveCnosCacheRoot,
2304
3008
  resolveCodegenPaths,
2305
3009
  resolveConfigDocumentPath,
2306
3010
  resolveConfiguredVaultPassphrase,
2307
3011
  resolveManifestRoot,
3012
+ resolveRemoteRootCachePaths,
3013
+ resolveRootUri,
2308
3014
  resolveSecretPassphrase,
2309
3015
  resolveSecretStoreRoot,
2310
3016
  resolveSecretVaultFile,
@@ -2317,11 +3023,14 @@ async function watchFiles(runtime, root) {
2317
3023
  serializeSecretPayload,
2318
3024
  serializeServerProjection,
2319
3025
  stringifyYaml,
3026
+ validateDerivedTargetNamespace,
3027
+ validateParsedDerivation,
2320
3028
  validateRuntime,
2321
3029
  watchFiles,
2322
3030
  watchSchema,
2323
3031
  writeCodegenOutput,
2324
3032
  writeKeychain,
2325
3033
  writeLocalSecret,
3034
+ writeRemoteRootCacheMetadata,
2326
3035
  writeVaultSessionKey
2327
3036
  });