@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.
Files changed (116) hide show
  1. package/dist/cache.js +1 -1
  2. package/dist/call-graph.d.ts +10 -0
  3. package/dist/call-graph.js +138 -9
  4. package/dist/call-graph.js.map +1 -1
  5. package/dist/concept-rules/auth-drift.js +2 -0
  6. package/dist/concept-rules/auth-drift.js.map +1 -1
  7. package/dist/concept-rules/auth-propagation-drift.d.ts +10 -0
  8. package/dist/concept-rules/auth-propagation-drift.js +85 -0
  9. package/dist/concept-rules/auth-propagation-drift.js.map +1 -0
  10. package/dist/concept-rules/body-shape-drift.d.ts +32 -0
  11. package/dist/concept-rules/body-shape-drift.js +98 -0
  12. package/dist/concept-rules/body-shape-drift.js.map +1 -0
  13. package/dist/concept-rules/contract-drift.js +3 -1
  14. package/dist/concept-rules/contract-drift.js.map +1 -1
  15. package/dist/concept-rules/contract-method-drift.js +2 -0
  16. package/dist/concept-rules/contract-method-drift.js.map +1 -1
  17. package/dist/concept-rules/cross-stack-utils.d.ts +24 -0
  18. package/dist/concept-rules/cross-stack-utils.js +123 -29
  19. package/dist/concept-rules/cross-stack-utils.js.map +1 -1
  20. package/dist/concept-rules/index.d.ts +4 -2
  21. package/dist/concept-rules/index.js +22 -3
  22. package/dist/concept-rules/index.js.map +1 -1
  23. package/dist/concept-rules/mutation-without-idempotency.d.ts +10 -0
  24. package/dist/concept-rules/mutation-without-idempotency.js +47 -0
  25. package/dist/concept-rules/mutation-without-idempotency.js.map +1 -0
  26. package/dist/concept-rules/request-validation-drift.d.ts +11 -0
  27. package/dist/concept-rules/request-validation-drift.js +99 -0
  28. package/dist/concept-rules/request-validation-drift.js.map +1 -0
  29. package/dist/concept-rules/root-cause.d.ts +4 -0
  30. package/dist/concept-rules/root-cause.js +31 -0
  31. package/dist/concept-rules/root-cause.js.map +1 -0
  32. package/dist/concept-rules/unbounded-collection-query.d.ts +10 -0
  33. package/dist/concept-rules/unbounded-collection-query.js +58 -0
  34. package/dist/concept-rules/unbounded-collection-query.js.map +1 -0
  35. package/dist/concept-rules/unhandled-api-error-shape.d.ts +10 -0
  36. package/dist/concept-rules/unhandled-api-error-shape.js +59 -0
  37. package/dist/concept-rules/unhandled-api-error-shape.js.map +1 -0
  38. package/dist/default-export.d.ts +41 -0
  39. package/dist/default-export.js +76 -0
  40. package/dist/default-export.js.map +1 -0
  41. package/dist/eval.d.ts +67 -0
  42. package/dist/eval.js +177 -0
  43. package/dist/eval.js.map +1 -0
  44. package/dist/external-tools.js +52 -3
  45. package/dist/external-tools.js.map +1 -1
  46. package/dist/file-context.js +32 -13
  47. package/dist/file-context.js.map +1 -1
  48. package/dist/file-role.d.ts +6 -0
  49. package/dist/file-role.js +27 -0
  50. package/dist/file-role.js.map +1 -1
  51. package/dist/framework-seeds.d.ts +46 -0
  52. package/dist/framework-seeds.js +245 -0
  53. package/dist/framework-seeds.js.map +1 -0
  54. package/dist/git-env.d.ts +1 -0
  55. package/dist/git-env.js +25 -0
  56. package/dist/git-env.js.map +1 -0
  57. package/dist/graph.js +246 -21
  58. package/dist/graph.js.map +1 -1
  59. package/dist/index.d.ts +12 -3
  60. package/dist/index.js +314 -96
  61. package/dist/index.js.map +1 -1
  62. package/dist/mappers/ts-concepts.js +730 -1
  63. package/dist/mappers/ts-concepts.js.map +1 -1
  64. package/dist/path-canonical.d.ts +34 -0
  65. package/dist/path-canonical.js +85 -0
  66. package/dist/path-canonical.js.map +1 -0
  67. package/dist/policy.d.ts +22 -0
  68. package/dist/policy.js +47 -0
  69. package/dist/policy.js.map +1 -0
  70. package/dist/project-context.d.ts +135 -0
  71. package/dist/project-context.js +563 -0
  72. package/dist/project-context.js.map +1 -0
  73. package/dist/public-api.d.ts +21 -0
  74. package/dist/public-api.js +17 -2
  75. package/dist/public-api.js.map +1 -1
  76. package/dist/python-fallback.d.ts +2 -0
  77. package/dist/python-fallback.js +506 -0
  78. package/dist/python-fallback.js.map +1 -0
  79. package/dist/reporter.js +106 -1
  80. package/dist/reporter.js.map +1 -1
  81. package/dist/rule-quality.d.ts +58 -0
  82. package/dist/rule-quality.js +357 -0
  83. package/dist/rule-quality.js.map +1 -0
  84. package/dist/rules/base.js +21 -3
  85. package/dist/rules/base.js.map +1 -1
  86. package/dist/rules/dead-code.d.ts +2 -2
  87. package/dist/rules/dead-code.js +88 -4
  88. package/dist/rules/dead-code.js.map +1 -1
  89. package/dist/rules/index.d.ts +22 -0
  90. package/dist/rules/index.js +72 -0
  91. package/dist/rules/index.js.map +1 -1
  92. package/dist/rules/kern-source.d.ts +4 -0
  93. package/dist/rules/kern-source.js +184 -0
  94. package/dist/rules/kern-source.js.map +1 -1
  95. package/dist/rules/react.js +52 -3
  96. package/dist/rules/react.js.map +1 -1
  97. package/dist/rules/suggest-kern-primitive.js +0 -1
  98. package/dist/rules/suggest-kern-primitive.js.map +1 -1
  99. package/dist/semantic-diff.js +2 -0
  100. package/dist/semantic-diff.js.map +1 -1
  101. package/dist/suppression/apply-suppression.js +2 -0
  102. package/dist/suppression/apply-suppression.js.map +1 -1
  103. package/dist/suppression/parse-directives.d.ts +13 -5
  104. package/dist/suppression/parse-directives.js +62 -8
  105. package/dist/suppression/parse-directives.js.map +1 -1
  106. package/dist/suppression/types.d.ts +9 -0
  107. package/dist/suppression/types.js +6 -1
  108. package/dist/suppression/types.js.map +1 -1
  109. package/dist/taint-crossfile.js +15 -8
  110. package/dist/taint-crossfile.js.map +1 -1
  111. package/dist/telemetry.d.ts +126 -0
  112. package/dist/telemetry.js +303 -0
  113. package/dist/telemetry.js.map +1 -0
  114. package/dist/types.d.ts +172 -2
  115. package/dist/types.js.map +1 -1
  116. 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;AAShC,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,IAAI,EAAE,CAAC,CAAC;QACjE,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;SACpE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,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":"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"}
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
- const routeSegments = trimTrailing(route.path).split('/');
201
- if (routeSegments.length !== clientSegments.length)
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
- let matched = true;
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
- const routeSegments = trimTrailing(route.path).split('/');
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 = { concepts, filePath, allConcepts, graphImports };
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;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,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,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAa1E,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,SAAS;IACT,gBAAgB;IAChB,aAAa;IACb,mBAAmB;IACnB,cAAc;IACd,YAAY;IACZ,oBAAoB;IACpB,WAAW;IACX,aAAa;IACb,iBAAiB;IACjB,iBAAiB;IACjB,eAAe;IACf,iBAAiB;IACjB,kBAAkB;IAClB,uBAAuB;CACxB,CAAC;AAEF,MAAM,UAAU,eAAe,CAC7B,QAAoB,EACpB,QAAgB,EAChB,WAAqC,EACrC,YAAoC;IAEpC,MAAM,GAAG,GAAuB,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;IAClF,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,QAAQ,CAAC;AAClB,CAAC"}
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;