claude-flow-novice 2.14.35 → 2.14.37

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 (56) hide show
  1. package/.claude/commands/CFN_LOOP_TASK_MODE.md +1 -1
  2. package/.claude/commands/cfn-loop-cli.md +491 -456
  3. package/.claude/commands/switch-api.md +1 -1
  4. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +2 -1
  5. package/.claude/skills/cfn-loop-validation/config.json +2 -2
  6. package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +220 -220
  7. package/claude-assets/agents/README-AGENT_LIFECYCLE.md +37 -10
  8. package/claude-assets/agents/README-VALIDATION.md +0 -8
  9. package/claude-assets/agents/cfn-dev-team/README.md +0 -8
  10. package/claude-assets/agents/cfn-dev-team/coordinators/README.md +1 -9
  11. package/claude-assets/agents/cfn-dev-team/developers/README.md +1 -9
  12. package/claude-assets/agents/cfn-dev-team/documentation/README-VALIDATION.md +0 -8
  13. package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md +0 -10
  14. package/claude-assets/agents/cfn-dev-team/reviewers/README.md +1 -9
  15. package/claude-assets/agents/cfn-dev-team/reviewers/quality/quality-metrics.md +0 -10
  16. package/claude-assets/agents/cfn-dev-team/test-agent.md +0 -10
  17. package/claude-assets/agents/cfn-dev-team/testers/README.md +1 -9
  18. package/claude-assets/agents/csuite/cto-agent.md +0 -10
  19. package/claude-assets/agents/custom/cfn-system-expert.md +1 -128
  20. package/claude-assets/agents/custom/claude-code-expert.md +151 -2
  21. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +39 -3
  22. package/claude-assets/agents/docker-team/csuite/c-suite-template.md +1 -5
  23. package/claude-assets/agents/docker-team/infrastructure/team-coordinator-template.md +1 -5
  24. package/claude-assets/agents/marketing_hybrid/cost_tracker.md +0 -10
  25. package/claude-assets/agents/marketing_hybrid/docker_deployer.md +0 -10
  26. package/claude-assets/agents/marketing_hybrid/zai_worker_spawner.md +0 -10
  27. package/claude-assets/commands/CFN_LOOP_TASK_MODE.md +1 -1
  28. package/claude-assets/commands/cfn-loop-cli.md +491 -456
  29. package/claude-assets/commands/switch-api.md +1 -1
  30. package/claude-assets/skills/cfn-error-logging/SKILL.md +339 -0
  31. package/claude-assets/skills/cfn-error-logging/cleanup-error-logs.sh +334 -0
  32. package/claude-assets/skills/cfn-error-logging/integrate-cli.sh +232 -0
  33. package/claude-assets/skills/cfn-error-logging/integrate-docker.sh +294 -0
  34. package/claude-assets/skills/cfn-error-logging/invoke-error-logging.sh +839 -0
  35. package/claude-assets/skills/cfn-error-logging/test-error-logging.sh +475 -0
  36. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +2 -1
  37. package/claude-assets/skills/cfn-loop-validation/config.json +2 -2
  38. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +326 -322
  39. package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +220 -220
  40. package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +2 -2
  41. package/claude-assets/skills/cfn-task-mode-sanitize/task-mode-env-sanitizer.sh +224 -181
  42. package/claude-assets/skills/cfn-validation-runner-instrumentation/wrapped-executor.sh +235 -271
  43. package/dist/agents/agent-loader.js +467 -133
  44. package/dist/agents/agent-loader.js.map +1 -1
  45. package/dist/cli/config-manager.js +109 -91
  46. package/dist/cli/config-manager.js.map +1 -1
  47. package/dist/hello.js +27 -3
  48. package/dist/hello.js.map +1 -1
  49. package/dist/server.js +194 -0
  50. package/dist/server.js.map +1 -0
  51. package/dist/server.test.js +207 -0
  52. package/dist/server.test.js.map +1 -0
  53. package/package.json +2 -1
  54. package/scripts/docker-build-mcp.sh +155 -0
  55. package/scripts/docker-test-mcp.sh +260 -0
  56. package/scripts/mcp-health-check.sh +123 -0
