proofscan 0.7.2 → 0.7.3

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 (39) hide show
  1. package/dist/cli.js +5 -2
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/index.d.ts +1 -0
  4. package/dist/commands/index.d.ts.map +1 -1
  5. package/dist/commands/index.js +2 -0
  6. package/dist/commands/index.js.map +1 -1
  7. package/dist/commands/secrets.d.ts +19 -0
  8. package/dist/commands/secrets.d.ts.map +1 -0
  9. package/dist/commands/secrets.js +387 -0
  10. package/dist/commands/secrets.js.map +1 -0
  11. package/dist/secrets/index.d.ts +2 -0
  12. package/dist/secrets/index.d.ts.map +1 -1
  13. package/dist/secrets/index.js +4 -0
  14. package/dist/secrets/index.js.map +1 -1
  15. package/dist/secrets/management.d.ts +112 -0
  16. package/dist/secrets/management.d.ts.map +1 -0
  17. package/dist/secrets/management.js +488 -0
  18. package/dist/secrets/management.js.map +1 -0
  19. package/dist/secrets/resolve.d.ts +51 -0
  20. package/dist/secrets/resolve.d.ts.map +1 -0
  21. package/dist/secrets/resolve.js +113 -0
  22. package/dist/secrets/resolve.js.map +1 -0
  23. package/dist/secrets/store.d.ts +4 -0
  24. package/dist/secrets/store.d.ts.map +1 -1
  25. package/dist/secrets/store.js +12 -0
  26. package/dist/secrets/store.js.map +1 -1
  27. package/dist/secrets/types.d.ts +1 -1
  28. package/dist/secrets/types.d.ts.map +1 -1
  29. package/dist/secrets/types.js +2 -2
  30. package/dist/secrets/types.js.map +1 -1
  31. package/dist/utils/clipboard.d.ts +4 -0
  32. package/dist/utils/clipboard.d.ts.map +1 -1
  33. package/dist/utils/clipboard.js +6 -0
  34. package/dist/utils/clipboard.js.map +1 -1
  35. package/dist/utils/secret-input.d.ts +22 -0
  36. package/dist/utils/secret-input.d.ts.map +1 -0
  37. package/dist/utils/secret-input.js +84 -0
  38. package/dist/utils/secret-input.js.map +1 -0
  39. package/package.json +1 -1
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Secrets management utilities (Phase 3.6)
3
+ *
4
+ * Provides functions for:
5
+ * - Listing secrets with bindings
6
+ * - Setting/updating secrets
7
+ * - Pruning orphan secrets
8
+ * - Export/import encrypted bundles
9
+ *
10
+ * Security: Never logs, prints, or writes plaintext secrets.
11
+ */
12
+ import { type ProviderType } from './types.js';
13
+ /** Information about a secret and its binding */
14
+ export interface SecretBindingInfo {
15
+ /** Secret reference (dpapi:xxx, plain:xxx) */
16
+ secret_ref: string;
17
+ /** Secret ID */
18
+ secret_id: string;
19
+ /** Connector ID (if bound) */
20
+ connector_id?: string;
21
+ /** Environment key (if bound) */
22
+ env_key?: string;
23
+ /** Provider type */
24
+ provider: ProviderType;
25
+ /** Creation timestamp */
26
+ created_at: string;
27
+ /** Last used timestamp (if tracked) */
28
+ last_used_at?: string;
29
+ /** Status: OK (bound), ORPHAN (not bound), MISSING (ref in config but not in store) */
30
+ status: 'OK' | 'ORPHAN' | 'MISSING';
31
+ }
32
+ /** Options for setting a secret */
33
+ export interface SetSecretOptions {
34
+ configPath: string;
35
+ connectorId: string;
36
+ envKey: string;
37
+ secretValue: string;
38
+ }
39
+ /** Result of setting a secret */
40
+ export interface SetSecretResult {
41
+ secretRef: string;
42
+ secretId: string;
43
+ updated: boolean;
44
+ }
45
+ /** Options for pruning secrets */
46
+ export interface PruneOptions {
47
+ configDir: string;
48
+ configPath: string;
49
+ dryRun?: boolean;
50
+ olderThanDays?: number;
51
+ }
52
+ /** Result of pruning secrets */
53
+ export interface PruneResult {
54
+ orphanCount: number;
55
+ removedCount: number;
56
+ removedIds: string[];
57
+ }
58
+ /** Options for exporting secrets */
59
+ export interface ExportOptions {
60
+ configDir: string;
61
+ configPath: string;
62
+ outputPath: string;
63
+ passphrase: string;
64
+ }
65
+ /** Result of exporting secrets */
66
+ export interface ExportResult {
67
+ exportedCount: number;
68
+ }
69
+ /** Options for importing secrets */
70
+ export interface ImportOptions {
71
+ configDir: string;
72
+ configPath: string;
73
+ inputPath: string;
74
+ passphrase: string;
75
+ overwrite?: boolean;
76
+ }
77
+ /** Error detail for import failures */
78
+ export interface ImportError {
79
+ connector_id: string;
80
+ env_key: string;
81
+ error: string;
82
+ }
83
+ /** Result of importing secrets */
84
+ export interface ImportResult {
85
+ importedCount: number;
86
+ skippedCount: number;
87
+ errorCount: number;
88
+ /** Details about individual import failures */
89
+ errors?: ImportError[];
90
+ }
91
+ /**
92
+ * List all secrets with their binding information
93
+ */
94
+ export declare function listSecretBindings(configDir: string, configPath: string): Promise<SecretBindingInfo[]>;
95
+ /**
96
+ * Set a secret value for a connector environment variable
97
+ * Uses file locking to prevent race conditions during concurrent access.
98
+ */
99
+ export declare function setSecret(options: SetSecretOptions): Promise<SetSecretResult>;
100
+ /**
101
+ * Remove orphan secrets not referenced by config
102
+ */
103
+ export declare function pruneOrphanSecrets(options: PruneOptions): Promise<PruneResult>;
104
+ /**
105
+ * Export secrets to encrypted bundle file
106
+ */
107
+ export declare function exportSecrets(options: ExportOptions): Promise<ExportResult>;
108
+ /**
109
+ * Import secrets from encrypted bundle file
110
+ */
111
+ export declare function importSecrets(options: ImportOptions): Promise<ImportResult>;
112
+ //# sourceMappingURL=management.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"management.d.ts","sourceRoot":"","sources":["../../src/secrets/management.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,488 @@
1
+ /**
2
+ * Secrets management utilities (Phase 3.6)
3
+ *
4
+ * Provides functions for:
5
+ * - Listing secrets with bindings
6
+ * - Setting/updating secrets
7
+ * - Pruning orphan secrets
8
+ * - Export/import encrypted bundles
9
+ *
10
+ * Security: Never logs, prints, or writes plaintext secrets.
11
+ */
12
+ import { existsSync, readFileSync, writeFileSync, unlinkSync, openSync, closeSync, renameSync } from 'fs';
13
+ import { dirname } from 'path';
14
+ import { randomBytes, createCipheriv, createDecipheriv, scryptSync, createHmac, timingSafeEqual } from 'crypto';
15
+ import { SqliteSecretStore } from './store.js';
16
+ import { parseSecretRef, makeSecretRef } from './types.js';
17
+ // ============================================================
18
+ // Crypto utilities
19
+ // ============================================================
20
+ const SCRYPT_N = 2 ** 14; // CPU/memory cost (16384 - compatible with low-memory environments)
21
+ const SCRYPT_R = 8;
22
+ const SCRYPT_P = 1;
23
+ const KEY_LEN = 32; // 256 bits
24
+ function deriveKey(passphrase, salt) {
25
+ return scryptSync(passphrase, salt, KEY_LEN, {
26
+ N: SCRYPT_N,
27
+ r: SCRYPT_R,
28
+ p: SCRYPT_P,
29
+ });
30
+ }
31
+ function encryptPayload(plaintext, key) {
32
+ const iv = randomBytes(12); // 96 bits for GCM
33
+ const cipher = createCipheriv('aes-256-gcm', key, iv);
34
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
35
+ const authTag = cipher.getAuthTag();
36
+ return { iv, authTag, ciphertext };
37
+ }
38
+ function decryptPayload(ciphertext, key, iv, authTag) {
39
+ const decipher = createDecipheriv('aes-256-gcm', key, iv);
40
+ decipher.setAuthTag(authTag);
41
+ return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
42
+ }
43
+ // ============================================================
44
+ // File locking utilities
45
+ // ============================================================
46
+ const LOCK_TIMEOUT_MS = 10000; // 10 seconds
47
+ const LOCK_RETRY_INTERVAL_MS = 100;
48
+ /**
49
+ * Acquire exclusive lock on config file
50
+ * Uses a .lock file mechanism for cross-process safety
51
+ */
52
+ async function acquireConfigLock(configPath) {
53
+ const lockPath = `${configPath}.lock`;
54
+ const startTime = Date.now();
55
+ while (Date.now() - startTime < LOCK_TIMEOUT_MS) {
56
+ try {
57
+ // O_CREAT | O_EXCL - fails if file already exists (atomic check-and-create)
58
+ const fd = openSync(lockPath, 'wx');
59
+ closeSync(fd);
60
+ return lockPath;
61
+ }
62
+ catch (err) {
63
+ if (err.code === 'EEXIST') {
64
+ // Lock exists, wait and retry
65
+ await new Promise(resolve => setTimeout(resolve, LOCK_RETRY_INTERVAL_MS));
66
+ }
67
+ else {
68
+ throw err;
69
+ }
70
+ }
71
+ }
72
+ throw new Error(`Failed to acquire lock on ${configPath} (timeout after ${LOCK_TIMEOUT_MS}ms)`);
73
+ }
74
+ /**
75
+ * Release config file lock
76
+ */
77
+ function releaseConfigLock(lockPath) {
78
+ try {
79
+ unlinkSync(lockPath);
80
+ }
81
+ catch {
82
+ // Ignore errors (lock may have been removed by timeout)
83
+ }
84
+ }
85
+ /**
86
+ * Read and write config file atomically with file locking
87
+ */
88
+ async function withConfigLock(configPath, operation) {
89
+ const lockPath = await acquireConfigLock(configPath);
90
+ const tempPath = `${configPath}.tmp`;
91
+ try {
92
+ // Read current config
93
+ if (!existsSync(configPath)) {
94
+ throw new Error(`Config file not found: ${configPath}`);
95
+ }
96
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
97
+ // Execute operation
98
+ const { config: updatedConfig, result } = await operation(config);
99
+ // Write atomically: write to temp file first, then rename to original
100
+ writeFileSync(tempPath, JSON.stringify(updatedConfig, null, 2));
101
+ renameSync(tempPath, configPath);
102
+ return result;
103
+ }
104
+ finally {
105
+ // Clean up temp file if it exists
106
+ try {
107
+ if (existsSync(tempPath)) {
108
+ unlinkSync(tempPath);
109
+ }
110
+ }
111
+ catch {
112
+ // Ignore cleanup errors
113
+ }
114
+ releaseConfigLock(lockPath);
115
+ }
116
+ }
117
+ // ============================================================
118
+ // Helper functions
119
+ // ============================================================
120
+ /** Extract all secret refs from config */
121
+ function collectConfigSecretRefs(config) {
122
+ const refs = new Map();
123
+ for (const connector of config.connectors || []) {
124
+ const env = connector.transport?.env;
125
+ if (!env)
126
+ continue;
127
+ for (const [key, value] of Object.entries(env)) {
128
+ const parsed = parseSecretRef(value);
129
+ if (parsed) {
130
+ refs.set(parsed.id, { connectorId: connector.id, envKey: key });
131
+ }
132
+ }
133
+ }
134
+ return refs;
135
+ }
136
+ // ============================================================
137
+ // Management functions
138
+ // ============================================================
139
+ /**
140
+ * List all secrets with their binding information
141
+ */
142
+ export async function listSecretBindings(configDir, configPath) {
143
+ const results = [];
144
+ const store = new SqliteSecretStore(configDir);
145
+ try {
146
+ // Get all secret IDs from store
147
+ const secretIds = await store.list();
148
+ // Load config to find bindings
149
+ let config = { version: 1, connectors: [] };
150
+ if (existsSync(configPath)) {
151
+ config = JSON.parse(readFileSync(configPath, 'utf-8'));
152
+ }
153
+ const configRefs = collectConfigSecretRefs(config);
154
+ // Build binding info for each secret
155
+ for (const id of secretIds) {
156
+ const binding = configRefs.get(id);
157
+ const createdAt = await store.getCreatedAt(id);
158
+ // Determine provider from meta or try to get from store
159
+ let provider = 'plain';
160
+ // We need to get the record to know the provider
161
+ // For now, use the store's provider type
162
+ provider = store.getProviderType();
163
+ results.push({
164
+ secret_ref: makeSecretRef(provider, id),
165
+ secret_id: id,
166
+ connector_id: binding?.connectorId,
167
+ env_key: binding?.envKey,
168
+ provider,
169
+ created_at: createdAt?.toISOString() ?? new Date().toISOString(),
170
+ status: binding ? 'OK' : 'ORPHAN',
171
+ });
172
+ // Remove from configRefs to track what we've seen
173
+ configRefs.delete(id);
174
+ }
175
+ // Any remaining configRefs are MISSING (in config but not in store)
176
+ for (const [id, binding] of configRefs) {
177
+ results.push({
178
+ secret_ref: `unknown:${id}`,
179
+ secret_id: id,
180
+ connector_id: binding.connectorId,
181
+ env_key: binding.envKey,
182
+ provider: 'plain',
183
+ created_at: '',
184
+ status: 'MISSING',
185
+ });
186
+ }
187
+ return results;
188
+ }
189
+ finally {
190
+ store.close();
191
+ }
192
+ }
193
+ /**
194
+ * Set a secret value for a connector environment variable
195
+ * Uses file locking to prevent race conditions during concurrent access.
196
+ */
197
+ export async function setSecret(options) {
198
+ const { configPath, connectorId, envKey, secretValue } = options;
199
+ const configDir = dirname(configPath);
200
+ // Store the secret first (outside the lock to minimize lock time)
201
+ const store = new SqliteSecretStore(configDir);
202
+ let storeResult;
203
+ try {
204
+ storeResult = await store.store(secretValue, {
205
+ connectorId,
206
+ keyName: envKey,
207
+ source: `${connectorId}.transport.env.${envKey}`,
208
+ });
209
+ }
210
+ finally {
211
+ store.close();
212
+ }
213
+ // Update config with file locking
214
+ return withConfigLock(configPath, async (config) => {
215
+ // Find connector
216
+ const connector = config.connectors?.find(c => c.id === connectorId);
217
+ if (!connector) {
218
+ throw new Error(`Connector not found: ${connectorId}`);
219
+ }
220
+ // Ensure transport.env exists
221
+ if (!connector.transport) {
222
+ connector.transport = { type: 'stdio', command: '' };
223
+ }
224
+ const transport = connector.transport;
225
+ if (!transport.env) {
226
+ transport.env = {};
227
+ }
228
+ // Check if there's an existing secret
229
+ const existingValue = transport.env[envKey];
230
+ let updated = false;
231
+ if (existingValue) {
232
+ const parsed = parseSecretRef(existingValue);
233
+ if (parsed) {
234
+ updated = true;
235
+ }
236
+ }
237
+ // Update config with new reference
238
+ transport.env[envKey] = storeResult.reference;
239
+ return {
240
+ config,
241
+ result: {
242
+ secretRef: storeResult.reference,
243
+ secretId: storeResult.id,
244
+ updated,
245
+ },
246
+ };
247
+ });
248
+ }
249
+ /**
250
+ * Remove orphan secrets not referenced by config
251
+ */
252
+ export async function pruneOrphanSecrets(options) {
253
+ const { configDir, configPath, dryRun = false, olderThanDays } = options;
254
+ const store = new SqliteSecretStore(configDir);
255
+ try {
256
+ const secretIds = await store.list();
257
+ // Load config to find active bindings
258
+ let config = { version: 1, connectors: [] };
259
+ if (existsSync(configPath)) {
260
+ config = JSON.parse(readFileSync(configPath, 'utf-8'));
261
+ }
262
+ const configRefs = collectConfigSecretRefs(config);
263
+ // Find orphans
264
+ const orphanIds = [];
265
+ const now = Date.now();
266
+ const ageThreshold = olderThanDays ? olderThanDays * 24 * 60 * 60 * 1000 : 0;
267
+ for (const id of secretIds) {
268
+ if (!configRefs.has(id)) {
269
+ // Check age if specified
270
+ if (ageThreshold > 0) {
271
+ const createdAt = await store.getCreatedAt(id);
272
+ if (createdAt) {
273
+ const age = now - createdAt.getTime();
274
+ if (age < ageThreshold) {
275
+ // Secret is too new, skip it
276
+ continue;
277
+ }
278
+ }
279
+ }
280
+ orphanIds.push(id);
281
+ }
282
+ }
283
+ // Remove orphans if not dry run
284
+ let removedCount = 0;
285
+ if (!dryRun) {
286
+ for (const id of orphanIds) {
287
+ const deleted = await store.delete(id);
288
+ if (deleted) {
289
+ removedCount++;
290
+ }
291
+ }
292
+ }
293
+ return {
294
+ orphanCount: orphanIds.length,
295
+ removedCount,
296
+ removedIds: orphanIds,
297
+ };
298
+ }
299
+ finally {
300
+ store.close();
301
+ }
302
+ }
303
+ /**
304
+ * Export secrets to encrypted bundle file
305
+ */
306
+ export async function exportSecrets(options) {
307
+ const { configDir, configPath, outputPath, passphrase } = options;
308
+ const store = new SqliteSecretStore(configDir);
309
+ try {
310
+ const secretIds = await store.list();
311
+ // Load config to get bindings
312
+ let config = { version: 1, connectors: [] };
313
+ if (existsSync(configPath)) {
314
+ config = JSON.parse(readFileSync(configPath, 'utf-8'));
315
+ }
316
+ const configRefs = collectConfigSecretRefs(config);
317
+ // Build entries
318
+ const entries = [];
319
+ for (const id of secretIds) {
320
+ const binding = configRefs.get(id);
321
+ if (!binding)
322
+ continue; // Skip orphans
323
+ // Retrieve plaintext (in-memory only)
324
+ const plaintext = await store.retrieve(id);
325
+ if (!plaintext)
326
+ continue;
327
+ entries.push({
328
+ connector_id: binding.connectorId,
329
+ env_key: binding.envKey,
330
+ secret_bytes_b64: Buffer.from(plaintext, 'utf-8').toString('base64'),
331
+ });
332
+ }
333
+ // Encrypt bundle
334
+ const payloadJson = JSON.stringify({ entries });
335
+ const payloadBytes = Buffer.from(payloadJson, 'utf-8');
336
+ const salt = randomBytes(16);
337
+ const key = deriveKey(passphrase, salt);
338
+ const { iv, authTag, ciphertext } = encryptPayload(payloadBytes, key);
339
+ // Prepare bundle metadata
340
+ const kdfInfo = {
341
+ name: 'scrypt',
342
+ salt: salt.toString('base64'),
343
+ N: SCRYPT_N,
344
+ r: SCRYPT_R,
345
+ p: SCRYPT_P,
346
+ keyLen: KEY_LEN,
347
+ };
348
+ const cipherInfo = {
349
+ name: 'aes-256-gcm',
350
+ iv: iv.toString('base64'),
351
+ authTag: authTag.toString('base64'),
352
+ };
353
+ // Compute HMAC over metadata to detect tampering of KDF/cipher parameters
354
+ const metadataForHmac = JSON.stringify({ version: 1, kdf: kdfInfo, cipher: cipherInfo });
355
+ const metadataHmac = createHmac('sha256', key).update(metadataForHmac).digest('base64');
356
+ const bundle = {
357
+ version: 1,
358
+ kdf: kdfInfo,
359
+ cipher: cipherInfo,
360
+ payload: ciphertext.toString('base64'),
361
+ metadataHmac,
362
+ };
363
+ // Write bundle to file
364
+ writeFileSync(outputPath, JSON.stringify(bundle, null, 2));
365
+ return {
366
+ exportedCount: entries.length,
367
+ };
368
+ }
369
+ finally {
370
+ store.close();
371
+ }
372
+ }
373
+ /**
374
+ * Import secrets from encrypted bundle file
375
+ */
376
+ export async function importSecrets(options) {
377
+ const { configDir, configPath, inputPath, passphrase, overwrite = false } = options;
378
+ // Read and parse bundle
379
+ const bundleJson = readFileSync(inputPath, 'utf-8');
380
+ const bundle = JSON.parse(bundleJson);
381
+ if (bundle.version !== 1) {
382
+ throw new Error(`Unsupported export bundle version: ${bundle.version}`);
383
+ }
384
+ // Derive key
385
+ const salt = Buffer.from(bundle.kdf.salt, 'base64');
386
+ const key = deriveKey(passphrase, salt);
387
+ // Verify HMAC before trusting metadata (prevents KDF parameter tampering)
388
+ // Uses timing-safe comparison to prevent timing attacks
389
+ const metadataForHmac = JSON.stringify({ version: bundle.version, kdf: bundle.kdf, cipher: bundle.cipher });
390
+ const expectedHmacBuf = createHmac('sha256', key).update(metadataForHmac).digest();
391
+ const actualHmacBuf = Buffer.from(bundle.metadataHmac, 'base64');
392
+ if (expectedHmacBuf.length !== actualHmacBuf.length || !timingSafeEqual(expectedHmacBuf, actualHmacBuf)) {
393
+ throw new Error('Bundle integrity check failed. The file may have been tampered with or the passphrase is incorrect.');
394
+ }
395
+ // Decrypt payload
396
+ const iv = Buffer.from(bundle.cipher.iv, 'base64');
397
+ const authTag = Buffer.from(bundle.cipher.authTag, 'base64');
398
+ const ciphertext = Buffer.from(bundle.payload, 'base64');
399
+ let payloadBytes;
400
+ try {
401
+ payloadBytes = decryptPayload(ciphertext, key, iv, authTag);
402
+ }
403
+ catch {
404
+ throw new Error('Decryption failed. Wrong passphrase?');
405
+ }
406
+ const payload = JSON.parse(payloadBytes.toString('utf-8'));
407
+ // Store secrets first (outside the config lock to minimize lock time)
408
+ const store = new SqliteSecretStore(configDir);
409
+ const storedSecrets = [];
410
+ const errors = [];
411
+ try {
412
+ for (const entry of payload.entries) {
413
+ try {
414
+ // Decode plaintext (in-memory only)
415
+ const plaintext = Buffer.from(entry.secret_bytes_b64, 'base64').toString('utf-8');
416
+ // Store secret
417
+ const result = await store.store(plaintext, {
418
+ connectorId: entry.connector_id,
419
+ keyName: entry.env_key,
420
+ source: `${entry.connector_id}.transport.env.${entry.env_key}`,
421
+ });
422
+ storedSecrets.push({ entry, reference: result.reference });
423
+ }
424
+ catch (err) {
425
+ errors.push({
426
+ connector_id: entry.connector_id,
427
+ env_key: entry.env_key,
428
+ error: err instanceof Error ? err.message : String(err),
429
+ });
430
+ }
431
+ }
432
+ }
433
+ finally {
434
+ store.close();
435
+ }
436
+ // If no secrets were stored, return early without touching config
437
+ if (storedSecrets.length === 0) {
438
+ return {
439
+ importedCount: 0,
440
+ skippedCount: payload.entries.length - errors.length,
441
+ errorCount: errors.length,
442
+ errors: errors.length > 0 ? errors : undefined,
443
+ };
444
+ }
445
+ // Update config with file locking to prevent race conditions
446
+ return withConfigLock(configPath, async (config) => {
447
+ let importedCount = 0;
448
+ let skippedCount = 0;
449
+ for (const { entry, reference } of storedSecrets) {
450
+ // Find connector
451
+ const connector = config.connectors?.find(c => c.id === entry.connector_id);
452
+ if (!connector) {
453
+ // Connector doesn't exist in config, skip
454
+ skippedCount++;
455
+ continue;
456
+ }
457
+ // Check if already has a secret ref
458
+ const transport = connector.transport;
459
+ const existingValue = transport?.env?.[entry.env_key];
460
+ if (existingValue && parseSecretRef(existingValue)) {
461
+ if (!overwrite) {
462
+ skippedCount++;
463
+ continue;
464
+ }
465
+ }
466
+ // Update config
467
+ if (!transport) {
468
+ connector.transport = { type: 'stdio', command: '' };
469
+ }
470
+ const t = connector.transport;
471
+ if (!t.env) {
472
+ t.env = {};
473
+ }
474
+ t.env[entry.env_key] = reference;
475
+ importedCount++;
476
+ }
477
+ return {
478
+ config,
479
+ result: {
480
+ importedCount,
481
+ skippedCount: skippedCount + (payload.entries.length - storedSecrets.length - errors.length),
482
+ errorCount: errors.length,
483
+ errors: errors.length > 0 ? errors : undefined,
484
+ },
485
+ };
486
+ });
487
+ }
488
+ //# sourceMappingURL=management.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"management.js","sourceRoot":"","sources":["../../src/secrets/management.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Secret reference resolution (Phase 3.6)
3
+ *
4
+ * Resolves secret references (dpapi:<id>, keychain:<id>, plain:<id>) in env vars
5
+ * to their plaintext values at runtime.
6
+ *
7
+ * Security:
8
+ * - Plaintext is only held in memory during process spawn
9
+ * - Never written to disk, logs, or config files
10
+ * - Original env with refs is not modified
11
+ */
12
+ /** Result of resolving env secrets */
13
+ export interface ResolveEnvSecretsResult {
14
+ /** Resolved env (with plaintext values) - SENSITIVE, in-memory only */
15
+ envResolved: Record<string, string>;
16
+ /** Secret refs that were successfully resolved */
17
+ resolvedRefs: string[];
18
+ /** Errors encountered during resolution */
19
+ errors: ResolveError[];
20
+ /** Whether resolution was fully successful */
21
+ success: boolean;
22
+ }
23
+ /** Error during secret resolution */
24
+ export interface ResolveError {
25
+ /** Environment key */
26
+ key: string;
27
+ /** Secret reference that failed */
28
+ ref: string;
29
+ /** Error message */
30
+ message: string;
31
+ /** Suggested fix command */
32
+ suggestion?: string;
33
+ }
34
+ /**
35
+ * Resolve secret references in env vars to plaintext values
36
+ *
37
+ * This function should be called just before spawning a child process.
38
+ * The returned envResolved should be passed to spawn() and then
39
+ * immediately discarded (not stored or logged).
40
+ *
41
+ * @param env - Environment variables potentially containing secret refs
42
+ * @param connectorId - Connector ID for error messages and suggestions
43
+ * @param configDir - Config directory (default: ~/.proofscan)
44
+ * @returns Resolved env and any errors
45
+ */
46
+ export declare function resolveEnvSecrets(env: Record<string, string> | undefined, connectorId: string, configDir?: string): Promise<ResolveEnvSecretsResult>;
47
+ /**
48
+ * Format resolution errors for user display
49
+ */
50
+ export declare function formatResolveErrors(errors: ResolveError[], connectorId: string): string[];
51
+ //# sourceMappingURL=resolve.d.ts.map