@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.
@@ -76,6 +76,52 @@ var import_node_path4 = __toESM(require("path"), 1);
76
76
  var import_promises5 = require("fs/promises");
77
77
  var import_node_path5 = __toESM(require("path"), 1);
78
78
 
79
+ // ../core/src/utils/secretStore.ts
80
+ var import_node_crypto = require("crypto");
81
+ var import_promises6 = require("fs/promises");
82
+ var import_node_path6 = __toESM(require("path"), 1);
83
+ function isObject(value) {
84
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
85
+ }
86
+ function isSecretReference(value) {
87
+ 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));
88
+ }
89
+
90
+ // ../core/src/runtime/toEnv.ts
91
+ function normalizeEnvValue(value) {
92
+ if (value === void 0 || value === null) {
93
+ return "";
94
+ }
95
+ if (typeof value === "string") {
96
+ return value;
97
+ }
98
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
99
+ return String(value);
100
+ }
101
+ return JSON.stringify(value);
102
+ }
103
+ function toEnv(graph, manifest, options = {}) {
104
+ const includeSecrets = options.includeSecrets ?? true;
105
+ const output = {};
106
+ const mappedEntries = Object.entries(manifest.envMapping.explicit).sort(
107
+ ([left], [right]) => left.localeCompare(right)
108
+ );
109
+ for (const [envVar, logicalKey] of mappedEntries) {
110
+ const entry = graph.entries.get(logicalKey);
111
+ if (!entry) {
112
+ continue;
113
+ }
114
+ if (entry.namespace === "secret" && !includeSecrets) {
115
+ continue;
116
+ }
117
+ if (isSecretReference(entry.value)) {
118
+ continue;
119
+ }
120
+ output[envVar] = normalizeEnvValue(entry.value);
121
+ }
122
+ return output;
123
+ }
124
+
79
125
  // ../core/src/utils/envNaming.ts
80
126
  function normalizeMappingConfig(config = {}) {
81
127
  return {
@@ -107,48 +153,6 @@ function logicalKeyToEnvVar(key, config = {}) {
107
153
  return void 0;
108
154
  }
109
155
 
110
- // ../core/src/runtime/toEnv.ts
111
- function fallbackLogicalKeyToEnvVar(key) {
112
- if (key.startsWith("value.")) {
113
- 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();
114
- }
115
- if (key.startsWith("secret.")) {
116
- 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();
117
- return `SECRET_${normalized}`;
118
- }
119
- return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
120
- }
121
- function normalizeEnvValue(value) {
122
- if (value === void 0 || value === null) {
123
- return "";
124
- }
125
- if (typeof value === "string") {
126
- return value;
127
- }
128
- if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
129
- return String(value);
130
- }
131
- return JSON.stringify(value);
132
- }
133
- function toEnv(graph, manifest, options = {}) {
134
- const includeSecrets = options.includeSecrets ?? true;
135
- const output = {};
136
- const resolvedEntries = Array.from(graph.entries.values()).sort(
137
- (left, right) => left.key.localeCompare(right.key)
138
- );
139
- for (const entry of resolvedEntries) {
140
- if (entry.namespace === "meta") {
141
- continue;
142
- }
143
- if (!includeSecrets && entry.namespace === "secret") {
144
- continue;
145
- }
146
- const envVar = logicalKeyToEnvVar(entry.key, manifest.envMapping) ?? fallbackLogicalKeyToEnvVar(entry.key);
147
- output[envVar] = normalizeEnvValue(entry.value);
148
- }
149
- return output;
150
- }
151
-
152
156
  // ../core/src/runtime/toPublicEnv.ts
153
157
  function fallbackValueEnvVar(key) {
154
158
  return key.replace(/^value\./, "").replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
@@ -201,11 +205,6 @@ function toPublicEnv(graph, manifest, options = {}) {
201
205
  }
202
206
 
203
207
  // ../core/src/runtime/dump.ts
204
- var import_promises6 = require("fs/promises");
205
- var import_node_path6 = __toESM(require("path"), 1);
206
-
207
- // ../core/src/utils/secretStore.ts
208
- var import_node_crypto = require("crypto");
209
208
  var import_promises7 = require("fs/promises");
210
209
  var import_node_path7 = __toESM(require("path"), 1);
211
210
 
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createEnvExportPlugin,
3
3
  createPublicEnvExportPlugin
4
- } from "../chunk-ASZ7I3JJ.js";
4
+ } from "../chunk-IHSV5AFX.js";
5
5
  import {
6
6
  toEnv,
7
7
  toPublicEnv
8
- } from "../chunk-K2T4R5WH.js";
8
+ } from "../chunk-33ZDYDQJ.js";
9
9
  export {
10
10
  createEnvExportPlugin,
11
11
  createPublicEnvExportPlugin,
@@ -100,29 +100,29 @@ var import_node_path4 = __toESM(require("path"), 1);
100
100
  var import_promises5 = require("fs/promises");
101
101
  var import_node_path5 = __toESM(require("path"), 1);
102
102
 
103
- // ../core/src/runtime/dump.ts
104
- var import_promises6 = require("fs/promises");
105
- var import_node_path6 = __toESM(require("path"), 1);
106
-
107
103
  // ../core/src/utils/secretStore.ts
108
104
  var import_node_crypto = require("crypto");
109
- var import_promises7 = require("fs/promises");
110
- var import_node_path7 = __toESM(require("path"), 1);
105
+ var import_promises6 = require("fs/promises");
106
+ var import_node_path6 = __toESM(require("path"), 1);
111
107
  function isObject(value) {
112
108
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
113
109
  }
114
110
  function isSecretReference(value) {
115
- 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));
111
+ 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));
116
112
  }