package/dist/server.js ADDED
@@ -0,0 +1,194 @@
1
+ import express from 'express';
2
+ import { hello, healthCheck, createApiResponse } from './hello.js';
3
+ const app = express();
4
+ const PORT = process.env.PORT || 3000;
5
+ // Middleware for JSON parsing and security
6
+ app.use(express.json());
7
+ app.use(express.urlencoded({
8
+ extended: true
9
+ }));
10
+ // Security headers middleware
11
+ app.use((req, res, next)=>{
12
+ res.setHeader('X-Content-Type-Options', 'nosniff');
13
+ res.setHeader('X-Frame-Options', 'DENY');
14
+ res.setHeader('X-XSS-Protection', '1; mode=block');
15
+ next();
16
+ });
17
+ // Request logging middleware
18
+ app.use((req, res, next)=>{
19
+ console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`);
20
+ next();
21
+ });
22
+ // API Routes
23
+ /**
24
+ * GET /api/hello
25
+ * Basic hello world endpoint
26
+ */ app.get('/api/hello', (req, res)=>{
27
+ try {
28
+ const message = hello();
29
+ const response = createApiResponse({
30
+ greeting: message
31
+ });
32
+ res.json(response);
33
+ } catch (error) {
34
+ console.error('Error in /api/hello:', error);
35
+ res.status(500).json({
36
+ success: false,
37
+ message: 'Internal server error',
38
+ timestamp: new Date().toISOString()
39
+ });
40
+ }
41
+ });
42
+ /**
43
+ * GET /api/hello/:name
44
+ * Personalized hello endpoint
45
+ */ app.get('/api/hello/:name', (req, res)=>{
46
+ try {
47
+ const { name } = req.params;
48
+ // Input validation
49
+ if (!name || typeof name !== 'string' || name.length > 100) {
50
+ return res.status(400).json({
51
+ success: false,
52
+ message: 'Invalid name parameter',
53
+ timestamp: new Date().toISOString()
54
+ });
55
+ }
56
+ // Sanitize input (remove potential XSS)
57
+ const sanitizedName = name.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
58
+ const message = hello(sanitizedName);
59
+ const response = createApiResponse({
60
+ greeting: message,
61
+ name: sanitizedName
62
+ });
63
+ res.json(response);
64
+ } catch (error) {
65
+ console.error('Error in /api/hello/:name:', error);
66
+ res.status(500).json({
67
+ success: false,
68
+ message: 'Internal server error',
69
+ timestamp: new Date().toISOString()
70
+ });
71
+ }
72
+ });
73
+ /**
74
+ * GET /api/health
75
+ * Health check endpoint
76
+ */ app.get('/api/health', (req, res)=>{
77
+ try {
78
+ const health = healthCheck();
79
+ const response = createApiResponse(health, 'Service is healthy');
80
+ res.json(response);
81
+ } catch (error) {
82
+ console.error('Error in /api/health:', error);
83
+ res.status(500).json({
84
+ success: false,
85
+ message: 'Health check failed',
86
+ timestamp: new Date().toISOString()
87
+ });
88
+ }
89
+ });
90
+ /**
91
+ * POST /api/hello
92
+ * Hello endpoint with POST body
93
+ */ app.post('/api/hello', (req, res)=>{
94
+ try {
95
+ const { name, language } = req.body;
96
+ // Input validation
97
+ if (name && (typeof name !== 'string' || name.length > 100)) {
98
+ return res.status(400).json({
99
+ success: false,
100
+ message: 'Invalid name in request body',
101
+ timestamp: new Date().toISOString()
102
+ });
103
+ }
104
+ // Support for different languages
105
+ let greeting = 'Hello';
106
+ if (language && typeof language === 'string') {
107
+ const greetings = {
108
+ 'es': 'Hola',
109
+ 'fr': 'Bonjour',
110
+ 'de': 'Hallo',
111
+ 'it': 'Ciao',
112
+ 'pt': 'Olá',
113
+ 'ja': 'こんにちは',
114
+ 'zh': '你好',
115
+ 'hi': 'नमस्ते',
116
+ 'ar': 'مرحبا'
117
+ };
118
+ greeting = greetings[language.toLowerCase()] || greeting;
119
+ }
120
+ const sanitizedName = name ? name.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '') : 'World';
121
+ const message = `${greeting} ${sanitizedName}!`;
122
+ const response = createApiResponse({
123
+ greeting: message,
124
+ name: sanitizedName,
125
+ language: language || 'en'
126
+ });
127
+ res.json(response);
128
+ } catch (error) {
129
+ console.error('Error in POST /api/hello:', error);
130
+ res.status(500).json({
131
+ success: false,
132
+ message: 'Internal server error',
133
+ timestamp: new Date().toISOString()
134
+ });
135
+ }
136
+ });
137
+ /**
138
+ * GET / - Root endpoint
139
+ */ app.get('/', (req, res)=>{
140
+ res.json({
141
+ success: true,
142
+ message: 'Hello World Backend Service',
143
+ version: '1.0.0',
144
+ endpoints: [
145
+ 'GET /api/hello - Basic hello world',
146
+ 'GET /api/hello/:name - Personalized greeting',
147
+ 'POST /api/hello - Greeting with language support',
148
+ 'GET /api/health - Health check'
149
+ ],
150
+ timestamp: new Date().toISOString()
151
+ });
152
+ });
153
+ /**
154
+ * 404 handler
155
+ */ app.use('*', (req, res)=>{
156
+ res.status(404).json({
157
+ success: false,
158
+ message: 'Endpoint not found',
159
+ path: req.originalUrl,
160
+ timestamp: new Date().toISOString()
161
+ });
162
+ });
163
+ /**
164
+ * Global error handler
165
+ */ app.use((error, req, res, next)=>{
166
+ console.error('Unhandled error:', error);
167
+ res.status(500).json({
168
+ success: false,
169
+ message: 'Internal server error',
170
+ timestamp: new Date().toISOString()
171
+ });
172
+ });
173
+ // Start server
174
+ const server = app.listen(PORT, ()=>{
175
+ console.log(`🚀 Hello World Backend Service running on port ${PORT}`);
176
+ console.log(`📖 API Documentation: http://localhost:${PORT}/`);
177
+ console.log(`❤️ Health Check: http://localhost:${PORT}/api/health`);
178
+ });
179
+ // Graceful shutdown
180
+ process.on('SIGTERM', ()=>{
181
+ console.log('SIGTERM received, shutting down gracefully');
182
+ server.close(()=>{
183
+ console.log('Process terminated');
184
+ });
185
+ });
186
+ process.on('SIGINT', ()=>{
187
+ console.log('SIGINT received, shutting down gracefully');
188
+ server.close(()=>{
189
+ console.log('Process terminated');
190
+ });
191
+ });
192
+ export default app;
193
+
194
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.js"],"sourcesContent":["import express from 'express';\nimport { hello, healthCheck, createApiResponse } from './hello.js';\n\nconst app = express();\nconst PORT = process.env.PORT || 3000;\n\n// Middleware for JSON parsing and security\napp.use(express.json());\napp.use(express.urlencoded({ extended: true }));\n\n// Security headers middleware\napp.use((req, res, next) => {\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.setHeader('X-Frame-Options', 'DENY');\n res.setHeader('X-XSS-Protection', '1; mode=block');\n next();\n});\n\n// Request logging middleware\napp.use((req, res, next) => {\n console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`);\n next();\n});\n\n// API Routes\n\n/**\n * GET /api/hello\n * Basic hello world endpoint\n */\napp.get('/api/hello', (req, res) => {\n try {\n const message = hello();\n const response = createApiResponse({ greeting: message });\n res.json(response);\n } catch (error) {\n console.error('Error in /api/hello:', error);\n res.status(500).json({\n success: false,\n message: 'Internal server error',\n timestamp: new Date().toISOString()\n });\n }\n});\n\n/**\n * GET /api/hello/:name\n * Personalized hello endpoint\n */\napp.get('/api/hello/:name', (req, res) => {\n try {\n const { name } = req.params;\n \n // Input validation\n if (!name || typeof name !== 'string' || name.length > 100) {\n return res.status(400).json({\n success: false,\n message: 'Invalid name parameter',\n timestamp: new Date().toISOString()\n });\n }\n\n // Sanitize input (remove potential XSS)\n const sanitizedName = name.replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '');\n const message = hello(sanitizedName);\n const response = createApiResponse({ \n greeting: message,\n name: sanitizedName \n });\n res.json(response);\n } catch (error) {\n console.error('Error in /api/hello/:name:', error);\n res.status(500).json({\n success: false,\n message: 'Internal server error',\n timestamp: new Date().toISOString()\n });\n }\n});\n\n/**\n * GET /api/health\n * Health check endpoint\n */\napp.get('/api/health', (req, res) => {\n try {\n const health = healthCheck();\n const response = createApiResponse(health, 'Service is healthy');\n res.json(response);\n } catch (error) {\n console.error('Error in /api/health:', error);\n res.status(500).json({\n success: false,\n message: 'Health check failed',\n timestamp: new Date().toISOString()\n });\n }\n});\n\n/**\n * POST /api/hello\n * Hello endpoint with POST body\n */\napp.post('/api/hello', (req, res) => {\n try {\n const { name, language } = req.body;\n \n // Input validation\n if (name && (typeof name !== 'string' || name.length > 100)) {\n return res.status(400).json({\n success: false,\n message: 'Invalid name in request body',\n timestamp: new Date().toISOString()\n });\n }\n\n // Support for different languages\n let greeting = 'Hello';\n if (language && typeof language === 'string') {\n const greetings = {\n 'es': 'Hola',\n 'fr': 'Bonjour',\n 'de': 'Hallo',\n 'it': 'Ciao',\n 'pt': 'Olá',\n 'ja': 'こんにちは',\n 'zh': '你好',\n 'hi': 'नमस्ते',\n 'ar': 'مرحبا'\n };\n greeting = greetings[language.toLowerCase()] || greeting;\n }\n\n const sanitizedName = name ? name.replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '') : 'World';\n const message = `${greeting} ${sanitizedName}!`;\n \n const response = createApiResponse({ \n greeting: message,\n name: sanitizedName,\n language: language || 'en'\n });\n res.json(response);\n } catch (error) {\n console.error('Error in POST /api/hello:', error);\n res.status(500).json({\n success: false,\n message: 'Internal server error',\n timestamp: new Date().toISOString()\n });\n }\n});\n\n/**\n * GET / - Root endpoint\n */\napp.get('/', (req, res) => {\n res.json({\n success: true,\n message: 'Hello World Backend Service',\n version: '1.0.0',\n endpoints: [\n 'GET /api/hello - Basic hello world',\n 'GET /api/hello/:name - Personalized greeting',\n 'POST /api/hello - Greeting with language support',\n 'GET /api/health - Health check'\n ],\n timestamp: new Date().toISOString()\n });\n});\n\n/**\n * 404 handler\n */\napp.use('*', (req, res) => {\n res.status(404).json({\n success: false,\n message: 'Endpoint not found',\n path: req.originalUrl,\n timestamp: new Date().toISOString()\n });\n});\n\n/**\n * Global error handler\n */\napp.use((error, req, res, next) => {\n console.error('Unhandled error:', error);\n res.status(500).json({\n success: false,\n message: 'Internal server error',\n timestamp: new Date().toISOString()\n });\n});\n\n// Start server\nconst server = app.listen(PORT, () => {\n console.log(`🚀 Hello World Backend Service running on port ${PORT}`);\n console.log(`📖 API Documentation: http://localhost:${PORT}/`);\n console.log(`❤️ Health Check: http://localhost:${PORT}/api/health`);\n});\n\n// Graceful shutdown\nprocess.on('SIGTERM', () => {\n console.log('SIGTERM received, shutting down gracefully');\n server.close(() => {\n console.log('Process terminated');\n });\n});\n\nprocess.on('SIGINT', () => {\n console.log('SIGINT received, shutting down gracefully');\n server.close(() => {\n console.log('Process terminated');\n });\n});\n\nexport default app;"],"names":["express","hello","healthCheck","createApiResponse","app","PORT","process","env","use","json","urlencoded","extended","req","res","next","setHeader","console","log","Date","toISOString","method","path","get","message","response","greeting","error","status","success","timestamp","name","params","length","sanitizedName","replace","health","post","language","body","greetings","toLowerCase","version","endpoints","originalUrl","server","listen","on","close"],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ import request from 'supertest';
2
+ import app from '../src/server.js';
3
+ describe('Hello World Backend Service', ()=>{
4
+ describe('GET /', ()=>{
5
+ it('should return service information', async ()=>{
6
+ const response = await request(app).get('/').expect(200);
7
+ expect(response.body.success).toBe(true);
8
+ expect(response.body.message).toBe('Hello World Backend Service');
9
+ expect(response.body.endpoints).toBeDefined();
10
+ expect(response.body.timestamp).toBeDefined();
11
+ });
12
+ });
13
+ describe('GET /api/health', ()=>{
14
+ it('should return health status', async ()=>{
15
+ const response = await request(app).get('/api/health').expect(200);
16
+ expect(response.body.success).toBe(true);
17
+ expect(response.body.data.status).toBe('healthy');
18
+ expect(response.body.data.timestamp).toBeDefined();
19
+ expect(response.body.data.uptime).toBeDefined();
20
+ expect(response.body.timestamp).toBeDefined();
21
+ });
22
+ });
23
+ describe('GET /api/hello', ()=>{
24
+ it('should return basic hello world greeting', async ()=>{
25
+ const response = await request(app).get('/api/hello').expect(200);
26
+ expect(response.body.success).toBe(true);
27
+ expect(response.body.data.greeting).toBe('Hello World!');
28
+ expect(response.body.timestamp).toBeDefined();
29
+ });
30
+ });
31
+ describe('GET /api/hello/:name', ()=>{
32
+ it('should return personalized greeting', async ()=>{
33
+ const response = await request(app).get('/api/hello/John').expect(200);
34
+ expect(response.body.success).toBe(true);
35
+ expect(response.body.data.greeting).toBe('Hello John!');
36
+ expect(response.body.data.name).toBe('John');
37
+ expect(response.body.timestamp).toBeDefined();
38
+ });
39
+ it('should sanitize XSS attempts in name parameter', async ()=>{
40
+ const maliciousName = '<script>alert("xss")</script>John';
41
+ const response = await request(app).get(`/api/hello/${encodeURIComponent(maliciousName)}`).expect(200);
42
+ expect(response.body.success).toBe(true);
43
+ expect(response.body.data.greeting).not.toContain('<script>');
44
+ expect(response.body.data.name).not.toContain('<script>');
45
+ expect(response.body.data.greeting).toBe('Hello John!');
46
+ });
47
+ it('should handle empty name', async ()=>{
48
+ const response = await request(app).get('/api/hello/').expect(404);
49
+ });
50
+ it('should reject names longer than 100 characters', async ()=>{
51
+ const longName = 'a'.repeat(101);
52
+ const response = await request(app).get(`/api/hello/${longName}`).expect(400);
53
+ expect(response.body.success).toBe(false);
54
+ expect(response.body.message).toContain('Invalid name parameter');
55
+ });
56
+ });
57
+ describe('POST /api/hello', ()=>{
58
+ it('should return greeting with name from request body', async ()=>{
59
+ const response = await request(app).post('/api/hello').send({
60
+ name: 'Alice'
61
+ }).expect(200);
62
+ expect(response.body.success).toBe(true);
63
+ expect(response.body.data.greeting).toBe('Hello Alice!');
64
+ expect(response.body.data.name).toBe('Alice');
65
+ expect(response.body.data.language).toBe('en');
66
+ expect(response.body.timestamp).toBeDefined();
67
+ });
68
+ it('should handle greeting without name', async ()=>{
69
+ const response = await request(app).post('/api/hello').send({}).expect(200);
70
+ expect(response.body.success).toBe(true);
71
+ expect(response.body.data.greeting).toBe('Hello World!');
72
+ expect(response.body.data.name).toBe('World');
73
+ });
74
+ it('should support different languages', async ()=>{
75
+ const testCases = [
76
+ {
77
+ language: 'es',
78
+ expected: 'Hola'
79
+ },
80
+ {
81
+ language: 'fr',
82
+ expected: 'Bonjour'
83
+ },
84
+ {
85
+ language: 'de',
86
+ expected: 'Hallo'
87
+ },
88
+ {
89
+ language: 'it',
90
+ expected: 'Ciao'
91
+ },
92
+ {
93
+ language: 'pt',
94
+ expected: 'Olá'
95
+ },
96
+ {
97
+ language: 'ja',
98
+ expected: 'こんにちは'
99
+ },
100
+ {
101
+ language: 'zh',
102
+ expected: '你好'
103
+ },
104
+ {
105
+ language: 'hi',
106
+ expected: 'नमस्ते'
107
+ },
108
+ {
109
+ language: 'ar',
110
+ expected: 'مرحبا'
111
+ },
112
+ {
113
+ language: 'invalid',
114
+ expected: 'Hello'
115
+ }
116
+ ];
117
+ for (const testCase of testCases){
118
+ const response = await request(app).post('/api/hello').send({
119
+ name: 'World',
120
+ language: testCase.language
121
+ }).expect(200);
122
+ expect(response.body.success).toBe(true);
123
+ expect(response.body.data.greeting).toBe(`${testCase.expected} World!`);
124
+ expect(response.body.data.language).toBe(testCase.language);
125
+ }
126
+ });
127
+ it('should sanitize XSS attempts in POST request body', async ()=>{
128
+ const maliciousPayload = {
129
+ name: '<script>alert("xss")</script>Bob',
130
+ language: 'en'
131
+ };
132
+ const response = await request(app).post('/api/hello').send(maliciousPayload).expect(200);
133
+ expect(response.body.success).toBe(true);
134
+ expect(response.body.data.greeting).not.toContain('<script>');
135
+ expect(response.body.data.name).not.toContain('<script>');
136
+ expect(response.body.data.greeting).toBe('Hello Bob!');
137
+ });
138
+ it('should reject names longer than 100 characters', async ()=>{
139
+ const longName = 'a'.repeat(101);
140
+ const response = await request(app).post('/api/hello').send({
141
+ name: longName
142
+ }).expect(400);
143
+ expect(response.body.success).toBe(false);
144
+ expect(response.body.message).toContain('Invalid name');
145
+ });
146
+ it('should reject invalid language types', async ()=>{
147
+ const response = await request(app).post('/api/hello').send({
148
+ name: 'World',
149
+ language: 123
150
+ }).expect(200); // Should still work, language defaults to English
151
+ expect(response.body.success).toBe(true);
152
+ expect(response.body.data.greeting).toBe('Hello World!');
153
+ });
154
+ });
155
+ describe('Error Handling', ()=>{
156
+ it('should return 404 for non-existent endpoints', async ()=>{
157
+ const response = await request(app).get('/api/nonexistent').expect(404);
158
+ expect(response.body.success).toBe(false);
159
+ expect(response.body.message).toContain('Endpoint not found');
160
+ expect(response.body.path).toBe('/api/nonexistent');
161
+ });
162
+ it('should return 404 for nested non-existent endpoints', async ()=>{
163
+ const response = await request(app).get('/api/hello/nonexistent/deep').expect(404);
164
+ expect(response.body.success).toBe(false);
165
+ expect(response.body.message).toContain('Endpoint not found');
166
+ });
167
+ it('should handle malformed JSON in POST requests', async ()=>{
168
+ const response = await request(app).post('/api/hello').set('Content-Type', 'application/json').send('{"invalid": json}').expect(400);
169
+ });
170
+ });
171
+ describe('Security Headers', ()=>{
172
+ it('should include security headers', async ()=>{
173
+ const response = await request(app).get('/api/hello').expect(200);
174
+ expect(response.headers['x-content-type-options']).toBe('nosniff');
175
+ expect(response.headers['x-frame-options']).toBe('DENY');
176
+ expect(response.headers['x-xss-protection']).toBe('1; mode=block');
177
+ });
178
+ });
179
+ describe('Performance and Load Testing', ()=>{
180
+ it('should handle multiple concurrent requests', async ()=>{
181
+ const requests = Array(10).fill().map(()=>request(app).get('/api/hello'));
182
+ const responses = await Promise.all(requests);
183
+ responses.forEach((response)=>{
184
+ expect(response.status).toBe(200);
185
+ expect(response.body.success).toBe(true);
186
+ expect(response.body.data.greeting).toBe('Hello World!');
187
+ });
188
+ });
189
+ it('should handle requests with small delays', async ()=>{
190
+ for(let i = 0; i < 5; i++){
191
+ const response = await request(app).get('/api/hello/TestUser').expect(200);
192
+ expect(response.body.success).toBe(true);
193
+ expect(response.body.data.greeting).toBe('Hello TestUser!');
194
+ }
195
+ });
196
+ });
197
+ describe('Content-Type Handling', ()=>{
198
+ it('should handle form-urlencoded data', async ()=>{
199
+ const response = await request(app).post('/api/hello').send('name=FormUser&language=es').set('Content-Type', 'application/x-www-form-urlencoded').expect(200);
200
+ expect(response.body.success).toBe(true);
201
+ expect(response.body.data.greeting).toBe('Hola FormUser!');
202
+ expect(response.body.data.language).toBe('es');
203
+ });
204
+ });
205
+ });
206
+
207
+ //# sourceMappingURL=server.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.test.js"],"sourcesContent":["import request from 'supertest';\nimport app from '../src/server.js';\n\ndescribe('Hello World Backend Service', () => {\n describe('GET /', () => {\n it('should return service information', async () => {\n const response = await request(app)\n .get('/')\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.message).toBe('Hello World Backend Service');\n expect(response.body.endpoints).toBeDefined();\n expect(response.body.timestamp).toBeDefined();\n });\n });\n\n describe('GET /api/health', () => {\n it('should return health status', async () => {\n const response = await request(app)\n .get('/api/health')\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.status).toBe('healthy');\n expect(response.body.data.timestamp).toBeDefined();\n expect(response.body.data.uptime).toBeDefined();\n expect(response.body.timestamp).toBeDefined();\n });\n });\n\n describe('GET /api/hello', () => {\n it('should return basic hello world greeting', async () => {\n const response = await request(app)\n .get('/api/hello')\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hello World!');\n expect(response.body.timestamp).toBeDefined();\n });\n });\n\n describe('GET /api/hello/:name', () => {\n it('should return personalized greeting', async () => {\n const response = await request(app)\n .get('/api/hello/John')\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hello John!');\n expect(response.body.data.name).toBe('John');\n expect(response.body.timestamp).toBeDefined();\n });\n\n it('should sanitize XSS attempts in name parameter', async () => {\n const maliciousName = '<script>alert(\"xss\")</script>John';\n const response = await request(app)\n .get(`/api/hello/${encodeURIComponent(maliciousName)}`)\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).not.toContain('<script>');\n expect(response.body.data.name).not.toContain('<script>');\n expect(response.body.data.greeting).toBe('Hello John!');\n });\n\n it('should handle empty name', async () => {\n const response = await request(app)\n .get('/api/hello/')\n .expect(404);\n });\n\n it('should reject names longer than 100 characters', async () => {\n const longName = 'a'.repeat(101);\n const response = await request(app)\n .get(`/api/hello/${longName}`)\n .expect(400);\n\n expect(response.body.success).toBe(false);\n expect(response.body.message).toContain('Invalid name parameter');\n });\n });\n\n describe('POST /api/hello', () => {\n it('should return greeting with name from request body', async () => {\n const response = await request(app)\n .post('/api/hello')\n .send({ name: 'Alice' })\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hello Alice!');\n expect(response.body.data.name).toBe('Alice');\n expect(response.body.data.language).toBe('en');\n expect(response.body.timestamp).toBeDefined();\n });\n\n it('should handle greeting without name', async () => {\n const response = await request(app)\n .post('/api/hello')\n .send({})\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hello World!');\n expect(response.body.data.name).toBe('World');\n });\n\n it('should support different languages', async () => {\n const testCases = [\n { language: 'es', expected: 'Hola' },\n { language: 'fr', expected: 'Bonjour' },\n { language: 'de', expected: 'Hallo' },\n { language: 'it', expected: 'Ciao' },\n { language: 'pt', expected: 'Olá' },\n { language: 'ja', expected: 'こんにちは' },\n { language: 'zh', expected: '你好' },\n { language: 'hi', expected: 'नमस्ते' },\n { language: 'ar', expected: 'مرحبا' },\n { language: 'invalid', expected: 'Hello' }\n ];\n\n for (const testCase of testCases) {\n const response = await request(app)\n .post('/api/hello')\n .send({ name: 'World', language: testCase.language })\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe(`${testCase.expected} World!`);\n expect(response.body.data.language).toBe(testCase.language);\n }\n });\n\n it('should sanitize XSS attempts in POST request body', async () => {\n const maliciousPayload = {\n name: '<script>alert(\"xss\")</script>Bob',\n language: 'en'\n };\n\n const response = await request(app)\n .post('/api/hello')\n .send(maliciousPayload)\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).not.toContain('<script>');\n expect(response.body.data.name).not.toContain('<script>');\n expect(response.body.data.greeting).toBe('Hello Bob!');\n });\n\n it('should reject names longer than 100 characters', async () => {\n const longName = 'a'.repeat(101);\n const response = await request(app)\n .post('/api/hello')\n .send({ name: longName })\n .expect(400);\n\n expect(response.body.success).toBe(false);\n expect(response.body.message).toContain('Invalid name');\n });\n\n it('should reject invalid language types', async () => {\n const response = await request(app)\n .post('/api/hello')\n .send({ name: 'World', language: 123 })\n .expect(200); // Should still work, language defaults to English\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hello World!');\n });\n });\n\n describe('Error Handling', () => {\n it('should return 404 for non-existent endpoints', async () => {\n const response = await request(app)\n .get('/api/nonexistent')\n .expect(404);\n\n expect(response.body.success).toBe(false);\n expect(response.body.message).toContain('Endpoint not found');\n expect(response.body.path).toBe('/api/nonexistent');\n });\n\n it('should return 404 for nested non-existent endpoints', async () => {\n const response = await request(app)\n .get('/api/hello/nonexistent/deep')\n .expect(404);\n\n expect(response.body.success).toBe(false);\n expect(response.body.message).toContain('Endpoint not found');\n });\n\n it('should handle malformed JSON in POST requests', async () => {\n const response = await request(app)\n .post('/api/hello')\n .set('Content-Type', 'application/json')\n .send('{\"invalid\": json}')\n .expect(400);\n });\n });\n\n describe('Security Headers', () => {\n it('should include security headers', async () => {\n const response = await request(app)\n .get('/api/hello')\n .expect(200);\n\n expect(response.headers['x-content-type-options']).toBe('nosniff');\n expect(response.headers['x-frame-options']).toBe('DENY');\n expect(response.headers['x-xss-protection']).toBe('1; mode=block');\n });\n });\n\n describe('Performance and Load Testing', () => {\n it('should handle multiple concurrent requests', async () => {\n const requests = Array(10).fill().map(() => \n request(app).get('/api/hello')\n );\n\n const responses = await Promise.all(requests);\n \n responses.forEach(response => {\n expect(response.status).toBe(200);\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hello World!');\n });\n });\n\n it('should handle requests with small delays', async () => {\n for (let i = 0; i < 5; i++) {\n const response = await request(app)\n .get('/api/hello/TestUser')\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hello TestUser!');\n }\n });\n });\n\n describe('Content-Type Handling', () => {\n it('should handle form-urlencoded data', async () => {\n const response = await request(app)\n .post('/api/hello')\n .send('name=FormUser&language=es')\n .set('Content-Type', 'application/x-www-form-urlencoded')\n .expect(200);\n\n expect(response.body.success).toBe(true);\n expect(response.body.data.greeting).toBe('Hola FormUser!');\n expect(response.body.data.language).toBe('es');\n });\n });\n});"],"names":["request","app","describe","it","response","get","expect","body","success","toBe","message","endpoints","toBeDefined","timestamp","data","status","uptime","greeting","name","maliciousName","encodeURIComponent","not","toContain","longName","repeat","post","send","language","testCases","expected","testCase","maliciousPayload","path","set","headers","requests","Array","fill","map","responses","Promise","all","forEach","i"],"mappings":"AAAA,OAAOA,aAAa,YAAY;AAChC,OAAOC,SAAS,mBAAmB;AAEnCC,SAAS,+BAA+B;IACtCA,SAAS,SAAS;QAChBC,GAAG,qCAAqC;YACtC,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,KACJC,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACG,OAAO,EAAED,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACI,SAAS,EAAEC,WAAW;YAC3CN,OAAOF,SAASG,IAAI,CAACM,SAAS,EAAED,WAAW;QAC7C;IACF;IAEAV,SAAS,mBAAmB;QAC1BC,GAAG,+BAA+B;YAChC,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,eACJC,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACC,MAAM,EAAEN,IAAI,CAAC;YACvCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACD,SAAS,EAAED,WAAW;YAChDN,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACE,MAAM,EAAEJ,WAAW;YAC7CN,OAAOF,SAASG,IAAI,CAACM,SAAS,EAAED,WAAW;QAC7C;IACF;IAEAV,SAAS,kBAAkB;QACzBC,GAAG,4CAA4C;YAC7C,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,cACJC,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;YACzCH,OAAOF,SAASG,IAAI,CAACM,SAAS,EAAED,WAAW;QAC7C;IACF;IAEAV,SAAS,wBAAwB;QAC/BC,GAAG,uCAAuC;YACxC,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,mBACJC,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;YACzCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACI,IAAI,EAAET,IAAI,CAAC;YACrCH,OAAOF,SAASG,IAAI,CAACM,SAAS,EAAED,WAAW;QAC7C;QAEAT,GAAG,kDAAkD;YACnD,MAAMgB,gBAAgB;YACtB,MAAMf,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,CAAC,WAAW,EAAEe,mBAAmBD,gBAAgB,EACrDb,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAEI,GAAG,CAACC,SAAS,CAAC;YAClDhB,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACI,IAAI,EAAEG,GAAG,CAACC,SAAS,CAAC;YAC9ChB,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;QAC3C;QAEAN,GAAG,4BAA4B;YAC7B,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,eACJC,MAAM,CAAC;QACZ;QAEAH,GAAG,kDAAkD;YACnD,MAAMoB,WAAW,IAAIC,MAAM,CAAC;YAC5B,MAAMpB,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,CAAC,WAAW,EAAEkB,UAAU,EAC5BjB,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACG,OAAO,EAAEY,SAAS,CAAC;QAC1C;IACF;IAEApB,SAAS,mBAAmB;QAC1BC,GAAG,sDAAsD;YACvD,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLC,IAAI,CAAC;gBAAER,MAAM;YAAQ,GACrBZ,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;YACzCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACI,IAAI,EAAET,IAAI,CAAC;YACrCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACa,QAAQ,EAAElB,IAAI,CAAC;YACzCH,OAAOF,SAASG,IAAI,CAACM,SAAS,EAAED,WAAW;QAC7C;QAEAT,GAAG,uCAAuC;YACxC,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLC,IAAI,CAAC,CAAC,GACNpB,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;YACzCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACI,IAAI,EAAET,IAAI,CAAC;QACvC;QAEAN,GAAG,sCAAsC;YACvC,MAAMyB,YAAY;gBAChB;oBAAED,UAAU;oBAAME,UAAU;gBAAO;gBACnC;oBAAEF,UAAU;oBAAME,UAAU;gBAAU;gBACtC;oBAAEF,UAAU;oBAAME,UAAU;gBAAQ;gBACpC;oBAAEF,UAAU;oBAAME,UAAU;gBAAO;gBACnC;oBAAEF,UAAU;oBAAME,UAAU;gBAAM;gBAClC;oBAAEF,UAAU;oBAAME,UAAU;gBAAQ;gBACpC;oBAAEF,UAAU;oBAAME,UAAU;gBAAK;gBACjC;oBAAEF,UAAU;oBAAME,UAAU;gBAAS;gBACrC;oBAAEF,UAAU;oBAAME,UAAU;gBAAQ;gBACpC;oBAAEF,UAAU;oBAAWE,UAAU;gBAAQ;aAC1C;YAED,KAAK,MAAMC,YAAYF,UAAW;gBAChC,MAAMxB,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLC,IAAI,CAAC;oBAAER,MAAM;oBAASS,UAAUG,SAASH,QAAQ;gBAAC,GAClDrB,MAAM,CAAC;gBAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;gBACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC,GAAGqB,SAASD,QAAQ,CAAC,OAAO,CAAC;gBACtEvB,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACa,QAAQ,EAAElB,IAAI,CAACqB,SAASH,QAAQ;YAC5D;QACF;QAEAxB,GAAG,qDAAqD;YACtD,MAAM4B,mBAAmB;gBACvBb,MAAM;gBACNS,UAAU;YACZ;YAEA,MAAMvB,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLC,IAAI,CAACK,kBACLzB,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAEI,GAAG,CAACC,SAAS,CAAC;YAClDhB,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACI,IAAI,EAAEG,GAAG,CAACC,SAAS,CAAC;YAC9ChB,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;QAC3C;QAEAN,GAAG,kDAAkD;YACnD,MAAMoB,WAAW,IAAIC,MAAM,CAAC;YAC5B,MAAMpB,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLC,IAAI,CAAC;gBAAER,MAAMK;YAAS,GACtBjB,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACG,OAAO,EAAEY,SAAS,CAAC;QAC1C;QAEAnB,GAAG,wCAAwC;YACzC,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLC,IAAI,CAAC;gBAAER,MAAM;gBAASS,UAAU;YAAI,GACpCrB,MAAM,CAAC,MAAM,kDAAkD;YAElEA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;QAC3C;IACF;IAEAP,SAAS,kBAAkB;QACzBC,GAAG,gDAAgD;YACjD,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,oBACJC,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACG,OAAO,EAAEY,SAAS,CAAC;YACxChB,OAAOF,SAASG,IAAI,CAACyB,IAAI,EAAEvB,IAAI,CAAC;QAClC;QAEAN,GAAG,uDAAuD;YACxD,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,+BACJC,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACG,OAAO,EAAEY,SAAS,CAAC;QAC1C;QAEAnB,GAAG,iDAAiD;YAClD,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLQ,GAAG,CAAC,gBAAgB,oBACpBP,IAAI,CAAC,qBACLpB,MAAM,CAAC;QACZ;IACF;IAEAJ,SAAS,oBAAoB;QAC3BC,GAAG,mCAAmC;YACpC,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,cACJC,MAAM,CAAC;YAEVA,OAAOF,SAAS8B,OAAO,CAAC,yBAAyB,EAAEzB,IAAI,CAAC;YACxDH,OAAOF,SAAS8B,OAAO,CAAC,kBAAkB,EAAEzB,IAAI,CAAC;YACjDH,OAAOF,SAAS8B,OAAO,CAAC,mBAAmB,EAAEzB,IAAI,CAAC;QACpD;IACF;IAEAP,SAAS,gCAAgC;QACvCC,GAAG,8CAA8C;YAC/C,MAAMgC,WAAWC,MAAM,IAAIC,IAAI,GAAGC,GAAG,CAAC,IACpCtC,QAAQC,KAAKI,GAAG,CAAC;YAGnB,MAAMkC,YAAY,MAAMC,QAAQC,GAAG,CAACN;YAEpCI,UAAUG,OAAO,CAACtC,CAAAA;gBAChBE,OAAOF,SAASW,MAAM,EAAEN,IAAI,CAAC;gBAC7BH,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;gBACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;YAC3C;QACF;QAEAN,GAAG,4CAA4C;YAC7C,IAAK,IAAIwC,IAAI,GAAGA,IAAI,GAAGA,IAAK;gBAC1B,MAAMvC,WAAW,MAAMJ,QAAQC,KAC5BI,GAAG,CAAC,uBACJC,MAAM,CAAC;gBAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;gBACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;YAC3C;QACF;IACF;IAEAP,SAAS,yBAAyB;QAChCC,GAAG,sCAAsC;YACvC,MAAMC,WAAW,MAAMJ,QAAQC,KAC5BwB,IAAI,CAAC,cACLC,IAAI,CAAC,6BACLO,GAAG,CAAC,gBAAgB,qCACpB3B,MAAM,CAAC;YAEVA,OAAOF,SAASG,IAAI,CAACC,OAAO,EAAEC,IAAI,CAAC;YACnCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACG,QAAQ,EAAER,IAAI,CAAC;YACzCH,OAAOF,SAASG,IAAI,CAACO,IAAI,CAACa,QAAQ,EAAElB,IAAI,CAAC;QAC3C;IACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow-novice",
3
- "version": "2.14.35",
3
+ "version": "2.14.37",
4
4
  "description": "AI agent orchestration framework with namespace-isolated skills, agents, and CFN Loop validation. Safe installation with ~0.01% collision risk.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -132,6 +132,7 @@
