@aiconnect/confidant 1.0.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 (103) hide show
  1. package/README.md +570 -0
  2. package/dist/api-client.d.ts +58 -0
  3. package/dist/api-client.d.ts.map +1 -0
  4. package/dist/api-client.js +101 -0
  5. package/dist/api-client.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +69 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/create.d.ts +3 -0
  11. package/dist/commands/create.d.ts.map +1 -0
  12. package/dist/commands/create.js +51 -0
  13. package/dist/commands/create.js.map +1 -0
  14. package/dist/commands/delete.d.ts +3 -0
  15. package/dist/commands/delete.d.ts.map +1 -0
  16. package/dist/commands/delete.js +29 -0
  17. package/dist/commands/delete.js.map +1 -0
  18. package/dist/commands/get-request.d.ts +3 -0
  19. package/dist/commands/get-request.d.ts.map +1 -0
  20. package/dist/commands/get-request.js +89 -0
  21. package/dist/commands/get-request.js.map +1 -0
  22. package/dist/commands/get.d.ts +3 -0
  23. package/dist/commands/get.d.ts.map +1 -0
  24. package/dist/commands/get.js +29 -0
  25. package/dist/commands/get.js.map +1 -0
  26. package/dist/commands/request.d.ts +3 -0
  27. package/dist/commands/request.d.ts.map +1 -0
  28. package/dist/commands/request.js +289 -0
  29. package/dist/commands/request.js.map +1 -0
  30. package/dist/commands/status.d.ts +3 -0
  31. package/dist/commands/status.d.ts.map +1 -0
  32. package/dist/commands/status.js +40 -0
  33. package/dist/commands/status.js.map +1 -0
  34. package/dist/crypto.d.ts +32 -0
  35. package/dist/crypto.d.ts.map +1 -0
  36. package/dist/crypto.js +79 -0
  37. package/dist/crypto.js.map +1 -0
  38. package/dist/crypto.test.d.ts +5 -0
  39. package/dist/crypto.test.d.ts.map +1 -0
  40. package/dist/crypto.test.js +77 -0
  41. package/dist/crypto.test.js.map +1 -0
  42. package/dist/i18n.d.ts +55 -0
  43. package/dist/i18n.d.ts.map +1 -0
  44. package/dist/i18n.js +63 -0
  45. package/dist/i18n.js.map +1 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +53 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/network-detection.d.ts +11 -0
  51. package/dist/network-detection.d.ts.map +1 -0
  52. package/dist/network-detection.js +54 -0
  53. package/dist/network-detection.js.map +1 -0
  54. package/dist/network-detection.test.d.ts +2 -0
  55. package/dist/network-detection.test.d.ts.map +1 -0
  56. package/dist/network-detection.test.js +150 -0
  57. package/dist/network-detection.test.js.map +1 -0
  58. package/dist/rate-limiter.d.ts +61 -0
  59. package/dist/rate-limiter.d.ts.map +1 -0
  60. package/dist/rate-limiter.js +128 -0
  61. package/dist/rate-limiter.js.map +1 -0
  62. package/dist/rate-limiter.test.d.ts +5 -0
  63. package/dist/rate-limiter.test.d.ts.map +1 -0
  64. package/dist/rate-limiter.test.js +130 -0
  65. package/dist/rate-limiter.test.js.map +1 -0
  66. package/dist/registry.d.ts +136 -0
  67. package/dist/registry.d.ts.map +1 -0
  68. package/dist/registry.js +182 -0
  69. package/dist/registry.js.map +1 -0
  70. package/dist/registry.test.d.ts +13 -0
  71. package/dist/registry.test.d.ts.map +1 -0
  72. package/dist/registry.test.js +308 -0
  73. package/dist/registry.test.js.map +1 -0
  74. package/dist/routes.d.ts +4 -0
  75. package/dist/routes.d.ts.map +1 -0
  76. package/dist/routes.js +931 -0
  77. package/dist/routes.js.map +1 -0
  78. package/dist/server.d.ts +27 -0
  79. package/dist/server.d.ts.map +1 -0
  80. package/dist/server.js +79 -0
  81. package/dist/server.js.map +1 -0
  82. package/dist/storage.d.ts +150 -0
  83. package/dist/storage.d.ts.map +1 -0
  84. package/dist/storage.js +298 -0
  85. package/dist/storage.js.map +1 -0
  86. package/dist/storage.test.d.ts +5 -0
  87. package/dist/storage.test.d.ts.map +1 -0
  88. package/dist/storage.test.js +466 -0
  89. package/dist/storage.test.js.map +1 -0
  90. package/dist/types.d.ts +144 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +56 -0
  93. package/dist/types.js.map +1 -0
  94. package/dist/url-helper.d.ts +16 -0
  95. package/dist/url-helper.d.ts.map +1 -0
  96. package/dist/url-helper.js +27 -0
  97. package/dist/url-helper.js.map +1 -0
  98. package/dist/url-helper.test.d.ts +2 -0
  99. package/dist/url-helper.test.d.ts.map +1 -0
  100. package/dist/url-helper.test.js +70 -0
  101. package/dist/url-helper.test.js.map +1 -0
  102. package/package.json +73 -0
  103. package/public/index.html +352 -0
