@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
package/dist/i18n.js ADDED
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Portuguese translations for CLI messages
3
+ */
4
+ export const translations = {
5
+ // Error messages
6
+ secretCannotBeEmpty: 'O segredo não pode estar vazio',
7
+ ttlMustBePositive: 'O TTL deve ser um número positivo',
8
+ maxAccessCountMustBePositive: 'O número máximo de acessos deve ser positivo',
9
+ secretNotFound: 'Segredo não encontrado',
10
+ secretHasExpired: 'O segredo expirou',
11
+ maxAccessCountExceeded: 'Número máximo de acessos excedido',
12
+ connectionFailed: 'Falha na conexão com o servidor',
13
+ requestTimedOut: 'A solicitação expirou',
14
+ invalidApiEndpoint: 'Endpoint de API inválido',
15
+ invalidJsonResponse: 'Resposta JSON inválida do servidor',
16
+ networkError: 'Erro de rede',
17
+ // Help descriptions
18
+ programDescription: 'Ferramenta de CLI para o sistema de transferência de segredos Confidant',
19
+ createDescription: 'Criar um novo segredo',
20
+ getDescription: 'Recuperar um segredo pelo ID',
21
+ deleteDescription: 'Excluir um segredo pelo ID',
22
+ statusDescription: 'Verificar o status de um segredo pelo ID',
23
+ serveDescription: 'Iniciar o servidor Confidant',
24
+ // Option descriptions
25
+ secretOption: 'Conteúdo do segredo (obrigatório)',
26
+ ttlOption: 'Tempo de vida em milissegundos (opcional)',
27
+ maxAccessCountOption: 'Número máximo de acessos (opcional)',
28
+ apiUrlOption: 'URL do endpoint da API',
29
+ portOption: 'Porta do servidor (padrão: 3000)',
30
+ hostOption: 'Host do servidor (padrão: localhost)',
31
+ // Examples
32
+ createExample: 'Exemplo: confidant create --secret "meu segredo" --ttl 60000 --max-access-count 3',
33
+ getExample: 'Exemplo: confidant get abc123',
34
+ deleteExample: 'Exemplo: confidant delete abc123',
35
+ statusExample: 'Exemplo: confidant status abc123',
36
+ // Success messages
37
+ secretCreated: 'Segredo criado com sucesso',
38
+ secretRetrieved: 'Segredo recuperado com sucesso',
39
+ secretDeleted: 'Segredo excluído com sucesso',
40
+ secretStatus: 'Status do segredo',
41
+ serverStarting: 'Iniciando servidor Confidant...',
42
+ serverRunning: '✅ Confidant rodando em:',
43
+ serverShutdown: 'Encerrando servidor Confidant...',
44
+ serverStopped: 'Servidor encerrado',
45
+ // Usage information
46
+ usage: 'Uso',
47
+ options: 'Opções',
48
+ commands: 'Comandos',
49
+ arguments: 'Argumentos',
50
+ required: '(obrigatório)',
51
+ optional: '(opcional)',
52
+ // Server messages
53
+ localhostUrl: ' - %s (localhost)',
54
+ networkUrl: ' - %s (rede local)',
55
+ pressCtrlCToStop: 'Pressione Ctrl+C para parar o servidor',
56
+ };
57
+ /**
58
+ * Get a translation by key
59
+ */
60
+ export function t(key) {
61
+ return translations[key];
62
+ }
63
+ //# sourceMappingURL=i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,iBAAiB;IACjB,mBAAmB,EAAE,gCAAgC;IACrD,iBAAiB,EAAE,mCAAmC;IACtD,4BAA4B,EAAE,8CAA8C;IAC5E,cAAc,EAAE,wBAAwB;IACxC,gBAAgB,EAAE,mBAAmB;IACrC,sBAAsB,EAAE,mCAAmC;IAC3D,gBAAgB,EAAE,iCAAiC;IACnD,eAAe,EAAE,uBAAuB;IACxC,kBAAkB,EAAE,0BAA0B;IAC9C,mBAAmB,EAAE,oCAAoC;IACzD,YAAY,EAAE,cAAc;IAE5B,oBAAoB;IACpB,kBAAkB,EAAE,yEAAyE;IAC7F,iBAAiB,EAAE,uBAAuB;IAC1C,cAAc,EAAE,8BAA8B;IAC9C,iBAAiB,EAAE,4BAA4B;IAC/C,iBAAiB,EAAE,0CAA0C;IAC7D,gBAAgB,EAAE,8BAA8B;IAEhD,sBAAsB;IACtB,YAAY,EAAE,mCAAmC;IACjD,SAAS,EAAE,2CAA2C;IACtD,oBAAoB,EAAE,qCAAqC;IAC3D,YAAY,EAAE,wBAAwB;IACtC,UAAU,EAAE,kCAAkC;IAC9C,UAAU,EAAE,sCAAsC;IAElD,WAAW;IACX,aAAa,EAAE,mFAAmF;IAClG,UAAU,EAAE,+BAA+B;IAC3C,aAAa,EAAE,kCAAkC;IACjD,aAAa,EAAE,kCAAkC;IAEjD,mBAAmB;IACnB,aAAa,EAAE,4BAA4B;IAC3C,eAAe,EAAE,gCAAgC;IACjD,aAAa,EAAE,8BAA8B;IAC7C,YAAY,EAAE,mBAAmB;IACjC,cAAc,EAAE,iCAAiC;IACjD,aAAa,EAAE,yBAAyB;IACxC,cAAc,EAAE,kCAAkC;IAClD,aAAa,EAAE,oBAAoB;IAEnC,oBAAoB;IACpB,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,QAAQ;IACjB,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,YAAY;IACvB,QAAQ,EAAE,eAAe;IACzB,QAAQ,EAAE,YAAY;IAEtB,kBAAkB;IAClB,YAAY,EAAE,oBAAoB;IAClC,UAAU,EAAE,qBAAqB;IACjC,gBAAgB,EAAE,wCAAwC;CAClD,CAAC;AAIX;;GAEG;AACH,MAAM,UAAU,CAAC,CAAC,GAAmB;IACnC,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { MemoryStorage, TTLStorage, SecretData, StorageOptions } from './storage.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { Hono } from 'hono';
3
+ import { routes } from './routes.js';
4
+ import { storageRegistry, validatorRegistry, transformerRegistry, MemoryStorageModule, BasicValidatorModule, UppercaseTransformerModule } from './registry.js';
5
+ import { detectLocalIp } from './network-detection.js';
6
+ export { MemoryStorage } from './storage.js';
7
+ const app = new Hono();
8
+ // Register routes
9
+ app.route('/', routes);
10
+ // Health check endpoint
11
+ app.get('/health', (c) => {
12
+ return c.json({ status: 'ok', message: 'Confidant is running' });
13
+ });
14
+ // Initialize registries with example modules
15
+ async function initializeRegistries() {
16
+ try {
17
+ // Register example storage module
18
+ await storageRegistry.register('memory', MemoryStorageModule);
19
+ console.log('✅ Storage registry initialized with memory module');
20
+ // Register example validator module
21
+ await validatorRegistry.register('basic', BasicValidatorModule);
22
+ console.log('✅ Validator registry initialized with basic module');
23
+ // Register example transformer module
24
+ await transformerRegistry.register('uppercase', UppercaseTransformerModule);
25
+ console.log('✅ Transformer registry initialized with uppercase module');
26
+ }
27
+ catch (error) {
28
+ console.error('❌ Failed to initialize registries:', error);
29
+ throw error;
30
+ }
31
+ }
32
+ // Start server
33
+ const port = parseInt(process.env.PORT || '3000');
34
+ console.log(`Starting Confidant server on port ${port}...`);
35
+ // Initialize registries before starting server
36
+ initializeRegistries().then(() => {
37
+ serve({
38
+ fetch: app.fetch,
39
+ port,
40
+ }, (info) => {
41
+ console.log(`✅ Confidant running at:`);
42
+ // Detect local IP for network URL
43
+ const localIp = detectLocalIp();
44
+ console.log(` - http://localhost:${info.port} (localhost)`);
45
+ if (localIp) {
46
+ console.log(` - http://${localIp}:${info.port} (rede local)`);
47
+ }
48
+ });
49
+ }).catch((error) => {
50
+ console.error('Failed to start server:', error);
51
+ process.exit(1);
52
+ });
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC/J,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,aAAa,EAA0C,MAAM,cAAc,CAAC;AAErF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;AAEvB,kBAAkB;AAClB,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAEvB,wBAAwB;AACxB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;IACvB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,6CAA6C;AAC7C,KAAK,UAAU,oBAAoB;IACjC,IAAI,CAAC;QACH,kCAAkC;QAClC,MAAM,eAAe,CAAC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QAEjE,oCAAoC;QACpC,MAAM,iBAAiB,CAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAElE,sCAAsC;QACtC,MAAM,mBAAmB,CAAC,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;IAC1E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;QAC3D,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,eAAe;AACf,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;AAClD,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,KAAK,CAAC,CAAC;AAE5D,+CAA+C;AAC/C,oBAAoB,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IAC/B,KAAK,CAAC;QACJ,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI;KACL,EAAE,CAAC,IAAI,EAAE,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAEvC,kCAAkC;QAClC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;QAEhC,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,CAAC,IAAI,cAAc,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,IAAI,IAAI,CAAC,IAAI,eAAe,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Check if an IP address is in a private range
3
+ * Private ranges: 192.168.x.x, 10.x.x.x, 172.16-31.x.x
4
+ */
5
+ export declare function isPrivateIp(ip: string): boolean;
6
+ /**
7
+ * Detect local network IP address for cross-device access
8
+ * Returns first private IP address found, or null if none detected
9
+ */
10
+ export declare function detectLocalIp(): string | null;
11
+ //# sourceMappingURL=network-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-detection.d.ts","sourceRoot":"","sources":["../src/network-detection.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAuB/C;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CA0B7C"}
@@ -0,0 +1,54 @@
1
+ import * as os from 'os';
2
+ /**
3
+ * Check if an IP address is in a private range
4
+ * Private ranges: 192.168.x.x, 10.x.x.x, 172.16-31.x.x
5
+ */
6
+ export function isPrivateIp(ip) {
7
+ const parts = ip.split('.').map(Number);
8
+ if (parts.length !== 4) {
9
+ return false;
10
+ }
11
+ // 10.0.0.0 - 10.255.255.255
12
+ if (parts[0] === 10) {
13
+ return true;
14
+ }
15
+ // 172.16.0.0 - 172.31.255.255
16
+ if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) {
17
+ return true;
18
+ }
19
+ // 192.168.0.0 - 192.168.255.255
20
+ if (parts[0] === 192 && parts[1] === 168) {
21
+ return true;
22
+ }
23
+ return false;
24
+ }
25
+ /**
26
+ * Detect local network IP address for cross-device access
27
+ * Returns first private IP address found, or null if none detected
28
+ */
29
+ export function detectLocalIp() {
30
+ try {
31
+ const interfaces = os.networkInterfaces();
32
+ for (const name of Object.keys(interfaces)) {
33
+ const networkInterface = interfaces[name];
34
+ if (!networkInterface)
35
+ continue;
36
+ for (const iface of networkInterface) {
37
+ // Skip internal and non-IPv4 addresses
38
+ if (iface.internal || iface.family !== 'IPv4') {
39
+ continue;
40
+ }
41
+ // Check if IP is in private range
42
+ if (isPrivateIp(iface.address)) {
43
+ return iface.address;
44
+ }
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ catch (error) {
50
+ // If detection fails, return null gracefully
51
+ return null;
52
+ }
53
+ }
54
+ //# sourceMappingURL=network-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-detection.js","sourceRoot":"","sources":["../src/network-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAExC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,4BAA4B;IAC5B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8BAA8B;IAC9B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gCAAgC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAE1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3C,MAAM,gBAAgB,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,gBAAgB;gBAAE,SAAS;YAEhC,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBACrC,uCAAuC;gBACvC,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;oBAC9C,SAAS;gBACX,CAAC;gBAED,kCAAkC;gBAClC,IAAI,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC/B,OAAO,KAAK,CAAC,OAAO,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,6CAA6C;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=network-detection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-detection.test.d.ts","sourceRoot":"","sources":["../src/network-detection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,150 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import * as os from 'os';
3
+ import { isPrivateIp, detectLocalIp } from './network-detection.js';
4
+ // Mock the os module
5
+ vi.mock('os', () => ({
6
+ networkInterfaces: vi.fn(),
7
+ }));
8
+ describe('network detection', () => {
9
+ beforeEach(() => {
10
+ vi.clearAllMocks();
11
+ });
12
+ afterEach(() => {
13
+ vi.restoreAllMocks();
14
+ });
15
+ describe('isPrivateIp', () => {
16
+ it('should return true for 10.x.x.x addresses', () => {
17
+ expect(isPrivateIp('10.0.0.1')).toBe(true);
18
+ expect(isPrivateIp('10.255.255.255')).toBe(true);
19
+ expect(isPrivateIp('10.128.64.32')).toBe(true);
20
+ });
21
+ it('should return true for 172.16.x.x to 172.31.x.x addresses', () => {
22
+ expect(isPrivateIp('172.16.0.1')).toBe(true);
23
+ expect(isPrivateIp('172.31.255.255')).toBe(true);
24
+ expect(isPrivateIp('172.20.128.64')).toBe(true);
25
+ });
26
+ it('should return false for 172.15.x.x addresses', () => {
27
+ expect(isPrivateIp('172.15.255.255')).toBe(false);
28
+ });
29
+ it('should return false for 172.32.x.x addresses', () => {
30
+ expect(isPrivateIp('172.32.0.1')).toBe(false);
31
+ });
32
+ it('should return true for 192.168.x.x addresses', () => {
33
+ expect(isPrivateIp('192.168.0.1')).toBe(true);
34
+ expect(isPrivateIp('192.168.255.255')).toBe(true);
35
+ expect(isPrivateIp('192.168.128.64')).toBe(true);
36
+ });
37
+ it('should return false for public IP addresses', () => {
38
+ expect(isPrivateIp('8.8.8.8')).toBe(false);
39
+ expect(isPrivateIp('1.1.1.1')).toBe(false);
40
+ expect(isPrivateIp('172.32.0.1')).toBe(false);
41
+ expect(isPrivateIp('192.169.0.1')).toBe(false);
42
+ });
43
+ it('should return false for invalid IP addresses', () => {
44
+ expect(isPrivateIp('')).toBe(false);
45
+ expect(isPrivateIp('invalid')).toBe(false);
46
+ expect(isPrivateIp('192.168')).toBe(false);
47
+ expect(isPrivateIp('192.168.1.1.1')).toBe(false);
48
+ expect(isPrivateIp('256.168.1.1')).toBe(false);
49
+ });
50
+ });
51
+ describe('detectLocalIp', () => {
52
+ it('should return first private IP address found', () => {
53
+ const mockInterfaces = [
54
+ { address: '192.168.1.100', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: false, cidr: '192.168.1.100/24' },
55
+ { address: '10.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: '00:00:00:00:00:01', internal: false, cidr: '10.0.0.1/8' },
56
+ ];
57
+ vi.mocked(os.networkInterfaces).mockReturnValue({
58
+ 'eth0': mockInterfaces,
59
+ });
60
+ const result = detectLocalIp();
61
+ expect(result).toBe('192.168.1.100');
62
+ });
63
+ it('should skip internal addresses', () => {
64
+ const mockInterfaces = [
65
+ { address: '127.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: true, cidr: '127.0.0.1/8' },
66
+ { address: '192.168.1.100', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:01', internal: false, cidr: '192.168.1.100/24' },
67
+ ];
68
+ vi.mocked(os.networkInterfaces).mockReturnValue({
69
+ 'lo': [mockInterfaces[0]],
70
+ 'eth0': [mockInterfaces[1]],
71
+ });
72
+ const result = detectLocalIp();
73
+ expect(result).toBe('192.168.1.100');
74
+ });
75
+ it('should skip IPv6 addresses', () => {
76
+ const mockInterfaces = [
77
+ { address: 'fe80::1', netmask: 'ffff:ffff:ffff:ffff::', family: 'IPv6', mac: '00:00:00:00:00:00', internal: false, cidr: 'fe80::1/64', scopeid: 1 },
78
+ { address: '192.168.1.100', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:01', internal: false, cidr: '192.168.1.100/24' },
79
+ ];
80
+ vi.mocked(os.networkInterfaces).mockReturnValue({
81
+ 'eth0': mockInterfaces,
82
+ });
83
+ const result = detectLocalIp();
84
+ expect(result).toBe('192.168.1.100');
85
+ });
86
+ it('should skip public IP addresses', () => {
87
+ const mockInterfaces = [
88
+ { address: '8.8.8.8', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: false, cidr: '8.8.8.8/24' },
89
+ { address: '192.168.1.100', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:01', internal: false, cidr: '192.168.1.100/24' },
90
+ ];
91
+ vi.mocked(os.networkInterfaces).mockReturnValue({
92
+ 'eth0': mockInterfaces,
93
+ });
94
+ const result = detectLocalIp();
95
+ expect(result).toBe('192.168.1.100');
96
+ });
97
+ it('should return null when no private IP is found', () => {
98
+ const mockInterfaces = [
99
+ { address: '8.8.8.8', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: false, cidr: '8.8.8.8/24' },
100
+ { address: '127.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: '00:00:00:00:00:01', internal: true, cidr: '127.0.0.1/8' },
101
+ ];
102
+ vi.mocked(os.networkInterfaces).mockReturnValue({
103
+ 'eth0': [mockInterfaces[0]],
104
+ 'lo': [mockInterfaces[1]],
105
+ });
106
+ const result = detectLocalIp();
107
+ expect(result).toBeNull();
108
+ });
109
+ it('should return null when networkInterfaces returns empty object', () => {
110
+ vi.mocked(os.networkInterfaces).mockReturnValue({});
111
+ const result = detectLocalIp();
112
+ expect(result).toBeNull();
113
+ });
114
+ it('should return null when networkInterfaces throws error', () => {
115
+ vi.mocked(os.networkInterfaces).mockImplementation(() => {
116
+ throw new Error('Network error');
117
+ });
118
+ const result = detectLocalIp();
119
+ expect(result).toBeNull();
120
+ });
121
+ it('should handle multiple network interfaces', () => {
122
+ const mockInterfaces = {
123
+ 'eth0': [
124
+ { address: '8.8.8.8', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: false, cidr: '8.8.8.8/24' },
125
+ ],
126
+ 'wlan0': [
127
+ { address: '192.168.1.100', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:01', internal: false, cidr: '192.168.1.100/24' },
128
+ ],
129
+ 'lo': [
130
+ { address: '127.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: '00:00:00:00:00:02', internal: true, cidr: '127.0.0.1/8' },
131
+ ],
132
+ };
133
+ vi.mocked(os.networkInterfaces).mockReturnValue(mockInterfaces);
134
+ const result = detectLocalIp();
135
+ expect(result).toBe('192.168.1.100');
136
+ });
137
+ it('should prefer 10.x.x.x over 192.168.x.x when both present', () => {
138
+ const mockInterfaces = [
139
+ { address: '192.168.1.100', netmask: '255.255.255.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: false, cidr: '192.168.1.100/24' },
140
+ { address: '10.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: '00:00:00:00:00:01', internal: false, cidr: '10.0.0.1/8' },
141
+ ];
142
+ vi.mocked(os.networkInterfaces).mockReturnValue({
143
+ 'eth0': mockInterfaces,
144
+ });
145
+ const result = detectLocalIp();
146
+ expect(result).toBe('192.168.1.100'); // First one found
147
+ });
148
+ });
149
+ });
150
+ //# sourceMappingURL=network-detection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-detection.test.js","sourceRoot":"","sources":["../src/network-detection.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Rate Limiter
3
+ *
4
+ * Implements in-memory rate limiting using a sliding window algorithm.
5
+ * Prevents brute-force attacks on hash space and API abuse.
6
+ */
7
+ /**
8
+ * Rate limiter configuration
9
+ */
10
+ export interface RateLimiterConfig {
11
+ maxRequests: number;
12
+ windowMs: number;
13
+ }
14
+ /**
15
+ * Rate limiter result
16
+ */
17
+ export interface RateLimitResult {
18
+ allowed: boolean;
19
+ remaining: number;
20
+ resetTime: number;
21
+ }
22
+ /**
23
+ * In-memory rate limiter using sliding window algorithm
24
+ */
25
+ export declare class RateLimiter {
26
+ private records;
27
+ private config;
28
+ /**
29
+ * Creates a new rate limiter
30
+ * @param config Rate limiter configuration
31
+ */
32
+ constructor(config: RateLimiterConfig);
33
+ /**
34
+ * Check if a request from the given IP is allowed
35
+ * @param ip The client IP address
36
+ * @returns Rate limit result
37
+ */
38
+ check(ip: string): RateLimitResult;
39
+ /**
40
+ * Reset the rate limit for a specific IP
41
+ * @param ip The client IP address
42
+ */
43
+ reset(ip: string): void;
44
+ /**
45
+ * Clean up old records to prevent memory leaks
46
+ * @param maxAge Maximum age of records to keep in milliseconds
47
+ */
48
+ cleanup(maxAge?: number): void;
49
+ /**
50
+ * Get the current rate limit status for an IP without incrementing
51
+ * @param ip The client IP address
52
+ * @returns Rate limit result
53
+ */
54
+ getStatus(ip: string): RateLimitResult;
55
+ }
56
+ /**
57
+ * Default rate limiter for secret request endpoints
58
+ * 10 requests per minute per IP
59
+ */
60
+ export declare const defaultRateLimiter: RateLimiter;
61
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,MAAM,CAAoB;IAElC;;;OAGG;gBACS,MAAM,EAAE,iBAAiB;IAKrC;;;;OAIG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe;IAmDlC;;;OAGG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIvB;;;OAGG;IACH,OAAO,CAAC,MAAM,GAAE,MAAgB,GAAG,IAAI;IAUvC;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe;CA4BvC;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,aAG7B,CAAC"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Rate Limiter
3
+ *
4
+ * Implements in-memory rate limiting using a sliding window algorithm.
5
+ * Prevents brute-force attacks on hash space and API abuse.
6
+ */
7
+ /**
8
+ * In-memory rate limiter using sliding window algorithm
9
+ */
10
+ export class RateLimiter {
11
+ records;
12
+ config;
13
+ /**
14
+ * Creates a new rate limiter
15
+ * @param config Rate limiter configuration
16
+ */
17
+ constructor(config) {
18
+ this.records = new Map();
19
+ this.config = config;
20
+ }
21
+ /**
22
+ * Check if a request from the given IP is allowed
23
+ * @param ip The client IP address
24
+ * @returns Rate limit result
25
+ */
26
+ check(ip) {
27
+ const now = Date.now();
28
+ const record = this.records.get(ip);
29
+ // No existing record, create a new one
30
+ if (!record) {
31
+ this.records.set(ip, {
32
+ count: 1,
33
+ windowStart: now
34
+ });
35
+ return {
36
+ allowed: true,
37
+ remaining: this.config.maxRequests - 1,
38
+ resetTime: now + this.config.windowMs
39
+ };
40
+ }
41
+ // Check if the window has expired
42
+ const windowAge = now - record.windowStart;
43
+ if (windowAge >= this.config.windowMs) {
44
+ // Reset the window
45
+ record.count = 1;
46
+ record.windowStart = now;
47
+ return {
48
+ allowed: true,
49
+ remaining: this.config.maxRequests - 1,
50
+ resetTime: now + this.config.windowMs
51
+ };
52
+ }
53
+ // Check if the limit has been exceeded
54
+ if (record.count >= this.config.maxRequests) {
55
+ return {
56
+ allowed: false,
57
+ remaining: 0,
58
+ resetTime: record.windowStart + this.config.windowMs
59
+ };
60
+ }
61
+ // Increment the count
62
+ record.count++;
63
+ return {
64
+ allowed: true,
65
+ remaining: this.config.maxRequests - record.count,
66
+ resetTime: record.windowStart + this.config.windowMs
67
+ };
68
+ }
69
+ /**
70
+ * Reset the rate limit for a specific IP
71
+ * @param ip The client IP address
72
+ */
73
+ reset(ip) {
74
+ this.records.delete(ip);
75
+ }
76
+ /**
77
+ * Clean up old records to prevent memory leaks
78
+ * @param maxAge Maximum age of records to keep in milliseconds
79
+ */
80
+ cleanup(maxAge = 3600000) {
81
+ const now = Date.now();
82
+ for (const [ip, record] of Array.from(this.records.entries())) {
83
+ const recordAge = now - record.windowStart;
84
+ if (recordAge > maxAge) {
85
+ this.records.delete(ip);
86
+ }
87
+ }
88
+ }
89
+ /**
90
+ * Get the current rate limit status for an IP without incrementing
91
+ * @param ip The client IP address
92
+ * @returns Rate limit result
93
+ */
94
+ getStatus(ip) {
95
+ const now = Date.now();
96
+ const record = this.records.get(ip);
97
+ if (!record) {
98
+ return {
99
+ allowed: true,
100
+ remaining: this.config.maxRequests,
101
+ resetTime: now + this.config.windowMs
102
+ };
103
+ }
104
+ // Check if the window has expired
105
+ const windowAge = now - record.windowStart;
106
+ if (windowAge >= this.config.windowMs) {
107
+ return {
108
+ allowed: true,
109
+ remaining: this.config.maxRequests,
110
+ resetTime: now + this.config.windowMs
111
+ };
112
+ }
113
+ return {
114
+ allowed: record.count < this.config.maxRequests,
115
+ remaining: Math.max(0, this.config.maxRequests - record.count),
116
+ resetTime: record.windowStart + this.config.windowMs
117
+ };
118
+ }
119
+ }
120
+ /**
121
+ * Default rate limiter for secret request endpoints
122
+ * 10 requests per minute per IP
123
+ */
124
+ export const defaultRateLimiter = new RateLimiter({
125
+ maxRequests: 10,
126
+ windowMs: 60000 // 1 minute
127
+ });
128
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for rate limiter
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=rate-limiter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.test.d.ts","sourceRoot":"","sources":["../src/rate-limiter.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}