secretless-ai 0.4.0 → 0.6.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.
Files changed (93) hide show
  1. package/README.md +92 -5
  2. package/dist/backends/aws-sm.d.ts +23 -0
  3. package/dist/backends/aws-sm.d.ts.map +1 -0
  4. package/dist/backends/aws-sm.js +179 -0
  5. package/dist/backends/aws-sm.js.map +1 -0
  6. package/dist/backends/env.d.ts +11 -0
  7. package/dist/backends/env.d.ts.map +1 -0
  8. package/dist/backends/env.js +26 -0
  9. package/dist/backends/env.js.map +1 -0
  10. package/dist/backends/index.d.ts +38 -0
  11. package/dist/backends/index.d.ts.map +1 -0
  12. package/dist/backends/index.js +195 -0
  13. package/dist/backends/index.js.map +1 -0
  14. package/dist/backends/local.d.ts +20 -0
  15. package/dist/backends/local.d.ts.map +1 -0
  16. package/dist/backends/local.js +165 -0
  17. package/dist/backends/local.js.map +1 -0
  18. package/dist/backends/onepassword.d.ts +26 -0
  19. package/dist/backends/onepassword.d.ts.map +1 -0
  20. package/dist/backends/onepassword.js +182 -0
  21. package/dist/backends/onepassword.js.map +1 -0
  22. package/dist/backends/types.d.ts +40 -0
  23. package/dist/backends/types.d.ts.map +1 -0
  24. package/dist/backends/types.js +3 -0
  25. package/dist/backends/types.js.map +1 -0
  26. package/dist/backends/vault.d.ts +28 -0
  27. package/dist/backends/vault.d.ts.map +1 -0
  28. package/dist/backends/vault.js +157 -0
  29. package/dist/backends/vault.js.map +1 -0
  30. package/dist/cli.js +103 -0
  31. package/dist/cli.js.map +1 -1
  32. package/dist/connections/http-session.d.ts +23 -0
  33. package/dist/connections/http-session.d.ts.map +1 -0
  34. package/dist/connections/http-session.js +172 -0
  35. package/dist/connections/http-session.js.map +1 -0
  36. package/dist/connections/index.d.ts +4 -0
  37. package/dist/connections/index.d.ts.map +1 -0
  38. package/dist/connections/index.js +8 -0
  39. package/dist/connections/index.js.map +1 -0
  40. package/dist/connections/postgres.d.ts +25 -0
  41. package/dist/connections/postgres.d.ts.map +1 -0
  42. package/dist/connections/postgres.js +96 -0
  43. package/dist/connections/postgres.js.map +1 -0
  44. package/dist/connections/types.d.ts +50 -0
  45. package/dist/connections/types.d.ts.map +1 -0
  46. package/dist/connections/types.js +8 -0
  47. package/dist/connections/types.js.map +1 -0
  48. package/dist/index.d.ts +2 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +10 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/init.d.ts.map +1 -1
  53. package/dist/init.js +26 -0
  54. package/dist/init.js.map +1 -1
  55. package/dist/mcp/classify.d.ts +17 -0
  56. package/dist/mcp/classify.d.ts.map +1 -0
  57. package/dist/mcp/classify.js +139 -0
  58. package/dist/mcp/classify.js.map +1 -0
  59. package/dist/mcp/discover.d.ts +32 -0
  60. package/dist/mcp/discover.d.ts.map +1 -0
  61. package/dist/mcp/discover.js +179 -0
  62. package/dist/mcp/discover.js.map +1 -0
  63. package/dist/mcp/index.d.ts +7 -0
  64. package/dist/mcp/index.d.ts.map +1 -0
  65. package/dist/mcp/index.js +18 -0
  66. package/dist/mcp/index.js.map +1 -0
  67. package/dist/mcp/install-wrapper.d.ts +33 -0
  68. package/dist/mcp/install-wrapper.d.ts.map +1 -0
  69. package/dist/mcp/install-wrapper.js +153 -0
  70. package/dist/mcp/install-wrapper.js.map +1 -0
  71. package/dist/mcp/protect.d.ts +40 -0
  72. package/dist/mcp/protect.d.ts.map +1 -0
  73. package/dist/mcp/protect.js +121 -0
  74. package/dist/mcp/protect.js.map +1 -0
  75. package/dist/mcp/rewrite.d.ts +43 -0
  76. package/dist/mcp/rewrite.d.ts.map +1 -0
  77. package/dist/mcp/rewrite.js +212 -0
  78. package/dist/mcp/rewrite.js.map +1 -0
  79. package/dist/mcp/vault.d.ts +34 -0
  80. package/dist/mcp/vault.d.ts.map +1 -0
  81. package/dist/mcp/vault.js +91 -0
  82. package/dist/mcp/vault.js.map +1 -0
  83. package/dist/mcp-wrapper.d.ts +12 -0
  84. package/dist/mcp-wrapper.d.ts.map +1 -0
  85. package/dist/mcp-wrapper.js +142 -0
  86. package/dist/mcp-wrapper.js.map +1 -0
  87. package/dist/patterns.d.ts +10 -0
  88. package/dist/patterns.d.ts.map +1 -1
  89. package/dist/patterns.js +93 -13
  90. package/dist/patterns.js.map +1 -1
  91. package/dist/scan.js +2 -2
  92. package/dist/scan.js.map +1 -1
  93. package/package.json +6 -3
