prr-kit 1.1.2 → 1.2.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 (173) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +260 -235
  3. package/docs/assets/banner.svg +33 -165
  4. package/docs/assets/how-it-works.svg +87 -0
  5. package/package.json +60 -60
  6. package/src/core/agents/prr-master.agent.yaml +18 -7
  7. package/src/core/tasks/clear.md +140 -0
  8. package/src/core/tasks/help.md +15 -13
  9. package/src/core/workflows/clear/workflow.md +6 -0
  10. package/src/core/workflows/help/workflow.md +6 -0
  11. package/src/core/workflows/party-mode/steps/step-01-load-reviewers.md +35 -24
  12. package/src/core/workflows/party-mode/steps/step-02-discussion.md +45 -25
  13. package/src/core/workflows/party-mode/workflow.md +2 -2
  14. package/src/prr/agents/architecture-reviewer.agent.yaml +65 -45
  15. package/src/prr/agents/business-reviewer.agent.yaml +66 -0
  16. package/src/prr/agents/general-reviewer.agent.yaml +64 -48
  17. package/src/prr/agents/performance-reviewer.agent.yaml +65 -45
  18. package/src/prr/agents/security-reviewer.agent.yaml +67 -43
  19. package/src/prr/config-template.yaml +97 -0
  20. package/src/prr/data/stacks/actix.md +55 -0
  21. package/src/prr/data/stacks/alpine.md +47 -0
  22. package/src/prr/data/stacks/android.md +53 -0
  23. package/src/prr/data/stacks/angular.md +96 -0
  24. package/src/prr/data/stacks/ansible.md +55 -0
  25. package/src/prr/data/stacks/apollo.md +54 -0
  26. package/src/prr/data/stacks/astro.md +48 -0
  27. package/src/prr/data/stacks/aws-cdk.md +55 -0
  28. package/src/prr/data/stacks/axum.md +56 -0
  29. package/src/prr/data/stacks/babylonjs.md +55 -0
  30. package/src/prr/data/stacks/bash.md +53 -0
  31. package/src/prr/data/stacks/bevy.md +53 -0
  32. package/src/prr/data/stacks/bootstrap.md +52 -0
  33. package/src/prr/data/stacks/bun.md +55 -0
  34. package/src/prr/data/stacks/cpp.md +57 -0
  35. package/src/prr/data/stacks/csharp.md +95 -0
  36. package/src/prr/data/stacks/css.md +55 -0
  37. package/src/prr/data/stacks/cypress.md +53 -0
  38. package/src/prr/data/stacks/d3.md +53 -0
  39. package/src/prr/data/stacks/deno.md +49 -0
  40. package/src/prr/data/stacks/django.md +92 -0
  41. package/src/prr/data/stacks/docker.md +79 -0
  42. package/src/prr/data/stacks/drizzle.md +54 -0
  43. package/src/prr/data/stacks/dynamodb.md +55 -0
  44. package/src/prr/data/stacks/electron.md +44 -0
  45. package/src/prr/data/stacks/elixir.md +53 -0
  46. package/src/prr/data/stacks/expo.md +53 -0
  47. package/src/prr/data/stacks/expressjs.md +82 -0
  48. package/src/prr/data/stacks/fastapi.md +88 -0
  49. package/src/prr/data/stacks/fastify.md +60 -0
  50. package/src/prr/data/stacks/fiber.md +55 -0
  51. package/src/prr/data/stacks/firebase.md +43 -0
  52. package/src/prr/data/stacks/flask.md +46 -0
  53. package/src/prr/data/stacks/flutter.md +75 -0
  54. package/src/prr/data/stacks/gin.md +57 -0
  55. package/src/prr/data/stacks/github-actions.md +71 -0
  56. package/src/prr/data/stacks/go.md +88 -0
  57. package/src/prr/data/stacks/godot.md +56 -0
  58. package/src/prr/data/stacks/graphql.md +76 -0
  59. package/src/prr/data/stacks/grpc.md +56 -0
  60. package/src/prr/data/stacks/haskell.md +48 -0
  61. package/src/prr/data/stacks/helm.md +54 -0
  62. package/src/prr/data/stacks/hono.md +54 -0
  63. package/src/prr/data/stacks/htmx.md +38 -0
  64. package/src/prr/data/stacks/java.md +87 -0
  65. package/src/prr/data/stacks/jest-vitest.md +87 -0
  66. package/src/prr/data/stacks/jquery.md +50 -0
  67. package/src/prr/data/stacks/junit.md +53 -0
  68. package/src/prr/data/stacks/kotlin.md +89 -0
  69. package/src/prr/data/stacks/kubernetes.md +148 -0
  70. package/src/prr/data/stacks/langchain.md +56 -0
  71. package/src/prr/data/stacks/laravel.md +56 -0
  72. package/src/prr/data/stacks/libgdx.md +46 -0
  73. package/src/prr/data/stacks/lit.md +49 -0
  74. package/src/prr/data/stacks/love2d.md +51 -0
  75. package/src/prr/data/stacks/lua.md +51 -0
  76. package/src/prr/data/stacks/mobx.md +54 -0
  77. package/src/prr/data/stacks/mongodb.md +85 -0
  78. package/src/prr/data/stacks/monogame.md +51 -0
  79. package/src/prr/data/stacks/mysql.md +57 -0
  80. package/src/prr/data/stacks/nestjs.md +95 -0
  81. package/src/prr/data/stacks/nextjs.md +88 -0
  82. package/src/prr/data/stacks/nginx.md +55 -0
  83. package/src/prr/data/stacks/node.md +56 -0
  84. package/src/prr/data/stacks/nuxtjs.md +91 -0
  85. package/src/prr/data/stacks/openai-api.md +54 -0
  86. package/src/prr/data/stacks/opengl.md +54 -0
  87. package/src/prr/data/stacks/phaser.md +54 -0
  88. package/src/prr/data/stacks/phoenix.md +55 -0
  89. package/src/prr/data/stacks/php.md +56 -0
  90. package/src/prr/data/stacks/playwright.md +86 -0
  91. package/src/prr/data/stacks/postgresql.md +60 -0
  92. package/src/prr/data/stacks/prisma.md +81 -0
  93. package/src/prr/data/stacks/pygame.md +52 -0
  94. package/src/prr/data/stacks/pytest.md +53 -0
  95. package/src/prr/data/stacks/python.md +94 -0
  96. package/src/prr/data/stacks/pytorch.md +54 -0
  97. package/src/prr/data/stacks/qwik.md +50 -0
  98. package/src/prr/data/stacks/rails.md +48 -0
  99. package/src/prr/data/stacks/react-native.md +77 -0
  100. package/src/prr/data/stacks/react.md +104 -0
  101. package/src/prr/data/stacks/redis.md +76 -0
  102. package/src/prr/data/stacks/redux.md +107 -0
  103. package/src/prr/data/stacks/remix.md +51 -0
  104. package/src/prr/data/stacks/rust.md +88 -0
  105. package/src/prr/data/stacks/sass.md +51 -0
  106. package/src/prr/data/stacks/scala.md +50 -0
  107. package/src/prr/data/stacks/scikit-learn.md +53 -0
  108. package/src/prr/data/stacks/sequelize.md +54 -0
  109. package/src/prr/data/stacks/socket-io.md +54 -0
  110. package/src/prr/data/stacks/solidity.md +53 -0
  111. package/src/prr/data/stacks/solidjs.md +45 -0
  112. package/src/prr/data/stacks/spring-boot.md +92 -0
  113. package/src/prr/data/stacks/sql.md +85 -0
  114. package/src/prr/data/stacks/sqlite.md +55 -0
  115. package/src/prr/data/stacks/styled-components.md +51 -0
  116. package/src/prr/data/stacks/supabase.md +57 -0
  117. package/src/prr/data/stacks/svelte.md +77 -0
  118. package/src/prr/data/stacks/sveltekit.md +54 -0
  119. package/src/prr/data/stacks/swift.md +61 -0
  120. package/src/prr/data/stacks/tailwindcss.md +10 -0
  121. package/src/prr/data/stacks/tanstack-query.md +48 -0
  122. package/src/prr/data/stacks/tauri.md +52 -0
  123. package/src/prr/data/stacks/terraform.md +53 -0
  124. package/src/prr/data/stacks/three.md +53 -0
  125. package/src/prr/data/stacks/trpc.md +49 -0
  126. package/src/prr/data/stacks/typeorm.md +40 -0
  127. package/src/prr/data/stacks/typescript.md +83 -0
  128. package/src/prr/data/stacks/unity.md +61 -0
  129. package/src/prr/data/stacks/unreal.md +58 -0
  130. package/src/prr/data/stacks/vite.md +48 -0
  131. package/src/prr/data/stacks/vue3.md +95 -0
  132. package/src/prr/data/stacks/vulkan.md +53 -0
  133. package/src/prr/data/stacks/wasm.md +49 -0
  134. package/src/prr/data/stacks/webpack.md +48 -0
  135. package/src/prr/data/stacks/zig.md +51 -0
  136. package/src/prr/data/stacks/zustand.md +56 -0
  137. package/src/prr/workflows/1-discover/select-pr/steps/step-05-confirm.md +1 -0
  138. package/src/prr/workflows/1-discover/select-pr/workflow.md +1 -1
  139. package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-01-analyze-files.md +334 -0
  140. package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-02-collect-sources.md +451 -0
  141. package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-03-build-knowledge-base.md +337 -0
  142. package/src/prr/workflows/2-analyze/collect-pr-context/workflow.md +123 -0
  143. package/src/prr/workflows/2-analyze/describe-pr/steps/step-02-classify.md +12 -6
  144. package/src/prr/workflows/2-analyze/describe-pr/steps/step-03-walkthrough.md +59 -1
  145. package/src/prr/workflows/3-review/architecture-review/checklist.md +4 -0
  146. package/src/prr/workflows/3-review/architecture-review/instructions.xml +32 -4
  147. package/src/prr/workflows/3-review/architecture-review/workflow.yaml +17 -18
  148. package/src/prr/workflows/3-review/business-review/checklist.md +27 -0
  149. package/src/prr/workflows/3-review/business-review/instructions.xml +153 -0
  150. package/src/prr/workflows/3-review/business-review/workflow.yaml +17 -0
  151. package/src/prr/workflows/3-review/general-review/checklist.md +5 -1
  152. package/src/prr/workflows/3-review/general-review/instructions.xml +39 -8
  153. package/src/prr/workflows/3-review/general-review/workflow.yaml +17 -18
  154. package/src/prr/workflows/3-review/performance-review/checklist.md +3 -1
  155. package/src/prr/workflows/3-review/performance-review/instructions.xml +10 -3
  156. package/src/prr/workflows/3-review/performance-review/workflow.yaml +17 -18
  157. package/src/prr/workflows/3-review/security-review/checklist.md +2 -1
  158. package/src/prr/workflows/3-review/security-review/instructions.xml +8 -3
  159. package/src/prr/workflows/3-review/security-review/workflow.yaml +18 -19
  160. package/src/prr/workflows/4-improve/improve-code/workflow.yaml +17 -18
  161. package/src/prr/workflows/6-report/generate-report/steps/step-01-collect.md +9 -2
  162. package/src/prr/workflows/6-report/generate-report/steps/step-02-organize.md +28 -7
  163. package/src/prr/workflows/6-report/generate-report/steps/step-03-write.md +6 -4
  164. package/src/prr/workflows/6-report/generate-report/templates/review-report.template.md +124 -78
  165. package/src/prr/workflows/6-report/post-comments/steps/step-01-format.md +104 -13
  166. package/src/prr/workflows/6-report/post-comments/steps/step-02-post.md +92 -21
  167. package/src/prr/workflows/6-report/post-comments/workflow.md +6 -0
  168. package/src/prr/workflows/quick/workflow.md +138 -32
  169. package/src/prr/workflows/0-setup/collect-project-context/steps/step-01-scan-configs.md +0 -106
  170. package/src/prr/workflows/0-setup/collect-project-context/steps/step-02-extract-rules.md +0 -131
  171. package/src/prr/workflows/0-setup/collect-project-context/steps/step-03-ask-context.md +0 -194
  172. package/src/prr/workflows/0-setup/collect-project-context/steps/step-04-save-context.md +0 -161
  173. package/src/prr/workflows/0-setup/collect-project-context/workflow.md +0 -58
