@kernlang/review 3.3.8 → 3.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/cache.js +1 -1
- package/dist/call-graph.d.ts +10 -0
- package/dist/call-graph.js +138 -9
- package/dist/call-graph.js.map +1 -1
- package/dist/concept-rules/auth-drift.js +2 -0
- package/dist/concept-rules/auth-drift.js.map +1 -1
- package/dist/concept-rules/auth-propagation-drift.d.ts +10 -0
- package/dist/concept-rules/auth-propagation-drift.js +85 -0
- package/dist/concept-rules/auth-propagation-drift.js.map +1 -0
- package/dist/concept-rules/body-shape-drift.d.ts +32 -0
- package/dist/concept-rules/body-shape-drift.js +98 -0
- package/dist/concept-rules/body-shape-drift.js.map +1 -0
- package/dist/concept-rules/contract-drift.js +3 -1
- package/dist/concept-rules/contract-drift.js.map +1 -1
- package/dist/concept-rules/contract-method-drift.js +2 -0
- package/dist/concept-rules/contract-method-drift.js.map +1 -1
- package/dist/concept-rules/cross-stack-utils.d.ts +24 -0
- package/dist/concept-rules/cross-stack-utils.js +123 -29
- package/dist/concept-rules/cross-stack-utils.js.map +1 -1
- package/dist/concept-rules/index.d.ts +4 -2
- package/dist/concept-rules/index.js +22 -3
- package/dist/concept-rules/index.js.map +1 -1
- package/dist/concept-rules/mutation-without-idempotency.d.ts +10 -0
- package/dist/concept-rules/mutation-without-idempotency.js +47 -0
- package/dist/concept-rules/mutation-without-idempotency.js.map +1 -0
- package/dist/concept-rules/request-validation-drift.d.ts +11 -0
- package/dist/concept-rules/request-validation-drift.js +99 -0
- package/dist/concept-rules/request-validation-drift.js.map +1 -0
- package/dist/concept-rules/root-cause.d.ts +4 -0
- package/dist/concept-rules/root-cause.js +31 -0
- package/dist/concept-rules/root-cause.js.map +1 -0
- package/dist/concept-rules/unbounded-collection-query.d.ts +10 -0
- package/dist/concept-rules/unbounded-collection-query.js +58 -0
- package/dist/concept-rules/unbounded-collection-query.js.map +1 -0
- package/dist/concept-rules/unhandled-api-error-shape.d.ts +10 -0
- package/dist/concept-rules/unhandled-api-error-shape.js +59 -0
- package/dist/concept-rules/unhandled-api-error-shape.js.map +1 -0
- package/dist/default-export.d.ts +41 -0
- package/dist/default-export.js +76 -0
- package/dist/default-export.js.map +1 -0
- package/dist/eval.d.ts +67 -0
- package/dist/eval.js +177 -0
- package/dist/eval.js.map +1 -0
- package/dist/external-tools.js +52 -3
- package/dist/external-tools.js.map +1 -1
- package/dist/file-context.js +32 -13
- package/dist/file-context.js.map +1 -1
- package/dist/file-role.d.ts +6 -0
- package/dist/file-role.js +27 -0
- package/dist/file-role.js.map +1 -1
- package/dist/framework-seeds.d.ts +46 -0
- package/dist/framework-seeds.js +245 -0
- package/dist/framework-seeds.js.map +1 -0
- package/dist/git-env.d.ts +1 -0
- package/dist/git-env.js +25 -0
- package/dist/git-env.js.map +1 -0
- package/dist/graph.js +246 -21
- package/dist/graph.js.map +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +314 -96
- package/dist/index.js.map +1 -1
- package/dist/mappers/ts-concepts.js +730 -1
- package/dist/mappers/ts-concepts.js.map +1 -1
- package/dist/path-canonical.d.ts +34 -0
- package/dist/path-canonical.js +85 -0
- package/dist/path-canonical.js.map +1 -0
- package/dist/policy.d.ts +22 -0
- package/dist/policy.js +47 -0
- package/dist/policy.js.map +1 -0
- package/dist/project-context.d.ts +135 -0
- package/dist/project-context.js +563 -0
- package/dist/project-context.js.map +1 -0
- package/dist/public-api.d.ts +21 -0
- package/dist/public-api.js +17 -2
- package/dist/public-api.js.map +1 -1
- package/dist/python-fallback.d.ts +2 -0
- package/dist/python-fallback.js +506 -0
- package/dist/python-fallback.js.map +1 -0
- package/dist/reporter.js +106 -1
- package/dist/reporter.js.map +1 -1
- package/dist/rule-quality.d.ts +58 -0
- package/dist/rule-quality.js +357 -0
- package/dist/rule-quality.js.map +1 -0
- package/dist/rules/base.js +21 -3
- package/dist/rules/base.js.map +1 -1
- package/dist/rules/dead-code.d.ts +2 -2
- package/dist/rules/dead-code.js +88 -4
- package/dist/rules/dead-code.js.map +1 -1
- package/dist/rules/index.d.ts +22 -0
- package/dist/rules/index.js +72 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/kern-source.d.ts +4 -0
- package/dist/rules/kern-source.js +184 -0
- package/dist/rules/kern-source.js.map +1 -1
- package/dist/rules/react.js +52 -3
- package/dist/rules/react.js.map +1 -1
- package/dist/rules/suggest-kern-primitive.js +0 -1
- package/dist/rules/suggest-kern-primitive.js.map +1 -1
- package/dist/semantic-diff.js +2 -0
- package/dist/semantic-diff.js.map +1 -1
- package/dist/suppression/apply-suppression.js +2 -0
- package/dist/suppression/apply-suppression.js.map +1 -1
- package/dist/suppression/parse-directives.d.ts +13 -5
- package/dist/suppression/parse-directives.js +62 -8
- package/dist/suppression/parse-directives.js.map +1 -1
- package/dist/suppression/types.d.ts +9 -0
- package/dist/suppression/types.js +6 -1
- package/dist/suppression/types.js.map +1 -1
- package/dist/taint-crossfile.js +15 -8
- package/dist/taint-crossfile.js.map +1 -1
- package/dist/telemetry.d.ts +126 -0
- package/dist/telemetry.js +303 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +172 -2
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { createFingerprint } from '../types.js';
|
|
20
20
|
import { API_PATH_RE, CROSS_STACK_HEURISTIC_CONFIDENCE, collectRoutesAcrossGraph, hasMatchingRoute, normalizeClientUrl, } from './cross-stack-utils.js';
|
|
21
|
+
import { apiCallRootCause } from './root-cause.js';
|
|
21
22
|
export function contractDrift(ctx) {
|
|
22
23
|
// Graph mode only — URL correlation is useless within a single file.
|
|
23
24
|
if (!ctx.allConcepts || ctx.allConcepts.size === 0)
|
|
@@ -34,7 +35,7 @@ export function contractDrift(ctx) {
|
|
|
34
35
|
const normalized = normalizeClientUrl(target);
|
|
35
36
|
if (!normalized || !API_PATH_RE.test(normalized))
|
|
36
37
|
continue;
|
|
37
|
-
clientCalls.push({ target, normalizedPath: normalized, node });
|
|
38
|
+
clientCalls.push({ target, normalizedPath: normalized, method: node.payload.method, node });
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
// Rule gate: need at least one route AND one client call, otherwise the
|
|
@@ -58,6 +59,7 @@ export function contractDrift(ctx) {
|
|
|
58
59
|
primarySpan: call.node.primarySpan,
|
|
59
60
|
fingerprint: createFingerprint('contract-drift', call.node.primarySpan.startLine, call.node.primarySpan.startCol),
|
|
60
61
|
confidence: call.node.confidence * CROSS_STACK_HEURISTIC_CONFIDENCE,
|
|
62
|
+
rootCause: apiCallRootCause(call.node, call.normalizedPath, call.method),
|
|
61
63
|
});
|
|
62
64
|
}
|
|
63
65
|
return findings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-drift.js","sourceRoot":"","sources":["../../src/concept-rules/contract-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,WAAW,EACX,gCAAgC,EAChC,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"contract-drift.js","sourceRoot":"","sources":["../../src/concept-rules/contract-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,WAAW,EACX,gCAAgC,EAChC,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AASnD,MAAM,UAAU,aAAa,CAAC,GAAuB;IACnD,qEAAqE;IACrE,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE9D,MAAM,YAAY,GAAG,wBAAwB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAiB,EAAE,CAAC;IAErC,KAAK,MAAM,CAAC,EAAE,UAAU,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QAC7C,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS;gBAAE,SAAS;YAC7G,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YACnC,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,SAAS;YACzC,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC;gBAAE,SAAS;YAC3D,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErE,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,wEAAwE;QACxE,4CAA4C;QAC5C,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,GAAG,CAAC,QAAQ;YAAE,SAAS;QAC1D,IAAI,gBAAgB,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC;YAAE,SAAS;QAElE,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,gBAAgB;YACxB,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,oBAAoB,IAAI,CAAC,MAAM,2KAA2K;YACnN,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;YAClC,WAAW,EAAE,iBAAiB,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;YACjH,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,gCAAgC;YACnE,SAAS,EAAE,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC;SACzE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { createFingerprint } from '../types.js';
|
|
21
21
|
import { API_PATH_RE, CROSS_STACK_EXACT_CONFIDENCE, collectRoutesAcrossGraph, findRoutesAtPath, normalizeClientUrl, } from './cross-stack-utils.js';
|
|
22
|
+
import { apiCallRootCause } from './root-cause.js';
|
|
22
23
|
// Verbs the TS/Python mappers emit for handlers that intentionally accept any
|
|
23
24
|
// method (Express `app.all()` emits `ALL`; `app.use()` emits `undefined`).
|
|
24
25
|
const WILDCARD_METHODS = new Set(['ALL', 'ANY']);
|
|
@@ -69,6 +70,7 @@ export function contractMethodDrift(ctx) {
|
|
|
69
70
|
primarySpan: call.node.primarySpan,
|
|
70
71
|
fingerprint: createFingerprint('contract-method-drift', call.node.primarySpan.startLine, call.node.primarySpan.startCol),
|
|
71
72
|
confidence: call.node.confidence * CROSS_STACK_EXACT_CONFIDENCE,
|
|
73
|
+
rootCause: apiCallRootCause(call.node, call.normalizedPath, call.method, routesAtPath[0]?.node),
|
|
72
74
|
});
|
|
73
75
|
}
|
|
74
76
|
return findings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-method-drift.js","sourceRoot":"","sources":["../../src/concept-rules/contract-method-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,WAAW,EACX,4BAA4B,EAC5B,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"contract-method-drift.js","sourceRoot":"","sources":["../../src/concept-rules/contract-method-drift.ts"],"names":[],"mappings":"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"}
|
|
@@ -84,6 +84,17 @@ export declare function normalizeClientUrl(raw: string): string | undefined;
|
|
|
84
84
|
* behaviour).
|
|
85
85
|
*/
|
|
86
86
|
export declare function findMatchingRoute(clientPath: string, routes: readonly ServerRoute[]): ServerRoute | undefined;
|
|
87
|
+
export declare function findMatchingRouteForMethod(clientPath: string, clientMethod: string | undefined, routes: readonly ServerRoute[]): ServerRoute | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Noise-gated route match for newer cross-stack rules.
|
|
90
|
+
*
|
|
91
|
+
* The older matcher intentionally returns the first path-shaped match so
|
|
92
|
+
* legacy rules retain broad coverage. Newer rules that can feel speculative
|
|
93
|
+
* should use this helper instead: it requires a known client method, exactly
|
|
94
|
+
* one matching server route for that method, a concrete internal API path, and
|
|
95
|
+
* no catch-all/wildcard route shapes.
|
|
96
|
+
*/
|
|
97
|
+
export declare function findHighConfidenceRouteForMethod(clientPath: string, clientMethod: string | undefined, routes: readonly ServerRoute[]): ServerRoute | undefined;
|
|
87
98
|
/** Boolean-returning thin wrapper preserved for callers that just need a yes/no. */
|
|
88
99
|
export declare function hasMatchingRoute(clientPath: string, routes: readonly ServerRoute[]): boolean;
|
|
89
100
|
/**
|
|
@@ -94,3 +105,16 @@ export declare function hasMatchingRoute(clientPath: string, routes: readonly Se
|
|
|
94
105
|
* no one calls it" (method-drift / orphan-route territory).
|
|
95
106
|
*/
|
|
96
107
|
export declare function findRoutesAtPath(clientPath: string, routes: readonly ServerRoute[]): ServerRoute[];
|
|
108
|
+
export declare function routeMethodMatches(routeMethod: string | undefined, clientMethod: string): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Resolve an inline Express handler's concept from a route node. Only
|
|
111
|
+
* meaningful for `route` entrypoints whose mapper set `handlerConceptId`
|
|
112
|
+
* (inline arrow/function handlers — not imported identifiers). Returns
|
|
113
|
+
* undefined when the route has no inline handler or the expected concept
|
|
114
|
+
* is absent from the map (e.g., stripped during serialisation).
|
|
115
|
+
*
|
|
116
|
+
* Rules that reason about handler body contents — body-shape drift, auth
|
|
117
|
+
* checks, response envelope detection — use this as the single lookup
|
|
118
|
+
* point so callers don't re-implement span-or-id matching in each rule.
|
|
119
|
+
*/
|
|
120
|
+
export declare function findHandlerConcept(map: ConceptMap, route: ConceptNode): ConceptNode | undefined;
|
|
@@ -197,25 +197,52 @@ export function normalizeClientUrl(raw) {
|
|
|
197
197
|
export function findMatchingRoute(clientPath, routes) {
|
|
198
198
|
const clientSegments = trimTrailing(clientPath).split('/');
|
|
199
199
|
for (const route of routes) {
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
if (routePathMatchesSegments(route.path, clientSegments))
|
|
201
|
+
return route;
|
|
202
|
+
}
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
export function findMatchingRouteForMethod(clientPath, clientMethod, routes) {
|
|
206
|
+
const clientSegments = trimTrailing(clientPath).split('/');
|
|
207
|
+
for (const route of routes) {
|
|
208
|
+
if (!routePathMatchesSegments(route.path, clientSegments))
|
|
202
209
|
continue;
|
|
203
|
-
|
|
204
|
-
for (let i = 0; i < routeSegments.length; i++) {
|
|
205
|
-
const rs = routeSegments[i];
|
|
206
|
-
const cs = clientSegments[i];
|
|
207
|
-
if (isParamSegment(rs))
|
|
208
|
-
continue;
|
|
209
|
-
if (rs !== cs) {
|
|
210
|
-
matched = false;
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
if (matched)
|
|
210
|
+
if (!clientMethod || routeMethodMatches(route.method, clientMethod))
|
|
215
211
|
return route;
|
|
216
212
|
}
|
|
217
213
|
return undefined;
|
|
218
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Noise-gated route match for newer cross-stack rules.
|
|
217
|
+
*
|
|
218
|
+
* The older matcher intentionally returns the first path-shaped match so
|
|
219
|
+
* legacy rules retain broad coverage. Newer rules that can feel speculative
|
|
220
|
+
* should use this helper instead: it requires a known client method, exactly
|
|
221
|
+
* one matching server route for that method, a concrete internal API path, and
|
|
222
|
+
* no catch-all/wildcard route shapes.
|
|
223
|
+
*/
|
|
224
|
+
export function findHighConfidenceRouteForMethod(clientPath, clientMethod, routes) {
|
|
225
|
+
if (!isHighConfidenceClientPath(clientPath))
|
|
226
|
+
return undefined;
|
|
227
|
+
if (!clientMethod)
|
|
228
|
+
return undefined;
|
|
229
|
+
const matches = findRoutesAtPath(clientPath, routes).filter((route) => {
|
|
230
|
+
if (!route.node)
|
|
231
|
+
return false;
|
|
232
|
+
if (route.node.confidence < 0.75)
|
|
233
|
+
return false;
|
|
234
|
+
if (!route.method)
|
|
235
|
+
return false;
|
|
236
|
+
if (WILDCARD_METHODS.has(route.method.toUpperCase()))
|
|
237
|
+
return false;
|
|
238
|
+
if (!routeMethodMatches(route.method, clientMethod))
|
|
239
|
+
return false;
|
|
240
|
+
if (!isHighConfidenceServerPath(route.path))
|
|
241
|
+
return false;
|
|
242
|
+
return true;
|
|
243
|
+
});
|
|
244
|
+
return matches.length === 1 ? matches[0] : undefined;
|
|
245
|
+
}
|
|
219
246
|
/** Boolean-returning thin wrapper preserved for callers that just need a yes/no. */
|
|
220
247
|
export function hasMatchingRoute(clientPath, routes) {
|
|
221
248
|
return findMatchingRoute(clientPath, routes) !== undefined;
|
|
@@ -231,21 +258,7 @@ export function findRoutesAtPath(clientPath, routes) {
|
|
|
231
258
|
const clientSegments = trimTrailing(clientPath).split('/');
|
|
232
259
|
const matches = [];
|
|
233
260
|
for (const route of routes) {
|
|
234
|
-
|
|
235
|
-
if (routeSegments.length !== clientSegments.length)
|
|
236
|
-
continue;
|
|
237
|
-
let matched = true;
|
|
238
|
-
for (let i = 0; i < routeSegments.length; i++) {
|
|
239
|
-
const rs = routeSegments[i];
|
|
240
|
-
const cs = clientSegments[i];
|
|
241
|
-
if (isParamSegment(rs))
|
|
242
|
-
continue;
|
|
243
|
-
if (rs !== cs) {
|
|
244
|
-
matched = false;
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (matched)
|
|
261
|
+
if (routePathMatchesSegments(route.path, clientSegments))
|
|
249
262
|
matches.push(route);
|
|
250
263
|
}
|
|
251
264
|
return matches;
|
|
@@ -253,6 +266,87 @@ export function findRoutesAtPath(clientPath, routes) {
|
|
|
253
266
|
function trimTrailing(path) {
|
|
254
267
|
return path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path;
|
|
255
268
|
}
|
|
269
|
+
function routePathMatchesSegments(routePath, clientSegments) {
|
|
270
|
+
const routeSegments = trimTrailing(routePath).split('/');
|
|
271
|
+
if (routeSegments.length !== clientSegments.length)
|
|
272
|
+
return false;
|
|
273
|
+
for (let i = 0; i < routeSegments.length; i++) {
|
|
274
|
+
const rs = routeSegments[i];
|
|
275
|
+
const cs = clientSegments[i];
|
|
276
|
+
if (isParamSegment(rs))
|
|
277
|
+
continue;
|
|
278
|
+
if (rs !== cs)
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
function isHighConfidenceClientPath(path) {
|
|
284
|
+
if (!API_PATH_RE.test(path))
|
|
285
|
+
return false;
|
|
286
|
+
if (hasCatchAllOrWildcardSegment(path))
|
|
287
|
+
return false;
|
|
288
|
+
const segments = trimTrailing(path).split('/').filter(Boolean);
|
|
289
|
+
return segments.every((segment) => {
|
|
290
|
+
if (!segment.includes('${'))
|
|
291
|
+
return true;
|
|
292
|
+
return /^\$\{[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)?\}$/.test(segment);
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
function isHighConfidenceServerPath(path) {
|
|
296
|
+
if (!API_PATH_RE.test(path))
|
|
297
|
+
return false;
|
|
298
|
+
return !hasCatchAllOrWildcardSegment(path);
|
|
299
|
+
}
|
|
300
|
+
function hasCatchAllOrWildcardSegment(path) {
|
|
301
|
+
return trimTrailing(path)
|
|
302
|
+
.split('/')
|
|
303
|
+
.some((segment) => {
|
|
304
|
+
if (!segment)
|
|
305
|
+
return false;
|
|
306
|
+
if (segment === '*' || segment.includes('...'))
|
|
307
|
+
return true;
|
|
308
|
+
if (segment.startsWith('*'))
|
|
309
|
+
return true;
|
|
310
|
+
if (/^\{[^}:]+:path\}$/.test(segment))
|
|
311
|
+
return true;
|
|
312
|
+
return false;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
// Verbs emitted by route declarations that intentionally accept any method.
|
|
316
|
+
const WILDCARD_METHODS = new Set(['ALL', 'ANY']);
|
|
317
|
+
export function routeMethodMatches(routeMethod, clientMethod) {
|
|
318
|
+
if (!routeMethod)
|
|
319
|
+
return true;
|
|
320
|
+
const r = routeMethod.toUpperCase();
|
|
321
|
+
if (WILDCARD_METHODS.has(r))
|
|
322
|
+
return true;
|
|
323
|
+
const c = clientMethod.toUpperCase();
|
|
324
|
+
if (r === c)
|
|
325
|
+
return true;
|
|
326
|
+
// Express and Starlette/FastAPI both auto-respond to HEAD on GET routes.
|
|
327
|
+
if (c === 'HEAD' && r === 'GET')
|
|
328
|
+
return true;
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Resolve an inline Express handler's concept from a route node. Only
|
|
333
|
+
* meaningful for `route` entrypoints whose mapper set `handlerConceptId`
|
|
334
|
+
* (inline arrow/function handlers — not imported identifiers). Returns
|
|
335
|
+
* undefined when the route has no inline handler or the expected concept
|
|
336
|
+
* is absent from the map (e.g., stripped during serialisation).
|
|
337
|
+
*
|
|
338
|
+
* Rules that reason about handler body contents — body-shape drift, auth
|
|
339
|
+
* checks, response envelope detection — use this as the single lookup
|
|
340
|
+
* point so callers don't re-implement span-or-id matching in each rule.
|
|
341
|
+
*/
|
|
342
|
+
export function findHandlerConcept(map, route) {
|
|
343
|
+
if (route.kind !== 'entrypoint' || route.payload.kind !== 'entrypoint')
|
|
344
|
+
return undefined;
|
|
345
|
+
const handlerId = route.payload.handlerConceptId;
|
|
346
|
+
if (!handlerId)
|
|
347
|
+
return undefined;
|
|
348
|
+
return map.nodes.find((n) => n.id === handlerId);
|
|
349
|
+
}
|
|
256
350
|
function isParamSegment(seg) {
|
|
257
351
|
return seg.startsWith(':') || (seg.startsWith('{') && seg.endsWith('}'));
|
|
258
352
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-stack-utils.js","sourceRoot":"","sources":["../../src/concept-rules/cross-stack-utils.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cross-stack-utils.js","sourceRoot":"","sources":["../../src/concept-rules/cross-stack-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Language-agnostic by design.
|
|
6
6
|
*/
|
|
7
7
|
import type { ConceptMap } from '@kernlang/core';
|
|
8
|
-
import type { ReviewFinding } from '../types.js';
|
|
8
|
+
import type { ReviewConfig, ReviewFinding } from '../types.js';
|
|
9
9
|
export interface ConceptRuleContext {
|
|
10
10
|
concepts: ConceptMap;
|
|
11
11
|
filePath: string;
|
|
@@ -13,7 +13,9 @@ export interface ConceptRuleContext {
|
|
|
13
13
|
allConcepts?: Map<string, ConceptMap>;
|
|
14
14
|
/** Resolved import graph — filePath → imported file paths */
|
|
15
15
|
graphImports?: Map<string, string[]>;
|
|
16
|
+
/** Cross-stack precision mode. Defaults to guard. */
|
|
17
|
+
crossStackMode?: 'guard' | 'audit';
|
|
16
18
|
}
|
|
17
19
|
export type ConceptRule = (ctx: ConceptRuleContext) => ReviewFinding[];
|
|
18
20
|
export declare const conceptRules: ConceptRule[];
|
|
19
|
-
export declare function runConceptRules(concepts: ConceptMap, filePath: string, allConcepts?: Map<string, ConceptMap>, graphImports?: Map<string, string[]>): ReviewFinding[];
|
|
21
|
+
export declare function runConceptRules(concepts: ConceptMap, filePath: string, allConcepts?: Map<string, ConceptMap>, graphImports?: Map<string, string[]>, config?: Pick<ReviewConfig, 'crossStackMode'>): ReviewFinding[];
|
|
@@ -4,44 +4,63 @@
|
|
|
4
4
|
* These rules work on any language that emits concepts.
|
|
5
5
|
* Language-agnostic by design.
|
|
6
6
|
*/
|
|
7
|
+
import { applyRuleSupersession } from '../rule-quality.js';
|
|
7
8
|
import { authDrift } from './auth-drift.js';
|
|
9
|
+
import { authPropagationDrift } from './auth-propagation-drift.js';
|
|
10
|
+
import { bodyShapeDrift } from './body-shape-drift.js';
|
|
8
11
|
import { boundaryMutation } from './boundary-mutation.js';
|
|
9
12
|
import { contractDrift } from './contract-drift.js';
|
|
10
13
|
import { contractMethodDrift } from './contract-method-drift.js';
|
|
11
14
|
import { duplicateRoute } from './duplicate-route.js';
|
|
12
15
|
import { ignoredError } from './ignored-error.js';
|
|
13
16
|
import { missingResponseModel } from './missing-response-model.js';
|
|
17
|
+
import { mutationWithoutIdempotency } from './mutation-without-idempotency.js';
|
|
14
18
|
import { orphanRoute } from './orphan-route.js';
|
|
15
19
|
import { paramNameSwap } from './param-name-swap.js';
|
|
20
|
+
import { requestValidationDrift } from './request-validation-drift.js';
|
|
16
21
|
import { syncHandlerDoesIo } from './sync-handler-does-io.js';
|
|
17
22
|
import { taintedAcrossWire } from './tainted-across-wire.js';
|
|
23
|
+
import { unboundedCollectionQuery } from './unbounded-collection-query.js';
|
|
18
24
|
import { unguardedEffect } from './unguarded-effect.js';
|
|
25
|
+
import { unhandledApiErrorShape } from './unhandled-api-error-shape.js';
|
|
19
26
|
import { unrecoveredEffect } from './unrecovered-effect.js';
|
|
20
27
|
import { untypedApiResponse } from './untyped-api-response.js';
|
|
21
28
|
import { untypedBothEndsResponse } from './untyped-both-ends-response.js';
|
|
22
29
|
export const conceptRules = [
|
|
23
30
|
authDrift,
|
|
31
|
+
authPropagationDrift,
|
|
32
|
+
bodyShapeDrift,
|
|
24
33
|
boundaryMutation,
|
|
25
34
|
contractDrift,
|
|
26
35
|
contractMethodDrift,
|
|
27
36
|
duplicateRoute,
|
|
28
37
|
ignoredError,
|
|
29
38
|
missingResponseModel,
|
|
39
|
+
mutationWithoutIdempotency,
|
|
30
40
|
orphanRoute,
|
|
31
41
|
paramNameSwap,
|
|
42
|
+
requestValidationDrift,
|
|
32
43
|
syncHandlerDoesIo,
|
|
33
44
|
taintedAcrossWire,
|
|
45
|
+
unboundedCollectionQuery,
|
|
34
46
|
unguardedEffect,
|
|
47
|
+
unhandledApiErrorShape,
|
|
35
48
|
unrecoveredEffect,
|
|
36
49
|
untypedApiResponse,
|
|
37
50
|
untypedBothEndsResponse,
|
|
38
51
|
];
|
|
39
|
-
export function runConceptRules(concepts, filePath, allConcepts, graphImports) {
|
|
40
|
-
const ctx = {
|
|
52
|
+
export function runConceptRules(concepts, filePath, allConcepts, graphImports, config) {
|
|
53
|
+
const ctx = {
|
|
54
|
+
concepts,
|
|
55
|
+
filePath,
|
|
56
|
+
allConcepts,
|
|
57
|
+
graphImports,
|
|
58
|
+
crossStackMode: config?.crossStackMode,
|
|
59
|
+
};
|
|
41
60
|
const findings = [];
|
|
42
61
|
for (const rule of conceptRules) {
|
|
43
62
|
findings.push(...rule(ctx));
|
|
44
63
|
}
|
|
45
|
-
return findings;
|
|
64
|
+
return applyRuleSupersession(findings, config);
|
|
46
65
|
}
|
|
47
66
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/concept-rules/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/concept-rules/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAe1E,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,SAAS;IACT,oBAAoB;IACpB,cAAc;IACd,gBAAgB;IAChB,aAAa;IACb,mBAAmB;IACnB,cAAc;IACd,YAAY;IACZ,oBAAoB;IACpB,0BAA0B;IAC1B,WAAW;IACX,aAAa;IACb,sBAAsB;IACtB,iBAAiB;IACjB,iBAAiB;IACjB,wBAAwB;IACxB,eAAe;IACf,sBAAsB;IACtB,iBAAiB;IACjB,kBAAkB;IAClB,uBAAuB;CACxB,CAAC;AAEF,MAAM,UAAU,eAAe,CAC7B,QAAoB,EACpB,QAAgB,EAChB,WAAqC,EACrC,YAAoC,EACpC,MAA6C;IAE7C,MAAM,GAAG,GAAuB;QAC9B,QAAQ;QACR,QAAQ;QACR,WAAW;QACX,YAAY;QACZ,cAAc,EAAE,MAAM,EAAE,cAAc;KACvC,CAAC;IACF,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: mutation-without-idempotency
|
|
3
|
+
*
|
|
4
|
+
* Backend rule — fires on mutating HTTP routes that perform a DB write without
|
|
5
|
+
* visible idempotency, transaction, unique/upsert, or duplicate-protection
|
|
6
|
+
* evidence.
|
|
7
|
+
*/
|
|
8
|
+
import type { ReviewFinding } from '../types.js';
|
|
9
|
+
import type { ConceptRuleContext } from './index.js';
|
|
10
|
+
export declare function mutationWithoutIdempotency(ctx: ConceptRuleContext): ReviewFinding[];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: mutation-without-idempotency
|
|
3
|
+
*
|
|
4
|
+
* Backend rule — fires on mutating HTTP routes that perform a DB write without
|
|
5
|
+
* visible idempotency, transaction, unique/upsert, or duplicate-protection
|
|
6
|
+
* evidence.
|
|
7
|
+
*/
|
|
8
|
+
import { createFingerprint } from '../types.js';
|
|
9
|
+
import { API_PATH_RE } from './cross-stack-utils.js';
|
|
10
|
+
const GUARD_MUTATING_METHODS = new Set(['POST']);
|
|
11
|
+
const AUDIT_MUTATING_METHODS = new Set(['POST', 'PATCH', 'DELETE']);
|
|
12
|
+
export function mutationWithoutIdempotency(ctx) {
|
|
13
|
+
const findings = [];
|
|
14
|
+
for (const node of ctx.concepts.nodes) {
|
|
15
|
+
if (node.kind !== 'entrypoint' || node.payload.kind !== 'entrypoint' || node.payload.subtype !== 'route')
|
|
16
|
+
continue;
|
|
17
|
+
const method = node.payload.httpMethod?.toUpperCase();
|
|
18
|
+
const mutatingMethods = ctx.crossStackMode === 'audit' ? AUDIT_MUTATING_METHODS : GUARD_MUTATING_METHODS;
|
|
19
|
+
if (!method || !mutatingMethods.has(method))
|
|
20
|
+
continue;
|
|
21
|
+
if (!API_PATH_RE.test(node.payload.name))
|
|
22
|
+
continue;
|
|
23
|
+
if (ctx.crossStackMode !== 'audit' && routeHasPathParam(node.payload.name))
|
|
24
|
+
continue;
|
|
25
|
+
if (node.payload.hasDbWrite !== true)
|
|
26
|
+
continue;
|
|
27
|
+
if (node.payload.hasIdempotencyProtection === true)
|
|
28
|
+
continue;
|
|
29
|
+
findings.push({
|
|
30
|
+
source: 'kern',
|
|
31
|
+
ruleId: 'mutation-without-idempotency',
|
|
32
|
+
severity: 'warning',
|
|
33
|
+
category: 'bug',
|
|
34
|
+
message: `Mutating route \`${method} ${node.payload.name}\` writes to the database without visible idempotency key, transaction, unique guard, upsert, or duplicate-protection evidence. Retries or double-submits can create duplicate side effects.`,
|
|
35
|
+
primarySpan: node.primarySpan,
|
|
36
|
+
fingerprint: createFingerprint('mutation-without-idempotency', node.primarySpan.startLine, node.primarySpan.startCol),
|
|
37
|
+
confidence: node.confidence * 0.75,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return findings;
|
|
41
|
+
}
|
|
42
|
+
function routeHasPathParam(path) {
|
|
43
|
+
return path
|
|
44
|
+
.split('/')
|
|
45
|
+
.some((segment) => segment.startsWith(':') || (segment.startsWith('{') && segment.endsWith('}')));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=mutation-without-idempotency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-without-idempotency.js","sourceRoot":"","sources":["../../src/concept-rules/mutation-without-idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEpE,MAAM,UAAU,0BAA0B,CAAC,GAAuB;IAChE,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO;YAAE,SAAS;QACnH,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC;QACtD,MAAM,eAAe,GAAG,GAAG,CAAC,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,sBAAsB,CAAC;QACzG,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,SAAS;QACtD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,SAAS;QACnD,IAAI,GAAG,CAAC,cAAc,KAAK,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,SAAS;QACrF,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,KAAK,IAAI;YAAE,SAAS;QAC/C,IAAI,IAAI,CAAC,OAAO,CAAC,wBAAwB,KAAK,IAAI;YAAE,SAAS;QAE7D,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,8BAA8B;YACtC,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,oBAAoB,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,8LAA8L;YACtP,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,iBAAiB,CAC5B,8BAA8B,EAC9B,IAAI,CAAC,WAAW,CAAC,SAAS,EAC1B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAC1B;YACD,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI;SACnC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,IAAI;SACR,KAAK,CAAC,GAAG,CAAC;SACV,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACtG,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: request-validation-drift
|
|
3
|
+
*
|
|
4
|
+
* Cross-stack/backend rule:
|
|
5
|
+
* - client sends fields outside the backend's resolved validation schema;
|
|
6
|
+
* - or a mutating backend route reads body fields and writes to DB with no
|
|
7
|
+
* visible body validation.
|
|
8
|
+
*/
|
|
9
|
+
import type { ReviewFinding } from '../types.js';
|
|
10
|
+
import type { ConceptRuleContext } from './index.js';
|
|
11
|
+
export declare function requestValidationDrift(ctx: ConceptRuleContext): ReviewFinding[];
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: request-validation-drift
|
|
3
|
+
*
|
|
4
|
+
* Cross-stack/backend rule:
|
|
5
|
+
* - client sends fields outside the backend's resolved validation schema;
|
|
6
|
+
* - or a mutating backend route reads body fields and writes to DB with no
|
|
7
|
+
* visible body validation.
|
|
8
|
+
*/
|
|
9
|
+
import { createFingerprint } from '../types.js';
|
|
10
|
+
import { API_PATH_RE, CROSS_STACK_HEURISTIC_CONFIDENCE, collectRoutesAcrossGraph, findHighConfidenceRouteForMethod, findMatchingRouteForMethod, normalizeClientUrl, } from './cross-stack-utils.js';
|
|
11
|
+
import { apiCallRootCause, routeRootCause } from './root-cause.js';
|
|
12
|
+
const GUARD_BODY_METHODS = new Set(['POST']);
|
|
13
|
+
const AUDIT_BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);
|
|
14
|
+
export function requestValidationDrift(ctx) {
|
|
15
|
+
const findings = [];
|
|
16
|
+
findings.push(...backendUnvalidatedBodyFindings(ctx));
|
|
17
|
+
findings.push(...clientExtraFieldFindings(ctx));
|
|
18
|
+
return findings;
|
|
19
|
+
}
|
|
20
|
+
function backendUnvalidatedBodyFindings(ctx) {
|
|
21
|
+
const findings = [];
|
|
22
|
+
for (const node of ctx.concepts.nodes) {
|
|
23
|
+
if (node.kind !== 'entrypoint' || node.payload.kind !== 'entrypoint' || node.payload.subtype !== 'route')
|
|
24
|
+
continue;
|
|
25
|
+
const method = node.payload.httpMethod?.toUpperCase();
|
|
26
|
+
const bodyMethods = ctx.crossStackMode === 'audit' ? AUDIT_BODY_METHODS : GUARD_BODY_METHODS;
|
|
27
|
+
if (!method || !bodyMethods.has(method))
|
|
28
|
+
continue;
|
|
29
|
+
if (!API_PATH_RE.test(node.payload.name))
|
|
30
|
+
continue;
|
|
31
|
+
if (node.payload.hasDbWrite !== true)
|
|
32
|
+
continue;
|
|
33
|
+
if (node.payload.bodyFieldsResolved !== true || !node.payload.bodyFields || node.payload.bodyFields.length === 0) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (node.payload.hasBodyValidation === true)
|
|
37
|
+
continue;
|
|
38
|
+
const fields = node.payload.bodyFields.map((field) => `\`${field}\``).join(', ');
|
|
39
|
+
findings.push({
|
|
40
|
+
source: 'kern',
|
|
41
|
+
ruleId: 'request-validation-drift',
|
|
42
|
+
severity: 'warning',
|
|
43
|
+
category: 'bug',
|
|
44
|
+
message: `Route \`${method} ${node.payload.name}\` reads request body fields ${fields} and writes to the database without visible request-body validation.`,
|
|
45
|
+
primarySpan: node.primarySpan,
|
|
46
|
+
fingerprint: createFingerprint('request-validation-drift', node.primarySpan.startLine, node.primarySpan.startCol),
|
|
47
|
+
confidence: node.confidence * 0.8,
|
|
48
|
+
rootCause: routeRootCause(node, method),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return findings;
|
|
52
|
+
}
|
|
53
|
+
function clientExtraFieldFindings(ctx) {
|
|
54
|
+
if (!ctx.allConcepts || ctx.allConcepts.size === 0)
|
|
55
|
+
return [];
|
|
56
|
+
const serverRoutes = collectRoutesAcrossGraph(ctx.allConcepts);
|
|
57
|
+
if (serverRoutes.length === 0)
|
|
58
|
+
return [];
|
|
59
|
+
const findings = [];
|
|
60
|
+
const localConcepts = ctx.allConcepts.get(ctx.filePath) ?? ctx.concepts;
|
|
61
|
+
for (const node of localConcepts.nodes) {
|
|
62
|
+
if (node.kind !== 'effect' || node.payload.kind !== 'effect' || node.payload.subtype !== 'network')
|
|
63
|
+
continue;
|
|
64
|
+
if (node.payload.sentFieldsResolved !== true || !node.payload.sentFields)
|
|
65
|
+
continue;
|
|
66
|
+
const target = node.payload.target;
|
|
67
|
+
if (typeof target !== 'string')
|
|
68
|
+
continue;
|
|
69
|
+
const normalized = normalizeClientUrl(target);
|
|
70
|
+
if (!normalized)
|
|
71
|
+
continue;
|
|
72
|
+
const route = ctx.crossStackMode === 'audit'
|
|
73
|
+
? findMatchingRouteForMethod(normalized, node.payload.method, serverRoutes)
|
|
74
|
+
: findHighConfidenceRouteForMethod(normalized, node.payload.method, serverRoutes);
|
|
75
|
+
if (route?.node?.payload.kind !== 'entrypoint')
|
|
76
|
+
continue;
|
|
77
|
+
if (route.node.payload.bodyValidationResolved !== true || !route.node.payload.validatedBodyFields)
|
|
78
|
+
continue;
|
|
79
|
+
const validated = new Set(route.node.payload.validatedBodyFields);
|
|
80
|
+
const extra = node.payload.sentFields.filter((field) => !validated.has(field));
|
|
81
|
+
if (extra.length === 0)
|
|
82
|
+
continue;
|
|
83
|
+
const fieldList = extra.map((field) => `\`${field}\``).join(', ');
|
|
84
|
+
findings.push({
|
|
85
|
+
source: 'kern',
|
|
86
|
+
ruleId: 'request-validation-drift',
|
|
87
|
+
severity: 'warning',
|
|
88
|
+
category: 'bug',
|
|
89
|
+
message: `Client sends ${fieldList} to \`${target}\`, but the matching backend validation schema does not accept ${extra.length === 1 ? 'that field' : 'those fields'}. Remove the extra payload data or update the backend schema intentionally.`,
|
|
90
|
+
primarySpan: node.primarySpan,
|
|
91
|
+
relatedSpans: [route.node.primarySpan],
|
|
92
|
+
fingerprint: createFingerprint('request-validation-drift', node.primarySpan.startLine, node.primarySpan.startCol),
|
|
93
|
+
confidence: node.confidence * CROSS_STACK_HEURISTIC_CONFIDENCE,
|
|
94
|
+
rootCause: apiCallRootCause(node, normalized, node.payload.method, route.node),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return findings;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=request-validation-drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-validation-drift.js","sourceRoot":"","sources":["../../src/concept-rules/request-validation-drift.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ConceptNode } from '@kernlang/core';
|
|
2
|
+
import type { RootCause } from '../types.js';
|
|
3
|
+
export declare function apiCallRootCause(clientNode: ConceptNode, normalizedPath: string, method?: string, routeNode?: ConceptNode): RootCause;
|
|
4
|
+
export declare function routeRootCause(routeNode: ConceptNode, method?: string): RootCause;
|