@kitsy/cnos 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1003,6 +1003,90 @@ function requireValue(graph, key) {
1003
1003
  return value;
1004
1004
  }
1005
1005
 
1006
+ // ../core/src/utils/secretStore.ts
1007
+ var import_node_crypto = require("crypto");
1008
+ var import_promises6 = require("fs/promises");
1009
+ var import_node_path6 = __toESM(require("path"), 1);
1010
+ function isObject(value) {
1011
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1012
+ }
1013
+ function isSecretReference(value) {
1014
+ 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));
1015
+ }
1016
+ function resolveSecretStoreRoot(processEnv = process.env) {
1017
+ return import_node_path6.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
1018
+ }
1019
+ function resolveSecretStoreFile(storeRoot, ref, vault = "default") {
1020
+ return import_node_path6.default.join(storeRoot, "vaults", vault, "store", ...ref.split("/")).concat(".json");
1021
+ }
1022
+ function deriveKey(passphrase, salt) {
1023
+ return (0, import_node_crypto.scryptSync)(passphrase, salt, 32);
1024
+ }
1025
+ function resolveSecretPassphrase(vault = "default", processEnv = process.env) {
1026
+ const vaultToken = vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1027
+ return processEnv[`CNOS_SECRET_PASSPHRASE_${vaultToken}`] ?? processEnv.CNOS_SECRET_PASSPHRASE;
1028
+ }
1029
+ function decryptDocument(document, passphrase) {
1030
+ const salt = Buffer.from(document.salt, "base64");
1031
+ const iv = Buffer.from(document.iv, "base64");
1032
+ const tag = Buffer.from(document.tag, "base64");
1033
+ const ciphertext = Buffer.from(document.ciphertext, "base64");
1034
+ const key = deriveKey(passphrase, salt);
1035
+ const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", key, iv);
1036
+ decipher.setAuthTag(tag);
1037
+ const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
1038
+ return plaintext.toString("utf8");
1039
+ }
1040
+ async function readLocalSecret(storeRoot, ref, passphrase, vault = "default") {
1041
+ if (!passphrase) {
1042
+ throw new CnosManifestError(
1043
+ `Missing CNOS secret passphrase for local secret ref "${ref}". Set CNOS_SECRET_PASSPHRASE or pass processEnv explicitly.`
1044
+ );
1045
+ }
1046
+ const filePath = resolveSecretStoreFile(storeRoot, ref, vault);
1047
+ const source = await (0, import_promises6.readFile)(filePath, "utf8");
1048
+ const document = JSON.parse(source);
1049
+ if (document.version !== 1 || document.algorithm !== "aes-256-gcm" || typeof document.salt !== "string" || typeof document.iv !== "string" || typeof document.tag !== "string" || typeof document.ciphertext !== "string") {
1050
+ throw new CnosManifestError("Invalid local secret document", filePath);
1051
+ }
1052
+ return decryptDocument(document, passphrase);
1053
+ }
1054
+
1055
+ // ../core/src/runtime/toEnv.ts
1056
+ function normalizeEnvValue(value) {
1057
+ if (value === void 0 || value === null) {
1058
+ return "";
1059
+ }
1060
+ if (typeof value === "string") {
1061
+ return value;
1062
+ }
1063
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
1064
+ return String(value);
1065
+ }
1066
+ return JSON.stringify(value);
1067
+ }
1068
+ function toEnv(graph, manifest, options = {}) {
1069
+ const includeSecrets = options.includeSecrets ?? true;
1070
+ const output = {};
1071
+ const mappedEntries = Object.entries(manifest.envMapping.explicit).sort(
1072
+ ([left], [right]) => left.localeCompare(right)
1073
+ );
1074
+ for (const [envVar, logicalKey] of mappedEntries) {
1075
+ const entry = graph.entries.get(logicalKey);
1076
+ if (!entry) {
1077
+ continue;
1078
+ }
1079
+ if (entry.namespace === "secret" && !includeSecrets) {
1080
+ continue;
1081
+ }
1082
+ if (isSecretReference(entry.value)) {
1083
+ continue;
1084
+ }
1085
+ output[envVar] = normalizeEnvValue(entry.value);
1086
+ }
1087
+ return output;
1088
+ }
1089
+
1006
1090
  // ../core/src/utils/envNaming.ts
