@wrongstack/core 0.148.0 → 0.236.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.
- package/dist/{agent-bridge-r9y6gdn4.d.ts → agent-bridge-Cimv7bK7.d.ts} +1 -1
- package/dist/{agent-subagent-runner-1GeQE_L0.d.ts → agent-subagent-runner-C658wj_c.d.ts} +9 -8
- package/dist/{brain-Cp_3GIS2.d.ts → brain-sCZ3lCjq.d.ts} +28 -2
- package/dist/{compactor-BueGt7LG.d.ts → compactor-BRfg3QPd.d.ts} +1 -1
- package/dist/{config-BaVThgnT.d.ts → config-Koq6f3fs.d.ts} +2 -2
- package/dist/{context-C7G_MtLV.d.ts → context-CLz3z_E8.d.ts} +126 -2
- package/dist/coordination/index.d.ts +70 -13
- package/dist/coordination/index.js +2126 -151
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +27 -27
- package/dist/defaults/index.js +1328 -354
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +45 -16
- package/dist/execution/index.js +367 -59
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +86 -0
- package/dist/execution/prompt-enhancer.js +125 -0
- package/dist/execution/prompt-enhancer.js.map +1 -0
- package/dist/extension/index.d.ts +6 -6
- package/dist/extension/index.js +3 -1
- package/dist/extension/index.js.map +1 -1
- package/dist/{goal-preamble-CYJLg0wk.d.ts → goal-preamble-CnbzyVvl.d.ts} +19 -10
- package/dist/{index-BZdezm3g.d.ts → index-BlMqh5GO.d.ts} +8 -8
- package/dist/{index-CPweVoFM.d.ts → index-C2eSNPsB.d.ts} +7 -5
- package/dist/index.d.ts +439 -129
- package/dist/index.js +5206 -905
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +7 -7
- package/dist/infrastructure/index.js +72 -15
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +9 -9
- package/dist/kernel/index.js +7 -1
- package/dist/kernel/index.js.map +1 -1
- package/dist/{llm-selector-CP72f1lC.d.ts → llm-selector-D22R4AFz.d.ts} +2 -2
- package/dist/logger-DmmQhf4P.d.ts +65 -0
- package/dist/{mcp-servers-Bl5LTvQg.d.ts → mcp-servers-DFbirBv6.d.ts} +11 -4
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js +89 -9
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-D90K9UnM.d.ts → models-registry-CnJRjTXc.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-QWEzJDlm.d.ts → multi-agent-coordinator-60weDZoA.d.ts} +8 -8
- package/dist/{null-fleet-bus-BUyfqh23.d.ts → null-fleet-bus-1068dEnr.d.ts} +7 -7
- package/dist/observability/index.d.ts +2 -2
- package/dist/package-outdated-watcher-pzJ5w7y8.d.ts +560 -0
- package/dist/{parallel-eternal-engine-C75QuhAI.d.ts → parallel-eternal-engine-DtG1fjc9.d.ts} +13 -9
- package/dist/{path-resolver-DRjQBkoO.d.ts → path-resolver-CA1ULU0J.d.ts} +3 -3
- package/dist/{permission-B7nKnEvQ.d.ts → permission-DbWPbuoA.d.ts} +1 -1
- package/dist/{permission-policy-8-6zBmfA.d.ts → permission-policy-AOk0LVsV.d.ts} +2 -2
- package/dist/pipeline-DsmlwTXu.d.ts +493 -0
- package/dist/{plan-templates-CkKNPU3I.d.ts → plan-templates-DPABrDvy.d.ts} +19 -8
- package/dist/{provider-runner-BNpuIyOL.d.ts → provider-runner-D0HgUqwV.d.ts} +3 -3
- package/dist/{retry-policy-rutAfVeR.d.ts → retry-policy-BVnkbMET.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -8
- package/dist/sdd/index.js +358 -85
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-DoISxaKO.d.ts → secret-vault-BJDY28ev.d.ts} +7 -1
- package/dist/{secret-vault-BTcC_T5v.d.ts → secret-vault-CeVNiy_f.d.ts} +4 -3
- package/dist/security/index.d.ts +6 -5
- package/dist/security/index.js +214 -35
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-4vDFZKt3.d.ts → selector-Cb4_9-hf.d.ts} +1 -1
- package/dist/{session-event-bridge-DWlvglC2.d.ts → session-event-bridge-BhtkkFFy.d.ts} +4 -2
- package/dist/{session-reader-BAtCxdaw.d.ts → session-reader-CCOssnBS.d.ts} +1 -1
- package/dist/skills/index.js +171 -21
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +151 -13
- package/dist/storage/index.js +1117 -256
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +68 -21
- package/dist/types/index.js +616 -74
- package/dist/types/index.js.map +1 -1
- package/dist/utils/expect-defined.js +3 -1
- package/dist/utils/expect-defined.js.map +1 -1
- package/dist/utils/index.d.ts +80 -4
- package/dist/utils/index.js +100 -15
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-DD50Omgn.d.ts → wstack-paths-CJjEwPXn.d.ts} +14 -1
- package/package.json +7 -3
- package/skills/chimera/SKILL.md +105 -0
- package/skills/research-web/SKILL.md +342 -0
- package/dist/logger-B9J5puGM.d.ts +0 -32
- package/dist/pipeline-BG7UgbDc.d.ts +0 -239
|
@@ -15,5 +15,11 @@ interface SecretVault {
|
|
|
15
15
|
decrypt(value: string): string;
|
|
16
16
|
isEncrypted(value: string): boolean;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* No-op SecretVault that passes values through unchanged.
|
|
20
|
+
* Used in contexts where encryption is not needed — e.g. reading/writing
|
|
21
|
+
* config sections that contain no secret fields (models, settings, etc.).
|
|
22
|
+
*/
|
|
23
|
+
declare const noOpVault: SecretVault;
|
|
18
24
|
|
|
19
|
-
export type
|
|
25
|
+
export { type SecretVault as S, noOpVault as n };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { S as SecretScrubber } from './permission-
|
|
2
|
-
import {
|
|
1
|
+
import { S as SecretScrubber } from './permission-DbWPbuoA.js';
|
|
2
|
+
import { L as Logger } from './logger-B63L5bTg.js';
|
|
3
|
+
import { S as SecretVault } from './secret-vault-BJDY28ev.js';
|
|
3
4
|
|
|
4
5
|
declare class DefaultSecretScrubber implements SecretScrubber {
|
|
5
6
|
scrub(text: string): string;
|
|
@@ -55,7 +56,7 @@ declare function rewriteConfigEncrypted(configPath: string, vault: SecretVault,
|
|
|
55
56
|
* users who had plaintext keys before the vault landed are upgraded
|
|
56
57
|
* transparently.
|
|
57
58
|
*/
|
|
58
|
-
declare function migratePlaintextSecrets(configPath: string, vault: SecretVault): Promise<{
|
|
59
|
+
declare function migratePlaintextSecrets(configPath: string, vault: SecretVault, logger?: Pick<Logger, 'warn'>): Promise<{
|
|
59
60
|
migrated: number;
|
|
60
61
|
file: string;
|
|
61
62
|
}>;
|
package/dist/security/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-vault-
|
|
2
|
-
export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-
|
|
3
|
-
import '../permission-
|
|
4
|
-
import '../context-
|
|
5
|
-
import '../
|
|
1
|
+
export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-vault-CeVNiy_f.js';
|
|
2
|
+
export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-AOk0LVsV.js';
|
|
3
|
+
import '../permission-DbWPbuoA.js';
|
|
4
|
+
import '../context-CLz3z_E8.js';
|
|
5
|
+
import '../logger-B63L5bTg.js';
|
|
6
|
+
import '../secret-vault-BJDY28ev.js';
|
|
6
7
|
import '../input-reader-E-ffP2ee.js';
|
|
7
8
|
|
|
8
9
|
/**
|
package/dist/security/index.js
CHANGED
|
@@ -110,6 +110,105 @@ var DefaultSecretScrubber = class {
|
|
|
110
110
|
}
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
// src/types/errors.ts
|
|
114
|
+
var ERROR_CODES = {
|
|
115
|
+
// Provider
|
|
116
|
+
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
117
|
+
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
118
|
+
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
119
|
+
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
120
|
+
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
121
|
+
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR",
|
|
122
|
+
PROVIDER_CONTEXT_OVERFLOW: "PROVIDER_CONTEXT_OVERFLOW",
|
|
123
|
+
// Tool
|
|
124
|
+
TOOL_NOT_FOUND: "TOOL_NOT_FOUND",
|
|
125
|
+
TOOL_PERMISSION_DENIED: "TOOL_PERMISSION_DENIED",
|
|
126
|
+
TOOL_EXECUTION_FAILED: "TOOL_EXECUTION_FAILED",
|
|
127
|
+
TOOL_TIMEOUT: "TOOL_TIMEOUT",
|
|
128
|
+
TOOL_INPUT_INVALID: "TOOL_INPUT_INVALID",
|
|
129
|
+
// Config
|
|
130
|
+
CONFIG_INVALID: "CONFIG_INVALID",
|
|
131
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
132
|
+
CONFIG_PARSE_FAILED: "CONFIG_PARSE_FAILED",
|
|
133
|
+
CONFIG_MIGRATION_NEEDED: "CONFIG_MIGRATION_NEEDED",
|
|
134
|
+
// Plugin
|
|
135
|
+
PLUGIN_LOAD_FAILED: "PLUGIN_LOAD_FAILED",
|
|
136
|
+
PLUGIN_API_MISMATCH: "PLUGIN_API_MISMATCH",
|
|
137
|
+
PLUGIN_MISSING_DEPENDENCY: "PLUGIN_MISSING_DEPENDENCY",
|
|
138
|
+
// Agent
|
|
139
|
+
AGENT_ITERATION_LIMIT: "AGENT_ITERATION_LIMIT",
|
|
140
|
+
AGENT_CONTEXT_OVERFLOW: "AGENT_CONTEXT_OVERFLOW",
|
|
141
|
+
AGENT_ABORTED: "AGENT_ABORTED",
|
|
142
|
+
AGENT_RUN_FAILED: "AGENT_RUN_FAILED",
|
|
143
|
+
// Session
|
|
144
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
145
|
+
SESSION_CORRUPTED: "SESSION_CORRUPTED",
|
|
146
|
+
SESSION_WRITE_FAILED: "SESSION_WRITE_FAILED",
|
|
147
|
+
// Container / Registry
|
|
148
|
+
CONTAINER_TOKEN_ALREADY_BOUND: "CONTAINER_TOKEN_ALREADY_BOUND",
|
|
149
|
+
CONTAINER_TOKEN_NOT_BOUND: "CONTAINER_TOKEN_NOT_BOUND",
|
|
150
|
+
CONTAINER_CIRCULAR_DEPENDENCY: "CONTAINER_CIRCULAR_DEPENDENCY",
|
|
151
|
+
REGISTRY_DUPLICATE: "REGISTRY_DUPLICATE",
|
|
152
|
+
REGISTRY_NOT_FOUND: "REGISTRY_NOT_FOUND",
|
|
153
|
+
REGISTRY_INVALID: "REGISTRY_INVALID",
|
|
154
|
+
// File system
|
|
155
|
+
FS_READ_FAILED: "FS_READ_FAILED",
|
|
156
|
+
FS_WRITE_FAILED: "FS_WRITE_FAILED",
|
|
157
|
+
FS_MKDIR_FAILED: "FS_MKDIR_FAILED",
|
|
158
|
+
FS_DELETE_FAILED: "FS_DELETE_FAILED",
|
|
159
|
+
FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED",
|
|
160
|
+
// SDD (Spec-Driven Development)
|
|
161
|
+
SDD_VALIDATION_FAILED: "SDD_VALIDATION_FAILED",
|
|
162
|
+
SDD_PARSE_FAILED: "SDD_PARSE_FAILED",
|
|
163
|
+
SDD_INVALID_STATE: "SDD_INVALID_STATE",
|
|
164
|
+
SDD_NOT_READY: "SDD_NOT_READY",
|
|
165
|
+
// General
|
|
166
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
167
|
+
UNKNOWN: "UNKNOWN"
|
|
168
|
+
};
|
|
169
|
+
var WrongStackError = class extends Error {
|
|
170
|
+
code;
|
|
171
|
+
subsystem;
|
|
172
|
+
severity;
|
|
173
|
+
recoverable;
|
|
174
|
+
context;
|
|
175
|
+
constructor(opts) {
|
|
176
|
+
super(opts.message, { cause: opts.cause });
|
|
177
|
+
this.name = "WrongStackError";
|
|
178
|
+
this.code = opts.code;
|
|
179
|
+
this.subsystem = opts.subsystem;
|
|
180
|
+
this.severity = opts.severity ?? "error";
|
|
181
|
+
this.recoverable = opts.recoverable ?? false;
|
|
182
|
+
this.context = opts.context;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Render a one-line user-facing description.
|
|
186
|
+
* Subclasses should override for domain-specific formatting.
|
|
187
|
+
*/
|
|
188
|
+
describe() {
|
|
189
|
+
const ctx = this.context ? ` ${formatContext(this.context)}` : "";
|
|
190
|
+
return `${this.code}: ${this.message}${ctx}`;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
function formatContext(ctx) {
|
|
194
|
+
const parts = Object.entries(ctx).filter(([, v]) => v !== void 0).slice(0, 3).map(([k, v]) => `${k}=${String(v)}`);
|
|
195
|
+
return parts.length > 0 ? `[${parts.join(" ")}]` : "";
|
|
196
|
+
}
|
|
197
|
+
var ConfigError = class extends WrongStackError {
|
|
198
|
+
constructor(opts) {
|
|
199
|
+
super({
|
|
200
|
+
message: opts.message,
|
|
201
|
+
code: opts.code,
|
|
202
|
+
subsystem: "config",
|
|
203
|
+
severity: "fatal",
|
|
204
|
+
recoverable: false,
|
|
205
|
+
context: opts.context,
|
|
206
|
+
cause: opts.cause
|
|
207
|
+
});
|
|
208
|
+
this.name = "ConfigError";
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
113
212
|
// src/types/secret-vault.ts
|
|
114
213
|
var ENCRYPTED_PREFIX = "enc:v1:";
|
|
115
214
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
@@ -174,11 +273,90 @@ async function renameWithRetry(from, to) {
|
|
|
174
273
|
throw lastErr;
|
|
175
274
|
}
|
|
176
275
|
|
|
276
|
+
// src/utils/deep-merge.ts
|
|
277
|
+
var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
278
|
+
"__proto__",
|
|
279
|
+
"constructor",
|
|
280
|
+
"prototype",
|
|
281
|
+
"__defineGetter__",
|
|
282
|
+
"__defineSetter__",
|
|
283
|
+
"__lookupGetter__",
|
|
284
|
+
"__lookupSetter__"
|
|
285
|
+
]);
|
|
286
|
+
function isPrimitiveArray(a) {
|
|
287
|
+
return a.every((v) => v === null || typeof v !== "object" && typeof v !== "function");
|
|
288
|
+
}
|
|
289
|
+
function deepMerge(base, patch, options = {}) {
|
|
290
|
+
const {
|
|
291
|
+
conflictResolution = "prefer-patch",
|
|
292
|
+
arrayMode = "replace",
|
|
293
|
+
protectProto = true,
|
|
294
|
+
onNonPrimitiveArrayReplace
|
|
295
|
+
} = options;
|
|
296
|
+
if (typeof base !== "object" || base === null) {
|
|
297
|
+
return conflictResolution === "prefer-patch" ? patch : base;
|
|
298
|
+
}
|
|
299
|
+
if (typeof patch !== "object" || patch === null) {
|
|
300
|
+
return conflictResolution === "prefer-patch" ? patch : base;
|
|
301
|
+
}
|
|
302
|
+
if (Array.isArray(base) && Array.isArray(patch)) {
|
|
303
|
+
if (arrayMode === "concat-primitives" && isPrimitiveArray(base) && isPrimitiveArray(patch)) {
|
|
304
|
+
return [.../* @__PURE__ */ new Set([...base, ...patch])];
|
|
305
|
+
}
|
|
306
|
+
return conflictResolution === "prefer-patch" ? patch : base;
|
|
307
|
+
}
|
|
308
|
+
if (Array.isArray(base) || Array.isArray(patch)) {
|
|
309
|
+
return conflictResolution === "prefer-patch" ? patch : base;
|
|
310
|
+
}
|
|
311
|
+
const baseObj = base;
|
|
312
|
+
const patchObj = patch;
|
|
313
|
+
const out = { ...baseObj };
|
|
314
|
+
for (const [k, v] of Object.entries(patchObj)) {
|
|
315
|
+
if (protectProto && FORBIDDEN_PROTO_KEYS.has(k)) continue;
|
|
316
|
+
const existing = out[k];
|
|
317
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v) && existing !== null && typeof existing === "object" && !Array.isArray(existing)) {
|
|
318
|
+
out[k] = deepMerge(existing, v, options);
|
|
319
|
+
} else if (Array.isArray(v) && Array.isArray(existing)) {
|
|
320
|
+
if (onNonPrimitiveArrayReplace && !isPrimitiveArray(v)) {
|
|
321
|
+
onNonPrimitiveArrayReplace(k, existing.length, v.length);
|
|
322
|
+
}
|
|
323
|
+
out[k] = deepMerge(existing, v, options);
|
|
324
|
+
} else if (v !== void 0) {
|
|
325
|
+
if (onNonPrimitiveArrayReplace && Array.isArray(v) && !isPrimitiveArray(v)) {
|
|
326
|
+
const existingLen = Array.isArray(existing) ? existing.length : 0;
|
|
327
|
+
onNonPrimitiveArrayReplace(k, existingLen, v.length);
|
|
328
|
+
}
|
|
329
|
+
out[k] = v;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return out;
|
|
333
|
+
}
|
|
334
|
+
|
|
177
335
|
// src/security/secret-vault.ts
|
|
178
336
|
var KEY_BYTES = 32;
|
|
179
337
|
var IV_BYTES = 12;
|
|
180
338
|
var TAG_BYTES = 16;
|
|
181
339
|
var ALGO = "aes-256-gcm";
|
|
340
|
+
var KEY_FILE_MODE = 384;
|
|
341
|
+
function checkKeyFilePermissions(keyFile) {
|
|
342
|
+
if (process.platform === "win32") return;
|
|
343
|
+
try {
|
|
344
|
+
const stat2 = fs2.statSync(keyFile);
|
|
345
|
+
const actualMode = stat2.mode & 511;
|
|
346
|
+
if (actualMode !== KEY_FILE_MODE) {
|
|
347
|
+
console.warn(JSON.stringify({
|
|
348
|
+
level: "warn",
|
|
349
|
+
event: "vault.key_file_wrong_permissions",
|
|
350
|
+
message: `Key file ${keyFile} has mode ${actualMode.toString(8)} \u2014 expected ${KEY_FILE_MODE.toString(8)}. Run: chmod ${KEY_FILE_MODE.toString(8)} ${keyFile}`,
|
|
351
|
+
keyFile,
|
|
352
|
+
expectedMode: KEY_FILE_MODE,
|
|
353
|
+
actualMode,
|
|
354
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
} catch {
|
|
358
|
+
}
|
|
359
|
+
}
|
|
182
360
|
var DefaultSecretVault = class {
|
|
183
361
|
keyFile;
|
|
184
362
|
key;
|
|
@@ -202,14 +380,26 @@ var DefaultSecretVault = class {
|
|
|
202
380
|
const rest = value.slice(ENCRYPTED_PREFIX.length);
|
|
203
381
|
const parts = rest.split(":");
|
|
204
382
|
if (parts.length !== 3) {
|
|
205
|
-
throw new
|
|
383
|
+
throw new ConfigError({
|
|
384
|
+
message: "SecretVault: malformed encrypted value",
|
|
385
|
+
code: ERROR_CODES.CONFIG_PARSE_FAILED,
|
|
386
|
+
context: { field: "encrypted_value" }
|
|
387
|
+
});
|
|
206
388
|
}
|
|
207
389
|
const [ivB64, tagB64, ctB64] = parts;
|
|
208
390
|
const iv = Buffer.from(ivB64, "base64");
|
|
209
391
|
const tag = Buffer.from(tagB64, "base64");
|
|
210
392
|
const ct = Buffer.from(ctB64, "base64");
|
|
211
|
-
if (iv.length !== IV_BYTES) throw new
|
|
212
|
-
|
|
393
|
+
if (iv.length !== IV_BYTES) throw new ConfigError({
|
|
394
|
+
message: "SecretVault: bad IV length",
|
|
395
|
+
code: ERROR_CODES.CONFIG_PARSE_FAILED,
|
|
396
|
+
context: { expected: IV_BYTES, actual: iv.length }
|
|
397
|
+
});
|
|
398
|
+
if (tag.length !== TAG_BYTES) throw new ConfigError({
|
|
399
|
+
message: "SecretVault: bad tag length",
|
|
400
|
+
code: ERROR_CODES.CONFIG_PARSE_FAILED,
|
|
401
|
+
context: { expected: TAG_BYTES, actual: tag.length }
|
|
402
|
+
});
|
|
213
403
|
const key = this.loadOrCreateKey();
|
|
214
404
|
const decipher = createDecipheriv(ALGO, key, iv);
|
|
215
405
|
decipher.setAuthTag(tag);
|
|
@@ -221,11 +411,14 @@ var DefaultSecretVault = class {
|
|
|
221
411
|
try {
|
|
222
412
|
const buf = fs2.readFileSync(this.keyFile);
|
|
223
413
|
if (buf.length !== KEY_BYTES) {
|
|
224
|
-
throw new
|
|
225
|
-
`SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key
|
|
226
|
-
|
|
414
|
+
throw new ConfigError({
|
|
415
|
+
message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`,
|
|
416
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
417
|
+
context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
|
|
418
|
+
});
|
|
227
419
|
}
|
|
228
420
|
this.key = buf;
|
|
421
|
+
checkKeyFilePermissions(this.keyFile);
|
|
229
422
|
return this.key;
|
|
230
423
|
} catch (err) {
|
|
231
424
|
if (err.code !== "ENOENT") throw err;
|
|
@@ -238,11 +431,14 @@ var DefaultSecretVault = class {
|
|
|
238
431
|
if (err.code !== "EEXIST") throw err;
|
|
239
432
|
const buf = fs2.readFileSync(this.keyFile);
|
|
240
433
|
if (buf.length !== KEY_BYTES) {
|
|
241
|
-
throw new
|
|
242
|
-
`SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key
|
|
243
|
-
|
|
434
|
+
throw new ConfigError({
|
|
435
|
+
message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`,
|
|
436
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
437
|
+
context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
|
|
438
|
+
});
|
|
244
439
|
}
|
|
245
440
|
this.key = buf;
|
|
441
|
+
checkKeyFilePermissions(this.keyFile);
|
|
246
442
|
return this.key;
|
|
247
443
|
}
|
|
248
444
|
this.key = key;
|
|
@@ -303,7 +499,7 @@ async function rewriteConfigEncrypted(configPath, vault, patch) {
|
|
|
303
499
|
await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
304
500
|
await restrictFilePermissions(configPath);
|
|
305
501
|
}
|
|
306
|
-
async function migratePlaintextSecrets(configPath, vault) {
|
|
502
|
+
async function migratePlaintextSecrets(configPath, vault, logger) {
|
|
307
503
|
let raw;
|
|
308
504
|
try {
|
|
309
505
|
raw = await fs.readFile(configPath, "utf8");
|
|
@@ -320,11 +516,14 @@ async function migratePlaintextSecrets(configPath, vault) {
|
|
|
320
516
|
const migrated = walkCount(parsed, vault, counter);
|
|
321
517
|
if (counter.n === 0) return { migrated: 0, file: configPath };
|
|
322
518
|
await atomicWrite(configPath, JSON.stringify(migrated, null, 2), { mode: 384 });
|
|
323
|
-
await restrictFilePermissions(
|
|
519
|
+
await restrictFilePermissions(
|
|
520
|
+
configPath,
|
|
521
|
+
logger ? { warn: (msg) => logger.warn(msg) } : void 0
|
|
522
|
+
);
|
|
324
523
|
return { migrated: counter.n, file: configPath };
|
|
325
524
|
}
|
|
326
525
|
async function restrictFilePermissions(filePath, opts) {
|
|
327
|
-
const warn = ((msg) => console.warn(msg));
|
|
526
|
+
const warn = opts?.warn ?? ((msg) => console.warn(msg));
|
|
328
527
|
if (process.platform === "win32") {
|
|
329
528
|
try {
|
|
330
529
|
const { execFile } = await import('child_process');
|
|
@@ -376,28 +575,6 @@ function walkCount(node, vault, counter) {
|
|
|
376
575
|
}
|
|
377
576
|
return out;
|
|
378
577
|
}
|
|
379
|
-
var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
380
|
-
"__proto__",
|
|
381
|
-
"constructor",
|
|
382
|
-
"prototype",
|
|
383
|
-
"__defineGetter__",
|
|
384
|
-
"__defineSetter__",
|
|
385
|
-
"__lookupGetter__",
|
|
386
|
-
"__lookupSetter__"
|
|
387
|
-
]);
|
|
388
|
-
function deepMerge(a, b) {
|
|
389
|
-
const out = { ...a };
|
|
390
|
-
for (const [k, v] of Object.entries(b)) {
|
|
391
|
-
if (FORBIDDEN_PROTO_KEYS.has(k)) continue;
|
|
392
|
-
const existing = out[k];
|
|
393
|
-
if (v !== null && typeof v === "object" && !Array.isArray(v) && existing !== null && typeof existing === "object" && !Array.isArray(existing)) {
|
|
394
|
-
out[k] = deepMerge(existing, v);
|
|
395
|
-
} else {
|
|
396
|
-
out[k] = v;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
return out;
|
|
400
|
-
}
|
|
401
578
|
|
|
402
579
|
// src/security/capabilities.ts
|
|
403
580
|
var ToolCapabilities = {
|
|
@@ -457,7 +634,9 @@ function getDangerousCapabilities(toolOrCaps) {
|
|
|
457
634
|
// src/utils/expect-defined.ts
|
|
458
635
|
function expectDefined(value, label) {
|
|
459
636
|
if (value === null || value === void 0) {
|
|
460
|
-
|
|
637
|
+
const err = new Error("Expected value to be defined");
|
|
638
|
+
err.name = "ExpectDefinedError";
|
|
639
|
+
throw err;
|
|
461
640
|
}
|
|
462
641
|
return value;
|
|
463
642
|
}
|