vesper-memory 0.3.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 (206) hide show
  1. package/.env.example +28 -0
  2. package/CHANGELOG.md +137 -0
  3. package/LICENSE +21 -0
  4. package/README.md +665 -0
  5. package/config/sqlite-schema.sql +413 -0
  6. package/dist/benchmark/index.d.ts +18 -0
  7. package/dist/benchmark/index.d.ts.map +1 -0
  8. package/dist/benchmark/index.js +19 -0
  9. package/dist/benchmark/index.js.map +1 -0
  10. package/dist/benchmark/metrics-collector.d.ts +90 -0
  11. package/dist/benchmark/metrics-collector.d.ts.map +1 -0
  12. package/dist/benchmark/metrics-collector.js +196 -0
  13. package/dist/benchmark/metrics-collector.js.map +1 -0
  14. package/dist/benchmark/report-generator.d.ts +35 -0
  15. package/dist/benchmark/report-generator.d.ts.map +1 -0
  16. package/dist/benchmark/report-generator.js +221 -0
  17. package/dist/benchmark/report-generator.js.map +1 -0
  18. package/dist/benchmark/runner.d.ts +30 -0
  19. package/dist/benchmark/runner.d.ts.map +1 -0
  20. package/dist/benchmark/runner.js +308 -0
  21. package/dist/benchmark/runner.js.map +1 -0
  22. package/dist/benchmark/scenarios/context-recall.d.ts +65 -0
  23. package/dist/benchmark/scenarios/context-recall.d.ts.map +1 -0
  24. package/dist/benchmark/scenarios/context-recall.js +180 -0
  25. package/dist/benchmark/scenarios/context-recall.js.map +1 -0
  26. package/dist/benchmark/scenarios/index.d.ts +34 -0
  27. package/dist/benchmark/scenarios/index.d.ts.map +1 -0
  28. package/dist/benchmark/scenarios/index.js +230 -0
  29. package/dist/benchmark/scenarios/index.js.map +1 -0
  30. package/dist/benchmark/statistics.d.ts +125 -0
  31. package/dist/benchmark/statistics.d.ts.map +1 -0
  32. package/dist/benchmark/statistics.js +520 -0
  33. package/dist/benchmark/statistics.js.map +1 -0
  34. package/dist/benchmark/types.d.ts +458 -0
  35. package/dist/benchmark/types.d.ts.map +1 -0
  36. package/dist/benchmark/types.js +297 -0
  37. package/dist/benchmark/types.js.map +1 -0
  38. package/dist/cli 2.js +583 -0
  39. package/dist/cli.d 2.ts +8 -0
  40. package/dist/cli.d.ts +8 -0
  41. package/dist/cli.d.ts 2.map +1 -0
  42. package/dist/cli.d.ts.map +1 -0
  43. package/dist/cli.js +583 -0
  44. package/dist/cli.js 2.map +1 -0
  45. package/dist/cli.js.map +1 -0
  46. package/dist/config/rate-limits.d.ts +76 -0
  47. package/dist/config/rate-limits.d.ts.map +1 -0
  48. package/dist/config/rate-limits.js +161 -0
  49. package/dist/config/rate-limits.js.map +1 -0
  50. package/dist/config 2/rate-limits.d.ts +76 -0
  51. package/dist/config 2/rate-limits.d.ts.map +1 -0
  52. package/dist/config 2/rate-limits.js +161 -0
  53. package/dist/config 2/rate-limits.js.map +1 -0
  54. package/dist/consolidation/pipeline.d.ts +52 -0
  55. package/dist/consolidation/pipeline.d.ts.map +1 -0
  56. package/dist/consolidation/pipeline.js +193 -0
  57. package/dist/consolidation/pipeline.js.map +1 -0
  58. package/dist/consolidation 2/pipeline.d.ts +52 -0
  59. package/dist/consolidation 2/pipeline.d.ts.map +1 -0
  60. package/dist/consolidation 2/pipeline.js +193 -0
  61. package/dist/consolidation 2/pipeline.js.map +1 -0
  62. package/dist/embeddings/client.d.ts +95 -0
  63. package/dist/embeddings/client.d.ts.map +1 -0
  64. package/dist/embeddings/client.js +162 -0
  65. package/dist/embeddings/client.js.map +1 -0
  66. package/dist/embeddings 2/client.d.ts +94 -0
  67. package/dist/embeddings 2/client.d.ts.map +1 -0
  68. package/dist/embeddings 2/client.js +144 -0
  69. package/dist/embeddings 2/client.js.map +1 -0
  70. package/dist/memory-layers/semantic-memory.d.ts +76 -0
  71. package/dist/memory-layers/semantic-memory.d.ts.map +1 -0
  72. package/dist/memory-layers/semantic-memory.js +231 -0
  73. package/dist/memory-layers/semantic-memory.js.map +1 -0
  74. package/dist/memory-layers/skill-library.d.ts +25 -0
  75. package/dist/memory-layers/skill-library.d.ts.map +1 -0
  76. package/dist/memory-layers/skill-library.js +54 -0
  77. package/dist/memory-layers/skill-library.js.map +1 -0
  78. package/dist/memory-layers/working-memory.d.ts +57 -0
  79. package/dist/memory-layers/working-memory.d.ts.map +1 -0
  80. package/dist/memory-layers/working-memory.js +153 -0
  81. package/dist/memory-layers/working-memory.js.map +1 -0
  82. package/dist/memory-layers 2/semantic-memory.d.ts +33 -0
  83. package/dist/memory-layers 2/semantic-memory.d.ts.map +1 -0
  84. package/dist/memory-layers 2/semantic-memory.js +114 -0
  85. package/dist/memory-layers 2/semantic-memory.js.map +1 -0
  86. package/dist/memory-layers 2/skill-library.d.ts +25 -0
  87. package/dist/memory-layers 2/skill-library.d.ts.map +1 -0
  88. package/dist/memory-layers 2/skill-library.js +54 -0
  89. package/dist/memory-layers 2/skill-library.js.map +1 -0
  90. package/dist/memory-layers 2/working-memory.d.ts +57 -0
  91. package/dist/memory-layers 2/working-memory.d.ts.map +1 -0
  92. package/dist/memory-layers 2/working-memory.js +153 -0
  93. package/dist/memory-layers 2/working-memory.js.map +1 -0
  94. package/dist/middleware/auth.d.ts +287 -0
  95. package/dist/middleware/auth.d.ts.map +1 -0
  96. package/dist/middleware/auth.js +610 -0
  97. package/dist/middleware/auth.js.map +1 -0
  98. package/dist/middleware 2/auth.d.ts +287 -0
  99. package/dist/middleware 2/auth.d.ts.map +1 -0
  100. package/dist/middleware 2/auth.js +610 -0
  101. package/dist/middleware 2/auth.js.map +1 -0
  102. package/dist/monitoring/health.d.ts +241 -0
  103. package/dist/monitoring/health.d.ts.map +1 -0
  104. package/dist/monitoring/health.js +649 -0
  105. package/dist/monitoring/health.js.map +1 -0
  106. package/dist/monitoring/metrics.d.ts +153 -0
  107. package/dist/monitoring/metrics.d.ts.map +1 -0
  108. package/dist/monitoring/metrics.js +349 -0
  109. package/dist/monitoring/metrics.js.map +1 -0
  110. package/dist/monitoring 2/health.d.ts +241 -0
  111. package/dist/monitoring 2/health.d.ts.map +1 -0
  112. package/dist/monitoring 2/health.js +649 -0
  113. package/dist/monitoring 2/health.js.map +1 -0
  114. package/dist/monitoring 2/metrics.d.ts +153 -0
  115. package/dist/monitoring 2/metrics.d.ts.map +1 -0
  116. package/dist/monitoring 2/metrics.js +349 -0
  117. package/dist/monitoring 2/metrics.js.map +1 -0
  118. package/dist/retrieval/hybrid-search.d.ts +186 -0
  119. package/dist/retrieval/hybrid-search.d.ts.map +1 -0
  120. package/dist/retrieval/hybrid-search.js +330 -0
  121. package/dist/retrieval/hybrid-search.js.map +1 -0
  122. package/dist/retrieval 2/hybrid-search.d.ts +186 -0
  123. package/dist/retrieval 2/hybrid-search.d.ts.map +1 -0
  124. package/dist/retrieval 2/hybrid-search.js +327 -0
  125. package/dist/retrieval 2/hybrid-search.js.map +1 -0
  126. package/dist/router/smart-router.d.ts +157 -0
  127. package/dist/router/smart-router.d.ts.map +1 -0
  128. package/dist/router/smart-router.js +524 -0
  129. package/dist/router/smart-router.js.map +1 -0
  130. package/dist/router 2/smart-router.d.ts +111 -0
  131. package/dist/router 2/smart-router.d.ts.map +1 -0
  132. package/dist/router 2/smart-router.js +383 -0
  133. package/dist/router 2/smart-router.js.map +1 -0
  134. package/dist/security/rate-limit-middleware.d.ts +119 -0
  135. package/dist/security/rate-limit-middleware.d.ts.map +1 -0
  136. package/dist/security/rate-limit-middleware.js +193 -0
  137. package/dist/security/rate-limit-middleware.js.map +1 -0
  138. package/dist/security 2/rate-limit-middleware.d.ts +119 -0
  139. package/dist/security 2/rate-limit-middleware.d.ts.map +1 -0
  140. package/dist/security 2/rate-limit-middleware.js +193 -0
  141. package/dist/security 2/rate-limit-middleware.js.map +1 -0
  142. package/dist/server 2.js +861 -0
  143. package/dist/server-wrapper 2.js +170 -0
  144. package/dist/server-wrapper.d 2.ts +12 -0
  145. package/dist/server-wrapper.d.ts +12 -0
  146. package/dist/server-wrapper.d.ts 2.map +1 -0
  147. package/dist/server-wrapper.d.ts.map +1 -0
  148. package/dist/server-wrapper.js +170 -0
  149. package/dist/server-wrapper.js 2.map +1 -0
  150. package/dist/server-wrapper.js.map +1 -0
  151. package/dist/server.d 2.ts +14 -0
  152. package/dist/server.d.ts +14 -0
  153. package/dist/server.d.ts 2.map +1 -0
  154. package/dist/server.d.ts.map +1 -0
  155. package/dist/server.js +656 -0
  156. package/dist/server.js 2.map +1 -0
  157. package/dist/server.js.map +1 -0
  158. package/dist/synthesis/conflict-detector.d.ts +43 -0
  159. package/dist/synthesis/conflict-detector.d.ts.map +1 -0
  160. package/dist/synthesis/conflict-detector.js +125 -0
  161. package/dist/synthesis/conflict-detector.js.map +1 -0
  162. package/dist/synthesis 2/conflict-detector.d.ts +43 -0
  163. package/dist/synthesis 2/conflict-detector.d.ts.map +1 -0
  164. package/dist/synthesis 2/conflict-detector.js +125 -0
  165. package/dist/synthesis 2/conflict-detector.js.map +1 -0
  166. package/dist/utils/monitoring.d.ts +25 -0
  167. package/dist/utils/monitoring.d.ts.map +1 -0
  168. package/dist/utils/monitoring.js +41 -0
  169. package/dist/utils/monitoring.js.map +1 -0
  170. package/dist/utils/rate-limiter.d.ts +97 -0
  171. package/dist/utils/rate-limiter.d.ts.map +1 -0
  172. package/dist/utils/rate-limiter.js +166 -0
  173. package/dist/utils/rate-limiter.js.map +1 -0
  174. package/dist/utils/validation.d.ts +139 -0
  175. package/dist/utils/validation.d.ts.map +1 -0
  176. package/dist/utils/validation.js +195 -0
  177. package/dist/utils/validation.js.map +1 -0
  178. package/dist/utils 2/monitoring.d.ts +25 -0
  179. package/dist/utils 2/monitoring.d.ts.map +1 -0
  180. package/dist/utils 2/monitoring.js +41 -0
  181. package/dist/utils 2/monitoring.js.map +1 -0
  182. package/dist/utils 2/rate-limiter.d.ts +97 -0
  183. package/dist/utils 2/rate-limiter.d.ts.map +1 -0
  184. package/dist/utils 2/rate-limiter.js +166 -0
  185. package/dist/utils 2/rate-limiter.js.map +1 -0
  186. package/dist/utils 2/validation.d.ts +139 -0
  187. package/dist/utils 2/validation.d.ts.map +1 -0
  188. package/dist/utils 2/validation.js +195 -0
  189. package/dist/utils 2/validation.js.map +1 -0
  190. package/docker-compose.yml +65 -0
  191. package/embedding-service/Dockerfile +29 -0
  192. package/embedding-service/README.md +68 -0
  193. package/embedding-service/requirements.txt +6 -0
  194. package/embedding-service/server.py +110 -0
  195. package/package.json +92 -0
  196. package/scripts/FRESH_INSTALL.md +280 -0
  197. package/scripts/README.md +101 -0
  198. package/scripts/ensure-infrastructure.sh +38 -0
  199. package/scripts/fresh-install-auto.sh +96 -0
  200. package/scripts/fresh-install.sh +167 -0
  201. package/scripts/health-check.sh +72 -0
  202. package/scripts/init-qdrant.ts +201 -0
  203. package/scripts/postinstall.js +94 -0
  204. package/scripts/run-accuracy-benchmark.ts +1237 -0
  205. package/scripts/run-real-benchmark.ts +581 -0
  206. package/scripts/test-mcp-server.sh +38 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Rate Limit Middleware