package/README.md CHANGED
@@ -11,7 +11,82 @@ Part of the [OpenA2A](https://opena2a.org) ecosystem — open-source security fo
11
11
  npx secretless-ai init
12
12
  ```
13
13
 
14
- ## The Problem
14
+ ## MCP Secret Protection
15
+
16
+ Every MCP server config has plaintext API keys sitting in JSON files on your laptop. The LLM sees them. Secretless encrypts them.
17
+
18
+ ```bash
19
+ npx secretless-ai protect-mcp
20
+ ```
21
+
22
+ ```
23
+ Secretless MCP Protection
24
+
25
+ Scanned 1 client(s)
26
+
27
+ + claude-desktop/browserbase
28
+ BROWSERBASE_API_KEY (encrypted)
29
+ + claude-desktop/github
30
+ GITHUB_PERSONAL_ACCESS_TOKEN (encrypted)
31
+ + claude-desktop/stripe
32
+ STRIPE_SECRET_KEY (encrypted)
33
+
34
+ 3 secret(s) encrypted across 3 server(s).
35
+
36
+ MCP servers will start normally — no workflow changes needed.
37
+ ```
38
+
39
+ **What happens:**
40
+
41
+ 1. Scans MCP configs across Claude Desktop, Cursor, Claude Code, VS Code, and Windsurf
42
+ 2. Identifies which env vars are secrets (key name patterns + value regex matching)
43
+ 3. Encrypts secrets into a local AES-256-GCM vault (`~/.secretless-ai/mcp-vault/`)
44
+ 4. Rewrites configs to use the `secretless-mcp` wrapper — decrypts at runtime, injects as env vars
45
+ 5. Non-secret env vars (URLs, org names, regions) stay in the config untouched
46
+
47
+ **Before:**
48
+ ```json
49
+ {
50
+ "mcpServers": {
51
+ "github": {
52
+ "command": "npx",
53
+ "args": ["@github/mcp-server"],
54
+ "env": {
55
+ "GITHUB_TOKEN": "ghp_plaintext_visible_to_LLM",
56
+ "GITHUB_ORG": "my-org"
57
+ }
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ **After:**
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "github": {
68
+ "command": "secretless-mcp",
69
+ "args": ["--server", "github", "--client", "claude-desktop", "--", "npx", "@github/mcp-server"],
70
+ "env": {
71
+ "GITHUB_ORG": "my-org"
72
+ }
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ The secret moves to the encrypted vault. The wrapper decrypts it at startup (<10ms overhead) and passes it to the MCP server as an env var. The LLM never sees it.
79
+
80
+ **Other MCP commands:**
81
+
82
+ ```bash
83
+ npx secretless-ai mcp-status # Show which servers are protected/exposed
84
+ npx secretless-ai mcp-unprotect # Restore original configs from backup
85
+ ```
86
+
87
+ ---
88
+
89
+ ## AI Context Protection
15
90
 
16
91
  AI coding tools read your files to provide context. That includes `.env` files, API keys in config, SSH keys, and cloud credentials. Once a secret enters an AI context window, it's sent to a remote API — and you can't take it back.
17
92
 
@@ -40,7 +115,7 @@ npx secretless-ai init
40
115
  Output:
41
116
 
42
117
  ```
43
- Secretless v0.3.0
118
+ Secretless v0.6.0
44
119
  Keeping secrets out of AI
45
120
 
46
121
  Detected:
@@ -114,7 +189,7 @@ Detects AI tools in your project and installs protections. If API keys are set a
114
189
 
115
190
  ### `npx secretless-ai scan`
116
191
 
117
- Scans config files for hardcoded credentials — both project-level and global (`~/.claude/CLAUDE.md`). Detects 12 credential patterns including Anthropic, OpenAI, AWS, GitHub, Slack, Google, Stripe, SendGrid, Supabase, and Azure keys.
192
+ Scans config files for hardcoded credentials — both project-level and global (`~/.claude/CLAUDE.md`). Detects 49 credential patterns including Anthropic, OpenAI, AWS, GitHub, Slack, Google, Stripe, SendGrid, Supabase, Azure, GitLab, Twilio, Mailgun, and more.
118
193
 
119
194
  ```
120
195
  Found 2 credential(s):
@@ -136,6 +211,18 @@ Confirms keys are usable but hidden from AI. Checks that env vars are set AND th
136
211
  PASS: Secrets are accessible via env vars but hidden from AI context.
137
212
  ```
138
213
 
214
+ ### `npx secretless-ai protect-mcp`
215
+
216
+ Scans all MCP configs on your machine, encrypts plaintext secrets into a local vault, and rewrites configs to use the `secretless-mcp` wrapper. Safe to run multiple times — skips already-protected servers.
217
+
218
+ ### `npx secretless-ai mcp-status`
219
+
220
+ Shows protection status for every MCP server across all clients. Tells you which servers have exposed secrets and which are protected.
221
+
222
+ ### `npx secretless-ai mcp-unprotect`
223
+
224
+ Restores all MCP configs to their original state from backups. One command to undo everything.
225
+
139
226
  ### `npx secretless-ai status`
140
227
 
141
228
  Shows current protection status.
@@ -154,9 +241,9 @@ Shows current protection status.
154
241
 
155
242
  `.env`, `.env.*`, `*.key`, `*.pem`, `*.p12`, `*.pfx`, `*.crt`, `.aws/credentials`, `.ssh/*`, `.docker/config.json`, `.git-credentials`, `.npmrc`, `.pypirc`, `*.tfstate`, `*.tfvars`, `secrets/`, `credentials/`
156
243
 
157
- ### Credential patterns (12)
244
+ ### Credential patterns (49)
158
245
 
159
- Anthropic API keys, OpenAI keys (project + legacy), AWS access keys, GitHub PATs (classic + fine-grained), Slack tokens, Google API keys, Stripe live keys, SendGrid keys, Supabase service keys, Azure keys
246
+ Anthropic API keys, OpenAI keys, AWS access keys, GitHub PATs, Slack tokens, Google API keys, Stripe keys, SendGrid keys, Supabase keys, Azure keys, GitLab tokens, Twilio keys, Mailgun keys, MongoDB URIs, JWTs, and 34 more
160
247
 
161
248
  ### Bash commands
162
249
 
@@ -0,0 +1,23 @@
1
+ import type { SecretBackend, BackendHealth } from './types';
2
+ /**
3
+ * AWS Secrets Manager backend — IAM/IRSA auth.
4
+ * Zero dependencies. Uses raw HTTP with AWS Signature V4.
5
+ *
6
+ * Config:
7
+ * region: AWS region (default: AWS_REGION or us-east-1)
8
+ * accessKeyId: (default: AWS_ACCESS_KEY_ID env)
9
+ * secretAccessKey: (default: AWS_SECRET_ACCESS_KEY env)
10
+ * sessionToken: (default: AWS_SESSION_TOKEN env — for IRSA/AssumeRole)
11
+ */
12
+ export declare class AWSSecretsManagerBackend implements SecretBackend {
13
+ readonly name = "aws-sm";
14
+ private readonly region;
15
+ private readonly accessKeyId;
16
+ private readonly secretAccessKey;
17
+ private readonly sessionToken;
18
+ constructor(config?: Record<string, unknown>);
19
+ resolve(secretPath: string): Promise<Record<string, string>>;
20
+ healthCheck(): Promise<BackendHealth>;
21
+ private signedRequest;
22
+ }
23
+ //# sourceMappingURL=aws-sm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aws-sm.d.ts","sourceRoot":"","sources":["../../src/backends/aws-sm.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;;;;GASG;AACH,qBAAa,wBAAyB,YAAW,aAAa;IAC5D,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAOtC,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAqB5D,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAoB3C,OAAO,CAAC,aAAa;CAoFtB"}
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AWSSecretsManagerBackend = void 0;
37
+ const https = __importStar(require("https"));
38
+ const crypto = __importStar(require("crypto"));
39
+ /**
40
+ * AWS Secrets Manager backend — IAM/IRSA auth.
41
+ * Zero dependencies. Uses raw HTTP with AWS Signature V4.
42
+ *
43
+ * Config:
44
+ * region: AWS region (default: AWS_REGION or us-east-1)
45
+ * accessKeyId: (default: AWS_ACCESS_KEY_ID env)
46
+ * secretAccessKey: (default: AWS_SECRET_ACCESS_KEY env)
47
+ * sessionToken: (default: AWS_SESSION_TOKEN env — for IRSA/AssumeRole)
48
+ */
49
+ class AWSSecretsManagerBackend {
50
+ constructor(config) {
51
+ this.name = 'aws-sm';
52
+ this.region = config?.region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? 'us-east-1';
53
+ this.accessKeyId = config?.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? '';
54
+ this.secretAccessKey = config?.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? '';
55
+ this.sessionToken = config?.sessionToken ?? process.env.AWS_SESSION_TOKEN ?? '';
56
+ }
57
+ async resolve(secretPath) {
58
+ try {
59
+ const body = JSON.stringify({ SecretId: secretPath });
60
+ const response = await this.signedRequest('GetSecretValue', body);
61
+ const data = JSON.parse(response);
62
+ if (data.SecretString) {
63
+ // Try to parse as JSON (common pattern)
64
+ try {
65
+ return JSON.parse(data.SecretString);
66
+ }
67
+ catch {
68
+ // Not JSON — return as single key-value
69
+ return { [secretPath]: data.SecretString };
70
+ }
71
+ }
72
+ return {};
73
+ }
74
+ catch {
75
+ return {};
76
+ }
77
+ }
78
+ async healthCheck() {
79
+ const start = Date.now();
80
+ try {
81
+ // List secrets (limited to 1) to verify auth
82
+ const body = JSON.stringify({ MaxResults: 1 });
83
+ await this.signedRequest('ListSecrets', body);
84
+ return {
85
+ healthy: true,
86
+ latencyMs: Date.now() - start,
87
+ message: `AWS Secrets Manager (${this.region})`,
88
+ };
89
+ }
90
+ catch (err) {
91
+ return {
92
+ healthy: false,
93
+ latencyMs: Date.now() - start,
94
+ message: `AWS SM error: ${err instanceof Error ? err.message : String(err)}`,
95
+ };
96
+ }
97
+ }
98
+ signedRequest(action, body) {
99
+ return new Promise((resolve, reject) => {
100
+ const host = `secretsmanager.${this.region}.amazonaws.com`;
101
+ const now = new Date();
102
+ const dateStamp = now.toISOString().replace(/[:-]|\.\d{3}/g, '').slice(0, 8);
103
+ const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
104
+ const headers = {
105
+ 'Content-Type': 'application/x-amz-json-1.1',
106
+ 'X-Amz-Target': `secretsmanager.${action}`,
107
+ 'X-Amz-Date': amzDate,
108
+ Host: host,
109
+ };
110
+ if (this.sessionToken) {
111
+ headers['X-Amz-Security-Token'] = this.sessionToken;
112
+ }
113
+ // AWS Signature V4
114
+ const canonicalHeaders = Object.entries(headers)
115
+ .sort(([a], [b]) => a.toLowerCase().localeCompare(b.toLowerCase()))
116
+ .map(([k, v]) => `${k.toLowerCase()}:${v}`)
117
+ .join('\n') + '\n';
118
+ const signedHeaders = Object.keys(headers)
119
+ .map((k) => k.toLowerCase())
120
+ .sort()
121
+ .join(';');
122
+ const payloadHash = crypto.createHash('sha256').update(body).digest('hex');
123
+ const canonicalRequest = [
124
+ 'POST',
125
+ '/',
126
+ '',
127
+ canonicalHeaders,
128
+ signedHeaders,
129
+ payloadHash,
130
+ ].join('\n');
131
+ const credentialScope = `${dateStamp}/${this.region}/secretsmanager/aws4_request`;
132
+ const stringToSign = [
133
+ 'AWS4-HMAC-SHA256',
134
+ amzDate,
135
+ credentialScope,
136
+ crypto.createHash('sha256').update(canonicalRequest).digest('hex'),
137
+ ].join('\n');
138
+ const signingKey = getSignatureKey(this.secretAccessKey, dateStamp, this.region, 'secretsmanager');
139
+ const signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex');
140
+ headers['Authorization'] = [
141
+ `AWS4-HMAC-SHA256 Credential=${this.accessKeyId}/${credentialScope}`,
142
+ `SignedHeaders=${signedHeaders}`,
143
+ `Signature=${signature}`,
144
+ ].join(', ');
145
+ const options = {
146
+ hostname: host,
147
+ port: 443,
148
+ path: '/',
149
+ method: 'POST',
150
+ headers: { ...headers, 'Content-Length': String(Buffer.byteLength(body)) },
151
+ timeout: 10000,
152
+ };
153
+ const req = https.request(options, (res) => {
154
+ let data = '';
155
+ res.on('data', (chunk) => { data += chunk; });
156
+ res.on('end', () => {
157
+ if (res.statusCode && res.statusCode >= 400) {
158
+ reject(new Error(`AWS SM ${res.statusCode}: ${data.slice(0, 200)}`));
159
+ }
160
+ else {
161
+ resolve(data);
162
+ }
163
+ });
164
+ });
165
+ req.on('error', reject);
166
+ req.on('timeout', () => { req.destroy(); reject(new Error('AWS SM request timeout')); });
167
+ req.write(body);
168
+ req.end();
169
+ });
170
+ }
171
+ }
172
+ exports.AWSSecretsManagerBackend = AWSSecretsManagerBackend;
173
+ function getSignatureKey(key, dateStamp, region, service) {
174
+ const kDate = crypto.createHmac('sha256', `AWS4${key}`).update(dateStamp).digest();
175
+ const kRegion = crypto.createHmac('sha256', kDate).update(region).digest();
176
+ const kService = crypto.createHmac('sha256', kRegion).update(service).digest();
177
+ return crypto.createHmac('sha256', kService).update('aws4_request').digest();
178
+ }
179
+ //# sourceMappingURL=aws-sm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aws-sm.js","sourceRoot":"","sources":["../../src/backends/aws-sm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { SecretBackend, BackendHealth } from './types';
2
+ /**
3
+ * Environment variable backend — resolves secrets from process.env.
4
+ * The simplest backend. Zero dependencies. Always available.
5
+ */
6
+ export declare class EnvBackend implements SecretBackend {
7
+ readonly name = "env";
8
+ resolve(path: string): Promise<Record<string, string>>;
9
+ healthCheck(): Promise<BackendHealth>;
10
+ }
11
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/backends/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE5D;;;GAGG;AACH,qBAAa,UAAW,YAAW,aAAa;IAC9C,QAAQ,CAAC,IAAI,SAAS;IAEhB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAYtD,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;CAG5C"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnvBackend = void 0;
4
+ /**
5
+ * Environment variable backend — resolves secrets from process.env.
6
+ * The simplest backend. Zero dependencies. Always available.
7
+ */
8
+ class EnvBackend {
9
+ constructor() {
10
+ this.name = 'env';
11
+ }
12
+ async resolve(path) {
13
+ // Path format: "ENV_VAR_NAME" or "prefix/ENV_VAR_NAME"
14
+ const varName = path.includes('/') ? path.split('/').pop() : path;
15
+ const value = process.env[varName];
16
+ if (value === undefined) {
17
+ return {};
18
+ }
19
+ return { [varName]: value };
20
+ }
21
+ async healthCheck() {
22
+ return { healthy: true, latencyMs: 0, message: 'Environment variables always available' };
23
+ }
24
+ }
25
+ exports.EnvBackend = EnvBackend;
26
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/backends/env.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACH,MAAa,UAAU;IAAvB;QACW,SAAI,GAAG,KAAK,CAAC;IAiBxB,CAAC;IAfC,KAAK,CAAC,OAAO,CAAC,IAAY;QACxB,uDAAuD;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QACnE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC;IAC5F,CAAC;CACF;AAlBD,gCAkBC"}
@@ -0,0 +1,38 @@
1
+ import type { SecretBackend, BackendConfig, BackendType, BackendHealth } from './types';
2
+ export type { SecretBackend, BackendConfig, BackendType, BackendHealth, AccessAuditEntry } from './types';
3
+ export { EnvBackend } from './env';
4
+ export { LocalBackend } from './local';
5
+ export { VaultBackend } from './vault';
6
+ export { AWSSecretsManagerBackend } from './aws-sm';
7
+ export { OnePasswordBackend } from './onepassword';
8
+ /** Create a backend instance from config */
9
+ export declare function createBackend(type: BackendType, config?: Record<string, unknown>): SecretBackend;
10
+ /**
11
+ * Backend registry — routes secret resolution to the right backend.
12
+ * Supports prefix-based routing and priority ordering.
13
+ */
14
+ export declare class BackendRegistry {
15
+ private readonly backends;
16
+ private readonly auditDir?;
17
+ constructor(configs?: BackendConfig[], auditDir?: string);
18
+ /** Resolve a secret, trying backends in priority order */
19
+ resolve(secretPath: string): Promise<Record<string, string>>;
20
+ /** Health check all backends */
21
+ healthCheckAll(): Promise<Array<{
22
+ name: string;
23
+ health: BackendHealth;
24
+ }>>;
25
+ /** List configured backends */
26
+ list(): Array<{
27
+ name: string;
28
+ prefix: string;
29
+ priority: number;
30
+ }>;
31
+ /** Migrate secrets from one backend to another */
32
+ migrate(fromBackend: SecretBackend, toBackend: SecretBackend, paths: string[]): Promise<{
33
+ migrated: number;
34
+ failed: number;
35
+ }>;
36
+ private audit;
37
+ }
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAoB,MAAM,SAAS,CAAC;AAS1G,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC1G,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAInD,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAUhG;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2E;IACpG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;gBAEvB,OAAO,CAAC,EAAE,aAAa,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM;IAqBxD,0DAA0D;IACpD,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IA0ClE,gCAAgC;IAC1B,cAAc,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAoB/E,+BAA+B;IAC/B,IAAI,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAQjE,kDAAkD;IAC5C,OAAO,CACX,WAAW,EAAE,aAAa,EAC1B,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IA4BhD,OAAO,CAAC,KAAK;CAad"}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BackendRegistry = exports.OnePasswordBackend = exports.AWSSecretsManagerBackend = exports.VaultBackend = exports.LocalBackend = exports.EnvBackend = void 0;
37
+ exports.createBackend = createBackend;
38
+ const env_1 = require("./env");
39
+ const local_1 = require("./local");
40
+ const vault_1 = require("./vault");
41
+ const aws_sm_1 = require("./aws-sm");
42
+ const onepassword_1 = require("./onepassword");
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ var env_2 = require("./env");
46
+ Object.defineProperty(exports, "EnvBackend", { enumerable: true, get: function () { return env_2.EnvBackend; } });
47
+ var local_2 = require("./local");
48
+ Object.defineProperty(exports, "LocalBackend", { enumerable: true, get: function () { return local_2.LocalBackend; } });
49
+ var vault_2 = require("./vault");
50
+ Object.defineProperty(exports, "VaultBackend", { enumerable: true, get: function () { return vault_2.VaultBackend; } });
51
+ var aws_sm_2 = require("./aws-sm");
52
+ Object.defineProperty(exports, "AWSSecretsManagerBackend", { enumerable: true, get: function () { return aws_sm_2.AWSSecretsManagerBackend; } });
53
+ var onepassword_2 = require("./onepassword");
54
+ Object.defineProperty(exports, "OnePasswordBackend", { enumerable: true, get: function () { return onepassword_2.OnePasswordBackend; } });
55
+ const AUDIT_FILE = 'access-audit.jsonl';
56
+ /** Create a backend instance from config */
57
+ function createBackend(type, config) {
58
+ switch (type) {
59
+ case 'env': return new env_1.EnvBackend();
60
+ case 'local': return new local_1.LocalBackend(config);
61
+ case 'vault': return new vault_1.VaultBackend(config);
62
+ case 'aws-sm': return new aws_sm_1.AWSSecretsManagerBackend(config);
63
+ case '1password': return new onepassword_1.OnePasswordBackend(config);
64
+ default:
65
+ throw new Error(`Unknown backend type: ${type}`);
66
+ }
67
+ }
68
+ /**
69
+ * Backend registry — routes secret resolution to the right backend.
70
+ * Supports prefix-based routing and priority ordering.
71
+ */
72
+ class BackendRegistry {
73
+ constructor(configs, auditDir) {
74
+ this.backends = [];
75
+ this.auditDir = auditDir;
76
+ if (configs && configs.length > 0) {
77
+ for (const cfg of configs) {
78
+ const backend = createBackend(cfg.type, cfg.config);
79
+ this.backends.push({
80
+ backend,
81
+ prefix: cfg.prefix ?? '',
82
+ priority: cfg.priority ?? 100,
83
+ });
84
+ }
85
+ }
86
+ else {
87
+ // Default: env backend
88
+ this.backends.push({ backend: new env_1.EnvBackend(), prefix: '', priority: 100 });
89
+ }
90
+ // Sort by priority (lower = preferred)
91
+ this.backends.sort((a, b) => a.priority - b.priority);
92
+ }
93
+ /** Resolve a secret, trying backends in priority order */
94
+ async resolve(secretPath) {
95
+ const start = Date.now();
96
+ for (const entry of this.backends) {
97
+ // Check prefix match
98
+ if (entry.prefix && !secretPath.startsWith(entry.prefix))
99
+ continue;
100
+ // Strip prefix before resolving
101
+ const resolvedPath = entry.prefix
102
+ ? secretPath.slice(entry.prefix.length).replace(/^\//, '')
103
+ : secretPath;
104
+ try {
105
+ const result = await entry.backend.resolve(resolvedPath);
106
+ if (Object.keys(result).length > 0) {
107
+ this.audit({
108
+ timestamp: new Date().toISOString(),
109
+ backend: entry.backend.name,
110
+ path: secretPath,
111
+ action: 'resolve',
112
+ success: true,
113
+ latencyMs: Date.now() - start,
114
+ });
115
+ return result;
116
+ }
117
+ }
118
+ catch {
119
+ // Try next backend
120
+ }
121
+ }
122
+ this.audit({
123
+ timestamp: new Date().toISOString(),
124
+ backend: 'none',
125
+ path: secretPath,
126
+ action: 'resolve',
127
+ success: false,
128
+ latencyMs: Date.now() - start,
129
+ });
130
+ return {};
131
+ }
132
+ /** Health check all backends */
133
+ async healthCheckAll() {
134
+ const results = [];
135
+ for (const entry of this.backends) {
136
+ const health = await entry.backend.healthCheck();
137
+ results.push({ name: entry.backend.name, health });
138
+ this.audit({
139
+ timestamp: new Date().toISOString(),
140
+ backend: entry.backend.name,
141
+ path: '',
142
+ action: 'healthCheck',
143
+ success: health.healthy,
144
+ latencyMs: health.latencyMs,
145
+ });
146
+ }
147
+ return results;
148
+ }
149
+ /** List configured backends */
150
+ list() {
151
+ return this.backends.map((e) => ({
152
+ name: e.backend.name,
153
+ prefix: e.prefix,
154
+ priority: e.priority,
155
+ }));
156
+ }
157
+ /** Migrate secrets from one backend to another */
158
+ async migrate(fromBackend, toBackend, paths) {
159
+ let migrated = 0;
160
+ let failed = 0;
161
+ for (const secretPath of paths) {
162
+ try {
163
+ const secrets = await fromBackend.resolve(secretPath);
164
+ if (Object.keys(secrets).length === 0) {
165
+ failed++;
166
+ continue;
167
+ }
168
+ // Store in target backend (if it supports store)
169
+ if ('store' in toBackend && typeof toBackend.store === 'function') {
170
+ for (const [key, value] of Object.entries(secrets)) {
171
+ await toBackend.store(key, value);
172
+ }
173
+ }
174
+ migrated++;
175
+ }
176
+ catch {
177
+ failed++;
178
+ }
179
+ }
180
+ return { migrated, failed };
181
+ }
182
+ audit(entry) {
183
+ if (!this.auditDir)
184
+ return;
185
+ try {
186
+ fs.mkdirSync(this.auditDir, { recursive: true });
187
+ fs.appendFileSync(path.join(this.auditDir, AUDIT_FILE), JSON.stringify(entry) + '\n', 'utf-8');
188
+ }
189
+ catch {
190
+ // Audit logging is best-effort
191
+ }
192
+ }
193
+ }
194
+ exports.BackendRegistry = BackendRegistry;
195
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"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"}