specforge-mcp 0.3.0 → 0.4.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/dist/tools/generate-tests/generators/database-test-generator.d.ts +11 -0
- package/dist/tools/generate-tests/generators/database-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/database-test-generator.js +329 -0
- package/dist/tools/generate-tests/generators/database-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.d.ts +10 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.js +341 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/security-test-generator.d.ts +11 -0
- package/dist/tools/generate-tests/generators/security-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/security-test-generator.js +318 -0
- package/dist/tools/generate-tests/generators/security-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/spec-dispatcher.d.ts.map +1 -1
- package/dist/tools/generate-tests/spec-dispatcher.js +21 -0
- package/dist/tools/generate-tests/spec-dispatcher.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TestDefinition, TestFile, ProjectKnowledge } from '../../../types/index.js';
|
|
2
|
+
export declare function detectCaching(knowledge: ProjectKnowledge): string | null;
|
|
3
|
+
export declare function detectSearchEngine(knowledge: ProjectKnowledge): string | null;
|
|
4
|
+
export declare function hasOrm(knowledge: ProjectKnowledge): boolean;
|
|
5
|
+
export declare function isDatabaseTestProject(knowledge: ProjectKnowledge): boolean;
|
|
6
|
+
export declare function generateDatabaseTestDefs(title: string, testDir: string, _testExt: string, knowledge: ProjectKnowledge): TestDefinition[];
|
|
7
|
+
export declare function generateDatabaseTestFiles(spec: {
|
|
8
|
+
title: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
}, testDir: string, framework: string, language: string, testExt: string, autoGenerate: boolean, knowledge: ProjectKnowledge): TestFile[];
|
|
11
|
+
//# sourceMappingURL=database-test-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-test-generator.d.ts","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/database-test-generator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAY1F,wBAAgB,aAAa,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAQxE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAQ7E;AAED,wBAAgB,MAAM,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAE3D;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAE1E;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,gBAAgB,GAC1B,cAAc,EAAE,CAwDlB;AAkPD,wBAAgB,yBAAyB,CACvC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,EACrB,SAAS,EAAE,gBAAgB,GAC1B,QAAQ,EAAE,CAoBZ"}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// tools/generate-tests/generators/database-test-generator.ts — SPEC-058b Section F
|
|
2
|
+
// Generates database & data layer test scaffolds:
|
|
3
|
+
// migrations, repository/DAO CRUD, caching, full-text search.
|
|
4
|
+
const CACHE_SIGNALS = ['redis', 'memcached', 'node-cache', 'caffeine', 'ehcache', 'valkey'];
|
|
5
|
+
const SEARCH_SIGNALS = [
|
|
6
|
+
'elasticsearch',
|
|
7
|
+
'meilisearch',
|
|
8
|
+
'algolia',
|
|
9
|
+
'opensearch',
|
|
10
|
+
'solr',
|
|
11
|
+
'typesense',
|
|
12
|
+
];
|
|
13
|
+
export function detectCaching(knowledge) {
|
|
14
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
15
|
+
for (const sig of CACHE_SIGNALS) {
|
|
16
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
17
|
+
return sig;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
export function detectSearchEngine(knowledge) {
|
|
23
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
24
|
+
for (const sig of SEARCH_SIGNALS) {
|
|
25
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
26
|
+
return sig;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
export function hasOrm(knowledge) {
|
|
32
|
+
return knowledge.orm !== null && knowledge.orm !== 'unknown';
|
|
33
|
+
}
|
|
34
|
+
export function isDatabaseTestProject(knowledge) {
|
|
35
|
+
return knowledge.database !== 'unknown';
|
|
36
|
+
}
|
|
37
|
+
export function generateDatabaseTestDefs(title, testDir, _testExt, knowledge) {
|
|
38
|
+
const defs = [
|
|
39
|
+
{
|
|
40
|
+
name: `${title} — migration: schema up/down and rollback safety`,
|
|
41
|
+
type: 'integration',
|
|
42
|
+
file: `${testDir}/database/`,
|
|
43
|
+
description: 'Verify schema migrations run up/down cleanly and preserve data integrity',
|
|
44
|
+
priority: 'critical',
|
|
45
|
+
automatable: true,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: `${title} — repository: CRUD operations on ${knowledge.database}`,
|
|
49
|
+
type: 'integration',
|
|
50
|
+
file: `${testDir}/database/`,
|
|
51
|
+
description: 'Verify create, read, update, delete operations on the data layer',
|
|
52
|
+
priority: 'high',
|
|
53
|
+
automatable: true,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
if (hasOrm(knowledge)) {
|
|
57
|
+
defs.push({
|
|
58
|
+
name: `${title} — transactions and optimistic locking`,
|
|
59
|
+
type: 'integration',
|
|
60
|
+
file: `${testDir}/database/`,
|
|
61
|
+
description: 'Verify transaction commit/rollback and optimistic locking conflict detection',
|
|
62
|
+
priority: 'high',
|
|
63
|
+
automatable: true,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const cache = detectCaching(knowledge);
|
|
67
|
+
if (cache !== null) {
|
|
68
|
+
defs.push({
|
|
69
|
+
name: `${title} — caching (${cache}): hit/miss, TTL, invalidation`,
|
|
70
|
+
type: 'integration',
|
|
71
|
+
file: `${testDir}/database/`,
|
|
72
|
+
description: 'Verify cache hit/miss behavior, TTL expiration, and invalidation patterns',
|
|
73
|
+
priority: 'high',
|
|
74
|
+
automatable: true,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const search = detectSearchEngine(knowledge);
|
|
78
|
+
if (search !== null) {
|
|
79
|
+
defs.push({
|
|
80
|
+
name: `${title} — full-text search (${search}): indexing and query relevance`,
|
|
81
|
+
type: 'integration',
|
|
82
|
+
file: `${testDir}/database/`,
|
|
83
|
+
description: 'Verify document indexing, query relevance ranking, and fuzzy matching',
|
|
84
|
+
priority: 'medium',
|
|
85
|
+
automatable: true,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return defs;
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Scaffold builders
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
function buildTsDatabaseTest(title, db, orm, cache, search) {
|
|
94
|
+
const cacheSection = cache
|
|
95
|
+
? `
|
|
96
|
+
describe('Caching (${cache})', () => {
|
|
97
|
+
it('returns cached value on cache hit', async () => {
|
|
98
|
+
// await cache.set('user:1', { name: 'Test' }, { ttl: 60 });
|
|
99
|
+
// const result = await cache.get('user:1');
|
|
100
|
+
// expect(result).toMatchObject({ name: 'Test' });
|
|
101
|
+
expect(true).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('returns null on cache miss', async () => {
|
|
105
|
+
expect(true).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('expires entry after TTL', async () => {
|
|
109
|
+
expect(true).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('invalidates cache on data update', async () => {
|
|
113
|
+
expect(true).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
`
|
|
117
|
+
: '';
|
|
118
|
+
const searchSection = search
|
|
119
|
+
? `
|
|
120
|
+
describe('Full-text search (${search})', () => {
|
|
121
|
+
it('indexes document and makes it searchable', async () => {
|
|
122
|
+
// await searchClient.index('products').addDocuments([{ id: 1, name: 'Widget' }]);
|
|
123
|
+
// const results = await searchClient.index('products').search('Widget');
|
|
124
|
+
// expect(results.hits).toHaveLength(1);
|
|
125
|
+
expect(true).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('returns relevant results ranked by score', async () => {
|
|
129
|
+
expect(true).toBe(true);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('supports fuzzy matching for typos', async () => {
|
|
133
|
+
expect(true).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
`
|
|
137
|
+
: '';
|
|
138
|
+
const ormSection = orm
|
|
139
|
+
? `
|
|
140
|
+
describe('Transactions and locking', () => {
|
|
141
|
+
it('commits transaction on success', async () => {
|
|
142
|
+
expect(true).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('rolls back transaction on error', async () => {
|
|
146
|
+
expect(true).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('detects optimistic locking conflict', async () => {
|
|
150
|
+
// Concurrent update with stale version → should throw
|
|
151
|
+
expect(true).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
`
|
|
155
|
+
: '';
|
|
156
|
+
return `// Database & Data Layer tests for: ${title}
|
|
157
|
+
// Generated by SpecForge SDD MCP Server (SPEC-058b)
|
|
158
|
+
import { describe, it, expect } from 'vitest';
|
|
159
|
+
|
|
160
|
+
describe('${title} — Database Tests (${db})', () => {
|
|
161
|
+
describe('Migrations', () => {
|
|
162
|
+
it('schema migration up applies cleanly', async () => {
|
|
163
|
+
// await migrate.up();
|
|
164
|
+
// const tables = await db.query("SELECT name FROM sqlite_master WHERE type='table'");
|
|
165
|
+
// expect(tables).toContainEqual({ name: 'users' });
|
|
166
|
+
expect(true).toBe(true); // Replace with real migration assertion
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('schema migration down reverts cleanly', async () => {
|
|
170
|
+
expect(true).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('data integrity preserved after migration', async () => {
|
|
174
|
+
expect(true).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('rollback does not lose existing data', async () => {
|
|
178
|
+
expect(true).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('Repository / DAO — CRUD', () => {
|
|
183
|
+
it('creates a record and returns its id', async () => {
|
|
184
|
+
// const user = await repo.create({ name: 'Test', email: 'test@example.com' });
|
|
185
|
+
// expect(user.id).toBeDefined();
|
|
186
|
+
expect(true).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('reads a record by id', async () => {
|
|
190
|
+
expect(true).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('updates a record', async () => {
|
|
194
|
+
expect(true).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('deletes a record', async () => {
|
|
198
|
+
expect(true).toBe(true);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('returns null for non-existent record', async () => {
|
|
202
|
+
expect(true).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
${ormSection}${cacheSection}${searchSection}});
|
|
206
|
+
`;
|
|
207
|
+
}
|
|
208
|
+
function buildPythonDatabaseTest(title, db, orm, cache, search) {
|
|
209
|
+
const cls = title.replace(/[^a-zA-Z0-9]/g, '');
|
|
210
|
+
const ormSection = orm
|
|
211
|
+
? `
|
|
212
|
+
def test_transaction_commits_on_success(self) -> None:
|
|
213
|
+
"""Transaction commits all changes on success."""
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
def test_transaction_rolls_back_on_error(self) -> None:
|
|
217
|
+
"""Transaction rolls back on exception."""
|
|
218
|
+
pass
|
|
219
|
+
|
|
220
|
+
def test_optimistic_locking_conflict(self) -> None:
|
|
221
|
+
"""Concurrent update with stale version raises conflict."""
|
|
222
|
+
pass
|
|
223
|
+
`
|
|
224
|
+
: '';
|
|
225
|
+
const cacheSection = cache
|
|
226
|
+
? `
|
|
227
|
+
def test_cache_hit_returns_value(self) -> None:
|
|
228
|
+
"""Cache returns stored value on hit."""
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
def test_cache_miss_returns_none(self) -> None:
|
|
232
|
+
"""Cache returns None on miss."""
|
|
233
|
+
pass
|
|
234
|
+
|
|
235
|
+
def test_cache_ttl_expiration(self) -> None:
|
|
236
|
+
"""Cache entry expires after TTL."""
|
|
237
|
+
pass
|
|
238
|
+
|
|
239
|
+
def test_cache_invalidation_on_update(self) -> None:
|
|
240
|
+
"""Cache is invalidated when underlying data changes."""
|
|
241
|
+
pass
|
|
242
|
+
`
|
|
243
|
+
: '';
|
|
244
|
+
const searchSection = search
|
|
245
|
+
? `
|
|
246
|
+
def test_index_document_searchable(self) -> None:
|
|
247
|
+
"""Indexed document is returned by search query."""
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
def test_query_relevance_ranking(self) -> None:
|
|
251
|
+
"""Results are ranked by relevance score."""
|
|
252
|
+
pass
|
|
253
|
+
|
|
254
|
+
def test_fuzzy_matching_for_typos(self) -> None:
|
|
255
|
+
"""Fuzzy search finds results despite typos."""
|
|
256
|
+
pass
|
|
257
|
+
`
|
|
258
|
+
: '';
|
|
259
|
+
return `"""Database & Data Layer tests for: ${title}
|
|
260
|
+
Generated by SpecForge SDD MCP Server (SPEC-058b).
|
|
261
|
+
Database: ${db}
|
|
262
|
+
"""
|
|
263
|
+
import pytest
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class Test${cls}Database:
|
|
267
|
+
"""Database test suite for ${title} (${db})."""
|
|
268
|
+
|
|
269
|
+
def test_migration_up_applies_cleanly(self) -> None:
|
|
270
|
+
"""Schema migration up creates expected tables."""
|
|
271
|
+
# TODO: result = alembic.command.upgrade(config, 'head')
|
|
272
|
+
pass
|
|
273
|
+
|
|
274
|
+
def test_migration_down_reverts_cleanly(self) -> None:
|
|
275
|
+
"""Schema migration down removes tables cleanly."""
|
|
276
|
+
pass
|
|
277
|
+
|
|
278
|
+
def test_data_integrity_after_migration(self) -> None:
|
|
279
|
+
"""Existing data is preserved after migration."""
|
|
280
|
+
pass
|
|
281
|
+
|
|
282
|
+
def test_rollback_safety(self) -> None:
|
|
283
|
+
"""Rollback does not lose existing data."""
|
|
284
|
+
pass
|
|
285
|
+
|
|
286
|
+
def test_create_record(self) -> None:
|
|
287
|
+
"""Creates a record and returns its id."""
|
|
288
|
+
# TODO: user = repo.create(name='Test', email='test@example.com')
|
|
289
|
+
# assert user.id is not None
|
|
290
|
+
pass
|
|
291
|
+
|
|
292
|
+
def test_read_record_by_id(self) -> None:
|
|
293
|
+
"""Reads a record by primary key."""
|
|
294
|
+
pass
|
|
295
|
+
|
|
296
|
+
def test_update_record(self) -> None:
|
|
297
|
+
"""Updates a record field."""
|
|
298
|
+
pass
|
|
299
|
+
|
|
300
|
+
def test_delete_record(self) -> None:
|
|
301
|
+
"""Deletes a record."""
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
def test_read_nonexistent_returns_none(self) -> None:
|
|
305
|
+
"""Reading a non-existent record returns None."""
|
|
306
|
+
pass
|
|
307
|
+
${ormSection}${cacheSection}${searchSection}`;
|
|
308
|
+
}
|
|
309
|
+
export function generateDatabaseTestFiles(spec, testDir, framework, language, testExt, autoGenerate, knowledge) {
|
|
310
|
+
const cache = detectCaching(knowledge);
|
|
311
|
+
const search = detectSearchEngine(knowledge);
|
|
312
|
+
const orm = hasOrm(knowledge);
|
|
313
|
+
const db = knowledge.database;
|
|
314
|
+
const isPython = language === 'python';
|
|
315
|
+
const ext = isPython ? 'py' : testExt;
|
|
316
|
+
const fw = isPython ? 'pytest' : framework;
|
|
317
|
+
const content = isPython
|
|
318
|
+
? buildPythonDatabaseTest(spec.title, db, orm, cache, search)
|
|
319
|
+
: buildTsDatabaseTest(spec.title, db, orm, cache, search);
|
|
320
|
+
return [
|
|
321
|
+
{
|
|
322
|
+
path: `${testDir}/database/${spec.slug}.database.test.${ext}`,
|
|
323
|
+
framework: fw,
|
|
324
|
+
content,
|
|
325
|
+
ready: autoGenerate,
|
|
326
|
+
},
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
//# sourceMappingURL=database-test-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-test-generator.js","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/database-test-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TestDefinition, TestFile, ProjectKnowledge } from '../../../types/index.js';
|
|
2
|
+
export declare function detectBroker(knowledge: ProjectKnowledge): string | null;
|
|
3
|
+
export declare function detectServiceMesh(knowledge: ProjectKnowledge): string | null;
|
|
4
|
+
export declare function isMicroservicesTestProject(knowledge: ProjectKnowledge): boolean;
|
|
5
|
+
export declare function generateMicroservicesTestDefs(title: string, testDir: string, _testExt: string, knowledge: ProjectKnowledge): TestDefinition[];
|
|
6
|
+
export declare function generateMicroservicesTestFiles(spec: {
|
|
7
|
+
title: string;
|
|
8
|
+
slug: string;
|
|
9
|
+
}, testDir: string, framework: string, language: string, testExt: string, autoGenerate: boolean, knowledge: ProjectKnowledge): TestFile[];
|
|
10
|
+
//# sourceMappingURL=microservices-test-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microservices-test-generator.d.ts","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/microservices-test-generator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAa1F,wBAAgB,YAAY,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAQvE;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAQ5E;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAe/E;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,gBAAgB,GAC1B,cAAc,EAAE,CA+DlB;AA2OD,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,EACrB,SAAS,EAAE,gBAAgB,GAC1B,QAAQ,EAAE,CAkBZ"}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// tools/generate-tests/generators/microservices-test-generator.ts — SPEC-058b Section E
|
|
2
|
+
// Generates microservices & distributed systems test scaffolds:
|
|
3
|
+
// contract testing, circuit breaker, retry, health checks, broker, service mesh.
|
|
4
|
+
const BROKER_SIGNALS = ['kafka', 'rabbitmq', 'sqs', 'nats', 'redis-streams', 'pulsar', 'amqp'];
|
|
5
|
+
const MESH_SIGNALS = [
|
|
6
|
+
'istio',
|
|
7
|
+
'envoy',
|
|
8
|
+
'linkerd',
|
|
9
|
+
'kong',
|
|
10
|
+
'traefik',
|
|
11
|
+
'nginx-ingress',
|
|
12
|
+
'api-gateway',
|
|
13
|
+
];
|
|
14
|
+
export function detectBroker(knowledge) {
|
|
15
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
16
|
+
for (const sig of BROKER_SIGNALS) {
|
|
17
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
18
|
+
return sig;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
export function detectServiceMesh(knowledge) {
|
|
24
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
25
|
+
for (const sig of MESH_SIGNALS) {
|
|
26
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
27
|
+
return sig;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
export function isMicroservicesTestProject(knowledge) {
|
|
33
|
+
if (knowledge.architecture.primary === 'microservices') {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (knowledge.architecture.secondary.some((s) => s === 'microservices')) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (detectBroker(knowledge) !== null) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (detectServiceMesh(knowledge) !== null) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
const backends = knowledge.apps.filter((a) => a.type === 'backend' || a.type === 'worker');
|
|
46
|
+
return backends.length > 1;
|
|
47
|
+
}
|
|
48
|
+
export function generateMicroservicesTestDefs(title, testDir, _testExt, knowledge) {
|
|
49
|
+
const defs = [
|
|
50
|
+
{
|
|
51
|
+
name: `${title} — contract testing: inter-service Pact verification`,
|
|
52
|
+
type: 'integration',
|
|
53
|
+
file: `${testDir}/microservices/`,
|
|
54
|
+
description: 'Consumer-driven contract tests verify API compatibility between services',
|
|
55
|
+
priority: 'critical',
|
|
56
|
+
automatable: true,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: `${title} — circuit breaker: open/half-open/closed state transitions`,
|
|
60
|
+
type: 'integration',
|
|
61
|
+
file: `${testDir}/microservices/`,
|
|
62
|
+
description: 'Verify circuit breaker opens on failures, transitions to half-open, and closes on recovery',
|
|
63
|
+
priority: 'high',
|
|
64
|
+
automatable: true,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: `${title} — retry with backoff: exponential backoff and idempotency`,
|
|
68
|
+
type: 'integration',
|
|
69
|
+
file: `${testDir}/microservices/`,
|
|
70
|
+
description: 'Verify retry logic uses exponential backoff with jitter and respects idempotency keys',
|
|
71
|
+
priority: 'high',
|
|
72
|
+
automatable: true,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: `${title} — health checks: liveness and readiness probes`,
|
|
76
|
+
type: 'integration',
|
|
77
|
+
file: `${testDir}/microservices/`,
|
|
78
|
+
description: 'Verify /healthz, /readyz, and startup probes return correct status codes',
|
|
79
|
+
priority: 'critical',
|
|
80
|
+
automatable: true,
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
if (detectBroker(knowledge) !== null) {
|
|
84
|
+
defs.push({
|
|
85
|
+
name: `${title} — message broker: delivery guarantee and DLQ handling`,
|
|
86
|
+
type: 'integration',
|
|
87
|
+
file: `${testDir}/microservices/`,
|
|
88
|
+
description: 'Verify message delivery, ordering, dead letter queue handling, and consumer group rebalancing',
|
|
89
|
+
priority: 'high',
|
|
90
|
+
automatable: true,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (detectServiceMesh(knowledge) !== null) {
|
|
94
|
+
defs.push({
|
|
95
|
+
name: `${title} — service mesh: routing rules and mTLS verification`,
|
|
96
|
+
type: 'integration',
|
|
97
|
+
file: `${testDir}/microservices/`,
|
|
98
|
+
description: 'Verify routing rules, mTLS certificate verification, and traffic splitting configuration',
|
|
99
|
+
priority: 'medium',
|
|
100
|
+
automatable: true,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return defs;
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// Scaffold builders
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
function buildTsMicroservicesTest(title, broker, mesh) {
|
|
109
|
+
const brokerSection = broker
|
|
110
|
+
? `
|
|
111
|
+
describe('Message broker (${broker})', () => {
|
|
112
|
+
it('guarantees message delivery to consumer', async () => {
|
|
113
|
+
// const producer = createProducer({ broker: '${broker}' });
|
|
114
|
+
// await producer.send({ topic: 'orders', value: { id: 1 } });
|
|
115
|
+
// const received = await consumer.waitForMessage('orders', 5000);
|
|
116
|
+
// expect(received.value).toMatchObject({ id: 1 });
|
|
117
|
+
expect(true).toBe(true); // Replace with real broker assertion
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('routes failed messages to dead letter queue', async () => {
|
|
121
|
+
// Simulate processing failure → verify message lands in DLQ
|
|
122
|
+
expect(true).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('preserves message ordering within partition', async () => {
|
|
126
|
+
expect(true).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('handles consumer group rebalancing gracefully', async () => {
|
|
130
|
+
expect(true).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
`
|
|
134
|
+
: '';
|
|
135
|
+
const meshSection = mesh
|
|
136
|
+
? `
|
|
137
|
+
describe('Service mesh (${mesh})', () => {
|
|
138
|
+
it('routes traffic according to configured rules', async () => {
|
|
139
|
+
expect(true).toBe(true);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('verifies mTLS certificates between services', async () => {
|
|
143
|
+
expect(true).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('splits traffic correctly between versions', async () => {
|
|
147
|
+
expect(true).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
`
|
|
151
|
+
: '';
|
|
152
|
+
return `// Microservices & Distributed Systems tests for: ${title}
|
|
153
|
+
// Generated by SpecForge SDD MCP Server (SPEC-058b)
|
|
154
|
+
import { describe, it, expect } from 'vitest';
|
|
155
|
+
|
|
156
|
+
describe('${title} — Microservices Tests', () => {
|
|
157
|
+
describe('Contract testing (Pact)', () => {
|
|
158
|
+
it('consumer contract matches provider API', async () => {
|
|
159
|
+
// const interaction = new PactInteraction()
|
|
160
|
+
// .uponReceiving('a request for user')
|
|
161
|
+
// .withRequest({ method: 'GET', path: '/api/users/1' })
|
|
162
|
+
// .willRespondWith({ status: 200, body: { id: 1, name: 'Test' } });
|
|
163
|
+
// await provider.verify(interaction);
|
|
164
|
+
expect(true).toBe(true); // Replace with real Pact assertion
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('Circuit breaker', () => {
|
|
169
|
+
it('opens after consecutive failures', async () => {
|
|
170
|
+
// Simulate 5 failures → verify circuit is open
|
|
171
|
+
expect(true).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('transitions from open to half-open after timeout', async () => {
|
|
175
|
+
expect(true).toBe(true);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('closes after successful request in half-open state', async () => {
|
|
179
|
+
expect(true).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('returns fallback response when circuit is open', async () => {
|
|
183
|
+
expect(true).toBe(true);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('Retry with backoff', () => {
|
|
188
|
+
it('retries with exponential backoff on transient failure', async () => {
|
|
189
|
+
// Verify delays: 100ms, 200ms, 400ms (exponential)
|
|
190
|
+
expect(true).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('respects max retry limit', async () => {
|
|
194
|
+
expect(true).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('applies jitter to avoid thundering herd', async () => {
|
|
198
|
+
expect(true).toBe(true);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('uses idempotency key to prevent duplicate processing', async () => {
|
|
202
|
+
expect(true).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('Health check endpoints', () => {
|
|
207
|
+
it('GET /healthz returns 200 when service is alive', async () => {
|
|
208
|
+
// const res = await request(app).get('/healthz');
|
|
209
|
+
// expect(res.status).toBe(200);
|
|
210
|
+
expect(true).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('GET /readyz returns 200 when dependencies are ready', async () => {
|
|
214
|
+
expect(true).toBe(true);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('GET /readyz returns 503 when a dependency is down', async () => {
|
|
218
|
+
expect(true).toBe(true);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('startup probe succeeds within timeout', async () => {
|
|
222
|
+
expect(true).toBe(true);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
${brokerSection}${meshSection}});
|
|
226
|
+
`;
|
|
227
|
+
}
|
|
228
|
+
function buildPythonMicroservicesTest(title, broker, mesh) {
|
|
229
|
+
const cls = title.replace(/[^a-zA-Z0-9]/g, '');
|
|
230
|
+
const brokerSection = broker
|
|
231
|
+
? `
|
|
232
|
+
def test_message_delivery_guarantee(self) -> None:
|
|
233
|
+
"""Messages are delivered to consumers with at-least-once guarantee."""
|
|
234
|
+
# TODO: producer.send('orders', {'id': 1})
|
|
235
|
+
# msg = consumer.poll(timeout=5.0)
|
|
236
|
+
# assert msg.value == {'id': 1}
|
|
237
|
+
pass
|
|
238
|
+
|
|
239
|
+
def test_dead_letter_queue_routing(self) -> None:
|
|
240
|
+
"""Failed messages are routed to the dead letter queue."""
|
|
241
|
+
pass
|
|
242
|
+
|
|
243
|
+
def test_message_ordering_within_partition(self) -> None:
|
|
244
|
+
"""Messages within same partition maintain ordering."""
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
def test_consumer_group_rebalancing(self) -> None:
|
|
248
|
+
"""Consumer group rebalancing does not lose messages."""
|
|
249
|
+
pass
|
|
250
|
+
`
|
|
251
|
+
: '';
|
|
252
|
+
const meshSection = mesh
|
|
253
|
+
? `
|
|
254
|
+
def test_routing_rules(self) -> None:
|
|
255
|
+
"""Traffic is routed according to configured rules."""
|
|
256
|
+
pass
|
|
257
|
+
|
|
258
|
+
def test_mtls_verification(self) -> None:
|
|
259
|
+
"""mTLS certificates are verified between services."""
|
|
260
|
+
pass
|
|
261
|
+
|
|
262
|
+
def test_traffic_splitting(self) -> None:
|
|
263
|
+
"""Traffic is split correctly between service versions."""
|
|
264
|
+
pass
|
|
265
|
+
`
|
|
266
|
+
: '';
|
|
267
|
+
return `"""Microservices & Distributed Systems tests for: ${title}
|
|
268
|
+
Generated by SpecForge SDD MCP Server (SPEC-058b).
|
|
269
|
+
"""
|
|
270
|
+
import pytest
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class Test${cls}Microservices:
|
|
274
|
+
"""Microservices test suite for ${title}."""
|
|
275
|
+
|
|
276
|
+
def test_consumer_contract_matches_provider(self) -> None:
|
|
277
|
+
"""Consumer-driven contract matches the provider API."""
|
|
278
|
+
# TODO: pact = Pact('consumer', 'provider')
|
|
279
|
+
# pact.given('user exists').upon_receiving('get user')
|
|
280
|
+
# .with_request('GET', '/api/users/1')
|
|
281
|
+
# .will_respond_with(200, body={'id': 1})
|
|
282
|
+
pass
|
|
283
|
+
|
|
284
|
+
def test_circuit_breaker_opens_on_failures(self) -> None:
|
|
285
|
+
"""Circuit breaker opens after consecutive failures."""
|
|
286
|
+
pass
|
|
287
|
+
|
|
288
|
+
def test_circuit_breaker_half_open_transition(self) -> None:
|
|
289
|
+
"""Circuit transitions from open to half-open after timeout."""
|
|
290
|
+
pass
|
|
291
|
+
|
|
292
|
+
def test_circuit_breaker_closes_on_recovery(self) -> None:
|
|
293
|
+
"""Circuit closes after successful request in half-open state."""
|
|
294
|
+
pass
|
|
295
|
+
|
|
296
|
+
def test_retry_exponential_backoff(self) -> None:
|
|
297
|
+
"""Retries use exponential backoff with jitter."""
|
|
298
|
+
pass
|
|
299
|
+
|
|
300
|
+
def test_retry_respects_max_limit(self) -> None:
|
|
301
|
+
"""Retry stops after max attempts."""
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
def test_idempotency_key_prevents_duplicates(self) -> None:
|
|
305
|
+
"""Idempotency key prevents duplicate processing on retry."""
|
|
306
|
+
pass
|
|
307
|
+
|
|
308
|
+
def test_healthz_returns_200(self) -> None:
|
|
309
|
+
"""GET /healthz returns 200 when service is alive."""
|
|
310
|
+
# TODO: response = client.get('/healthz')
|
|
311
|
+
# assert response.status_code == 200
|
|
312
|
+
pass
|
|
313
|
+
|
|
314
|
+
def test_readyz_returns_200_when_ready(self) -> None:
|
|
315
|
+
"""GET /readyz returns 200 when all dependencies are ready."""
|
|
316
|
+
pass
|
|
317
|
+
|
|
318
|
+
def test_readyz_returns_503_when_dependency_down(self) -> None:
|
|
319
|
+
"""GET /readyz returns 503 when a dependency is unavailable."""
|
|
320
|
+
pass
|
|
321
|
+
${brokerSection}${meshSection}`;
|
|
322
|
+
}
|
|
323
|
+
export function generateMicroservicesTestFiles(spec, testDir, framework, language, testExt, autoGenerate, knowledge) {
|
|
324
|
+
const broker = detectBroker(knowledge);
|
|
325
|
+
const mesh = detectServiceMesh(knowledge);
|
|
326
|
+
const isPython = language === 'python';
|
|
327
|
+
const ext = isPython ? 'py' : testExt;
|
|
328
|
+
const fw = isPython ? 'pytest' : framework;
|
|
329
|
+
const content = isPython
|
|
330
|
+
? buildPythonMicroservicesTest(spec.title, broker, mesh)
|
|
331
|
+
: buildTsMicroservicesTest(spec.title, broker, mesh);
|
|
332
|
+
return [
|
|
333
|
+
{
|
|
334
|
+
path: `${testDir}/microservices/${spec.slug}.microservices.test.${ext}`,
|
|
335
|
+
framework: fw,
|
|
336
|
+
content,
|
|
337
|
+
ready: autoGenerate,
|
|
338
|
+
},
|
|
339
|
+
];
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=microservices-test-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microservices-test-generator.js","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/microservices-test-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TestDefinition, TestFile, ProjectKnowledge } from '../../../types/index.js';
|
|
2
|
+
export declare function detectAuth(knowledge: ProjectKnowledge): string | null;
|
|
3
|
+
export declare function detectFileUpload(knowledge: ProjectKnowledge): string | null;
|
|
4
|
+
export declare function hasPublicApi(knowledge: ProjectKnowledge): boolean;
|
|
5
|
+
export declare function isSecurityTestProject(knowledge: ProjectKnowledge): boolean;
|
|
6
|
+
export declare function generateSecurityTestDefs(title: string, testDir: string, _testExt: string, knowledge: ProjectKnowledge): TestDefinition[];
|
|
7
|
+
export declare function generateSecurityTestFiles(spec: {
|
|
8
|
+
title: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
}, testDir: string, framework: string, language: string, testExt: string, autoGenerate: boolean, knowledge: ProjectKnowledge): TestFile[];
|
|
11
|
+
//# sourceMappingURL=security-test-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-test-generator.d.ts","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/security-test-generator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AA4B1F,wBAAgB,UAAU,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAQrE;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAQ3E;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAKjE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAQ1E;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,gBAAgB,GAC1B,cAAc,EAAE,CAiDlB;AAwND,wBAAgB,yBAAyB,CACvC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,EACrB,SAAS,EAAE,gBAAgB,GAC1B,QAAQ,EAAE,CAmBZ"}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
// tools/generate-tests/generators/security-test-generator.ts — SPEC-058b Section G
|
|
2
|
+
// Generates security test scaffolds:
|
|
3
|
+
// OWASP Top 10, auth flows, file upload, API rate limiting.
|
|
4
|
+
const AUTH_SIGNALS = [
|
|
5
|
+
'jwt',
|
|
6
|
+
'oauth',
|
|
7
|
+
'passport',
|
|
8
|
+
'keycloak',
|
|
9
|
+
'auth0',
|
|
10
|
+
'clerk',
|
|
11
|
+
'supabase',
|
|
12
|
+
'session',
|
|
13
|
+
'cookie-session',
|
|
14
|
+
'express-session',
|
|
15
|
+
'next-auth',
|
|
16
|
+
'lucia',
|
|
17
|
+
'better-auth',
|
|
18
|
+
];
|
|
19
|
+
const UPLOAD_SIGNALS = [
|
|
20
|
+
'multer',
|
|
21
|
+
'formidable',
|
|
22
|
+
'busboy',
|
|
23
|
+
'sharp',
|
|
24
|
+
'jimp',
|
|
25
|
+
'imagemagick',
|
|
26
|
+
'file-upload',
|
|
27
|
+
'multipart',
|
|
28
|
+
];
|
|
29
|
+
export function detectAuth(knowledge) {
|
|
30
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
31
|
+
for (const sig of AUTH_SIGNALS) {
|
|
32
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
33
|
+
return sig;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
export function detectFileUpload(knowledge) {
|
|
39
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
40
|
+
for (const sig of UPLOAD_SIGNALS) {
|
|
41
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
42
|
+
return sig;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
export function hasPublicApi(knowledge) {
|
|
48
|
+
if (knowledge.apiContracts.length > 0) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return knowledge.apps.some((a) => a.type === 'backend');
|
|
52
|
+
}
|
|
53
|
+
export function isSecurityTestProject(knowledge) {
|
|
54
|
+
if (detectAuth(knowledge) !== null) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
if (hasPublicApi(knowledge)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return knowledge.apps.some((a) => a.type === 'backend' || a.type === 'frontend');
|
|
61
|
+
}
|
|
62
|
+
export function generateSecurityTestDefs(title, testDir, _testExt, knowledge) {
|
|
63
|
+
const defs = [];
|
|
64
|
+
if (hasPublicApi(knowledge)) {
|
|
65
|
+
defs.push({
|
|
66
|
+
name: `${title} — OWASP Top 10: injection, XSS, CSRF, auth bypass`,
|
|
67
|
+
type: 'integration',
|
|
68
|
+
file: `${testDir}/security/`,
|
|
69
|
+
description: 'Verify protection against OWASP Top 10 vulnerabilities on public endpoints',
|
|
70
|
+
priority: 'critical',
|
|
71
|
+
automatable: true,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (detectAuth(knowledge) !== null) {
|
|
75
|
+
defs.push({
|
|
76
|
+
name: `${title} — auth: token expiration, refresh flow, privilege escalation`,
|
|
77
|
+
type: 'integration',
|
|
78
|
+
file: `${testDir}/security/`,
|
|
79
|
+
description: 'Verify auth token lifecycle, refresh flow, and privilege escalation prevention',
|
|
80
|
+
priority: 'critical',
|
|
81
|
+
automatable: true,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (detectFileUpload(knowledge) !== null) {
|
|
85
|
+
defs.push({
|
|
86
|
+
name: `${title} — file upload: type validation, size limits, path traversal`,
|
|
87
|
+
type: 'integration',
|
|
88
|
+
file: `${testDir}/security/`,
|
|
89
|
+
description: 'Verify file upload security: type validation, size limits, path traversal prevention',
|
|
90
|
+
priority: 'high',
|
|
91
|
+
automatable: true,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (hasPublicApi(knowledge)) {
|
|
95
|
+
defs.push({
|
|
96
|
+
name: `${title} — API security: rate limiting, CORS, API key rotation`,
|
|
97
|
+
type: 'integration',
|
|
98
|
+
file: `${testDir}/security/`,
|
|
99
|
+
description: 'Verify rate limiting effectiveness, CORS policy, and API key rotation support',
|
|
100
|
+
priority: 'high',
|
|
101
|
+
automatable: true,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return defs;
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Scaffold builders
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
function buildTsSecurityTest(title, auth, upload, publicApi) {
|
|
110
|
+
const owaspSection = publicApi
|
|
111
|
+
? `
|
|
112
|
+
describe('OWASP Top 10', () => {
|
|
113
|
+
it('rejects SQL injection in query parameters', async () => {
|
|
114
|
+
// const res = await request(app).get("/api/users?id=' OR 1=1 --");
|
|
115
|
+
// expect(res.status).toBe(400);
|
|
116
|
+
expect(true).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('escapes XSS payloads in response', async () => {
|
|
120
|
+
// const res = await request(app).post('/api/comments')
|
|
121
|
+
// .send({ body: '<script>alert("xss")</script>' });
|
|
122
|
+
// expect(res.body.body).not.toContain('<script>');
|
|
123
|
+
expect(true).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('validates CSRF token on state-changing requests', async () => {
|
|
127
|
+
expect(true).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('rejects auth bypass attempts', async () => {
|
|
131
|
+
expect(true).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
`
|
|
135
|
+
: '';
|
|
136
|
+
const authSection = auth
|
|
137
|
+
? `
|
|
138
|
+
describe('Authentication (${auth})', () => {
|
|
139
|
+
it('rejects expired token with 401', async () => {
|
|
140
|
+
// const expiredToken = signToken({ exp: Math.floor(Date.now()/1000) - 60 });
|
|
141
|
+
// const res = await request(app).get('/api/me').set('Authorization', \`Bearer \${expiredToken}\`);
|
|
142
|
+
// expect(res.status).toBe(401);
|
|
143
|
+
expect(true).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('refresh token returns new access token', async () => {
|
|
147
|
+
expect(true).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('prevents privilege escalation (user cannot access admin)', async () => {
|
|
151
|
+
expect(true).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('prevents session fixation attack', async () => {
|
|
155
|
+
expect(true).toBe(true);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
`
|
|
159
|
+
: '';
|
|
160
|
+
const uploadSection = upload
|
|
161
|
+
? `
|
|
162
|
+
describe('File upload (${upload})', () => {
|
|
163
|
+
it('rejects disallowed file types', async () => {
|
|
164
|
+
// const res = await request(app).post('/api/upload')
|
|
165
|
+
// .attach('file', Buffer.from('#!/bin/sh'), { filename: 'evil.sh' });
|
|
166
|
+
// expect(res.status).toBe(400);
|
|
167
|
+
expect(true).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('enforces maximum file size', async () => {
|
|
171
|
+
expect(true).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('prevents path traversal in filename', async () => {
|
|
175
|
+
// filename: '../../etc/passwd' → should be sanitized
|
|
176
|
+
expect(true).toBe(true);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('scans for malicious content', async () => {
|
|
180
|
+
expect(true).toBe(true);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
`
|
|
184
|
+
: '';
|
|
185
|
+
const apiSection = publicApi
|
|
186
|
+
? `
|
|
187
|
+
describe('API security', () => {
|
|
188
|
+
it('rate limiter blocks excessive requests', async () => {
|
|
189
|
+
// for (let i = 0; i < 101; i++) await request(app).get('/api/data');
|
|
190
|
+
// const res = await request(app).get('/api/data');
|
|
191
|
+
// expect(res.status).toBe(429);
|
|
192
|
+
expect(true).toBe(true);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('CORS rejects requests from unauthorized origins', async () => {
|
|
196
|
+
expect(true).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('supports API key rotation without downtime', async () => {
|
|
200
|
+
expect(true).toBe(true);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
`
|
|
204
|
+
: '';
|
|
205
|
+
return `// Security tests for: ${title}
|
|
206
|
+
// Generated by SpecForge SDD MCP Server (SPEC-058b)
|
|
207
|
+
import { describe, it, expect } from 'vitest';
|
|
208
|
+
|
|
209
|
+
describe('${title} — Security Tests', () => {
|
|
210
|
+
${owaspSection}${authSection}${uploadSection}${apiSection}});
|
|
211
|
+
`;
|
|
212
|
+
}
|
|
213
|
+
function buildPythonSecurityTest(title, auth, upload, publicApi) {
|
|
214
|
+
const cls = title.replace(/[^a-zA-Z0-9]/g, '');
|
|
215
|
+
const owaspSection = publicApi
|
|
216
|
+
? `
|
|
217
|
+
def test_sql_injection_rejected(self) -> None:
|
|
218
|
+
"""SQL injection in query parameters is rejected."""
|
|
219
|
+
# response = client.get("/api/users?id=' OR 1=1 --")
|
|
220
|
+
# assert response.status_code == 400
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
def test_xss_payload_escaped(self) -> None:
|
|
224
|
+
"""XSS payloads are escaped in response."""
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
def test_csrf_token_validated(self) -> None:
|
|
228
|
+
"""CSRF token is required on state-changing requests."""
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
def test_auth_bypass_rejected(self) -> None:
|
|
232
|
+
"""Auth bypass attempts are rejected."""
|
|
233
|
+
pass
|
|
234
|
+
`
|
|
235
|
+
: '';
|
|
236
|
+
const authSection = auth
|
|
237
|
+
? `
|
|
238
|
+
def test_expired_token_returns_401(self) -> None:
|
|
239
|
+
"""Expired token is rejected with 401."""
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
def test_refresh_token_returns_new_access_token(self) -> None:
|
|
243
|
+
"""Refresh token flow issues a new access token."""
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
def test_privilege_escalation_prevented(self) -> None:
|
|
247
|
+
"""User cannot access admin-only endpoints."""
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
def test_session_fixation_prevented(self) -> None:
|
|
251
|
+
"""Session fixation attack is prevented."""
|
|
252
|
+
pass
|
|
253
|
+
`
|
|
254
|
+
: '';
|
|
255
|
+
const uploadSection = upload
|
|
256
|
+
? `
|
|
257
|
+
def test_disallowed_file_type_rejected(self) -> None:
|
|
258
|
+
"""Disallowed file types are rejected on upload."""
|
|
259
|
+
pass
|
|
260
|
+
|
|
261
|
+
def test_max_file_size_enforced(self) -> None:
|
|
262
|
+
"""Files exceeding size limit are rejected."""
|
|
263
|
+
pass
|
|
264
|
+
|
|
265
|
+
def test_path_traversal_in_filename_prevented(self) -> None:
|
|
266
|
+
"""Path traversal in filename is sanitized."""
|
|
267
|
+
pass
|
|
268
|
+
|
|
269
|
+
def test_malicious_content_detected(self) -> None:
|
|
270
|
+
"""Malicious file content is detected and rejected."""
|
|
271
|
+
pass
|
|
272
|
+
`
|
|
273
|
+
: '';
|
|
274
|
+
const apiSection = publicApi
|
|
275
|
+
? `
|
|
276
|
+
def test_rate_limiter_blocks_excess(self) -> None:
|
|
277
|
+
"""Rate limiter returns 429 after threshold."""
|
|
278
|
+
pass
|
|
279
|
+
|
|
280
|
+
def test_cors_rejects_unauthorized_origin(self) -> None:
|
|
281
|
+
"""CORS policy rejects requests from unauthorized origins."""
|
|
282
|
+
pass
|
|
283
|
+
|
|
284
|
+
def test_api_key_rotation_supported(self) -> None:
|
|
285
|
+
"""API key rotation works without downtime."""
|
|
286
|
+
pass
|
|
287
|
+
`
|
|
288
|
+
: '';
|
|
289
|
+
return `"""Security tests for: ${title}
|
|
290
|
+
Generated by SpecForge SDD MCP Server (SPEC-058b).
|
|
291
|
+
"""
|
|
292
|
+
import pytest
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class Test${cls}Security:
|
|
296
|
+
"""Security test suite for ${title}."""
|
|
297
|
+
${owaspSection}${authSection}${uploadSection}${apiSection}`;
|
|
298
|
+
}
|
|
299
|
+
export function generateSecurityTestFiles(spec, testDir, framework, language, testExt, autoGenerate, knowledge) {
|
|
300
|
+
const auth = detectAuth(knowledge);
|
|
301
|
+
const upload = detectFileUpload(knowledge);
|
|
302
|
+
const publicApi = hasPublicApi(knowledge);
|
|
303
|
+
const isPython = language === 'python';
|
|
304
|
+
const ext = isPython ? 'py' : testExt;
|
|
305
|
+
const fw = isPython ? 'pytest' : framework;
|
|
306
|
+
const content = isPython
|
|
307
|
+
? buildPythonSecurityTest(spec.title, auth, upload, publicApi)
|
|
308
|
+
: buildTsSecurityTest(spec.title, auth, upload, publicApi);
|
|
309
|
+
return [
|
|
310
|
+
{
|
|
311
|
+
path: `${testDir}/security/${spec.slug}.security.test.${ext}`,
|
|
312
|
+
framework: fw,
|
|
313
|
+
content,
|
|
314
|
+
ready: autoGenerate,
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=security-test-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-test-generator.js","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/security-test-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-dispatcher.d.ts","sourceRoot":"","sources":["../../../src/tools/generate-tests/spec-dispatcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"spec-dispatcher.d.ts","sourceRoot":"","sources":["../../../src/tools/generate-tests/spec-dispatcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AA4G7F;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE;IACJ,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,gBAAgB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,EACD,SAAS,EAAE,cAAc,EAAE,EAC3B,gBAAgB,EAAE,cAAc,EAAE,EAClC,SAAS,EAAE,QAAQ,EAAE,GACpB;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,CA0QxB"}
|
|
@@ -21,6 +21,9 @@ import { isVisualRegressionProject, generateVisualRegressionTestDefs, generateVi
|
|
|
21
21
|
import { isGraphqlProject, generateGraphqlTestDefs, generateGraphqlTestFiles, } from './generators/graphql-test-generator.js';
|
|
22
22
|
import { isGrpcProject, generateGrpcTestDefs, generateGrpcTestFiles, } from './generators/grpc-test-generator.js';
|
|
23
23
|
import { isWebSocketProject, generateWebSocketTestDefs, generateWebSocketTestFiles, } from './generators/websocket-test-generator.js';
|
|
24
|
+
import { isMicroservicesTestProject, generateMicroservicesTestDefs, generateMicroservicesTestFiles, } from './generators/microservices-test-generator.js';
|
|
25
|
+
import { isDatabaseTestProject, generateDatabaseTestDefs, generateDatabaseTestFiles, } from './generators/database-test-generator.js';
|
|
26
|
+
import { isSecurityTestProject, generateSecurityTestDefs, generateSecurityTestFiles, } from './generators/security-test-generator.js';
|
|
24
27
|
/**
|
|
25
28
|
* Runs all spec-specific test generation dispatchers.
|
|
26
29
|
* Mutates unitTests, integrationTests, testFiles in-place.
|
|
@@ -144,6 +147,24 @@ export function runSpecializedGenerators(args, unitTests, integrationTests, test
|
|
|
144
147
|
integrationTests.push(...wsDefs);
|
|
145
148
|
testFiles.push(...generateWebSocketTestFiles({ title: spec.title, slug }, testDir, testFramework, knowledge.language, testExt, autoGenerate));
|
|
146
149
|
}
|
|
150
|
+
// SPEC-058b: Microservices & Distributed Systems
|
|
151
|
+
if (isMicroservicesTestProject(knowledge)) {
|
|
152
|
+
const msDefs = generateMicroservicesTestDefs(spec.title, testDir, testExt, knowledge);
|
|
153
|
+
integrationTests.push(...msDefs);
|
|
154
|
+
testFiles.push(...generateMicroservicesTestFiles({ title: spec.title, slug }, testDir, testFramework, knowledge.language, testExt, autoGenerate, knowledge));
|
|
155
|
+
}
|
|
156
|
+
// SPEC-058b: Database & Data Layer
|
|
157
|
+
if (isDatabaseTestProject(knowledge)) {
|
|
158
|
+
const dbDefs = generateDatabaseTestDefs(spec.title, testDir, testExt, knowledge);
|
|
159
|
+
integrationTests.push(...dbDefs);
|
|
160
|
+
testFiles.push(...generateDatabaseTestFiles({ title: spec.title, slug }, testDir, testFramework, knowledge.language, testExt, autoGenerate, knowledge));
|
|
161
|
+
}
|
|
162
|
+
// SPEC-058b: Security Testing
|
|
163
|
+
if (isSecurityTestProject(knowledge)) {
|
|
164
|
+
const secDefs = generateSecurityTestDefs(spec.title, testDir, testExt, knowledge);
|
|
165
|
+
integrationTests.push(...secDefs);
|
|
166
|
+
testFiles.push(...generateSecurityTestFiles({ title: spec.title, slug }, testDir, testFramework, knowledge.language, testExt, autoGenerate, knowledge));
|
|
167
|
+
}
|
|
147
168
|
const isApiSpec = spec.target === 'backend' || spec.target === 'fullstack';
|
|
148
169
|
if (isApiSpec) {
|
|
149
170
|
testFiles.push(buildContractTestFile(spec.title, slug, knowledge, autoGenerate));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-dispatcher.js","sourceRoot":"","sources":["../../../src/tools/generate-tests/spec-dispatcher.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,yDAAyD;AACzD,0EAA0E;AAC1E,0DAA0D;AAC1D,2CAA2C;AAG3C,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,6BAA6B,EAC7B,kBAAkB,EAClB,2BAA2B,EAC3B,gBAAgB,GACjB,MAAM,yDAAyD,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AACpG,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,EAC3B,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,iCAAiC,GAClC,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,0CAA0C,CAAC;AAElD;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAQC,EACD,SAA2B,EAC3B,gBAAkC,EAClC,SAAqB;IAErB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAEtF,IAAI,cAAc,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC7D,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC9D,gBAAgB,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC5E,SAAS,CAAC,IAAI,CAAC,GAAG,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,6BAA6B,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACxE,SAAS,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QACjE,gBAAgB,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC/E,SAAS,CAAC,IAAI,CACZ,GAAG,2BAA2B,CAC5B,IAAI,CAAC,KAAK,EACV,IAAI,EACJ,OAAO,EACP,SAAS,CAAC,SAAS,IAAI,SAAS,EAChC,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvD,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC3D,gBAAgB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QACzE,SAAS,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC5D,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QAC7B,SAAS,CAAC,IAAI,CAAC;YACb,IAAI,EAAE,GAAG,OAAO,SAAS,IAAI,cAAc,OAAO,EAAE;YACpD,SAAS,EAAE,aAAa;YACxB,OAAO,EAAE,uBAAuB,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC;YAC/E,KAAK,EAAE,YAAY;SACpB,CAAC,CAAC;IACL,CAAC;IAED,IAAI,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACtE,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC7D,gBAAgB,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC3E,SAAS,CAAC,IAAI,CAAC;YACb,IAAI,EAAE,GAAG,OAAO,oBAAoB,IAAI,cAAc,OAAO,EAAE;YAC/D,SAAS,EAAE,aAAa;YACxB,OAAO,EAAE,uBAAuB,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,IAAI,QAAQ,EAAE,aAAa,CAAC;YAC5F,KAAK,EAAE,YAAY;SACpB,CAAC,CAAC;IACL,CAAC;IAED,IAAI,YAAY,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACrD,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzD,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC5D,gBAAgB,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC1E,IAAI,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,SAAS,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAED,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACxE,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC9D,gBAAgB,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC5E,SAAS,CAAC,IAAI,CACZ,GAAG,sBAAsB,CACvB,IAAI,EACJ,OAAO,EACP,aAAa,EACb,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,IAAI,oBAAoB,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,MAAM,eAAe,GAAG,2BAA2B,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC7F,SAAS,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QACpE,gBAAgB,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAClF,SAAS,CAAC,IAAI,CACZ,GAAG,4BAA4B,CAC7B,IAAI,EACJ,OAAO,EACP,aAAa,EACb,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,IAAI,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,gBAAgB,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,SAAS,CAAC,IAAI,CACZ,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CACzF,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,gBAAgB,CAAC,IAAI,CAAC,GAAG,0BAA0B,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1E,SAAS,CAAC,IAAI,CAAC,GAAG,2BAA2B,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,IAAI,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3D,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC7D,gBAAgB,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC3E,SAAS,CAAC,IAAI,CAAC,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,IAAI,oBAAoB,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,gBAAgB,CAAC,IAAI,CAAC,GAAG,2BAA2B,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3E,SAAS,CAAC,IAAI,CACZ,GAAG,4BAA4B,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CACjF,CAAC;IACJ,CAAC;IAED,IAAI,oBAAoB,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACjE,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC5D,gBAAgB,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC1E,SAAS,CAAC,IAAI,CACZ,GAAG,4BAA4B,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CACjF,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,MAAM,cAAc,GAAG,0BAA0B,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvE,SAAS,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QACnE,gBAAgB,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QACjF,SAAS,CAAC,IAAI,CAAC,GAAG,2BAA2B,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,IAAI,wBAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;QAC9C,MAAM,YAAY,GAAG,2BAA2B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAChE,SAAS,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QACjE,gBAAgB,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QAC/E,SAAS,CAAC,IAAI,CACZ,GAAG,4BAA4B,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAC5F,CAAC;IACJ,CAAC;IAED,IAAI,yBAAyB,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,gCAAgC,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACxE,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;QAC3D,gBAAgB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC;QACzE,SAAS,CAAC,IAAI,CACZ,GAAG,iCAAiC,CAClC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAC3B,OAAO,EACP,aAAa,EACb,SAAS,CAAC,QAAQ,EAClB,OAAO,EACP,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,IAAI,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACtE,gBAAgB,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QAClC,SAAS,CAAC,IAAI,CACZ,GAAG,wBAAwB,CACzB,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAC3B,OAAO,EACP,aAAa,EACb,SAAS,CAAC,QAAQ,EAClB,OAAO,EACP,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpE,gBAAgB,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QACnC,SAAS,CAAC,IAAI,CACZ,GAAG,qBAAqB,CACtB,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAC3B,OAAO,EACP,aAAa,EACb,SAAS,CAAC,QAAQ,EAClB,OAAO,EACP,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,IAAI,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,yBAAyB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,gBAAgB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;QACjC,SAAS,CAAC,IAAI,CACZ,GAAG,0BAA0B,CAC3B,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAC3B,OAAO,EACP,aAAa,EACb,SAAS,CAAC,QAAQ,EAClB,OAAO,EACP,YAAY,CACb,CACF,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC;IAC3E,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;QACjF,SAAS,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
|
|
1
|
+
{"version":3,"file":"spec-dispatcher.js","sourceRoot":"","sources":["../../../src/tools/generate-tests/spec-dispatcher.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specforge-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "SpecForge — MCP Server for Spec Driven Development. Manages specs, estimations, reverse engineering, and auto-learning across any language/framework.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|