@critiq/rules 0.0.1

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 (121) hide show
  1. package/README.md +169 -0
  2. package/catalog.yaml +599 -0
  3. package/package.json +21 -0
  4. package/rules/shared/security.insecure-http-transport.rule.yaml +42 -0
  5. package/rules/shared/security.no-command-execution-with-request-input.rule.yaml +42 -0
  6. package/rules/shared/security.no-hardcoded-credentials.rule.yaml +42 -0
  7. package/rules/shared/security.no-request-path-file-read.rule.yaml +42 -0
  8. package/rules/shared/security.no-sensitive-data-in-logs-and-telemetry.rule.yaml +44 -0
  9. package/rules/shared/security.no-sql-interpolation.rule.yaml +42 -0
  10. package/rules/shared/security.tls-verification-disabled.rule.yaml +42 -0
  11. package/rules/shared/security.unsafe-deserialization.rule.yaml +41 -0
  12. package/rules/shared/security.weak-hash-algorithm.rule.yaml +41 -0
  13. package/rules/typescript/ts.config.no-process-env-outside-config.rule.yaml +37 -0
  14. package/rules/typescript/ts.correctness.blocking-call-in-async-flow.rule.yaml +35 -0
  15. package/rules/typescript/ts.correctness.constant-condition.rule.yaml +35 -0
  16. package/rules/typescript/ts.correctness.implicit-undefined-return.rule.yaml +34 -0
  17. package/rules/typescript/ts.correctness.incorrect-boolean-logic.rule.yaml +35 -0
  18. package/rules/typescript/ts.correctness.missing-await-on-async-call.rule.yaml +35 -0
  19. package/rules/typescript/ts.correctness.missing-default-dispatch.rule.yaml +35 -0
  20. package/rules/typescript/ts.correctness.missing-timeout-on-external-call.rule.yaml +35 -0
  21. package/rules/typescript/ts.correctness.nested-property-access-without-check.rule.yaml +35 -0
  22. package/rules/typescript/ts.correctness.off-by-one-loop-boundary.rule.yaml +35 -0
  23. package/rules/typescript/ts.correctness.optional-value-without-fallback.rule.yaml +35 -0
  24. package/rules/typescript/ts.correctness.possible-null-dereference.rule.yaml +35 -0
  25. package/rules/typescript/ts.correctness.shared-state-race.rule.yaml +35 -0
  26. package/rules/typescript/ts.correctness.unchecked-map-key-access.rule.yaml +35 -0
  27. package/rules/typescript/ts.correctness.unhandled-async-error.rule.yaml +35 -0
  28. package/rules/typescript/ts.correctness.unreachable-statement.rule.yaml +40 -0
  29. package/rules/typescript/ts.logging.no-console-error.rule.yaml +34 -0
  30. package/rules/typescript/ts.logging.no-console-log.rule.yaml +34 -0
  31. package/rules/typescript/ts.next.no-server-client-boundary-leaks.rule.yaml +36 -0
  32. package/rules/typescript/ts.performance.inefficient-data-structure-usage.rule.yaml +35 -0
  33. package/rules/typescript/ts.performance.large-payload-without-streaming.rule.yaml +35 -0
  34. package/rules/typescript/ts.performance.missing-batch-operations.rule.yaml +35 -0
  35. package/rules/typescript/ts.performance.nested-loops-hot-path.rule.yaml +35 -0
  36. package/rules/typescript/ts.performance.repeated-expensive-computation.rule.yaml +35 -0
  37. package/rules/typescript/ts.performance.repeated-io-in-loop.rule.yaml +35 -0
  38. package/rules/typescript/ts.performance.retained-large-object.rule.yaml +35 -0
  39. package/rules/typescript/ts.performance.sequential-async-calls.rule.yaml +35 -0
  40. package/rules/typescript/ts.performance.unbounded-growth-memory-leak.rule.yaml +35 -0
  41. package/rules/typescript/ts.performance.unnecessary-rerenders-from-state-misuse.rule.yaml +35 -0
  42. package/rules/typescript/ts.quality.deep-nesting.rule.yaml +35 -0
  43. package/rules/typescript/ts.quality.duplicate-code-block.rule.yaml +35 -0
  44. package/rules/typescript/ts.quality.function-too-large-or-complex.rule.yaml +35 -0
  45. package/rules/typescript/ts.quality.hardcoded-configuration-values.rule.yaml +35 -0
  46. package/rules/typescript/ts.quality.logic-change-without-test-updates.rule.yaml +36 -0
  47. package/rules/typescript/ts.quality.magic-numbers-or-strings.rule.yaml +35 -0
  48. package/rules/typescript/ts.quality.missing-error-context.rule.yaml +35 -0
  49. package/rules/typescript/ts.quality.missing-tests-for-critical-logic.rule.yaml +35 -0
  50. package/rules/typescript/ts.quality.swallowed-error.rule.yaml +35 -0
  51. package/rules/typescript/ts.quality.tight-module-coupling.rule.yaml +35 -0
  52. package/rules/typescript/ts.random.no-math-random-in-core.rule.yaml +37 -0
  53. package/rules/typescript/ts.react.no-cascaded-effect-fetches.rule.yaml +37 -0
  54. package/rules/typescript/ts.runtime.no-debugger-statement.rule.yaml +29 -0
  55. package/rules/typescript/ts.security.bind-to-all-interfaces.rule.yaml +36 -0
  56. package/rules/typescript/ts.security.browser-token-storage.rule.yaml +37 -0
  57. package/rules/typescript/ts.security.dangerous-insert-html.rule.yaml +36 -0
  58. package/rules/typescript/ts.security.dangerously-set-inner-html.rule.yaml +38 -0
  59. package/rules/typescript/ts.security.datadog-browser-track-user-interactions.rule.yaml +37 -0
  60. package/rules/typescript/ts.security.debug-mode-enabled.rule.yaml +38 -0
  61. package/rules/typescript/ts.security.dynamodb-query-injection.rule.yaml +36 -0
  62. package/rules/typescript/ts.security.exposed-directory-listing.rule.yaml +37 -0
  63. package/rules/typescript/ts.security.express-cookie-missing-http-only.rule.yaml +36 -0
  64. package/rules/typescript/ts.security.express-default-cookie-config.rule.yaml +39 -0
  65. package/rules/typescript/ts.security.express-default-session-config.rule.yaml +37 -0
  66. package/rules/typescript/ts.security.express-insecure-cookie.rule.yaml +36 -0
  67. package/rules/typescript/ts.security.express-missing-helmet.rule.yaml +37 -0
  68. package/rules/typescript/ts.security.express-nosql-injection.rule.yaml +36 -0
  69. package/rules/typescript/ts.security.express-permissive-cookie-config.rule.yaml +38 -0
  70. package/rules/typescript/ts.security.express-reduce-fingerprint.rule.yaml +37 -0
  71. package/rules/typescript/ts.security.express-static-assets-after-session.rule.yaml +37 -0
  72. package/rules/typescript/ts.security.external-file-upload.rule.yaml +36 -0
  73. package/rules/typescript/ts.security.file-generation.rule.yaml +36 -0
  74. package/rules/typescript/ts.security.format-string-using-user-input.rule.yaml +36 -0
  75. package/rules/typescript/ts.security.frontend-only-authorization.rule.yaml +35 -0
  76. package/rules/typescript/ts.security.handlebars-no-escape.rule.yaml +38 -0
  77. package/rules/typescript/ts.security.hardcoded-auth-secret.rule.yaml +37 -0
  78. package/rules/typescript/ts.security.import-using-user-input.rule.yaml +36 -0
  79. package/rules/typescript/ts.security.information-leakage.rule.yaml +38 -0
  80. package/rules/typescript/ts.security.insecure-allow-origin.rule.yaml +36 -0
  81. package/rules/typescript/ts.security.insecure-auth-cookie-flags.rule.yaml +37 -0
  82. package/rules/typescript/ts.security.insecure-password-hash-configuration.rule.yaml +37 -0
  83. package/rules/typescript/ts.security.insecure-websocket-transport.rule.yaml +37 -0
  84. package/rules/typescript/ts.security.insufficiently-random-values.rule.yaml +36 -0
  85. package/rules/typescript/ts.security.jwt-not-revoked.rule.yaml +37 -0
  86. package/rules/typescript/ts.security.jwt-sensitive-claims.rule.yaml +37 -0
  87. package/rules/typescript/ts.security.manual-html-sanitization.rule.yaml +37 -0
  88. package/rules/typescript/ts.security.missing-authorization-before-sensitive-action.rule.yaml +35 -0
  89. package/rules/typescript/ts.security.missing-integrity-check.rule.yaml +36 -0
  90. package/rules/typescript/ts.security.missing-message-origin-check.rule.yaml +36 -0
  91. package/rules/typescript/ts.security.missing-ownership-validation.rule.yaml +35 -0
  92. package/rules/typescript/ts.security.missing-request-timeout-or-retry.rule.yaml +35 -0
  93. package/rules/typescript/ts.security.no-dynamic-execution.rule.yaml +34 -0
  94. package/rules/typescript/ts.security.no-innerhtml-assignment.rule.yaml +36 -0
  95. package/rules/typescript/ts.security.non-literal-fs-filename.rule.yaml +36 -0
  96. package/rules/typescript/ts.security.observable-timing-discrepancy.rule.yaml +37 -0
  97. package/rules/typescript/ts.security.open-redirect.rule.yaml +37 -0
  98. package/rules/typescript/ts.security.permissive-allow-origin.rule.yaml +36 -0
  99. package/rules/typescript/ts.security.permissive-file-permissions.rule.yaml +37 -0
  100. package/rules/typescript/ts.security.postmessage-wildcard-origin.rule.yaml +36 -0
  101. package/rules/typescript/ts.security.predictable-token-generation.rule.yaml +36 -0
  102. package/rules/typescript/ts.security.raw-html-using-user-input.rule.yaml +37 -0
  103. package/rules/typescript/ts.security.sensitive-data-egress.rule.yaml +36 -0
  104. package/rules/typescript/ts.security.sensitive-data-in-exception.rule.yaml +37 -0
  105. package/rules/typescript/ts.security.sensitive-data-written-to-file.rule.yaml +37 -0
  106. package/rules/typescript/ts.security.ssrf.rule.yaml +34 -0
  107. package/rules/typescript/ts.security.token-or-session-not-validated.rule.yaml +35 -0
  108. package/rules/typescript/ts.security.ui-redress.rule.yaml +37 -0
  109. package/rules/typescript/ts.security.unsanitized-http-response.rule.yaml +36 -0
  110. package/rules/typescript/ts.security.unvalidated-external-input.rule.yaml +35 -0
  111. package/rules/typescript/ts.security.user-controlled-sendfile.rule.yaml +36 -0
  112. package/rules/typescript/ts.security.user-controlled-view-render.rule.yaml +36 -0
  113. package/rules/typescript/ts.security.weak-cipher-or-mode.rule.yaml +35 -0
  114. package/rules/typescript/ts.security.weak-key-strength.rule.yaml +36 -0
  115. package/rules/typescript/ts.security.weak-tls-version.rule.yaml +36 -0
  116. package/src/index.d.ts +1 -0
  117. package/src/index.js +5 -0
  118. package/src/index.js.map +1 -0
  119. package/src/lib/rules-package.d.ts +3 -0
  120. package/src/lib/rules-package.js +16 -0
  121. package/src/lib/rules-package.js.map +1 -0
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.optional-value-without-fallback
5
+ title: Optional value used without fallback
6
+ summary: Optional values should be normalized before arithmetic, concatenation, or other direct use.
7
+ rationale: Using maybe-undefined values in ordinary expressions bakes uncertainty into the result and can fail or stringify unexpectedly at runtime.
8
+ tags:
9
+ - correctness
10
+ - "null"
11
+ - rules-catalog
12
+ - crq-cor-004
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: data-flow.optional-value-without-fallback
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.null
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - correctness
30
+ - "null"
31
+ message:
32
+ title: Normalize optional values before using them
33
+ summary: "`${captures.issue.text}` uses a maybe-missing value without a fallback."
34
+ remediation:
35
+ summary: Add `??`, `||`, or an explicit guard so the expression always receives a defined value.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.possible-null-dereference
5
+ title: Possible null or undefined dereference
6
+ summary: Nullable values should be guarded before property access or invocation.
7
+ rationale: Dereferencing a value that can still be null or undefined causes avoidable runtime failures on common unhappy paths.
8
+ tags:
9
+ - correctness
10
+ - "null"
11
+ - rules-catalog
12
+ - crq-cor-001
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: data-flow.possible-null-dereference
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.null
26
+ severity: high
27
+ confidence: 0.85
28
+ tags:
29
+ - correctness
30
+ - "null"
31
+ message:
32
+ title: Guard nullable values before dereferencing
33
+ summary: "`${captures.issue.text}` dereferences a value that may still be null or undefined."
34
+ remediation:
35
+ summary: Add an explicit guard, use optional chaining deliberately, or provide a fallback before dereferencing the value.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.shared-state-race
5
+ title: Race condition on shared state
6
+ summary: Async functions that mutate shared state after an await boundary should be reviewed for races.
7
+ rationale: Mutating outer-scope or instance state after suspension can interleave with concurrent callers and corrupt shared state.
8
+ tags:
9
+ - correctness
10
+ - concurrency
11
+ - rules-catalog
12
+ - crq-cor-015
13
+ stability: experimental
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: concurrency.shared-state-race
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.concurrency
26
+ severity: high
27
+ confidence: 0.65
28
+ tags:
29
+ - correctness
30
+ - concurrency
31
+ message:
32
+ title: Review shared-state mutation across await boundaries
33
+ summary: "`${captures.issue.text}` mutates shared state after async suspension."
34
+ remediation:
35
+ summary: Isolate the state per request, serialize access, or move the mutation before the await boundary.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.unchecked-map-key-access
5
+ title: Unchecked map or dictionary key access
6
+ summary: Lookups should verify key presence before reading from maps or keyed objects.
7
+ rationale: Missing-key reads often flow undefined deeper into the function and fail far away from the original lookup.
8
+ tags:
9
+ - correctness
10
+ - data-access
11
+ - rules-catalog
12
+ - crq-cor-003
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: data-flow.unchecked-map-key-access
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.data-access
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - correctness
30
+ - data-access
31
+ message:
32
+ title: Guard keyed lookups before reading values
33
+ summary: "`${captures.issue.text}` reads from a keyed collection without checking whether the key is present."
34
+ remediation:
35
+ summary: Check `has`, `in`, or `Object.hasOwn` before reading, or provide a safe default when the key is missing.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.unhandled-async-error
5
+ title: Unhandled promise rejection or async error
6
+ summary: Promise chains started in a function should terminate with explicit rejection handling.
7
+ rationale: Floating `.then(...)` chains without a terminal catch can reject outside the intended error-handling path and make failures hard to trace.
8
+ tags:
9
+ - correctness
10
+ - async
11
+ - rules-catalog
12
+ - crq-cor-012
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: async.unhandled-async-error
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.async
26
+ severity: high
27
+ confidence: 0.85
28
+ tags:
29
+ - correctness
30
+ - async
31
+ message:
32
+ title: Handle async rejections explicitly
33
+ summary: Review `${captures.issue.text}` and terminate the promise chain with rejection handling.
34
+ remediation:
35
+ summary: Await the operation in a try/catch block or attach a terminal `.catch(...)` handler to the promise chain.
@@ -0,0 +1,40 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.unreachable-statement
5
+ title: Unreachable code after return or throw
6
+ summary: Statements after terminal exits should be removed or moved before the exit.
7
+ rationale: Dead statements obscure intent and often indicate a refactor that left stale logic behind.
8
+ tags:
9
+ - correctness
10
+ - control-flow
11
+ - rules-catalog
12
+ - crq-cor-010
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: control-flow.unreachable-statement
22
+ bind: issue
23
+ where:
24
+ - path: reason
25
+ in:
26
+ - after-return
27
+ - after-throw
28
+ emit:
29
+ finding:
30
+ category: correctness.control-flow
31
+ severity: low
32
+ confidence: 0.95
33
+ tags:
34
+ - correctness
35
+ - control-flow
36
+ message:
37
+ title: Remove unreachable statement
38
+ summary: "`${captures.issue.text}` cannot execute because control flow already terminated."
39
+ remediation:
40
+ summary: Delete the dead statement or move it before the return or throw.
@@ -0,0 +1,34 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.logging.no-console-error
5
+ title: Avoid console.error
6
+ summary: Route error logs through the project logger.
7
+ rationale: Console error calls bypass the shared logging pipeline.
8
+ tags:
9
+ - logging
10
+ - rules-catalog
11
+ scope:
12
+ languages:
13
+ - typescript
14
+ match:
15
+ node:
16
+ kind: CallExpression
17
+ bind: call
18
+ where:
19
+ - path: callee.object.text
20
+ equals: console
21
+ - path: callee.property.text
22
+ equals: error
23
+ emit:
24
+ finding:
25
+ category: maintainability
26
+ severity: medium
27
+ confidence: high
28
+ tags:
29
+ - logging
30
+ message:
31
+ title: Avoid `${captures.call.text}`
32
+ summary: Route `${captures.call.text}` through the project logger.
33
+ remediation:
34
+ summary: Replace `${captures.call.text}` with the logger.
@@ -0,0 +1,34 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.logging.no-console-log
5
+ title: Avoid console.log
6
+ summary: Use the project logger instead of console.log.
7
+ rationale: Console logging bypasses the shared logger pipeline.
8
+ tags:
9
+ - logging
10
+ - rules-catalog
11
+ scope:
12
+ languages:
13
+ - typescript
14
+ match:
15
+ node:
16
+ kind: CallExpression
17
+ bind: call
18
+ where:
19
+ - path: callee.object.text
20
+ equals: console
21
+ - path: callee.property.text
22
+ equals: log
23
+ emit:
24
+ finding:
25
+ category: maintainability
26
+ severity: low
27
+ confidence: high
28
+ tags:
29
+ - logging
30
+ message:
31
+ title: Avoid `${captures.call.text}`
32
+ summary: Use the project logger instead of `${captures.call.text}`.
33
+ remediation:
34
+ summary: Replace `${captures.call.text}` with the logger.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.next.no-server-client-boundary-leaks
5
+ title: Avoid server/client boundary leaks in Next.js
6
+ summary: Server components should not use browser-only APIs or client-only hooks without an explicit client boundary.
7
+ rationale: Browser globals and client-only hooks break server rendering boundaries and make component intent unclear.
8
+ tags:
9
+ - next
10
+ - react
11
+ - rules-catalog
12
+ stability: experimental
13
+ appliesTo: file
14
+ scope:
15
+ languages:
16
+ - typescript
17
+ - javascript
18
+ match:
19
+ fact:
20
+ kind: framework.next-server-client-boundary-leak
21
+ bind: issue
22
+ emit:
23
+ finding:
24
+ category: correctness.framework
25
+ severity: high
26
+ confidence: 0.8
27
+ tags:
28
+ - next
29
+ - react
30
+ - correctness
31
+ message:
32
+ title: Add a client boundary before using browser-only APIs
33
+ summary: "`${captures.issue.text}` uses a browser-only API or client-only hook in a server file."
34
+ remediation:
35
+ summary: Add `'use client'` or move the code into a client component or hook.
36
+
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.inefficient-data-structure-usage
5
+ title: Inefficient data structure usage
6
+ summary: Linear membership checks or key projections should be reviewed for more suitable lookup structures.
7
+ rationale: Repeated array scans or `Object.keys(...).includes(...)` patterns are often avoidable with `Set`, `Map`, or direct key checks.
8
+ tags:
9
+ - performance
10
+ - algorithmic
11
+ - rules-catalog
12
+ - crq-per-034
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.inefficient-data-structure-usage
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.algorithmic
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - performance
30
+ - algorithmic
31
+ message:
32
+ title: Prefer a more efficient lookup structure
33
+ summary: "`${captures.issue.text}` uses a linear lookup where a dedicated structure would be cheaper."
34
+ remediation:
35
+ summary: Replace repeated array scans with `Set` or `Map`, or use direct key existence checks instead of projecting keys first.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.large-payload-without-streaming
5
+ title: Large payload processing without streaming
6
+ summary: Whole-payload reads of likely large content should be reviewed for streaming alternatives.
7
+ rationale: Pulling large payloads into memory increases latency and memory pressure compared with streaming or chunked processing.
8
+ tags:
9
+ - performance
10
+ - memory-io
11
+ - rules-catalog
12
+ - crq-per-037
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.large-payload-without-streaming
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.memory-io
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - performance
30
+ - memory-io
31
+ message:
32
+ title: Stream large payloads when practical
33
+ summary: "`${captures.issue.text}` reads likely large payload data into memory at once."
34
+ remediation:
35
+ summary: Prefer `createReadStream`, iterator-based parsing, or chunked processing for large files and binary payloads.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.missing-batch-operations
5
+ title: Missing batching of operations
6
+ summary: Repeated one-by-one operations inside loops should prefer available batch-style helpers.
7
+ rationale: Batch APIs usually reduce round trips, contention, and request overhead compared with item-at-a-time loops.
8
+ tags:
9
+ - performance
10
+ - io
11
+ - rules-catalog
12
+ - crq-per-036
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.missing-batch-operations
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.io
26
+ severity: medium
27
+ confidence: 0.75
28
+ tags:
29
+ - performance
30
+ - io
31
+ message:
32
+ title: Prefer batch helpers over one-by-one loops
33
+ summary: "`${captures.issue.text}` runs one item at a time even though a batch-style helper appears available."
34
+ remediation:
35
+ summary: Replace the per-item loop with the available batch or bulk helper, or add one if the dependency already supports it.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.nested-loops-hot-path
5
+ title: Nested loops in hot path (O(n²) risk)
6
+ summary: Nested loops in the same function should be reviewed for quadratic work on larger inputs.
7
+ rationale: Nested iteration often becomes the dominant cost on hot paths and usually benefits from indexing or precomputation.
8
+ tags:
9
+ - performance
10
+ - algorithmic
11
+ - rules-catalog
12
+ - crq-per-031
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.nested-loops-hot-path
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.algorithmic
26
+ severity: medium
27
+ confidence: 0.75
28
+ tags:
29
+ - performance
30
+ - algorithmic
31
+ message:
32
+ title: Review nested loops on hot paths
33
+ summary: "`${captures.issue.text}` nests loops and may introduce quadratic work."
34
+ remediation:
35
+ summary: Precompute lookups, index one side with a set or map, or otherwise flatten the repeated scan.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.repeated-expensive-computation
5
+ title: Repeated expensive computation
6
+ summary: Repeating the same expensive computation in one block should usually be cached.
7
+ rationale: Recomputing the same serialization, key projection, or formatter construction wastes CPU and obscures intent.
8
+ tags:
9
+ - performance
10
+ - compute
11
+ - rules-catalog
12
+ - crq-per-032
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.repeated-expensive-computation
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.compute
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - performance
30
+ - compute
31
+ message:
32
+ title: Cache repeated expensive work
33
+ summary: "`${captures.issue.text}` repeats expensive computation in the same block."
34
+ remediation:
35
+ summary: Compute the value once, store it in a local binding, and reuse the cached result.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.repeated-io-in-loop
5
+ title: Repeated IO call inside loop
6
+ summary: Database or network calls inside loops can multiply latency and load.
7
+ rationale: Per-item IO in loops often turns one operation into N round trips and is a common performance bottleneck.
8
+ tags:
9
+ - performance
10
+ - io
11
+ - rules-catalog
12
+ - crq-per-033
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.repeated-io-in-loop
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.io
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - performance
30
+ - io
31
+ message:
32
+ title: Avoid repeated IO calls inside loops
33
+ summary: "`${captures.issue.text}` performs IO inside a loop and can multiply latency."
34
+ remediation:
35
+ summary: Move the IO outside the loop, batch the work, or fetch the required data in one call before iterating.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.retained-large-object
5
+ title: Unnecessarily retained large object
6
+ summary: Large payloads assigned into shared state should be reviewed for shorter lifetimes.
7
+ rationale: Retaining large buffers or payload objects longer than needed increases memory pressure and GC churn.
8
+ tags:
9
+ - performance
10
+ - memory
11
+ - rules-catalog
12
+ - crq-per-039
13
+ stability: experimental
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.retained-large-object
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.memory
26
+ severity: medium
27
+ confidence: 0.65
28
+ tags:
29
+ - performance
30
+ - memory
31
+ message:
32
+ title: Avoid retaining large payloads in shared state
33
+ summary: Review `${captures.issue.text}` and release large payload objects as soon as possible.
34
+ remediation:
35
+ summary: Keep the payload local, persist only the fields you need, or clear the shared reference after use.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.sequential-async-calls
5
+ title: Sequential async calls that could run in parallel
6
+ summary: Independent awaited calls in the same block should not serialize unnecessarily.
7
+ rationale: Awaiting unrelated async operations one by one increases end-to-end latency without adding correctness.
8
+ tags:
9
+ - performance
10
+ - async
11
+ - rules-catalog
12
+ - crq-per-035
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.sequential-async-calls
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.async
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - performance
30
+ - async
31
+ message:
32
+ title: Parallelize independent async calls
33
+ summary: "`${captures.issue.text}` is awaited after an independent async call and may serialize work unnecessarily."
34
+ remediation:
35
+ summary: Start both operations first and await them together, for example with `Promise.all(...)`.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.unbounded-growth-memory-leak
5
+ title: Potential memory leak from unbounded growth
6
+ summary: Shared collections that only grow should be reviewed for eviction or lifecycle boundaries.
7
+ rationale: Appending to long-lived state without a cap can leak memory across requests or over process lifetime.
8
+ tags:
9
+ - performance
10
+ - memory
11
+ - rules-catalog
12
+ - crq-per-038
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.unbounded-growth-memory-leak
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.memory
26
+ severity: high
27
+ confidence: 0.75
28
+ tags:
29
+ - performance
30
+ - memory
31
+ message:
32
+ title: Bound long-lived collection growth
33
+ summary: Review `${captures.issue.text}` for unbounded growth of shared state.
34
+ remediation:
35
+ summary: Add eviction, scoping, or cleanup so the collection cannot grow forever across calls.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.performance.unnecessary-rerenders-from-state-misuse
5
+ title: Unnecessary re-renders from state misuse
6
+ summary: React state setters invoked directly during render should be reviewed for rerender loops.
7
+ rationale: Calling a state setter during render can trigger avoidable rerenders and unstable component behavior.
8
+ tags:
9
+ - performance
10
+ - ui
11
+ - rules-catalog
12
+ - crq-per-040
13
+ stability: experimental
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: performance.unnecessary-rerenders-from-state-misuse
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: performance.ui
26
+ severity: medium
27
+ confidence: 0.7
28
+ tags:
29
+ - performance
30
+ - ui
31
+ message:
32
+ title: Avoid render-path state updates
33
+ summary: Review `${captures.issue.text}` and move state updates out of the render path.
34
+ remediation:
35
+ summary: Trigger the state update from an event, effect, or transition instead of directly during render.