@xtr-dev/rondevu-server 0.5.7 → 0.5.9
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/dist/index.js +22 -8
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/src/config.ts +22 -7
- package/src/rpc.ts +4 -4
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { Storage } from './storage/types.ts';
|
|
2
2
|
import { StorageType } from './storage/factory.ts';
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
// Read version from package.json for standalone server
|
|
8
|
+
function getPackageVersion(): string {
|
|
9
|
+
try {
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const pkgPath = join(__dirname, '..', 'package.json');
|
|
12
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
13
|
+
return pkg.version || 'unknown';
|
|
14
|
+
} catch {
|
|
15
|
+
return 'unknown';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
3
18
|
|
|
4
19
|
/**
|
|
5
20
|
* Application configuration
|
|
@@ -32,7 +47,7 @@ export interface Config {
|
|
|
32
47
|
maxTotalOffers: number; // Max total offers in storage
|
|
33
48
|
maxTotalCredentials: number; // Max total credentials in storage
|
|
34
49
|
maxIceCandidatesPerOffer: number; // Max ICE candidates per offer
|
|
35
|
-
|
|
50
|
+
credentialsPerIpPerSecond: number; // Rate limit: credentials per IP per second
|
|
36
51
|
requestsPerIpPerSecond: number; // Rate limit: requests per IP per second
|
|
37
52
|
}
|
|
38
53
|
|
|
@@ -93,7 +108,7 @@ export function loadConfig(): Config {
|
|
|
93
108
|
corsOrigins: process.env.CORS_ORIGINS
|
|
94
109
|
? process.env.CORS_ORIGINS.split(',').map(o => o.trim())
|
|
95
110
|
: ['*'],
|
|
96
|
-
version: process.env.VERSION ||
|
|
111
|
+
version: process.env.VERSION || getPackageVersion(),
|
|
97
112
|
offerDefaultTtl: parsePositiveInt(process.env.OFFER_DEFAULT_TTL, '60000', 'OFFER_DEFAULT_TTL', 1000),
|
|
98
113
|
offerMaxTtl: parsePositiveInt(process.env.OFFER_MAX_TTL, '86400000', 'OFFER_MAX_TTL', 1000),
|
|
99
114
|
offerMinTtl: parsePositiveInt(process.env.OFFER_MIN_TTL, '60000', 'OFFER_MIN_TTL', 1000),
|
|
@@ -113,7 +128,7 @@ export function loadConfig(): Config {
|
|
|
113
128
|
maxTotalOffers: parsePositiveInt(process.env.MAX_TOTAL_OFFERS, '10000', 'MAX_TOTAL_OFFERS', 1),
|
|
114
129
|
maxTotalCredentials: parsePositiveInt(process.env.MAX_TOTAL_CREDENTIALS, '50000', 'MAX_TOTAL_CREDENTIALS', 1),
|
|
115
130
|
maxIceCandidatesPerOffer: parsePositiveInt(process.env.MAX_ICE_CANDIDATES_PER_OFFER, '50', 'MAX_ICE_CANDIDATES_PER_OFFER', 1),
|
|
116
|
-
|
|
131
|
+
credentialsPerIpPerSecond: parsePositiveInt(process.env.CREDENTIALS_PER_IP_PER_SECOND, '5', 'CREDENTIALS_PER_IP_PER_SECOND', 1),
|
|
117
132
|
requestsPerIpPerSecond: parsePositiveInt(process.env.REQUESTS_PER_IP_PER_SECOND, '50', 'REQUESTS_PER_IP_PER_SECOND', 1),
|
|
118
133
|
};
|
|
119
134
|
|
|
@@ -138,11 +153,11 @@ export const CONFIG_DEFAULTS = {
|
|
|
138
153
|
timestampMaxAge: 60000,
|
|
139
154
|
timestampMaxFuture: 60000,
|
|
140
155
|
// Resource limits
|
|
141
|
-
maxOffersPerUser:
|
|
142
|
-
maxTotalOffers:
|
|
156
|
+
maxOffersPerUser: 1000,
|
|
157
|
+
maxTotalOffers: 100000,
|
|
143
158
|
maxTotalCredentials: 50000,
|
|
144
159
|
maxIceCandidatesPerOffer: 50,
|
|
145
|
-
|
|
160
|
+
credentialsPerIpPerSecond: 5,
|
|
146
161
|
requestsPerIpPerSecond: 50,
|
|
147
162
|
} as const;
|
|
148
163
|
|
|
@@ -186,7 +201,7 @@ export function buildWorkerConfig(env: {
|
|
|
186
201
|
maxTotalOffers: CONFIG_DEFAULTS.maxTotalOffers,
|
|
187
202
|
maxTotalCredentials: CONFIG_DEFAULTS.maxTotalCredentials,
|
|
188
203
|
maxIceCandidatesPerOffer: CONFIG_DEFAULTS.maxIceCandidatesPerOffer,
|
|
189
|
-
|
|
204
|
+
credentialsPerIpPerSecond: CONFIG_DEFAULTS.credentialsPerIpPerSecond,
|
|
190
205
|
requestsPerIpPerSecond: CONFIG_DEFAULTS.requestsPerIpPerSecond,
|
|
191
206
|
};
|
|
192
207
|
}
|
package/src/rpc.ts
CHANGED
|
@@ -21,7 +21,7 @@ const MAX_PAGE_SIZE = 100;
|
|
|
21
21
|
// - Window starts on first request and expires after window duration
|
|
22
22
|
// - When window expires, counter resets to 0 and new window starts
|
|
23
23
|
// - This is simpler than sliding windows but may allow bursts at window boundaries
|
|
24
|
-
const CREDENTIAL_RATE_WINDOW =
|
|
24
|
+
const CREDENTIAL_RATE_WINDOW = 1000; // 1 second in milliseconds
|
|
25
25
|
const REQUEST_RATE_WINDOW = 1000; // 1 second in milliseconds
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -298,10 +298,10 @@ const handlers: Record<string, RpcHandler> = {
|
|
|
298
298
|
console.warn('⚠️ WARNING: Unable to determine client IP for credential generation. Using global rate limit.');
|
|
299
299
|
// Use global rate limit with much stricter limit (prevents DoS while allowing basic function)
|
|
300
300
|
rateLimitKey = 'cred_gen:global_unknown';
|
|
301
|
-
rateLimit = 2; // Only 2 credentials per
|
|
301
|
+
rateLimit = 2; // Only 2 credentials per second globally for all unknown IPs combined
|
|
302
302
|
} else {
|
|
303
303
|
rateLimitKey = `cred_gen:${request.clientIp}`;
|
|
304
|
-
rateLimit = config.
|
|
304
|
+
rateLimit = config.credentialsPerIpPerSecond;
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
const allowed = await storage.checkRateLimit(
|
|
@@ -313,7 +313,7 @@ const handlers: Record<string, RpcHandler> = {
|
|
|
313
313
|
if (!allowed) {
|
|
314
314
|
throw new RpcError(
|
|
315
315
|
ErrorCodes.RATE_LIMIT_EXCEEDED,
|
|
316
|
-
`Rate limit exceeded. Maximum ${rateLimit} credentials per
|
|
316
|
+
`Rate limit exceeded. Maximum ${rateLimit} credentials per second${request.clientIp ? ' per IP' : ' (global limit for unidentified IPs)'}.`
|
|
317
317
|
);
|
|
318
318
|
}
|
|
319
319
|
|