@id-wispera/core 0.1.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 (154) hide show
  1. package/README.md +268 -0
  2. package/dist/audit.d.ts +68 -0
  3. package/dist/audit.d.ts.map +1 -0
  4. package/dist/audit.js +252 -0
  5. package/dist/audit.js.map +1 -0
  6. package/dist/auth/index.d.ts +8 -0
  7. package/dist/auth/index.d.ts.map +1 -0
  8. package/dist/auth/index.js +8 -0
  9. package/dist/auth/index.js.map +1 -0
  10. package/dist/auth/keychainProvider.d.ts +40 -0
  11. package/dist/auth/keychainProvider.d.ts.map +1 -0
  12. package/dist/auth/keychainProvider.js +98 -0
  13. package/dist/auth/keychainProvider.js.map +1 -0
  14. package/dist/auth/passphraseProvider.d.ts +80 -0
  15. package/dist/auth/passphraseProvider.d.ts.map +1 -0
  16. package/dist/auth/passphraseProvider.js +188 -0
  17. package/dist/auth/passphraseProvider.js.map +1 -0
  18. package/dist/auth/sessionTokenManager.d.ts +106 -0
  19. package/dist/auth/sessionTokenManager.d.ts.map +1 -0
  20. package/dist/auth/sessionTokenManager.js +263 -0
  21. package/dist/auth/sessionTokenManager.js.map +1 -0
  22. package/dist/delegation.d.ts +81 -0
  23. package/dist/delegation.d.ts.map +1 -0
  24. package/dist/delegation.js +299 -0
  25. package/dist/delegation.js.map +1 -0
  26. package/dist/detection.d.ts +35 -0
  27. package/dist/detection.d.ts.map +1 -0
  28. package/dist/detection.js +474 -0
  29. package/dist/detection.js.map +1 -0
  30. package/dist/exec/execManager.d.ts +60 -0
  31. package/dist/exec/execManager.d.ts.map +1 -0
  32. package/dist/exec/execManager.js +226 -0
  33. package/dist/exec/execManager.js.map +1 -0
  34. package/dist/exec/index.d.ts +6 -0
  35. package/dist/exec/index.d.ts.map +1 -0
  36. package/dist/exec/index.js +5 -0
  37. package/dist/exec/index.js.map +1 -0
  38. package/dist/index.d.ts +35 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +98 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/integrations/base.d.ts +64 -0
  43. package/dist/integrations/base.d.ts.map +1 -0
  44. package/dist/integrations/base.js +173 -0
  45. package/dist/integrations/base.js.map +1 -0
  46. package/dist/integrations/envMapping.d.ts +47 -0
  47. package/dist/integrations/envMapping.d.ts.map +1 -0
  48. package/dist/integrations/envMapping.js +174 -0
  49. package/dist/integrations/envMapping.js.map +1 -0
  50. package/dist/integrations/google-a2a.d.ts +48 -0
  51. package/dist/integrations/google-a2a.d.ts.map +1 -0
  52. package/dist/integrations/google-a2a.js +108 -0
  53. package/dist/integrations/google-a2a.js.map +1 -0
  54. package/dist/integrations/index.d.ts +14 -0
  55. package/dist/integrations/index.d.ts.map +1 -0
  56. package/dist/integrations/index.js +14 -0
  57. package/dist/integrations/index.js.map +1 -0
  58. package/dist/integrations/langchain.d.ts +38 -0
  59. package/dist/integrations/langchain.d.ts.map +1 -0
  60. package/dist/integrations/langchain.js +45 -0
  61. package/dist/integrations/langchain.js.map +1 -0
  62. package/dist/integrations/openai-agents.d.ts +76 -0
  63. package/dist/integrations/openai-agents.d.ts.map +1 -0
  64. package/dist/integrations/openai-agents.js +95 -0
  65. package/dist/integrations/openai-agents.js.map +1 -0
  66. package/dist/integrations/slack.d.ts +59 -0
  67. package/dist/integrations/slack.d.ts.map +1 -0
  68. package/dist/integrations/slack.js +113 -0
  69. package/dist/integrations/slack.js.map +1 -0
  70. package/dist/integrations/types.d.ts +107 -0
  71. package/dist/integrations/types.d.ts.map +1 -0
  72. package/dist/integrations/types.js +6 -0
  73. package/dist/integrations/types.js.map +1 -0
  74. package/dist/locations.d.ts +157 -0
  75. package/dist/locations.d.ts.map +1 -0
  76. package/dist/locations.js +733 -0
  77. package/dist/locations.js.map +1 -0
  78. package/dist/passport.d.ts +70 -0
  79. package/dist/passport.d.ts.map +1 -0
  80. package/dist/passport.js +429 -0
  81. package/dist/passport.js.map +1 -0
  82. package/dist/policy.d.ts +80 -0
  83. package/dist/policy.d.ts.map +1 -0
  84. package/dist/policy.js +392 -0
  85. package/dist/policy.js.map +1 -0
  86. package/dist/providers/openclaw.d.ts +80 -0
  87. package/dist/providers/openclaw.d.ts.map +1 -0
  88. package/dist/providers/openclaw.js +712 -0
  89. package/dist/providers/openclaw.js.map +1 -0
  90. package/dist/provisioning/adminPassport.d.ts +51 -0
  91. package/dist/provisioning/adminPassport.d.ts.map +1 -0
  92. package/dist/provisioning/adminPassport.js +101 -0
  93. package/dist/provisioning/adminPassport.js.map +1 -0
  94. package/dist/provisioning/index.d.ts +81 -0
  95. package/dist/provisioning/index.d.ts.map +1 -0
  96. package/dist/provisioning/index.js +141 -0
  97. package/dist/provisioning/index.js.map +1 -0
  98. package/dist/provisioning/provider.d.ts +59 -0
  99. package/dist/provisioning/provider.d.ts.map +1 -0
  100. package/dist/provisioning/provider.js +52 -0
  101. package/dist/provisioning/provider.js.map +1 -0
  102. package/dist/provisioning/providers/anthropic.d.ts +32 -0
  103. package/dist/provisioning/providers/anthropic.d.ts.map +1 -0
  104. package/dist/provisioning/providers/anthropic.js +116 -0
  105. package/dist/provisioning/providers/anthropic.js.map +1 -0
  106. package/dist/provisioning/providers/aws.d.ts +29 -0
  107. package/dist/provisioning/providers/aws.d.ts.map +1 -0
  108. package/dist/provisioning/providers/aws.js +455 -0
  109. package/dist/provisioning/providers/aws.js.map +1 -0
  110. package/dist/provisioning/providers/azure-entra.d.ts +32 -0
  111. package/dist/provisioning/providers/azure-entra.d.ts.map +1 -0
  112. package/dist/provisioning/providers/azure-entra.js +312 -0
  113. package/dist/provisioning/providers/azure-entra.js.map +1 -0
  114. package/dist/provisioning/providers/github.d.ts +24 -0
  115. package/dist/provisioning/providers/github.d.ts.map +1 -0
  116. package/dist/provisioning/providers/github.js +219 -0
  117. package/dist/provisioning/providers/github.js.map +1 -0
  118. package/dist/provisioning/providers/google-cloud.d.ts +34 -0
  119. package/dist/provisioning/providers/google-cloud.d.ts.map +1 -0
  120. package/dist/provisioning/providers/google-cloud.js +366 -0
  121. package/dist/provisioning/providers/google-cloud.js.map +1 -0
  122. package/dist/provisioning/providers/openai.d.ts +29 -0
  123. package/dist/provisioning/providers/openai.d.ts.map +1 -0
  124. package/dist/provisioning/providers/openai.js +263 -0
  125. package/dist/provisioning/providers/openai.js.map +1 -0
  126. package/dist/provisioning/providers/sendgrid.d.ts +27 -0
  127. package/dist/provisioning/providers/sendgrid.d.ts.map +1 -0
  128. package/dist/provisioning/providers/sendgrid.js +186 -0
  129. package/dist/provisioning/providers/sendgrid.js.map +1 -0
  130. package/dist/provisioning/providers/twilio.d.ts +27 -0
  131. package/dist/provisioning/providers/twilio.d.ts.map +1 -0
  132. package/dist/provisioning/providers/twilio.js +194 -0
  133. package/dist/provisioning/providers/twilio.js.map +1 -0
  134. package/dist/provisioning/types.d.ts +274 -0
  135. package/dist/provisioning/types.d.ts.map +1 -0
  136. package/dist/provisioning/types.js +6 -0
  137. package/dist/provisioning/types.js.map +1 -0
  138. package/dist/sharing.d.ts +60 -0
  139. package/dist/sharing.d.ts.map +1 -0
  140. package/dist/sharing.js +305 -0
  141. package/dist/sharing.js.map +1 -0
  142. package/dist/types.d.ts +396 -0
  143. package/dist/types.d.ts.map +1 -0
  144. package/dist/types.js +88 -0
  145. package/dist/types.js.map +1 -0
  146. package/dist/utils.d.ts +45 -0
  147. package/dist/utils.d.ts.map +1 -0
  148. package/dist/utils.js +110 -0
  149. package/dist/utils.js.map +1 -0
  150. package/dist/vault.d.ts +151 -0
  151. package/dist/vault.d.ts.map +1 -0
  152. package/dist/vault.js +499 -0
  153. package/dist/vault.js.map +1 -0
  154. package/package.json +117 -0
