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.
- package/.env.example +28 -0
- package/CHANGELOG.md +137 -0
- package/LICENSE +21 -0
- package/README.md +665 -0
- package/config/sqlite-schema.sql +413 -0
- package/dist/benchmark/index.d.ts +18 -0
- package/dist/benchmark/index.d.ts.map +1 -0
- package/dist/benchmark/index.js +19 -0
- package/dist/benchmark/index.js.map +1 -0
- package/dist/benchmark/metrics-collector.d.ts +90 -0
- package/dist/benchmark/metrics-collector.d.ts.map +1 -0
- package/dist/benchmark/metrics-collector.js +196 -0
- package/dist/benchmark/metrics-collector.js.map +1 -0
- package/dist/benchmark/report-generator.d.ts +35 -0
- package/dist/benchmark/report-generator.d.ts.map +1 -0
- package/dist/benchmark/report-generator.js +221 -0
- package/dist/benchmark/report-generator.js.map +1 -0
- package/dist/benchmark/runner.d.ts +30 -0
- package/dist/benchmark/runner.d.ts.map +1 -0
- package/dist/benchmark/runner.js +308 -0
- package/dist/benchmark/runner.js.map +1 -0
- package/dist/benchmark/scenarios/context-recall.d.ts +65 -0
- package/dist/benchmark/scenarios/context-recall.d.ts.map +1 -0
- package/dist/benchmark/scenarios/context-recall.js +180 -0
- package/dist/benchmark/scenarios/context-recall.js.map +1 -0
- package/dist/benchmark/scenarios/index.d.ts +34 -0
- package/dist/benchmark/scenarios/index.d.ts.map +1 -0
- package/dist/benchmark/scenarios/index.js +230 -0
- package/dist/benchmark/scenarios/index.js.map +1 -0
- package/dist/benchmark/statistics.d.ts +125 -0
- package/dist/benchmark/statistics.d.ts.map +1 -0
- package/dist/benchmark/statistics.js +520 -0
- package/dist/benchmark/statistics.js.map +1 -0
- package/dist/benchmark/types.d.ts +458 -0
- package/dist/benchmark/types.d.ts.map +1 -0
- package/dist/benchmark/types.js +297 -0
- package/dist/benchmark/types.js.map +1 -0
- package/dist/cli 2.js +583 -0
- package/dist/cli.d 2.ts +8 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts 2.map +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +583 -0
- package/dist/cli.js 2.map +1 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/rate-limits.d.ts +76 -0
- package/dist/config/rate-limits.d.ts.map +1 -0
- package/dist/config/rate-limits.js +161 -0
- package/dist/config/rate-limits.js.map +1 -0
- package/dist/config 2/rate-limits.d.ts +76 -0
- package/dist/config 2/rate-limits.d.ts.map +1 -0
- package/dist/config 2/rate-limits.js +161 -0
- package/dist/config 2/rate-limits.js.map +1 -0
- package/dist/consolidation/pipeline.d.ts +52 -0
- package/dist/consolidation/pipeline.d.ts.map +1 -0
- package/dist/consolidation/pipeline.js +193 -0
- package/dist/consolidation/pipeline.js.map +1 -0
- package/dist/consolidation 2/pipeline.d.ts +52 -0
- package/dist/consolidation 2/pipeline.d.ts.map +1 -0
- package/dist/consolidation 2/pipeline.js +193 -0
- package/dist/consolidation 2/pipeline.js.map +1 -0
- package/dist/embeddings/client.d.ts +95 -0
- package/dist/embeddings/client.d.ts.map +1 -0
- package/dist/embeddings/client.js +162 -0
- package/dist/embeddings/client.js.map +1 -0
- package/dist/embeddings 2/client.d.ts +94 -0
- package/dist/embeddings 2/client.d.ts.map +1 -0
- package/dist/embeddings 2/client.js +144 -0
- package/dist/embeddings 2/client.js.map +1 -0
- package/dist/memory-layers/semantic-memory.d.ts +76 -0
- package/dist/memory-layers/semantic-memory.d.ts.map +1 -0
- package/dist/memory-layers/semantic-memory.js +231 -0
- package/dist/memory-layers/semantic-memory.js.map +1 -0
- package/dist/memory-layers/skill-library.d.ts +25 -0
- package/dist/memory-layers/skill-library.d.ts.map +1 -0
- package/dist/memory-layers/skill-library.js +54 -0
- package/dist/memory-layers/skill-library.js.map +1 -0
- package/dist/memory-layers/working-memory.d.ts +57 -0
- package/dist/memory-layers/working-memory.d.ts.map +1 -0
- package/dist/memory-layers/working-memory.js +153 -0
- package/dist/memory-layers/working-memory.js.map +1 -0
- package/dist/memory-layers 2/semantic-memory.d.ts +33 -0
- package/dist/memory-layers 2/semantic-memory.d.ts.map +1 -0
- package/dist/memory-layers 2/semantic-memory.js +114 -0
- package/dist/memory-layers 2/semantic-memory.js.map +1 -0
- package/dist/memory-layers 2/skill-library.d.ts +25 -0
- package/dist/memory-layers 2/skill-library.d.ts.map +1 -0
- package/dist/memory-layers 2/skill-library.js +54 -0
- package/dist/memory-layers 2/skill-library.js.map +1 -0
- package/dist/memory-layers 2/working-memory.d.ts +57 -0
- package/dist/memory-layers 2/working-memory.d.ts.map +1 -0
- package/dist/memory-layers 2/working-memory.js +153 -0
- package/dist/memory-layers 2/working-memory.js.map +1 -0
- package/dist/middleware/auth.d.ts +287 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +610 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware 2/auth.d.ts +287 -0
- package/dist/middleware 2/auth.d.ts.map +1 -0
- package/dist/middleware 2/auth.js +610 -0
- package/dist/middleware 2/auth.js.map +1 -0
- package/dist/monitoring/health.d.ts +241 -0
- package/dist/monitoring/health.d.ts.map +1 -0
- package/dist/monitoring/health.js +649 -0
- package/dist/monitoring/health.js.map +1 -0
- package/dist/monitoring/metrics.d.ts +153 -0
- package/dist/monitoring/metrics.d.ts.map +1 -0
- package/dist/monitoring/metrics.js +349 -0
- package/dist/monitoring/metrics.js.map +1 -0
- package/dist/monitoring 2/health.d.ts +241 -0
- package/dist/monitoring 2/health.d.ts.map +1 -0
- package/dist/monitoring 2/health.js +649 -0
- package/dist/monitoring 2/health.js.map +1 -0
- package/dist/monitoring 2/metrics.d.ts +153 -0
- package/dist/monitoring 2/metrics.d.ts.map +1 -0
- package/dist/monitoring 2/metrics.js +349 -0
- package/dist/monitoring 2/metrics.js.map +1 -0
- package/dist/retrieval/hybrid-search.d.ts +186 -0
- package/dist/retrieval/hybrid-search.d.ts.map +1 -0
- package/dist/retrieval/hybrid-search.js +330 -0
- package/dist/retrieval/hybrid-search.js.map +1 -0
- package/dist/retrieval 2/hybrid-search.d.ts +186 -0
- package/dist/retrieval 2/hybrid-search.d.ts.map +1 -0
- package/dist/retrieval 2/hybrid-search.js +327 -0
- package/dist/retrieval 2/hybrid-search.js.map +1 -0
- package/dist/router/smart-router.d.ts +157 -0
- package/dist/router/smart-router.d.ts.map +1 -0
- package/dist/router/smart-router.js +524 -0
- package/dist/router/smart-router.js.map +1 -0
- package/dist/router 2/smart-router.d.ts +111 -0
- package/dist/router 2/smart-router.d.ts.map +1 -0
- package/dist/router 2/smart-router.js +383 -0
- package/dist/router 2/smart-router.js.map +1 -0
- package/dist/security/rate-limit-middleware.d.ts +119 -0
- package/dist/security/rate-limit-middleware.d.ts.map +1 -0
- package/dist/security/rate-limit-middleware.js +193 -0
- package/dist/security/rate-limit-middleware.js.map +1 -0
- package/dist/security 2/rate-limit-middleware.d.ts +119 -0
- package/dist/security 2/rate-limit-middleware.d.ts.map +1 -0
- package/dist/security 2/rate-limit-middleware.js +193 -0
- package/dist/security 2/rate-limit-middleware.js.map +1 -0
- package/dist/server 2.js +861 -0
- package/dist/server-wrapper 2.js +170 -0
- package/dist/server-wrapper.d 2.ts +12 -0
- package/dist/server-wrapper.d.ts +12 -0
- package/dist/server-wrapper.d.ts 2.map +1 -0
- package/dist/server-wrapper.d.ts.map +1 -0
- package/dist/server-wrapper.js +170 -0
- package/dist/server-wrapper.js 2.map +1 -0
- package/dist/server-wrapper.js.map +1 -0
- package/dist/server.d 2.ts +14 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts 2.map +1 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +656 -0
- package/dist/server.js 2.map +1 -0
- package/dist/server.js.map +1 -0
- package/dist/synthesis/conflict-detector.d.ts +43 -0
- package/dist/synthesis/conflict-detector.d.ts.map +1 -0
- package/dist/synthesis/conflict-detector.js +125 -0
- package/dist/synthesis/conflict-detector.js.map +1 -0
- package/dist/synthesis 2/conflict-detector.d.ts +43 -0
- package/dist/synthesis 2/conflict-detector.d.ts.map +1 -0
- package/dist/synthesis 2/conflict-detector.js +125 -0
- package/dist/synthesis 2/conflict-detector.js.map +1 -0
- package/dist/utils/monitoring.d.ts +25 -0
- package/dist/utils/monitoring.d.ts.map +1 -0
- package/dist/utils/monitoring.js +41 -0
- package/dist/utils/monitoring.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +97 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +166 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/validation.d.ts +139 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +195 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/utils 2/monitoring.d.ts +25 -0
- package/dist/utils 2/monitoring.d.ts.map +1 -0
- package/dist/utils 2/monitoring.js +41 -0
- package/dist/utils 2/monitoring.js.map +1 -0
- package/dist/utils 2/rate-limiter.d.ts +97 -0
- package/dist/utils 2/rate-limiter.d.ts.map +1 -0
- package/dist/utils 2/rate-limiter.js +166 -0
- package/dist/utils 2/rate-limiter.js.map +1 -0
- package/dist/utils 2/validation.d.ts +139 -0
- package/dist/utils 2/validation.d.ts.map +1 -0
- package/dist/utils 2/validation.js +195 -0
- package/dist/utils 2/validation.js.map +1 -0
- package/docker-compose.yml +65 -0
- package/embedding-service/Dockerfile +29 -0
- package/embedding-service/README.md +68 -0
- package/embedding-service/requirements.txt +6 -0
- package/embedding-service/server.py +110 -0
- package/package.json +92 -0
- package/scripts/FRESH_INSTALL.md +280 -0
- package/scripts/README.md +101 -0
- package/scripts/ensure-infrastructure.sh +38 -0
- package/scripts/fresh-install-auto.sh +96 -0
- package/scripts/fresh-install.sh +167 -0
- package/scripts/health-check.sh +72 -0
- package/scripts/init-qdrant.ts +201 -0
- package/scripts/postinstall.js +94 -0
- package/scripts/run-accuracy-benchmark.ts +1237 -0
- package/scripts/run-real-benchmark.ts +581 -0
- package/scripts/test-mcp-server.sh +38 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Module
|
|
3
|
+
*
|
|
4
|
+
* Token bucket implementation for preventing DoS attacks and abuse.
|
|
5
|
+
* Limits requests per user per time window.
|
|
6
|
+
*
|
|
7
|
+
* Security Features:
|
|
8
|
+
* - Per-user rate limiting
|
|
9
|
+
* - Configurable limits per operation type
|
|
10
|
+
* - Redis-backed for distributed systems
|
|
11
|
+
* - Automatic token refill
|
|
12
|
+
*/
|
|
13
|
+
import { validateUserId } from './validation.js';
|
|
14
|
+
/**
|
|
15
|
+
* Default rate limits per operation
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_RATE_LIMITS = {
|
|
18
|
+
store_memory: {
|
|
19
|
+
maxRequests: 100,
|
|
20
|
+
windowSeconds: 60, // 100 requests per minute
|
|
21
|
+
},
|
|
22
|
+
retrieve_memory: {
|
|
23
|
+
maxRequests: 300,
|
|
24
|
+
windowSeconds: 60, // 300 requests per minute
|
|
25
|
+
},
|
|
26
|
+
list_recent: {
|
|
27
|
+
maxRequests: 60,
|
|
28
|
+
windowSeconds: 60, // 60 requests per minute
|
|
29
|
+
},
|
|
30
|
+
get_stats: {
|
|
31
|
+
maxRequests: 30,
|
|
32
|
+
windowSeconds: 60, // 30 requests per minute
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Token Bucket Rate Limiter
|
|
37
|
+
*
|
|
38
|
+
* Implements the token bucket algorithm using Redis for distributed rate limiting.
|
|
39
|
+
* Each user has a separate bucket per operation type.
|
|
40
|
+
*/
|
|
41
|
+
export class RateLimiter {
|
|
42
|
+
redis;
|
|
43
|
+
limits;
|
|
44
|
+
constructor(redis, limits = DEFAULT_RATE_LIMITS) {
|
|
45
|
+
this.redis = redis;
|
|
46
|
+
this.limits = limits;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if a request is allowed under rate limits
|
|
50
|
+
*
|
|
51
|
+
* @param userId - User identifier
|
|
52
|
+
* @param operation - Operation name (e.g., "store_memory")
|
|
53
|
+
* @returns Rate limit result with allowed status and metadata
|
|
54
|
+
*/
|
|
55
|
+
async checkLimit(userId, operation) {
|
|
56
|
+
// Validate user ID to prevent injection attacks
|
|
57
|
+
const sanitizedUserId = validateUserId(userId);
|
|
58
|
+
// Get rate limit config for this operation
|
|
59
|
+
const config = this.limits[operation];
|
|
60
|
+
if (!config) {
|
|
61
|
+
throw new Error(`No rate limit configured for operation: ${operation}`);
|
|
62
|
+
}
|
|
63
|
+
const key = `ratelimit:${sanitizedUserId}:${operation}`;
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
const windowMs = config.windowSeconds * 1000;
|
|
66
|
+
// Use Redis pipeline for atomic operations
|
|
67
|
+
const pipeline = this.redis.pipeline();
|
|
68
|
+
// Add current timestamp to sorted set with unique member
|
|
69
|
+
// Use timestamp + random component to ensure uniqueness
|
|
70
|
+
const member = `${now}:${Math.random().toString(36).substr(2, 9)}`;
|
|
71
|
+
pipeline.zadd(key, now, member);
|
|
72
|
+
// Remove timestamps outside the current window
|
|
73
|
+
const windowStart = now - windowMs;
|
|
74
|
+
pipeline.zremrangebyscore(key, 0, windowStart);
|
|
75
|
+
// Count requests in current window
|
|
76
|
+
pipeline.zcard(key);
|
|
77
|
+
// Set expiration to prevent memory leaks
|
|
78
|
+
pipeline.expire(key, config.windowSeconds * 2);
|
|
79
|
+
const results = await pipeline.exec();
|
|
80
|
+
if (!results) {
|
|
81
|
+
throw new Error('Redis pipeline failed');
|
|
82
|
+
}
|
|
83
|
+
// Extract count from pipeline results
|
|
84
|
+
// results[2] is the zcard result: [error, count]
|
|
85
|
+
const count = results[2][1];
|
|
86
|
+
const allowed = count <= config.maxRequests;
|
|
87
|
+
const remaining = Math.max(0, config.maxRequests - count);
|
|
88
|
+
// Calculate reset time (time until oldest request expires)
|
|
89
|
+
let resetIn = config.windowSeconds;
|
|
90
|
+
if (count > 0) {
|
|
91
|
+
const oldestTimestamps = await this.redis.zrange(key, 0, 0, 'WITHSCORES');
|
|
92
|
+
if (oldestTimestamps.length >= 2) {
|
|
93
|
+
const oldestTime = parseInt(oldestTimestamps[1]);
|
|
94
|
+
const expiresAt = oldestTime + windowMs;
|
|
95
|
+
resetIn = Math.ceil((expiresAt - now) / 1000);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
allowed,
|
|
100
|
+
remaining,
|
|
101
|
+
resetIn: Math.max(0, resetIn),
|
|
102
|
+
limit: config.maxRequests,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Reset rate limit for a user and operation
|
|
107
|
+
*
|
|
108
|
+
* Useful for testing or administrative overrides.
|
|
109
|
+
*
|
|
110
|
+
* @param userId - User identifier
|
|
111
|
+
* @param operation - Operation name
|
|
112
|
+
*/
|
|
113
|
+
async resetLimit(userId, operation) {
|
|
114
|
+
const sanitizedUserId = validateUserId(userId);
|
|
115
|
+
const key = `ratelimit:${sanitizedUserId}:${operation}`;
|
|
116
|
+
await this.redis.del(key);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get current usage for a user and operation
|
|
120
|
+
*
|
|
121
|
+
* @param userId - User identifier
|
|
122
|
+
* @param operation - Operation name
|
|
123
|
+
* @returns Current request count in window
|
|
124
|
+
*/
|
|
125
|
+
async getUsage(userId, operation) {
|
|
126
|
+
const sanitizedUserId = validateUserId(userId);
|
|
127
|
+
const config = this.limits[operation];
|
|
128
|
+
if (!config) {
|
|
129
|
+
throw new Error(`No rate limit configured for operation: ${operation}`);
|
|
130
|
+
}
|
|
131
|
+
const key = `ratelimit:${sanitizedUserId}:${operation}`;
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
const windowStart = now - (config.windowSeconds * 1000);
|
|
134
|
+
// Count requests in current window
|
|
135
|
+
const count = await this.redis.zcount(key, windowStart, now);
|
|
136
|
+
return count;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Update rate limit configuration
|
|
140
|
+
*
|
|
141
|
+
* @param operation - Operation name
|
|
142
|
+
* @param config - New rate limit configuration
|
|
143
|
+
*/
|
|
144
|
+
setLimit(operation, config) {
|
|
145
|
+
this.limits[operation] = config;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Get rate limit configuration for an operation
|
|
149
|
+
*
|
|
150
|
+
* @param operation - Operation name
|
|
151
|
+
* @returns Rate limit configuration
|
|
152
|
+
*/
|
|
153
|
+
getLimit(operation) {
|
|
154
|
+
return this.limits[operation];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Factory function to create a rate limiter
|
|
159
|
+
*
|
|
160
|
+
* @param redis - Redis client
|
|
161
|
+
* @param limits - Optional custom rate limits
|
|
162
|
+
*/
|
|
163
|
+
export function createRateLimiter(redis, limits) {
|
|
164
|
+
return new RateLimiter(redis, limits);
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA0BjD;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAoC;IAClE,YAAY,EAAE;QACZ,WAAW,EAAE,GAAG;QAChB,aAAa,EAAE,EAAE,EAAE,0BAA0B;KAC9C;IACD,eAAe,EAAE;QACf,WAAW,EAAE,GAAG;QAChB,aAAa,EAAE,EAAE,EAAE,0BAA0B;KAC9C;IACD,WAAW,EAAE;QACX,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,EAAE,EAAE,yBAAyB;KAC7C;IACD,SAAS,EAAE;QACT,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,EAAE,EAAE,yBAAyB;KAC7C;CACF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACd,KAAK,CAAQ;IACb,MAAM,CAAkC;IAEhD,YAAY,KAAY,EAAE,SAA0C,mBAAmB;QACrF,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,SAAiB;QAChD,gDAAgD;QAChD,MAAM,eAAe,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAE/C,2CAA2C;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2CAA2C,SAAS,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,GAAG,GAAG,aAAa,eAAe,IAAI,SAAS,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC;QAE7C,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QAEvC,yDAAyD;QACzD,wDAAwD;QACxD,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACnE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAEhC,+CAA+C;QAC/C,MAAM,WAAW,GAAG,GAAG,GAAG,QAAQ,CAAC;QACnC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;QAE/C,mCAAmC;QACnC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAEpB,yCAAyC;QACzC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;QAE/C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QAED,sCAAsC;QACtC,iDAAiD;QACjD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAW,CAAC;QAEtC,MAAM,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,WAAW,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC;QAE1D,2DAA2D;QAC3D,IAAI,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC;QACnC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;YAC1E,IAAI,gBAAgB,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjD,MAAM,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;gBACxC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO;YACP,SAAS;YACT,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;YAC7B,KAAK,EAAE,MAAM,CAAC,WAAW;SAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,SAAiB;QAChD,MAAM,eAAe,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,aAAa,eAAe,IAAI,SAAS,EAAE,CAAC;QACxD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,SAAiB;QAC9C,MAAM,eAAe,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2CAA2C,SAAS,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,GAAG,GAAG,aAAa,eAAe,IAAI,SAAS,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;QAExD,mCAAmC;QACnC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,SAAiB,EAAE,MAAuB;QACjD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC;IAClC,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,SAAiB;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAY,EACZ,MAAwC;IAExC,OAAO,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation Module
|
|
3
|
+
*
|
|
4
|
+
* Provides Zod schemas and validation functions for all MCP tool inputs
|
|
5
|
+
* and internal data types. Prevents injection attacks, DoS via oversized
|
|
6
|
+
* payloads, and data corruption.
|
|
7
|
+
*
|
|
8
|
+
* Security Features:
|
|
9
|
+
* - Length limits on all string inputs
|
|
10
|
+
* - Enum validation for controlled vocabularies
|
|
11
|
+
* - Vector value validation (NaN/Infinity prevention)
|
|
12
|
+
* - Collection name sanitization (injection prevention)
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
/**
|
|
16
|
+
* Schema for store_memory tool input
|
|
17
|
+
*
|
|
18
|
+
* Enforces:
|
|
19
|
+
* - Content between 1 and 100,000 characters (100KB limit)
|
|
20
|
+
* - Memory type must be one of: episodic, semantic, procedural
|
|
21
|
+
* - Metadata object optional, max 50 keys
|
|
22
|
+
*/
|
|
23
|
+
export declare const StoreMemoryInputSchema: z.ZodObject<{
|
|
24
|
+
content: z.ZodString;
|
|
25
|
+
memory_type: z.ZodEnum<{
|
|
26
|
+
episodic: "episodic";
|
|
27
|
+
semantic: "semantic";
|
|
28
|
+
procedural: "procedural";
|
|
29
|
+
}>;
|
|
30
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
export type StoreMemoryInput = z.infer<typeof StoreMemoryInputSchema>;
|
|
33
|
+
/**
|
|
34
|
+
* Schema for retrieve_memory tool input
|
|
35
|
+
*
|
|
36
|
+
* Enforces:
|
|
37
|
+
* - Query between 1 and 10,000 characters (10KB limit)
|
|
38
|
+
* - Memory types array max 10 items
|
|
39
|
+
* - Max results between 1 and 100
|
|
40
|
+
*/
|
|
41
|
+
export declare const RetrieveMemoryInputSchema: z.ZodObject<{
|
|
42
|
+
query: z.ZodString;
|
|
43
|
+
memory_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
44
|
+
episodic: "episodic";
|
|
45
|
+
semantic: "semantic";
|
|
46
|
+
procedural: "procedural";
|
|
47
|
+
}>>>;
|
|
48
|
+
max_results: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
49
|
+
routing_strategy: z.ZodOptional<z.ZodEnum<{
|
|
50
|
+
semantic: "semantic";
|
|
51
|
+
fast_path: "fast_path";
|
|
52
|
+
full_text: "full_text";
|
|
53
|
+
graph: "graph";
|
|
54
|
+
}>>;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
export type RetrieveMemoryInput = z.infer<typeof RetrieveMemoryInputSchema>;
|
|
57
|
+
/**
|
|
58
|
+
* Schema for list_recent tool input
|
|
59
|
+
*/
|
|
60
|
+
export declare const ListRecentInputSchema: z.ZodObject<{
|
|
61
|
+
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
62
|
+
memory_type: z.ZodOptional<z.ZodEnum<{
|
|
63
|
+
episodic: "episodic";
|
|
64
|
+
semantic: "semantic";
|
|
65
|
+
procedural: "procedural";
|
|
66
|
+
}>>;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
export type ListRecentInput = z.infer<typeof ListRecentInputSchema>;
|
|
69
|
+
/**
|
|
70
|
+
* Schema for get_stats tool input
|
|
71
|
+
*/
|
|
72
|
+
export declare const GetStatsInputSchema: z.ZodObject<{
|
|
73
|
+
detailed: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
export type GetStatsInput = z.infer<typeof GetStatsInputSchema>;
|
|
76
|
+
/**
|
|
77
|
+
* Vector validation schema
|
|
78
|
+
*
|
|
79
|
+
* Validates that all vector elements are finite numbers.
|
|
80
|
+
* Prevents NaN poisoning attacks that corrupt vector indexes.
|
|
81
|
+
*
|
|
82
|
+
* Security: SEC-005 fix
|
|
83
|
+
*/
|
|
84
|
+
export declare const VectorSchema: z.ZodArray<z.ZodNumber>;
|
|
85
|
+
/**
|
|
86
|
+
* Collection name validation schema
|
|
87
|
+
*
|
|
88
|
+
* Enforces alphanumeric names with underscores/hyphens only.
|
|
89
|
+
* Prevents injection attacks via malicious collection names.
|
|
90
|
+
*
|
|
91
|
+
* Security: SEC-012 fix
|
|
92
|
+
*/
|
|
93
|
+
export declare const CollectionNameSchema: z.ZodString;
|
|
94
|
+
/**
|
|
95
|
+
* User ID schema (for rate limiting)
|
|
96
|
+
*/
|
|
97
|
+
export declare const UserIdSchema: z.ZodString;
|
|
98
|
+
/**
|
|
99
|
+
* Validates input against a Zod schema and returns typed result
|
|
100
|
+
*
|
|
101
|
+
* @param schema - Zod schema to validate against
|
|
102
|
+
* @param input - Raw input to validate
|
|
103
|
+
* @returns Validated and typed data
|
|
104
|
+
* @throws McpError if validation fails
|
|
105
|
+
*/
|
|
106
|
+
export declare function validateInput<T>(schema: z.ZodSchema<T>, input: unknown): T;
|
|
107
|
+
/**
|
|
108
|
+
* Validates a vector has correct dimensions and finite values
|
|
109
|
+
*
|
|
110
|
+
* @param vector - Vector to validate
|
|
111
|
+
* @param expectedSize - Expected vector dimension
|
|
112
|
+
* @returns true if valid
|
|
113
|
+
* @throws Error if invalid
|
|
114
|
+
*/
|
|
115
|
+
export declare function validateVector(vector: number[], expectedSize: number): void;
|
|
116
|
+
/**
|
|
117
|
+
* Sanitizes a collection name to prevent injection attacks
|
|
118
|
+
*
|
|
119
|
+
* @param name - Collection name to sanitize
|
|
120
|
+
* @returns Sanitized collection name
|
|
121
|
+
* @throws Error if name is invalid
|
|
122
|
+
*/
|
|
123
|
+
export declare function sanitizeCollectionName(name: string): string;
|
|
124
|
+
/**
|
|
125
|
+
* Sanitizes a string by removing potentially dangerous characters
|
|
126
|
+
*
|
|
127
|
+
* @param input - String to sanitize
|
|
128
|
+
* @returns Sanitized string
|
|
129
|
+
*/
|
|
130
|
+
export declare function sanitizeString(input: string): string;
|
|
131
|
+
/**
|
|
132
|
+
* Validates a user ID for rate limiting
|
|
133
|
+
*
|
|
134
|
+
* @param userId - User ID to validate
|
|
135
|
+
* @returns Validated user ID
|
|
136
|
+
* @throws Error if invalid
|
|
137
|
+
*/
|
|
138
|
+
export declare function validateUserId(userId: string): string;
|
|
139
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;iBAajC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;iBAkBpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;iBAUhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,mBAAmB;;iBAI9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAMhE;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,yBAItB,CAAC;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,aAM9B,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,YAAY,aAMtB,CAAC;AAMJ;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAY1E;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAc3E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQpD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQrD"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation Module
|
|
3
|
+
*
|
|
4
|
+
* Provides Zod schemas and validation functions for all MCP tool inputs
|
|
5
|
+
* and internal data types. Prevents injection attacks, DoS via oversized
|
|
6
|
+
* payloads, and data corruption.
|
|
7
|
+
*
|
|
8
|
+
* Security Features:
|
|
9
|
+
* - Length limits on all string inputs
|
|
10
|
+
* - Enum validation for controlled vocabularies
|
|
11
|
+
* - Vector value validation (NaN/Infinity prevention)
|
|
12
|
+
* - Collection name sanitization (injection prevention)
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// MCP Tool Input Schemas
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Schema for store_memory tool input
|
|
21
|
+
*
|
|
22
|
+
* Enforces:
|
|
23
|
+
* - Content between 1 and 100,000 characters (100KB limit)
|
|
24
|
+
* - Memory type must be one of: episodic, semantic, procedural
|
|
25
|
+
* - Metadata object optional, max 50 keys
|
|
26
|
+
*/
|
|
27
|
+
export const StoreMemoryInputSchema = z.object({
|
|
28
|
+
content: z.string()
|
|
29
|
+
.min(1, "Content cannot be empty")
|
|
30
|
+
.max(100000, "Content exceeds 100KB limit"),
|
|
31
|
+
memory_type: z.enum(["episodic", "semantic", "procedural"], {
|
|
32
|
+
message: "Invalid memory type. Must be episodic, semantic, or procedural"
|
|
33
|
+
}),
|
|
34
|
+
metadata: z.record(z.string(), z.unknown())
|
|
35
|
+
.optional()
|
|
36
|
+
.refine((val) => !val || Object.keys(val).length <= 50, "Metadata cannot exceed 50 keys")
|
|
37
|
+
.refine((val) => !val || JSON.stringify(val).length <= 10000, "Metadata size exceeds 10KB limit"),
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Schema for retrieve_memory tool input
|
|
41
|
+
*
|
|
42
|
+
* Enforces:
|
|
43
|
+
* - Query between 1 and 10,000 characters (10KB limit)
|
|
44
|
+
* - Memory types array max 10 items
|
|
45
|
+
* - Max results between 1 and 100
|
|
46
|
+
*/
|
|
47
|
+
export const RetrieveMemoryInputSchema = z.object({
|
|
48
|
+
query: z.string()
|
|
49
|
+
.min(1, "Query cannot be empty")
|
|
50
|
+
.max(10000, "Query exceeds 10KB limit"),
|
|
51
|
+
memory_types: z.array(z.enum(["episodic", "semantic", "procedural"]))
|
|
52
|
+
.max(10, "Cannot filter by more than 10 memory types")
|
|
53
|
+
.optional(),
|
|
54
|
+
max_results: z.number()
|
|
55
|
+
.int("max_results must be an integer")
|
|
56
|
+
.min(1, "max_results must be at least 1")
|
|
57
|
+
.max(100, "max_results cannot exceed 100")
|
|
58
|
+
.optional()
|
|
59
|
+
.default(5),
|
|
60
|
+
routing_strategy: z.enum(["fast_path", "semantic", "full_text", "graph"])
|
|
61
|
+
.optional(),
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Schema for list_recent tool input
|
|
65
|
+
*/
|
|
66
|
+
export const ListRecentInputSchema = z.object({
|
|
67
|
+
limit: z.number()
|
|
68
|
+
.int("limit must be an integer")
|
|
69
|
+
.min(1, "limit must be at least 1")
|
|
70
|
+
.max(100, "limit cannot exceed 100")
|
|
71
|
+
.optional()
|
|
72
|
+
.default(5),
|
|
73
|
+
memory_type: z.enum(["episodic", "semantic", "procedural"])
|
|
74
|
+
.optional(),
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Schema for get_stats tool input
|
|
78
|
+
*/
|
|
79
|
+
export const GetStatsInputSchema = z.object({
|
|
80
|
+
detailed: z.boolean()
|
|
81
|
+
.optional()
|
|
82
|
+
.default(false),
|
|
83
|
+
});
|
|
84
|
+
// ============================================================================
|
|
85
|
+
// Internal Data Type Schemas
|
|
86
|
+
// ============================================================================
|
|
87
|
+
/**
|
|
88
|
+
* Vector validation schema
|
|
89
|
+
*
|
|
90
|
+
* Validates that all vector elements are finite numbers.
|
|
91
|
+
* Prevents NaN poisoning attacks that corrupt vector indexes.
|
|
92
|
+
*
|
|
93
|
+
* Security: SEC-005 fix
|
|
94
|
+
*/
|
|
95
|
+
export const VectorSchema = z.array(z.number())
|
|
96
|
+
.refine((arr) => arr.every(v => Number.isFinite(v)), { message: "Vector contains NaN or Infinity values" });
|
|
97
|
+
/**
|
|
98
|
+
* Collection name validation schema
|
|
99
|
+
*
|
|
100
|
+
* Enforces alphanumeric names with underscores/hyphens only.
|
|
101
|
+
* Prevents injection attacks via malicious collection names.
|
|
102
|
+
*
|
|
103
|
+
* Security: SEC-012 fix
|
|
104
|
+
*/
|
|
105
|
+
export const CollectionNameSchema = z.string()
|
|
106
|
+
.min(1, "Collection name cannot be empty")
|
|
107
|
+
.max(255, "Collection name cannot exceed 255 characters")
|
|
108
|
+
.regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/, "Collection name must start with a letter and contain only alphanumeric characters, underscores, or hyphens");
|
|
109
|
+
/**
|
|
110
|
+
* User ID schema (for rate limiting)
|
|
111
|
+
*/
|
|
112
|
+
export const UserIdSchema = z.string()
|
|
113
|
+
.min(1, "User ID cannot be empty")
|
|
114
|
+
.max(255, "User ID cannot exceed 255 characters")
|
|
115
|
+
.regex(/^[a-zA-Z0-9_-]+$/, "User ID must be alphanumeric with underscores or hyphens only");
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Validation Helper Functions
|
|
118
|
+
// ============================================================================
|
|
119
|
+
/**
|
|
120
|
+
* Validates input against a Zod schema and returns typed result
|
|
121
|
+
*
|
|
122
|
+
* @param schema - Zod schema to validate against
|
|
123
|
+
* @param input - Raw input to validate
|
|
124
|
+
* @returns Validated and typed data
|
|
125
|
+
* @throws McpError if validation fails
|
|
126
|
+
*/
|
|
127
|
+
export function validateInput(schema, input) {
|
|
128
|
+
const result = schema.safeParse(input);
|
|
129
|
+
if (!result.success) {
|
|
130
|
+
const errors = result.error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
131
|
+
throw new McpError(ErrorCode.InvalidParams, `Validation failed: ${errors}`);
|
|
132
|
+
}
|
|
133
|
+
return result.data;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Validates a vector has correct dimensions and finite values
|
|
137
|
+
*
|
|
138
|
+
* @param vector - Vector to validate
|
|
139
|
+
* @param expectedSize - Expected vector dimension
|
|
140
|
+
* @returns true if valid
|
|
141
|
+
* @throws Error if invalid
|
|
142
|
+
*/
|
|
143
|
+
export function validateVector(vector, expectedSize) {
|
|
144
|
+
// Dimension check
|
|
145
|
+
if (vector.length !== expectedSize) {
|
|
146
|
+
throw new Error(`Vector dimension mismatch: expected ${expectedSize}, got ${vector.length}`);
|
|
147
|
+
}
|
|
148
|
+
// Value validation (NaN/Infinity check)
|
|
149
|
+
if (!vector.every(v => Number.isFinite(v))) {
|
|
150
|
+
throw new Error("Vector contains invalid values (NaN or Infinity)");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Sanitizes a collection name to prevent injection attacks
|
|
155
|
+
*
|
|
156
|
+
* @param name - Collection name to sanitize
|
|
157
|
+
* @returns Sanitized collection name
|
|
158
|
+
* @throws Error if name is invalid
|
|
159
|
+
*/
|
|
160
|
+
export function sanitizeCollectionName(name) {
|
|
161
|
+
const result = CollectionNameSchema.safeParse(name);
|
|
162
|
+
if (!result.success) {
|
|
163
|
+
const error = result.error.issues[0];
|
|
164
|
+
throw new Error(`Invalid collection name: ${error.message}`);
|
|
165
|
+
}
|
|
166
|
+
return result.data;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Sanitizes a string by removing potentially dangerous characters
|
|
170
|
+
*
|
|
171
|
+
* @param input - String to sanitize
|
|
172
|
+
* @returns Sanitized string
|
|
173
|
+
*/
|
|
174
|
+
export function sanitizeString(input) {
|
|
175
|
+
// Remove null bytes
|
|
176
|
+
let sanitized = input.replace(/\0/g, '');
|
|
177
|
+
// Trim whitespace
|
|
178
|
+
sanitized = sanitized.trim();
|
|
179
|
+
return sanitized;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Validates a user ID for rate limiting
|
|
183
|
+
*
|
|
184
|
+
* @param userId - User ID to validate
|
|
185
|
+
* @returns Validated user ID
|
|
186
|
+
* @throws Error if invalid
|
|
187
|
+
*/
|
|
188
|
+
export function validateUserId(userId) {
|
|
189
|
+
const result = UserIdSchema.safeParse(userId);
|
|
190
|
+
if (!result.success) {
|
|
191
|
+
throw new Error("Invalid user ID format");
|
|
192
|
+
}
|
|
193
|
+
return result.data;
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monitoring & Logging - v3.0
|
|
3
|
+
*
|
|
4
|
+
* Track latency, accuracy, cache hit rates.
|
|
5
|
+
*/
|
|
6
|
+
export interface PerformanceMetrics {
|
|
7
|
+
p50: number;
|
|
8
|
+
p95: number;
|
|
9
|
+
p99: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class PerformanceMonitor {
|
|
12
|
+
private latencies;
|
|
13
|
+
private cacheHits;
|
|
14
|
+
private cacheMisses;
|
|
15
|
+
recordLatency(ms: number): void;
|
|
16
|
+
recordCacheHit(): void;
|
|
17
|
+
recordCacheMiss(): void;
|
|
18
|
+
getMetrics(): {
|
|
19
|
+
latency: PerformanceMetrics;
|
|
20
|
+
cacheHitRate: number;
|
|
21
|
+
totalRequests: number;
|
|
22
|
+
};
|
|
23
|
+
reset(): void;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=monitoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitoring.d.ts","sourceRoot":"","sources":["../../src/utils/monitoring.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,WAAW,CAAa;IAEhC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAO/B,cAAc,IAAI,IAAI;IAItB,eAAe,IAAI,IAAI;IAIvB,UAAU,IAAI;QACZ,OAAO,EAAE,kBAAkB,CAAC;QAC5B,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB;IAgBD,KAAK,IAAI,IAAI;CAKd"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monitoring & Logging - v3.0
|
|
3
|
+
*
|
|
4
|
+
* Track latency, accuracy, cache hit rates.
|
|
5
|
+
*/
|
|
6
|
+
export class PerformanceMonitor {
|
|
7
|
+
latencies = [];
|
|
8
|
+
cacheHits = 0;
|
|
9
|
+
cacheMisses = 0;
|
|
10
|
+
recordLatency(ms) {
|
|
11
|
+
this.latencies.push(ms);
|
|
12
|
+
if (this.latencies.length > 1000) {
|
|
13
|
+
this.latencies.shift();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
recordCacheHit() {
|
|
17
|
+
this.cacheHits++;
|
|
18
|
+
}
|
|
19
|
+
recordCacheMiss() {
|
|
20
|
+
this.cacheMisses++;
|
|
21
|
+
}
|
|
22
|
+
getMetrics() {
|
|
23
|
+
const sorted = [...this.latencies].sort((a, b) => a - b);
|
|
24
|
+
const p50 = sorted[Math.floor(sorted.length * 0.5)] || 0;
|
|
25
|
+
const p95 = sorted[Math.floor(sorted.length * 0.95)] || 0;
|
|
26
|
+
const p99 = sorted[Math.floor(sorted.length * 0.99)] || 0;
|
|
27
|
+
const total = this.cacheHits + this.cacheMisses;
|
|
28
|
+
const hitRate = total > 0 ? this.cacheHits / total : 0;
|
|
29
|
+
return {
|
|
30
|
+
latency: { p50, p95, p99 },
|
|
31
|
+
cacheHitRate: hitRate,
|
|
32
|
+
totalRequests: this.latencies.length,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
reset() {
|
|
36
|
+
this.latencies = [];
|
|
37
|
+
this.cacheHits = 0;
|
|
38
|
+
this.cacheMisses = 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=monitoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitoring.js","sourceRoot":"","sources":["../../src/utils/monitoring.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,OAAO,kBAAkB;IACrB,SAAS,GAAa,EAAE,CAAC;IACzB,SAAS,GAAW,CAAC,CAAC;IACtB,WAAW,GAAW,CAAC,CAAC;IAEhC,aAAa,CAAC,EAAU;QACtB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,eAAe;QACb,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,UAAU;QAKR,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC;QAChD,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvD,OAAO;YACL,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;YAC1B,YAAY,EAAE,OAAO;YACrB,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM;SACrC,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IACvB,CAAC;CACF"}
|