latchkey 2.6.1 → 2.7.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 (176) hide show
  1. package/README.md +50 -1
  2. package/dist/scripts/recordBrowserSession.js +3 -3
  3. package/dist/scripts/recordBrowserSession.js.map +1 -1
  4. package/dist/src/{apiCredentials.d.ts → apiCredentials/base.d.ts} +6 -6
  5. package/dist/src/apiCredentials/base.d.ts.map +1 -0
  6. package/dist/src/{apiCredentials.js → apiCredentials/base.js} +5 -5
  7. package/dist/src/apiCredentials/base.js.map +1 -0
  8. package/dist/src/{apiCredentialsSerialization.d.ts → apiCredentials/serialization.d.ts} +5 -5
  9. package/dist/src/apiCredentials/serialization.d.ts.map +1 -0
  10. package/dist/src/{apiCredentialsSerialization.js → apiCredentials/serialization.js} +9 -9
  11. package/dist/src/apiCredentials/serialization.js.map +1 -0
  12. package/dist/src/{apiCredentialStore.d.ts → apiCredentials/store.d.ts} +3 -3
  13. package/dist/src/apiCredentials/store.d.ts.map +1 -0
  14. package/dist/src/{apiCredentialStore.js → apiCredentials/store.js} +2 -2
  15. package/dist/src/apiCredentials/store.js.map +1 -0
  16. package/dist/src/apiCredentials/utils.d.ts +13 -0
  17. package/dist/src/apiCredentials/utils.d.ts.map +1 -0
  18. package/dist/src/apiCredentials/utils.js +27 -0
  19. package/dist/src/apiCredentials/utils.js.map +1 -0
  20. package/dist/src/cli.js +42 -39
  21. package/dist/src/cli.js.map +1 -1
  22. package/dist/src/cliCommands.d.ts +5 -2
  23. package/dist/src/cliCommands.d.ts.map +1 -1
  24. package/dist/src/cliCommands.js +243 -190
  25. package/dist/src/cliCommands.js.map +1 -1
  26. package/dist/src/config.d.ts +32 -2
  27. package/dist/src/config.d.ts.map +1 -1
  28. package/dist/src/config.js +107 -20
  29. package/dist/src/config.js.map +1 -1
  30. package/dist/src/configDataStore.d.ts +44 -0
  31. package/dist/src/configDataStore.d.ts.map +1 -1
  32. package/dist/src/configDataStore.js +27 -0
  33. package/dist/src/configDataStore.js.map +1 -1
  34. package/dist/src/curl.d.ts +41 -8
  35. package/dist/src/curl.d.ts.map +1 -1
  36. package/dist/src/curl.js +80 -75
  37. package/dist/src/curl.js.map +1 -1
  38. package/dist/src/curlInjection.d.ts +46 -0
  39. package/dist/src/curlInjection.d.ts.map +1 -0
  40. package/dist/src/curlInjection.js +99 -0
  41. package/dist/src/curlInjection.js.map +1 -0
  42. package/dist/src/errorMessages.d.ts +14 -0
  43. package/dist/src/errorMessages.d.ts.map +1 -0
  44. package/dist/src/errorMessages.js +22 -0
  45. package/dist/src/errorMessages.js.map +1 -0
  46. package/dist/src/gateway/client.d.ts +32 -0
  47. package/dist/src/gateway/client.d.ts.map +1 -0
  48. package/dist/src/gateway/client.js +89 -0
  49. package/dist/src/gateway/client.js.map +1 -0
  50. package/dist/src/gateway/gatewayEndpoint.d.ts +43 -0
  51. package/dist/src/gateway/gatewayEndpoint.d.ts.map +1 -0
  52. package/dist/src/gateway/gatewayEndpoint.js +297 -0
  53. package/dist/src/gateway/gatewayEndpoint.js.map +1 -0
  54. package/dist/src/gateway/latchkeyEndpoint.d.ts +105 -0
  55. package/dist/src/gateway/latchkeyEndpoint.d.ts.map +1 -0
  56. package/dist/src/gateway/latchkeyEndpoint.js +144 -0
  57. package/dist/src/gateway/latchkeyEndpoint.js.map +1 -0
  58. package/dist/src/gateway/server.d.ts +20 -0
  59. package/dist/src/gateway/server.d.ts.map +1 -0
  60. package/dist/src/gateway/server.js +90 -0
  61. package/dist/src/gateway/server.js.map +1 -0
  62. package/dist/src/index.d.ts +4 -4
  63. package/dist/src/index.d.ts.map +1 -1
  64. package/dist/src/index.js +5 -5
  65. package/dist/src/index.js.map +1 -1
  66. package/dist/src/permissions.d.ts.map +1 -1
  67. package/dist/src/permissions.js +4 -2
  68. package/dist/src/permissions.js.map +1 -1
  69. package/dist/src/{registry.d.ts → serviceRegistry.d.ts} +4 -4
  70. package/dist/src/serviceRegistry.d.ts.map +1 -0
  71. package/dist/src/{registry.js → serviceRegistry.js} +4 -4
  72. package/dist/src/serviceRegistry.js.map +1 -0
  73. package/dist/src/services/aws.d.ts +2 -2
  74. package/dist/src/services/aws.d.ts.map +1 -1
  75. package/dist/src/services/aws.js +17 -10
  76. package/dist/src/services/aws.js.map +1 -1
  77. package/dist/src/services/core/base.d.ts +2 -2
  78. package/dist/src/services/core/base.d.ts.map +1 -1
  79. package/dist/src/services/core/base.js +3 -3
  80. package/dist/src/services/core/base.js.map +1 -1
  81. package/dist/src/services/core/registered.d.ts +2 -2
  82. package/dist/src/services/core/registered.d.ts.map +1 -1
  83. package/dist/src/services/core/registered.js +2 -2
  84. package/dist/src/services/core/registered.js.map +1 -1
  85. package/dist/src/services/discord.d.ts +1 -1
  86. package/dist/src/services/discord.d.ts.map +1 -1
  87. package/dist/src/services/discord.js +1 -1
  88. package/dist/src/services/discord.js.map +1 -1
  89. package/dist/src/services/dropbox.d.ts +1 -1
  90. package/dist/src/services/dropbox.d.ts.map +1 -1
  91. package/dist/src/services/dropbox.js +1 -1
  92. package/dist/src/services/dropbox.js.map +1 -1
  93. package/dist/src/services/github.d.ts +1 -1
  94. package/dist/src/services/github.d.ts.map +1 -1
  95. package/dist/src/services/github.js +1 -1
  96. package/dist/src/services/github.js.map +1 -1
  97. package/dist/src/services/google/base.d.ts +2 -2
  98. package/dist/src/services/google/base.d.ts.map +1 -1
  99. package/dist/src/services/google/base.js +3 -3
  100. package/dist/src/services/google/base.js.map +1 -1
  101. package/dist/src/services/google/directions.d.ts +1 -1
  102. package/dist/src/services/google/directions.d.ts.map +1 -1
  103. package/dist/src/services/linear.d.ts +1 -1
  104. package/dist/src/services/linear.d.ts.map +1 -1
  105. package/dist/src/services/linear.js +1 -1
  106. package/dist/src/services/linear.js.map +1 -1
  107. package/dist/src/services/notion.d.ts +1 -1
  108. package/dist/src/services/notion.d.ts.map +1 -1
  109. package/dist/src/services/notion.js +1 -1
  110. package/dist/src/services/notion.js.map +1 -1
  111. package/dist/src/services/sentry.d.ts +2 -2
  112. package/dist/src/services/sentry.d.ts.map +1 -1
  113. package/dist/src/services/sentry.js +6 -3
  114. package/dist/src/services/sentry.js.map +1 -1
  115. package/dist/src/services/slack.d.ts +3 -3
  116. package/dist/src/services/slack.d.ts.map +1 -1
  117. package/dist/src/services/slack.js +5 -5
  118. package/dist/src/services/slack.js.map +1 -1
  119. package/dist/src/services/telegram.d.ts +2 -2
  120. package/dist/src/services/telegram.d.ts.map +1 -1
  121. package/dist/src/services/telegram.js +2 -2
  122. package/dist/src/services/telegram.js.map +1 -1
  123. package/dist/src/sharedOperations.d.ts +44 -0
  124. package/dist/src/sharedOperations.d.ts.map +1 -0
  125. package/dist/src/sharedOperations.js +131 -0
  126. package/dist/src/sharedOperations.js.map +1 -0
  127. package/dist/src/version.d.ts +2 -0
  128. package/dist/src/version.d.ts.map +1 -0
  129. package/dist/src/version.js +4 -0
  130. package/dist/src/version.js.map +1 -0
  131. package/dist/tests/apiCredentialStore.test.js +2 -2
  132. package/dist/tests/apiCredentialStore.test.js.map +1 -1
  133. package/dist/tests/apiCredentials.test.js +37 -36
  134. package/dist/tests/apiCredentials.test.js.map +1 -1
  135. package/dist/tests/cli.test.js +240 -55
  136. package/dist/tests/cli.test.js.map +1 -1
  137. package/dist/tests/config.test.d.ts +2 -0
  138. package/dist/tests/config.test.d.ts.map +1 -0
  139. package/dist/tests/config.test.js +150 -0
  140. package/dist/tests/config.test.js.map +1 -0
  141. package/dist/tests/gateway.test.d.ts +2 -0
  142. package/dist/tests/gateway.test.d.ts.map +1 -0
  143. package/dist/tests/gateway.test.js +566 -0
  144. package/dist/tests/gateway.test.js.map +1 -0
  145. package/dist/tests/gatewayClient.test.d.ts +2 -0
  146. package/dist/tests/gatewayClient.test.d.ts.map +1 -0
  147. package/dist/tests/gatewayClient.test.js +85 -0
  148. package/dist/tests/gatewayClient.test.js.map +1 -0
  149. package/dist/tests/latchkeyEndpoint.test.d.ts +2 -0
  150. package/dist/tests/latchkeyEndpoint.test.d.ts.map +1 -0
  151. package/dist/tests/latchkeyEndpoint.test.js +385 -0
  152. package/dist/tests/latchkeyEndpoint.test.js.map +1 -0
  153. package/dist/tests/permissions.test.js +15 -0
  154. package/dist/tests/permissions.test.js.map +1 -1
  155. package/dist/tests/serviceRegistry.test.d.ts +2 -0
  156. package/dist/tests/serviceRegistry.test.d.ts.map +1 -0
  157. package/dist/tests/{registry.test.js → serviceRegistry.test.js} +17 -17
  158. package/dist/tests/serviceRegistry.test.js.map +1 -0
  159. package/dist/tests/servicesAgainstRecordings.test.js +3 -3
  160. package/dist/tests/servicesAgainstRecordings.test.js.map +1 -1
  161. package/dist/tests/sharedOperations.test.d.ts +2 -0
  162. package/dist/tests/sharedOperations.test.d.ts.map +1 -0
  163. package/dist/tests/sharedOperations.test.js +264 -0
  164. package/dist/tests/sharedOperations.test.js.map +1 -0
  165. package/package.json +8 -2
  166. package/dist/src/apiCredentialStore.d.ts.map +0 -1
  167. package/dist/src/apiCredentialStore.js.map +0 -1
  168. package/dist/src/apiCredentials.d.ts.map +0 -1
  169. package/dist/src/apiCredentials.js.map +0 -1
  170. package/dist/src/apiCredentialsSerialization.d.ts.map +0 -1
  171. package/dist/src/apiCredentialsSerialization.js.map +0 -1
  172. package/dist/src/registry.d.ts.map +0 -1
  173. package/dist/src/registry.js.map +0 -1
  174. package/dist/tests/registry.test.d.ts +0 -2
  175. package/dist/tests/registry.test.d.ts.map +0 -1
  176. package/dist/tests/registry.test.js.map +0 -1