3
+ *
4
+ * Integrates rate limiting into the MCP server.
5
+ * Implements SEC-HIGH-001 and SEC-HIGH-002 from security audit.
6
+ *
7
+ * Security Features:
8
+ * - Fail-closed behavior when Redis unavailable (SEC-HIGH-002)
9
+ * - Tier-based rate limits
10
+ * - Standard rate limit headers
11
+ * - 429 error responses with Retry-After
12
+ */
13
+ import { createRateLimiter, } from "../utils/rate-limiter.js";
14
+ import { getTierLimits, } from "../config/rate-limits.js";
15
+ /**
16
+ * Rate limit error for 429 responses
17
+ */
18
+ export class RateLimitError extends Error {
19
+ statusCode;
20
+ retryAfter;
21
+ constructor(message, statusCode, retryAfter) {
22
+ super(message);
23
+ this.name = "RateLimitError";
24
+ this.statusCode = statusCode;
25
+ this.retryAfter = retryAfter;
26
+ // Maintain proper stack trace for where our error was thrown
27
+ if (Error.captureStackTrace) {
28
+ Error.captureStackTrace(this, RateLimitError);
29
+ }
30
+ }
31
+ }
32
+ /**
33
+ * Rate Limit Middleware
34
+ *
35
+ * Wraps the RateLimiter class and provides:
36
+ * - Standard HTTP headers
37
+ * - Fail-closed behavior
38
+ * - Error handling for 429 responses
39
+ */
40
+ export class RateLimitMiddleware {
41
+ redis;
42
+ rateLimiter = null;
43
+ options;
44
+ inMemoryLimits = new Map();
45
+ constructor(redis, options) {
46
+ this.redis = redis;
47
+ this.options = options;
48
+ // Build rate limit config from tier and custom limits
49
+ const config = this.buildConfig();
50
+ try {
51
+ this.rateLimiter = createRateLimiter(redis, config);
52
+ }
53
+ catch {
54
+ // Redis not available during construction - will handle in checkRateLimit
55
+ this.rateLimiter = null;
56
+ }
57
+ }
58
+ /**
59
+ * Build rate limit configuration from options
60
+ */
61
+ buildConfig() {
62
+ const tierLimits = getTierLimits(this.options.tier);
63
+ if (!this.options.customLimits) {
64
+ return tierLimits;
65
+ }
66
+ // Merge custom limits with tier defaults
67
+ const merged = { ...tierLimits };
68
+ for (const [operation, customConfig] of Object.entries(this.options.customLimits)) {
69
+ merged[operation] = customConfig;
70
+ }
71
+ return merged;
72
+ }
73
+ /**
74
+ * Check rate limit for a request
75
+ *
76
+ * @param userId - User identifier
77
+ * @param operation - MCP tool name
78
+ * @returns Rate limit check result
79
+ * @throws RateLimitError if rate limited or Redis unavailable (fail-closed)
80
+ */
81
+ async checkRateLimit(userId, operation) {
82
+ try {
83
+ // Try Redis-based rate limiting
84
+ return await this.checkRateLimitRedis(userId, operation);
85
+ }
86
+ catch (error) {
87
+ console.error("[WARN] Rate limiter Redis error:", error instanceof Error ? error.message : String(error));
88
+ if (this.options.failOpen) {
89
+ // FAIL OPEN: Allow request but log warning
90
+ console.warn("[SECURITY] Rate limiting bypassed due to Redis failure");
91
+ return this.createBypassResult();
92
+ }
93
+ else {
94
+ // FAIL CLOSED: Deny request (recommended for security)
95
+ console.error("[SECURITY] Rate limiting enforced - request denied");
96
+ throw new RateLimitError("Service temporarily unavailable. Please try again in a few minutes.", 503, 30);
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Check rate limit using Redis
102
+ */
103
+ async checkRateLimitRedis(userId, operation) {
104
+ // Ensure Redis is connected
105
+ if (this.redis.status !== "ready") {
106
+ // Try to connect
107
+ try {
108
+ await this.redis.connect();
109
+ }
110
+ catch {
111
+ throw new Error("Redis connection failed");
112
+ }
113
+ }
114
+ if (!this.rateLimiter) {
115
+ // Reinitialize rate limiter
116
+ const config = this.buildConfig();
117
+ this.rateLimiter = createRateLimiter(this.redis, config);
118
+ }
119
+ // Check rate limit
120
+ const result = await this.rateLimiter.checkLimit(userId, operation);
121
+ // Calculate reset timestamp (Unix seconds)
122
+ const resetAt = Math.floor(Date.now() / 1000) + result.resetIn;
123
+ // Build headers
124
+ const headers = {
125
+ "X-RateLimit-Limit": String(result.limit),
126
+ "X-RateLimit-Remaining": String(result.remaining),
127
+ "X-RateLimit-Reset": String(resetAt),
128
+ };
129
+ // Add Retry-After header if rate limited
130
+ if (!result.allowed) {
131
+ headers["Retry-After"] = String(result.resetIn);
132
+ }
133
+ return {
134
+ allowed: result.allowed,
135
+ remaining: result.remaining,
136
+ resetAt,
137
+ headers,
138
+ };
139
+ }
140
+ /**
141
+ * Create bypass result for fail-open mode
142
+ */
143
+ createBypassResult() {
144
+ return {
145
+ allowed: true,
146
+ remaining: -1,
147
+ resetAt: 0,
148
+ headers: {
149
+ "X-RateLimit-Limit": "-1",
150
+ "X-RateLimit-Remaining": "-1",
151
+ "X-RateLimit-Reset": "0",
152
+ "X-RateLimit-Bypass": "true",
153
+ },
154
+ };
155
+ }
156
+ /**
157
+ * Get current configuration
158
+ */
159
+ getConfig() {
160
+ return this.buildConfig();
161
+ }
162
+ /**
163
+ * Update tier
164
+ */
165
+ setTier(tier) {
166
+ this.options.tier = tier;
167
+ // Reinitialize rate limiter with new tier
168
+ const config = this.buildConfig();
169
+ if (this.redis.status === "ready") {
170
+ this.rateLimiter = createRateLimiter(this.redis, config);
171
+ }
172
+ }
173
+ }
174
+ /**
175
+ * Factory function to create rate limit middleware
176
+ *
177
+ * @param redis - Redis client
178
+ * @param options - Middleware options
179
+ */
180
+ export function createRateLimitMiddleware(redis, options) {
181
+ return new RateLimitMiddleware(redis, options);
182
+ }
183
+ /**
184
+ * Format rate limit error for MCP response
185
+ */
186
+ export function formatRateLimitError(error, operation) {
187
+ return {
188
+ error: error.message,
189
+ retryAfter: error.retryAfter,
190
+ operation,
191
+ };
192
+ }
193
+ //# sourceMappingURL=rate-limit-middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-middleware.js","sourceRoot":"","sources":["../../src/security/rate-limit-middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Rate Limit Middleware
3
+ *
4
+ * Integrates rate limiting into the MCP server.
5
+ * Implements SEC-HIGH-001 and SEC-HIGH-002 from security audit.
6
+ *
7
+ * Security Features:
8
+ * - Fail-closed behavior when Redis unavailable (SEC-HIGH-002)
9
+ * - Tier-based rate limits
10
+ * - Standard rate limit headers
11
+ * - 429 error responses with Retry-After
12
+ */
13
+ import { Redis } from "ioredis";
14
+ import { RateLimitConfig } from "../utils/rate-limiter.js";
15
+ import { TierName } from "../config/rate-limits.js";
16
+ /**
17
+ * Rate limit headers to include in responses
18
+ */
19
+ export interface RateLimitHeaders {
20
+ "X-RateLimit-Limit": string;
21
+ "X-RateLimit-Remaining": string;
22
+ "X-RateLimit-Reset": string;
23
+ "Retry-After"?: string;
24
+ "X-RateLimit-Bypass"?: string;
25
+ }
26
+ /**
27
+ * Result from rate limit check
28
+ */
29
+ export interface RateLimitCheckResult {
30
+ /** Whether the request is allowed */
31
+ allowed: boolean;
32
+ /** Remaining requests in current window */
33
+ remaining: number;
34
+ /** Unix timestamp when limit resets */
35
+ resetAt: number;
36
+ /** Rate limit headers to include in response */
37
+ headers: RateLimitHeaders;
38
+ }
39
+ /**
40
+ * Rate limit error for 429 responses
41
+ */
42
+ export declare class RateLimitError extends Error {
43
+ readonly statusCode: number;
44
+ readonly retryAfter: number;
45
+ constructor(message: string, statusCode: number, retryAfter: number);
46
+ }
47
+ /**
48
+ * Middleware options
49
+ */
50
+ export interface RateLimitMiddlewareOptions {
51
+ /** Whether to allow requests when Redis is unavailable */
52
+ failOpen: boolean;
53
+ /** Rate limit tier to apply */
54
+ tier: TierName;
55
+ /** Custom limits that override tier defaults */
56
+ customLimits?: Record<string, RateLimitConfig>;
57
+ /** Emergency limit for in-memory fallback */
58
+ emergencyLimit?: number;
59
+ }
60
+ /**
61
+ * Rate Limit Middleware
62
+ *
63
+ * Wraps the RateLimiter class and provides:
64
+ * - Standard HTTP headers
65
+ * - Fail-closed behavior
66
+ * - Error handling for 429 responses
67
+ */
68
+ export declare class RateLimitMiddleware {
69
+ private redis;
70
+ private rateLimiter;
71
+ private options;
72
+ private inMemoryLimits;
73
+ constructor(redis: Redis, options: RateLimitMiddlewareOptions);
74
+ /**
75
+ * Build rate limit configuration from options
76
+ */
77
+ private buildConfig;
78
+ /**
79
+ * Check rate limit for a request
80
+ *
81
+ * @param userId - User identifier
82
+ * @param operation - MCP tool name
83
+ * @returns Rate limit check result
84
+ * @throws RateLimitError if rate limited or Redis unavailable (fail-closed)
85
+ */
86
+ checkRateLimit(userId: string, operation: string): Promise<RateLimitCheckResult>;
87
+ /**
88
+ * Check rate limit using Redis
89
+ */
90
+ private checkRateLimitRedis;
91
+ /**
92
+ * Create bypass result for fail-open mode
93
+ */
94
+ private createBypassResult;
95
+ /**
96
+ * Get current configuration
97
+ */
98
+ getConfig(): Record<string, RateLimitConfig>;
99
+ /**
100
+ * Update tier
101
+ */
102
+ setTier(tier: TierName): void;
103
+ }
104
+ /**
105
+ * Factory function to create rate limit middleware
106
+ *
107
+ * @param redis - Redis client
108
+ * @param options - Middleware options
109
+ */
110
+ export declare function createRateLimitMiddleware(redis: Redis, options: RateLimitMiddlewareOptions): RateLimitMiddleware;
111
+ /**
112
+ * Format rate limit error for MCP response
113
+ */
114
+ export declare function formatRateLimitError(error: RateLimitError, operation: string): {
115
+ error: string;
116
+ retryAfter: number;
117
+ operation: string;
118
+ };
119
+ //# sourceMappingURL=rate-limit-middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-middleware.d.ts","sourceRoot":"","sources":["../../src/security/rate-limit-middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAGL,eAAe,EAEhB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,QAAQ,EAGT,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uBAAuB,EAAE,MAAM,CAAC;IAChC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAWpE;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,CAAC;IAClB,+BAA+B;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,cAAc,CACV;gBAEA,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,0BAA0B;IAe7D;;OAEG;IACH,OAAO,CAAC,WAAW;IAmBnB;;;;;;;OAOG;IACG,cAAc,CAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,CAAC;IA0BhC;;OAEG;YACW,mBAAmB;IA8CjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAc1B;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAI5C;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;CAQ9B;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CAErB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAM1D"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Rate Limit Middleware
3
+ *
4
+ * Integrates rate limiting into the MCP server.
5
+ * Implements SEC-HIGH-001 and SEC-HIGH-002 from security audit.
6
+ *
7
+ * Security Features:
8
+ * - Fail-closed behavior when Redis unavailable (SEC-HIGH-002)
9
+ * - Tier-based rate limits
10
+ * - Standard rate limit headers
11
+ * - 429 error responses with Retry-After
12
+ */
13
+ import { createRateLimiter, } from "../utils/rate-limiter.js";
14
+ import { getTierLimits, } from "../config/rate-limits.js";
15
+ /**
16
+ * Rate limit error for 429 responses
17
+ */
18
+ export class RateLimitError extends Error {
19
+ statusCode;
20
+ retryAfter;
21
+ constructor(message, statusCode, retryAfter) {
22
+ super(message);
23
+ this.name = "RateLimitError";
24
+ this.statusCode = statusCode;
25
+ this.retryAfter = retryAfter;
26
+ // Maintain proper stack trace for where our error was thrown
27
+ if (Error.captureStackTrace) {
28
+ Error.captureStackTrace(this, RateLimitError);
29
+ }
30
+ }
31
+ }
32
+ /**
33
+ * Rate Limit Middleware
34
+ *
35
+ * Wraps the RateLimiter class and provides:
36
+ * - Standard HTTP headers
37
+ * - Fail-closed behavior
38
+ * - Error handling for 429 responses
39
+ */
40
+ export class RateLimitMiddleware {
41
+ redis;
42
+ rateLimiter = null;
43
+ options;
44
+ inMemoryLimits = new Map();
45
+ constructor(redis, options) {
46
+ this.redis = redis;
47
+ this.options = options;
48
+ // Build rate limit config from tier and custom limits
49
+ const config = this.buildConfig();
50
+ try {
51
+ this.rateLimiter = createRateLimiter(redis, config);
52
+ }
53
+ catch {
54
+ // Redis not available during construction - will handle in checkRateLimit
55
+ this.rateLimiter = null;
56
+ }
57
+ }
58
+ /**
59
+ * Build rate limit configuration from options
60
+ */
61
+ buildConfig() {
62
+ const tierLimits = getTierLimits(this.options.tier);
63
+ if (!this.options.customLimits) {
64
+ return tierLimits;
65
+ }
66
+ // Merge custom limits with tier defaults
67
+ const merged = { ...tierLimits };
68
+ for (const [operation, customConfig] of Object.entries(this.options.customLimits)) {
69
+ merged[operation] = customConfig;
70
+ }
71
+ return merged;
72
+ }
73
+ /**
74
+ * Check rate limit for a request
75
+ *
76
+ * @param userId - User identifier
77
+ * @param operation - MCP tool name
78
+ * @returns Rate limit check result
79
+ * @throws RateLimitError if rate limited or Redis unavailable (fail-closed)
80
+ */
81
+ async checkRateLimit(userId, operation) {
82
+ try {
83
+ // Try Redis-based rate limiting
84
+ return await this.checkRateLimitRedis(userId, operation);
85
+ }
86
+ catch (error) {
87
+ console.error("[WARN] Rate limiter Redis error:", error instanceof Error ? error.message : String(error));
88
+ if (this.options.failOpen) {
89
+ // FAIL OPEN: Allow request but log warning
90
+ console.warn("[SECURITY] Rate limiting bypassed due to Redis failure");
91
+ return this.createBypassResult();
92
+ }
93
+ else {
94
+ // FAIL CLOSED: Deny request (recommended for security)
95
+ console.error("[SECURITY] Rate limiting enforced - request denied");
96
+ throw new RateLimitError("Service temporarily unavailable. Please try again in a few minutes.", 503, 30);
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Check rate limit using Redis
102
+ */
103
+ async checkRateLimitRedis(userId, operation) {
104
+ // Ensure Redis is connected
105
+ if (this.redis.status !== "ready") {
106
+ // Try to connect
107
+ try {
108
+ await this.redis.connect();
109
+ }
110
+ catch {
111
+ throw new Error("Redis connection failed");
112
+ }
113
+ }
114
+ if (!this.rateLimiter) {
115
+ // Reinitialize rate limiter
116
+ const config = this.buildConfig();
117
+ this.rateLimiter = createRateLimiter(this.redis, config);
118
+ }
119
+ // Check rate limit
120
+ const result = await this.rateLimiter.checkLimit(userId, operation);
121
+ // Calculate reset timestamp (Unix seconds)
122
+ const resetAt = Math.floor(Date.now() / 1000) + result.resetIn;
123
+ // Build headers
124
+ const headers = {
125
+ "X-RateLimit-Limit": String(result.limit),
126
+ "X-RateLimit-Remaining": String(result.remaining),
127
+ "X-RateLimit-Reset": String(resetAt),
128
+ };
129
+ // Add Retry-After header if rate limited
130
+ if (!result.allowed) {
131
+ headers["Retry-After"] = String(result.resetIn);
132
+ }
133
+ return {
134
+ allowed: result.allowed,
135
+ remaining: result.remaining,
136
+ resetAt,
137
+ headers,
138
+ };
139
+ }
140
+ /**
141
+ * Create bypass result for fail-open mode
142
+ */
143
+ createBypassResult() {
144
+ return {
145
+ allowed: true,
146
+ remaining: -1,
147
+ resetAt: 0,
148
+ headers: {
149
+ "X-RateLimit-Limit": "-1",
150
+ "X-RateLimit-Remaining": "-1",
151
+ "X-RateLimit-Reset": "0",
152
+ "X-RateLimit-Bypass": "true",
153
+ },
154
+ };
155
+ }
156
+ /**
157
+ * Get current configuration
158
+ */
159
+ getConfig() {
160
+ return this.buildConfig();
161
+ }
162
+ /**
163
+ * Update tier
164
+ */
165
+ setTier(tier) {
166
+ this.options.tier = tier;
167
+ // Reinitialize rate limiter with new tier
168
+ const config = this.buildConfig();
169
+ if (this.redis.status === "ready") {
170
+ this.rateLimiter = createRateLimiter(this.redis, config);
171
+ }
172
+ }
173
+ }
174
+ /**
175
+ * Factory function to create rate limit middleware
176
+ *
177
+ * @param redis - Redis client
178
+ * @param options - Middleware options
179
+ */
180
+ export function createRateLimitMiddleware(redis, options) {
181
+ return new RateLimitMiddleware(redis, options);
182
+ }
183
+ /**
184
+ * Format rate limit error for MCP response
185
+ */
186
+ export function formatRateLimitError(error, operation) {
187
+ return {
188
+ error: error.message,
189
+ retryAfter: error.retryAfter,
190
+ operation,
191
+ };
192
+ }
193
+ //# sourceMappingURL=rate-limit-middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-middleware.js","sourceRoot":"","sources":["../../src/security/rate-limit-middleware.ts"],"names":[],"mappings":"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"}