1007
1091
  function normalizeMappingConfig(config = {}) {
1008
1092
  return {
@@ -1058,48 +1142,6 @@ function envVarToLogicalKey(envVar, config = {}) {
1058
1142
  return `value.${fromScreamingSnake(envVar)}`;
1059
1143
  }
1060
1144
 
1061
- // ../core/src/runtime/toEnv.ts
1062
- function fallbackLogicalKeyToEnvVar(key) {
1063
- if (key.startsWith("value.")) {
1064
- return key.slice("value.".length).replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1065
- }
1066
- if (key.startsWith("secret.")) {
1067
- const normalized = key.slice("secret.".length).replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1068
- return `SECRET_${normalized}`;
1069
- }
1070
- return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1071
- }
1072
- function normalizeEnvValue(value) {
1073
- if (value === void 0 || value === null) {
1074
- return "";
1075
- }
1076
- if (typeof value === "string") {
1077
- return value;
1078
- }
1079
- if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
1080
- return String(value);
1081
- }
1082
- return JSON.stringify(value);
1083
- }
1084
- function toEnv(graph, manifest, options = {}) {
1085
- const includeSecrets = options.includeSecrets ?? true;
1086
- const output = {};
1087
- const resolvedEntries = Array.from(graph.entries.values()).sort(
1088
- (left, right) => left.key.localeCompare(right.key)
1089
- );
1090
- for (const entry of resolvedEntries) {
1091
- if (entry.namespace === "meta") {
1092
- continue;
1093
- }
1094
- if (!includeSecrets && entry.namespace === "secret") {
1095
- continue;
1096
- }
1097
- const envVar = logicalKeyToEnvVar(entry.key, manifest.envMapping) ?? fallbackLogicalKeyToEnvVar(entry.key);
1098
- output[envVar] = normalizeEnvValue(entry.value);
1099
- }
1100
- return output;
1101
- }
1102
-
1103
1145
  // ../core/src/runtime/toPublicEnv.ts
1104
1146
  function fallbackValueEnvVar(key) {
1105
1147
  return key.replace(/^value\./, "").replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
@@ -1338,23 +1380,23 @@ async function createCnos(options = {}) {
1338
1380
  }
1339
1381
 
1340
1382
  // ../core/src/runtime/dump.ts
1341
- var import_promises6 = require("fs/promises");
1342
- var import_node_path6 = __toESM(require("path"), 1);
1383
+ var import_promises7 = require("fs/promises");
1384
+ var import_node_path7 = __toESM(require("path"), 1);
1343
1385
  function buildDumpFiles(graph, options = {}) {
1344
- const basePath = options.flatten ? "" : import_node_path6.default.posix.join("workspaces", graph.workspace.workspaceId);
1386
+ const basePath = options.flatten ? "" : import_node_path7.default.posix.join("workspaces", graph.workspace.workspaceId);
1345
1387
  const values = toNamespaceObject(graph, "value");
1346
1388
  const secrets = toNamespaceObject(graph, "secret");
1347
1389
  const files = [];
1348
1390
  if (Object.keys(values).length > 0) {
1349
1391
  files.push({
1350
- path: import_node_path6.default.posix.join(basePath, "values", graph.profile, "app.yml"),
1392
+ path: import_node_path7.default.posix.join(basePath, "values", graph.profile, "app.yml"),
1351
1393
  namespace: "value",
1352
1394
  content: stringifyYaml(values)
1353
1395
  });
1354
1396
  }
1355
1397
  if (Object.keys(secrets).length > 0) {
1356
1398
  files.push({
1357
- path: import_node_path6.default.posix.join(basePath, "secrets", graph.profile, "app.yml"),
1399
+ path: import_node_path7.default.posix.join(basePath, "secrets", graph.profile, "app.yml"),
1358
1400
  namespace: "secret",
1359
1401
  content: stringifyYaml(secrets)
1360
1402
  });
@@ -1370,12 +1412,12 @@ function planDump(graph, options = {}) {
1370
1412
  };
1371
1413
  }
1372
1414
  async function writeDump(graph, options) {
1373
- const root = import_node_path6.default.resolve(options.to);
1415
+ const root = import_node_path7.default.resolve(options.to);
1374
1416
  const plan = planDump(graph, options);
1375
1417
  for (const file of plan.files) {
1376
- const destination = import_node_path6.default.join(root, file.path);
1377
- await (0, import_promises6.mkdir)(import_node_path6.default.dirname(destination), { recursive: true });
1378
- await (0, import_promises6.writeFile)(destination, file.content, "utf8");
1418
+ const destination = import_node_path7.default.join(root, file.path);
1419
+ await (0, import_promises7.mkdir)(import_node_path7.default.dirname(destination), { recursive: true });
1420
+ await (0, import_promises7.writeFile)(destination, file.content, "utf8");
1379
1421
  }
1380
1422
  return {
1381
1423
  ...plan,
@@ -1383,55 +1425,10 @@ async function writeDump(graph, options) {
1383
1425
  };
1384
1426
  }
1385
1427
 
1386
- // ../core/src/utils/secretStore.ts
1387
- var import_node_crypto = require("crypto");
1388
- var import_promises7 = require("fs/promises");
1389
- var import_node_path7 = __toESM(require("path"), 1);
1390
- function isObject(value) {
1391
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1392
- }
1393
- function isSecretReference(value) {
1394
- return isObject(value) && typeof value.provider === "string" && value.provider.trim().length > 0 && typeof value.ref === "string" && value.ref.trim().length > 0 && Object.keys(value).every((key) => ["provider", "ref"].includes(key));
1395
- }
1396
- function resolveSecretStoreRoot(processEnv = process.env) {
1397
- return import_node_path7.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
1398
- }
1399
- function resolveSecretStoreFile(storeRoot, ref) {
1400
- return import_node_path7.default.join(storeRoot, "store", ...ref.split("/")).concat(".json");
1401
- }
1402
- function deriveKey(passphrase, salt) {
1403
- return (0, import_node_crypto.scryptSync)(passphrase, salt, 32);
1404
- }
1405
- function decryptDocument(document, passphrase) {
1406
- const salt = Buffer.from(document.salt, "base64");
1407
- const iv = Buffer.from(document.iv, "base64");
1408
- const tag = Buffer.from(document.tag, "base64");
1409
- const ciphertext = Buffer.from(document.ciphertext, "base64");
1410
- const key = deriveKey(passphrase, salt);
1411
- const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", key, iv);
1412
- decipher.setAuthTag(tag);
1413
- const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
1414
- return plaintext.toString("utf8");
1415
- }
1416
- async function readLocalSecret(storeRoot, ref, passphrase) {
1417
- if (!passphrase) {
1418
- throw new CnosManifestError(
1419
- `Missing CNOS secret passphrase for local secret ref "${ref}". Set CNOS_SECRET_PASSPHRASE or pass processEnv explicitly.`
1420
- );
1421
- }
1422
- const filePath = resolveSecretStoreFile(storeRoot, ref);
1423
- const source = await (0, import_promises7.readFile)(filePath, "utf8");
1424
- const document = JSON.parse(source);
1425
- if (document.version !== 1 || document.algorithm !== "aes-256-gcm" || typeof document.salt !== "string" || typeof document.iv !== "string" || typeof document.tag !== "string" || typeof document.ciphertext !== "string") {
1426
- throw new CnosManifestError("Invalid local secret document", filePath);
1427
- }
1428
- return decryptDocument(document, passphrase);
1429
- }
1430
-
1431
1428
  // package.json
1432
1429
  var package_default = {
1433
1430
  name: "@kitsy/cnos",
1434
- version: "1.0.1",
1431
+ version: "1.1.2",
1435
1432
  description: "Batteries-included CNOS runtime package wired with the official plugins.",
1436
1433
  type: "module",
1437
1434
  main: "./dist/index.cjs",
@@ -1504,10 +1501,11 @@ var package_default = {
1504
1501
  yaml: "^2.8.3"
1505
1502
  },
1506
1503
  scripts: {
1507
- build: "tsup --config tsup.config.ts",
1504
+ build: "rimraf dist && tsup --config tsup.config.ts",
1508
1505
  clean: "rimraf dist",
1509
1506
  dev: "tsup --config tsup.config.ts --watch",
1510
1507
  lint: "eslint src test",
1508
+ prepack: "pnpm build",
1511
1509
  test: "vitest run",
1512
1510
  typecheck: "tsc -p tsconfig.json --noEmit"
1513
1511
  }
@@ -1825,13 +1823,15 @@ async function resolveSecretValue(value, processEnv) {
1825
1823
  return value;
1826
1824
  }
1827
1825
  if (value.provider === "local") {
1828
- if (!processEnv?.CNOS_SECRET_PASSPHRASE) {
1826
+ const passphrase = resolveSecretPassphrase(value.vault, processEnv);
1827
+ if (!passphrase) {
1829
1828
  return value;
1830
1829
  }
1831
1830
  return readLocalSecret(
1832
1831
  resolveSecretStoreRoot(processEnv),
1833
1832
  value.ref,
1834
- processEnv?.CNOS_SECRET_PASSPHRASE
1833
+ passphrase,
1834
+ value.vault
1835
1835
  );
1836
1836
  }
1837
1837
  if (value.provider === "env") {
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  createBasicSchemaPlugin
3
- } from "./chunk-H65FPTDM.js";
3
+ } from "./chunk-JQGGSNCL.js";
4
4
  import {
5
5
  createCliArgsPlugin
6
- } from "./chunk-GGYIRIGU.js";
6
+ } from "./chunk-HOS4E7XO.js";
7
7
  import {
8
8
  createDotenvPlugin
9
- } from "./chunk-44JOQPSN.js";
9
+ } from "./chunk-IQOUWY6T.js";
10
10
  import {
11
11
  createEnvExportPlugin,
12
12
  createPublicEnvExportPlugin
13
- } from "./chunk-ASZ7I3JJ.js";
13
+ } from "./chunk-IHSV5AFX.js";
14
14
  import {
15
15
  createFilesystemSecretsPlugin,
16
16
  createFilesystemValuesPlugin
17
- } from "./chunk-KG6OZX5C.js";
17
+ } from "./chunk-7FBRVJD6.js";
18
18
  import {
19
19
  createProcessEnvPlugin
20
- } from "./chunk-CGTFH4QQ.js";
20
+ } from "./chunk-53HXUSM6.js";
21
21
  import {
22
22
  createCnos,
23
23
  createProvenanceInspector,
@@ -25,12 +25,12 @@ import {
25
25
  toEnv,
26
26
  toPublicEnv,
27
27
  writeDump
28
- } from "./chunk-K2T4R5WH.js";
28
+ } from "./chunk-33ZDYDQJ.js";
29
29
 
