@securecode-ai/mcp 0.5.5 → 0.5.6

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 (185) hide show
  1. package/dist/api/types.d.ts +7 -0
  2. package/dist/approval/auditLog.d.ts +1 -1
  3. package/dist/approval/auditLog.js +11 -3
  4. package/dist/approval/auditLog.js.map +1 -1
  5. package/dist/approval/broker.d.ts +7 -2
  6. package/dist/approval/broker.js +239 -110
  7. package/dist/approval/broker.js.map +1 -1
  8. package/dist/approval/policy.d.ts +10 -0
  9. package/dist/approval/policy.js +104 -0
  10. package/dist/approval/policy.js.map +1 -0
  11. package/dist/approval/types.d.ts +11 -2
  12. package/dist/approval/types.js +10 -1
  13. package/dist/approval/types.js.map +1 -1
  14. package/dist/attack/agentScanExecutor.d.ts +35 -1
  15. package/dist/attack/agentScanExecutor.js +405 -76
  16. package/dist/attack/agentScanExecutor.js.map +1 -1
  17. package/dist/attack/agentScanLoop.d.ts +20 -0
  18. package/dist/attack/agentScanLoop.js +1264 -60
  19. package/dist/attack/agentScanLoop.js.map +1 -1
  20. package/dist/attack/agentScanProtocol.d.ts +382 -6
  21. package/dist/attack/agentScanProtocol.js +110 -4
  22. package/dist/attack/agentScanProtocol.js.map +1 -1
  23. package/dist/attack/agentTrace.d.ts +73 -0
  24. package/dist/attack/agentTrace.js +228 -0
  25. package/dist/attack/agentTrace.js.map +1 -0
  26. package/dist/attack/architectureScoutExecutor.d.ts +18 -0
  27. package/dist/attack/architectureScoutExecutor.js +211 -0
  28. package/dist/attack/architectureScoutExecutor.js.map +1 -0
  29. package/dist/attack/architectureScoutLoop.d.ts +36 -0
  30. package/dist/attack/architectureScoutLoop.js +403 -0
  31. package/dist/attack/architectureScoutLoop.js.map +1 -0
  32. package/dist/attack/architectureScoutProtocol.d.ts +209 -0
  33. package/dist/attack/architectureScoutProtocol.js +47 -0
  34. package/dist/attack/architectureScoutProtocol.js.map +1 -0
  35. package/dist/attack/candidateStore.d.ts +95 -0
  36. package/dist/attack/candidateStore.js +231 -0
  37. package/dist/attack/candidateStore.js.map +1 -0
  38. package/dist/attack/evidenceLedger.d.ts +67 -0
  39. package/dist/attack/evidenceLedger.js +192 -0
  40. package/dist/attack/evidenceLedger.js.map +1 -0
  41. package/dist/attack/finishGate.d.ts +62 -0
  42. package/dist/attack/finishGate.js +209 -0
  43. package/dist/attack/finishGate.js.map +1 -0
  44. package/dist/attack/fixCodeMerge.d.ts +27 -0
  45. package/dist/attack/fixCodeMerge.js +42 -0
  46. package/dist/attack/fixCodeMerge.js.map +1 -0
  47. package/dist/attack/fixVerifyLoop.d.ts +55 -0
  48. package/dist/attack/fixVerifyLoop.js +187 -0
  49. package/dist/attack/fixVerifyLoop.js.map +1 -0
  50. package/dist/attack/investigationProfiles.d.ts +36 -0
  51. package/dist/attack/investigationProfiles.js +144 -0
  52. package/dist/attack/investigationProfiles.js.map +1 -0
  53. package/dist/attack/investigationState.d.ts +227 -0
  54. package/dist/attack/investigationState.js +666 -0
  55. package/dist/attack/investigationState.js.map +1 -0
  56. package/dist/attack/mutationOperators.d.ts +22 -0
  57. package/dist/attack/mutationOperators.js +170 -0
  58. package/dist/attack/mutationOperators.js.map +1 -0
  59. package/dist/attack/mutationTest.d.ts +33 -0
  60. package/dist/attack/mutationTest.js +110 -0
  61. package/dist/attack/mutationTest.js.map +1 -0
  62. package/dist/attack/proofGate.d.ts +20 -0
  63. package/dist/attack/proofGate.js +104 -0
  64. package/dist/attack/proofGate.js.map +1 -0
  65. package/dist/attack/proofTypes.d.ts +57 -0
  66. package/dist/attack/proofTypes.js +32 -0
  67. package/dist/attack/proofTypes.js.map +1 -0
  68. package/dist/attack/protocolValidator.d.ts +50 -0
  69. package/dist/attack/protocolValidator.js +427 -0
  70. package/dist/attack/protocolValidator.js.map +1 -0
  71. package/dist/attack/qualityMetrics.d.ts +133 -0
  72. package/dist/attack/qualityMetrics.js +226 -0
  73. package/dist/attack/qualityMetrics.js.map +1 -0
  74. package/dist/attack/scanScheduler.d.ts +52 -0
  75. package/dist/attack/scanScheduler.js +265 -0
  76. package/dist/attack/scanScheduler.js.map +1 -0
  77. package/dist/attack/scanState.d.ts +58 -0
  78. package/dist/attack/scanState.js +102 -0
  79. package/dist/attack/scanState.js.map +1 -0
  80. package/dist/attack/searchIntent.d.ts +16 -0
  81. package/dist/attack/searchIntent.js +57 -0
  82. package/dist/attack/searchIntent.js.map +1 -0
  83. package/dist/attack/verifyLoop.d.ts +43 -0
  84. package/dist/attack/verifyLoop.js +314 -14
  85. package/dist/attack/verifyLoop.js.map +1 -1
  86. package/dist/attack/workItem.d.ts +57 -0
  87. package/dist/attack/workItem.js +225 -0
  88. package/dist/attack/workItem.js.map +1 -0
  89. package/dist/audit/findingReviewQueue.d.ts +109 -0
  90. package/dist/audit/findingReviewQueue.js +335 -0
  91. package/dist/audit/findingReviewQueue.js.map +1 -0
  92. package/dist/audit/scanAuditLog.d.ts +160 -0
  93. package/dist/audit/scanAuditLog.js +404 -0
  94. package/dist/audit/scanAuditLog.js.map +1 -0
  95. package/dist/dependency/dependencyChecker.js +35 -9
  96. package/dist/dependency/dependencyChecker.js.map +1 -1
  97. package/dist/dependency/exploitPriority.d.ts +33 -0
  98. package/dist/dependency/exploitPriority.js +78 -0
  99. package/dist/dependency/exploitPriority.js.map +1 -0
  100. package/dist/dependency/finding.d.ts +16 -0
  101. package/dist/dependency/osvClient.js +2 -0
  102. package/dist/dependency/osvClient.js.map +1 -1
  103. package/dist/dependency/types.d.ts +12 -1
  104. package/dist/mcp/server.js +13 -2
  105. package/dist/mcp/server.js.map +1 -1
  106. package/dist/mcp/tools.d.ts +1 -0
  107. package/dist/mcp/tools.js +127 -6
  108. package/dist/mcp/tools.js.map +1 -1
  109. package/dist/project-map/agentMemory.d.ts +83 -1
  110. package/dist/project-map/agentMemory.js +197 -7
  111. package/dist/project-map/agentMemory.js.map +1 -1
  112. package/dist/project-map/architectureContext.d.ts +202 -0
  113. package/dist/project-map/architectureContext.js +421 -0
  114. package/dist/project-map/architectureContext.js.map +1 -0
  115. package/dist/project-map/blastRadius.d.ts +54 -0
  116. package/dist/project-map/blastRadius.js +196 -0
  117. package/dist/project-map/blastRadius.js.map +1 -0
  118. package/dist/project-map/callGraphExtractor.d.ts +13 -0
  119. package/dist/project-map/callGraphExtractor.js +222 -0
  120. package/dist/project-map/callGraphExtractor.js.map +1 -0
  121. package/dist/project-map/capabilityRegistry.d.ts +46 -0
  122. package/dist/project-map/capabilityRegistry.js +91 -0
  123. package/dist/project-map/capabilityRegistry.js.map +1 -0
  124. package/dist/project-map/findTests.d.ts +29 -0
  125. package/dist/project-map/findTests.js +236 -0
  126. package/dist/project-map/findTests.js.map +1 -0
  127. package/dist/project-map/handlerInventory.d.ts +112 -0
  128. package/dist/project-map/handlerInventory.js +184 -0
  129. package/dist/project-map/handlerInventory.js.map +1 -0
  130. package/dist/project-map/implementationResolver.d.ts +43 -0
  131. package/dist/project-map/implementationResolver.js +217 -0
  132. package/dist/project-map/implementationResolver.js.map +1 -0
  133. package/dist/project-map/mapContext.d.ts +6 -1
  134. package/dist/project-map/mapContext.js +1 -0
  135. package/dist/project-map/mapContext.js.map +1 -1
  136. package/dist/project-map/scanCache.d.ts +57 -3
  137. package/dist/project-map/scanCache.js +61 -2
  138. package/dist/project-map/scanCache.js.map +1 -1
  139. package/dist/project-map/symbolIndex.d.ts +39 -0
  140. package/dist/project-map/symbolIndex.js +385 -0
  141. package/dist/project-map/symbolIndex.js.map +1 -0
  142. package/dist/tooling/agentEvalScoring.d.ts +77 -0
  143. package/dist/tooling/agentEvalScoring.js +140 -0
  144. package/dist/tooling/agentEvalScoring.js.map +1 -0
  145. package/dist/tooling/agentRegression.d.ts +53 -0
  146. package/dist/tooling/agentRegression.js +99 -0
  147. package/dist/tooling/agentRegression.js.map +1 -0
  148. package/dist/tools/agentScan.d.ts +69 -0
  149. package/dist/tools/agentScan.js +702 -43
  150. package/dist/tools/agentScan.js.map +1 -1
  151. package/dist/tools/findingReviewTools.d.ts +22 -0
  152. package/dist/tools/findingReviewTools.js +121 -0
  153. package/dist/tools/findingReviewTools.js.map +1 -0
  154. package/dist/tools/fix.js +1 -1
  155. package/dist/tools/fix.js.map +1 -1
  156. package/dist/tools/map.js +191 -1
  157. package/dist/tools/map.js.map +1 -1
  158. package/dist/tools/runTests.d.ts +2 -0
  159. package/dist/tools/runTests.js +29 -0
  160. package/dist/tools/runTests.js.map +1 -0
  161. package/dist/utils/effectMock.d.ts +1 -0
  162. package/dist/utils/effectMock.js +162 -0
  163. package/dist/utils/effectMock.js.map +1 -0
  164. package/dist/utils/gitContext.d.ts +26 -0
  165. package/dist/utils/gitContext.js +317 -0
  166. package/dist/utils/gitContext.js.map +1 -0
  167. package/dist/utils/localTestRunner.d.ts +57 -2
  168. package/dist/utils/localTestRunner.js +122 -115
  169. package/dist/utils/localTestRunner.js.map +1 -1
  170. package/dist/utils/securityConfig.d.ts +17 -0
  171. package/dist/utils/securityConfig.js +192 -0
  172. package/dist/utils/securityConfig.js.map +1 -0
  173. package/dist/utils/testCommandPolicy.d.ts +36 -0
  174. package/dist/utils/testCommandPolicy.js +252 -0
  175. package/dist/utils/testCommandPolicy.js.map +1 -0
  176. package/dist/utils/testRunner.d.ts +56 -0
  177. package/dist/utils/testRunner.js +246 -0
  178. package/dist/utils/testRunner.js.map +1 -0
  179. package/dist/utils/testSafety.d.ts +40 -2
  180. package/dist/utils/testSafety.js +205 -26
  181. package/dist/utils/testSafety.js.map +1 -1
  182. package/dist/utils/verificationSandbox.d.ts +113 -0
  183. package/dist/utils/verificationSandbox.js +656 -0
  184. package/dist/utils/verificationSandbox.js.map +1 -0
  185. package/package.json +1 -1
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ /**
3
+ * Test discovery — finds test files that exercise a source file or symbol.
4
+ *
5
+ * Two strategies:
6
+ * 1. Naming convention: derive candidate test file paths from the source
7
+ * file (src/foo.ts → tests/foo.test.ts, src/foo.test.ts, etc.)
8
+ * 2. Symbol reference: if a symbol name is provided, search all test files
9
+ * in the workspace for references to that symbol.
10
+ *
11
+ * Returns ranked results with match type and confidence.
12
+ *
13
+ * Security:
14
+ * - All paths workspace-confined via resolveWorkspacePath
15
+ * - Output truncated to 16KB
16
+ * - No file contents returned — only paths and matched lines
17
+ */
18
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ var desc = Object.getOwnPropertyDescriptor(m, k);
21
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
22
+ desc = { enumerable: true, get: function() { return m[k]; } };
23
+ }
24
+ Object.defineProperty(o, k2, desc);
25
+ }) : (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ o[k2] = m[k];
28
+ }));
29
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
30
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
31
+ }) : function(o, v) {
32
+ o["default"] = v;
33
+ });
34
+ var __importStar = (this && this.__importStar) || (function () {
35
+ var ownKeys = function(o) {
36
+ ownKeys = Object.getOwnPropertyNames || function (o) {
37
+ var ar = [];
38
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
39
+ return ar;
40
+ };
41
+ return ownKeys(o);
42
+ };
43
+ return function (mod) {
44
+ if (mod && mod.__esModule) return mod;
45
+ var result = {};
46
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
47
+ __setModuleDefault(result, mod);
48
+ return result;
49
+ };
50
+ })();
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.findTests = findTests;
53
+ const fs = __importStar(require("fs"));
54
+ const path = __importStar(require("path"));
55
+ const files_1 = require("../utils/files");
56
+ const searchCode_1 = require("../utils/searchCode");
57
+ const MAX_RESULTS = 30;
58
+ const MAX_PREVIEW_LENGTH = 120;
59
+ function getBaseName(filePath) {
60
+ const ext = path.extname(filePath);
61
+ return path.basename(filePath, ext);
62
+ }
63
+ function getExt(filePath) {
64
+ return path.extname(filePath).toLowerCase();
65
+ }
66
+ function isTestFile(fileName) {
67
+ const lower = fileName.toLowerCase();
68
+ return (lower.endsWith('.test.ts') ||
69
+ lower.endsWith('.test.tsx') ||
70
+ lower.endsWith('.test.js') ||
71
+ lower.endsWith('.test.jsx') ||
72
+ lower.endsWith('.test.mjs') ||
73
+ lower.endsWith('.test.cjs') ||
74
+ lower.endsWith('.spec.ts') ||
75
+ lower.endsWith('.spec.tsx') ||
76
+ lower.endsWith('.spec.js') ||
77
+ lower.endsWith('.spec.jsx') ||
78
+ lower.endsWith('.spec.mjs') ||
79
+ lower.endsWith('.spec.cjs') ||
80
+ lower.startsWith('test_') && lower.endsWith('.py') ||
81
+ lower.endsWith('_test.py'));
82
+ }
83
+ function deriveTestCandidates(filePath) {
84
+ const ext = getExt(filePath);
85
+ const baseName = getBaseName(filePath);
86
+ const dir = path.dirname(filePath);
87
+ const candidates = [];
88
+ if (ext === '.py') {
89
+ const pyTestName = `test_${baseName}.py`;
90
+ const dirs = ['tests', 'test', dir, 'src', ''];
91
+ for (const d of dirs) {
92
+ candidates.push(d ? path.join(d, pyTestName) : pyTestName);
93
+ }
94
+ candidates.push(path.join(dir, `test_${baseName}.py`));
95
+ return candidates;
96
+ }
97
+ const tsExts = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
98
+ const testDirs = ['tests', 'test', '__tests__', '__test__', 'spec', ''];
99
+ const sameDir = dir;
100
+ for (const testExt of tsExts) {
101
+ for (const suffix of ['.test', '.spec']) {
102
+ for (const d of testDirs) {
103
+ candidates.push(d ? path.join(d, baseName + suffix + testExt) : baseName + suffix + testExt);
104
+ }
105
+ candidates.push(path.join(sameDir, baseName + suffix + testExt));
106
+ }
107
+ }
108
+ return candidates;
109
+ }
110
+ function findTestsByNaming(workspaceRoot, filePath) {
111
+ const candidates = deriveTestCandidates(filePath);
112
+ const results = [];
113
+ const seen = new Set();
114
+ for (const candidate of candidates) {
115
+ try {
116
+ const abs = (0, files_1.resolveWorkspacePath)(workspaceRoot, candidate);
117
+ if (fs.existsSync(abs)) {
118
+ const rel = path.relative(workspaceRoot, abs).replace(/\\/g, '/');
119
+ if (seen.has(rel))
120
+ continue;
121
+ seen.add(rel);
122
+ results.push({
123
+ filePath: rel,
124
+ matchType: 'naming',
125
+ confidence: 0.9,
126
+ });
127
+ }
128
+ }
129
+ catch {
130
+ // path outside workspace — skip
131
+ }
132
+ }
133
+ return results;
134
+ }
135
+ async function findTestsBySymbol(workspaceRoot, symbol, existing) {
136
+ const results = [];
137
+ const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
138
+ const pattern = `\\b${escaped}\\b`;
139
+ const testGlobs = [
140
+ '*.test.ts', '*.test.tsx', '*.test.js', '*.test.jsx',
141
+ '*.test.mjs', '*.test.cjs',
142
+ '*.spec.ts', '*.spec.tsx', '*.spec.js', '*.spec.jsx',
143
+ '*.spec.mjs', '*.spec.cjs',
144
+ 'test_*.py', '*_test.py',
145
+ ];
146
+ const byFile = new Map();
147
+ for (const glob of testGlobs) {
148
+ try {
149
+ const result = await (0, searchCode_1.searchCode)(workspaceRoot, pattern, glob);
150
+ for (const hit of result.hits || []) {
151
+ const fileName = path.basename(hit.path);
152
+ if (!isTestFile(fileName))
153
+ continue;
154
+ const existing_ = byFile.get(hit.path);
155
+ if (existing_) {
156
+ if (existing_.lines.length < 5) {
157
+ existing_.lines.push(hit.line);
158
+ existing_.previews.push(hit.text.slice(0, MAX_PREVIEW_LENGTH));
159
+ }
160
+ }
161
+ else {
162
+ byFile.set(hit.path, {
163
+ lines: [hit.line],
164
+ previews: [hit.text.slice(0, MAX_PREVIEW_LENGTH)],
165
+ });
166
+ }
167
+ }
168
+ }
169
+ catch {
170
+ // search failed for this glob — continue
171
+ }
172
+ }
173
+ for (const [filePath, { lines, previews }] of byFile) {
174
+ if (existing.has(filePath))
175
+ continue;
176
+ results.push({
177
+ filePath,
178
+ matchType: 'symbol',
179
+ confidence: 0.7,
180
+ matchedLines: lines,
181
+ matchedPreviews: previews,
182
+ });
183
+ }
184
+ return results;
185
+ }
186
+ async function findTests(workspaceRoot, filePath, symbol) {
187
+ try {
188
+ (0, files_1.resolveWorkspacePath)(workspaceRoot, filePath);
189
+ }
190
+ catch (e) {
191
+ return `Error: ${e.message}`;
192
+ }
193
+ const parts = [];
194
+ if (!fs.existsSync((0, files_1.resolveWorkspacePath)(workspaceRoot, filePath))) {
195
+ return `Source file not found: ${filePath}`;
196
+ }
197
+ const namingResults = findTestsByNaming(workspaceRoot, filePath);
198
+ const namingPaths = new Set(namingResults.map(r => r.filePath));
199
+ let symbolResults = [];
200
+ if (symbol) {
201
+ symbolResults = await findTestsBySymbol(workspaceRoot, symbol, namingPaths);
202
+ }
203
+ const allResults = [...namingResults, ...symbolResults].slice(0, MAX_RESULTS);
204
+ if (allResults.length === 0) {
205
+ const symMsg = symbol ? ` referencing "${symbol}"` : '';
206
+ return `No test files found for ${filePath}${symMsg}.`;
207
+ }
208
+ const symMsg = symbol ? ` referencing "${symbol}"` : '';
209
+ parts.push(`Tests for ${filePath}${symMsg} (${allResults.length} found):`);
210
+ parts.push('');
211
+ const naming = allResults.filter(r => r.matchType === 'naming');
212
+ const bySymbol = allResults.filter(r => r.matchType === 'symbol');
213
+ if (naming.length > 0) {
214
+ parts.push('By naming convention:');
215
+ for (const r of naming) {
216
+ parts.push(` ${r.filePath} (confidence ${r.confidence})`);
217
+ }
218
+ parts.push('');
219
+ }
220
+ if (bySymbol.length > 0) {
221
+ parts.push(`By symbol reference "${symbol}":`);
222
+ for (const r of bySymbol) {
223
+ const lines = r.matchedLines || [];
224
+ const previews = r.matchedPreviews || [];
225
+ const lineSummary = lines.length === 1
226
+ ? `:${lines[0]}`
227
+ : `:${lines[0]} (+${lines.length - 1} more)`;
228
+ parts.push(` ${r.filePath}${lineSummary} (confidence ${r.confidence})`);
229
+ for (let i = 0; i < Math.min(lines.length, 3); i++) {
230
+ parts.push(` L${lines[i]}: ${previews[i]}`);
231
+ }
232
+ }
233
+ }
234
+ return parts.join('\n');
235
+ }
236
+ //# sourceMappingURL=findTests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findTests.js","sourceRoot":"","sources":["../../src/project-map/findTests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Handler inventory — discovers and tracks HTTP handlers, RPC methods,
3
+ * auth operations, and event handlers in a target file.
4
+ *
5
+ * A handler is "reviewed" when its source range was delivered AND its
6
+ * relevant authentication/authorization path was inspected. A handler
7
+ * is NOT reviewed because it appeared in a function map or search result.
8
+ */
9
+ import type { LineRange } from '../attack/investigationState';
10
+ export type HandlerKind = 'http-handler' | 'rpc-method' | 'auth-operation' | 'event-handler';
11
+ export interface HandlerInventoryItem {
12
+ id: string;
13
+ filePath: string;
14
+ symbol?: string;
15
+ range: LineRange;
16
+ route?: string;
17
+ method?: string;
18
+ kind: HandlerKind;
19
+ securitySensitive: boolean;
20
+ reviewed: boolean;
21
+ evidenceRefs: string[];
22
+ }
23
+ export declare class HandlerInventory {
24
+ private handlers;
25
+ /**
26
+ * Add a discovered handler to the inventory.
27
+ */
28
+ add(input: Omit<HandlerInventoryItem, 'id' | 'reviewed' | 'evidenceRefs'>): HandlerInventoryItem;
29
+ /**
30
+ * Add handlers from discovered endpoints (HTTP route handlers).
31
+ */
32
+ addFromEndpoints(endpoints: {
33
+ method: string;
34
+ path: string;
35
+ file: string;
36
+ line: number;
37
+ }[], filePath: string): void;
38
+ /**
39
+ * Add RPC methods from search results (e.g., WebSocket message handlers).
40
+ */
41
+ addRpcMethods(methods: {
42
+ symbol: string;
43
+ line: number;
44
+ filePath: string;
45
+ }[]): void;
46
+ /**
47
+ * Mark a handler as reviewed by linking evidence to it.
48
+ */
49
+ addEvidence(handlerId: string, evidenceRef: string): void;
50
+ /**
51
+ * Mark a handler as reviewed explicitly (when source range was delivered
52
+ * AND relevant auth/policy evidence was recorded).
53
+ */
54
+ markReviewed(handlerId: string): void;
55
+ /**
56
+ * Check if a handler's source range was covered by an actual read.
57
+ */
58
+ isRangeCovered(handler: HandlerInventoryItem, coveredRanges: LineRange[]): boolean;
59
+ /**
60
+ * Update a handler's reviewed status based on evidence and coverage.
61
+ */
62
+ private updateReviewedStatus;
63
+ /**
64
+ * Get all handlers in the inventory.
65
+ */
66
+ getAll(): HandlerInventoryItem[];
67
+ /**
68
+ * Get the number of handlers in the inventory.
69
+ */
70
+ size(): number;
71
+ /**
72
+ * Get handlers for a specific file.
73
+ */
74
+ getForFile(filePath: string): HandlerInventoryItem[];
75
+ /**
76
+ * Get all unreviewed handlers.
77
+ */
78
+ getUnreviewed(): HandlerInventoryItem[];
79
+ /**
80
+ * Get all reviewed handlers.
81
+ */
82
+ getReviewed(): HandlerInventoryItem[];
83
+ /**
84
+ * Check if all handlers have been reviewed.
85
+ */
86
+ allReviewed(): boolean;
87
+ /**
88
+ * Get the count of security-sensitive unreviewed handlers.
89
+ */
90
+ getUnreviewedSensitiveCount(): number;
91
+ /**
92
+ * Get unreviewed handlers sorted by line number for efficient reading.
93
+ */
94
+ getUnreviewedSorted(): HandlerInventoryItem[];
95
+ /**
96
+ * Get the next unreviewed handler's range, useful for scheduling reads.
97
+ */
98
+ getNextUnreviewedRange(): LineRange | null;
99
+ /**
100
+ * Snapshot for audit/tracing.
101
+ */
102
+ snapshot(): {
103
+ total: number;
104
+ reviewed: number;
105
+ unreviewed: number;
106
+ sensitive: number;
107
+ };
108
+ /**
109
+ * Clear the inventory (for tests).
110
+ */
111
+ clear(): void;
112
+ }
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ /**
3
+ * Handler inventory — discovers and tracks HTTP handlers, RPC methods,
4
+ * auth operations, and event handlers in a target file.
5
+ *
6
+ * A handler is "reviewed" when its source range was delivered AND its
7
+ * relevant authentication/authorization path was inspected. A handler
8
+ * is NOT reviewed because it appeared in a function map or search result.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.HandlerInventory = void 0;
12
+ let handlerIdCounter = 0;
13
+ class HandlerInventory {
14
+ handlers = new Map();
15
+ /**
16
+ * Add a discovered handler to the inventory.
17
+ */
18
+ add(input) {
19
+ const id = `handler-${++handlerIdCounter}`;
20
+ const item = {
21
+ ...input,
22
+ id,
23
+ reviewed: false,
24
+ evidenceRefs: [],
25
+ };
26
+ this.handlers.set(id, item);
27
+ return item;
28
+ }
29
+ /**
30
+ * Add handlers from discovered endpoints (HTTP route handlers).
31
+ */
32
+ addFromEndpoints(endpoints, filePath) {
33
+ for (const ep of endpoints) {
34
+ const normalizedFile = ep.file.replace(/\\/g, '/').toLowerCase();
35
+ const targetFile = filePath.replace(/\\/g, '/').toLowerCase();
36
+ if (normalizedFile !== targetFile && !normalizedFile.includes(targetFile))
37
+ continue;
38
+ this.add({
39
+ filePath: ep.file,
40
+ symbol: ep.method.toLowerCase(),
41
+ range: { start: ep.line, end: ep.line },
42
+ route: ep.path,
43
+ method: ep.method,
44
+ kind: 'http-handler',
45
+ securitySensitive: true,
46
+ });
47
+ }
48
+ }
49
+ /**
50
+ * Add RPC methods from search results (e.g., WebSocket message handlers).
51
+ */
52
+ addRpcMethods(methods) {
53
+ for (const m of methods) {
54
+ this.add({
55
+ filePath: m.filePath,
56
+ symbol: m.symbol,
57
+ range: { start: m.line, end: m.line },
58
+ kind: 'rpc-method',
59
+ securitySensitive: true,
60
+ });
61
+ }
62
+ }
63
+ /**
64
+ * Mark a handler as reviewed by linking evidence to it.
65
+ */
66
+ addEvidence(handlerId, evidenceRef) {
67
+ const handler = this.handlers.get(handlerId);
68
+ if (handler && !handler.evidenceRefs.includes(evidenceRef)) {
69
+ handler.evidenceRefs.push(evidenceRef);
70
+ this.updateReviewedStatus(handlerId);
71
+ }
72
+ }
73
+ /**
74
+ * Mark a handler as reviewed explicitly (when source range was delivered
75
+ * AND relevant auth/policy evidence was recorded).
76
+ */
77
+ markReviewed(handlerId) {
78
+ const handler = this.handlers.get(handlerId);
79
+ if (handler) {
80
+ handler.reviewed = true;
81
+ }
82
+ }
83
+ /**
84
+ * Check if a handler's source range was covered by an actual read.
85
+ */
86
+ isRangeCovered(handler, coveredRanges) {
87
+ return coveredRanges.some(r => r.start <= handler.range.start && r.end >= handler.range.end);
88
+ }
89
+ /**
90
+ * Update a handler's reviewed status based on evidence and coverage.
91
+ */
92
+ updateReviewedStatus(handlerId) {
93
+ const handler = this.handlers.get(handlerId);
94
+ if (!handler || handler.reviewed)
95
+ return;
96
+ // A handler is reviewed when it has at least 2 evidence refs:
97
+ // typically source-range + policy/guard/flow evidence
98
+ if (handler.evidenceRefs.length >= 2) {
99
+ handler.reviewed = true;
100
+ }
101
+ }
102
+ /**
103
+ * Get all handlers in the inventory.
104
+ */
105
+ getAll() {
106
+ return [...this.handlers.values()];
107
+ }
108
+ /**
109
+ * Get the number of handlers in the inventory.
110
+ */
111
+ size() {
112
+ return this.handlers.size;
113
+ }
114
+ /**
115
+ * Get handlers for a specific file.
116
+ */
117
+ getForFile(filePath) {
118
+ const normalized = filePath.replace(/\\/g, '/').toLowerCase();
119
+ return [...this.handlers.values()].filter(h => h.filePath.replace(/\\/g, '/').toLowerCase() === normalized);
120
+ }
121
+ /**
122
+ * Get all unreviewed handlers.
123
+ */
124
+ getUnreviewed() {
125
+ return [...this.handlers.values()].filter(h => !h.reviewed);
126
+ }
127
+ /**
128
+ * Get all reviewed handlers.
129
+ */
130
+ getReviewed() {
131
+ return [...this.handlers.values()].filter(h => h.reviewed);
132
+ }
133
+ /**
134
+ * Check if all handlers have been reviewed.
135
+ */
136
+ allReviewed() {
137
+ const all = this.getAll();
138
+ if (all.length === 0)
139
+ return true; // No handlers to review
140
+ return all.every(h => h.reviewed);
141
+ }
142
+ /**
143
+ * Get the count of security-sensitive unreviewed handlers.
144
+ */
145
+ getUnreviewedSensitiveCount() {
146
+ return this.getUnreviewed().filter(h => h.securitySensitive).length;
147
+ }
148
+ /**
149
+ * Get unreviewed handlers sorted by line number for efficient reading.
150
+ */
151
+ getUnreviewedSorted() {
152
+ return this.getUnreviewed().sort((a, b) => a.range.start - b.range.start);
153
+ }
154
+ /**
155
+ * Get the next unreviewed handler's range, useful for scheduling reads.
156
+ */
157
+ getNextUnreviewedRange() {
158
+ const sorted = this.getUnreviewedSorted();
159
+ if (sorted.length === 0)
160
+ return null;
161
+ const first = sorted[0];
162
+ return first.range;
163
+ }
164
+ /**
165
+ * Snapshot for audit/tracing.
166
+ */
167
+ snapshot() {
168
+ const all = this.getAll();
169
+ return {
170
+ total: all.length,
171
+ reviewed: all.filter(h => h.reviewed).length,
172
+ unreviewed: all.filter(h => !h.reviewed).length,
173
+ sensitive: all.filter(h => h.securitySensitive).length,
174
+ };
175
+ }
176
+ /**
177
+ * Clear the inventory (for tests).
178
+ */
179
+ clear() {
180
+ this.handlers.clear();
181
+ }
182
+ }
183
+ exports.HandlerInventory = HandlerInventory;
184
+ //# sourceMappingURL=handlerInventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlerInventory.js","sourceRoot":"","sources":["../../src/project-map/handlerInventory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Implementation resolver — generic interface-to-implementation redirection.
3
+ *
4
+ * When the agent scans an interface, type declaration, or service contract,
5
+ * the resolver finds the actual implementation files and symbols so the
6
+ * investigation can continue on real code, not signatures.
7
+ *
8
+ * Matching strategies (all generic, no project-specific logic):
9
+ * - TypeScript interface → classes that implement it
10
+ * - Effect service declaration → live layer implementations
11
+ * - Abstract classes → subclasses
12
+ * - Exported type → functions returning the type
13
+ * - Route contracts → handler registrations
14
+ * - Python protocols/abstract classes → implementations (when symbol data supports it)
15
+ */
16
+ export interface EvidenceLocation {
17
+ filePath: string;
18
+ line: number;
19
+ symbol?: string;
20
+ }
21
+ export interface ImplementationResolution {
22
+ contractLocations: EvidenceLocation[];
23
+ implementationLocations: EvidenceLocation[];
24
+ callSites: EvidenceLocation[];
25
+ unresolved: boolean;
26
+ description: string;
27
+ }
28
+ /**
29
+ * Resolve implementations for a symbol in a contract/interface file.
30
+ *
31
+ * This is a generic search — it uses workspace-wide code search to find
32
+ * patterns that indicate implementation of the given symbol.
33
+ */
34
+ export declare function resolveImplementation(workspaceRoot: string, filePath: string, symbol: string): Promise<ImplementationResolution>;
35
+ /**
36
+ * Format an implementation resolution for the agent transcript.
37
+ */
38
+ export declare function formatImplementationResolution(resolution: ImplementationResolution): string;
39
+ /**
40
+ * Check if a file looks like a contract/interface/type declaration only
41
+ * (has no runtime implementation). Generic heuristic, not project-specific.
42
+ */
43
+ export declare function looksLikeContractOnly(content: string): boolean;