@@ -0,0 +1,733 @@
1
+ /**
2
+ * ID Wispera Credential Locations Registry
3
+ * Defines well-known credential storage paths for various providers
4
+ */
5
+ import { homedir } from 'os';
6
+ import { join } from 'path';
7
+ // ============================================================================
8
+ // Path Helpers
9
+ // ============================================================================
10
+ /**
11
+ * Expand path patterns like {home} to actual paths
12
+ */
13
+ export function expandPath(pattern, vars = {}) {
14
+ let result = pattern;
15
+ result = result.replace('{home}', homedir());
16
+ for (const [key, value] of Object.entries(vars)) {
17
+ result = result.replace(`{${key}}`, value);
18
+ }
19
+ return result;
20
+ }
21
+ /**
22
+ * Get the home directory
23
+ */
24
+ export function getHomeDir() {
25
+ return homedir();
26
+ }
27
+ // ============================================================================
28
+ // OpenClaw Provider
29
+ // ============================================================================
30
+ /**
31
+ * Parse WhatsApp credentials from creds.json
32
+ */
33
+ function parseWhatsAppCreds(filePath, content) {
34
+ try {
35
+ const data = JSON.parse(content);
36
+ const credentials = [];
37
+ // Extract account ID from path or me.id
38
+ const pathMatch = filePath.match(/whatsapp\/([^/]+)\/creds\.json$/);
39
+ const accountId = pathMatch?.[1] || data.me?.id?.split(':')[0] || 'unknown';
40
+ const phoneNumber = data.me?.id?.split(':')[0] || accountId;
41
+ // The entire creds.json is a sensitive session credential
42
+ credentials.push({
43
+ provider: 'openclaw',
44
+ filePath,
45
+ classification: {
46
+ name: `WhatsApp Session (${accountId})`,
47
+ credentialType: 'session-keys',
48
+ visaType: 'access',
49
+ riskLevel: 'high',
50
+ platforms: ['openclaw', 'whatsapp'],
51
+ tags: ['openclaw', 'whatsapp', 'session', 'imported'],
52
+ issuingAuthority: 'OpenClaw (self-managed)',
53
+ },
54
+ rawValue: content,
55
+ metadata: {
56
+ accountId,
57
+ phoneNumber,
58
+ botName: data.me?.name,
59
+ registrationId: data.registrationId,
60
+ hasNoiseKey: !!data.noiseKey,
61
+ hasSignedIdentityKey: !!data.signedIdentityKey,
62
+ hasSignedPreKey: !!data.signedPreKey,
63
+ },
64
+ });
65
+ return credentials;
66
+ }
67
+ catch {
68
+ return [];
69
+ }
70
+ }
71
+ /**
72
+ * Parse channel allowlist files
73
+ */
74
+ function parseAllowlist(filePath, content) {
75
+ try {
76
+ const data = JSON.parse(content);
77
+ const credentials = [];
78
+ // Extract channel name from filename
79
+ const fileMatch = filePath.match(/([^/]+)-allowFrom\.json$/);
80
+ const channel = fileMatch?.[1] || 'unknown';
81
+ const pairedCount = Object.keys(data).length;
82
+ credentials.push({
83
+ provider: 'openclaw',
84
+ filePath,
85
+ classification: {
86
+ name: `Pairing Allowlist: ${channel} (${pairedCount} users)`,
87
+ credentialType: 'custom',
88
+ visaType: 'access',
89
+ riskLevel: 'low',
90
+ platforms: ['openclaw', channel],
91
+ tags: ['openclaw', channel, 'allowlist', 'imported'],
92
+ issuingAuthority: 'OpenClaw (self-managed)',
93
+ },
94
+ rawValue: content,
95
+ metadata: {
96
+ channel,
97
+ pairedUsers: Object.entries(data).map(([id, info]) => ({
98
+ id,
99
+ name: info.name,
100
+ pairedAt: info.pairedAt,
101
+ })),
102
+ pairedCount,
103
+ },
104
+ });
105
+ return credentials;
106
+ }
107
+ catch {
108
+ return [];
109
+ }
110
+ }
111
+ /**
112
+ * Parse auth-profiles.json for LLM API keys
113
+ */
114
+ function parseAuthProfiles(filePath, content) {
115
+ try {
116
+ const data = JSON.parse(content);
117
+ const credentials = [];
118
+ // Extract agent ID from path
119
+ const pathMatch = filePath.match(/agents\/([^/]+)\/agent\/auth-profiles\.json$/);
120
+ const agentId = pathMatch?.[1] || 'unknown';
121
+ for (const [provider, profile] of Object.entries(data)) {
122
+ if (profile.type === 'api-key' && profile.key) {
123
+ const keyPreview = profile.key.substring(0, 10) + '...' +
124
+ profile.key.substring(profile.key.length - 4);
125
+ credentials.push({
126
+ provider: 'openclaw',
127
+ filePath,
128
+ classification: {
129
+ name: `${capitalizeFirst(provider)} API Key (${keyPreview})`,
130
+ credentialType: 'api-key',
131
+ visaType: 'privilege',
132
+ riskLevel: 'critical',
133
+ platforms: ['openclaw', 'mcp', provider],
134
+ tags: ['openclaw', provider, 'api-key', 'llm', 'imported'],
135
+ issuingAuthority: 'OpenClaw (self-managed)',
136
+ context: { agentId, model: profile.model },
137
+ },
138
+ rawValue: profile.key,
139
+ metadata: {
140
+ agentId,
141
+ provider,
142
+ model: profile.model,
143
+ keyType: profile.type,
144
+ },
145
+ });
146
+ }
147
+ }
148
+ return credentials;
149
+ }
150
+ catch {
151
+ return [];
152
+ }
153
+ }
154
+ /**
155
+ * Parse oauth.json for OAuth tokens
156
+ */
157
+ function parseOAuthTokens(filePath, content) {
158
+ try {
159
+ const data = JSON.parse(content);
160
+ const credentials = [];
161
+ for (const [provider, tokens] of Object.entries(data)) {
162
+ if (tokens.access_token) {
163
+ const tokenPreview = tokens.access_token.substring(0, 10) + '...';
164
+ const expiresAt = tokens.expires_at ? new Date(tokens.expires_at * 1000) : undefined;
165
+ const isExpired = expiresAt && expiresAt < new Date();
166
+ credentials.push({
167
+ provider: 'openclaw',
168
+ filePath,
169
+ classification: {
170
+ name: `${capitalizeFirst(provider)} OAuth Token (${tokenPreview})`,
171
+ credentialType: 'oauth-token',
172
+ visaType: 'access',
173
+ riskLevel: 'medium',
174
+ platforms: ['openclaw', provider],
175
+ tags: ['openclaw', provider, 'oauth', 'imported', ...(isExpired ? ['expired'] : [])],
176
+ issuingAuthority: 'OpenClaw (self-managed)',
177
+ },
178
+ rawValue: tokens.access_token,
179
+ metadata: {
180
+ provider,
181
+ hasRefreshToken: !!tokens.refresh_token,
182
+ tokenType: tokens.token_type,
183
+ expiresAt: expiresAt?.toISOString(),
184
+ isExpired,
185
+ },
186
+ expiresAt,
187
+ });
188
+ }
189
+ }
190
+ return credentials;
191
+ }
192
+ catch {
193
+ return [];
194
+ }
195
+ }
196
+ /**
197
+ * Parse openclaw.json for channel tokens and gateway config
198
+ */
199
+ function parseOpenClawConfig(filePath, content) {
200
+ try {
201
+ const data = JSON.parse(content);
202
+ const credentials = [];
203
+ // Parse channel tokens
204
+ if (data.channels) {
205
+ for (const [channel, config] of Object.entries(data.channels)) {
206
+ // Telegram bot token
207
+ if (channel === 'telegram' && config.token) {
208
+ const tokenPreview = config.token.substring(0, 7) + '...' +
209
+ config.token.substring(config.token.length - 4);
210
+ credentials.push({
211
+ provider: 'openclaw',
212
+ filePath,
213
+ classification: {
214
+ name: `Telegram Bot Token (${tokenPreview})`,
215
+ credentialType: 'api-key',
216
+ visaType: 'access',
217
+ riskLevel: 'high',
218
+ platforms: ['openclaw', 'telegram'],
219
+ tags: ['openclaw', 'telegram', 'bot-token', 'imported'],
220
+ issuingAuthority: 'OpenClaw (self-managed)',
221
+ },
222
+ rawValue: config.token,
223
+ metadata: { channel: 'telegram' },
224
+ });
225
+ }
226
+ // Slack tokens
227
+ if (channel === 'slack') {
228
+ if (config.botToken) {
229
+ const tokenPreview = config.botToken.substring(0, 10) + '...' +
230
+ config.botToken.substring(config.botToken.length - 4);
231
+ credentials.push({
232
+ provider: 'openclaw',
233
+ filePath,
234
+ classification: {
235
+ name: `Slack Bot Token (${tokenPreview})`,
236
+ credentialType: 'api-key',
237
+ visaType: 'access',
238
+ riskLevel: 'high',
239
+ platforms: ['openclaw', 'slack'],
240
+ tags: ['openclaw', 'slack', 'bot-token', 'imported'],
241
+ issuingAuthority: 'OpenClaw (self-managed)',
242
+ },
243
+ rawValue: config.botToken,
244
+ metadata: { channel: 'slack', tokenType: 'bot' },
245
+ });
246
+ }
247
+ if (config.appToken) {
248
+ const tokenPreview = config.appToken.substring(0, 10) + '...' +
249
+ config.appToken.substring(config.appToken.length - 4);
250
+ credentials.push({
251
+ provider: 'openclaw',
252
+ filePath,
253
+ classification: {
254
+ name: `Slack App Token (${tokenPreview})`,
255
+ credentialType: 'api-key',
256
+ visaType: 'access',
257
+ riskLevel: 'high',
258
+ platforms: ['openclaw', 'slack'],
259
+ tags: ['openclaw', 'slack', 'app-token', 'imported'],
260
+ issuingAuthority: 'OpenClaw (self-managed)',
261
+ },
262
+ rawValue: config.appToken,
263
+ metadata: { channel: 'slack', tokenType: 'app' },
264
+ });
265
+ }
266
+ }
267
+ // Discord token
268
+ if (channel === 'discord' && config.token) {
269
+ const tokenPreview = config.token.substring(0, 10) + '...' +
270
+ config.token.substring(config.token.length - 4);
271
+ credentials.push({
272
+ provider: 'openclaw',
273
+ filePath,
274
+ classification: {
275
+ name: `Discord Bot Token (${tokenPreview})`,
276
+ credentialType: 'api-key',
277
+ visaType: 'access',
278
+ riskLevel: 'high',
279
+ platforms: ['openclaw', 'discord'],
280
+ tags: ['openclaw', 'discord', 'bot-token', 'imported'],
281
+ issuingAuthority: 'OpenClaw (self-managed)',
282
+ },
283
+ rawValue: config.token,
284
+ metadata: { channel: 'discord' },
285
+ });
286
+ }
287
+ }
288
+ }
289
+ // Parse gateway token
290
+ if (data.gateway?.token) {
291
+ const tokenPreview = data.gateway.token.substring(0, 6) + '...' +
292
+ data.gateway.token.substring(data.gateway.token.length - 4);
293
+ credentials.push({
294
+ provider: 'openclaw',
295
+ filePath,
296
+ classification: {
297
+ name: `Gateway Token (${tokenPreview})`,
298
+ credentialType: 'api-key',
299
+ visaType: 'privilege',
300
+ riskLevel: 'high',
301
+ platforms: ['openclaw'],
302
+ tags: ['openclaw', 'gateway', 'admin', 'imported'],
303
+ issuingAuthority: 'OpenClaw (self-managed)',
304
+ },
305
+ rawValue: data.gateway.token,
306
+ metadata: {
307
+ gatewayPort: data.gateway.port,
308
+ },
309
+ });
310
+ }
311
+ return credentials;
312
+ }
313
+ catch {
314
+ return [];
315
+ }
316
+ }
317
+ /**
318
+ * Helper to capitalize first letter
319
+ */
320
+ function capitalizeFirst(str) {
321
+ return str.charAt(0).toUpperCase() + str.slice(1);
322
+ }
323
+ /**
324
+ * OpenClaw provider definition
325
+ */
326
+ export const openclawProvider = {
327
+ id: 'openclaw',
328
+ name: 'OpenClaw',
329
+ description: 'OpenClaw AI agent framework credentials',
330
+ detect: async () => {
331
+ const fs = await import('fs/promises');
332
+ const openclawPath = join(homedir(), '.openclaw');
333
+ try {
334
+ await fs.access(openclawPath);
335
+ return true;
336
+ }
337
+ catch {
338
+ return false;
339
+ }
340
+ },
341
+ locations: [
342
+ {
343
+ id: 'whatsapp-creds',
344
+ name: 'WhatsApp Credentials',
345
+ pathPattern: '{home}/.openclaw/credentials/whatsapp',
346
+ filePattern: '**/creds.json',
347
+ parse: parseWhatsAppCreds,
348
+ },
349
+ {
350
+ id: 'channel-allowlists',
351
+ name: 'Channel Allowlists',
352
+ pathPattern: '{home}/.openclaw/credentials',
353
+ filePattern: '*-allowFrom.json',
354
+ parse: parseAllowlist,
355
+ },
356
+ {
357
+ id: 'auth-profiles',
358
+ name: 'LLM Auth Profiles',
359
+ pathPattern: '{home}/.openclaw/agents',
360
+ filePattern: '**/agent/auth-profiles.json',
361
+ parse: parseAuthProfiles,
362
+ },
363
+ {
364
+ id: 'oauth-tokens',
365
+ name: 'OAuth Tokens',
366
+ pathPattern: '{home}/.openclaw/credentials',
367
+ filePattern: 'oauth.json',
368
+ parse: parseOAuthTokens,
369
+ },
370
+ {
371
+ id: 'config',
372
+ name: 'OpenClaw Config',
373
+ pathPattern: '{home}/.openclaw',
374
+ filePattern: 'openclaw.json',
375
+ parse: parseOpenClawConfig,
376
+ },
377
+ ],
378
+ };
379
+ // ============================================================================
380
+ // Other Common Providers
381
+ // ============================================================================
382
+ /**
383
+ * AWS provider definition
384
+ */
385
+ export const awsProvider = {
386
+ id: 'aws',
387
+ name: 'AWS',
388
+ description: 'Amazon Web Services credentials',
389
+ detect: async () => {
390
+ const fs = await import('fs/promises');
391
+ try {
392
+ await fs.access(join(homedir(), '.aws'));
393
+ return true;
394
+ }
395
+ catch {
396
+ return false;
397
+ }
398
+ },
399
+ locations: [
400
+ {
401
+ id: 'credentials',
402
+ name: 'AWS Credentials',
403
+ pathPattern: '{home}/.aws',
404
+ filePattern: 'credentials',
405
+ parse: (filePath, content) => {
406
+ const credentials = [];
407
+ const profileRegex = /\[([^\]]+)\]\s*\n((?:[^[]*(?:\n|$))*)/g;
408
+ let match;
409
+ while ((match = profileRegex.exec(content)) !== null) {
410
+ const profileName = match[1] ?? 'default';
411
+ const profileContent = match[2] ?? '';
412
+ const accessKeyMatch = profileContent.match(/aws_access_key_id\s*=\s*(\S+)/);
413
+ const secretKeyMatch = profileContent.match(/aws_secret_access_key\s*=\s*(\S+)/);
414
+ if (accessKeyMatch?.[1] && secretKeyMatch?.[1]) {
415
+ const keyPreview = accessKeyMatch[1].substring(0, 8) + '...';
416
+ credentials.push({
417
+ provider: 'aws',
418
+ filePath,
419
+ classification: {
420
+ name: `AWS Access Key [${profileName}] (${keyPreview})`,
421
+ credentialType: 'api-key',
422
+ visaType: 'privilege',
423
+ riskLevel: 'critical',
424
+ platforms: ['aws'],
425
+ tags: ['aws', profileName, 'imported'],
426
+ issuingAuthority: 'AWS IAM',
427
+ },
428
+ rawValue: `${accessKeyMatch[1]}:${secretKeyMatch[1]}`,
429
+ metadata: {
430
+ profile: profileName,
431
+ accessKeyId: accessKeyMatch[1],
432
+ },
433
+ });
434
+ }
435
+ }
436
+ return credentials;
437
+ },
438
+ },
439
+ ],
440
+ };
441
+ /**
442
+ * SSH provider definition
443
+ */
444
+ export const sshProvider = {
445
+ id: 'ssh',
446
+ name: 'SSH',
447
+ description: 'SSH private keys',
448
+ detect: async () => {
449
+ const fs = await import('fs/promises');
450
+ try {
451
+ await fs.access(join(homedir(), '.ssh'));
452
+ return true;
453
+ }
454
+ catch {
455
+ return false;
456
+ }
457
+ },
458
+ locations: [
459
+ {
460
+ id: 'private-keys',
461
+ name: 'SSH Private Keys',
462
+ pathPattern: '{home}/.ssh',
463
+ filePattern: 'id_*',
464
+ parse: (filePath, content) => {
465
+ const credentials = [];
466
+ // Only process private keys (not .pub files)
467
+ if (filePath.endsWith('.pub'))
468
+ return credentials;
469
+ // Check if it's a private key
470
+ if (content.includes('PRIVATE KEY')) {
471
+ const keyType = content.includes('RSA') ? 'RSA' :
472
+ content.includes('EC') ? 'EC' :
473
+ content.includes('OPENSSH') ? 'OpenSSH' : 'Unknown';
474
+ const fileName = filePath.split('/').pop() || 'unknown';
475
+ credentials.push({
476
+ provider: 'ssh',
477
+ filePath,
478
+ classification: {
479
+ name: `SSH Private Key (${fileName})`,
480
+ credentialType: 'private-key',
481
+ visaType: 'access',
482
+ riskLevel: 'high',
483
+ platforms: ['ssh'],
484
+ tags: ['ssh', keyType.toLowerCase(), 'imported'],
485
+ issuingAuthority: 'Self-generated',
486
+ },
487
+ rawValue: content,
488
+ metadata: {
489
+ keyType,
490
+ fileName,
491
+ },
492
+ });
493
+ }
494
+ return credentials;
495
+ },
496
+ },
497
+ ],
498
+ };
499
+ /**
500
+ * Docker provider definition
501
+ */
502
+ export const dockerProvider = {
503
+ id: 'docker',
504
+ name: 'Docker',
505
+ description: 'Docker registry credentials',
506
+ detect: async () => {
507
+ const fs = await import('fs/promises');
508
+ try {
509
+ await fs.access(join(homedir(), '.docker', 'config.json'));
510
+ return true;
511
+ }
512
+ catch {
513
+ return false;
514
+ }
515
+ },
516
+ locations: [
517
+ {
518
+ id: 'config',
519
+ name: 'Docker Config',
520
+ pathPattern: '{home}/.docker',
521
+ filePattern: 'config.json',
522
+ parse: (filePath, content) => {
523
+ const credentials = [];
524
+ try {
525
+ const data = JSON.parse(content);
526
+ if (data.auths) {
527
+ for (const [registry, auth] of Object.entries(data.auths)) {
528
+ if (auth.auth) {
529
+ credentials.push({
530
+ provider: 'docker',
531
+ filePath,
532
+ classification: {
533
+ name: `Docker Registry (${registry})`,
534
+ credentialType: 'api-key',
535
+ visaType: 'access',
536
+ riskLevel: 'medium',
537
+ platforms: ['docker'],
538
+ tags: ['docker', 'registry', 'imported'],
539
+ issuingAuthority: registry,
540
+ },
541
+ rawValue: auth.auth,
542
+ metadata: {
543
+ registry,
544
+ },
545
+ });
546
+ }
547
+ }
548
+ }
549
+ }
550
+ catch {
551
+ // Invalid JSON
552
+ }
553
+ return credentials;
554
+ },
555
+ },
556
+ ],
557
+ };
558
+ /**
559
+ * npm provider definition
560
+ */
561
+ export const npmProvider = {
562
+ id: 'npm',
563
+ name: 'npm',
564
+ description: 'npm registry tokens',
565
+ detect: async () => {
566
+ const fs = await import('fs/promises');
567
+ try {
568
+ await fs.access(join(homedir(), '.npmrc'));
569
+ return true;
570
+ }
571
+ catch {
572
+ return false;
573
+ }
574
+ },
575
+ locations: [
576
+ {
577
+ id: 'npmrc',
578
+ name: 'npm Config',
579
+ pathPattern: '{home}',
580
+ filePattern: '.npmrc',
581
+ parse: (filePath, content) => {
582
+ const credentials = [];
583
+ // Match auth tokens
584
+ const tokenMatch = content.match(/_authToken=([^\s\n]+)/);
585
+ if (tokenMatch?.[1]) {
586
+ const tokenPreview = tokenMatch[1].substring(0, 8) + '...';
587
+ credentials.push({
588
+ provider: 'npm',
589
+ filePath,
590
+ classification: {
591
+ name: `npm Auth Token (${tokenPreview})`,
592
+ credentialType: 'api-key',
593
+ visaType: 'access',
594
+ riskLevel: 'medium',
595
+ platforms: ['npm'],
596
+ tags: ['npm', 'registry', 'imported'],
597
+ issuingAuthority: 'npm Registry',
598
+ },
599
+ rawValue: tokenMatch[1],
600
+ metadata: {},
601
+ });
602
+ }
603
+ return credentials;
604
+ },
605
+ },
606
+ ],
607
+ };
608
+ /**
609
+ * Kubernetes provider definition
610
+ */
611
+ export const kubernetesProvider = {
612
+ id: 'kubernetes',
613
+ name: 'Kubernetes',
614
+ description: 'Kubernetes cluster credentials',
615
+ detect: async () => {
616
+ const fs = await import('fs/promises');
617
+ try {
618
+ await fs.access(join(homedir(), '.kube', 'config'));
619
+ return true;
620
+ }
621
+ catch {
622
+ return false;
623
+ }
624
+ },
625
+ locations: [
626
+ {
627
+ id: 'kubeconfig',
628
+ name: 'Kubeconfig',
629
+ pathPattern: '{home}/.kube',
630
+ filePattern: 'config',
631
+ parse: (filePath, content) => {
632
+ const credentials = [];
633
+ // Simple YAML parsing for kubeconfig
634
+ const clusterMatches = content.match(/- name:\s*([^\n]+)/g);
635
+ if (clusterMatches) {
636
+ for (const match of clusterMatches) {
637
+ const name = match.replace('- name:', '').trim();
638
+ credentials.push({
639
+ provider: 'kubernetes',
640
+ filePath,
641
+ classification: {
642
+ name: `Kubernetes Cluster (${name})`,
643
+ credentialType: 'custom',
644
+ visaType: 'privilege',
645
+ riskLevel: 'high',
646
+ platforms: ['kubernetes'],
647
+ tags: ['kubernetes', 'cluster', 'imported'],
648
+ issuingAuthority: 'Kubernetes',
649
+ },
650
+ rawValue: content,
651
+ metadata: {
652
+ clusterName: name,
653
+ },
654
+ });
655
+ break; // Just capture the first cluster as the main credential
656
+ }
657
+ }
658
+ return credentials;
659
+ },
660
+ },
661
+ ],
662
+ };
663
+ // ============================================================================
664
+ // Provider Registry
665
+ // ============================================================================
666
+ /**
667
+ * All registered providers
668
+ */
669
+ export const providers = [
670
+ openclawProvider,
671
+ awsProvider,
672
+ sshProvider,
673
+ dockerProvider,
674
+ npmProvider,
675
+ kubernetesProvider,
676
+ ];
677
+ /**
678
+ * Get provider by ID
679
+ */
680
+ export function getProvider(id) {
681
+ return providers.find(p => p.id === id);
682
+ }
683
+ /**
684
+ * Get all provider IDs
685
+ */
686
+ export function getProviderIds() {
687
+ return providers.map(p => p.id);
688
+ }
689
+ /**
690
+ * Detect which providers are installed
691
+ */
692
+ export async function detectInstalledProviders() {
693
+ const installed = [];
694
+ for (const provider of providers) {
695
+ if (await provider.detect()) {
696
+ installed.push(provider);
697
+ }
698
+ }
699
+ return installed;
700
+ }
701
+ // ============================================================================
702
+ // Risk Level Helpers
703
+ // ============================================================================
704
+ /**
705
+ * Get risk level emoji
706
+ */
707
+ export function getRiskEmoji(level) {
708
+ switch (level) {
709
+ case 'critical': return '🔴';
710
+ case 'high': return '⚠️ ';
711
+ case 'medium': return '⚠️ ';
712
+ case 'low': return 'ℹ️ ';
713
+ }
714
+ }
715
+ /**
716
+ * Get risk level label
717
+ */
718
+ export function getRiskLabel(level) {
719
+ return level.toUpperCase();
720
+ }
721
+ /**
722
+ * Sort credentials by risk level (critical first)
723
+ */
724
+ export function sortByRisk(credentials) {
725
+ const order = {
726
+ critical: 0,
727
+ high: 1,
728
+ medium: 2,
729
+ low: 3,
730
+ };
731
+ return [...credentials].sort((a, b) => order[a.classification.riskLevel] - order[b.classification.riskLevel]);
732
+ }
733
+ //# sourceMappingURL=locations.js.map