@getaegis/cli 0.8.1 → 0.9.1

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 (97) hide show
  1. package/README.md +38 -14
  2. package/dist/agent/agent.d.ts +1 -1
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/cli/commands/config.d.ts.map +1 -1
  5. package/dist/cli/commands/config.js +1 -1
  6. package/dist/cli/commands/config.js.map +1 -1
  7. package/dist/cli/commands/dashboard.d.ts.map +1 -1
  8. package/dist/cli/commands/dashboard.js +8 -2
  9. package/dist/cli/commands/dashboard.js.map +1 -1
  10. package/dist/cli/commands/db.d.ts +6 -0
  11. package/dist/cli/commands/db.d.ts.map +1 -0
  12. package/dist/cli/commands/db.js +139 -0
  13. package/dist/cli/commands/db.js.map +1 -0
  14. package/dist/cli/commands/gate.d.ts.map +1 -1
  15. package/dist/cli/commands/gate.js +8 -2
  16. package/dist/cli/commands/gate.js.map +1 -1
  17. package/dist/cli/commands/init.d.ts.map +1 -1
  18. package/dist/cli/commands/init.js +90 -24
  19. package/dist/cli/commands/init.js.map +1 -1
  20. package/dist/cli/commands/key.d.ts +6 -0
  21. package/dist/cli/commands/key.d.ts.map +1 -0
  22. package/dist/cli/commands/key.js +49 -0
  23. package/dist/cli/commands/key.js.map +1 -0
  24. package/dist/cli/commands/vault-manager.js +1 -1
  25. package/dist/cli/commands/vault-manager.js.map +1 -1
  26. package/dist/cli/commands/vault.d.ts.map +1 -1
  27. package/dist/cli/commands/vault.js +27 -3
  28. package/dist/cli/commands/vault.js.map +1 -1
  29. package/dist/cli/index.d.ts +2 -0
  30. package/dist/cli/index.d.ts.map +1 -1
  31. package/dist/cli/index.js +2 -0
  32. package/dist/cli/index.js.map +1 -1
  33. package/dist/cli.js +9 -2
  34. package/dist/cli.js.map +1 -1
  35. package/dist/config.d.ts +12 -0
  36. package/dist/config.d.ts.map +1 -1
  37. package/dist/config.js +54 -8
  38. package/dist/config.js.map +1 -1
  39. package/dist/dashboard/public/assets/{index-DkHiw9_f.js → index-Cah0_BKk.js} +1 -1
  40. package/dist/dashboard/public/index.html +1 -1
  41. package/dist/db.d.ts +13 -1
  42. package/dist/db.d.ts.map +1 -1
  43. package/dist/db.js +68 -49
  44. package/dist/db.js.map +1 -1
  45. package/dist/doctor.d.ts +1 -1
  46. package/dist/doctor.d.ts.map +1 -1
  47. package/dist/doctor.js +20 -0
  48. package/dist/doctor.js.map +1 -1
  49. package/dist/gate/gate.d.ts +24 -2
  50. package/dist/gate/gate.d.ts.map +1 -1
  51. package/dist/gate/gate.js +289 -62
  52. package/dist/gate/gate.js.map +1 -1
  53. package/dist/index.d.ts +2 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +1 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/key-storage/credential-manager-windows.d.ts +19 -0
  58. package/dist/key-storage/credential-manager-windows.d.ts.map +1 -0
  59. package/dist/key-storage/credential-manager-windows.js +87 -0
  60. package/dist/key-storage/credential-manager-windows.js.map +1 -0
  61. package/dist/key-storage/file-fallback.d.ts +21 -0
  62. package/dist/key-storage/file-fallback.d.ts.map +1 -0
  63. package/dist/key-storage/file-fallback.js +62 -0
  64. package/dist/key-storage/file-fallback.js.map +1 -0
  65. package/dist/key-storage/index.d.ts +6 -0
  66. package/dist/key-storage/index.d.ts.map +1 -0
  67. package/dist/key-storage/index.js +6 -0
  68. package/dist/key-storage/index.js.map +1 -0
  69. package/dist/key-storage/key-storage.d.ts +41 -0
  70. package/dist/key-storage/key-storage.d.ts.map +1 -0
  71. package/dist/key-storage/key-storage.js +70 -0
  72. package/dist/key-storage/key-storage.js.map +1 -0
  73. package/dist/key-storage/keychain-macos.d.ts +19 -0
  74. package/dist/key-storage/keychain-macos.d.ts.map +1 -0
  75. package/dist/key-storage/keychain-macos.js +51 -0
  76. package/dist/key-storage/keychain-macos.js.map +1 -0
  77. package/dist/key-storage/secret-service-linux.d.ts +19 -0
  78. package/dist/key-storage/secret-service-linux.d.ts.map +1 -0
  79. package/dist/key-storage/secret-service-linux.js +55 -0
  80. package/dist/key-storage/secret-service-linux.js.map +1 -0
  81. package/dist/ledger/ledger.d.ts +1 -1
  82. package/dist/ledger/ledger.d.ts.map +1 -1
  83. package/dist/metrics/metrics.d.ts +1 -1
  84. package/dist/metrics/metrics.d.ts.map +1 -1
  85. package/dist/metrics/metrics.js.map +1 -1
  86. package/dist/user/user.d.ts +1 -1
  87. package/dist/user/user.d.ts.map +1 -1
  88. package/dist/vault/crypto.js +1 -1
  89. package/dist/vault/vault-manager.d.ts +3 -3
  90. package/dist/vault/vault-manager.d.ts.map +1 -1
  91. package/dist/vault/vault-manager.js +14 -4
  92. package/dist/vault/vault-manager.js.map +1 -1
  93. package/dist/vault/vault.d.ts +1 -1
  94. package/dist/vault/vault.d.ts.map +1 -1
  95. package/dist/webhook/webhook.d.ts +1 -1
  96. package/dist/webhook/webhook.d.ts.map +1 -1
  97. package/package.json +12 -4
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
@@ -24,9 +24,9 @@ export interface GateOptions {
24
24
  tls?: TlsOptions;
25
25
  /** Maximum time (ms) to wait for in-flight requests during shutdown (default: 10000) */
26
26
  shutdownTimeoutMs?: number;
27
- /** Agent registry — required when requireAgentAuth is true */
27
+ /** Agent registry — required when agent auth is enabled (default) */
28
28
  agentRegistry?: AgentRegistry;
29
- /** When true, every request must include a valid X-Aegis-Agent token */
29
+ /** When true (default), every request must include a valid X-Aegis-Agent token. Use --no-agent-auth to disable. */
30
30
  requireAgentAuth?: boolean;
31
31
  /** Directory containing YAML policy files — enables policy evaluation */
32
32
  policyDir?: string;
@@ -38,6 +38,12 @@ export interface GateOptions {
38
38
  webhooks?: WebhookManager;
39
39
  /** Callback fired after every audit entry is logged — used by dashboard for live feed */
40
40
  onAuditEntry?: (entry: AuditBroadcast) => void;
41
+ /** Maximum request body size in bytes (default: 1 MB). Bodies exceeding this return 413. */
42
+ maxBodySize?: number;
43
+ /** Request timeout in milliseconds (default: 30s). Covers both inbound and outbound. */
44
+ requestTimeout?: number;
45
+ /** Maximum concurrent in-flight requests per agent (default: 50). */
46
+ maxConnectionsPerAgent?: number;
41
47
  /** Testing: redirect outbound requests to a local server */
42
48
  _testUpstream?: {
43
49
  protocol: 'http' | 'https';
@@ -93,6 +99,17 @@ export declare class Gate {
93
99
  private metrics?;
94
100
  private webhooks?;
95
101
  private onAuditEntry?;
102
+ private maxBodySize;
103
+ private requestTimeout;
104
+ private maxConnectionsPerAgent;
105
+ /** Tracks in-flight request count per agent (keyed by agent ID). */
106
+ private agentConnections;
107
+ /** Tracks upstream service failures for circuit breaker (keyed by service name). */
108
+ private circuitBreaker;
109
+ /** Dedicated HTTP agent for outbound proxy requests (connection pooling with keep-alive). */
110
+ private httpAgent;
111
+ /** Dedicated HTTPS agent for outbound proxy requests (connection pooling with keep-alive + TLS session reuse). */
112
+ private httpsAgent;
96
113
  constructor(options: GateOptions);
97
114
  /**
98
115
  * Start the Gate proxy server.
@@ -151,6 +168,11 @@ export declare class Gate {
151
168
  */
152
169
  get inFlightRequests(): number;
153
170
  private handleRequest;
171
+ /**
172
+ * Record an upstream failure for circuit breaker logic.
173
+ * After 5 consecutive failures, the circuit opens for 30 seconds.
174
+ */
175
+ private recordCircuitFailure;
154
176
  /**
155
177
  * Inject the credential into outbound request headers based on auth type.
156
178
  * For `query` auth, the secret is appended as a URL query parameter instead.
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/gate/gate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/gate/gate.ts"],"names":[],"mappings":"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"}
package/dist/gate/gate.js CHANGED
@@ -57,6 +57,17 @@ export class Gate {
57
57
  metrics;
58
58
  webhooks;
59
59
  onAuditEntry;
60
+ maxBodySize;
61
+ requestTimeout;
62
+ maxConnectionsPerAgent;
63
+ /** Tracks in-flight request count per agent (keyed by agent ID). */
64
+ agentConnections = new Map();
65
+ /** Tracks upstream service failures for circuit breaker (keyed by service name). */
66
+ circuitBreaker = new Map();
67
+ /** Dedicated HTTP agent for outbound proxy requests (connection pooling with keep-alive). */
68
+ httpAgent;
69
+ /** Dedicated HTTPS agent for outbound proxy requests (connection pooling with keep-alive + TLS session reuse). */
70
+ httpsAgent;
60
71
  constructor(options) {
61
72
  this.vault = options.vault;
62
73
  this.ledger = options.ledger;
@@ -71,12 +82,30 @@ export class Gate {
71
82
  this.bodyInspector = new BodyInspector();
72
83
  this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 10_000;
73
84
  this.agentRegistry = options.agentRegistry;
74
- this.requireAgentAuth = options.requireAgentAuth ?? false;
85
+ this.requireAgentAuth = options.requireAgentAuth ?? true;
75
86
  this.policyMode = options.policyMode ?? 'enforce';
76
87
  this.policyDir = options.policyDir;
77
88
  this.metrics = options.metrics;
78
89
  this.webhooks = options.webhooks;
79
90
  this.onAuditEntry = options.onAuditEntry;
91
+ this.maxBodySize = options.maxBodySize ?? 1_048_576; // 1 MB
92
+ this.requestTimeout = options.requestTimeout ?? 30_000; // 30 seconds
93
+ this.maxConnectionsPerAgent = options.maxConnectionsPerAgent ?? 50;
94
+ // Dedicated connection pool agents for outbound proxy requests.
95
+ // keepAlive: true — reuse TCP connections across requests (avoids TCP+TLS handshake per request)
96
+ // maxSockets: 256 — cap concurrent sockets per upstream host (prevents socket exhaustion)
97
+ // maxFreeSockets: 64 — keep up to 64 idle sockets per host in the pool
98
+ // scheduling: 'lifo' — reuse most-recent socket first (reduces stale connection risk)
99
+ // timeout: 60s — idle socket timeout (close sockets unused for 60s)
100
+ const poolOptions = {
101
+ keepAlive: true,
102
+ maxSockets: 256,
103
+ maxFreeSockets: 64,
104
+ scheduling: 'lifo',
105
+ timeout: 60_000,
106
+ };
107
+ this.httpAgent = new http.Agent(poolOptions);
108
+ this.httpsAgent = new https.Agent(poolOptions);
80
109
  // Load policies from disk or test injection
81
110
  if (options._testPolicies) {
82
111
  this.policyMap = options._testPolicies;
@@ -207,6 +236,13 @@ export class Gate {
207
236
  if (addr && typeof addr === 'object') {
208
237
  this.port = addr.port;
209
238
  }
239
+ // Set server-level idle timeout to defend against slowloris attacks.
240
+ // Only covers idle socket time — outbound proxy has its own `timeout` option.
241
+ // Provide a custom callback so the default auto-destroy doesn't kill sockets
242
+ // that are legitimately waiting for upstream responses.
243
+ this.server?.setTimeout(this.requestTimeout, (socket) => {
244
+ socket.destroy();
245
+ });
210
246
  const protocol = this.tlsOptions ? 'https' : 'http';
211
247
  this.logger.info({ protocol, port: this.port }, `Aegis Gate listening on ${protocol}://localhost:${this.port}`);
212
248
  this.logger.info({ port: this.port }, 'Agent requests → localhost:{port}/{service}/path → credential injected → forwarded');
@@ -243,11 +279,16 @@ export class Gate {
243
279
  }
244
280
  return new Promise((resolve) => {
245
281
  if (!this.server) {
282
+ this.httpAgent.destroy();
283
+ this.httpsAgent.destroy();
246
284
  resolve({ drained: true, activeAtClose: 0 });
247
285
  return;
248
286
  }
249
287
  const finish = (drained) => {
250
288
  const activeAtClose = this.activeRequests;
289
+ // Destroy connection pool agents — close all keep-alive sockets
290
+ this.httpAgent.destroy();
291
+ this.httpsAgent.destroy();
251
292
  if (!drained) {
252
293
  // Force-destroy remaining connections so server.close() can complete
253
294
  this.server?.closeAllConnections();
@@ -313,8 +354,36 @@ export class Gate {
313
354
  const requestId = generateRequestId();
314
355
  const reqLog = this.logger.child({ requestId });
315
356
  try {
316
- const reqUrl = new URL(req.url ?? '/', `http://localhost:${this.port}`);
317
- const pathParts = reqUrl.pathname.split('/').filter(Boolean);
357
+ // Parse path segments from the RAW URL (not via new URL()) to prevent
358
+ // percent-encoded path traversal. new URL() normalises %2e%2e → .. and
359
+ // resolves /../, which would let an agent escape service routing and
360
+ // reach internal /_aegis/* endpoints via /service/%2e%2e/_aegis/health.
361
+ const rawUrl = req.url ?? '/';
362
+ const qIdx = rawUrl.indexOf('?');
363
+ const rawPath = qIdx >= 0 ? rawUrl.slice(0, qIdx) : rawUrl;
364
+ const rawQuery = qIdx >= 0 ? rawUrl.slice(qIdx) : '';
365
+ const pathParts = rawPath.split('/').filter(Boolean);
366
+ // Explicit path traversal guard: reject any segment that decodes to
367
+ // ".." or "." — belt-and-suspenders defense on top of raw parsing.
368
+ // The service lookup would naturally reject these, but blocking here
369
+ // produces a clear 400 and audit trail entry for traversal attempts.
370
+ const hasTraversal = pathParts.some((seg) => {
371
+ if (seg === '..' || seg === '.')
372
+ return true;
373
+ try {
374
+ const decoded = decodeURIComponent(seg);
375
+ return decoded === '..' || decoded === '.';
376
+ }
377
+ catch {
378
+ return false;
379
+ }
380
+ });
381
+ if (hasTraversal) {
382
+ reqLog.warn({ path: rawPath }, 'Blocked: path traversal attempt');
383
+ res.writeHead(400, { 'Content-Type': 'application/json' });
384
+ res.end(`${JSON.stringify({ error: 'Path traversal detected' })}\n`);
385
+ return;
386
+ }
318
387
  // Health check
319
388
  if (pathParts[0] === '_aegis' && pathParts[1] === 'health') {
320
389
  res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -367,7 +436,7 @@ export class Gate {
367
436
  res.writeHead(401, { 'Content-Type': 'application/json' });
368
437
  res.end(`${JSON.stringify({
369
438
  error: 'Agent authentication required',
370
- hint: 'Include X-Aegis-Agent header with your agent token',
439
+ hint: "Include X-Aegis-Agent header with your agent token. Run 'aegis agent add --name my-agent' to create one.",
371
440
  })}\n`);
372
441
  return;
373
442
  }
@@ -409,6 +478,40 @@ export class Gate {
409
478
  }
410
479
  }
411
480
  }
481
+ // ─── Per-Agent Connection Limits ─────────────────────────────────
482
+ // Prevent a single agent from exhausting all available connections
483
+ // by tracking in-flight requests per agent.
484
+ if (authenticatedAgent) {
485
+ const agentId = authenticatedAgent.id;
486
+ const currentConnections = this.agentConnections.get(agentId) ?? 0;
487
+ if (currentConnections >= this.maxConnectionsPerAgent) {
488
+ reqLog.warn({
489
+ agent: authenticatedAgent.name,
490
+ current: currentConnections,
491
+ max: this.maxConnectionsPerAgent,
492
+ }, 'Blocked: per-agent connection limit exceeded');
493
+ this.metrics?.recordBlocked(pathParts[0] ?? 'unknown', 'agent_connection_limit', authenticatedAgent.name);
494
+ res.writeHead(429, { 'Content-Type': 'application/json' });
495
+ res.end(`${JSON.stringify({
496
+ error: 'Too many concurrent requests for this agent',
497
+ agent: authenticatedAgent.name,
498
+ limit: this.maxConnectionsPerAgent,
499
+ hint: 'Wait for in-flight requests to complete or increase gate.max_connections_per_agent',
500
+ })}\n`);
501
+ return;
502
+ }
503
+ this.agentConnections.set(agentId, currentConnections + 1);
504
+ // Decrement on response close
505
+ res.on('close', () => {
506
+ const count = this.agentConnections.get(agentId) ?? 1;
507
+ if (count <= 1) {
508
+ this.agentConnections.delete(agentId);
509
+ }
510
+ else {
511
+ this.agentConnections.set(agentId, count - 1);
512
+ }
513
+ });
514
+ }
412
515
  // Route format: /{service}/rest/of/the/path
413
516
  const serviceName = pathParts[0];
414
517
  if (!serviceName) {
@@ -776,7 +879,7 @@ export class Gate {
776
879
  const agentRequestedHost = req.headers['x-target-host'] ?? undefined;
777
880
  const targetDomain = agentRequestedHost ?? credential.domains[0];
778
881
  const remainingPath = `/${pathParts.slice(1).join('/')}`;
779
- const query = reqUrl.search ?? '';
882
+ const query = rawQuery;
780
883
  // Domain guard: verify target domain is in the credential's allowlist
781
884
  // This is the core security boundary — blocks agents from exfiltrating
782
885
  // credentials to domains not explicitly approved.
@@ -827,12 +930,46 @@ export class Gate {
827
930
  reqLog.debug({ service: serviceName, method: req.method, targetDomain, path: remainingPath }, 'Proxying request');
828
931
  // Start request duration timer for Prometheus histogram
829
932
  const stopTimer = this.metrics?.startRequestTimer(serviceName);
830
- // Buffer the request body for inspection before forwarding
933
+ // Buffer the request body for inspection before forwarding.
934
+ // Enforce max body size to prevent memory exhaustion.
831
935
  const bodyChunks = [];
936
+ let bodySize = 0;
937
+ let bodySizeExceeded = false;
832
938
  req.on('data', (chunk) => {
833
- bodyChunks.push(chunk);
939
+ bodySize += chunk.length;
940
+ if (bodySize > this.maxBodySize) {
941
+ bodySizeExceeded = true;
942
+ // Stop buffering — we'll reject in the 'end' handler.
943
+ // Don't destroy the stream (that kills the socket before we can respond).
944
+ }
945
+ else {
946
+ bodyChunks.push(chunk);
947
+ }
834
948
  });
835
949
  req.on('end', () => {
950
+ // Reject oversized bodies
951
+ if (bodySizeExceeded) {
952
+ reqLog.warn({ service: serviceName, bodySize, maxBodySize: this.maxBodySize }, 'Blocked: request body too large');
953
+ this.auditBlocked({
954
+ service: serviceName,
955
+ targetDomain,
956
+ method: req.method ?? 'GET',
957
+ path: remainingPath,
958
+ reason: 'Body too large',
959
+ });
960
+ this.metrics?.recordBlocked(serviceName, 'body_too_large', authenticatedAgent?.name);
961
+ res.writeHead(413, { 'Content-Type': 'application/json' });
962
+ res.end(`${JSON.stringify({
963
+ error: 'Request body too large',
964
+ received: bodySize,
965
+ limit: this.maxBodySize,
966
+ hint: 'Reduce body size or increase gate.max_body_size in aegis.config.yaml',
967
+ })}\n`);
968
+ return;
969
+ }
970
+ // Clear the server-level idle timeout — the body is fully received,
971
+ // so slowloris is no longer a risk. The outbound proxy timeout handles upstream delays.
972
+ req.socket?.setTimeout(0);
836
973
  const bodyBuffer = Buffer.concat(bodyChunks);
837
974
  const bodyString = bodyBuffer.toString('utf-8');
838
975
  // Body inspection: scan for credential-like patterns in the request body
@@ -873,67 +1010,141 @@ export class Gate {
873
1010
  reqLog.warn({ credential: credential.name, matches: inspection.matches }, 'Body inspection: credential-like patterns detected (warn mode)');
874
1011
  }
875
1012
  }
876
- // Forward the request
1013
+ // ─── Circuit Breaker Check ────────────────────────────────────
1014
+ // If the upstream service has been failing repeatedly, short-circuit
1015
+ // with 503 instead of adding more load to a struggling service.
1016
+ const circuitState = this.circuitBreaker.get(serviceName);
1017
+ if (circuitState && circuitState.openUntil > Date.now()) {
1018
+ reqLog.warn({ service: serviceName, failures: circuitState.failures }, 'Blocked: circuit breaker open');
1019
+ if (!res.headersSent) {
1020
+ const retryAfterSeconds = Math.ceil((circuitState.openUntil - Date.now()) / 1000);
1021
+ res.writeHead(503, {
1022
+ 'Content-Type': 'application/json',
1023
+ 'Retry-After': String(retryAfterSeconds),
1024
+ });
1025
+ res.end(`${JSON.stringify({
1026
+ error: 'Service temporarily unavailable (circuit breaker open)',
1027
+ service: serviceName,
1028
+ retryAfter: retryAfterSeconds,
1029
+ hint: 'The upstream service has been failing repeatedly. Requests will resume automatically.',
1030
+ })}\n`);
1031
+ }
1032
+ return;
1033
+ }
1034
+ // Forward the request with timeout and retry for transient failures
877
1035
  const upstream = this.testUpstream;
878
1036
  const transport = upstream?.protocol === 'http' ? http : https;
879
- const proxyReq = transport.request({
880
- hostname: upstream?.hostname ?? targetDomain,
881
- port: upstream?.port ?? 443,
882
- path: injectedPath ?? `${remainingPath}${query}`,
883
- method: req.method,
884
- headers: outboundHeaders,
885
- }, (proxyRes) => {
886
- // Strip any credential info from response headers
887
- const safeHeaders = { ...proxyRes.headers };
888
- delete safeHeaders['set-cookie']; // Prevent session hijack via agent
889
- this.auditAllowed({
890
- credentialId: credential.id,
891
- credentialName: credential.name,
892
- service: serviceName,
893
- targetDomain,
894
- method: req.method ?? 'GET',
895
- path: remainingPath,
896
- responseCode: proxyRes.statusCode,
897
- agentName: authenticatedAgent?.name,
898
- agentTokenPrefix: authenticatedAgent?.tokenPrefix,
899
- });
900
- reqLog.info({
901
- service: serviceName,
1037
+ const agent = upstream?.protocol === 'http' ? this.httpAgent : this.httpsAgent;
1038
+ const maxRetries = 2; // original + 2 retries = 3 total attempts
1039
+ const attemptProxy = (attempt) => {
1040
+ const proxyReq = transport.request({
1041
+ hostname: upstream?.hostname ?? targetDomain,
1042
+ port: upstream?.port ?? 443,
1043
+ path: injectedPath ?? `${remainingPath}${query}`,
902
1044
  method: req.method,
903
- path: remainingPath,
904
- status: proxyRes.statusCode,
905
- }, 'Request proxied');
906
- stopTimer?.();
907
- this.metrics?.recordRequest(serviceName, req.method ?? 'GET', proxyRes.statusCode ?? 500, authenticatedAgent?.name);
908
- res.writeHead(proxyRes.statusCode ?? 500, safeHeaders);
909
- proxyRes.pipe(res);
910
- });
911
- proxyReq.on('error', (err) => {
912
- reqLog.error({ service: serviceName, err: err.message }, 'Proxy error');
913
- if (!this.shuttingDown) {
914
- try {
915
- this.auditBlocked({
916
- service: serviceName,
917
- targetDomain,
918
- method: req.method ?? 'GET',
919
- path: remainingPath,
920
- reason: `Proxy error: ${err.message}`,
921
- });
1045
+ headers: outboundHeaders,
1046
+ timeout: this.requestTimeout,
1047
+ agent,
1048
+ }, (proxyRes) => {
1049
+ const statusCode = proxyRes.statusCode ?? 500;
1050
+ // Retry on transient upstream failures (502, 503, 504) if retries remain
1051
+ // Only retry idempotent methods (GET, HEAD, OPTIONS) — never retry state-changing methods
1052
+ const isRetryable = (statusCode === 502 || statusCode === 503 || statusCode === 504) &&
1053
+ attempt < maxRetries &&
1054
+ READ_METHODS.has(req.method?.toUpperCase() ?? 'GET');
1055
+ if (isRetryable) {
1056
+ reqLog.info({ service: serviceName, status: statusCode, attempt: attempt + 1 }, 'Retrying transient upstream failure');
1057
+ // Consume the response body before retrying
1058
+ proxyRes.resume();
1059
+ // Exponential backoff: 500ms, 1000ms
1060
+ const backoff = 500 * (attempt + 1);
1061
+ setTimeout(() => attemptProxy(attempt + 1), backoff);
1062
+ return;
922
1063
  }
923
- catch {
924
- // Ledger may be unavailable during shutdown cleanup
1064
+ // Record circuit breaker state on upstream failures
1065
+ if (statusCode >= 500) {
1066
+ this.recordCircuitFailure(serviceName);
925
1067
  }
1068
+ else {
1069
+ // Success — reset circuit breaker for this service
1070
+ this.circuitBreaker.delete(serviceName);
1071
+ }
1072
+ // Strip any credential info from response headers
1073
+ const safeHeaders = { ...proxyRes.headers };
1074
+ delete safeHeaders['set-cookie']; // Prevent session hijack via agent
1075
+ this.auditAllowed({
1076
+ credentialId: credential.id,
1077
+ credentialName: credential.name,
1078
+ service: serviceName,
1079
+ targetDomain,
1080
+ method: req.method ?? 'GET',
1081
+ path: remainingPath,
1082
+ responseCode: statusCode,
1083
+ agentName: authenticatedAgent?.name,
1084
+ agentTokenPrefix: authenticatedAgent?.tokenPrefix,
1085
+ });
1086
+ reqLog.info({
1087
+ service: serviceName,
1088
+ method: req.method,
1089
+ path: remainingPath,
1090
+ status: statusCode,
1091
+ }, 'Request proxied');
1092
+ stopTimer?.();
1093
+ this.metrics?.recordRequest(serviceName, req.method ?? 'GET', statusCode, authenticatedAgent?.name);
1094
+ res.writeHead(statusCode, safeHeaders);
1095
+ proxyRes.pipe(res);
1096
+ });
1097
+ // Outbound request timeout — fires if upstream takes too long
1098
+ proxyReq.on('timeout', () => {
1099
+ proxyReq.destroy(new Error('upstream request timed out'));
1100
+ });
1101
+ proxyReq.on('error', (err) => {
1102
+ // Retry on ECONNRESET / socket hang up when using a reused (keep-alive) socket.
1103
+ // The server may have closed the idle connection before our request arrived.
1104
+ const isStaleSocket = (err.message.includes('ECONNRESET') || err.message.includes('socket hang up')) &&
1105
+ proxyReq.reusedSocket;
1106
+ if (isStaleSocket && attempt < maxRetries) {
1107
+ reqLog.info({ service: serviceName, attempt: attempt + 1 }, 'Retrying after stale socket error on reused connection');
1108
+ attemptProxy(attempt + 1);
1109
+ return;
1110
+ }
1111
+ reqLog.error({ service: serviceName, err: err.message }, 'Proxy error');
1112
+ // Record the failure for circuit breaker
1113
+ this.recordCircuitFailure(serviceName);
1114
+ if (!this.shuttingDown) {
1115
+ try {
1116
+ this.auditBlocked({
1117
+ service: serviceName,
1118
+ targetDomain,
1119
+ method: req.method ?? 'GET',
1120
+ path: remainingPath,
1121
+ reason: `Proxy error: ${err.message}`,
1122
+ });
1123
+ }
1124
+ catch {
1125
+ // Ledger may be unavailable during shutdown cleanup
1126
+ }
1127
+ }
1128
+ if (!res.headersSent) {
1129
+ const isTimeout = err.message.includes('timed out');
1130
+ const statusCode = isTimeout ? 504 : 502;
1131
+ const errorMessage = isTimeout
1132
+ ? 'Upstream request timed out'
1133
+ : 'Failed to reach upstream service';
1134
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
1135
+ res.end(`${JSON.stringify({
1136
+ error: errorMessage,
1137
+ service: serviceName,
1138
+ })}\n`);
1139
+ }
1140
+ });
1141
+ // Write the buffered body and end
1142
+ if (bodyBuffer.length > 0) {
1143
+ proxyReq.write(bodyBuffer);
926
1144
  }
927
- if (!res.headersSent) {
928
- res.writeHead(502, { 'Content-Type': 'application/json' });
929
- res.end(`${JSON.stringify({ error: 'Failed to reach upstream service' })}\n`);
930
- }
931
- });
932
- // Write the buffered body and end
933
- if (bodyBuffer.length > 0) {
934
- proxyReq.write(bodyBuffer);
935
- }
936
- proxyReq.end();
1145
+ proxyReq.end();
1146
+ };
1147
+ attemptProxy(0);
937
1148
  });
938
1149
  }
939
1150
  catch (err) {
@@ -942,6 +1153,22 @@ export class Gate {
942
1153
  res.end(`${JSON.stringify({ error: 'Internal Aegis Gate error' })}\n`);
943
1154
  }
944
1155
  }
1156
+ /**
1157
+ * Record an upstream failure for circuit breaker logic.
1158
+ * After 5 consecutive failures, the circuit opens for 30 seconds.
1159
+ */
1160
+ recordCircuitFailure(service) {
1161
+ const state = this.circuitBreaker.get(service) ?? { failures: 0, openUntil: 0 };
1162
+ state.failures++;
1163
+ // Open the circuit after 5 consecutive failures (30s cooldown)
1164
+ const FAILURE_THRESHOLD = 5;
1165
+ const COOLDOWN_MS = 30_000;
1166
+ if (state.failures >= FAILURE_THRESHOLD) {
1167
+ state.openUntil = Date.now() + COOLDOWN_MS;
1168
+ this.logger.warn({ service, failures: state.failures, cooldownMs: COOLDOWN_MS }, 'Circuit breaker opened — service failures exceeded threshold');
1169
+ }
1170
+ this.circuitBreaker.set(service, state);
1171
+ }
945
1172
  /**
946
1173
  * Inject the credential into outbound request headers based on auth type.
947
1174
  * For `query` auth, the secret is appended as a URL query parameter instead.