sentinelayer-cli 0.32.0 → 0.32.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sentinelayer-cli",
3
- "version": "0.32.0",
3
+ "version": "0.32.1",
4
4
  "description": "Scaffold Sentinelayer spec/prompt/guide artifacts with secure browser auth and token bootstrap.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -13,6 +13,14 @@ import {
13
13
  } from "../config/service.js";
14
14
 
15
15
  const SCOPES = "global|project|env|resolved";
16
+ const REDACTION_MARKER = "[REDACTED]";
17
+ const SENSITIVE_TOP_LEVEL_KEYS = new Set([
18
+ "sentinelayerToken",
19
+ "openaiApiKey",
20
+ "anthropicApiKey",
21
+ "googleApiKey",
22
+ ]);
23
+ const SENSITIVE_KEY_RE = /(authorization|cookie|set-cookie|x-api-key|api[_-]?key|secret|password|credential|token|webhook[_-]?url)/i;
16
24
 
17
25
  function shouldEmitJson(options, command) {
18
26
  const local = Boolean(options && options.json);
@@ -21,14 +29,59 @@ function shouldEmitJson(options, command) {
21
29
  return local || globalFromCommand;
22
30
  }
23
31
 
24
- function displayValue(value) {
32
+ function isPlainObject(value) {
33
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
34
+ }
35
+
36
+ function isSensitiveConfigPath(pathParts = []) {
37
+ const lastKey = String(pathParts[pathParts.length - 1] || "");
38
+ if (!lastKey) return false;
39
+ if (pathParts.length === 1 && SENSITIVE_TOP_LEVEL_KEYS.has(lastKey)) return true;
40
+ if (SENSITIVE_KEY_RE.test(lastKey)) return true;
41
+ if (pathParts.includes("alerts") && lastKey.replace(/[_-]/g, "").toLowerCase() === "url") {
42
+ return true;
43
+ }
44
+ return false;
45
+ }
46
+
47
+ function redactConfigValue(value, pathParts = [], depth = 0) {
48
+ if (value === undefined) return undefined;
49
+ if (isSensitiveConfigPath(pathParts)) return REDACTION_MARKER;
50
+ if (depth > 8) return REDACTION_MARKER;
51
+ if (Array.isArray(value)) {
52
+ return value.map((entry) => redactConfigValue(entry, pathParts, depth + 1));
53
+ }
54
+ if (isPlainObject(value)) {
55
+ return Object.fromEntries(
56
+ Object.entries(value).map(([key, inner]) => [
57
+ key,
58
+ redactConfigValue(inner, [...pathParts, key], depth + 1),
59
+ ])
60
+ );
61
+ }
62
+ return value;
63
+ }
64
+
65
+ function redactConfigLayer(layer = {}) {
66
+ return redactConfigValue(layer, []);
67
+ }
68
+
69
+ function redactConfigResult(result = {}) {
70
+ return {
71
+ ...result,
72
+ value: redactConfigValue(result.value, [result.key]),
73
+ };
74
+ }
75
+
76
+ function displayValue(key, value) {
77
+ const safeValue = redactConfigValue(value, [key]);
25
78
  if (value === undefined) {
26
79
  return "";
27
80
  }
28
- if (typeof value === "string") {
29
- return value;
81
+ if (typeof safeValue === "string") {
82
+ return safeValue;
30
83
  }
31
- return JSON.stringify(value);
84
+ return JSON.stringify(safeValue);
32
85
  }
33
86
 
34
87
  function assertKnownKey(key) {
@@ -61,7 +114,7 @@ export function registerConfigCommand(program) {
61
114
  JSON.stringify(
62
115
  {
63
116
  scope,
64
- config: layer,
117
+ config: redactConfigLayer(layer),
65
118
  paths: payload.paths,
66
119
  },
67
120
  null,
@@ -78,7 +131,7 @@ export function registerConfigCommand(program) {
78
131
  return;
79
132
  }
80
133
  for (const [key, value] of entries) {
81
- console.log(`${key}: ${displayValue(value)}`);
134
+ console.log(`${key}: ${displayValue(key, value)}`);
82
135
  }
83
136
  });
84
137
 
@@ -103,7 +156,7 @@ export function registerConfigCommand(program) {
103
156
  {
104
157
  key: normalizedKey,
105
158
  scope,
106
- value,
159
+ value: redactConfigValue(value, [normalizedKey]),
107
160
  source,
108
161
  },
109
162
  null,
@@ -119,7 +172,7 @@ export function registerConfigCommand(program) {
119
172
  return;
120
173
  }
121
174
 
122
- console.log(displayValue(value));
175
+ console.log(displayValue(normalizedKey, value));
123
176
  });
124
177
 
125
178
  config
@@ -137,13 +190,13 @@ export function registerConfigCommand(program) {
137
190
  });
138
191
 
139
192
  if (shouldEmitJson(options, command)) {
140
- console.log(JSON.stringify(result, null, 2));
193
+ console.log(JSON.stringify(redactConfigResult(result), null, 2));
141
194
  return;
142
195
  }
143
196
 
144
197
  console.log(pc.green(`Updated ${result.key} in ${result.scope} config.`));
145
198
  console.log(pc.gray(`Path: ${result.path}`));
146
- console.log(`${result.key}: ${displayValue(result.value)}`);
199
+ console.log(`${result.key}: ${displayValue(result.key, result.value)}`);
147
200
  });
148
201
 
149
202
  config