@@ -0,0 +1,289 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { ApiClient } from '../api-client.js';
4
+ import { generateUrls } from '../url-helper.js';
5
+ import { detectLocalIp } from '../network-detection.js';
6
+ export const requestCommand = new Command('request')
7
+ .description('Create a secret request and poll for the secret')
8
+ .option('--expires-in <seconds>', 'Request expiration time in seconds (60-86400)', '86400')
9
+ .option('--poll-interval <seconds>', 'Polling interval in seconds (1-60)', '2')
10
+ .option('--poll <id>', 'Manually poll for an existing request by ID')
11
+ .option('--label <text>', 'Optional label to describe what secret is being requested (max 200 characters)')
12
+ .option('--json', 'Output in JSON format')
13
+ .option('--quiet', 'Minimal output (only URLs and secret)')
14
+ .option('--verbose', 'Verbose output with detailed logging')
15
+ .addHelpText('after', `
16
+ Examples:
17
+ confidant request # Create request with default settings
18
+ confidant request --expires-in 3600 # Create request with 1-hour expiration
19
+ confidant request --poll-interval 5 # Poll every 5 seconds
20
+ confidant request --poll abc123 # Manually poll for existing request
21
+ confidant request --label "API Key" # Create request with a label
22
+ confidant request --json # Output in JSON format
23
+ confidant request --quiet # Minimal output
24
+ confidant request --verbose # Show detailed information including network detection
25
+
26
+ URL Options:
27
+ When you create a request, multiple URLs are displayed for different scenarios:
28
+
29
+ • Localhost URL: Use when both CLI and user are on the same machine
30
+ Example: http://localhost:3000/request/abc123
31
+
32
+ • Local Network IP URL: Automatically displayed when detected, for cross-device access
33
+ Example: http://192.168.1.100:3000/request/abc123
34
+ Use when: CLI on Mac Mini, user on iPhone; or CLI in Docker, user on host
35
+
36
+ • Tunneling Services: Use when running in containers/VMs or need external access
37
+ Popular services:
38
+ - ngrok: https://ngrok.com (quick setup, free tier available)
39
+ - Tailscale: https://tailscale.com (mesh VPN, secure)
40
+ - Cloudflare Tunnel: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/
41
+ - localtunnel: https://localtunnel.github.io/www/ (simple, no signup)
42
+
43
+ Choose the appropriate URL based on your deployment scenario.
44
+ `)
45
+ .action(async (options) => {
46
+ try {
47
+ // Get API URL from parent command options
48
+ const program = requestCommand.parent;
49
+ const apiUrl = program?.opts().apiUrl || 'http://localhost:3000';
50
+ // Create API client
51
+ const client = new ApiClient(apiUrl);
52
+ // Manual polling mode
53
+ if (options.poll) {
54
+ await manualPoll(client, options.poll, options);
55
+ return;
56
+ }
57
+ // Create request mode
58
+ await createAndPoll(client, options);
59
+ }
60
+ catch (error) {
61
+ if (error instanceof Error) {
62
+ if (options.json) {
63
+ console.error(JSON.stringify({ error: error.message }));
64
+ }
65
+ else {
66
+ console.error(chalk.red(`Error: ${error.message}`));
67
+ }
68
+ }
69
+ else {
70
+ console.error(chalk.red('An unknown error occurred'));
71
+ }
72
+ process.exit(1);
73
+ }
74
+ });
75
+ /**
76
+ * Create a request and poll for the secret
77
+ */
78
+ async function createAndPoll(client, options) {
79
+ // Validate options
80
+ const expiresIn = parseInt(options.expiresIn);
81
+ if (isNaN(expiresIn) || expiresIn < 60 || expiresIn > 86400) {
82
+ throw new Error('expires-in must be a number between 60 and 86400');
83
+ }
84
+ const pollInterval = parseInt(options.pollInterval);
85
+ if (isNaN(pollInterval) || pollInterval < 1 || pollInterval > 60) {
86
+ throw new Error('poll-interval must be a number between 1 and 60');
87
+ }
88
+ // Validate label if provided
89
+ if (options.label !== undefined) {
90
+ if (options.label === '') {
91
+ throw new Error('label cannot be empty');
92
+ }
93
+ if (options.label.length > 200) {
94
+ throw new Error('label must not exceed 200 characters');
95
+ }
96
+ }
97
+ // Detect local IP
98
+ const localIp = detectLocalIp();
99
+ // Verbose mode: show network interface detection results
100
+ if (options.verbose && !options.json) {
101
+ console.log('');
102
+ console.log(chalk.gray('Network Interface Detection:'));
103
+ if (localIp) {
104
+ console.log(chalk.gray(` Detected local IP: ${localIp}`));
105
+ }
106
+ else {
107
+ console.log(chalk.gray(' No local IP detected (only localhost available)'));
108
+ }
109
+ console.log('');
110
+ }
111
+ // Create the request
112
+ if (!options.quiet && !options.json) {
113
+ console.log(chalk.cyan('Creating secret request...'));
114
+ }
115
+ const result = await client.createSecretRequest(expiresIn, options.label);
116
+ // Generate URLs for display
117
+ const urls = generateUrls(client.apiUrl, result.hash, localIp);
118
+ // Tunneling service suggestions
119
+ const tunnelingSuggestions = [
120
+ 'ngrok',
121
+ 'Tailscale',
122
+ 'Cloudflare Tunnel',
123
+ 'localtunnel'
124
+ ];
125
+ // Output the result
126
+ if (options.json) {
127
+ console.log(JSON.stringify({
128
+ ...result,
129
+ localhostUrl: urls.localhost,
130
+ localIpUrl: urls.network,
131
+ tunnelingSuggestions: tunnelingSuggestions
132
+ }, null, 2));
133
+ }
134
+ else {
135
+ if (!options.quiet) {
136
+ console.log('');
137
+ console.log(chalk.green('✓ Request created successfully'));
138
+ console.log('');
139
+ console.log(chalk.bold('Request Details:'));
140
+ console.log(` ID: ${chalk.yellow(result.id)}`);
141
+ console.log(` Expires: ${chalk.gray(result.expiresAt)}`);
142
+ console.log(` Status: ${chalk.yellow(result.status)}`);
143
+ if (result.label) {
144
+ console.log(` Label: ${chalk.magenta(result.label)}`);
145
+ }
146
+ console.log('');
147
+ console.log(chalk.bold('Access URLs:'));
148
+ console.log('');
149
+ // Localhost URL (always shown as primary)
150
+ console.log(chalk.cyan('Localhost (primary):'));
151
+ console.log(chalk.gray(' Use when both CLI and user are on the same machine'));
152
+ console.log(` ${chalk.cyan(urls.localhost)}`);
153
+ console.log('');
154
+ // Local IP URL (conditional)
155
+ if (urls.network) {
156
+ console.log(chalk.cyan('Local Network IP:'));
157
+ console.log(chalk.gray(' Use for cross-device access on the same network'));
158
+ console.log(` ${chalk.cyan(urls.network)}`);
159
+ console.log('');
160
+ }
161
+ // Tunneling suggestions (always shown)
162
+ console.log(chalk.cyan('Tunneling Services (for external access):'));
163
+ console.log(chalk.gray(' Use when running in containers/VMs or need external access'));
164
+ console.log(chalk.gray(' Recommended services:'));
165
+ for (const service of tunnelingSuggestions) {
166
+ console.log(chalk.gray(` • ${service}`));
167
+ }
168
+ console.log('');
169
+ console.log(chalk.bold('Sharing Instructions:'));
170
+ console.log(' 1. Choose the appropriate URL based on your situation');
171
+ console.log(' 2. Copy the URL');
172
+ console.log(' 3. Share it with the person who has the secret');
173
+ console.log(' 4. They will open the URL and submit the secret');
174
+ console.log(' 5. The secret will be displayed below when submitted');
175
+ console.log('');
176
+ }
177
+ else {
178
+ // Quiet mode - output all available URLs
179
+ console.log(urls.localhost);
180
+ if (urls.network) {
181
+ console.log(urls.network);
182
+ }
183
+ }
184
+ }
185
+ // Start polling
186
+ if (!options.json) {
187
+ console.log(chalk.gray('Waiting for secret submission...'));
188
+ }
189
+ await pollForSecret(client, result.id, pollInterval, options);
190
+ }
191
+ /**
192
+ * Manually poll for an existing request
193
+ */
194
+ async function manualPoll(client, requestId, options) {
195
+ if (!options.quiet && !options.json) {
196
+ console.log(chalk.cyan(`Polling for request: ${requestId}`));
197
+ }
198
+ const pollInterval = parseInt(options.pollInterval) || 2;
199
+ await pollForSecret(client, requestId, pollInterval, options);
200
+ }
201
+ /**
202
+ * Poll for the secret
203
+ */
204
+ async function pollForSecret(client, requestId, pollInterval, options) {
205
+ let pollCount = 0;
206
+ let backoff = pollInterval * 1000;
207
+ const handleShutdown = () => {
208
+ if (!options.quiet && !options.json) {
209
+ console.log('');
210
+ console.log(chalk.yellow('Polling interrupted'));
211
+ console.log('');
212
+ console.log(chalk.bold('To resume polling, run:'));
213
+ console.log(chalk.cyan(`confidant request --poll ${requestId}`));
214
+ }
215
+ process.exit(130);
216
+ };
217
+ process.on('SIGINT', handleShutdown);
218
+ process.on('SIGTERM', handleShutdown);
219
+ try {
220
+ while (true) {
221
+ pollCount++;
222
+ if (options.verbose && !options.json) {
223
+ console.log(chalk.gray(`Polling... (attempt ${pollCount})`));
224
+ }
225
+ try {
226
+ const result = await client.pollSecretRequest(requestId);
227
+ if (result.status === 'completed' || result.status === 'retrieved') {
228
+ // Secret is available
229
+ if (!options.quiet && !options.json) {
230
+ console.log('');
231
+ console.log(chalk.green('✓ Secret received!'));
232
+ console.log('');
233
+ }
234
+ if (options.json) {
235
+ console.log(JSON.stringify(result, null, 2));
236
+ }
237
+ else {
238
+ console.log(chalk.bold('Secret:'));
239
+ console.log(chalk.cyan(result.secret || ''));
240
+ console.log('');
241
+ console.log(chalk.gray('The secret has been deleted from the server.'));
242
+ }
243
+ process.exit(0);
244
+ }
245
+ else if (result.status === 'expired') {
246
+ throw new Error('Request has expired');
247
+ }
248
+ else if (result.status === 'pending') {
249
+ // Continue polling
250
+ if (options.verbose && !options.json) {
251
+ console.log(chalk.gray('Still waiting...'));
252
+ }
253
+ }
254
+ }
255
+ catch (error) {
256
+ if (error instanceof Error) {
257
+ const message = error.message.toLowerCase();
258
+ if (message.includes('expired')) {
259
+ throw error;
260
+ }
261
+ else if (message.includes('not found')) {
262
+ throw new Error('Request not found or already retrieved');
263
+ }
264
+ else {
265
+ // Network or other error - implement exponential backoff
266
+ if (options.verbose && !options.json) {
267
+ console.log(chalk.yellow(`Error: ${error.message}`));
268
+ console.log(chalk.gray(`Retrying in ${backoff / 1000} seconds...`));
269
+ }
270
+ backoff = Math.min(backoff * 2, 60000); // Max 60 seconds
271
+ }
272
+ }
273
+ }
274
+ // Wait before next poll
275
+ await sleep(backoff);
276
+ }
277
+ }
278
+ finally {
279
+ process.removeListener('SIGINT', handleShutdown);
280
+ process.removeListener('SIGTERM', handleShutdown);
281
+ }
282
+ }
283
+ /**
284
+ * Sleep for a specified number of milliseconds
285
+ */
286
+ function sleep(ms) {
287
+ return new Promise(resolve => setTimeout(resolve, ms));
288
+ }
289
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/commands/request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const statusCommand: Command;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,aAAa,SAkCtB,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { Command } from 'commander';
2
+ import { ApiClient } from '../api-client.js';
3
+ import { t } from '../i18n.js';
4
+ import { generateUrls } from '../url-helper.js';
5
+ import { detectLocalIp } from '../network-detection.js';
6
+ export const statusCommand = new Command('status')
7
+ .description(t('statusDescription'))
8
+ .argument('<id>', 'ID do segredo')
9
+ .addHelpText('after', `\n${t('statusExample')}`)
10
+ .action(async (id) => {
11
+ try {
12
+ // Get API URL from parent command options
13
+ const program = statusCommand.parent;
14
+ const apiUrl = program?.opts().apiUrl || 'http://localhost:3000';
15
+ // Create API client and call API
16
+ const client = new ApiClient(apiUrl);
17
+ const result = await client.getSecretStatus(id);
18
+ // Detect local IP for network URL
19
+ const localIp = detectLocalIp();
20
+ const urls = generateUrls(client.apiUrl, id, localIp);
21
+ // Output JSON response with URLs
22
+ console.log(JSON.stringify({
23
+ ...result,
24
+ urls: {
25
+ localhost: urls.localhost,
26
+ network: urls.network
27
+ }
28
+ }, null, 2));
29
+ }
30
+ catch (error) {
31
+ if (error instanceof Error) {
32
+ console.error(JSON.stringify({ error: error.message }));
33
+ }
34
+ else {
35
+ console.error(JSON.stringify({ error: t('networkError') }));
36
+ }
37
+ process.exit(1);
38
+ }
39
+ });
40
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;KACnC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;KACjC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC;KAC/C,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;IACnB,IAAI,CAAC;QACH,0CAA0C;QAC1C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC;QACrC,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,EAAE,CAAC,MAAM,IAAI,uBAAuB,CAAC;QAEjE,iCAAiC;QACjC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAEhD,kCAAkC;QAClC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QAEtD,iCAAiC;QACjC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACzB,GAAG,MAAM;YACT,IAAI,EAAE;gBACJ,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB;SACF,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Cryptography Utilities
3
+ *
4
+ * Provides encryption/decryption functions for secret storage using AES-256-GCM.
5
+ * Uses per-request keys derived from the request hash for security.
6
+ */
7
+ /**
8
+ * Generate a cryptographically secure random hash for secret requests
9
+ * @returns 64-character hex string (256 bits of entropy)
10
+ */
11
+ export declare function generateHash(): string;
12
+ /**
13
+ * Encrypt a secret using AES-256-GCM
14
+ * @param secret The secret to encrypt
15
+ * @param hash The request hash (used to derive the encryption key)
16
+ * @returns Encrypted secret in format: iv:authTag:encryptedData
17
+ */
18
+ export declare function encryptSecret(secret: string, hash: string): string;
19
+ /**
20
+ * Decrypt a secret using AES-256-GCM
21
+ * @param encryptedSecret The encrypted secret in format: iv:authTag:encryptedData
22
+ * @param hash The request hash (used to derive the encryption key)
23
+ * @returns The decrypted secret
24
+ * @throws Error if decryption fails (invalid hash or corrupted data)
25
+ */
26
+ export declare function decryptSecret(encryptedSecret: string, hash: string): string;
27
+ /**
28
+ * Generate a UUID v4 for request IDs
29
+ * @returns UUID v4 string
30
+ */
31
+ export declare function generateUUID(): string;
32
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAaD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAYlE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB3E;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAMrC"}
package/dist/crypto.js ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Cryptography Utilities
3
+ *
4
+ * Provides encryption/decryption functions for secret storage using AES-256-GCM.
5
+ * Uses per-request keys derived from the request hash for security.
6
+ */
7
+ import * as crypto from 'node:crypto';
8
+ /**
9
+ * Generate a cryptographically secure random hash for secret requests
10
+ * @returns 64-character hex string (256 bits of entropy)
11
+ */
12
+ export function generateHash() {
13
+ return crypto.randomBytes(32).toString('hex');
14
+ }
15
+ /**
16
+ * Derive an encryption key from the request hash using scrypt
17
+ * @param hash The request hash
18
+ * @returns 32-byte encryption key
19
+ */
20
+ function deriveKey(hash) {
21
+ // Use scrypt with a fixed salt to derive a key from the hash
22
+ // The hash itself provides enough entropy, so the salt can be fixed
23
+ return crypto.scryptSync(hash, 'confidant-secret-request-salt', 32);
24
+ }
25
+ /**
26
+ * Encrypt a secret using AES-256-GCM
27
+ * @param secret The secret to encrypt
28
+ * @param hash The request hash (used to derive the encryption key)
29
+ * @returns Encrypted secret in format: iv:authTag:encryptedData
30
+ */
31
+ export function encryptSecret(secret, hash) {
32
+ const key = deriveKey(hash);
33
+ const iv = crypto.randomBytes(16);
34
+ const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
35
+ let encrypted = cipher.update(secret, 'utf8', 'hex');
36
+ encrypted += cipher.final('hex');
37
+ const authTag = cipher.getAuthTag();
38
+ // Format: iv:authTag:encryptedData
39
+ return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
40
+ }
41
+ /**
42
+ * Decrypt a secret using AES-256-GCM
43
+ * @param encryptedSecret The encrypted secret in format: iv:authTag:encryptedData
44
+ * @param hash The request hash (used to derive the encryption key)
45
+ * @returns The decrypted secret
46
+ * @throws Error if decryption fails (invalid hash or corrupted data)
47
+ */
48
+ export function decryptSecret(encryptedSecret, hash) {
49
+ try {
50
+ const parts = encryptedSecret.split(':');
51
+ if (parts.length !== 3) {
52
+ throw new Error('Invalid encrypted secret format');
53
+ }
54
+ const [ivHex, authTagHex, encryptedData] = parts;
55
+ const key = deriveKey(hash);
56
+ const iv = Buffer.from(ivHex, 'hex');
57
+ const authTag = Buffer.from(authTagHex, 'hex');
58
+ const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
59
+ decipher.setAuthTag(authTag);
60
+ let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
61
+ decrypted += decipher.final('utf8');
62
+ return decrypted;
63
+ }
64
+ catch (error) {
65
+ throw new Error('Failed to decrypt secret: invalid hash or corrupted data');
66
+ }
67
+ }
68
+ /**
69
+ * Generate a UUID v4 for request IDs
70
+ * @returns UUID v4 string
71
+ */
72
+ export function generateUUID() {
73
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
74
+ const r = Math.random() * 16 | 0;
75
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
76
+ return v.toString(16);
77
+ });
78
+ }
79
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for crypto utilities
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=crypto.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.test.d.ts","sourceRoot":"","sources":["../src/crypto.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Tests for crypto utilities
3
+ */
4
+ import { describe, it, expect } from 'vitest';
5
+ import { generateHash, encryptSecret, decryptSecret, generateUUID } from './crypto.js';
6
+ describe('crypto', () => {
7
+ describe('generateHash', () => {
8
+ it('should generate a 64-character hex string', () => {
9
+ const hash = generateHash();
10
+ expect(hash).toHaveLength(64);
11
+ expect(hash).toMatch(/^[a-f0-9]{64}$/);
12
+ });
13
+ it('should generate unique hashes', () => {
14
+ const hash1 = generateHash();
15
+ const hash2 = generateHash();
16
+ expect(hash1).not.toBe(hash2);
17
+ });
18
+ });
19
+ describe('encryptSecret and decryptSecret', () => {
20
+ it('should encrypt and decrypt a secret correctly', () => {
21
+ const secret = 'my-secret-password';
22
+ const hash = generateHash();
23
+ const encrypted = encryptSecret(secret, hash);
24
+ const decrypted = decryptSecret(encrypted, hash);
25
+ expect(decrypted).toBe(secret);
26
+ });
27
+ it('should produce different encrypted values for the same secret with different hashes', () => {
28
+ const secret = 'my-secret-password';
29
+ const hash1 = generateHash();
30
+ const hash2 = generateHash();
31
+ const encrypted1 = encryptSecret(secret, hash1);
32
+ const encrypted2 = encryptSecret(secret, hash2);
33
+ expect(encrypted1).not.toBe(encrypted2);
34
+ });
35
+ it('should encrypt multi-line secrets', () => {
36
+ const secret = 'line1\nline2\nline3';
37
+ const hash = generateHash();
38
+ const encrypted = encryptSecret(secret, hash);
39
+ const decrypted = decryptSecret(encrypted, hash);
40
+ expect(decrypted).toBe(secret);
41
+ });
42
+ it('should encrypt special characters', () => {
43
+ const secret = '!@#$%^&*()_+-=[]{}|;:,.<>?';
44
+ const hash = generateHash();
45
+ const encrypted = encryptSecret(secret, hash);
46
+ const decrypted = decryptSecret(encrypted, hash);
47
+ expect(decrypted).toBe(secret);
48
+ });
49
+ it('should throw error when decrypting with wrong hash', () => {
50
+ const secret = 'my-secret-password';
51
+ const hash1 = generateHash();
52
+ const hash2 = generateHash();
53
+ const encrypted = encryptSecret(secret, hash1);
54
+ expect(() => {
55
+ decryptSecret(encrypted, hash2);
56
+ }).toThrow();
57
+ });
58
+ it('should throw error when decrypting invalid format', () => {
59
+ const hash = generateHash();
60
+ expect(() => {
61
+ decryptSecret('invalid-format', hash);
62
+ }).toThrow();
63
+ });
64
+ });
65
+ describe('generateUUID', () => {
66
+ it('should generate a valid UUID v4 format', () => {
67
+ const uuid = generateUUID();
68
+ expect(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
69
+ });
70
+ it('should generate unique UUIDs', () => {
71
+ const uuid1 = generateUUID();
72
+ const uuid2 = generateUUID();
73
+ expect(uuid1).not.toBe(uuid2);
74
+ });
75
+ });
76
+ });
77
+ //# sourceMappingURL=crypto.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.test.js","sourceRoot":"","sources":["../src/crypto.test.ts"],"names":[],"mappings":"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"}
package/dist/i18n.d.ts ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Portuguese translations for CLI messages
3
+ */
4
+ export declare const translations: {
5
+ readonly secretCannotBeEmpty: "O segredo não pode estar vazio";
6
+ readonly ttlMustBePositive: "O TTL deve ser um número positivo";
7
+ readonly maxAccessCountMustBePositive: "O número máximo de acessos deve ser positivo";
8
+ readonly secretNotFound: "Segredo não encontrado";
9
+ readonly secretHasExpired: "O segredo expirou";
10
+ readonly maxAccessCountExceeded: "Número máximo de acessos excedido";
11
+ readonly connectionFailed: "Falha na conexão com o servidor";
12
+ readonly requestTimedOut: "A solicitação expirou";
13
+ readonly invalidApiEndpoint: "Endpoint de API inválido";
14
+ readonly invalidJsonResponse: "Resposta JSON inválida do servidor";
15
+ readonly networkError: "Erro de rede";
16
+ readonly programDescription: "Ferramenta de CLI para o sistema de transferência de segredos Confidant";
17
+ readonly createDescription: "Criar um novo segredo";
18
+ readonly getDescription: "Recuperar um segredo pelo ID";
19
+ readonly deleteDescription: "Excluir um segredo pelo ID";
20
+ readonly statusDescription: "Verificar o status de um segredo pelo ID";
21
+ readonly serveDescription: "Iniciar o servidor Confidant";
22
+ readonly secretOption: "Conteúdo do segredo (obrigatório)";
23
+ readonly ttlOption: "Tempo de vida em milissegundos (opcional)";
24
+ readonly maxAccessCountOption: "Número máximo de acessos (opcional)";
25
+ readonly apiUrlOption: "URL do endpoint da API";
26
+ readonly portOption: "Porta do servidor (padrão: 3000)";
27
+ readonly hostOption: "Host do servidor (padrão: localhost)";
28
+ readonly createExample: "Exemplo: confidant create --secret \"meu segredo\" --ttl 60000 --max-access-count 3";
29
+ readonly getExample: "Exemplo: confidant get abc123";
30
+ readonly deleteExample: "Exemplo: confidant delete abc123";
31
+ readonly statusExample: "Exemplo: confidant status abc123";
32
+ readonly secretCreated: "Segredo criado com sucesso";
33
+ readonly secretRetrieved: "Segredo recuperado com sucesso";
34
+ readonly secretDeleted: "Segredo excluído com sucesso";
35
+ readonly secretStatus: "Status do segredo";
36
+ readonly serverStarting: "Iniciando servidor Confidant...";
37
+ readonly serverRunning: "✅ Confidant rodando em:";
38
+ readonly serverShutdown: "Encerrando servidor Confidant...";
39
+ readonly serverStopped: "Servidor encerrado";
40
+ readonly usage: "Uso";
41
+ readonly options: "Opções";
42
+ readonly commands: "Comandos";
43
+ readonly arguments: "Argumentos";
44
+ readonly required: "(obrigatório)";
45
+ readonly optional: "(opcional)";
46
+ readonly localhostUrl: " - %s (localhost)";
47
+ readonly networkUrl: " - %s (rede local)";
48
+ readonly pressCtrlCToStop: "Pressione Ctrl+C para parar o servidor";
49
+ };
50
+ export type TranslationKey = keyof typeof translations;
51
+ /**
52
+ * Get a translation by key
53
+ */
54
+ export declare function t(key: TranslationKey): string;
55
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Df,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,YAAY,CAAC;AAEvD;;GAEG;AACH,wBAAgB,CAAC,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAE7C"}