132
132
  "chalk": "^4.1.2",
133
133
  "commander": "^11.1.0",
134
134
  "dotenv": "^17.2.3",
135
+ "express": "^5.1.0",
135
136
  "glob": "^11.0.3",
136
137
  "ioredis": "^5.8.2",
137
138
  "lodash": "^4.17.21",
@@ -0,0 +1,155 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ # Docker MCP Build Script
5
+ # Builds all MCP server images and enhanced agent image with MCP clients
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
9
+
10
+ # Colors for output
11
+ RED='\033[0;31m'
12
+ GREEN='\033[0;32m'
13
+ YELLOW='\033[1;33m'
14
+ NC='\033[0m' # No Color
15
+
16
+ echo "========================================="
17
+ echo " Docker MCP Build Script"
18
+ echo "========================================="
19
+ echo ""
20
+
21
+ # Function to print colored output
22
+ print_status() {
23
+ local status=$1
24
+ local message=$2
25
+ case $status in
26
+ "success")
27
+ echo -e "${GREEN}✓${NC} $message"
28
+ ;;
29
+ "error")
30
+ echo -e "${RED}✗${NC} $message"
31
+ ;;
32
+ "info")
33
+ echo -e "${YELLOW}→${NC} $message"
34
+ ;;
35
+ esac
36
+ }
37
+
38
+ # Check if Docker is available
39
+ if ! command -v docker &> /dev/null; then
40
+ print_status "error" "Docker is not installed or not in PATH"
41
+ exit 1
42
+ fi
43
+
44
+ # Check if docker-compose is available
45
+ if ! command -v docker-compose &> /dev/null; then
46
+ print_status "error" "docker-compose is not installed or not in PATH"
47
+ exit 1
48
+ fi
49
+
50
+ # Navigate to project root
51
+ cd "$PROJECT_ROOT"
52
+
53
+ # Validate MCP configuration exists
54
+ if [ ! -f "config/mcp-servers.json" ]; then
55
+ print_status "error" "MCP configuration not found: config/mcp-servers.json"
56
+ exit 1
57
+ fi
58
+
59
+ print_status "success" "Found MCP configuration"
60
+
61
+ # Build enhanced production Dockerfile with MCP clients
62
+ print_status "info" "Building enhanced agent image with MCP clients..."
63
+ if docker build -f Dockerfile.production \
64
+ --target production \
65
+ --tag cfn-agent-mcp:latest \
66
+ --tag cfn-agent-mcp:$(date +%Y%m%d) \
67
+ --build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
68
+ --build-arg VCS_REF="$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')" \
69
+ --build-arg VERSION="4.1.0-mcp" \
70
+ . 2>&1 | tee /tmp/docker-build-agent.log; then
71
+ print_status "success" "Agent image built successfully"
72
+ else
73
+ print_status "error" "Failed to build agent image"
74
+ exit 1
75
+ fi
76
+
77
+ # Build MCP server images from docker-compose
78
+ print_status "info" "Building MCP server containers..."
79
+ if docker-compose -f docker-compose.production.yml build \
80
+ mcp-playwright \
81
+ mcp-redis-tools \
82
+ mcp-n8n \
83
+ mcp-security-scanner 2>&1 | tee /tmp/docker-build-mcp.log; then
84
+ print_status "success" "MCP server images built successfully"
85
+ else
86
+ print_status "error" "Failed to build MCP server images"
87
+ exit 1
88
+ fi
89
+
90
+ # Pull base images that we reference directly
91
+ print_status "info" "Pulling base MCP images..."
92
+ docker pull mcr.microsoft.com/playwright:v1.40.0-jammy
93
+ docker pull redis:7-alpine
94
+ docker pull n8nio/n8n:latest
95
+ docker pull aquasec/trivy:latest
96
+ print_status "success" "Base images pulled"
97
+
98
+ # Run security scans if Trivy is available
99
+ if command -v trivy &> /dev/null; then
100
+ print_status "info" "Running security scans with Trivy..."
101
+
102
+ # Scan agent image
103
+ print_status "info" "Scanning cfn-agent-mcp:latest..."
104
+ if trivy image --severity HIGH,CRITICAL \
105
+ --exit-code 0 \
106
+ --no-progress \
107
+ cfn-agent-mcp:latest > /tmp/trivy-scan-agent.txt 2>&1; then
108
+ print_status "success" "Agent image scan complete"
109
+ else
110
+ print_status "error" "Agent image has vulnerabilities (see /tmp/trivy-scan-agent.txt)"
111
+ fi
112
+
113
+ # Scan MCP server images
114
+ for image in mcr.microsoft.com/playwright:v1.40.0-jammy \
115
+ redis:7-alpine \
116
+ n8nio/n8n:latest \
117
+ aquasec/trivy:latest; do
118
+ print_status "info" "Scanning $image..."
119
+ trivy image --severity HIGH,CRITICAL \
120
+ --exit-code 0 \
121
+ --no-progress \
122
+ "$image" > /tmp/trivy-scan-$(echo $image | sed 's/[^a-zA-Z0-9]/-/g').txt 2>&1 || true
123
+ done
124
+
125
+ print_status "success" "Security scans complete (results in /tmp/trivy-scan-*.txt)"
126
+ else
127
+ print_status "info" "Trivy not found - skipping security scans"
128
+ fi
129
+
130
+ # Summary
131
+ echo ""
132
+ echo "========================================="
133
+ echo " Build Summary"
134
+ echo "========================================="
135
+ echo ""
136
+
137
+ docker images | grep -E "(cfn-agent-mcp|mcp-playwright|mcp-redis-tools|mcp-n8n|mcp-security|playwright|n8n|trivy)" | head -20
138
+
139
+ echo ""
140
+ print_status "success" "Build complete!"
141
+ echo ""
142
+ echo "Tagged images:"
143
+ echo " - cfn-agent-mcp:latest"
144
+ echo " - cfn-agent-mcp:$(date +%Y%m%d)"
145
+ echo ""
146
+ echo "MCP Server images ready:"
147
+ echo " - mcp-playwright (mcr.microsoft.com/playwright:v1.40.0-jammy)"
148
+ echo " - mcp-redis-tools (redis:7-alpine)"
149
+ echo " - mcp-n8n (n8nio/n8n:latest)"
150
+ echo " - mcp-security-scanner (aquasec/trivy:latest)"
151
+ echo ""
152
+ echo "Next steps:"
153
+ echo " 1. Run tests: ./scripts/docker-test-mcp.sh"
154
+ echo " 2. Deploy: docker-compose -f docker-compose.production.yml up -d"
155
+ echo ""