@kernlang/review 3.3.4 → 3.3.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 (62) hide show
  1. package/dist/cache.js +1 -1
  2. package/dist/concept-rules/auth-drift.d.ts +29 -0
  3. package/dist/concept-rules/auth-drift.js +127 -0
  4. package/dist/concept-rules/auth-drift.js.map +1 -0
  5. package/dist/concept-rules/contract-drift.d.ts +21 -0
  6. package/dist/concept-rules/contract-drift.js +65 -0
  7. package/dist/concept-rules/contract-drift.js.map +1 -0
  8. package/dist/concept-rules/contract-method-drift.d.ts +22 -0
  9. package/dist/concept-rules/contract-method-drift.js +105 -0
  10. package/dist/concept-rules/contract-method-drift.js.map +1 -0
  11. package/dist/concept-rules/cross-stack-utils.d.ts +96 -0
  12. package/dist/concept-rules/cross-stack-utils.js +259 -0
  13. package/dist/concept-rules/cross-stack-utils.js.map +1 -0
  14. package/dist/concept-rules/duplicate-route.d.ts +20 -0
  15. package/dist/concept-rules/duplicate-route.js +112 -0
  16. package/dist/concept-rules/duplicate-route.js.map +1 -0
  17. package/dist/concept-rules/index.js +26 -1
  18. package/dist/concept-rules/index.js.map +1 -1
  19. package/dist/concept-rules/missing-response-model.d.ts +10 -0
  20. package/dist/concept-rules/missing-response-model.js +38 -0
  21. package/dist/concept-rules/missing-response-model.js.map +1 -0
  22. package/dist/concept-rules/orphan-route.d.ts +20 -0
  23. package/dist/concept-rules/orphan-route.js +96 -0
  24. package/dist/concept-rules/orphan-route.js.map +1 -0
  25. package/dist/concept-rules/sync-handler-does-io.d.ts +9 -0
  26. package/dist/concept-rules/sync-handler-does-io.js +56 -0
  27. package/dist/concept-rules/sync-handler-does-io.js.map +1 -0
  28. package/dist/concept-rules/tainted-across-wire.d.ts +33 -0
  29. package/dist/concept-rules/tainted-across-wire.js +95 -0
  30. package/dist/concept-rules/tainted-across-wire.js.map +1 -0
  31. package/dist/concept-rules/untyped-api-response.d.ts +30 -0
  32. package/dist/concept-rules/untyped-api-response.js +73 -0
  33. package/dist/concept-rules/untyped-api-response.js.map +1 -0
  34. package/dist/concept-rules/untyped-both-ends-response.d.ts +10 -0
  35. package/dist/concept-rules/untyped-both-ends-response.js +55 -0
  36. package/dist/concept-rules/untyped-both-ends-response.js.map +1 -0
  37. package/dist/external-tools.d.ts +17 -4
  38. package/dist/external-tools.js +12 -1
  39. package/dist/external-tools.js.map +1 -1
  40. package/dist/index.d.ts +2 -1
  41. package/dist/index.js +115 -9
  42. package/dist/index.js.map +1 -1
  43. package/dist/llm-bridge.d.ts +38 -1
  44. package/dist/llm-bridge.js +172 -12
  45. package/dist/llm-bridge.js.map +1 -1
  46. package/dist/llm-review.js +29 -11
  47. package/dist/llm-review.js.map +1 -1
  48. package/dist/mappers/ts-concepts.js +650 -11
  49. package/dist/mappers/ts-concepts.js.map +1 -1
  50. package/dist/rules/index.js +17 -1
  51. package/dist/rules/index.js.map +1 -1
  52. package/dist/rules/kern-source.js +37 -5
  53. package/dist/rules/kern-source.js.map +1 -1
  54. package/dist/rules/set-setter-collision.d.ts +21 -0
  55. package/dist/rules/set-setter-collision.js +74 -0
  56. package/dist/rules/set-setter-collision.js.map +1 -0
  57. package/dist/rules/suggest-kern-primitive.d.ts +30 -0
  58. package/dist/rules/suggest-kern-primitive.js +543 -0
  59. package/dist/rules/suggest-kern-primitive.js.map +1 -0
  60. package/dist/types.d.ts +2 -0
  61. package/dist/types.js.map +1 -1
  62. package/package.json +2 -2
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Rule: sync-handler-does-io
3
+ *
4
+ * Fires when a route handler is explicitly synchronous and performs
5
+ * network/db/fs I/O in the same function container.
6
+ */
7
+ import { createFingerprint } from '../types.js';
8
+ const BLOCKING_IO_SUBTYPES = new Set(['network', 'db', 'fs']);
9
+ export function syncHandlerDoesIo(ctx) {
10
+ const effectsByContainer = new Map();
11
+ for (const node of ctx.concepts.nodes) {
12
+ if (node.kind !== 'effect')
13
+ continue;
14
+ if (node.payload.kind !== 'effect')
15
+ continue;
16
+ if (!BLOCKING_IO_SUBTYPES.has(node.payload.subtype))
17
+ continue;
18
+ if (!node.containerId)
19
+ continue;
20
+ const existing = effectsByContainer.get(node.containerId) ?? [];
21
+ existing.push(node);
22
+ effectsByContainer.set(node.containerId, existing);
23
+ }
24
+ const findings = [];
25
+ for (const node of ctx.concepts.nodes) {
26
+ if (node.kind !== 'entrypoint')
27
+ continue;
28
+ if (node.payload.kind !== 'entrypoint')
29
+ continue;
30
+ if (node.payload.subtype !== 'route')
31
+ continue;
32
+ if (node.payload.isAsync !== false)
33
+ continue;
34
+ if (!node.containerId)
35
+ continue;
36
+ const effects = effectsByContainer.get(node.containerId);
37
+ if (!effects || effects.length === 0)
38
+ continue;
39
+ const firstEffect = effects[0];
40
+ if (firstEffect.payload.kind !== 'effect')
41
+ continue;
42
+ findings.push({
43
+ source: 'kern',
44
+ ruleId: 'sync-handler-does-io',
45
+ severity: 'warning',
46
+ category: 'bug',
47
+ message: `Sync route handler \`${node.payload.name}\` performs ${firstEffect.payload.subtype} I/O. Make the handler async and use non-blocking I/O, or move the blocking work out of the request path.`,
48
+ primarySpan: node.primarySpan,
49
+ relatedSpans: effects.map((effect) => effect.primarySpan),
50
+ fingerprint: createFingerprint('sync-handler-does-io', node.primarySpan.startLine, node.primarySpan.startCol),
51
+ confidence: 0.9,
52
+ });
53
+ }
54
+ return findings;
55
+ }
56
+ //# sourceMappingURL=sync-handler-does-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-handler-does-io.js","sourceRoot":"","sources":["../../src/concept-rules/sync-handler-does-io.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAE9D,MAAM,UAAU,iBAAiB,CAAC,GAAuB;IACvD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAyB,CAAC;IAE5D,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QACrC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QAC7C,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAS;QAC9D,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,SAAS;QAEhC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAChE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;YAAE,SAAS;QACzC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY;YAAE,SAAS;QACjD,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO;YAAE,SAAS;QAC/C,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK;YAAE,SAAS;QAC7C,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,SAAS;QAEhC,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QAEpD,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,sBAAsB;YAC9B,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,wBAAwB,IAAI,CAAC,OAAO,CAAC,IAAI,eAAe,WAAW,CAAC,OAAO,CAAC,OAAO,2GAA2G;YACvM,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;YACzD,WAAW,EAAE,iBAAiB,CAAC,sBAAsB,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;YAC7G,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Rule: tainted-across-wire
3
+ *
4
+ * Cross-stack rule — fires when a frontend (TS) network call sends a
5
+ * dynamic (user-controlled) body to a server-side route in the reviewed
6
+ * project AND that route's handler has no validation guard in scope.
7
+ *
8
+ * This is rule #3 of the fullstack wedge. Pure server-side taint analysis
9
+ * (already in @kernlang/review's taint-crossfile module) finds sinks
10
+ * reachable from `req.body`, but it can't see the *client-side call site*
11
+ * that's feeding the unvalidated input. And pure client-side analysis
12
+ * doesn't know whether the server validates — so it either fires on every
13
+ * dynamic POST (noise) or on none (misses the moat).
14
+ *
15
+ * By correlating both sides via the concept graph we can fire precisely:
16
+ * "here's the fetch that sends user input to an endpoint whose handler
17
+ * doesn't parse it with zod/yup/joi/pydantic". The finding lands on the
18
+ * client-side call so the fix is visible where the developer is working.
19
+ *
20
+ * Preconditions to fire:
21
+ * 1. Graph mode (`ctx.allConcepts` populated).
22
+ * 2. Client concept has `bodyKind === 'dynamic'` — we know real data is
23
+ * crossing the wire, not a ping/HEAD/etc.
24
+ * 3. Client target path matches a server route in the graph.
25
+ * 4. That server route's container has NO `guard` concept with
26
+ * `subtype === 'validation'` (schema.parse / zod.parse / …).
27
+ *
28
+ * Silent on `bodyKind === undefined` (mapper couldn't classify) and on
29
+ * missing server matches (contract-drift owns that class).
30
+ */
31
+ import type { ReviewFinding } from '../types.js';
32
+ import type { ConceptRuleContext } from './index.js';
33
+ export declare function taintedAcrossWire(ctx: ConceptRuleContext): ReviewFinding[];
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Rule: tainted-across-wire
3
+ *
4
+ * Cross-stack rule — fires when a frontend (TS) network call sends a
5
+ * dynamic (user-controlled) body to a server-side route in the reviewed
6
+ * project AND that route's handler has no validation guard in scope.
7
+ *
8
+ * This is rule #3 of the fullstack wedge. Pure server-side taint analysis
9
+ * (already in @kernlang/review's taint-crossfile module) finds sinks
10
+ * reachable from `req.body`, but it can't see the *client-side call site*
11
+ * that's feeding the unvalidated input. And pure client-side analysis
12
+ * doesn't know whether the server validates — so it either fires on every
13
+ * dynamic POST (noise) or on none (misses the moat).
14
+ *
15
+ * By correlating both sides via the concept graph we can fire precisely:
16
+ * "here's the fetch that sends user input to an endpoint whose handler
17
+ * doesn't parse it with zod/yup/joi/pydantic". The finding lands on the
18
+ * client-side call so the fix is visible where the developer is working.
19
+ *
20
+ * Preconditions to fire:
21
+ * 1. Graph mode (`ctx.allConcepts` populated).
22
+ * 2. Client concept has `bodyKind === 'dynamic'` — we know real data is
23
+ * crossing the wire, not a ping/HEAD/etc.
24
+ * 3. Client target path matches a server route in the graph.
25
+ * 4. That server route's container has NO `guard` concept with
26
+ * `subtype === 'validation'` (schema.parse / zod.parse / …).
27
+ *
28
+ * Silent on `bodyKind === undefined` (mapper couldn't classify) and on
29
+ * missing server matches (contract-drift owns that class).
30
+ */
31
+ import { createFingerprint } from '../types.js';
32
+ import { API_PATH_RE, CROSS_STACK_HEURISTIC_CONFIDENCE, collectRoutesAcrossGraph, findMatchingRoute, normalizeClientUrl, } from './cross-stack-utils.js';
33
+ export function taintedAcrossWire(ctx) {
34
+ if (!ctx.allConcepts || ctx.allConcepts.size === 0)
35
+ return [];
36
+ const serverRoutes = collectRoutesAcrossGraph(ctx.allConcepts);
37
+ if (serverRoutes.length === 0)
38
+ return [];
39
+ // Build the set of files that contain at least one validation guard.
40
+ // Container-level matching is too strict: zod/yup parsers typically live
41
+ // inside the route callback body (arrow function container) while the
42
+ // route entrypoint itself is emitted at the call-expression level (module
43
+ // container). File-level matching is coarser but safer — it silences the
44
+ // common case where a validator exists in the same server file as the
45
+ // route, which is a strong signal the handler is guarded. False negatives
46
+ // (a validation-less route in a file that validates *other* routes) cost
47
+ // us less than false positives on the pitch.
48
+ const validatedFiles = collectValidatedFiles(ctx.allConcepts);
49
+ const findings = [];
50
+ const localConcepts = ctx.allConcepts.get(ctx.filePath) ?? ctx.concepts;
51
+ for (const node of localConcepts.nodes) {
52
+ if (node.kind !== 'effect' || node.payload.kind !== 'effect' || node.payload.subtype !== 'network')
53
+ continue;
54
+ if (node.payload.bodyKind !== 'dynamic')
55
+ continue;
56
+ const target = node.payload.target;
57
+ if (typeof target !== 'string')
58
+ continue;
59
+ const normalized = normalizeClientUrl(target);
60
+ if (!normalized || !API_PATH_RE.test(normalized))
61
+ continue;
62
+ const matchedRoute = findMatchingRoute(normalized, serverRoutes);
63
+ if (!matchedRoute)
64
+ continue; // contract-drift owns the "wrong URL" class.
65
+ const routeFile = matchedRoute.node?.primarySpan.file;
66
+ if (routeFile && validatedFiles.has(routeFile))
67
+ continue;
68
+ findings.push({
69
+ source: 'kern',
70
+ ruleId: 'tainted-across-wire',
71
+ severity: 'warning',
72
+ category: 'pattern',
73
+ message: `Dynamic body sent to \`${target}\` but the matching server route has no validation guard (schema.parse / zod / yup / pydantic). Add a validator on the server before trusting the payload, or move validation to the client if this endpoint is internal-only.`,
74
+ primarySpan: node.primarySpan,
75
+ fingerprint: createFingerprint('tainted-across-wire', node.primarySpan.startLine, node.primarySpan.startCol),
76
+ confidence: node.confidence * CROSS_STACK_HEURISTIC_CONFIDENCE,
77
+ });
78
+ }
79
+ return findings;
80
+ }
81
+ function collectValidatedFiles(allConcepts) {
82
+ const set = new Set();
83
+ for (const [file, conceptMap] of allConcepts) {
84
+ for (const node of conceptMap.nodes) {
85
+ if (node.kind !== 'guard' || node.payload.kind !== 'guard')
86
+ continue;
87
+ if (node.payload.subtype !== 'validation')
88
+ continue;
89
+ set.add(file);
90
+ break;
91
+ }
92
+ }
93
+ return set;
94
+ }
95
+ //# sourceMappingURL=tainted-across-wire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tainted-across-wire.js","sourceRoot":"","sources":["../../src/concept-rules/tainted-across-wire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Rule: untyped-api-response
3
+ *
4
+ * Cross-stack rule — fires when a frontend (TS) network call targets a
5
+ * server-side route in the reviewed project AND consumes the JSON body
6
+ * without a type annotation, `as T` cast, or `satisfies T` clause.
7
+ *
8
+ * This is rule #2 of the fullstack wedge (TS ↔ Python/Express). The server
9
+ * has a declared response shape (Pydantic `response_model=`, Express
10
+ * `Response<T>`, …) but the client is treating the payload as `any`, which
11
+ * means any breaking change in the response shape will silently rot the
12
+ * frontend at runtime. ESLint can catch "no-explicit-any" at the TS level
13
+ * but it can't tell you *which* fetch() is actually talking to a project
14
+ * endpoint — only the concept graph knows that.
15
+ *
16
+ * Preconditions to fire:
17
+ * 1. Graph mode (`ctx.allConcepts` populated).
18
+ * 2. Client concept has `responseAsserted === false` (mapper proved the
19
+ * .json() consumption is untyped).
20
+ * 3. The call's target path matches a server-side route in the graph —
21
+ * otherwise this is just a generic untyped-fetch case, which Biome
22
+ * already covers and we don't want to duplicate.
23
+ *
24
+ * Kept conservative: when the mapper returns `undefined` for
25
+ * responseAsserted (patterns it couldn't analyze) the rule stays silent.
26
+ * False positives here would poison the pitch.
27
+ */
28
+ import type { ReviewFinding } from '../types.js';
29
+ import type { ConceptRuleContext } from './index.js';
30
+ export declare function untypedApiResponse(ctx: ConceptRuleContext): ReviewFinding[];
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Rule: untyped-api-response
3
+ *
4
+ * Cross-stack rule — fires when a frontend (TS) network call targets a
5
+ * server-side route in the reviewed project AND consumes the JSON body
6
+ * without a type annotation, `as T` cast, or `satisfies T` clause.
7
+ *
8
+ * This is rule #2 of the fullstack wedge (TS ↔ Python/Express). The server
9
+ * has a declared response shape (Pydantic `response_model=`, Express
10
+ * `Response<T>`, …) but the client is treating the payload as `any`, which
11
+ * means any breaking change in the response shape will silently rot the
12
+ * frontend at runtime. ESLint can catch "no-explicit-any" at the TS level
13
+ * but it can't tell you *which* fetch() is actually talking to a project
14
+ * endpoint — only the concept graph knows that.
15
+ *
16
+ * Preconditions to fire:
17
+ * 1. Graph mode (`ctx.allConcepts` populated).
18
+ * 2. Client concept has `responseAsserted === false` (mapper proved the
19
+ * .json() consumption is untyped).
20
+ * 3. The call's target path matches a server-side route in the graph —
21
+ * otherwise this is just a generic untyped-fetch case, which Biome
22
+ * already covers and we don't want to duplicate.
23
+ *
24
+ * Kept conservative: when the mapper returns `undefined` for
25
+ * responseAsserted (patterns it couldn't analyze) the rule stays silent.
26
+ * False positives here would poison the pitch.
27
+ */
28
+ import { createFingerprint } from '../types.js';
29
+ import { API_PATH_RE, CROSS_STACK_HEURISTIC_CONFIDENCE, collectRoutesAcrossGraph, findMatchingRoute, isFastApiRouteMissingResponseModel, normalizeClientUrl, } from './cross-stack-utils.js';
30
+ export function untypedApiResponse(ctx) {
31
+ if (!ctx.allConcepts || ctx.allConcepts.size === 0)
32
+ return [];
33
+ const serverRoutes = collectRoutesAcrossGraph(ctx.allConcepts);
34
+ if (serverRoutes.length === 0)
35
+ return [];
36
+ const findings = [];
37
+ // Only scan this file's concepts so we don't duplicate findings per call.
38
+ const localConcepts = ctx.allConcepts.get(ctx.filePath) ?? ctx.concepts;
39
+ for (const node of localConcepts.nodes) {
40
+ if (node.kind !== 'effect' || node.payload.kind !== 'effect' || node.payload.subtype !== 'network')
41
+ continue;
42
+ if (node.payload.responseAsserted !== false)
43
+ continue; // undefined stays silent
44
+ const target = node.payload.target;
45
+ if (typeof target !== 'string')
46
+ continue;
47
+ const normalized = normalizeClientUrl(target);
48
+ if (!normalized || !API_PATH_RE.test(normalized))
49
+ continue;
50
+ const matchedRoute = findMatchingRoute(normalized, serverRoutes);
51
+ if (!matchedRoute)
52
+ continue;
53
+ if (matchedRoute.node &&
54
+ isFastApiRouteMissingResponseModel(matchedRoute.node, ctx.allConcepts.get(matchedRoute.node.primarySpan.file))) {
55
+ continue;
56
+ }
57
+ findings.push({
58
+ source: 'kern',
59
+ ruleId: 'untyped-api-response',
60
+ severity: 'warning',
61
+ category: 'bug',
62
+ message: `Response from \`${target}\` is consumed without a type annotation. The server route defines a response shape — assign the awaited value to a typed variable or use \`as T\` / \`satisfies T\` so response-shape drift is caught at compile time instead of breaking at runtime.`,
63
+ primarySpan: node.primarySpan,
64
+ fingerprint: createFingerprint('untyped-api-response', node.primarySpan.startLine, node.primarySpan.startCol),
65
+ // Same tier as contract-drift. Upgrade once the Python mapper surfaces
66
+ // `response_model=` and we can also cite the specific server type the
67
+ // frontend should be asserting against.
68
+ confidence: node.confidence * CROSS_STACK_HEURISTIC_CONFIDENCE,
69
+ });
70
+ }
71
+ return findings;
72
+ }
73
+ //# sourceMappingURL=untyped-api-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"untyped-api-response.js","sourceRoot":"","sources":["../../src/concept-rules/untyped-api-response.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,WAAW,EACX,gCAAgC,EAChC,wBAAwB,EACxB,iBAAiB,EACjB,kCAAkC,EAClC,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAGhC,MAAM,UAAU,kBAAkB,CAAC,GAAuB;IACxD,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,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEzC,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,0EAA0E;IAC1E,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC;IACxE,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS;YAAE,SAAS;QAC7G,IAAI,IAAI,CAAC,OAAO,CAAC,gBAAgB,KAAK,KAAK;YAAE,SAAS,CAAC,yBAAyB;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACnC,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,SAAS;QACzC,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,SAAS;QAC3D,MAAM,YAAY,GAAG,iBAAiB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACjE,IAAI,CAAC,YAAY;YAAE,SAAS;QAC5B,IACE,YAAY,CAAC,IAAI;YACjB,kCAAkC,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAC9G,CAAC;YACD,SAAS;QACX,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,sBAAsB;YAC9B,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,mBAAmB,MAAM,wPAAwP;YAC1R,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,iBAAiB,CAAC,sBAAsB,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;YAC7G,uEAAuE;YACvE,sEAAsE;YACtE,wCAAwC;YACxC,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,gCAAgC;SAC/D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Rule: untyped-both-ends-response
3
+ *
4
+ * Cross-stack linker for the response typing wedge. Fires when the client
5
+ * consumes a matching API response without a type assertion and the Python
6
+ * server route also has no `response_model=...`.
7
+ */
8
+ import type { ReviewFinding } from '../types.js';
9
+ import type { ConceptRuleContext } from './index.js';
10
+ export declare function untypedBothEndsResponse(ctx: ConceptRuleContext): ReviewFinding[];
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Rule: untyped-both-ends-response
3
+ *
4
+ * Cross-stack linker for the response typing wedge. Fires when the client
5
+ * consumes a matching API response without a type assertion and the Python
6
+ * server route also has no `response_model=...`.
7
+ */
8
+ import { createFingerprint } from '../types.js';
9
+ import { API_PATH_RE, CROSS_STACK_HEURISTIC_CONFIDENCE, collectRoutesAcrossGraph, findMatchingRoute, isFastApiRouteMissingResponseModel, normalizeClientUrl, } from './cross-stack-utils.js';
10
+ export function untypedBothEndsResponse(ctx) {
11
+ if (!ctx.allConcepts || ctx.allConcepts.size === 0)
12
+ return [];
13
+ const allConcepts = ctx.allConcepts;
14
+ const routesMissingModel = collectRoutesAcrossGraph(allConcepts).filter((route) => routeMissingResponseModel(route, allConcepts));
15
+ if (routesMissingModel.length === 0)
16
+ return [];
17
+ const findings = [];
18
+ const localConcepts = allConcepts.get(ctx.filePath) ?? ctx.concepts;
19
+ for (const node of localConcepts.nodes) {
20
+ if (node.language !== 'ts')
21
+ continue;
22
+ if (node.kind !== 'effect' || node.payload.kind !== 'effect' || node.payload.subtype !== 'network')
23
+ continue;
24
+ if (node.payload.responseAsserted !== false)
25
+ continue;
26
+ const target = node.payload.target;
27
+ if (typeof target !== 'string')
28
+ continue;
29
+ const normalized = normalizeClientUrl(target);
30
+ if (!normalized || !API_PATH_RE.test(normalized))
31
+ continue;
32
+ const matchedRoute = findMatchingRoute(normalized, routesMissingModel);
33
+ if (!matchedRoute?.node)
34
+ continue;
35
+ findings.push({
36
+ source: 'kern',
37
+ ruleId: 'untyped-both-ends-response',
38
+ severity: 'warning',
39
+ category: 'bug',
40
+ message: `Response for \`${target}\` is untyped on both ends: the client consumes it without a type assertion and the matching backend route has no response_model.`,
41
+ primarySpan: node.primarySpan,
42
+ relatedSpans: [matchedRoute.node.primarySpan],
43
+ fingerprint: createFingerprint('untyped-both-ends-response', node.primarySpan.startLine, node.primarySpan.startCol),
44
+ confidence: Math.min(node.confidence, matchedRoute.node.confidence) * CROSS_STACK_HEURISTIC_CONFIDENCE,
45
+ });
46
+ }
47
+ return findings;
48
+ }
49
+ function routeMissingResponseModel(route, allConcepts) {
50
+ const node = route.node;
51
+ if (!node)
52
+ return false;
53
+ return isFastApiRouteMissingResponseModel(node, allConcepts.get(node.primarySpan.file));
54
+ }
55
+ //# sourceMappingURL=untyped-both-ends-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"untyped-both-ends-response.js","sourceRoot":"","sources":["../../src/concept-rules/untyped-both-ends-response.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,WAAW,EACX,gCAAgC,EAChC,wBAAwB,EACxB,iBAAiB,EACjB,kCAAkC,EAClC,kBAAkB,GAEnB,MAAM,wBAAwB,CAAC;AAGhC,MAAM,UAAU,uBAAuB,CAAC,GAAuB;IAC7D,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9D,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;IAEpC,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAChF,yBAAyB,CAAC,KAAK,EAAE,WAAW,CAAC,CAC9C,CAAC;IACF,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE/C,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC;IAEpE,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;YAAE,SAAS;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS;YAAE,SAAS;QAC7G,IAAI,IAAI,CAAC,OAAO,CAAC,gBAAgB,KAAK,KAAK;YAAE,SAAS;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACnC,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,SAAS;QACzC,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,SAAS;QAC3D,MAAM,YAAY,GAAG,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QACvE,IAAI,CAAC,YAAY,EAAE,IAAI;YAAE,SAAS;QAElC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,4BAA4B;YACpC,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,kBAAkB,MAAM,mIAAmI;YACpK,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC;YAC7C,WAAW,EAAE,iBAAiB,CAC5B,4BAA4B,EAC5B,IAAI,CAAC,WAAW,CAAC,SAAS,EAC1B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAC1B;YACD,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,gCAAgC;SACvG,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAkB,EAAE,WAA4C;IACjG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,OAAO,kCAAkC,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1F,CAAC"}
@@ -22,10 +22,23 @@ import type { InferResult, ReviewFinding } from './types.js';
22
22
  export declare function runESLint(filePaths: string[], cwd: string, health?: ReviewHealthBuilder): Promise<ReviewFinding[]>;
23
23
  export interface RunTSCDiagnosticsOptions {
24
24
  /**
25
- * When true, suppress TS6059/TS6307 project-loading diagnostics. Set this only for callers that
26
- * inject ad-hoc files into a Project that carries a host tsconfig those two codes then fire as
27
- * infrastructure noise, not user bugs. The --lint path must leave this false so a real tsconfig
28
- * misconfiguration still surfaces as an error.
25
+ * When true, suppress TS diagnostics that fire as kern-review infrastructure noise when we inject
26
+ * ad-hoc files into a Project that carries a host tsconfig. Suppressed codes fall into two classes:
27
+ *
28
+ * Project membership (in-memory Project vs host rootDir):
29
+ * - TS6059 — "File is not listed within the file list of project"
30
+ * - TS6307 — "File is not under 'rootDir'"
31
+ *
32
+ * Environmental (in-memory Project doesn't mirror host compilerOptions — moduleResolution, jsx, lib):
33
+ * - TS2792 — "Cannot find module X. Did you mean to set 'moduleResolution' to 'nodenext'?"
34
+ * - TS17004 — "Cannot use JSX unless the '--jsx' flag is provided"
35
+ * - TS2580 / TS2591 — "Cannot find name 'process'/'require'/'module'" (@types/node missing)
36
+ *
37
+ * The dev already sees the environmental class in their IDE / local `tsc --noEmit` when real.
38
+ * Set this only for the standard review path. The --lint path must leave it false so real
39
+ * tsconfig misconfigurations still surface as errors.
40
+ *
41
+ * The name is kept for backward compatibility; scope broadened deliberately.
29
42
  */
30
43
  downgradeProjectLoadingErrors?: boolean;
31
44
  }
@@ -151,8 +151,19 @@ export function runTSCDiagnostics(project, options = {}, health) {
151
151
  // them as info still pollutes every barrel/re-export report in composite monorepos.
152
152
  // ts6059 — "File is not listed within the file list of project"
153
153
  // ts6307 — "File is not under 'rootDir'"
154
+ // The following codes are environmental: they reflect ts-morph's in-memory Project not
155
+ // perfectly mirroring the host's compilerOptions (moduleResolution, jsx, lib). The dev
156
+ // already sees them in their IDE / local `tsc --noEmit` if real; the review's value-add
157
+ // is KERN-relevant findings, not duplicating compiler output. A sweep of the agon repo
158
+ // (451 files) emitted 1869 of these as errors — pure noise drowning real findings.
159
+ // ts2792 — "Cannot find module X. Did you mean to set 'moduleResolution' to 'nodenext'?"
160
+ // ts17004 — "Cannot use JSX unless the '--jsx' flag is provided"
161
+ // ts2580 / ts2591 — "Cannot find name 'process'/'require'/'module'. Install @types/node?"
162
+ // (TS emits 2580 when the name resolves via global lib shims, 2591 when it doesn't —
163
+ // both point at the same user-side remedy, both are environmental from review's POV.)
154
164
  const isLoadingNoise = code === 6059 || code === 6307;
155
- if (isLoadingNoise && options.downgradeProjectLoadingErrors) {
165
+ const isEnvironmentalNoise = code === 2792 || code === 17004 || code === 2580 || code === 2591;
166
+ if ((isLoadingNoise || isEnvironmentalNoise) && options.downgradeProjectLoadingErrors) {
156
167
  continue;
157
168
  }
158
169
  findings.push({
@@ -1 +1 @@
1
- {"version":3,"file":"external-tools.js","sourceRoot":"","sources":["../src/external-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"external-tools.js","sourceRoot":"","sources":["../src/external-tools.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export { resolveImportGraph } from './graph.js';
24
24
  export { findTsConfig, inferFromFile, inferFromSource } from './inferrer.js';
25
25
  export type { KernLintRule } from './kern-lint.js';
26
26
  export { flattenIR, lintKernIR } from './kern-lint.js';
27
- export type { LLMBridgeConfig, LLMReviewInput, ReviewInstructionOptions } from './llm-bridge.js';
27
+ export type { LLMBridgeConfig, LLMCallResult, LLMReviewInput, LLMReviewResult, LLMUsage, ReviewInstructionOptions, } from './llm-bridge.js';
28
28
  export { buildReviewInstructions, isLLMAvailable, runLLMReview } from './llm-bridge.js';
29
29
  export type { LLMGraphContext } from './llm-review.js';
30
30
  export { buildLLMPrompt, exportKernIR, parseLLMResponse } from './llm-review.js';
@@ -81,6 +81,7 @@ export declare function resetFsProject(): void;
81
81
  export declare function refreshFsProjectFromDisk(): number;
82
82
  /** True when the file is codegen output — detected via common path patterns or a @generated header. */
83
83
  export declare function isGeneratedFile(filePath: string, source?: string): boolean;
84
+ export declare function isReviewableFile(filePath: string): boolean;
84
85
  /**
85
86
  * Review a single file. Auto-detects language from extension.
86
87
  * Uses a filesystem-backed ts-morph Project for type-aware analysis.