30
30
  // package.json
31
31
  var package_default = {
32
32
  name: "@kitsy/cnos",
33
- version: "1.0.1",
33
+ version: "1.1.2",
34
34
  description: "Batteries-included CNOS runtime package wired with the official plugins.",
35
35
  type: "module",
36
36
  main: "./dist/index.cjs",
@@ -103,10 +103,11 @@ var package_default = {
103
103
  yaml: "^2.8.3"
104
104
  },
105
105
  scripts: {
106
- build: "tsup --config tsup.config.ts",
106
+ build: "rimraf dist && tsup --config tsup.config.ts",
107
107
  clean: "rimraf dist",
108
108
  dev: "tsup --config tsup.config.ts --watch",
109
109
  lint: "eslint src test",
110
+ prepack: "pnpm build",
110
111
  test: "vitest run",
111
112
  typecheck: "tsc -p tsconfig.json --noEmit"
112
113
  }
package/dist/internal.cjs CHANGED
@@ -30,10 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/internal.ts
31
31
  var internal_exports = {};
32
32
  __export(internal_exports, {
33
+ createSecretVault: () => createSecretVault,
33
34
  flattenObject: () => flattenObject,
35
+ listSecretVaults: () => listSecretVaults,
34
36
  parseYaml: () => parseYaml,
35
37
  resolveConfigDocumentPath: () => resolveConfigDocumentPath,
38
+ resolveSecretPassphrase: () => resolveSecretPassphrase,
36
39
  resolveSecretStoreRoot: () => resolveSecretStoreRoot,
40
+ resolveSecretVaultFile: () => resolveSecretVaultFile,
37
41
  stringifyYaml: () => stringifyYaml,
38
42
  validateRuntime: () => validateRuntime,
39
43
  writeLocalSecret: () => writeLocalSecret
@@ -91,6 +95,85 @@ var import_node_path4 = __toESM(require("path"), 1);
91
95
  var import_promises5 = require("fs/promises");
92
96
  var import_node_path5 = __toESM(require("path"), 1);
93
97
 
98
+ // ../core/src/utils/secretStore.ts
99
+ var import_node_crypto = require("crypto");
100
+ var import_promises6 = require("fs/promises");
101
+ var import_node_path6 = __toESM(require("path"), 1);
102
+ function resolveSecretStoreRoot(processEnv = process.env) {
103
+ return import_node_path6.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
104
+ }
105
+ function resolveSecretVaultFile(storeRoot, vault = "default") {
106
+ return import_node_path6.default.join(storeRoot, "vaults", `${vault}.json`);
107
+ }
108
+ function resolveSecretStoreFile(storeRoot, ref, vault = "default") {
109
+ return import_node_path6.default.join(storeRoot, "vaults", vault, "store", ...ref.split("/")).concat(".json");
110
+ }
111
+ function deriveKey(passphrase, salt) {
112
+ return (0, import_node_crypto.scryptSync)(passphrase, salt, 32);
113
+ }
114
+ function resolveSecretPassphrase(vault = "default", processEnv = process.env) {
115
+ const vaultToken = vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
116
+ return processEnv[`CNOS_SECRET_PASSPHRASE_${vaultToken}`] ?? processEnv.CNOS_SECRET_PASSPHRASE;
117
+ }
118
+ function encryptDocument(value, passphrase) {
119
+ const salt = (0, import_node_crypto.randomBytes)(16);
120
+ const iv = (0, import_node_crypto.randomBytes)(12);
121
+ const key = deriveKey(passphrase, salt);
122
+ const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", key, iv);
123
+ const ciphertext = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
124
+ const tag = cipher.getAuthTag();
125
+ return {
126
+ version: 1,
127
+ algorithm: "aes-256-gcm",
128
+ salt: salt.toString("base64"),
129
+ iv: iv.toString("base64"),
130
+ tag: tag.toString("base64"),
131
+ ciphertext: ciphertext.toString("base64")
132
+ };
133
+ }
134
+ async function createSecretVault(storeRoot, vault, passphrase) {
135
+ const normalizedVault = vault.trim() || "default";
136
+ const filePath = resolveSecretVaultFile(storeRoot, normalizedVault);
137
+ await (0, import_promises6.mkdir)(import_node_path6.default.dirname(filePath), { recursive: true });
138
+ const document = {
139
+ version: 1,
140
+ name: normalizedVault,
141
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
142
+ verifier: encryptDocument(`cnos-vault:${normalizedVault}`, passphrase)
143
+ };
144
+ await (0, import_promises6.writeFile)(filePath, JSON.stringify(document, null, 2), "utf8");
145
+ return filePath;
146
+ }
147
+ async function ensureSecretVault(storeRoot, vault, passphrase) {
148
+ const normalizedVault = vault.trim() || "default";
149
+ const filePath = resolveSecretVaultFile(storeRoot, normalizedVault);
150
+ try {
151
+ await (0, import_promises6.readFile)(filePath, "utf8");
152
+ return filePath;
153
+ } catch (error) {
154
+ if (error.code !== "ENOENT") {
155
+ throw error;
156
+ }
157
+ }
158
+ return createSecretVault(storeRoot, normalizedVault, passphrase);
159
+ }
160
+ async function listSecretVaults(storeRoot) {
161
+ const vaultRoot = import_node_path6.default.join(storeRoot, "vaults");
162
+ try {
163
+ const entries = await (0, import_promises6.readdir)(vaultRoot, { withFileTypes: true });
164
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.replace(/\.json$/, "")).sort((left, right) => left.localeCompare(right));
165
+ } catch {
166
+ return [];
167
+ }
168
+ }
169
+ async function writeLocalSecret(storeRoot, ref, value, passphrase, vault = "default") {
170
+ await ensureSecretVault(storeRoot, vault, passphrase);
171
+ const filePath = resolveSecretStoreFile(storeRoot, ref, vault);
172
+ await (0, import_promises6.mkdir)(import_node_path6.default.dirname(filePath), { recursive: true });
173
+ await (0, import_promises6.writeFile)(filePath, JSON.stringify(encryptDocument(value, passphrase), null, 2), "utf8");
174
+ return filePath;
175
+ }
176
+
94
177
  // ../core/src/utils/envNaming.ts
95
178
  function normalizeMappingConfig(config = {}) {
96
179
  return {
@@ -123,8 +206,8 @@ function logicalKeyToEnvVar(key, config = {}) {
123
206
  }
124
207
 
125
208
  // ../core/src/runtime/dump.ts
126
- var import_promises6 = require("fs/promises");
127
- var import_node_path6 = __toESM(require("path"), 1);
209
+ var import_promises7 = require("fs/promises");
210
+ var import_node_path7 = __toESM(require("path"), 1);
128
211
 
129
212
  // ../core/src/utils/flatten.ts
130
213
  function flattenObject(value, prefix = "") {
@@ -139,42 +222,6 @@ function flattenObject(value, prefix = "") {
139
222
  }, {});
140
223
  }
141
224
 
142
- // ../core/src/utils/secretStore.ts
143
- var import_node_crypto = require("crypto");
144
- var import_promises7 = require("fs/promises");
145
- var import_node_path7 = __toESM(require("path"), 1);
146
- function resolveSecretStoreRoot(processEnv = process.env) {
147
- return import_node_path7.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
148
- }
149
- function resolveSecretStoreFile(storeRoot, ref) {
150
- return import_node_path7.default.join(storeRoot, "store", ...ref.split("/")).concat(".json");
151
- }
152
- function deriveKey(passphrase, salt) {
153
- return (0, import_node_crypto.scryptSync)(passphrase, salt, 32);
154
- }
155
- function encryptDocument(value, passphrase) {
156
- const salt = (0, import_node_crypto.randomBytes)(16);
157
- const iv = (0, import_node_crypto.randomBytes)(12);
158
- const key = deriveKey(passphrase, salt);
159
- const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", key, iv);
160
- const ciphertext = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
161
- const tag = cipher.getAuthTag();
162
- return {
163
- version: 1,
164
- algorithm: "aes-256-gcm",
165
- salt: salt.toString("base64"),
166
- iv: iv.toString("base64"),
167
- tag: tag.toString("base64"),
168
- ciphertext: ciphertext.toString("base64")
169
- };
170
- }
171
- async function writeLocalSecret(storeRoot, ref, value, passphrase) {
172
- const filePath = resolveSecretStoreFile(storeRoot, ref);
173
- await (0, import_promises7.mkdir)(import_node_path7.default.dirname(filePath), { recursive: true });
174
- await (0, import_promises7.writeFile)(filePath, JSON.stringify(encryptDocument(value, passphrase), null, 2), "utf8");
175
- return filePath;
176
- }
177
-
178
225
  // ../core/src/validation/envMapping.ts
179
226
  function fallbackLogicalKeyToEnvVar(key) {
180
227
  return key.replace(/^(value|secret)\./, "").replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
@@ -278,10 +325,14 @@ async function validateRuntime(runtime) {
278
325
  }
279
326
  // Annotate the CommonJS export names for ESM import in node:
280
327
  0 && (module.exports = {
328
+ createSecretVault,
281
329
  flattenObject,
330
+ listSecretVaults,
282
331
  parseYaml,
283
332
  resolveConfigDocumentPath,
333
+ resolveSecretPassphrase,
284
334
  resolveSecretStoreRoot,
335
+ resolveSecretVaultFile,
285
336
  stringifyYaml,
286
337
  validateRuntime,
287
338
  writeLocalSecret
@@ -8,13 +8,18 @@ declare function resolveConfigDocumentPath(workspaceRoot: string, namespace: 'va
8
8
  interface SecretReference {
9
9
  provider: string;
10
10
  ref: string;
11
+ vault?: string;
11
12
  }
12
13
  declare function resolveSecretStoreRoot(processEnv?: Record<string, string | undefined>): string;
13
- declare function writeLocalSecret(storeRoot: string, ref: string, value: string, passphrase: string): Promise<string>;
14
+ declare function resolveSecretVaultFile(storeRoot: string, vault?: string): string;
15
+ declare function resolveSecretPassphrase(vault?: string, processEnv?: Record<string, string | undefined>): string | undefined;
16
+ declare function createSecretVault(storeRoot: string, vault: string, passphrase: string): Promise<string>;
17
+ declare function listSecretVaults(storeRoot: string): Promise<string[]>;
18
+ declare function writeLocalSecret(storeRoot: string, ref: string, value: string, passphrase: string, vault?: string): Promise<string>;
14
19
 
15
20
  declare function parseYaml<T>(source: string): T;
16
21
  declare function stringifyYaml(value: unknown): string;
17
22
 
18
23
  declare function validateRuntime(runtime: CnosRuntime): Promise<ValidationSummary>;
19
24
 
20
- export { type SecretReference, ValidationSummary, flattenObject, parseYaml, resolveConfigDocumentPath, resolveSecretStoreRoot, stringifyYaml, validateRuntime, writeLocalSecret };
25
+ export { type SecretReference, ValidationSummary, createSecretVault, flattenObject, listSecretVaults, parseYaml, resolveConfigDocumentPath, resolveSecretPassphrase, resolveSecretStoreRoot, resolveSecretVaultFile, stringifyYaml, validateRuntime, writeLocalSecret };
@@ -8,13 +8,18 @@ declare function resolveConfigDocumentPath(workspaceRoot: string, namespace: 'va
8
8
  interface SecretReference {
9
9
  provider: string;
10
10
  ref: string;
11
+ vault?: string;
11
12
  }
12
13
  declare function resolveSecretStoreRoot(processEnv?: Record<string, string | undefined>): string;
13
- declare function writeLocalSecret(storeRoot: string, ref: string, value: string, passphrase: string): Promise<string>;
14
+ declare function resolveSecretVaultFile(storeRoot: string, vault?: string): string;
15
+ declare function resolveSecretPassphrase(vault?: string, processEnv?: Record<string, string | undefined>): string | undefined;
16
+ declare function createSecretVault(storeRoot: string, vault: string, passphrase: string): Promise<string>;
17
+ declare function listSecretVaults(storeRoot: string): Promise<string[]>;
18
+ declare function writeLocalSecret(storeRoot: string, ref: string, value: string, passphrase: string, vault?: string): Promise<string>;
14
19
 
15
20
  declare function parseYaml<T>(source: string): T;
16
21
  declare function stringifyYaml(value: unknown): string;
17
22
 
18
23
  declare function validateRuntime(runtime: CnosRuntime): Promise<ValidationSummary>;
19
24
 
20
- export { type SecretReference, ValidationSummary, flattenObject, parseYaml, resolveConfigDocumentPath, resolveSecretStoreRoot, stringifyYaml, validateRuntime, writeLocalSecret };
25
+ export { type SecretReference, ValidationSummary, createSecretVault, flattenObject, listSecretVaults, parseYaml, resolveConfigDocumentPath, resolveSecretPassphrase, resolveSecretStoreRoot, resolveSecretVaultFile, stringifyYaml, validateRuntime, writeLocalSecret };
package/dist/internal.js CHANGED
@@ -1,17 +1,25 @@
1
1
  import {
2
+ createSecretVault,
2
3
  flattenObject,
4
+ listSecretVaults,
3
5
  parseYaml,
4
6
  resolveConfigDocumentPath,
7
+ resolveSecretPassphrase,
5
8
  resolveSecretStoreRoot,
9
+ resolveSecretVaultFile,
6
10
  stringifyYaml,
7
11
  validateRuntime,
8
12
  writeLocalSecret
9
- } from "./chunk-K2T4R5WH.js";
13
+ } from "./chunk-33ZDYDQJ.js";
10
14
  export {
15
+ createSecretVault,
11
16
  flattenObject,
17
+ listSecretVaults,
12
18
  parseYaml,
13
19
  resolveConfigDocumentPath,
20
+ resolveSecretPassphrase,
14
21
  resolveSecretStoreRoot,
22
+ resolveSecretVaultFile,
15
23
  stringifyYaml,
16
24
  validateRuntime,
17
25
  writeLocalSecret
@@ -205,12 +205,12 @@ function applySchemaRules(graph, schema) {
205
205
  };
206
206
  }
207
207
 
208
- // ../core/src/runtime/dump.ts
208
+ // ../core/src/utils/secretStore.ts
209
+ var import_node_crypto = require("crypto");
209
210
  var import_promises6 = require("fs/promises");
210
211
  var import_node_path6 = __toESM(require("path"), 1);
211
212
 
212
- // ../core/src/utils/secretStore.ts
213
- var import_node_crypto = require("crypto");
213
+ // ../core/src/runtime/dump.ts
214
214
  var import_promises7 = require("fs/promises");
215
215
  var import_node_path7 = __toESM(require("path"), 1);
216
216
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createBasicSchemaPlugin
3
- } from "../chunk-H65FPTDM.js";
4
- import "../chunk-K2T4R5WH.js";
3
+ } from "../chunk-JQGGSNCL.js";
4
+ import "../chunk-33ZDYDQJ.js";
5
5
  export {
6
6
  createBasicSchemaPlugin
7
7
  };
@@ -63,12 +63,12 @@ var import_node_path4 = __toESM(require("path"), 1);
63
63
  var import_promises5 = require("fs/promises");
64
64
  var import_node_path5 = __toESM(require("path"), 1);
65
65
 
66
- // ../core/src/runtime/dump.ts
66
+ // ../core/src/utils/secretStore.ts
67
+ var import_node_crypto = require("crypto");
67
68
  var import_promises6 = require("fs/promises");
68
69
  var import_node_path6 = __toESM(require("path"), 1);
69
70
 
70
- // ../core/src/utils/secretStore.ts
71
- var import_node_crypto = require("crypto");
71
+ // ../core/src/runtime/dump.ts
72
72
  var import_promises7 = require("fs/promises");
73
73
  var import_node_path7 = __toESM(require("path"), 1);
74
74
 
@@ -2,8 +2,8 @@ import {
2
2
  cliArgEntriesFromArgs,
3
3
  createCliArgsPlugin,
4
4
  parseCliArgs
5
- } from "../chunk-GGYIRIGU.js";
6
- import "../chunk-K2T4R5WH.js";
5
+ } from "../chunk-HOS4E7XO.js";
6
+ import "../chunk-33ZDYDQJ.js";
7
7
  export {
8
8
  cliArgEntriesFromArgs,
9
9
  createCliArgsPlugin,
@@ -89,6 +89,11 @@ var import_node_path4 = __toESM(require("path"), 1);
89
89
  var import_promises5 = require("fs/promises");
90
90
  var import_node_path5 = __toESM(require("path"), 1);
91
91
 
92
+ // ../core/src/utils/secretStore.ts
93
+ var import_node_crypto = require("crypto");
94
+ var import_promises6 = require("fs/promises");
95
+ var import_node_path6 = __toESM(require("path"), 1);
96
+
92
97
  // ../core/src/utils/envNaming.ts
93
98
  function normalizeMappingConfig(config = {}) {
94
99
  return {
@@ -122,11 +127,6 @@ function envVarToLogicalKey(envVar, config = {}) {
122
127
  }
123
128
 
124
129
  // ../core/src/runtime/dump.ts
125
- var import_promises6 = require("fs/promises");
126
- var import_node_path6 = __toESM(require("path"), 1);
127
-
128
- // ../core/src/utils/secretStore.ts
129
- var import_node_crypto = require("crypto");
130
130
  var import_promises7 = require("fs/promises");
131
131
  var import_node_path7 = __toESM(require("path"), 1);
132
132
 
@@ -2,8 +2,8 @@ import {
2
2
  createDotenvPlugin,
3
3
  dotenvEntriesFromObject,
4
4
  parseDotenv
5
- } from "../chunk-44JOQPSN.js";
6
- import "../chunk-K2T4R5WH.js";
5
+ } from "../chunk-IQOUWY6T.js";
6
+ import "../chunk-33ZDYDQJ.js";
7
7
  export {
8
8
  createDotenvPlugin,
9
9
  dotenvEntriesFromObject,