@@ -0,0 +1,75 @@
1
+ # Flutter / Dart — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.dart` files · `pubspec.yaml` with `flutter:` · `import 'package:flutter/` · `Widget` · `StatefulWidget` · `BuildContext` · `Riverpod`/`Bloc`/`Provider`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[HIGH]** Sensitive data (tokens, passwords, PINs) in `SharedPreferences` → not encrypted. Use `flutter_secure_storage` (Keychain on iOS, Keystore on Android).
11
+ - **[HIGH]** `WebView` with `javaScriptMode: JavascriptMode.unrestricted` loading untrusted URLs → XSS, platform channel access.
12
+ - **[HIGH]** API keys hardcoded in Dart source → extracted from APK/IPA via reverse engineering. Use `--dart-define` or backend proxy.
13
+ - **[HIGH]** `dart:mirrors` used for dynamic invocation of user-controlled method names → code injection.
14
+ - **[MEDIUM]** Certificate validation disabled (custom `HttpClient.badCertificateCallback`) → MITM.
15
+ - **[MEDIUM]** `Platform.environment` in Flutter → may expose environment variables. Use `--dart-define` for build-time constants.
16
+ - **[MEDIUM]** Deep link params not validated → malicious intent triggers action with crafted data.
17
+ - **[LOW]** Debug flag (`kDebugMode`) not checked before logging sensitive data.
18
+
19
+ ---
20
+
21
+ ## Performance
22
+
23
+ - **[HIGH]** `setState()` on high-level ancestor for leaf change → rebuilds entire subtree. Use `Provider`/`Riverpod`/`ValueNotifier` to scope rebuilds.
24
+ - **[HIGH]** Heavy objects created inside `build()` → recreated on every rebuild. Move to `initState()` or `didChangeDependencies()`.
25
+ - **[HIGH]** `ListView` (non-builder) for dynamic/long lists → all items rendered. Use `ListView.builder()`.
26
+ - **[HIGH]** `FutureBuilder` without stable `future` reference → parent rebuild creates new Future, re-fetches every time. Store Future in `initState`.
27
+ - **[HIGH]** `const` constructor missing on stateless widgets → prevents subtree optimization.
28
+ - **[HIGH]** `build()` method doing I/O or heavy computation → blocks UI thread. Use `compute()` or `Isolate`.
29
+ - **[MEDIUM]** `Image.network` without `cacheWidth`/`cacheHeight` → full resolution decoded for small display.
30
+ - **[MEDIUM]** `AnimationController` not disposed → memory leak and assertion errors.
31
+ - **[MEDIUM]** `StreamBuilder` subscribing to broadcast stream that never closes → subscription held forever.
32
+ - **[LOW]** Not using `RepaintBoundary` to isolate frequently repainting widgets → whole tree repainted.
33
+ - **[LOW]** `Opacity` widget used for animations instead of `AnimatedOpacity` or `FadeTransition`.
34
+
35
+ ---
36
+
37
+ ## Architecture
38
+
39
+ - **[HIGH]** Business logic inside `Widget.build()` → hard to test. Use BLoC, Provider, Riverpod, or GetX.
40
+ - **[HIGH]** `BuildContext` used across `async` gap without `mounted` check → crash after navigation.
41
+ - **[HIGH]** `Navigator.pop()` called without checking navigator stack → `FlutterError` on first route.
42
+ - **[HIGH]** `StatefulWidget` used for everything → use `StatelessWidget` + state management for separation.
43
+ - **[MEDIUM]** `GetX` controller not bound to widget lifecycle → controller persists after widget destroyed.
44
+ - **[MEDIUM]** Not using `GoRouter` or `auto_route` for deep link + navigation → manual route management breaks.
45
+ - **[MEDIUM]** Platform channel not handling errors → unhandled exception on plugin failure.
46
+ - **[LOW]** Widget `build()` >100 lines → extract named sub-widgets or methods.
47
+ - **[LOW]** Not organizing code by feature → flat `lib/` directory with hundreds of files.
48
+
49
+ ---
50
+
51
+ ## Code Quality
52
+
53
+ - **[HIGH]** `dynamic` type used broadly → defeats Dart sound null safety. Use specific types or generics.
54
+ - **[HIGH]** `TextEditingController`/`FocusNode`/`ScrollController` not disposed → memory leak + debug assertion.
55
+ - **[HIGH]** `mounted` check missing after every `await` in `StatefulWidget` method.
56
+ - **[MEDIUM]** `print()` in production → use `debugPrint()` (no-op in release) or structured logging.
57
+ - **[MEDIUM]** Missing `Key` on list items → Flutter can't reconcile tree on reorder.
58
+ - **[MEDIUM]** `late` variables accessed before initialization → `LateInitializationError` at runtime.
59
+ - **[MEDIUM]** Nullable variable accessed with `!` without check → `Null check operator used on null value`.
60
+ - **[LOW]** Not running `flutter analyze` in CI → lint issues uncaught.
61
+ - **[LOW]** `pubspec.yaml` dependencies not version-pinned → unexpected breaking changes.
62
+
63
+ ---
64
+
65
+ ## Common Bugs & Pitfalls
66
+
67
+ - **[HIGH]** `async` `onPressed` without `mounted` check → `setState()` on unmounted widget.
68
+ - **[HIGH]** `Column` with `Expanded` inside `ListView` → layout exception (unbounded height). Use `shrinkWrap` or restructure.
69
+ - **[HIGH]** `StreamController` not closed → memory leak and lint warning.
70
+ - **[MEDIUM]** `Image.network` without `errorBuilder` → broken image shown silently.
71
+ - **[MEDIUM]** `FocusNode.dispose()` not called → memory leak.
72
+ - **[MEDIUM]** `Riverpod` provider accessed after widget disposed → `ProviderScope` not found error.
73
+ - **[MEDIUM]** `WillPopScope` deprecated (Flutter 3.12+) → use `PopScope` with `canPop` instead.
74
+ - **[LOW]** `ThemeData` not using `ColorScheme.fromSeed` (Material 3) → inconsistent colors.
75
+ - **[LOW]** Not testing on both iOS and Android → platform-specific bugs missed.
@@ -0,0 +1,57 @@
1
+ # Gin — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: "github.com/gin-gonic/gin", gin.Default(), gin.New(), c.JSON(, c.ShouldBindJSON, r.GET(, r.POST(
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** `c.ShouldBind` used without validation struct tags → unvalidated user input reaches business logic. Always define and enforce validation tags (`binding:"required"`, `validate:"email"`, etc.) on all bound structs.
10
+ - **[CRITICAL]** SQL injection via `fmt.Sprintf` in database queries → attacker-controlled input alters query structure. Always use parameterized queries or an ORM with prepared statements.
11
+ - **[HIGH]** Missing CORS configuration or wildcard CORS (`"*"`) in production → cross-origin requests accepted from any domain. Configure explicit allowed origins via gin-cors middleware.
12
+ - **[HIGH]** No rate limiting middleware → DoS attacks succeed without throttling. Integrate a rate limiter such as `golang.org/x/time/rate` or a middleware library.
13
+ - **[HIGH]** Server binding to `0.0.0.0` in production without TLS → traffic transmitted in plaintext over network. Terminate TLS at the load balancer or configure `tls.ListenAndServeTLS`.
14
+ - **[HIGH]** SSRF via user-controlled URL in proxy or fetch handlers → attacker triggers requests to internal services. Validate and whitelist allowed URL schemes and hosts before making server-side requests.
15
+ - **[MEDIUM]** Sensitive data (tokens, passwords) logged in debug mode → secrets appear in log files accessible to operators. Use structured logging with field redaction and disable debug logs in production.
16
+ - **[MEDIUM]** Missing input length limits on string fields → oversized payloads cause excessive memory allocation or ReDoS in regex validators. Enforce maximum lengths in validation tags or middleware.
17
+
18
+ ---
19
+
20
+ ## Performance
21
+ - **[HIGH]** Debug mode (`gin.Default()`) used in production → verbose logging and color output add unnecessary overhead. Use `gin.New()` with explicit middleware and set `GIN_MODE=release`.
22
+ - **[MEDIUM]** No response caching for static or slow-changing data → repeated expensive queries for identical data on every request. Add cache-control headers or an in-memory cache layer.
23
+ - **[MEDIUM]** Synchronous database calls in handlers without goroutines for independent queries → sequential round-trips increase total response latency. Use goroutines with `errgroup` for parallel independent DB calls.
24
+ - **[MEDIUM]** Large JSON marshaling of full structs without streaming → entire response built in memory before sending. For very large datasets, use streaming encoders or pagination.
25
+ - **[LOW]** Missing gzip middleware for large responses → uncompressed payloads increase bandwidth and client latency. Add `github.com/gin-contrib/gzip` to the middleware stack.
26
+ - **[MEDIUM]** Allocating large slices with fixed capacity inside handlers → GC pressure accumulates under load. Pre-allocate with realistic capacity estimates or use sync.Pool for reusable buffers.
27
+ - **[MEDIUM]** Not using Gin route groups for common middleware (e.g., auth, logging) → middleware applied redundantly or inconsistently across routes. Use `r.Group()` with shared middleware.
28
+
29
+ ---
30
+
31
+ ## Architecture
32
+ - **[HIGH]** Business logic implemented in handler functions instead of a service layer → handlers become large, untestable, and tightly coupled to HTTP. Extract logic into service structs with well-defined interfaces.
33
+ - **[HIGH]** Not using dependency injection → hardcoded global DB connections and singletons make testing impossible and hide coupling. Pass dependencies (DB, logger, services) through handler structs or closures.
34
+ - **[MEDIUM]** Route groups not organized by domain or API version → route file becomes a flat, unnavigable list as the app grows. Group related routes with `r.Group("/api/v1/")` and domain prefixes.
35
+ - **[MEDIUM]** Middleware not scoped appropriately to route groups → auth or logging middleware applied globally when only needed for specific paths. Attach middleware at the group level, not globally.
36
+ - **[MEDIUM]** No graceful shutdown handling → in-flight requests dropped when the process receives SIGTERM. Implement `srv.Shutdown(ctx)` on SIGTERM/SIGINT signals.
37
+ - **[LOW]** Single router file containing all route definitions → file grows unwieldy in large applications. Split route registration into per-domain files and register them in the main router setup.
38
+
39
+ ---
40
+
41
+ ## Code Quality
42
+ - **[HIGH]** Missing `binding:"required"` tags on struct fields → optional fields treated as present when absent, leading to zero-value data passing validation silently. Tag all required fields explicitly.
43
+ - **[MEDIUM]** Not using `c.Error()` for error accumulation during request processing → multiple errors not collected, only the last one surfaced. Use `c.Error(err)` and a centralized error handler middleware.
44
+ - **[MEDIUM]** Handler returning `nil` error for all code paths → callers cannot differentiate success from business-logic errors. Return meaningful typed errors and let the error handler map them to HTTP status codes.
45
+ - **[HIGH]** `c.Abort()` not called after `c.JSON()` in error path → handler chain continues executing after error response is sent. Always call `c.Abort()` when sending an early response in middleware.
46
+ - **[MEDIUM]** Missing API versioning strategy → breaking changes break existing clients without warning. Use route groups with version prefixes (`/api/v1`) and document deprecation timelines.
47
+ - **[LOW]** Not using Gin's custom validator tags via `validator.RegisterValidation` → complex validation rules duplicated across handlers. Register custom validators once and reference them via struct tags.
48
+
49
+ ---
50
+
51
+ ## Common Bugs & Pitfalls
52
+ - **[MEDIUM]** Confusing `c.ShouldBindJSON` with `c.BindJSON` → `c.BindJSON` writes a 400 response automatically on error, preventing custom error handling. Prefer `c.ShouldBindJSON` and handle errors explicitly.
53
+ - **[CRITICAL]** Handler goroutine using `c *gin.Context` after the request ends → Gin reuses context objects, causing data races and panics. Copy needed values before launching goroutines; never pass `c` directly.
54
+ - **[MEDIUM]** `gin.Recovery()` swallowing panics silently in production without custom handler → panics logged at error level but client gets a generic 500 with no alerting. Replace with a custom recovery middleware that triggers alerting.
55
+ - **[LOW]** Route params and paths being case-sensitive with trailing slash issues → clients get unexpected 404s due to URL casing or missing slash. Configure `RedirectTrailingSlash` and document case sensitivity.
56
+ - **[HIGH]** Not validating `Content-Type` header before binding → unexpected content type causes a 400 error that is hard to debug. Check content-type early and return a clear error message.
57
+ - **[MEDIUM]** Ignoring errors from `c.JSON()` or `c.String()` → write failures go undetected. Log write errors or use a response wrapper that captures write errors.
@@ -0,0 +1,71 @@
1
+ # GitHub Actions Stack Rules
2
+
3
+ Detection signals: `.github/workflows/*.yml`, `.github/workflows/*.yaml`, `on:` trigger, `jobs:`, `steps:`, `uses:`, `runs-on:`, `actions/checkout`
4
+
5
+ ---
6
+
7
+ ## Security
8
+
9
+ - **[CRITICAL]** User-controlled data interpolated directly in a `run:` step via expressions like `github.event.issue.title` passed as shell arguments → script injection allows an attacker to execute arbitrary commands with the runner's permissions. Always pass untrusted input via an env var and reference as `$VAR` in shell, never inline the expression.
10
+ - **[CRITICAL]** `pull_request_target` trigger checking out and running code from the PR branch → this event runs with write permissions and access to secrets; a malicious PR can exfiltrate the `GITHUB_TOKEN` or deploy credentials. Never checkout the PR ref in `pull_request_target` without strict branch restrictions and required approvals.
11
+ - **[CRITICAL]** Secrets echoed or logged in run steps → GitHub masks known secret values but transformed or encoded forms may still leak. Never echo, log, or interpolate secrets into shell output; pass them only as environment variables to commands that need them.
12
+ - **[HIGH]** Actions pinned by mutable tag (e.g. `uses: actions/checkout@v4`) rather than a full commit SHA → the tag can be moved or deleted, enabling a supply-chain attack that substitutes malicious code. Pin to full SHA with a tag comment: `uses: actions/checkout@11bd71901... # v4`.
13
+ - **[HIGH]** `permissions: write-all` or omitting the `permissions` key entirely (defaults to write on some repos) → the `GITHUB_TOKEN` is over-privileged, increasing the blast radius of any compromised step. Always declare minimal permissions per job.
14
+ - **[HIGH]** Self-hosted runner on shared infrastructure with no job isolation between runs → one workflow can read another job's secrets, artifacts, or working directory state. Use ephemeral self-hosted runners or GitHub-hosted runners for sensitive jobs.
15
+ - **[HIGH]** Workflow triggered on `pull_request` with write permissions and no approval requirement for fork PRs → fork PR can trigger a privileged workflow and leak secrets. Use environment protection rules with required reviewers for any job that accesses secrets.
16
+ - **[MEDIUM]** Third-party action from an unverified publisher without SHA pinning → the action could be compromised at any future point without warning. Fork the action into your own org, or pin to a specific commit SHA and audit the source.
17
+ - **[MEDIUM]** Secrets stored in repo-level env blocks visible in verbose runner logs → even masked secrets may appear in transformed form. Use step-level env blocks and minimize secret scope to the step that needs it.
18
+ - **[MEDIUM]** `GITHUB_TOKEN` used beyond its intended repository scope without explicit permission grant → scoping errors cause unexpected access or unexpected failures. Declare permissions explicitly; use fine-grained PATs for cross-repository operations.
19
+ - **[LOW]** Workflow files in public repositories not reviewed by a security-aware maintainer → any maintainer can introduce a step that exfiltrates secrets. Require CODEOWNERS review for all changes to `.github/workflows/`.
20
+ - **[LOW]** `continue-on-error: true` on security-sensitive steps such as secret rotation or audit submission → failure is silently ignored, leaving the system in an insecure state. Only use this on genuinely optional steps.
21
+
22
+ ---
23
+
24
+ ## Performance
25
+
26
+ - **[CRITICAL]** No dependency caching (`actions/cache` or setup action built-in cache) for package managers → npm/pip/maven/gradle install runs from scratch on every job, wasting 1-5 minutes. Cache with a key based on the lockfile hash using hashFiles.
27
+ - **[HIGH]** All steps in a single monolithic job with no parallelism → serial bottleneck; the job is as slow as the sum of all steps. Split into parallel jobs using the `needs:` dependency graph to run independent work concurrently.
28
+ - **[HIGH]** Uploading and downloading artifacts in every job when only specific jobs need them → unnecessary I/O and artifact storage costs. Upload once in the producing job; download only in jobs that explicitly need it.
29
+ - **[HIGH]** Matrix strategy not used for multi-platform or multi-version testing → sequential test runs instead of parallel. Use `strategy: matrix: { os: [...], node: [...] }` to test all combinations concurrently.
30
+ - **[MEDIUM]** Uploading large unused artifacts (full build directories, node_modules) → wastes storage quota and slows down the workflow summary. Filter artifacts to only the files needed by downstream jobs or for debugging.
31
+ - **[MEDIUM]** Missing `timeout-minutes` on jobs → a hung job (deadlocked process, waiting for user input) runs until the 6-hour GitHub default limit, burning paid minutes. Set an explicit timeout appropriate for each job.
32
+ - **[MEDIUM]** No concurrency cancellation for PR branch workflows → every push to a PR branch queues a new run while old runs are still active, wasting minutes. Add a concurrency group with cancel-in-progress: true for pull_request triggers.
33
+ - **[MEDIUM]** Running the full test suite on every push to every branch without path filtering → a docs-only change triggers a full 10-minute test run. Use `on: push: paths:` or `paths-ignore:` filters to skip irrelevant runs.
34
+ - **[LOW]** Tool installation repeated in every job because the runner environment is not cached → installing Node.js, Python, or other runtimes adds 30-60 seconds per job. Use setup actions (`actions/setup-node`) with their built-in caching options.
35
+ - **[LOW]** Not using composite actions or reusable workflows for repeated step sequences → the same 5-step build setup copy-pasted across 8 workflows drifts over time. Extract to a composite action or reusable workflow called via `uses:`.
36
+ - **[LOW]** Not gating expensive steps on PR draft status or fork conditions → expensive deployments and integration tests run on every commit including work-in-progress. Check `github.event.pull_request.draft` before expensive steps.
37
+ - **[LOW]** Not using `fetch-depth: 1` for jobs that do not need git history → full clone adds seconds on large repos. Add `fetch-depth: 1` to the checkout step for pure build/test jobs.
38
+
39
+ ---
40
+
41
+ ## Architecture
42
+
43
+ - **[HIGH]** All deployment and CI logic in a single monolithic workflow file → no reusability; every project duplicates the same steps. Extract shared logic to reusable workflows (`workflow_call`) or composite actions and call them from individual workflow files.
44
+ - **[HIGH]** Workflow triggered on push to main with no branch protection rules → direct pushes bypass PR review and immediately trigger production deployment. Enforce branch protection: require PR, status checks, and at least one review before merge.
45
+ - **[HIGH]** No environment protection rules on production deployment jobs → any branch or actor can trigger a production deploy. Use GitHub Environments with required reviewers and deployment wait timers for production.
46
+ - **[HIGH]** Repository-level secrets used across all workflows regardless of need → any workflow can read any repo secret, increasing blast radius of a compromised workflow. Use environment-scoped secrets that are only available to jobs targeting that environment.
47
+ - **[MEDIUM]** Environment URLs, account IDs, or regions hardcoded in workflow YAML → changing environments requires searching and editing all workflow files. Use GitHub Environments, the `vars` context, or repository variables for environment-specific values.
48
+ - **[MEDIUM]** No concurrency group on deployment workflows → parallel deployments to the same environment create race conditions and partial rollouts. Add a concurrency group per environment and cancel-in-progress or queue-based strategy.
49
+ - **[MEDIUM]** Reusable workflow not versioned with a release tag → callers get breaking changes automatically when the reusable workflow is updated. Tag reusable workflows with semver releases and have callers pin to a tag.
50
+ - **[MEDIUM]** Complex job dependency graph (needs:) not documented → multi-job DAGs are impossible to understand without a visual aid. Add a Mermaid diagram or ASCII art of the workflow DAG to the README or workflow file header.
51
+ - **[LOW]** No branch naming convention enforced on wildcard triggers → wildcard branch patterns in triggers match unintended branches. Document and enforce a branch naming convention (`feature/*`, `fix/*`) and use it in trigger patterns.
52
+ - **[LOW]** `workflow_dispatch` inputs not validated before use → integer or enum inputs arrive as strings; invalid values cause obscure errors in later steps. Validate all inputs in the first step and fail fast with a clear error message.
53
+ - **[LOW]** No staging environment between CI and production → code goes directly from CI green to production without a pre-production validation step. Add a staging environment job with a smoke test gate before the production deployment job.
54
+ - **[LOW]** Secrets shared between staging and production environments → a staging breach exposes production credentials. Use separate secret sets per environment; rotate independently.
55
+
56
+ ---
57
+
58
+ ## Code Quality
59
+
60
+ - **[HIGH]** Deprecated `set-output` command: `echo "::set-output name=foo::bar"` → command was removed; workflows using it silently fail or produce warnings. Replace with the environment file approach: `echo "foo=bar" >> 'GITHUB_OUTPUT var'`.
61
+ - **[HIGH]** Deprecated `set-env` command: `echo "::set-env name=VAR::val"` → command was disabled due to security vulnerabilities. Replace with: `echo "VAR=val" >> 'GITHUB_ENV var'`.
62
+ - **[HIGH]** Deprecated `add-path` command: `echo "::add-path::..."` → command was disabled. Replace with: `echo "/my/path" >> 'GITHUB_PATH var'`.
63
+ - **[HIGH]** `continue-on-error: true` on critical steps (build, test, security scan, deploy) → the job shows green even when a critical step fails, hiding real failures. Only use `continue-on-error` for genuinely optional steps; always check step outcome.
64
+ - **[MEDIUM]** Long inline shell scripts in `run:` blocks → inline scripts are untestable, unlintable, and hard to review. Extract scripts to files in the repository (`.github/scripts/`), test them locally, and call them from the workflow.
65
+ - **[MEDIUM]** Missing `defaults.run.shell` at workflow or job level → shell behavior differs across ubuntu, windows, and macos runners. Be explicit: set `defaults: run: shell: bash` to ensure consistent behavior.
66
+ - **[MEDIUM]** Hardcoded runner labels using specific OS versions (`ubuntu-20.04`) → end-of-life runners cause silent workflow failures when GitHub removes them. Use `ubuntu-latest` or document the pinned version and set a calendar reminder to update.
67
+ - **[MEDIUM]** Not using `fromJSON()` for complex expressions involving JSON manipulation → string operations on JSON in expression context are fragile and hard to debug. Use `fromJSON(steps.id.outputs.value)` to parse JSON outputs properly.
68
+ - **[MEDIUM]** YAML anchors not used for repeated step configurations (env vars, options) → the same environment variable block copy-pasted across 12 steps drifts when values change. Use YAML anchors and aliases to define once and reference many times.
69
+ - **[LOW]** Missing `if: always()` on cleanup or notification steps → these steps are skipped when a previous step fails, leaving cleanup undone and stakeholders uninformed. Add `if: always()` to steps that must run regardless of prior step outcome.
70
+ - **[LOW]** Workflow files not linted with `actionlint` or a similar tool → YAML syntax errors, unknown context references, and deprecated commands are only caught at runtime. Add `rhysd/actionlint` to a pre-commit hook or a dedicated lint workflow.
71
+ - **[LOW]** No comments explaining non-obvious workflow logic or permission grants → future maintainers cannot understand why a permission is needed or why a step exists. Add inline comments for all non-obvious decisions.
@@ -0,0 +1,88 @@
1
+ # Go — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.go` files, `go.mod`, `package main`, `func main()`, `goroutine`, `chan`, `go vet`, `golangci-lint`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** SQL query with `fmt.Sprintf` / string concatenation of user input → SQL injection. Use `db.Query("SELECT ... WHERE id = ?", userInput)`.
11
+ - **[CRITICAL]** `os/exec.Command` with user input as string to shell → command injection. Use argument list form.
12
+ - **[HIGH]** `html/template` replaced with `text/template` for HTML rendering → XSS, `text/template` doesn't escape.
13
+ - **[HIGH]** Sensitive data in error messages returned to client → info disclosure.
14
+ - **[HIGH]** `math/rand` for security-sensitive values (tokens, IDs) → predictable. Use `crypto/rand`.
15
+ - **[HIGH]** `filepath.Join` not used for user-controlled paths → path traversal via `../`.
16
+ - **[HIGH]** `http.ListenAndServe` without TLS in production → plaintext traffic.
17
+ - **[HIGH]** Goroutine spawned to handle request without context cancellation → goroutine leak on client disconnect.
18
+ - **[HIGH]** CORS wildcard with credentials in HTTP handler → credential leakage to any origin.
19
+ - **[MEDIUM]** Secrets loaded with `os.Getenv()` without validation for empty string → app runs with empty secret.
20
+ - **[MEDIUM]** Race condition on shared map without `sync.Mutex` or `sync.RWMutex`.
21
+ - **[LOW]** `regexp.MustCompile` with user input at runtime → panic on invalid regex.
22
+
23
+ ---
24
+
25
+ ## Performance
26
+
27
+ - **[HIGH]** Goroutine leak — goroutine started but never signaled to stop (no `ctx.Done()`, no WaitGroup) → memory grows indefinitely.
28
+ - **[HIGH]** Mutex held during I/O → blocks all goroutines waiting for lock.
29
+ - **[HIGH]** Unbuffered channel for high-frequency events → sender blocks on every send.
30
+ - **[HIGH]** `append` in tight loop without pre-allocated capacity → many reallocations. Use `make([]T, 0, knownSize)`.
31
+ - **[HIGH]** `fmt.Sprintf` in hot path for string building → use `strings.Builder`.
32
+ - **[HIGH]** Missing context timeout/deadline on HTTP client calls → requests hang indefinitely.
33
+ - **[HIGH]** `sync.Mutex` protecting large struct when `sync.RWMutex` allows parallel reads.
34
+ - **[MEDIUM]** Pointer to small struct unnecessarily → passing small structs by value is cheaper.
35
+ - **[MEDIUM]** `defer` inside loop → defers execute at function end, not loop end → resource exhaustion.
36
+ - **[MEDIUM]** Goroutine per request without worker pool → goroutine explosion under load.
37
+ - **[MEDIUM]** JSON marshaling/unmarshaling in hot path without pooling encoder/decoder.
38
+ - **[LOW]** `interface{}` / `any` in hot path → boxing/unboxing overhead.
39
+ - **[LOW]** Not using `sync.Pool` for frequently allocated/freed objects.
40
+
41
+ ---
42
+
43
+ ## Architecture
44
+
45
+ - **[HIGH]** Error ignored with `_` on operations that can fail → silent failures.
46
+ - **[HIGH]** Panic used for expected error conditions → use error returns. Panic only for programmer errors.
47
+ - **[HIGH]** Global mutable state (`var globalDB *sql.DB` mutated after init) → race conditions.
48
+ - **[HIGH]** `init()` functions doing side effects (DB init, file I/O) → hard to test, unpredictable order.
49
+ - **[HIGH]** Context not propagated through function call chain → cancellation doesn't work.
50
+ - **[MEDIUM]** Interface defined by implementer instead of consumer → breaks dependency inversion.
51
+ - **[MEDIUM]** Package names too generic (`util`, `common`, `helper`) → hard to discover.
52
+ - **[MEDIUM]** Struct embedding for code reuse when composition/interfaces cleaner → hidden method promotion.
53
+ - **[MEDIUM]** Not using `errors.Is()` / `errors.As()` for error inspection → string comparison brittle.
54
+ - **[MEDIUM]** Not using sentinel errors or custom error types → callers can't distinguish error categories.
55
+ - **[LOW]** Exported type without methods returning interface → unnecessary coupling.
56
+ - **[LOW]** Not using `go generate` for repetitive boilerplate.
57
+
58
+ ---
59
+
60
+ ## Code Quality
61
+
62
+ - **[HIGH]** Error not checked: `result, _ := someFunc()` when error indicates real failure.
63
+ - **[HIGH]** `defer file.Close()` after error check omitted → resource leak if `Open()` fails.
64
+ - **[HIGH]** Goroutine closure capturing loop variable → all goroutines use last value. Shadow: `v := v`.
65
+ - **[MEDIUM]** Named return values with naked `return` in long functions → confusing.
66
+ - **[MEDIUM]** Returning concrete type instead of interface from constructor → couples callers to implementation.
67
+ - **[MEDIUM]** Not using `golangci-lint` / `staticcheck` → issues not caught.
68
+ - **[MEDIUM]** `go vet` not run in CI → common mistakes missed.
69
+ - **[MEDIUM]** Test files not using `_test` package for black-box testing → testing internal state.
70
+ - **[LOW]** Missing `golint` compliance (exported types without comments).
71
+ - **[LOW]** Not using table-driven tests → duplicated test setup.
72
+
73
+ ---
74
+
75
+ ## Common Bugs & Pitfalls
76
+
77
+ - **[HIGH]** Loop variable captured by goroutine: `go func() { use(v) }()` in range → all use last value (fixed in Go 1.22).
78
+ - **[HIGH]** Map/slice concurrent read+write without mutex → data race, undefined behavior.
79
+ - **[HIGH]** `time.Sleep` for synchronization → use channels or `sync.WaitGroup`.
80
+ - **[HIGH]** `nil` interface vs nil concrete pointer — `interface{}` wrapping nil pointer is not `== nil`.
81
+ - **[HIGH]** `http.Response.Body` not closed after reading → connection leak.
82
+ - **[HIGH]** Goroutine panics not recovered → crashes entire program.
83
+ - **[MEDIUM]** `json.Unmarshal` ignoring error → silently retains zero values on malformed JSON.
84
+ - **[MEDIUM]** Integer conversion between `int32` and `int64` losing data on 32-bit platforms.
85
+ - **[MEDIUM]** `select` with default case in timing-sensitive code → busy loop.
86
+ - **[MEDIUM]** `context.WithCancel` defer cancel not called → context leak.
87
+ - **[LOW]** `make(chan T)` vs `make(chan T, 1)` — unbuffered vs buffered behavior difference not understood.
88
+ - **[LOW]** `strings.Contains` used where `strings.HasPrefix`/`HasSuffix` is more appropriate.
@@ -0,0 +1,56 @@
1
+ # Godot — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.gd` GDScript files, `*.tscn` scenes, `extends Node`, `func _ready()`, `func _process()`, `export var`, `@export`, `Godot`, `project.godot`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** `OS.execute()` or `OS.shell_open()` called with user-controlled arguments → command injection on the host OS; never pass untrusted input to OS execution APIs.
10
+ - **[HIGH]** HTTP requests made to user-provided URLs without validation → SSRF and malicious content fetching; validate URLs against an allowlist before any network request.
11
+ - **[HIGH]** Save game files loaded with `JSON.parse()` or `ResourceLoader.load()` without schema validation → crashes or exploits from malformed data; validate all fields and types after deserialization.
12
+ - **[MEDIUM]** `get_node()` called with a `NodePath` derived from user input → accessing arbitrary nodes in the scene tree; never construct node paths from untrusted data.
13
+ - **[MEDIUM]** Autoload singletons storing authentication tokens or private game state accessible from any script → overly broad attack surface; restrict sensitive data access to dedicated, narrowly scoped systems.
14
+ - **[LOW]** GDScript source files not encrypted in exported project (`Export > Resources > Script export mode`) → readable with PCK extraction tools; use bytecode-only export and PCK encryption for commercial titles.
15
+
16
+ ---
17
+
18
+ ## Performance
19
+ - **[HIGH]** Heavy computation (pathfinding, collision queries, string building) in `_process(delta)` → called every frame at full refresh rate; move to `_physics_process`, signals, timers, or background threads via `Thread`.
20
+ - **[HIGH]** `get_node()` or `$NodePath` shorthand called every frame instead of cached in `_ready()` → repeated scene-tree traversal; cache all node references as member variables in `_ready()`.
21
+ - **[HIGH]** Nodes instantiated and freed every frame (bullets, particles, effects) without pooling → GC pressure and frame spikes; implement a node pool using `queue_free()` + `visible = false` recycling.
22
+ - **[HIGH]** Large images imported without enabling appropriate compression (VRAM-compressed formats like S3TC, ETC2, BPTC) → excessive VRAM usage; configure import settings per texture type.
23
+ - **[MEDIUM]** `await get_tree().process_frame` used in tight loops without frame budget awareness → logic spread across many deferred frames; batch work with explicit budgeting.
24
+ - **[MEDIUM]** Signals not disconnected when nodes are freed → potential callbacks on freed objects; always disconnect signals in `_exit_tree()` or use `connect(..., CONNECT_ONE_SHOT)`.
25
+ - **[LOW]** `VisibleOnScreenNotifier2D`/`VisibleOnScreenNotifier3D` not used for off-screen objects that run `_process` → wasted CPU on invisible nodes; disable processing when off-screen.
26
+
27
+ ---
28
+
29
+ ## Architecture
30
+ - **[HIGH]** Scene tree traversal using `get_parent().get_parent().get_child(2)` chains → brittle structural coupling; use signals, groups, or exported node references for cross-node communication.
31
+ - **[HIGH]** Autoloads used as a dumping ground for all shared state and logic → implicit global coupling that makes scenes non-portable; limit autoloads to truly global services and use scene-local composition otherwise.
32
+ - **[MEDIUM]** Node-to-node communication done by calling methods directly on sibling or parent nodes instead of emitting signals → tight coupling; emit signals upward and call methods downward.
33
+ - **[MEDIUM]** Game logic embedded in UI nodes (`Button`, `Label` subclasses with game rules) → untestable in isolation; separate game logic into non-UI Node or RefCounted classes.
34
+ - **[MEDIUM]** Data not modeled as `Resource` subclasses → ad-hoc dictionaries passed everywhere; use typed `Resource` subclasses with `@export` fields for all structured data.
35
+ - **[LOW]** Scenes not decomposed into reusable sub-scenes → monolithic tscn files that are hard to maintain; extract repeating structures into their own scenes.
36
+
37
+ ---
38
+
39
+ ## Code Quality
40
+ - **[HIGH]** `@export` variables declared without type hints (`@export var speed` instead of `@export var speed: float`) → no editor type validation or static analysis; always type all exported variables.
41
+ - **[HIGH]** Return value of `get_node()` used without null check on nodes that may be absent → "Invalid get index" runtime error; null-check or use `has_node()` before access.
42
+ - **[MEDIUM]** GDScript functions and variables declared without type hints → static analyzer and Godot's type checker cannot catch errors; add type annotations to all declarations.
43
+ - **[MEDIUM]** `match` statement without a default `_:` branch for enum-like values → unhandled states silently fall through; always include a default branch that asserts or logs.
44
+ - **[MEDIUM]** Signals defined but never emitted, or emitted but never connected → dead code or broken communication channels; audit all signal definitions for use.
45
+ - **[LOW]** Node names containing spaces (e.g., `"My Node"`) → `$My Node` shorthand breaks; use PascalCase or snake_case node names consistently.
46
+
47
+ ---
48
+
49
+ ## Common Bugs & Pitfalls
50
+ - **[HIGH]** Holding a reference to a node after `queue_free()` and accessing it on the next frame → "Object was deleted" crash; use `is_instance_valid(node)` before accessing any potentially freed node.
51
+ - **[HIGH]** Signal connected multiple times (e.g., inside `_process` or on scene re-entry) without checking for existing connections → callback invoked multiple times per event; use `is_connected()` guard or `CONNECT_ONE_SHOT`.
52
+ - **[HIGH]** `_ready()` called before parent node's `_ready()` has completed in child-first order → child accesses parent state that is not yet initialized; use `call_deferred()` or `await owner.ready` for deferred initialization.
53
+ - **[MEDIUM]** `CharacterBody2D`/`CharacterBody3D` velocity not reset to zero before applying new movement each frame → accumulated velocity causing unintended drift; reset or reassign `velocity` explicitly each physics frame.
54
+ - **[MEDIUM]** `@export` variable default value changed in script after the scene has been saved → saved scene retains old serialized value, script default ignored; reset the property in the scene inspector after changing script defaults.
55
+ - **[MEDIUM]** `Timer` node not stopped and freed when the owning node is removed → timer fires callback on a freed object; always call `timer.stop()` in `_exit_tree()`.
56
+ - **[LOW]** Integer division used unintentionally in GDScript 4 (`5 / 2 == 2`) → use `float(5) / 2` or `5.0 / 2.0` for fractional results.
@@ -0,0 +1,76 @@
1
+ # GraphQL — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.graphql` / `*.gql` files, `gql\`\``, `GraphQLSchema`, `typeDefs`, `resolvers`, `ApolloServer`, `graphql-yoga`, `pothos`, `nexus`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** Missing field-level authorization in resolver → any authenticated user queries any field/mutation. Check permissions per-resolver, not just at route level.
11
+ - **[CRITICAL]** Introspection enabled in production → full schema exposed to attackers. Set `introspection: false` in production.
12
+ - **[HIGH]** Missing query depth limit → nested queries cause exponential DB calls (DoS). Use `graphql-depth-limit` (max 7-10 levels).
13
+ - **[HIGH]** Missing query complexity limit → single query requesting thousands of nodes. Use `graphql-query-complexity`.
14
+ - **[HIGH]** User-controlled field names in dynamic resolver → injection or over-fetching of sensitive fields.
15
+ - **[HIGH]** Batch query abuse — 1000 aliases in single query bypassing per-query rate limit. Limit max aliases.
16
+ - **[HIGH]** Missing rate limiting at GraphQL endpoint → high-complexity queries bypass REST-level limits.
17
+ - **[HIGH]** GraphQL errors leaking stack traces → configure custom error formatter to strip internal details.
18
+ - **[MEDIUM]** IDOR in resolver — fetching resource by ID in args without ownership check.
19
+ - **[MEDIUM]** Subscription not authenticated → real-time events delivered to unauthenticated WebSocket.
20
+ - **[LOW]** `directives` not documented or enforced on sensitive fields → ad-hoc security.
21
+
22
+ ---
23
+
24
+ ## Performance
25
+
26
+ - **[CRITICAL]** N+1 in resolver — DB query per parent node's children. Use `DataLoader` for batching + per-request caching.
27
+ - **[HIGH]** Resolver fetching all related data regardless of selection set → over-fetching. Use projection based on `info.fieldNodes`.
28
+ - **[HIGH]** No persisted queries → clients send full query string each request, larger payload, no CDN caching.
29
+ - **[HIGH]** `DataLoader` not scoped per-request → stale data served from previous request's loader cache.
30
+ - **[HIGH]** Subscription sending full object on every update when client only needs changed fields.
31
+ - **[MEDIUM]** Missing `@cacheControl` directives → CDN cannot cache GraphQL responses.
32
+ - **[MEDIUM]** Over-fetching in resolvers — entire DB record loaded for 2-field selection.
33
+ - **[MEDIUM]** `context.dataloaders` not used → DataLoader instances not shared across resolvers in request.
34
+ - **[MEDIUM]** Deeply nested fragment spread causing resolver chain traversal on every request.
35
+ - **[LOW]** Not using `graphql-jit` for hot query compilation.
36
+
37
+ ---
38
+
39
+ ## Architecture
40
+
41
+ - **[HIGH]** Business logic in resolver functions → move to service/domain layer; resolvers orchestrate only.
42
+ - **[HIGH]** Schema-first vs code-first inconsistency in same project → pick one, enforce via lint.
43
+ - **[HIGH]** Mutations not returning affected type → client must do extra query to refresh; return mutated entity.
44
+ - **[HIGH]** Missing input validation on mutation args → invalid data reaches business logic.
45
+ - **[MEDIUM]** Overloaded `Query` type with dozens of top-level fields → use namespaced query types.
46
+ - **[MEDIUM]** Not using schema federation for microservices → monolithic schema becomes bottleneck.
47
+ - **[MEDIUM]** Context not used for shared services (DB, auth, DataLoader) → instantiating per-resolver.
48
+ - **[MEDIUM]** Union/interface types not used for polymorphic data → overloaded nullable fields.
49
+ - **[LOW]** Missing `description` on types/fields → poor schema documentation, bad DX.
50
+ - **[LOW]** Not using code-generation (`graphql-codegen`) for TypeScript types → resolvers typed as `any`.
51
+
52
+ ---
53
+
54
+ ## Code Quality
55
+
56
+ - **[HIGH]** `any` type on resolver `context` or `parent` → no type safety.
57
+ - **[HIGH]** Missing `__resolveType` on union/interface → Apollo can't distinguish members.
58
+ - **[MEDIUM]** Resolver returning `undefined` for nullable field → client gets `null` unexpectedly.
59
+ - **[MEDIUM]** `async` resolver not returning Promise → Apollo silently resolves, async work never awaited.
60
+ - **[MEDIUM]** Mutations not following `input` type convention → inline args instead of typed `input` object.
61
+ - **[MEDIUM]** Error handling inconsistent — some resolvers throw, others return `null` → client can't distinguish.
62
+ - **[LOW]** Not using `graphql-scalars` for common scalars (DateTime, URL, Email) → custom validator reinvented.
63
+ - **[LOW]** Schema not validated with `graphql-inspector` → breaking changes undetected.
64
+
65
+ ---
66
+
67
+ ## Common Bugs & Pitfalls
68
+
69
+ - **[HIGH]** `DataLoader` key type mismatch (string vs number) → batching function receives mixed types, wrong results.
70
+ - **[HIGH]** Subscription not cleaned up on client disconnect → resource leak (DB connection, event listener).
71
+ - **[HIGH]** Resolver error not wrapped in `GraphQLError` → error format inconsistent, stack trace leaked.
72
+ - **[MEDIUM]** `context` mutated inside resolver → shared between parallel field resolvers, race condition.
73
+ - **[MEDIUM]** DataLoader `batchLoadFn` not returning results in same order as keys → wrong data mapped to wrong parents.
74
+ - **[MEDIUM]** `@deprecated` directive added but not enforced in CI → clients continue using deprecated fields.
75
+ - **[LOW]** Union type `__resolveType` missing → Apollo returns null for union field.
76
+ - **[LOW]** `null` vs empty array not distinguished in list fields → client gets wrong "no results" state.
@@ -0,0 +1,56 @@
1
+ # gRPC — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: grpc, .proto files, protoc, grpc-js, grpcio, google.golang.org/grpc, @grpc/grpc-js, protobuf
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** gRPC server not configured with TLS → all traffic transmitted in plaintext over the network. Configure mutual TLS or server-side TLS for all production gRPC servers.
10
+ - **[CRITICAL]** No authentication interceptor → unauthenticated calls accepted by all service methods. Add a server interceptor that validates JWT, mTLS certificate, or API key on every incoming RPC.
11
+ - **[HIGH]** Metadata headers not validated for auth tokens → auth data present in metadata but not verified, allowing forged tokens. Extract and validate tokens from incoming metadata in the auth interceptor.
12
+ - **[HIGH]** Server reflection enabled in production → attackers can enumerate all service definitions and methods, aiding targeted attacks. Disable server reflection in production; enable only in development.
13
+ - **[HIGH]** Unvalidated proto message fields → missing required field validation allows invalid data into business logic, causing panics or incorrect behavior. Use protoc-gen-validate or protovalidate to enforce field constraints.
14
+ - **[HIGH]** SSRF via server-side gRPC calls to user-provided service addresses → attacker routes internal requests to arbitrary targets. Validate and whitelist allowed gRPC endpoints before dialing.
15
+ - **[MEDIUM]** Error messages in gRPC status details exposing internal implementation → stack traces or DB errors sent to clients aid attackers. Return sanitized error messages; log detailed errors server-side only.
16
+ - **[MEDIUM]** Insufficient input size limits on streaming RPCs → oversized messages exhaust server memory. Configure max message size limits on the server and validate message sizes in streaming handlers.
17
+
18
+ ---
19
+
20
+ ## Performance
21
+ - **[HIGH]** Unary RPC used for streaming use cases (large result sets, real-time events) → high latency and excessive overhead from repeated round-trips. Use server-streaming or bidirectional-streaming RPCs for continuous data flows.
22
+ - **[HIGH]** Large proto messages not using field streaming or chunking → entire payload buffered in memory, causing high latency and memory pressure. Break large payloads into streaming chunks or paginate with server-streaming.
23
+ - **[HIGH]** Client connection not reused across calls → TLS handshake and TCP connection established per call, adding significant latency. Create a single gRPC client connection or connection pool and reuse it.
24
+ - **[HIGH]** Missing deadline or timeout on every RPC call → slow or unresponsive servers hold goroutines/threads indefinitely, exhausting client resources. Always set a deadline via context: ctx, cancel := context.WithTimeout(ctx, 5*time.Second).
25
+ - **[MEDIUM]** No client-side load balancing configured → all calls routed to a single server instance, negating horizontal scaling. Configure gRPC client-side load balancing (round-robin, pick-first) or use a service mesh.
26
+ - **[MEDIUM]** Not retrying idempotent RPCs on transient failures → network blips cause unnecessary failures for safe-to-retry operations. Configure retry policy or implement exponential backoff for UNAVAILABLE and DEADLINE_EXCEEDED errors.
27
+ - **[LOW]** Not enabling gzip compression for large message payloads → large proto messages consume excess bandwidth. Enable compression codec on both client and server for message-heavy services.
28
+
29
+ ---
30
+
31
+ ## Architecture
32
+ - **[MEDIUM]** Proto definitions not in a separate shared proto repository or directory → service teams duplicate definitions, leading to drift and incompatibility. Centralize proto files in a shared repo with versioned packages.
33
+ - **[HIGH]** Breaking proto changes (renaming fields, changing field numbers, removing fields) without versioning → existing clients break when server updates. Create new package versions (v2, v3) for breaking changes; never alter field numbers.
34
+ - **[HIGH]** Business logic in gRPC server handler methods instead of a service layer → handlers become untestable monoliths. Extract domain logic into service types and call them from thin handler methods.
35
+ - **[MEDIUM]** Not using interceptors for logging, tracing, and metrics → observability data absent, making production debugging difficult. Add unary and streaming interceptors for structured logging, OpenTelemetry tracing, and Prometheus metrics.
36
+ - **[MEDIUM]** Proto-generated code committed to the repository instead of generated in CI → generated code drifts from proto definitions when developers forget to regenerate. Run protoc as a CI step and check for uncommitted changes.
37
+
38
+ ---
39
+
40
+ ## Code Quality
41
+ - **[MEDIUM]** Generated proto code committed to repo instead of generated in CI → generated files drift from proto source when developers forget to regenerate. Add proto compilation to CI and fail the build on uncommitted generated changes.
42
+ - **[HIGH]** Missing protoc-gen-validate or protovalidate for field-level validation → business logic receives invalid field values (empty required strings, out-of-range numbers). Add validation annotations to proto files and enforce them at the RPC boundary.
43
+ - **[MEDIUM]** gRPC status codes not semantically correct (e.g., INTERNAL returned for NOT_FOUND) → clients cannot distinguish error categories to implement correct retry or fallback logic. Map domain errors to appropriate gRPC status codes (NOT_FOUND, INVALID_ARGUMENT, etc.).
44
+ - **[LOW]** Not documenting proto service and message fields with comments → API consumers cannot understand expected values or semantics without reading source code. Add proto comment annotations; use buf.build or similar for generated API docs.
45
+ - **[MEDIUM]** Not using well-known types (google.protobuf.Timestamp, google.protobuf.Duration) for time fields → custom time representations lead to parsing bugs across language implementations. Use official well-known proto types for temporal data.
46
+ - **[MEDIUM]** Service definitions not following proto naming conventions → inconsistent naming confuses consumers and makes tooling harder. Follow Google API design guide naming conventions for RPCs, fields, and enums.
47
+
48
+ ---
49
+
50
+ ## Common Bugs & Pitfalls
51
+ - **[HIGH]** Deadline not propagated from the incoming parent context to downstream RPC calls → child calls run past the parent deadline, consuming resources after the client has given up. Always derive child contexts from the incoming request context.
52
+ - **[HIGH]** ClientConn not closed after use → goroutines and TCP connections leak indefinitely. Always defer conn.Close() after creating a gRPC client connection.
53
+ - **[MEDIUM]** Streaming server not sending an error status before closing the stream → client receives an EOF with no error context, making debugging difficult. Send a non-OK status via stream.SendMsg or return an error from the handler before returning.
54
+ - **[MEDIUM]** Proto oneof fields not handled exhaustively in switch statements → new oneof variants introduced in future proto versions silently fall through to a default case. Add a default branch that logs an unknown variant warning.
55
+ - **[HIGH]** Not handling stream context cancellation in server-streaming handlers → handlers continue sending after the client disconnects, wasting server resources. Check stream.Context().Done() in the streaming loop and exit cleanly.
56
+ - **[MEDIUM]** Reusing proto message structs across goroutines without copying → concurrent mutation of proto messages causes data races. Clone proto messages before passing to goroutines using proto.Clone().
@@ -0,0 +1,48 @@
1
+ # Haskell — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.hs`, `import Control.`, `import Data.`, `module `, `where`, `do`, `IO ()`, `cabal.project`, `stack.yaml`, `ghc`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** `unsafePerformIO` used in ostensibly pure code → violates referential transparency and can introduce data races when the IO action is shared across threads. Replace with properly threaded `IO` or use `IORef`/`MVar` for shared mutable state.
10
+ - **[HIGH]** `read` called on untrusted input → throws an exception (partial function) on any parse failure, crashing the thread. Use `readMaybe` from `Text.Read` and handle the `Nothing` case explicitly.
11
+ - **[MEDIUM]** Lazy IO via `readFile` / `hGetContents` → file handle not closed until the lazy string is fully consumed; if evaluation is deferred, handle leaks occur. Use `withFile` + strict `Data.ByteString` / `Data.Text` IO or the `conduit`/`pipes` streaming library.
12
+ - **[MEDIUM]** Cryptographic operations using unmaintained or unaudited libraries → known vulnerabilities unpatched. Use `cryptonite` or `botan-bindings` and pin exact versions; review library update history before adoption.
13
+
14
+ ---
15
+
16
+ ## Performance
17
+ - **[HIGH]** Lazy evaluation causing space leaks — thunks accumulate in long-running folds or accumulator patterns → process RSS grows unboundedly. Force strict evaluation with `seq`, `deepseq`, `BangPatterns`, or strict data fields (`{-# LANGUAGE StrictData #-}`).
18
+ - **[HIGH]** `String` (linked list of `Char`) used for text processing → 5–20× memory overhead and poor cache performance compared to `Text`. Use `Data.Text` (UTF-16 packed) or `Data.ByteString` for all string-heavy code.
19
+ - **[HIGH]** `Data.List` operations (`!!`, `length`) on large lists → O(n) traversal. Use `Data.Sequence` for O(log n) indexed access or `Data.Vector` for O(1) arrays.
20
+ - **[MEDIUM]** Accumulator in recursive function not forced with `!` (BangPattern) → thunk chain of size n built before evaluation begins, consuming O(n) stack/heap. Add `BangPatterns` or use `foldl'` (strict fold from `Data.List`).
21
+ - **[MEDIUM]** No profiling performed with GHC's `+RTS -p -s` runtime flags → space leaks and hot spots remain undetected until production. Run with `-prof -fprof-auto` during development to generate heap profiles.
22
+
23
+ ---
24
+
25
+ ## Architecture
26
+ - **[HIGH]** `IO` actions scattered throughout pure business logic → untestable without executing real effects. Separate pure logic from effects using the `ReaderT` pattern, `MTL` type classes, or an algebraic effects library (`effectful`, `polysemy`).
27
+ - **[HIGH]** Partial functions (`head`, `tail`, `fromJust`, `!!`) used in production code → `Exception` thrown on empty list or `Nothing`. Replace with total alternatives: `listToMaybe`, `maybe`, pattern match with an explicit empty case.
28
+ - **[MEDIUM]** Not using the `ReaderT` pattern for passing configuration and dependencies → functions take many explicit arguments or rely on global `IORef`s. Thread a `Env` record through `ReaderT Env IO` for implicit dependency injection.
29
+ - **[MEDIUM]** `State` monad overused for logic that is actually a pure fold → unnecessary monad overhead. Prefer `foldl'` or explicit accumulator arguments for simple stateful transformations.
30
+ - **[LOW]** Library and executable sources not separated in the Cabal file → internal modules exposed inadvertently; slower test compilation. Define a `library` stanza with the `exposed-modules` list and have the `executable` depend on it.
31
+
32
+ ---
33
+
34
+ ## Code Quality
35
+ - **[HIGH]** Partial functions in production: `head []`, `fromJust Nothing`, `arr !! outOfBounds` → runtime `Exception` with no meaningful error site. Use `listToMaybe`, `maybe default id`, and bounds-checked indexing; compile with `-Wall -Werror` to catch incomplete patterns.
36
+ - **[HIGH]** `error "TODO"` or `undefined` left in non-test code → crashes at runtime when the code path is reached. Replace with proper `Either`/`Maybe` returns or typed not-implemented errors before merging.
37
+ - **[MEDIUM]** Not running `hlint` and `ormolu`/`fourmolu` in CI → stylistic inconsistencies and common anti-patterns accumulate. Add `hlint` and formatter checks as CI steps; fail on any hint.
38
+ - **[MEDIUM]** Type signatures missing on top-level functions → GHC infers types but they may be more general than intended, causing subtle bugs or confusing error messages elsewhere. Add explicit type signatures to all top-level and exported functions.
39
+ - **[LOW]** Pattern matching not exhaustive with `-Wall` suppressed → `Non-exhaustive patterns` warning hidden, crashes in production. Compile with `-Wall -Wexhaustive-fields` and treat warnings as errors in CI.
40
+
41
+ ---
42
+
43
+ ## Common Bugs & Pitfalls
44
+ - **[HIGH]** Lazy `foldl` instead of strict `foldl'` for summation or accumulation → O(n) thunk chain causes stack overflow on large inputs. Always use `Data.List.foldl'` or `Data.Foldable.foldl'`; never use `foldl` on a strict result.
45
+ - **[HIGH]** `show` / `read` round-trip assumed for all types → `read (show x) /= x` for types like `Double` (NaN, Infinity) or custom `Show` instances. Use explicit serialization (Aeson, binary) for persistence rather than `show`/`read`.
46
+ - **[MEDIUM]** Monad transformer stack order not carefully chosen → `StateT s (ExceptT e IO)` (state lost on error) vs `ExceptT e (StateT s IO)` (state preserved on error) have different semantics. Document the intended error/state interaction and encode it in the type stack order.
47
+ - **[MEDIUM]** `unsafeCoerce` used to work around a type-checker error → type safety voided, potential runtime crash or memory corruption. Fix the underlying type mismatch; use `Data.Coerce.coerce` only for `newtype` coercions where it is guaranteed safe.
48
+ - **[LOW]** `deriving (Eq, Ord)` field order determines comparison semantics → adding a field changes the `Ord` instance, breaking `Map`/`Set` ordering. Document the intended comparison key and consider a manual `Ord` instance or `newtype` wrapper for maps.