mastercontroller 1.3.10 → 1.3.13
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/.claude/settings.local.json +4 -1
- package/.eslintrc.json +50 -0
- package/.github/workflows/ci.yml +317 -0
- package/.prettierrc +10 -0
- package/DEPLOYMENT.md +956 -0
- package/MasterControl.js +98 -16
- package/MasterRequest.js +42 -1
- package/MasterRouter.js +15 -5
- package/README.md +485 -28
- package/SENIOR_ENGINEER_AUDIT.md +2477 -0
- package/VERIFICATION_CHECKLIST.md +726 -0
- package/error/README.md +2452 -0
- package/monitoring/HealthCheck.js +347 -0
- package/monitoring/PrometheusExporter.js +416 -0
- package/package.json +64 -11
- package/security/MasterValidator.js +140 -10
- package/security/adapters/RedisCSRFStore.js +428 -0
- package/security/adapters/RedisRateLimiter.js +462 -0
- package/security/adapters/RedisSessionStore.js +476 -0
- package/FIXES_APPLIED.md +0 -378
- package/error/ErrorBoundary.js +0 -353
- package/error/HydrationMismatch.js +0 -265
- package/error/MasterError.js +0 -240
- package/error/MasterError.js.tmp +0 -0
- package/error/MasterErrorRenderer.js +0 -536
- package/error/MasterErrorRenderer.js.tmp +0 -0
- package/error/SSRErrorHandler.js +0 -273
|
@@ -0,0 +1,726 @@
|
|
|
1
|
+
# MasterController Fortune 500 Upgrade - Verification Checklist
|
|
2
|
+
|
|
3
|
+
**Use this checklist to verify all changes were implemented correctly before deploying to production.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Critical Fixes Verification
|
|
8
|
+
|
|
9
|
+
### ✅ Fix 1: Race Condition in Scoped Services
|
|
10
|
+
|
|
11
|
+
**File:** `MasterRouter.js`
|
|
12
|
+
|
|
13
|
+
**Check Points:**
|
|
14
|
+
- [ ] Line ~243: `loadScopedListClasses` function accepts `context` parameter
|
|
15
|
+
- [ ] Line ~244: Services stored in `context[key]` instead of `this._master.requestList[key]`
|
|
16
|
+
- [ ] Line ~420: `requestContext` created with `Object.create(this._master.requestList)`
|
|
17
|
+
- [ ] Line ~535: `loadScopedListClasses.call(this, requestObject)` passes requestObject
|
|
18
|
+
|
|
19
|
+
**Test:**
|
|
20
|
+
```javascript
|
|
21
|
+
// Create two concurrent requests and verify no data leakage
|
|
22
|
+
// Expected: Each request has isolated scoped services
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
### ✅ Fix 2: Regex DoS Vulnerability
|
|
28
|
+
|
|
29
|
+
**File:** `security/MasterValidator.js`
|
|
30
|
+
|
|
31
|
+
**Check Points:**
|
|
32
|
+
- [ ] Lines 8-15: `MAX_INPUT_LENGTH` and `REGEX_TIMEOUT_MS` constants defined
|
|
33
|
+
- [ ] Line ~220: `detectSQLInjection` has input length check
|
|
34
|
+
- [ ] Line ~230: `_safeRegexTest()` method exists
|
|
35
|
+
- [ ] Line ~240: `detectNoSQLInjection` has input length check
|
|
36
|
+
- [ ] Line ~255: `detectCommandInjection` has input length check
|
|
37
|
+
- [ ] Line ~273: `detectPathTraversal` has input length check
|
|
38
|
+
- [ ] Lines 487-570: `_safeRegexTest()` implementation with timeout logic
|
|
39
|
+
|
|
40
|
+
**Test:**
|
|
41
|
+
```javascript
|
|
42
|
+
const { validator } = require('./security/MasterValidator');
|
|
43
|
+
|
|
44
|
+
// Test 1: Large input is rejected
|
|
45
|
+
const largeInput = 'a'.repeat(20000);
|
|
46
|
+
const result = validator.detectSQLInjection(largeInput);
|
|
47
|
+
console.assert(result.safe === false, 'Should reject oversized input');
|
|
48
|
+
|
|
49
|
+
// Test 2: Normal input still works
|
|
50
|
+
const normalInput = 'SELECT * FROM users';
|
|
51
|
+
const result2 = validator.detectSQLInjection(normalInput);
|
|
52
|
+
console.assert(result2.safe === false, 'Should detect SQL injection');
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### ✅ Fix 3: File Upload Limits
|
|
58
|
+
|
|
59
|
+
**File:** `MasterRequest.js`
|
|
60
|
+
|
|
61
|
+
**Check Points:**
|
|
62
|
+
- [ ] Lines 25-47: Formidable options include `maxFiles`, `maxFileSize`, `maxTotalFileSize`
|
|
63
|
+
- [ ] Line ~70: `totalUploadedSize` variable initialized
|
|
64
|
+
- [ ] Lines 87-107: File size tracking and total size validation
|
|
65
|
+
- [ ] Line ~105: Files cleaned up on total size exceed
|
|
66
|
+
|
|
67
|
+
**Test:**
|
|
68
|
+
```javascript
|
|
69
|
+
// Test 1: Upload 11 files (should be rejected - max is 10)
|
|
70
|
+
// Test 2: Upload 60MB file (should be rejected - max is 50MB)
|
|
71
|
+
// Test 3: Upload 3x40MB files (should be rejected - total max is 100MB)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### ✅ Fix 4: Streaming for Large Files
|
|
77
|
+
|
|
78
|
+
**File:** `MasterControl.js`
|
|
79
|
+
|
|
80
|
+
**Check Points:**
|
|
81
|
+
- [ ] Line 3: `crypto` module imported
|
|
82
|
+
- [ ] Line ~784: `STREAM_THRESHOLD` constant defined (1MB)
|
|
83
|
+
- [ ] Line ~785: `fileSize` variable calculated
|
|
84
|
+
- [ ] Line ~792: Check for streaming threshold
|
|
85
|
+
- [ ] Lines 793-822: Stream implementation with `fs.createReadStream()`
|
|
86
|
+
- [ ] Lines 823-838: Buffer implementation for small files
|
|
87
|
+
|
|
88
|
+
**Test:**
|
|
89
|
+
```bash
|
|
90
|
+
# Create a 2MB test file
|
|
91
|
+
dd if=/dev/zero of=public/test-2mb.bin bs=1M count=2
|
|
92
|
+
|
|
93
|
+
# Start server
|
|
94
|
+
node server.js
|
|
95
|
+
|
|
96
|
+
# Monitor memory usage
|
|
97
|
+
ps aux | grep node
|
|
98
|
+
|
|
99
|
+
# Download file (should use streaming, memory should stay low)
|
|
100
|
+
curl http://localhost:3000/test-2mb.bin > /dev/null
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### ✅ Fix 5: ETag and Cache Headers
|
|
106
|
+
|
|
107
|
+
**File:** `MasterControl.js`
|
|
108
|
+
|
|
109
|
+
**Check Points:**
|
|
110
|
+
- [ ] Line ~789: ETag generation from file stats
|
|
111
|
+
- [ ] Lines 791-800: If-None-Match check for 304 response
|
|
112
|
+
- [ ] Line ~805: ETag header set
|
|
113
|
+
- [ ] Line ~806: Last-Modified header set
|
|
114
|
+
- [ ] Lines 808-816: Cache-Control headers set based on file type
|
|
115
|
+
|
|
116
|
+
**Test:**
|
|
117
|
+
```bash
|
|
118
|
+
# First request - should return 200 with ETag
|
|
119
|
+
curl -I http://localhost:3000/test.css
|
|
120
|
+
|
|
121
|
+
# Second request with ETag - should return 304 Not Modified
|
|
122
|
+
curl -I -H "If-None-Match: W/\"123-456\"" http://localhost:3000/test.css
|
|
123
|
+
|
|
124
|
+
# Check Cache-Control header
|
|
125
|
+
curl -I http://localhost:3000/test.css | grep Cache-Control
|
|
126
|
+
# Should be: Cache-Control: public, max-age=31536000, immutable
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## New Features Verification
|
|
132
|
+
|
|
133
|
+
### ✅ Feature 6: Health Check Endpoint
|
|
134
|
+
|
|
135
|
+
**File:** `monitoring/HealthCheck.js`
|
|
136
|
+
|
|
137
|
+
**Check Points:**
|
|
138
|
+
- [ ] File exists and has 387 lines
|
|
139
|
+
- [ ] `HealthCheck` class exported
|
|
140
|
+
- [ ] `healthCheck` singleton exported
|
|
141
|
+
- [ ] Helper functions exported: `createDatabaseCheck`, `createRedisCheck`, `createAPIHealthCheck`
|
|
142
|
+
|
|
143
|
+
**Test:**
|
|
144
|
+
```javascript
|
|
145
|
+
const { healthCheck } = require('./monitoring/HealthCheck');
|
|
146
|
+
const master = require('./MasterControl');
|
|
147
|
+
|
|
148
|
+
master.pipeline.use(healthCheck.middleware());
|
|
149
|
+
master.listen(3000);
|
|
150
|
+
|
|
151
|
+
// Test endpoint
|
|
152
|
+
// curl http://localhost:3000/_health
|
|
153
|
+
// Should return JSON with status, uptime, memory, etc.
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### ✅ Feature 7: Prometheus Metrics Exporter
|
|
159
|
+
|
|
160
|
+
**File:** `monitoring/PrometheusExporter.js`
|
|
161
|
+
|
|
162
|
+
**Check Points:**
|
|
163
|
+
- [ ] File exists and has 435 lines
|
|
164
|
+
- [ ] `PrometheusExporter` class exported
|
|
165
|
+
- [ ] `prometheusExporter` singleton exported
|
|
166
|
+
- [ ] Simple mode implemented (works without prom-client)
|
|
167
|
+
|
|
168
|
+
**Test:**
|
|
169
|
+
```javascript
|
|
170
|
+
const { prometheusExporter } = require('./monitoring/PrometheusExporter');
|
|
171
|
+
const master = require('./MasterControl');
|
|
172
|
+
|
|
173
|
+
master.pipeline.use(prometheusExporter.middleware());
|
|
174
|
+
master.listen(3000);
|
|
175
|
+
|
|
176
|
+
// Test endpoint
|
|
177
|
+
// curl http://localhost:3000/_metrics
|
|
178
|
+
// Should return Prometheus text format
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### ✅ Feature 8: Redis Session Store
|
|
184
|
+
|
|
185
|
+
**File:** `security/adapters/RedisSessionStore.js`
|
|
186
|
+
|
|
187
|
+
**Check Points:**
|
|
188
|
+
- [ ] File exists and has 449 lines
|
|
189
|
+
- [ ] `RedisSessionStore` class exported
|
|
190
|
+
- [ ] Implements required methods: get, set, update, destroy, touch
|
|
191
|
+
- [ ] Session locking implemented: acquireLock, releaseLock
|
|
192
|
+
|
|
193
|
+
**Test:**
|
|
194
|
+
```javascript
|
|
195
|
+
const Redis = require('ioredis');
|
|
196
|
+
const { RedisSessionStore } = require('./security/adapters/RedisSessionStore');
|
|
197
|
+
|
|
198
|
+
const redis = new Redis();
|
|
199
|
+
const store = new RedisSessionStore(redis);
|
|
200
|
+
|
|
201
|
+
// Test basic operations
|
|
202
|
+
async function test() {
|
|
203
|
+
await store.set('test-session-id', { userId: 123 });
|
|
204
|
+
const data = await store.get('test-session-id');
|
|
205
|
+
console.assert(data.userId === 123, 'Session data should be retrieved');
|
|
206
|
+
await store.destroy('test-session-id');
|
|
207
|
+
const deleted = await store.get('test-session-id');
|
|
208
|
+
console.assert(deleted === null, 'Session should be deleted');
|
|
209
|
+
}
|
|
210
|
+
test();
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### ✅ Feature 9: Redis Rate Limiter
|
|
216
|
+
|
|
217
|
+
**File:** `security/adapters/RedisRateLimiter.js`
|
|
218
|
+
|
|
219
|
+
**Check Points:**
|
|
220
|
+
- [ ] File exists and has 392 lines
|
|
221
|
+
- [ ] `RedisRateLimiter` class exported
|
|
222
|
+
- [ ] Implements consume, get, reset, block, unblock methods
|
|
223
|
+
- [ ] Middleware factory method exists
|
|
224
|
+
|
|
225
|
+
**Test:**
|
|
226
|
+
```javascript
|
|
227
|
+
const Redis = require('ioredis');
|
|
228
|
+
const { RedisRateLimiter } = require('./security/adapters/RedisRateLimiter');
|
|
229
|
+
|
|
230
|
+
const redis = new Redis();
|
|
231
|
+
const limiter = new RedisRateLimiter(redis, { points: 5, duration: 10 });
|
|
232
|
+
|
|
233
|
+
// Test rate limiting
|
|
234
|
+
async function test() {
|
|
235
|
+
for (let i = 0; i < 6; i++) {
|
|
236
|
+
const result = await limiter.consume('test-ip');
|
|
237
|
+
console.log(`Request ${i + 1}: allowed=${result.allowed}, remaining=${result.remaining}`);
|
|
238
|
+
if (i === 5) {
|
|
239
|
+
console.assert(result.allowed === false, 'Should be blocked after 5 requests');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
test();
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### ✅ Feature 10: Redis CSRF Store
|
|
249
|
+
|
|
250
|
+
**File:** `security/adapters/RedisCSRFStore.js`
|
|
251
|
+
|
|
252
|
+
**Check Points:**
|
|
253
|
+
- [ ] File exists and has 363 lines
|
|
254
|
+
- [ ] `RedisCSRFStore` class exported
|
|
255
|
+
- [ ] Implements create, get, validate, invalidate, rotate methods
|
|
256
|
+
- [ ] Middleware factory method exists
|
|
257
|
+
|
|
258
|
+
**Test:**
|
|
259
|
+
```javascript
|
|
260
|
+
const Redis = require('ioredis');
|
|
261
|
+
const { RedisCSRFStore } = require('./security/adapters/RedisCSRFStore');
|
|
262
|
+
|
|
263
|
+
const redis = new Redis();
|
|
264
|
+
const store = new RedisCSRFStore(redis);
|
|
265
|
+
|
|
266
|
+
// Test CSRF token workflow
|
|
267
|
+
async function test() {
|
|
268
|
+
const sessionId = 'test-session-123';
|
|
269
|
+
const token = await store.create(sessionId);
|
|
270
|
+
console.assert(token !== null, 'Token should be created');
|
|
271
|
+
|
|
272
|
+
const valid = await store.validate(sessionId, token);
|
|
273
|
+
console.assert(valid === true, 'Token should be valid');
|
|
274
|
+
|
|
275
|
+
const invalid = await store.validate(sessionId, 'wrong-token');
|
|
276
|
+
console.assert(invalid === false, 'Wrong token should be invalid');
|
|
277
|
+
}
|
|
278
|
+
test();
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### ✅ Feature 11: GitHub Actions CI/CD
|
|
284
|
+
|
|
285
|
+
**File:** `.github/workflows/ci.yml`
|
|
286
|
+
|
|
287
|
+
**Check Points:**
|
|
288
|
+
- [ ] File exists and has 254 lines
|
|
289
|
+
- [ ] Lint job defined
|
|
290
|
+
- [ ] Security job defined (npm audit, Snyk, OWASP)
|
|
291
|
+
- [ ] Test job defined (Node 18/20/22, Ubuntu/macOS/Windows)
|
|
292
|
+
- [ ] Integration test job defined
|
|
293
|
+
- [ ] Docker build job defined
|
|
294
|
+
- [ ] Publish job defined
|
|
295
|
+
|
|
296
|
+
**Test:**
|
|
297
|
+
```bash
|
|
298
|
+
# Push to GitHub and verify workflow runs
|
|
299
|
+
git add .
|
|
300
|
+
git commit -m "Fortune 500 upgrade"
|
|
301
|
+
git push origin master
|
|
302
|
+
|
|
303
|
+
# Check GitHub Actions tab for workflow execution
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
### ✅ Feature 12: Deployment Documentation
|
|
309
|
+
|
|
310
|
+
**File:** `DEPLOYMENT.md`
|
|
311
|
+
|
|
312
|
+
**Check Points:**
|
|
313
|
+
- [ ] File exists and has 750+ lines
|
|
314
|
+
- [ ] Docker section with Dockerfile and docker-compose.yml
|
|
315
|
+
- [ ] Kubernetes section with manifests
|
|
316
|
+
- [ ] Nginx configuration example
|
|
317
|
+
- [ ] HAProxy configuration example
|
|
318
|
+
- [ ] Redis cluster setup instructions
|
|
319
|
+
- [ ] Environment variables documented
|
|
320
|
+
- [ ] Health checks section
|
|
321
|
+
- [ ] Monitoring setup (Prometheus/Grafana)
|
|
322
|
+
- [ ] Security best practices
|
|
323
|
+
- [ ] Performance tuning section
|
|
324
|
+
- [ ] Troubleshooting guide
|
|
325
|
+
|
|
326
|
+
**Review:**
|
|
327
|
+
```bash
|
|
328
|
+
# Read through documentation
|
|
329
|
+
less DEPLOYMENT.md
|
|
330
|
+
|
|
331
|
+
# Verify all code examples are correct
|
|
332
|
+
# Try deploying using the documentation
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
### ✅ Feature 13: Updated package.json
|
|
338
|
+
|
|
339
|
+
**File:** `package.json`
|
|
340
|
+
|
|
341
|
+
**Check Points:**
|
|
342
|
+
- [ ] `"engines": { "node": ">=18.0.0" }` present
|
|
343
|
+
- [ ] Fortune 500 keywords added
|
|
344
|
+
- [ ] `optionalDependencies` includes ioredis, prom-client
|
|
345
|
+
- [ ] `peerDependencies` defined with optional flags
|
|
346
|
+
- [ ] `devDependencies` includes ESLint, Prettier
|
|
347
|
+
- [ ] npm scripts defined: lint, format, security-audit
|
|
348
|
+
|
|
349
|
+
**Test:**
|
|
350
|
+
```bash
|
|
351
|
+
# Verify package.json is valid
|
|
352
|
+
npm install --dry-run
|
|
353
|
+
|
|
354
|
+
# Test new scripts
|
|
355
|
+
npm run lint:check
|
|
356
|
+
npm run format:check
|
|
357
|
+
npm run security-audit
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Configuration Files Verification
|
|
363
|
+
|
|
364
|
+
### ✅ ESLint Configuration
|
|
365
|
+
|
|
366
|
+
**File:** `.eslintrc.json`
|
|
367
|
+
|
|
368
|
+
**Check Points:**
|
|
369
|
+
- [ ] File exists
|
|
370
|
+
- [ ] Node environment set
|
|
371
|
+
- [ ] ES2021 features enabled
|
|
372
|
+
- [ ] Security rules present (no-eval, no-implied-eval)
|
|
373
|
+
|
|
374
|
+
**Test:**
|
|
375
|
+
```bash
|
|
376
|
+
npm run lint:check
|
|
377
|
+
# Should report any linting issues
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
### ✅ Prettier Configuration
|
|
383
|
+
|
|
384
|
+
**File:** `.prettierrc`
|
|
385
|
+
|
|
386
|
+
**Check Points:**
|
|
387
|
+
- [ ] File exists
|
|
388
|
+
- [ ] 4 spaces indentation
|
|
389
|
+
- [ ] Single quotes
|
|
390
|
+
- [ ] 100 character line width
|
|
391
|
+
|
|
392
|
+
**Test:**
|
|
393
|
+
```bash
|
|
394
|
+
npm run format:check
|
|
395
|
+
# Should report any formatting issues
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Documentation Verification
|
|
401
|
+
|
|
402
|
+
### ✅ Upgrade Documentation
|
|
403
|
+
|
|
404
|
+
**File:** `FORTUNE_500_UPGRADE.md`
|
|
405
|
+
|
|
406
|
+
**Check Points:**
|
|
407
|
+
- [ ] Executive summary present
|
|
408
|
+
- [ ] All 5 critical fixes documented
|
|
409
|
+
- [ ] All 9 new features documented
|
|
410
|
+
- [ ] Performance benchmarks included
|
|
411
|
+
- [ ] Migration guide present
|
|
412
|
+
- [ ] Zero breaking changes confirmed
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
### ✅ Changes Summary
|
|
417
|
+
|
|
418
|
+
**File:** `CHANGES.md`
|
|
419
|
+
|
|
420
|
+
**Check Points:**
|
|
421
|
+
- [ ] All modified files listed (5)
|
|
422
|
+
- [ ] All new files listed (14)
|
|
423
|
+
- [ ] Line numbers documented
|
|
424
|
+
- [ ] Change descriptions accurate
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Syntax Validation
|
|
429
|
+
|
|
430
|
+
Run these commands to verify all files have valid syntax:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
# Core files
|
|
434
|
+
node -c MasterRouter.js
|
|
435
|
+
node -c MasterRequest.js
|
|
436
|
+
node -c MasterControl.js
|
|
437
|
+
node -c security/MasterValidator.js
|
|
438
|
+
|
|
439
|
+
# New monitoring files
|
|
440
|
+
node -c monitoring/HealthCheck.js
|
|
441
|
+
node -c monitoring/PrometheusExporter.js
|
|
442
|
+
|
|
443
|
+
# New security adapter files
|
|
444
|
+
node -c security/adapters/RedisSessionStore.js
|
|
445
|
+
node -c security/adapters/RedisRateLimiter.js
|
|
446
|
+
node -c security/adapters/RedisCSRFStore.js
|
|
447
|
+
|
|
448
|
+
# All checks should complete with no output (success)
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Integration Testing
|
|
454
|
+
|
|
455
|
+
### Test 1: Basic Server Startup
|
|
456
|
+
|
|
457
|
+
```javascript
|
|
458
|
+
// test-startup.js
|
|
459
|
+
const MasterControl = require('./MasterControl');
|
|
460
|
+
const master = new MasterControl();
|
|
461
|
+
|
|
462
|
+
master.init({ port: 3000 });
|
|
463
|
+
|
|
464
|
+
master.routes((router) => {
|
|
465
|
+
router.route('/test', 'test#index', 'GET');
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
master.listen(3000, () => {
|
|
469
|
+
console.log('✅ Server started successfully');
|
|
470
|
+
process.exit(0);
|
|
471
|
+
});
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
### Test 2: Health Check
|
|
477
|
+
|
|
478
|
+
```bash
|
|
479
|
+
# Start server
|
|
480
|
+
node server.js &
|
|
481
|
+
|
|
482
|
+
# Wait for startup
|
|
483
|
+
sleep 2
|
|
484
|
+
|
|
485
|
+
# Test health endpoint
|
|
486
|
+
curl http://localhost:3000/_health | jq .
|
|
487
|
+
|
|
488
|
+
# Should return JSON with status: "healthy"
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
### Test 3: Prometheus Metrics
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
# Test metrics endpoint
|
|
497
|
+
curl http://localhost:3000/_metrics
|
|
498
|
+
|
|
499
|
+
# Should return Prometheus text format
|
|
500
|
+
# mastercontroller_http_requests_total
|
|
501
|
+
# process_memory_heap_used_bytes
|
|
502
|
+
# etc.
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
### Test 4: Redis Session Store (requires Redis)
|
|
508
|
+
|
|
509
|
+
```javascript
|
|
510
|
+
// test-redis-session.js
|
|
511
|
+
const Redis = require('ioredis');
|
|
512
|
+
const { RedisSessionStore } = require('./security/adapters/RedisSessionStore');
|
|
513
|
+
|
|
514
|
+
const redis = new Redis();
|
|
515
|
+
const store = new RedisSessionStore(redis);
|
|
516
|
+
|
|
517
|
+
async function test() {
|
|
518
|
+
console.log('Testing Redis Session Store...');
|
|
519
|
+
|
|
520
|
+
// Test set
|
|
521
|
+
await store.set('test-123', { userId: 456, username: 'test' });
|
|
522
|
+
console.log('✅ Session saved');
|
|
523
|
+
|
|
524
|
+
// Test get
|
|
525
|
+
const data = await store.get('test-123');
|
|
526
|
+
console.assert(data.userId === 456, 'User ID should match');
|
|
527
|
+
console.log('✅ Session retrieved');
|
|
528
|
+
|
|
529
|
+
// Test destroy
|
|
530
|
+
await store.destroy('test-123');
|
|
531
|
+
const deleted = await store.get('test-123');
|
|
532
|
+
console.assert(deleted === null, 'Session should be deleted');
|
|
533
|
+
console.log('✅ Session destroyed');
|
|
534
|
+
|
|
535
|
+
console.log('All tests passed!');
|
|
536
|
+
redis.quit();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
test().catch(console.error);
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
### Test 5: Rate Limiting (requires Redis)
|
|
545
|
+
|
|
546
|
+
```javascript
|
|
547
|
+
// test-rate-limiter.js
|
|
548
|
+
const Redis = require('ioredis');
|
|
549
|
+
const { RedisRateLimiter } = require('./security/adapters/RedisRateLimiter');
|
|
550
|
+
|
|
551
|
+
const redis = new Redis();
|
|
552
|
+
const limiter = new RedisRateLimiter(redis, {
|
|
553
|
+
points: 5,
|
|
554
|
+
duration: 10
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
async function test() {
|
|
558
|
+
console.log('Testing Redis Rate Limiter...');
|
|
559
|
+
|
|
560
|
+
const ip = '192.168.1.1';
|
|
561
|
+
|
|
562
|
+
// Make 5 requests (should all succeed)
|
|
563
|
+
for (let i = 1; i <= 5; i++) {
|
|
564
|
+
const result = await limiter.consume(ip);
|
|
565
|
+
console.log(`Request ${i}: allowed=${result.allowed}, remaining=${result.remaining}`);
|
|
566
|
+
console.assert(result.allowed === true, `Request ${i} should be allowed`);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// 6th request should be blocked
|
|
570
|
+
const blocked = await limiter.consume(ip);
|
|
571
|
+
console.assert(blocked.allowed === false, 'Request 6 should be blocked');
|
|
572
|
+
console.log('✅ Rate limiting working correctly');
|
|
573
|
+
|
|
574
|
+
await limiter.reset(ip);
|
|
575
|
+
redis.quit();
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
test().catch(console.error);
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
## Security Testing
|
|
584
|
+
|
|
585
|
+
### Test 1: ReDoS Protection
|
|
586
|
+
|
|
587
|
+
```javascript
|
|
588
|
+
// test-redos.js
|
|
589
|
+
const { validator } = require('./security/MasterValidator');
|
|
590
|
+
|
|
591
|
+
console.log('Testing ReDoS protection...');
|
|
592
|
+
|
|
593
|
+
// Test 1: Oversized input
|
|
594
|
+
const largeInput = 'a'.repeat(15000);
|
|
595
|
+
const result1 = validator.detectSQLInjection(largeInput);
|
|
596
|
+
console.assert(result1.safe === false, 'Should reject oversized input');
|
|
597
|
+
console.assert(result1.threat === 'OVERSIZED_INPUT', 'Should indicate oversized input');
|
|
598
|
+
console.log('✅ Oversized input rejected');
|
|
599
|
+
|
|
600
|
+
// Test 2: Normal malicious input
|
|
601
|
+
const sqlInjection = "admin' OR '1'='1";
|
|
602
|
+
const result2 = validator.detectSQLInjection(sqlInjection);
|
|
603
|
+
console.assert(result2.safe === false, 'Should detect SQL injection');
|
|
604
|
+
console.log('✅ SQL injection detected');
|
|
605
|
+
|
|
606
|
+
// Test 3: Safe input
|
|
607
|
+
const safeInput = 'normal text';
|
|
608
|
+
const result3 = validator.detectSQLInjection(safeInput);
|
|
609
|
+
console.assert(result3.safe === true, 'Should allow safe input');
|
|
610
|
+
console.log('✅ Safe input allowed');
|
|
611
|
+
|
|
612
|
+
console.log('All ReDoS protection tests passed!');
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
### Test 2: File Upload Limits
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
# Test oversized file upload
|
|
621
|
+
dd if=/dev/zero of=/tmp/test-60mb.bin bs=1M count=60
|
|
622
|
+
|
|
623
|
+
curl -X POST http://localhost:3000/upload \
|
|
624
|
+
-F "file=@/tmp/test-60mb.bin"
|
|
625
|
+
|
|
626
|
+
# Should return error: "Total upload size exceeds limit"
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## Performance Testing
|
|
632
|
+
|
|
633
|
+
### Test 1: Memory Usage with Large Files
|
|
634
|
+
|
|
635
|
+
```bash
|
|
636
|
+
# Create test file
|
|
637
|
+
dd if=/dev/zero of=public/test-10mb.bin bs=1M count=10
|
|
638
|
+
|
|
639
|
+
# Start server and monitor memory
|
|
640
|
+
node server.js &
|
|
641
|
+
SERVER_PID=$!
|
|
642
|
+
|
|
643
|
+
# Initial memory
|
|
644
|
+
ps -o rss= -p $SERVER_PID
|
|
645
|
+
|
|
646
|
+
# Download file 10 times
|
|
647
|
+
for i in {1..10}; do
|
|
648
|
+
curl -s http://localhost:3000/test-10mb.bin > /dev/null &
|
|
649
|
+
done
|
|
650
|
+
wait
|
|
651
|
+
|
|
652
|
+
# Final memory (should not increase significantly due to streaming)
|
|
653
|
+
ps -o rss= -p $SERVER_PID
|
|
654
|
+
|
|
655
|
+
kill $SERVER_PID
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
---
|
|
659
|
+
|
|
660
|
+
### Test 2: ETag Caching Efficiency
|
|
661
|
+
|
|
662
|
+
```bash
|
|
663
|
+
# First request (200 OK)
|
|
664
|
+
curl -w "\nStatus: %{http_code}\n" http://localhost:3000/test.css
|
|
665
|
+
|
|
666
|
+
# Get ETag from response
|
|
667
|
+
ETAG=$(curl -sI http://localhost:3000/test.css | grep -i etag | cut -d' ' -f2)
|
|
668
|
+
|
|
669
|
+
# Second request with If-None-Match (304 Not Modified)
|
|
670
|
+
curl -w "\nStatus: %{http_code}\n" -H "If-None-Match: $ETAG" http://localhost:3000/test.css
|
|
671
|
+
|
|
672
|
+
# Should return 304 Not Modified
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
## Load Testing
|
|
678
|
+
|
|
679
|
+
```bash
|
|
680
|
+
# Install Apache Bench
|
|
681
|
+
# Ubuntu: sudo apt install apache2-utils
|
|
682
|
+
# macOS: brew install apr-util
|
|
683
|
+
|
|
684
|
+
# Basic load test
|
|
685
|
+
ab -n 10000 -c 100 http://localhost:3000/
|
|
686
|
+
|
|
687
|
+
# Results should show:
|
|
688
|
+
# - No failed requests
|
|
689
|
+
# - Consistent memory usage
|
|
690
|
+
# - Good requests per second (>500)
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
## Cleanup & Finalization
|
|
696
|
+
|
|
697
|
+
- [ ] All syntax checks passed
|
|
698
|
+
- [ ] All integration tests passed
|
|
699
|
+
- [ ] All security tests passed
|
|
700
|
+
- [ ] All performance tests passed
|
|
701
|
+
- [ ] Documentation reviewed and accurate
|
|
702
|
+
- [ ] No breaking changes introduced
|
|
703
|
+
- [ ] Git commit messages are clear
|
|
704
|
+
- [ ] Ready for production deployment
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## Final Sign-Off
|
|
709
|
+
|
|
710
|
+
**Tested by:** _________________
|
|
711
|
+
**Date:** _________________
|
|
712
|
+
**Environment:** _________________
|
|
713
|
+
**Result:** ☐ Pass ☐ Fail
|
|
714
|
+
|
|
715
|
+
**Notes:**
|
|
716
|
+
_________________________________________________________________
|
|
717
|
+
_________________________________________________________________
|
|
718
|
+
_________________________________________________________________
|
|
719
|
+
|
|
720
|
+
---
|
|
721
|
+
|
|
722
|
+
**Status:** Ready for production deployment ✅
|
|
723
|
+
|
|
724
|
+
---
|
|
725
|
+
|
|
726
|
+
*Last Updated: January 29, 2026*
|