@@ -0,0 +1,566 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { mkdtempSync, rmSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { Command } from 'commander';
6
+ import { registerCommands } from '../src/cliCommands.js';
7
+ import { extractTargetUrl, buildCurlArguments, parseResponseHeaders, } from '../src/gateway/gatewayEndpoint.js';
8
+ import { startGateway } from '../src/gateway/server.js';
9
+ import { EncryptedStorage } from '../src/encryptedStorage.js';
10
+ import { ApiCredentialStore } from '../src/apiCredentials/store.js';
11
+ import { Config } from '../src/config.js';
12
+ import { ServiceRegistry } from '../src/serviceRegistry.js';
13
+ import { ApiCredentialStatus } from '../src/apiCredentials/base.js';
14
+ import { NoCurlCredentialsNotSupportedError } from '../src/services/core/base.js';
15
+ const TEST_ENCRYPTION_KEY = 'dGVzdGtleXRlc3RrZXl0ZXN0a2V5dGVzdGtleXRlc3Q=';
16
+ async function writeSecureFile(path, content) {
17
+ const storage = await EncryptedStorage.create({ encryptionKeyOverride: TEST_ENCRYPTION_KEY });
18
+ storage.writeFile(path, content);
19
+ }
20
+ // ─── Unit Tests ───────────────────────────────────────────────────────────────
21
+ describe('extractTargetUrl', () => {
22
+ it('should extract https URL from gateway path', () => {
23
+ expect(extractTargetUrl('/gateway/https://api.github.com/user')).toBe('https://api.github.com/user');
24
+ });
25
+ it('should extract http URL from gateway path', () => {
26
+ expect(extractTargetUrl('/gateway/http://localhost:3000/api')).toBe('http://localhost:3000/api');
27
+ });
28
+ it('should preserve query parameters', () => {
29
+ expect(extractTargetUrl('/gateway/https://api.github.com/search/repositories?q=auth&sort=stars')).toBe('https://api.github.com/search/repositories?q=auth&sort=stars');
30
+ });
31
+ it('should return null for non-gateway paths', () => {
32
+ expect(extractTargetUrl('/other/https://example.com')).toBeNull();
33
+ expect(extractTargetUrl('/')).toBeNull();
34
+ expect(extractTargetUrl('')).toBeNull();
35
+ });
36
+ it('should return null for non-HTTP schemes', () => {
37
+ expect(extractTargetUrl('/gateway/ftp://example.com')).toBeNull();
38
+ expect(extractTargetUrl('/gateway/not-a-url')).toBeNull();
39
+ });
40
+ it('should return null for empty target after prefix', () => {
41
+ expect(extractTargetUrl('/gateway/')).toBeNull();
42
+ });
43
+ });
44
+ describe('buildCurlArguments', () => {
45
+ it('should build GET request with URL only', () => {
46
+ const args = buildCurlArguments('GET', new Map(), 'https://api.example.com/test', false);
47
+ expect(args).toEqual(['https://api.example.com/test']);
48
+ });
49
+ it('should add -X for non-GET methods', () => {
50
+ const args = buildCurlArguments('POST', new Map(), 'https://api.example.com/test', false);
51
+ expect(args).toEqual(['-X', 'POST', 'https://api.example.com/test']);
52
+ });
53
+ it('should forward headers', () => {
54
+ const headers = new Map([
55
+ ['Content-Type', 'application/json'],
56
+ ['Accept', 'application/json'],
57
+ ]);
58
+ const args = buildCurlArguments('GET', headers, 'https://api.example.com/test', false);
59
+ expect(args).toContain('-H');
60
+ expect(args).toContain('Content-Type: application/json');
61
+ expect(args).toContain('Accept: application/json');
62
+ });
63
+ it('should strip hop-by-hop headers', () => {
64
+ const headers = new Map([
65
+ ['Content-Type', 'application/json'],
66
+ ['Connection', 'keep-alive'],
67
+ ['Host', 'api.example.com'],
68
+ ['Transfer-Encoding', 'chunked'],
69
+ ['Keep-Alive', 'timeout=5'],
70
+ ]);
71
+ const args = buildCurlArguments('GET', headers, 'https://api.example.com/test', false);
72
+ expect(args).toContain('Content-Type: application/json');
73
+ expect(args.join(' ')).not.toContain('Connection');
74
+ expect(args.join(' ')).not.toContain('Host');
75
+ expect(args.join(' ')).not.toContain('Transfer-Encoding');
76
+ expect(args.join(' ')).not.toContain('Keep-Alive');
77
+ });
78
+ it('should add --data-binary @- when body is present', () => {
79
+ const args = buildCurlArguments('POST', new Map([['Content-Type', 'application/json']]), 'https://api.example.com/test', true);
80
+ expect(args).toContain('--data-binary');
81
+ expect(args).toContain('@-');
82
+ });
83
+ it('should not add --data-binary when no body', () => {
84
+ const args = buildCurlArguments('POST', new Map(), 'https://api.example.com/test', false);
85
+ expect(args).not.toContain('--data-binary');
86
+ });
87
+ });
88
+ describe('parseResponseHeaders', () => {
89
+ it('should parse status line and headers', () => {
90
+ const dump = 'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nX-Custom: value\r\n\r\n';
91
+ const result = parseResponseHeaders(dump);
92
+ expect(result.statusCode).toBe(200);
93
+ expect(result.headers.get('content-type')).toEqual(['application/json']);
94
+ expect(result.headers.get('x-custom')).toEqual(['value']);
95
+ });
96
+ it('should parse HTTP/2 status line', () => {
97
+ const dump = 'HTTP/2 404\r\nContent-Type: text/plain\r\n\r\n';
98
+ const result = parseResponseHeaders(dump);
99
+ expect(result.statusCode).toBe(404);
100
+ });
101
+ it('should handle multiple values for the same header', () => {
102
+ const dump = 'HTTP/1.1 200 OK\r\nSet-Cookie: a=1\r\nSet-Cookie: b=2\r\n\r\n';
103
+ const result = parseResponseHeaders(dump);
104
+ expect(result.headers.get('set-cookie')).toEqual(['a=1', 'b=2']);
105
+ });
106
+ it('should use last status line in case of redirects or 100 Continue', () => {
107
+ const dump = 'HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n';
108
+ const result = parseResponseHeaders(dump);
109
+ expect(result.statusCode).toBe(200);
110
+ expect(result.headers.get('content-type')).toEqual(['text/html']);
111
+ });
112
+ it('should handle empty header dump', () => {
113
+ const result = parseResponseHeaders('');
114
+ expect(result.statusCode).toBe(0);
115
+ expect(result.headers.size).toBe(0);
116
+ });
117
+ it('should handle LF-only line endings', () => {
118
+ const dump = 'HTTP/1.1 200 OK\nContent-Type: text/plain\n\n';
119
+ const result = parseResponseHeaders(dump);
120
+ expect(result.statusCode).toBe(200);
121
+ expect(result.headers.get('content-type')).toEqual(['text/plain']);
122
+ });
123
+ });
124
+ // ─── Integration Tests ────────────────────────────────────────────────────────
125
+ describe('gateway server', () => {
126
+ let tempDir;
127
+ let gateway;
128
+ let logs;
129
+ let errorLogs;
130
+ let capturedCurlArgs;
131
+ let capturedCurlStdin;
132
+ let mockCurlResponse;
133
+ let mockCurlHeaderDump;
134
+ let mockPermissionResult;
135
+ const mockSlackService = {
136
+ name: 'slack',
137
+ displayName: 'Slack',
138
+ baseApiUrls: ['https://slack.com/api/'],
139
+ loginUrl: 'https://slack.com/signin',
140
+ info: 'Test Slack service.',
141
+ credentialCheckCurlArguments: ['https://slack.com/api/auth.test'],
142
+ checkApiCredentials: vi.fn().mockResolvedValue(ApiCredentialStatus.Valid),
143
+ setCredentialsExample(serviceName) {
144
+ return `latchkey auth set ${serviceName} -H "Authorization: Bearer xoxb-your-token"`;
145
+ },
146
+ getCredentialsNoCurl() {
147
+ throw new NoCurlCredentialsNotSupportedError('slack');
148
+ },
149
+ };
150
+ function createMockConfig(configOverrides = {}) {
151
+ const base = new Config((name) => {
152
+ if (name === 'LATCHKEY_DIRECTORY')
153
+ return tempDir;
154
+ if (name === 'LATCHKEY_ENCRYPTION_KEY')
155
+ return TEST_ENCRYPTION_KEY;
156
+ return undefined;
157
+ });
158
+ if (Object.keys(configOverrides).length === 0) {
159
+ return base;
160
+ }
161
+ return Object.assign(Object.create(Object.getPrototypeOf(base)), base, configOverrides);
162
+ }
163
+ async function createTestGateway(credentialsData = {
164
+ slack: { objectType: 'rawCurl', curlArguments: ['-H', 'Authorization: Bearer test-token'] },
165
+ }, overrides = {}, optionOverrides = {}, configOverrides = {}) {
166
+ const storePath = join(tempDir, 'credentials.json');
167
+ await writeSecureFile(storePath, JSON.stringify(credentialsData));
168
+ const encryptedStorage = await EncryptedStorage.create({
169
+ encryptionKeyOverride: TEST_ENCRYPTION_KEY,
170
+ });
171
+ const apiCredentialStore = new ApiCredentialStore(storePath, encryptedStorage);
172
+ const deps = {
173
+ registry: new ServiceRegistry([mockSlackService]),
174
+ config: createMockConfig(configOverrides),
175
+ runCurl: () => ({ returncode: 0, stdout: '', stderr: '' }),
176
+ runCurlAsync: async (args, options) => {
177
+ capturedCurlArgs = args;
178
+ capturedCurlStdin = options?.stdin;
179
+ // Write mock header dump to the temp file if -D flag is present
180
+ const dashDIndex = args.indexOf('-D');
181
+ if (dashDIndex !== -1 && dashDIndex + 1 < args.length) {
182
+ const headerFile = args[dashDIndex + 1];
183
+ const { writeFileSync } = await import('node:fs');
184
+ writeFileSync(headerFile, mockCurlHeaderDump);
185
+ }
186
+ return mockCurlResponse;
187
+ },
188
+ checkPermission: () => Promise.resolve(mockPermissionResult),
189
+ confirm: () => Promise.resolve(true),
190
+ exit: (code) => {
191
+ throw new Error(`process.exit(${String(code)})`);
192
+ },
193
+ log: (message) => {
194
+ logs.push(message);
195
+ },
196
+ errorLog: (message) => {
197
+ errorLogs.push(message);
198
+ },
199
+ version: '0.0.0-test',
200
+ ...overrides,
201
+ };
202
+ const options = {
203
+ port: 0, // auto-assign port
204
+ host: 'localhost',
205
+ maxBodySize: 10 * 1024 * 1024,
206
+ ...optionOverrides,
207
+ };
208
+ return startGateway(deps, apiCredentialStore, encryptedStorage, options);
209
+ }
210
+ function getHost() {
211
+ if (gateway === undefined) {
212
+ throw new Error('Gateway not started');
213
+ }
214
+ const address = gateway.server.address();
215
+ if (address === null || typeof address === 'string') {
216
+ throw new Error('Failed to get server address');
217
+ }
218
+ // Use the actual bound address to avoid IPv4/IPv6 mismatch
219
+ const host = address.family === 'IPv6' ? `[${address.address}]` : address.address;
220
+ return `http://${host}:${String(address.port)}`;
221
+ }
222
+ function fetch(path, options = {}) {
223
+ return globalThis.fetch(`${getHost()}${path}`, options);
224
+ }
225
+ beforeEach(() => {
226
+ tempDir = mkdtempSync(join(tmpdir(), 'latchkey-gw-test-'));
227
+ logs = [];
228
+ errorLogs = [];
229
+ capturedCurlArgs = [];
230
+ capturedCurlStdin = undefined;
231
+ mockPermissionResult = true;
232
+ mockCurlResponse = {
233
+ returncode: 0,
234
+ stdout: Buffer.from('{"ok":true}'),
235
+ stderr: '',
236
+ };
237
+ mockCurlHeaderDump = 'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n';
238
+ });
239
+ afterEach(async () => {
240
+ if (gateway) {
241
+ await gateway.close();
242
+ }
243
+ rmSync(tempDir, { recursive: true, force: true });
244
+ });
245
+ describe('health endpoint', () => {
246
+ it('should return status and version on GET /', async () => {
247
+ gateway = await createTestGateway();
248
+ const response = await fetch('/');
249
+ expect(response.status).toBe(200);
250
+ const body = (await response.json());
251
+ expect(body.status).toBe('ok');
252
+ expect(body.version).toBe('0.0.0-test');
253
+ });
254
+ });
255
+ describe('404 for unknown paths', () => {
256
+ it('should return 404 for non-gateway, non-root paths', async () => {
257
+ gateway = await createTestGateway();
258
+ const response = await fetch('/unknown');
259
+ expect(response.status).toBe(404);
260
+ });
261
+ });
262
+ describe('proxy requests', () => {
263
+ it('should proxy a GET request and forward response', async () => {
264
+ gateway = await createTestGateway();
265
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
266
+ expect(response.status).toBe(200);
267
+ expect(response.headers.get('content-type')).toBe('application/json');
268
+ const body = await response.text();
269
+ expect(body).toBe('{"ok":true}');
270
+ // Verify curl was called with injected credentials
271
+ expect(capturedCurlArgs).toContain('Authorization: Bearer test-token');
272
+ expect(capturedCurlArgs).toContain('https://slack.com/api/auth.test');
273
+ });
274
+ it('should proxy a POST request with body', async () => {
275
+ gateway = await createTestGateway();
276
+ const requestBody = '{"channel":"C01","text":"hello"}';
277
+ const response = await fetch('/gateway/https://slack.com/api/chat.postMessage', {
278
+ method: 'POST',
279
+ headers: { 'Content-Type': 'application/json' },
280
+ body: requestBody,
281
+ });
282
+ expect(response.status).toBe(200);
283
+ // Verify method and body were forwarded
284
+ expect(capturedCurlArgs).toContain('-X');
285
+ expect(capturedCurlArgs).toContain('POST');
286
+ expect(capturedCurlArgs).toContain('--data-binary');
287
+ expect(capturedCurlArgs).toContain('@-');
288
+ expect(capturedCurlStdin?.toString()).toBe(requestBody);
289
+ });
290
+ it('should forward query parameters in the target URL', async () => {
291
+ gateway = await createTestGateway();
292
+ await fetch('/gateway/https://slack.com/api/search.messages?query=hello&count=10');
293
+ expect(capturedCurlArgs).toContain('https://slack.com/api/search.messages?query=hello&count=10');
294
+ });
295
+ it('should strip hop-by-hop headers from inbound request', async () => {
296
+ gateway = await createTestGateway();
297
+ await fetch('/gateway/https://slack.com/api/auth.test', {
298
+ headers: {
299
+ 'Content-Type': 'application/json',
300
+ Connection: 'keep-alive',
301
+ },
302
+ });
303
+ // The Connection header should not be in curl args
304
+ const headerArgs = [];
305
+ for (let i = 0; i < capturedCurlArgs.length; i++) {
306
+ if (capturedCurlArgs[i] === '-H' && i + 1 < capturedCurlArgs.length) {
307
+ headerArgs.push(capturedCurlArgs[i + 1]);
308
+ }
309
+ }
310
+ expect(headerArgs.some((h) => h.toLowerCase().startsWith('connection:'))).toBe(false);
311
+ });
312
+ it('should forward upstream response headers', async () => {
313
+ mockCurlHeaderDump =
314
+ 'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nX-Custom-Header: custom-value\r\n\r\n';
315
+ gateway = await createTestGateway();
316
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
317
+ expect(response.headers.get('x-custom-header')).toBe('custom-value');
318
+ });
319
+ it('should forward upstream status code', async () => {
320
+ mockCurlHeaderDump = 'HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\n';
321
+ mockCurlResponse = {
322
+ returncode: 0,
323
+ stdout: Buffer.from('not found'),
324
+ stderr: '',
325
+ };
326
+ gateway = await createTestGateway();
327
+ const response = await fetch('/gateway/https://slack.com/api/unknown');
328
+ expect(response.status).toBe(404);
329
+ expect(await response.text()).toBe('not found');
330
+ });
331
+ });
332
+ describe('error handling', () => {
333
+ it('should return 400 for unknown service', async () => {
334
+ gateway = await createTestGateway();
335
+ const response = await fetch('/gateway/https://unknown-api.example.com/test');
336
+ expect(response.status).toBe(400);
337
+ const body = (await response.json());
338
+ expect(body.error).toContain('No service matches URL');
339
+ });
340
+ it('should return 400 for missing credentials', async () => {
341
+ gateway = await createTestGateway({});
342
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
343
+ expect(response.status).toBe(400);
344
+ const body = (await response.json());
345
+ expect(body.error).toContain('No credentials found for slack');
346
+ });
347
+ it('should pass through unknown service when passthroughUnknown is enabled', async () => {
348
+ mockCurlHeaderDump = 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n';
349
+ mockCurlResponse = {
350
+ returncode: 0,
351
+ stdout: Buffer.from('passthrough response'),
352
+ stderr: '',
353
+ };
354
+ gateway = await createTestGateway({
355
+ slack: {
356
+ objectType: 'rawCurl',
357
+ curlArguments: ['-H', 'Authorization: Bearer test-token'],
358
+ },
359
+ }, {}, {}, { passthroughUnknown: true });
360
+ const response = await fetch('/gateway/https://unknown-api.example.com/test');
361
+ expect(response.status).toBe(200);
362
+ const body = await response.text();
363
+ expect(body).toBe('passthrough response');
364
+ // Should not contain any credential injection
365
+ const headerArgs = [];
366
+ for (let i = 0; i < capturedCurlArgs.length; i++) {
367
+ if (capturedCurlArgs[i] === '-H' && i + 1 < capturedCurlArgs.length) {
368
+ headerArgs.push(capturedCurlArgs[i + 1]);
369
+ }
370
+ }
371
+ expect(headerArgs.some((h) => h.includes('Authorization: Bearer test-token'))).toBe(false);
372
+ });
373
+ it('should pass through missing credentials when passthroughUnknown is enabled', async () => {
374
+ mockCurlHeaderDump = 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n';
375
+ mockCurlResponse = {
376
+ returncode: 0,
377
+ stdout: Buffer.from('no-creds response'),
378
+ stderr: '',
379
+ };
380
+ gateway = await createTestGateway({}, {}, {}, { passthroughUnknown: true });
381
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
382
+ expect(response.status).toBe(200);
383
+ const body = await response.text();
384
+ expect(body).toBe('no-creds response');
385
+ });
386
+ it('should still inject credentials for known services when passthroughUnknown is enabled', async () => {
387
+ gateway = await createTestGateway({
388
+ slack: {
389
+ objectType: 'rawCurl',
390
+ curlArguments: ['-H', 'Authorization: Bearer test-token'],
391
+ },
392
+ }, {}, {}, { passthroughUnknown: true });
393
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
394
+ expect(response.status).toBe(200);
395
+ expect(capturedCurlArgs).toContain('Authorization: Bearer test-token');
396
+ });
397
+ it('should return 400 for invalid target URL scheme', async () => {
398
+ gateway = await createTestGateway();
399
+ const response = await fetch('/gateway/ftp://example.com/file');
400
+ expect(response.status).toBe(400);
401
+ const body = (await response.json());
402
+ expect(body.error).toContain('Could not extract URL');
403
+ });
404
+ it('should return 403 for permission denied', async () => {
405
+ mockPermissionResult = false;
406
+ gateway = await createTestGateway();
407
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
408
+ expect(response.status).toBe(403);
409
+ const body = (await response.json());
410
+ expect(body.error).toContain('not permitted');
411
+ });
412
+ it('should return 413 for oversized body', async () => {
413
+ gateway = await createTestGateway({
414
+ slack: {
415
+ objectType: 'rawCurl',
416
+ curlArguments: ['-H', 'Authorization: Bearer test-token'],
417
+ },
418
+ }, {}, { maxBodySize: 10 });
419
+ const response = await fetch('/gateway/https://slack.com/api/chat.postMessage', {
420
+ method: 'POST',
421
+ body: 'x'.repeat(100),
422
+ });
423
+ expect(response.status).toBe(413);
424
+ const body = (await response.json());
425
+ expect(body.error).toContain('body too large');
426
+ });
427
+ it('should return 502 with curl stderr as the error message', async () => {
428
+ mockCurlResponse = {
429
+ returncode: 6,
430
+ stdout: Buffer.from(''),
431
+ stderr: 'curl: (6) Could not resolve host: nonexistent',
432
+ };
433
+ // Don't write any header file
434
+ gateway = await createTestGateway({
435
+ slack: {
436
+ objectType: 'rawCurl',
437
+ curlArguments: ['-H', 'Authorization: Bearer test-token'],
438
+ },
439
+ }, {
440
+ runCurlAsync: (args) => {
441
+ capturedCurlArgs = args;
442
+ return Promise.resolve(mockCurlResponse);
443
+ },
444
+ });
445
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
446
+ expect(response.status).toBe(502);
447
+ const body = (await response.json());
448
+ // The upstream curl stderr is surfaced verbatim so callers see the
449
+ // actual failure reason (DNS, connection refused, TLS, ...) rather
450
+ // than a generic "Upstream request failed." placeholder.
451
+ expect(body.error).toContain('Could not resolve host: nonexistent');
452
+ });
453
+ it('falls back to the generic message when upstream curl produces no stderr', async () => {
454
+ mockCurlResponse = {
455
+ returncode: 7,
456
+ stdout: Buffer.from(''),
457
+ stderr: '',
458
+ };
459
+ gateway = await createTestGateway({
460
+ slack: {
461
+ objectType: 'rawCurl',
462
+ curlArguments: ['-H', 'Authorization: Bearer test-token'],
463
+ },
464
+ }, {
465
+ runCurlAsync: (args) => {
466
+ capturedCurlArgs = args;
467
+ return Promise.resolve(mockCurlResponse);
468
+ },
469
+ });
470
+ const response = await fetch('/gateway/https://slack.com/api/auth.test');
471
+ expect(response.status).toBe(502);
472
+ const body = (await response.json());
473
+ expect(body.error).toContain('Upstream request failed');
474
+ });
475
+ });
476
+ describe('logging', () => {
477
+ it('should log startup message', async () => {
478
+ gateway = await createTestGateway();
479
+ expect(logs.some((l) => l.includes('Latchkey gateway listening on'))).toBe(true);
480
+ });
481
+ it('should log request with status', async () => {
482
+ gateway = await createTestGateway();
483
+ await fetch('/gateway/https://slack.com/api/auth.test');
484
+ expect(logs.some((l) => l.includes('GET') && l.includes('200'))).toBe(true);
485
+ });
486
+ });
487
+ describe('concurrent requests', () => {
488
+ it('should handle multiple concurrent requests', async () => {
489
+ let requestCount = 0;
490
+ gateway = await createTestGateway({
491
+ slack: {
492
+ objectType: 'rawCurl',
493
+ curlArguments: ['-H', 'Authorization: Bearer test-token'],
494
+ },
495
+ }, {
496
+ runCurlAsync: async (args) => {
497
+ requestCount++;
498
+ const dashDIndex = args.indexOf('-D');
499
+ if (dashDIndex !== -1 && dashDIndex + 1 < args.length) {
500
+ const { writeFileSync } = await import('node:fs');
501
+ writeFileSync(args[dashDIndex + 1], 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n');
502
+ }
503
+ // Small delay to ensure concurrency
504
+ await new Promise((resolve) => setTimeout(resolve, 50));
505
+ return {
506
+ returncode: 0,
507
+ stdout: Buffer.from(`response-${String(requestCount)}`),
508
+ stderr: '',
509
+ };
510
+ },
511
+ });
512
+ const responses = await Promise.all([
513
+ fetch('/gateway/https://slack.com/api/test1'),
514
+ fetch('/gateway/https://slack.com/api/test2'),
515
+ fetch('/gateway/https://slack.com/api/test3'),
516
+ ]);
517
+ for (const response of responses) {
518
+ expect(response.status).toBe(200);
519
+ }
520
+ });
521
+ });
522
+ describe('shutdown', () => {
523
+ it('should shut down cleanly', async () => {
524
+ gateway = await createTestGateway();
525
+ const baseUrl = getHost();
526
+ await gateway.close();
527
+ expect(logs.some((l) => l.includes('Shutting down'))).toBe(true);
528
+ // Verify server is no longer accepting connections
529
+ await expect(globalThis.fetch(`${baseUrl}/`)).rejects.toThrow();
530
+ // Prevent double-close in afterEach
531
+ gateway = undefined;
532
+ });
533
+ });
534
+ });
535
+ // ─── CLI Command Tests ────────────────────────────────────────────────────────
536
+ describe('gateway CLI command registration', () => {
537
+ it('should register the gateway command', () => {
538
+ const program = new Command();
539
+ program.exitOverride();
540
+ const logs = [];
541
+ const errorLogs = [];
542
+ const mockDeps = {
543
+ registry: new ServiceRegistry([]),
544
+ config: new Config(() => undefined),
545
+ runCurl: () => ({ returncode: 0, stdout: '', stderr: '' }),
546
+ runCurlAsync: () => Promise.resolve({ returncode: 0, stdout: Buffer.from(''), stderr: '' }),
547
+ checkPermission: () => Promise.resolve(true),
548
+ confirm: () => Promise.resolve(true),
549
+ exit: (code) => {
550
+ throw new Error(`process.exit(${String(code)})`);
551
+ },
552
+ log: (message) => {
553
+ logs.push(message);
554
+ },
555
+ errorLog: (message) => {
556
+ errorLogs.push(message);
557
+ },
558
+ version: '0.0.0-test',
559
+ };
560
+ registerCommands(program, mockDeps);
561
+ const gatewayCommand = program.commands.find((c) => c.name() === 'gateway');
562
+ expect(gatewayCommand).toBeDefined();
563
+ expect(gatewayCommand.description()).toContain('gateway');
564
+ });
565
+ });
566
+ //# sourceMappingURL=gateway.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.test.js","sourceRoot":"","sources":["../../tests/gateway.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gatewayClient.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gatewayClient.test.d.ts","sourceRoot":"","sources":["../../tests/gatewayClient.test.ts"],"names":[],"mappings":""}