117
113
  function resolveSecretStoreRoot(processEnv = process.env) {
118
- return import_node_path7.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
114
+ return import_node_path6.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
119
115
  }
120
- function resolveSecretStoreFile(storeRoot, ref) {
121
- return import_node_path7.default.join(storeRoot, "store", ...ref.split("/")).concat(".json");
116
+ function resolveSecretStoreFile(storeRoot, ref, vault = "default") {
117
+ return import_node_path6.default.join(storeRoot, "vaults", vault, "store", ...ref.split("/")).concat(".json");
122
118
  }
123
119
  function deriveKey(passphrase, salt) {
124
120
  return (0, import_node_crypto.scryptSync)(passphrase, salt, 32);
125
121
  }
122
+ function resolveSecretPassphrase(vault = "default", processEnv = process.env) {
123
+ const vaultToken = vault.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
124
+ return processEnv[`CNOS_SECRET_PASSPHRASE_${vaultToken}`] ?? processEnv.CNOS_SECRET_PASSPHRASE;
125
+ }
126
126
  function decryptDocument(document, passphrase) {
127
127
  const salt = Buffer.from(document.salt, "base64");
128
128
  const iv = Buffer.from(document.iv, "base64");
@@ -134,14 +134,14 @@ function decryptDocument(document, passphrase) {
134
134
  const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
135
135
  return plaintext.toString("utf8");
136
136
  }
137
- async function readLocalSecret(storeRoot, ref, passphrase) {
137
+ async function readLocalSecret(storeRoot, ref, passphrase, vault = "default") {
138
138
  if (!passphrase) {
139
139
  throw new CnosManifestError(
140
140
  `Missing CNOS secret passphrase for local secret ref "${ref}". Set CNOS_SECRET_PASSPHRASE or pass processEnv explicitly.`
141
141
  );
142
142
  }
143
- const filePath = resolveSecretStoreFile(storeRoot, ref);
144
- const source = await (0, import_promises7.readFile)(filePath, "utf8");
143
+ const filePath = resolveSecretStoreFile(storeRoot, ref, vault);
144
+ const source = await (0, import_promises6.readFile)(filePath, "utf8");
145
145
  const document = JSON.parse(source);
146
146
  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") {
147
147
  throw new CnosManifestError("Invalid local secret document", filePath);
@@ -149,6 +149,10 @@ async function readLocalSecret(storeRoot, ref, passphrase) {
149
149
  return decryptDocument(document, passphrase);
150
150
  }
151
151
 
152
+ // ../core/src/runtime/dump.ts
153
+ var import_promises7 = require("fs/promises");
154
+ var import_node_path7 = __toESM(require("path"), 1);
155
+
152
156
  // ../../plugins/filesystem/src/helpers.ts
153
157
  var YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yml", ".yaml"]);
154
158
  var FILESYSTEM_PLUGIN_ID = "@kitsy/cnos/plugins/filesystem";
@@ -242,13 +246,15 @@ async function resolveSecretValue(value, processEnv) {
242
246
  return value;
243
247
  }
244
248
  if (value.provider === "local") {
245
- if (!processEnv?.CNOS_SECRET_PASSPHRASE) {
249
+ const passphrase = resolveSecretPassphrase(value.vault, processEnv);
250
+ if (!passphrase) {
246
251
  return value;
247
252
  }
248
253
  return readLocalSecret(
249
254
  resolveSecretStoreRoot(processEnv),
250
255
  value.ref,
251
- processEnv?.CNOS_SECRET_PASSPHRASE
256
+ passphrase,
257
+ value.vault
252
258
  );
253
259
  }
254
260
  if (value.provider === "env") {
@@ -5,8 +5,8 @@ import {
5
5
  filesystemSecretsReader,
6
6
  filesystemValuesReader,
7
7
  yamlObjectToEntries
8
- } from "../chunk-KG6OZX5C.js";
9
- import "../chunk-K2T4R5WH.js";
8
+ } from "../chunk-7FBRVJD6.js";
9
+ import "../chunk-33ZDYDQJ.js";
10
10
  export {
11
11
  collectFilesystemLayerFiles,
12
12
  createFilesystemSecretsPlugin,
@@ -59,6 +59,11 @@ var import_node_path4 = __toESM(require("path"), 1);
59
59
  var import_promises5 = require("fs/promises");
60
60
  var import_node_path5 = __toESM(require("path"), 1);
61
61
 
62
+ // ../core/src/utils/secretStore.ts
63
+ var import_node_crypto = require("crypto");
64
+ var import_promises6 = require("fs/promises");
65
+ var import_node_path6 = __toESM(require("path"), 1);
66
+
62
67
  // ../core/src/utils/envNaming.ts
63
68
  function normalizeMappingConfig(config = {}) {
64
69
  return {
@@ -92,11 +97,6 @@ function envVarToLogicalKey(envVar, config = {}) {
92
97
  }
93
98
 
94
99
  // ../core/src/runtime/dump.ts
95
- var import_promises6 = require("fs/promises");
96
- var import_node_path6 = __toESM(require("path"), 1);
97
-
98
- // ../core/src/utils/secretStore.ts
99
- var import_node_crypto = require("crypto");
100
100
  var import_promises7 = require("fs/promises");
101
101
  var import_node_path7 = __toESM(require("path"), 1);
102
102
 
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createProcessEnvPlugin,
3
3
  processEnvEntriesFromObject
4
- } from "../chunk-CGTFH4QQ.js";
5
- import "../chunk-K2T4R5WH.js";
4
+ } from "../chunk-53HXUSM6.js";
5
+ import "../chunk-33ZDYDQJ.js";
6
6
  export {
7
7
  createProcessEnvPlugin,
8
8
  processEnvEntriesFromObject
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitsy/cnos",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Batteries-included CNOS runtime package wired with the official plugins.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -73,7 +73,7 @@
73
73
  "yaml": "^2.8.3"
74
74
  },
75
75
  "scripts": {
76
- "build": "tsup --config tsup.config.ts",
76
+ "build": "rimraf dist && tsup --config tsup.config.ts",
77
77
  "clean": "rimraf dist",
78
78
  "dev": "tsup --config tsup.config.ts --watch",
79
79
  "lint": "eslint src test",