prr-kit 1.1.3 → 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 +30 -248
  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,77 @@
1
+ # Svelte / SvelteKit — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.svelte` files, `svelte.config.*`, `from 'svelte'`, `$store`, `+page.svelte`, `+layout.svelte`, `+server.ts`, `$app/`, `svelte:` tags
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** `{@html userContent}` with user-controlled data → XSS. Svelte escapes `{}` by default; `{@html}` bypasses this. Sanitize with DOMPurify first.
11
+ - **[CRITICAL]** SvelteKit `load()` function returning sensitive data without auth check → serialized into HTML, sent to client.
12
+ - **[HIGH]** `+server.ts` route missing authentication check → unprotected API endpoint.
13
+ - **[HIGH]** `PUBLIC_` env prefix on secrets → exposed to browser. Non-public secrets use `$env/static/private` / `$env/dynamic/private`.
14
+ - **[HIGH]** Form action mutation missing CSRF protection (SvelteKit handles this but `csrf.checkOrigin: false` config disables it).
15
+ - **[HIGH]** `eval()` in Svelte component or action with user input → code injection.
16
+ - **[HIGH]** User-controlled `<svelte:component this={...}>` → arbitrary component injection.
17
+ - **[MEDIUM]** `event.locals` set in `hooks.server.ts` without proper auth validation → auth state not verified.
18
+ - **[MEDIUM]** Sensitive data in `$page.data` (SvelteKit store) accessible in client-side devtools.
19
+ - **[LOW]** XSS via `href={userUrl}` without protocol validation → `javascript:` injection.
20
+
21
+ ---
22
+
23
+ ## Performance
24
+
25
+ - **[HIGH]** Svelte store subscriptions with manual `subscribe()` not unsubscribed in `onDestroy` → memory leak. Use `$store` auto-subscription.
26
+ - **[HIGH]** `{#each}` on large arrays without `key` expression → O(n) DOM diffing. Use `{#each items as item (item.id)}`.
27
+ - **[HIGH]** SvelteKit not using `+page.server.ts` for data fetching → client-side fetch waterfall.
28
+ - **[HIGH]** Reactive declaration `$:` depending on entire object/array → recalculates on any nested change.
29
+ - **[HIGH]** Heavy computation in `$:` reactive statement → runs synchronously on every dependency change.
30
+ - **[MEDIUM]** Not using `svelte:fragment` → adding unnecessary wrapper DOM elements.
31
+ - **[MEDIUM]** `{#if}` / `{/if}` on frequently toggling content → DOM destroy/recreate. Use CSS `visibility` for keep-alive.
32
+ - **[MEDIUM]** Importing large libraries in `.svelte` file that could stay in `+page.server.ts`.
33
+ - **[MEDIUM]** Svelte transitions/animations running on server → use `browser` guard from `$app/environment`.
34
+ - **[LOW]** Missing `data-sveltekit-preload-data` on navigation links → no prefetching on hover.
35
+ - **[LOW]** Unused CSS selectors not removed → Svelte warns, but increases style bundle.
36
+
37
+ ---
38
+
39
+ ## Architecture
40
+
41
+ - **[HIGH]** Business logic in `.svelte` file → extract to `+page.ts` load function or service module.
42
+ - **[HIGH]** Writable store mutated from multiple components without centralized actions → unpredictable state.
43
+ - **[HIGH]** Calling `goto()` from non-browser context (SSR) → throws. Guard with `if (browser)`.
44
+ - **[MEDIUM]** `setContext`/`getContext` across distant components instead of store → harder to track data flow.
45
+ - **[MEDIUM]** Not using SvelteKit form actions for mutations → manual `fetch` + reloading.
46
+ - **[MEDIUM]** `event.depends('key')` not used in load functions that need manual invalidation.
47
+ - **[MEDIUM]** Stores defined at module level shared between SSR requests → user data leakage between requests.
48
+ - **[LOW]** `on:click` instead of `<button>` for interactive elements → accessibility issue.
49
+ - **[LOW]** Component dispatching events with non-prefixed names → conflicts with native DOM events.
50
+
51
+ ---
52
+
53
+ ## Code Quality
54
+
55
+ - **[HIGH]** `{#await promise}` without `:catch` block → rejected promise silently swallowed.
56
+ - **[HIGH]** `bind:this={el}` without null-check before use → undefined on SSR.
57
+ - **[MEDIUM]** `$:` reactive block with side effects (API calls) → runs on every dependency change, not just when needed.
58
+ - **[MEDIUM]** Two-way `bind:value` on derived/computed value → binding non-reactive source.
59
+ - **[MEDIUM]** Not using Svelte's `<svelte:head>` for page-specific meta tags → SEO issues.
60
+ - **[MEDIUM]** Missing TypeScript types on component props via `export let prop: Type` → any type assumed.
61
+ - **[MEDIUM]** `on:` event handlers not using TypeScript event types (`CustomEvent<T>`).
62
+ - **[LOW]** Using `writable` when `readable` or `derived` is semantically correct.
63
+ - **[LOW]** Not using `$effect` (Svelte 5 runes) when migrating from Svelte 4 → mixing APIs.
64
+
65
+ ---
66
+
67
+ ## Common Bugs & Pitfalls
68
+
69
+ - **[HIGH]** Reactive `$:` not triggering because object reference unchanged (mutating array in place) → use spread/immutable update `items = [...items, newItem]`.
70
+ - **[HIGH]** `onMount` / `onDestroy` called in SSR context → must guard with `browser` check.
71
+ - **[HIGH]** SvelteKit load function returning non-serializable objects (class instances, functions) → hydration error.
72
+ - **[HIGH]** `invalidate()` not called after form action mutation → stale `$page.data`.
73
+ - **[MEDIUM]** Svelte store `$value` used in `<script>` (not template) → must use `get(store)` or manual subscribe.
74
+ - **[MEDIUM]** Transition running on initial render when not desired → use `in:fade|local`.
75
+ - **[MEDIUM]** `svelte:component this={null}` → renders nothing but may error in strict mode.
76
+ - **[MEDIUM]** Props passed to child with `$$props` / `$$restProps` leaking internal props to DOM elements.
77
+ - **[LOW]** `class:active={true}` always → static class, just use `class="active"`.
@@ -0,0 +1,54 @@
1
+ # SvelteKit — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.svelte`, `svelte.config.*`, `+page.svelte`, `+layout.svelte`, `+server.ts`, `from 'svelte'`, `$lib/`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** `{@html}` used with user-controlled input → XSS allowing arbitrary script execution. Sanitize with DOMPurify or avoid `{@html}` entirely.
10
+ - **[CRITICAL]** Missing auth check in `+server.ts` endpoints → unauthenticated API access. Validate session/token at the top of every handler before processing.
11
+ - **[HIGH]** CSRF protection absent on form actions → state-changing requests forgeable. Use SvelteKit's built-in CSRF protection or add `csrf` check in hooks.
12
+ - **[HIGH]** `load()` function returning sensitive fields (passwords, tokens, internal IDs) → data leaked to client serialization. Strip sensitive fields before returning from server `load()`.
13
+ - **[HIGH]** Insecure direct object reference via route params (`/items/[id]`) without ownership check → users access other users' data. Verify `params.id` belongs to the authenticated user.
14
+ - **[MEDIUM]** Secrets placed in `$env/static/public` instead of `$env/static/private` → exposed in client bundle. Move all secrets to `$env/static/private` and access only in server files.
15
+
16
+ ---
17
+
18
+ ## Performance
19
+ - **[HIGH]** Data fetching in `+page.svelte` `onMount` instead of `+page.server.ts` `load()` → client-side waterfall after hydration. Move all initial data fetching to server-side `load()` functions.
20
+ - **[HIGH]** Repeated DB queries across nested layout `load()` functions without caching → redundant round trips. Use `event.locals` or a request-scoped cache to share data between layouts.
21
+ - **[HIGH]** Heavy libraries (e.g. chart.js, moment) imported client-side without dynamic import → large initial bundle. Use `import()` lazily or move processing to server-side `load()`.
22
+ - **[MEDIUM]** Large images not using `<enhanced:img>` → unoptimized images shipped without resize/format conversion. Replace `<img>` with `<enhanced:img>` for automatic WebP conversion and srcset.
23
+ - **[MEDIUM]** Slow non-critical data not using `defer` in `load()` → page blocked until all data resolves. Use `return { streamed: { data: fetchSlow() } }` with `{#await}` blocks.
24
+ - **[LOW]** Missing `<link rel="preload">` hints for critical fonts/scripts → render-blocking discovery delay. Add preload hints in `<svelte:head>` for known critical resources.
25
+
26
+ ---
27
+
28
+ ## Architecture
29
+ - **[CRITICAL]** Module-level Svelte stores used for request-scoped state → state leaks between SSR requests across users. Use `setContext`/`getContext` or per-request locals instead of module singletons.
30
+ - **[HIGH]** Business logic (DB calls, validation) inside `+page.svelte` `<script>` → untestable, mixed concerns. Move to server `load()` functions or dedicated service modules in `$lib/server/`.
31
+ - **[HIGH]** Client/server env variables not segregated (`$env/static/public` vs `$env/static/private`) → accidental secret exposure. Enforce that `$env/static/private` is only imported from `.server.ts` files.
32
+ - **[HIGH]** Direct `fetch` mutations from component instead of form actions → loses progressive enhancement and CSRF protection. Use `+page.server.ts` form `actions` for all state mutations.
33
+ - **[MEDIUM]** Deep prop drilling through layout hierarchy instead of Svelte stores or `setContext` → brittle coupling. Use `setContext`/`getContext` for layout-to-component data or a scoped store.
34
+ - **[MEDIUM]** Route-specific logic placed in `+layout.server.ts` affecting unrelated child routes → unintended coupling. Scope data loading to the lowest applicable `+page.server.ts` or `+layout.server.ts`.
35
+
36
+ ---
37
+
38
+ ## Code Quality
39
+ - **[HIGH]** Not importing `PageData`/`ActionData` types from `./$types` → loss of end-to-end type safety on `load()` return values. Use `export let data: PageData` and `export let form: ActionData` with generated types.
40
+ - **[MEDIUM]** Form data parsed manually without schema validation (e.g. Zod, superforms) → runtime type errors and missing validation errors. Use `sveltekit-superforms` with Zod for typed, validated form handling.
41
+ - **[MEDIUM]** Hardcoded absolute URLs instead of `base` from `$app/paths` → breaks when deployed to a sub-path. Use `import { base } from '$app/paths'` and prefix all internal links.
42
+ - **[MEDIUM]** Missing `+error.svelte` at route or layout level → SvelteKit's default error page shown to users. Add `+error.svelte` with user-friendly messaging at each route group boundary.
43
+ - **[MEDIUM]** `event.fetch` not used inside `load()` for internal API calls → misses cookie forwarding and SSR deduplication. Replace `fetch` with `event.fetch` inside all `load()` and server handlers.
44
+ - **[LOW]** No TypeScript strict mode in `tsconfig.json` → type errors silently ignored. Enable `"strict": true` in tsconfig and resolve all resulting errors.
45
+
46
+ ---
47
+
48
+ ## Common Bugs & Pitfalls
49
+ - **[HIGH]** `onMount` code accessing browser APIs runs during SSR → hydration mismatch and server errors. Guard with `if (browser)` from `$app/environment` or move to `onMount` which already skips SSR.
50
+ - **[HIGH]** Reactive statement `$: result = compute(value)` with side effects (fetch, DOM mutation) → infinite reactive loops. Move side-effectful reactive code into `$: { }` blocks or Svelte lifecycle hooks.
51
+ - **[HIGH]** Svelte store subscription via `$store` syntax in a component never unsubscribed when created manually → memory leak. Use the `$` auto-subscribe syntax or manually call `unsubscribe()` in `onDestroy`.
52
+ - **[HIGH]** `load()` returning class instances, `Date` objects, or functions → serialization failure when passing from server to client. Return only plain JSON-serializable objects; convert `Date` to ISO strings.
53
+ - **[MEDIUM]** `goto()` called inside server-side code (`+server.ts`, `load()`) → no-op or runtime error. Use `redirect(303, url)` from `@sveltejs/kit` for server-side redirects.
54
+ - **[MEDIUM]** `invalidate()` or `invalidateAll()` called without understanding which `load()` functions re-run → over-fetching or stale data. Understand dependency tracking via `event.depends()` before using invalidation.
@@ -0,0 +1,61 @@
1
+ # Swift Stack Rules
2
+
3
+ ## Detection Signals
4
+ `*.swift` files · `import UIKit` · `import SwiftUI` · `import Foundation` · `Package.swift` · `*.xcodeproj` · `Podfile` · `*.xcworkspace`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ **[CRITICAL]** Sensitive data (passwords, tokens, keys) stored in UserDefaults → not encrypted, included in device backups, and readable on jailbroken devices. Use Keychain via Security framework or KeychainAccess library for all sensitive values.
11
+
12
+ **[CRITICAL]** Certificate validation disabled via custom URLSession delegate returning .useCredential for all challenges → MITM attack intercepts all network traffic in cleartext. Never bypass certificate validation; implement pinning correctly using SecTrustEvaluateWithError.
13
+
14
+ **[HIGH]** WKWebView loading user-controlled URLs without scheme/host validation → open redirect, XSS from malicious web content reaching native bridges. Validate and allowlist URL schemes and hosts before loading.
15
+
16
+ **[HIGH]** WebView with JavaScript enabled loading untrusted content → XSS in web content can access native message handlers and call Swift code. Disable JavaScript for untrusted content or use WKContentWorld isolation for message handlers.
17
+
18
+ **[HIGH]** Hardcoded API keys, secrets, or connection strings in Swift source files → extractable from compiled binary using strings tool or Hopper. Use environment-specific xcconfig files, obfuscation, or a backend proxy for secrets.
19
+
20
+ **[HIGH]** SQL injection via raw SQLite query constructed with string interpolation of user input → arbitrary SQL executed against local database. Use parameterized queries with sqlite3_bind_* functions instead of string interpolation.
21
+
22
+ **[HIGH]** Sensitive content written to UIPasteboard.general without expiry date → pasteboard data persists across apps and is accessible to any app the user switches to. Set expirationDate on sensitive pasteboard items or clear after use.
23
+
24
+ **[HIGH]** No jailbreak detection for high-security operations in banking or health apps → jailbroken device can bypass Keychain security, intercept traffic, and inspect memory. Implement jailbreak detection checks for sensitive operations in high-security contexts.
25
+
26
+ **[MEDIUM]** Sensitive screens not protected from screenshots in app switcher → app switcher captures a snapshot of the last screen, potentially exposing sensitive data. Add a privacy overlay in applicationWillResignActive and remove it in applicationDidBecomeActive.
27
+
28
+ **[MEDIUM]** Log statements containing sensitive data (tokens, PII, passwords) → visible in Xcode console during development and in device system logs. Use compile-time or runtime flags to strip sensitive log statements from release builds.
29
+
30
+ **[MEDIUM]** try! on network or cryptographic operations → any failure crashes the app with a fatal error rather than being handled gracefully. Use do/catch for all throwing operations and handle errors explicitly.
31
+
32
+ **[LOW]** Hardcoded bundle IDs or environment URLs in source code → changing environments requires source changes and recompilation. Use xcconfig files with per-scheme settings for bundle ID, URLs, and other environment-specific values.
33
+ ---
34
+
35
+ ## Performance
36
+
37
+ **[CRITICAL]** Retain cycle in closure where self is captured strongly without [weak self] or [unowned self] → ARC never releases the object, memory leaks accumulate over the session lifetime. Always capture self weakly in escaping closures stored as properties.
38
+
39
+ **[HIGH]** @Published property updated from a background thread → SwiftUI requires all UI updates on the main thread; background updates cause runtime warnings and undefined rendering behavior. Wrap background updates with DispatchQueue.main.async or mark the class @MainActor.
40
+
41
+ **[HIGH]** Synchronous URLSession call on main thread using dataTask with semaphore wait → UI freezes for the duration of the network call, watchdog kills the app after a few seconds. Always use async/await or completion handlers on a background queue.
42
+
43
+ **[HIGH]** Full-resolution image decoded in memory for thumbnail display → a 12MP JPEG decoded at full resolution uses hundreds of MB of memory, causing OOM and app termination. Use ImageIO with kCGImageSourceThumbnailMaxPixelSize to downsample at decode time.
44
+
45
+ **[HIGH]** Core Data fetch request executed on the main thread with large datasets → UI freezes during the fetch; large datasets can cause ANR and app termination. Perform fetches using performAndWait on a background managed object context.
46
+
47
+ **[HIGH]** Not using Swift Concurrency (async/await) for concurrent tasks → GCD DispatchQueue nesting creates callback pyramids, no structured cancellation, hard to reason about. Migrate to async/await with Task and TaskGroup for structured concurrency.
48
+
49
+ **[MEDIUM]** DispatchQueue.main.sync called from the main thread → deadlock; the main thread blocks waiting for itself to complete the sync block. Always use DispatchQueue.main.async when dispatching to main from the main thread.
50
+
51
+ **[MEDIUM]** Large Codable model decoded synchronously on the main thread → JSON decoding of large payloads freezes the UI noticeably. Decode on a background Task or DispatchQueue.global and update state on main.
52
+
53
+ **[MEDIUM]** SwiftUI View body performing expensive computation (sorting, filtering large arrays) on every render → runs on every state change even for unrelated properties, causing jank. Cache results in @State or compute in ViewModel with @Published.
54
+
55
+ **[MEDIUM]** Not using LazyVStack or LazyHStack for long lists in SwiftUI → all rows computed and laid out upfront even if off-screen, wasting memory and CPU. Use LazyVStack inside ScrollView or List for large collections.
56
+
57
+ **[MEDIUM]** Heavy objects allocated inside SwiftUI View body initializer → recreated on every render cycle because View structs are value types. Move expensive objects to @StateObject or @EnvironmentObject so they survive re-renders.
58
+
59
+ **[LOW]** Array used for membership testing in hot paths → contains() on Array is O(n); with large arrays called frequently this causes measurable performance degradation. Use Set for O(1) membership testing.
60
+
61
+ **[LOW]** NotificationCenter callback performing UI work without main thread dispatch → notifications are delivered on the posting thread which may be a background thread, causing crashes or undefined UI behavior. Always dispatch UI work to DispatchQueue.main inside notification handlers.
@@ -0,0 +1,10 @@
1
+ # Tailwind CSS — Stack-Specific Review Rules
2
+ > Applies to: GR · SR · PR · AR · BR
3
+ > Detection signals: `tailwind.config.*`, `@tailwind` directives in CSS, `@apply`, utility class patterns (`flex`, `grid`, `text-`, `bg-`, `p-`, `m-`), `tw` template tag
4
+
5
+ ## Security
6
+
7
+ - **[HIGH]** `url()` in arbitrary value with user-controlled content: `bg-[url(${userUrl})]` → CSS injection loading external resources. Never interpolate user data into Tailwind classes or CSS `url()`.
8
+ - **[MEDIUM]** Missing Content-Security-Policy `style-src` → injected inline styles from XSS not blocked. CSP must cover `style-src 'self'` or nonce-based.
9
+ - **[MEDIUM]** Dynamic class construction with user-provided values → classes not in safelist not generated, silent styling failure. Sanitize and allowlist user-provided class values.
10
+ - **[LOW]** Tailwind's `theme()` function in CSS exposing design tokens via CSS custom properties → design system values readable by JS. Document intentionally or restrict.
@@ -0,0 +1,48 @@
1
+ # TanStack Query (React Query) — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `from '@tanstack/react-query'`, `from 'react-query'`, `useQuery`, `useMutation`, `QueryClient`, `QueryClientProvider`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** Single `QueryClient` instance shared across SSR requests (module-level singleton) → cached data from user A served to user B. Create a new `QueryClient` per server request; only share client-side.
10
+ - **[HIGH]** Query cache not cleared on user logout → stale authenticated data (PII, private content) accessible to the next user of the same browser session. Call `queryClient.clear()` on logout before redirecting.
11
+ - **[HIGH]** `queryFn` making requests without attaching auth headers or cookies → unauthenticated API calls returning empty or error responses. Centralize auth header attachment in a shared fetch wrapper passed to all `queryFn`s.
12
+ - **[MEDIUM]** Sensitive PII cached with `gcTime: Infinity` or very long `staleTime` → private data persists in memory longer than the session. Set conservative `gcTime` and `staleTime` for queries containing PII; clear on logout.
13
+
14
+ ---
15
+
16
+ ## Performance
17
+ - **[HIGH]** `staleTime` not set (defaults to `0`) → data refetched on every component mount and every window focus event. Set `staleTime` based on data volatility: `staleTime: 60_000` for semi-static data.
18
+ - **[HIGH]** `refetchInterval` set aggressively (< 5s) for non-real-time data → unnecessary server load and bandwidth consumption. Use WebSockets or SSE for real-time data; set `refetchInterval` to the minimum meaningful update frequency.
19
+ - **[HIGH]** Parallel independent queries not using `useQueries` → multiple `useQuery` hooks cause sequential waterfall in some renderers. Combine parallel queries with `useQueries([{ queryKey, queryFn }, ...])` for concurrent execution.
20
+ - **[MEDIUM]** `select` option not used to derive/transform data → entire raw response stored in cache and components re-render on any field change. Use `select: (data) => transform(data)` to subscribe only to the derived slice.
21
+ - **[MEDIUM]** `gcTime: Infinity` set globally or on large queries → memory grows unboundedly in long-running SPAs. Use the default `gcTime` (5 minutes) or set it explicitly; never use `Infinity` for large datasets.
22
+ - **[LOW]** Prefetching not used for predictable navigation (hover, visible links) → users wait for data fetch after every navigation. Use `queryClient.prefetchQuery` on hover or route anticipation to pre-warm the cache.
23
+
24
+ ---
25
+
26
+ ## Architecture
27
+ - **[HIGH]** Query key arrays defined as inline literals across multiple files (`['users', id]`) → typos cause cache misses and broken invalidation. Centralize query keys in a factory: `userKeys.detail(id)` returning `['users', 'detail', id]`.
28
+ - **[HIGH]** `queryFn` containing business logic (data transformation, error mapping) instead of pure data fetching → logic untestable in isolation. Keep `queryFn` as a thin fetch wrapper; transform data in `select` or a separate utility.
29
+ - **[MEDIUM]** Overly broad query key used for invalidation (e.g. `['users']` invalidating all user queries) → unnecessary refetches for unrelated components. Use scoped keys and targeted invalidation: `queryClient.invalidateQueries({ queryKey: userKeys.detail(id) })`.
30
+ - **[MEDIUM]** Mutations missing optimistic updates for latency-sensitive UI interactions (like/dislike, reorder) → UI lags behind user action. Implement `onMutate`/`onError`/`onSettled` pattern for optimistic updates on interactive mutations.
31
+ - **[MEDIUM]** Dependent queries not using the `enabled` flag → query fires immediately with `undefined` params, causing spurious 400/404 errors. Use `enabled: !!userId` to prevent a query from running until its dependencies are ready.
32
+
33
+ ---
34
+
35
+ ## Code Quality
36
+ - **[HIGH]** `useQuery` called without TypeScript generics (`useQuery<TData, TError>`) → data and error typed as `unknown`, losing type safety throughout the component. Always provide generics or use a typed query factory that infers them.
37
+ - **[HIGH]** `error` state not handled in every `useQuery` consumer → components render loading or empty state indefinitely on error. Destructure `error` and `isError` and render an appropriate error UI in every query consumer.
38
+ - **[MEDIUM]** `queryKey` as inline array literal (`['posts', id]`) → referential instability causes unnecessary cache misses in `useQuery` comparisons. Define query keys via factory functions that return stable arrays.
39
+ - **[LOW]** `QueryClient` default options not configured globally → each query re-specifies the same `staleTime`, `retry`, and `refetchOnWindowFocus` options. Set sensible app-wide defaults in `new QueryClient({ defaultOptions: { queries: { ... } } })`.
40
+
41
+ ---
42
+
43
+ ## Common Bugs & Pitfalls
44
+ - **[CRITICAL]** Cached query data mutated directly (`data.items.push(newItem)`) instead of using `setQueryData` → bypasses TanStack Query's immutability contract, causing unpredictable re-renders and cache corruption. Always produce new objects: `queryClient.setQueryData(key, old => ({ ...old, items: [...old.items, newItem] }))`.
45
+ - **[CRITICAL]** `useQuery` called conditionally (inside an `if` or after an early return) → violates React Rules of Hooks, causing runtime error. Always call `useQuery` unconditionally at the top level; use the `enabled` option to control when fetching occurs.
46
+ - **[HIGH]** `onSuccess` callback used in TanStack Query v5 (`useQuery` no longer supports it) → silent no-op, invalidation or side effects never run. Migrate to `mutation.isSuccess` in render or use `useEffect` watching `isSuccess`.
47
+ - **[HIGH]** `queryKey` not including all variables the query depends on (e.g. filters, page number omitted) → stale data served when variables change, cache never invalidated correctly. Include every variable that affects the query result in the key array.
48
+ - **[HIGH]** SSR dehydration/hydration with non-serializable data (`Date`, `Map`, `Set`) in cached queries → hydration mismatch or JSON serialization failure. Use `superjson` as the serializer for `dehydrate`/`hydrate`, or convert to serializable types before caching.
@@ -0,0 +1,52 @@
1
+ # Tauri — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `tauri`, `tauri.conf.json`, `from '@tauri-apps/api'`, `#[tauri::command]`, `src-tauri/`, `Cargo.toml` with tauri
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** Tauri `allowlist` set to `all: true` or broad permission groups → entire Tauri API surface exposed to the frontend JavaScript context. Enable only the specific API namespaces required by the application.
10
+ - **[CRITICAL]** `shell` allowlist enabled without an explicit `scope` allowlist → frontend JavaScript can execute arbitrary shell commands on the user's machine. Define an exact command allowlist with fixed arguments in `tauri.conf.json`.
11
+ - **[HIGH]** Frontend loads remote URLs (not `tauri://localhost`) without a strict Content Security Policy → XSS in remote content gains access to enabled Tauri APIs. Set a restrictive `csp` in `tauri.conf.json` and avoid loading remote content.
12
+ - **[HIGH]** Tauri command handler accepts user-supplied input and passes it to file system, shell, or SQL operations without validation → injection attacks. Validate and sanitize all inputs inside the Rust command handler before use.
13
+ - **[HIGH]** `fs` allowlist scope too broad (e.g., `$HOME`) → frontend can read or write arbitrary files. Restrict `fs` scope to `$APPDATA`, `$APPCONFIG`, or specific subdirectories the application actually needs.
14
+ - **[MEDIUM]** `invoke()` commands for sensitive operations (delete, export, admin) not verifying session state or caller context → any frontend code can trigger privileged commands. Add session validation inside each sensitive Tauri command.
15
+
16
+ ---
17
+
18
+ ## Performance
19
+ - **[HIGH]** Long-running or CPU-bound work performed synchronously inside a Tauri command → blocks the async runtime thread pool. Mark commands `async` and use `tokio::spawn` for truly parallel work or `tokio::task::spawn_blocking` for blocking operations.
20
+ - **[HIGH]** Large data payloads (images, binary files) passed across the IPC boundary as base64 JSON → high serialization overhead and memory doubling. Use Tauri's resource system or write to a temp file and pass the path instead.
21
+ - **[MEDIUM]** Tauri updater not configured with delta updates → full application binary downloaded on every update. Enable delta updates via the updater plugin to minimize update size.
22
+ - **[MEDIUM]** Application window created and shown immediately at startup before content is ready → blank white flash on launch. Use `visible: false` in window config and call `appWindow.show()` after the frontend signals readiness.
23
+ - **[MEDIUM]** All application logic kept in the frontend bundle → no benefit from Rust's performance for compute-heavy tasks. Move computation-intensive operations (crypto, parsing, compression) to Tauri commands.
24
+ - **[LOW]** System tray not used for background tasks → main window kept open solely to maintain a background process. Use `tauri-plugin-system-tray` with a hidden window for background daemon behaviour.
25
+
26
+ ---
27
+
28
+ ## Architecture
29
+ - **[HIGH]** All business logic implemented in the frontend JavaScript → security controls and data access fully bypassable from DevTools. Move trust boundaries, validation, and data access to Rust Tauri commands.
30
+ - **[MEDIUM]** Tauri commands not organized into logical Rust modules → all commands in one file, hard to navigate. Group commands by domain into separate modules and register them with `generate_handler!`.
31
+ - **[MEDIUM]** Shared mutable state managed as a Rust `Mutex<Option<T>>` global instead of Tauri's `State<T>` → not integrated with Tauri's lifecycle. Use `tauri::Builder::manage()` to register state and `State<T>` in command signatures.
32
+ - **[MEDIUM]** Frontend communicates with Rust exclusively through synchronous `invoke()` calls → no event-driven updates from Rust to frontend. Use `window.emit()` from Rust for push notifications (progress, background events) to the frontend.
33
+ - **[LOW]** Common functionality (file watching, HTTP, shell) reimplemented manually instead of using official Tauri plugins → duplicated effort and missed security fixes. Use `tauri-plugin-fs`, `tauri-plugin-http`, and other official plugins where available.
34
+
35
+ ---
36
+
37
+ ## Code Quality
38
+ - **[HIGH]** `unwrap()` or `expect()` used inside Tauri command handlers → panics surface as untyped errors on the frontend with no actionable information. Define a custom error enum implementing `serde::Serialize` and return `Result<T, AppError>` from all commands.
39
+ - **[MEDIUM]** Tauri command errors not typed with a serializable enum → frontend receives a plain string and cannot programmatically distinguish error types. Create an `AppError` enum with `#[derive(Debug, Serialize)]` and map all error types to it.
40
+ - **[MEDIUM]** Commands not registered via `generate_handler!` macro → commands silently missing at runtime with no compile-time error. Ensure all public command functions are listed in `generate_handler!` in `main.rs`.
41
+ - **[MEDIUM]** Window configuration (title, min/max size, decorations) not specified in `tauri.conf.json` → window appears with OS defaults that may not match application design. Define window properties explicitly in the config.
42
+ - **[LOW]** Rust dependencies in `Cargo.toml` not version-pinned → `cargo update` may introduce breaking changes. Pin dependencies to exact versions and review `Cargo.lock` in version control.
43
+
44
+ ---
45
+
46
+ ## Common Bugs & Pitfalls
47
+ - **[HIGH]** Content Security Policy blocks `tauri://localhost` or `ipc://localhost` → Tauri's IPC bridge is non-functional and `invoke()` calls silently fail. Ensure the CSP `connect-src` directive includes `tauri://localhost` and `ipc://localhost`.
48
+ - **[HIGH]** `async` Tauri command performing blocking I/O with `std::fs` or `std::thread::sleep` → starves the async runtime. Replace with `tokio::fs`, `tokio::time::sleep`, and other async-compatible alternatives.
49
+ - **[MEDIUM]** Two windows created with the same `label` → Tauri panics or silently fails to open the second window. Use unique labels per window and check for existing windows with `app.get_window()` before creating.
50
+ - **[MEDIUM]** File paths constructed with string concatenation instead of `std::path::PathBuf` → path separator mismatches on Windows (`\` vs `/`). Always use `PathBuf` and `.join()` for cross-platform path construction.
51
+ - **[MEDIUM]** Tauri `beforeMount` or `DOMContentLoaded` events used to call `invoke()` before the IPC bridge is ready → race condition causing failed invocations on startup. Wait for the `tauri://window-created` event before making IPC calls.
52
+ - **[LOW]** macOS code signing and notarization not configured in EAS/CI → Gatekeeper blocks the app on first launch. Configure `signingIdentity` and Apple notarization credentials in the build pipeline.
@@ -0,0 +1,53 @@
1
+ # Terraform — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.tf` files · `terraform {` block · `resource "` · `provider "` · `variable "` · `module "` · `terraform.tfvars` · `.terraform/` directory
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** Sensitive values (passwords, private keys, connection strings) hardcoded in `.tf` files → committed to version control. Use `sensitive = true` variables + secrets manager or environment variable injection.
11
+ - **[HIGH]** `sensitive = false` on variables containing passwords or keys → value printed in `terraform plan` output and stored in state file in plaintext. Mark as `sensitive = true`.
12
+ - **[HIGH]** State file in unencrypted S3 bucket or stored locally → Terraform state contains all resource attributes including secrets. Enable server-side encryption and restrict bucket access.
13
+ - **[HIGH]** Overly permissive IAM policies: `"Action": "*"` or `"Resource": "*"` → violates least-privilege. Grant only the specific actions and resources needed.
14
+ - **[MEDIUM]** `terraform.tfvars` or `*.auto.tfvars` with secrets committed to version control → add to `.gitignore`, use environment variables or vault integration.
15
+ - **[MEDIUM]** Publicly accessible S3 bucket, RDS instance, or security group with `0.0.0.0/0` ingress on sensitive ports → review each resource for unintended exposure.
16
+
17
+ ---
18
+
19
+ ## Performance
20
+
21
+ - **[HIGH]** `count` used for resource iteration when `for_each` is more appropriate → with `count`, inserting at index N causes destroy/recreate of all resources after N. Use `for_each` with a map or set for stable addressing.
22
+ - **[MEDIUM]** Monolithic root module with hundreds of resources → slow `terraform plan` (all providers refreshed) and hard to review. Split into composable child modules.
23
+ - **[MEDIUM]** Missing `depends_on` for resources with implicit ordering requirements not expressible through attribute references → apply may fail on first run, succeed on retry.
24
+ - **[LOW]** Unused `data` sources or `local` values → increases plan time. Remove unused blocks.
25
+
26
+ ---
27
+
28
+ ## Architecture
29
+
30
+ - **[HIGH]** No remote backend configured → state is local, not shared with team, no state locking. Configure `backend "s3"`, `backend "azurerm"`, or Terraform Cloud.
31
+ - **[HIGH]** Applying directly to production without reviewing `terraform plan` output first → risk of unintended `destroy` or `replace` operations.
32
+ - **[MEDIUM]** Hardcoded region, account ID, or environment name in module → module not reusable. Parameterize with variables.
33
+ - **[MEDIUM]** Resources without tags for environment, owner, and cost-center → no governance, no cost attribution in billing dashboards.
34
+ - **[LOW]** Circular module dependencies → Terraform cannot resolve the dependency graph. Restructure modules or use data sources.
35
+
36
+ ---
37
+
38
+ ## Code Quality
39
+
40
+ - **[HIGH]** Variable declared without a `type` constraint → implicit `any` type; type errors surface at `apply` time, not `validate` or `plan` time.
41
+ - **[MEDIUM]** `lifecycle { prevent_destroy = true }` missing on critical resources (RDS, S3, load balancers) → accidental `terraform destroy` or resource replacement deletes data.
42
+ - **[MEDIUM]** Large inline `user_data` or `metadata_startup_script` → hard to review, can't be linted. Extract to a `templatefile()` call referencing an external `.sh` / `.tpl` file.
43
+ - **[LOW]** No `description` field on `variable` or `output` blocks → other team members can't understand the module interface without reading all `.tf` files.
44
+
45
+ ---
46
+
47
+ ## Common Bugs & Pitfalls
48
+
49
+ - **[CRITICAL]** Running `terraform destroy` without `-target` on a shared environment → destroys ALL resources in the state, including shared infrastructure.
50
+ - **[HIGH]** `terraform plan` shows "forces replacement" on a critical resource (RDS, EKS cluster) but change is applied anyway → downtime or data loss. Understand the cause before applying.
51
+ - **[MEDIUM]** Forgetting `terraform init` after adding a new provider or module source → `provider not installed` error at plan/apply time.
52
+ - **[MEDIUM]** `output { sensitive = false }` on an output that references a `sensitive` variable → Terraform 0.15+ will error. Mark output as `sensitive = true`.
53
+ - **[LOW]** `.terraform.lock.hcl` not committed to version control → non-reproducible provider versions across team members and CI.
@@ -0,0 +1,53 @@
1
+ # Three.js — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `from 'three'`, `THREE.`, `WebGLRenderer`, `Scene`, `PerspectiveCamera`, `AnimationMixer`, `from '@react-three/fiber'`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** Loading 3D models (GLTF, OBJ, FBX) from user-supplied URLs without validation → SSRF, loading of malicious files from internal network. Validate URLs against an allowlist and load only from trusted origins.
10
+ - **[HIGH]** Executing code stored in `userData` property of loaded 3D objects → arbitrary code execution from untrusted model files. Never `eval` or invoke functions sourced from loaded model metadata.
11
+ - **[MEDIUM]** Cross-origin textures loaded with `THREE.TextureLoader` without explicit CORS policy on the asset server → WebGL security error or silent failure. Set `crossOrigin = 'anonymous'` on the loader and ensure the asset server sends CORS headers.
12
+ - **[MEDIUM]** Renderer canvas element accessible and writable by untrusted third-party scripts on the page → canvas poisoning or pixel data theft via `getImageData`. Apply Content Security Policy and isolate the canvas from third-party script access.
13
+ - **[LOW]** Debug helpers (`AxesHelper`, `GridHelper`, `Stats`) left in production builds → scene structure and performance metrics exposed. Gate all helpers behind a `DEBUG` flag.
14
+
15
+ ---
16
+
17
+ ## Performance
18
+ - **[CRITICAL]** Geometries, materials, and textures not disposed when objects are removed from the scene → GPU memory leak that grows indefinitely. Always call `geometry.dispose()`, `material.dispose()`, and `texture.dispose()` before removing objects, and call `renderer.dispose()` on teardown.
19
+ - **[HIGH]** Animation loop running without `requestAnimationFrame` (e.g., `setInterval`) → uncapped frame rate, excessive CPU/GPU usage, and frame timing drift. Always drive the render loop with `requestAnimationFrame` or R3F's `useFrame`.
20
+ - **[HIGH]** `castShadow` and `receiveShadow` enabled on all objects indiscriminately → shadow map recalculated for every shadow-casting object each frame. Enable shadows only on objects that require them and use `renderer.shadowMap.autoUpdate = false` for static scenes.
21
+ - **[HIGH]** High-polygon geometry without Level of Detail (LOD) → frame budget exceeded for distant or small objects. Implement `THREE.LOD` with reduced-poly meshes at increasing distances.
22
+ - **[HIGH]** Uncompressed textures (PNG/JPEG) loaded directly → excessive VRAM usage and long load times. Use KTX2/Basis compressed textures via `KTX2Loader` for GPU-native formats.
23
+ - **[MEDIUM]** New `THREE.Vector3`, `THREE.Color`, or `THREE.Matrix4` instantiated inside the animation loop → garbage collection pauses causing frame drops. Pre-allocate reusable objects outside the loop and use `.set()` to update values.
24
+ - **[MEDIUM]** No frustum culling awareness for large scenes with many off-screen objects → GPU draw calls wasted on invisible geometry. Enable `object.frustumCulled = true` (default) and avoid disabling it without reason.
25
+
26
+ ---
27
+
28
+ ## Architecture
29
+ - **[HIGH]** All scene setup, animation, and interaction logic in a single file or class → unmaintainable God object. Separate scene graph setup, animation system, asset loading, and input handling into distinct modules.
30
+ - **[HIGH]** Animation loop (`requestAnimationFrame` callback) not stopped on component unmount → renderer continues consuming GPU resources after the component is gone. Store the animation frame ID and call `cancelAnimationFrame(id)` on cleanup.
31
+ - **[MEDIUM]** Assets loaded without `GLTFLoader` Draco or Meshopt compression → large file sizes increasing time-to-interactive. Use `DRACOLoader` or `MeshoptDecoder` with `GLTFLoader` for geometry compression.
32
+ - **[MEDIUM]** Physics or game logic calculations tied directly to frame rate inside `renderer.render()` callback → simulation speed varies with display refresh rate. Use a fixed timestep accumulator pattern separate from the render loop.
33
+ - **[LOW]** No asset loading manager (`THREE.LoadingManager`) → no coordinated loading progress or error handling across multiple assets. Use a shared `LoadingManager` to track and report loading state.
34
+
35
+ ---
36
+
37
+ ## Code Quality
38
+ - **[HIGH]** `renderer.render(scene, camera)` called without a `resize` event handler updating renderer size and camera aspect ratio → distorted perspective on window resize or container size change. Add `ResizeObserver` or `window.resize` handler calling `renderer.setSize()` and updating `camera.aspect` then `camera.updateProjectionMatrix()`.
39
+ - **[MEDIUM]** Manual `requestAnimationFrame` loop used inside React components instead of R3F's `useFrame` hook → conflicts with R3F's render loop causing double renders. Use `useFrame` exclusively when working within React Three Fiber.
40
+ - **[MEDIUM]** Three.js objects not typed with JSDoc or TypeScript imports → autocompletion and type safety lost. Import types from `three` and annotate all scene object variables explicitly.
41
+ - **[MEDIUM]** `renderer.setPixelRatio(window.devicePixelRatio)` not capped → on high-DPI displays, pixel ratio of 3+ multiplies GPU work by 9x. Cap with `Math.min(window.devicePixelRatio, 2)`.
42
+ - **[LOW]** `Object3D.name` properties left empty on scene graph nodes → debugging via `scene.getObjectByName()` impossible and DevTools scene inspector uninformative. Assign meaningful names to all significant scene objects.
43
+
44
+ ---
45
+
46
+ ## Common Bugs & Pitfalls
47
+ - **[CRITICAL]** Geometry and material not disposed when mesh is removed from scene → GPU memory leak; application slows and crashes over time. Implement a disposal utility that traverses removed subtrees and calls `dispose()` on all geometry and material instances.
48
+ - **[HIGH]** Z-fighting artifacts from two coplanar geometries (e.g., decal on a surface) → flickering at shared depth. Apply `polygonOffset: true` with `polygonOffsetFactor` and `polygonOffsetUnits` to the front material.
49
+ - **[HIGH]** Camera aspect ratio not updated after renderer resize → scene appears squashed or stretched. Always call `camera.aspect = width / height` and `camera.updateProjectionMatrix()` in the resize handler.
50
+ - **[MEDIUM]** `AnimationMixer` actions not stopped and mixer not `uncacheRoot`'d before disposing the associated object → animation system holds a reference, preventing GC. Call `mixer.stopAllAction()` and `mixer.uncacheRoot(mesh)` before removal.
51
+ - **[MEDIUM]** `Raycaster` not updated by calling `raycaster.setFromCamera(mouse, camera)` immediately before `intersectObjects()` → intersection test uses stale camera state, returning wrong or no hits.
52
+ - **[MEDIUM]** `WebGLRenderer` created multiple times without disposing the previous instance → each renderer allocates a WebGL context; browsers limit WebGL contexts per page. Reuse a single renderer instance or dispose before creating a new one.
53
+ - **[LOW]** `OrbitControls` `update()` not called in animation loop when `enableDamping` is true → damping never resolves, camera movement is choppy. Call `controls.update()` every frame when damping is enabled.
@@ -0,0 +1,49 @@
1
+ # tRPC — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `from '@trpc/server'`, `from '@trpc/client'`, `from '@trpc/react-query'`, `initTRPC`, `router()`, `publicProcedure`, `protectedProcedure`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** Sensitive operations (user data, admin actions) implemented on `publicProcedure` without any auth middleware → unauthenticated access to protected resources. Create `protectedProcedure` that validates session from context and use it for all authenticated routes.
10
+ - **[CRITICAL]** `protectedProcedure` middleware absent → no consistent enforcement of authentication across the router. Define and enforce a middleware chain: `t.middleware(({ ctx, next }) => { if (!ctx.user) throw new TRPCError({ code: 'UNAUTHORIZED' }); return next({ ctx }) })`.
11
+ - **[HIGH]** Procedure input not validated with a Zod schema → type confusion, prototype pollution, and unexpected data shapes reaching business logic. Always define `.input(z.object({ ... }))` on every procedure that accepts input.
12
+ - **[HIGH]** Returning full ORM/DB model objects instead of selecting only needed fields → PII and internal fields (hashed passwords, internal IDs) exposed to clients. Select only required fields in DB queries; use Zod `.pick()` or explicit select projections.
13
+ - **[HIGH]** IDOR via ID passed in input without ownership verification → user A reads or mutates user B's data. After fetching by input ID, assert `record.userId === ctx.user.id` before returning or modifying.
14
+ - **[MEDIUM]** Internal error details (stack traces, DB error messages) leaking to client in production → reconnaissance information for attackers. Configure `errorFormatter` to strip internal details in production: return only `code` and a safe `message`.
15
+
16
+ ---
17
+
18
+ ## Performance
19
+ - **[HIGH]** N+1 query pattern in query handlers — fetching a list then querying per-item in a loop → multiplicative DB round trips. Batch with a single query using `WHERE id IN (...)` or use a DataLoader instance per request.
20
+ - **[HIGH]** DataLoader pattern not used for cross-procedure data sharing → repeated identical queries across procedures in a single request. Attach per-request DataLoader instances to context and use them in all procedures.
21
+ - **[HIGH]** tRPC subscriptions not cleaned up when the client disconnects → server-side resource leak (DB connections, event emitter listeners). Use the `on` cleanup return in `observable` to tear down resources when the subscription ends.
22
+ - **[MEDIUM]** `useQuery` called without configuring `staleTime` or `gcTime` → refetches on every component mount and window focus. Set appropriate `staleTime` per query based on data freshness requirements.
23
+ - **[MEDIUM]** Large objects serialized over the wire without selecting specific fields → high bandwidth usage and slow serialization. Define output schemas with `.output(z.object({ ... }))` to enforce response shape and size.
24
+
25
+ ---
26
+
27
+ ## Architecture
28
+ - **[HIGH]** Business logic (complex validation, external API calls, DB operations) written directly inside procedure handlers → untestable handlers, fat router files. Extract to a service layer; procedures should only orchestrate: validate input → call service → return result.
29
+ - **[HIGH]** `t.createCallerFactory` not used for server-to-server calls; instead procedures called by importing handler functions directly → context middleware (auth, logging) is bypassed. Use `createCallerFactory` to call procedures server-side so middleware runs correctly.
30
+ - **[MEDIUM]** Context not used to inject shared services (DB client, logger, auth) → services instantiated inside procedures, no request-scoped sharing. Attach all shared services to the tRPC context in `createContext` and consume via `ctx`.
31
+ - **[MEDIUM]** Deeply nested routers without a clear domain boundary grouping → hard to navigate, hard to apply middleware selectively. Group by domain (e.g. `userRouter`, `postRouter`) with one file per domain; merge in a root `appRouter`.
32
+ - **[MEDIUM]** Missing `errorFormatter` in `initTRPC` configuration → default error shape varies between tRPC versions and client expectations. Define a consistent `errorFormatter` that maps `TRPCError` to a stable client-facing structure.
33
+
34
+ ---
35
+
36
+ ## Code Quality
37
+ - **[MEDIUM]** Procedure responses not validated with `.output()` schema → clients receive untyped `unknown` responses; breaking changes in DB schema silently alter API shape. Add `.output(z.object({ ... }))` to critical procedures to enforce response contracts.
38
+ - **[MEDIUM]** Procedures scattered across many files without a consistent co-location strategy → hard to find and review related functionality. Co-locate each router with its domain: `src/server/routers/user.ts` contains all user-related procedures.
39
+ - **[HIGH]** `query` procedure used for operations with side effects (sending email, writing DB) → GET requests cached by browser/CDN, side effect may not run on repeat navigations. Always use `mutation` for any operation that changes state.
40
+ - **[LOW]** Procedures not annotated with a `meta` description → generated OpenAPI docs (if used) are empty; hard to discover API surface. Add `meta: { openapi: { method: 'GET', path: '/resource', description: '...' } }` or use `procedure.meta({ description: '...' })`.
41
+
42
+ ---
43
+
44
+ ## Common Bugs & Pitfalls
45
+ - **[HIGH]** `useQuery` without `error` state handled in the UI → unhandled errors are silently swallowed; user sees blank/stale UI with no feedback. Always destructure and render `error` from every `useQuery` call.
46
+ - **[HIGH]** `ctx.user` typed as `any` because context type not properly inferred → type safety of `protectedProcedure` is illusory. Ensure `createContext` return type is explicit and flows into the `initTRPC` generic: `initTRPC.context<Context>().create()`.
47
+ - **[HIGH]** Infinite queries not using cursor-based pagination → offset pagination breaks on concurrent inserts/deletes. Use `z.object({ cursor: z.string().optional() })` input and return `{ items, nextCursor }` for `useInfiniteQuery`.
48
+ - **[HIGH]** `useMutation`'s `onSuccess` not calling `utils.queryName.invalidate()` → related `useQuery` data stays stale after mutation. Add cache invalidation in `onSuccess`: `await utils.posts.list.invalidate()`.
49
+ - **[HIGH]** `superjson` transformer not configured on both the tRPC client and server → `Date` objects serialized as strings on server are not deserialized back to `Date` on client; type mismatch. Add `transformer: superjson` to both `initTRPC.create()` and `createTRPCProxyClient()`.
@@ -0,0 +1,40 @@
1
+ # TypeORM — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `@Entity(`, `@Column(`, `@PrimaryGeneratedColumn`, `TypeORM`, `DataSource`, `createConnection`, `getRepository(`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** `createQueryBuilder().where(\`id = ${userId}\`)` → SQL injection. Always use parameterized: `.where("id = :id", { id: userId })`.
11
+ - **[HIGH]** Entity returned directly from controller → exposes all columns. Use DTOs and `@Exclude()` / `plainToClass`.
12
+ - **[MEDIUM]** `getManager().query()` with string interpolation → injection. Use parameterized.
13
+
14
+ ---
15
+
16
+ ## Performance
17
+
18
+ - **[HIGH]** N+1 — accessing relation (`entity.relation`) in loop without `relations` option or `leftJoinAndSelect`. Use `find({ relations: ['relation'] })`.
19
+ - **[HIGH]** `find()` without `take`/`skip` on large tables → unbounded result.
20
+ - **[HIGH]** Missing `@Index()` on columns used in `where`, `order`, `join`.
21
+ - **[MEDIUM]** Using `getRepository()` inside function calls → creates new repository instance each time. Get repository once outside.
22
+ - **[MEDIUM]** Multiple separate queries that could be wrapped in `queryRunner.startTransaction()`.
23
+ - **[LOW]** `eager: true` on relation → always loaded even when not needed.
24
+
25
+ ---
26
+
27
+ ## Architecture
28
+
29
+ - **[HIGH]** TypeORM entity used as DTO directly → couples DB schema to API contract.
30
+ - **[MEDIUM]** `getConnection()` (deprecated) instead of `DataSource.getRepository()`.
31
+ - **[MEDIUM]** Missing `@Transaction()` decorator or manual transaction on multi-step writes.
32
+
33
+ ---
34
+
35
+ ## Common Bugs & Pitfalls
36
+
37
+ - **[HIGH]** `save()` on partial entity object → fields not included default to `undefined`, overwriting existing values with NULL.
38
+ - **[MEDIUM]** `@BeforeInsert` / `@BeforeUpdate` hooks not firing on `update()` query builder — hooks only fire on `save()`.
39
+ - **[MEDIUM]** `cascade: true` on relation without understanding → unintended deletes or inserts.
40
+ - **[LOW]** Missing `synchronize: false` in production config → TypeORM auto-migrates schema, dangerous on live DB.
@@ -0,0 +1,83 @@
1
+ # TypeScript — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.ts` / `*.tsx` files, `tsconfig.json`, `typescript` in devDeps, `strict: true`, type imports
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[HIGH]** `as any` on external/user data bypasses all type checking → runtime errors and security holes. Use `unknown` + type narrowing.
11
+ - **[HIGH]** Missing runtime validation at system boundaries (API responses, user input, env vars) — types are erased at runtime; use Zod/Valibot/ArkType.
12
+ - **[HIGH]** Prototype pollution via `Object.assign({}, userInput)` with no type guard → attacker can set `__proto__`.
13
+ - **[MEDIUM]** `@ts-ignore` without explanation → suppressing errors that may indicate real bugs.
14
+ - **[MEDIUM]** Unsafe type cast `value as SpecificType` without runtime validation → assumption may be wrong at runtime.
15
+ - **[MEDIUM]** `JSON.parse(userInput)` typed with `as MyType` without validation → type lie, runtime mismatch.
16
+ - **[LOW]** `any` return from `JSON.parse()` propagating through typed interfaces without guard.
17
+
18
+ ---
19
+
20
+ ## Performance
21
+
22
+ - **[HIGH]** Massive barrel files (`index.ts` re-exporting hundreds of items) → slow TypeScript compilation and IDE.
23
+ - **[HIGH]** Deeply nested conditional types → exponential type-checking time; simplify with mapped types.
24
+ - **[MEDIUM]** `const enum` used in declaration files / across module boundaries → erasure issues with bundlers.
25
+ - **[MEDIUM]** Type assertions `as` in hot paths creating false sense of safety and potential misuse.
26
+ - **[LOW]** Project references not configured for monorepo → single tsconfig compiling everything slowly.
27
+ - **[LOW]** `tsc --noEmit` not run in CI → type errors only caught on build.
28
+
29
+ ---
30
+
31
+ ## Architecture
32
+
33
+ - **[HIGH]** `any` type on function parameters, return types, or variables → defeats TypeScript's purpose. Use `unknown` + narrow.
34
+ - **[HIGH]** `strict: false` in tsconfig → implicit `any`, loose null checks. Always enable `"strict": true`.
35
+ - **[HIGH]** Non-null assertion `!` without justification → potential `null`/`undefined` runtime crash.
36
+ - **[HIGH]** Types defined as `interface` with implementation knowledge leaked into them → couple type to impl.
37
+ - **[HIGH]** `any` used in generics `<T = any>` → generic provides no type safety.
38
+ - **[HIGH]** Discriminated union missing exhaustive check → new variant added later silently falls through.
39
+ - **[MEDIUM]** Missing return type annotation on exported functions → API contract not enforced.
40
+ - **[MEDIUM]** `interface` vs `type` inconsistency → pick one convention; `type` for unions/intersections, `interface` for objects.
41
+ - **[MEDIUM]** Overly broad union type instead of discriminated union → defeats narrowing.
42
+ - **[MEDIUM]** `extends` abuse creating deep inheritance chains → use composition/intersection types.
43
+ - **[MEDIUM]** `Partial<T>` used as function return type when specific optional fields are known → too permissive.
44
+ - **[MEDIUM]** Type utilities (`Pick`, `Omit`, `Partial`) not used → manual re-typing of subsets creates drift.
45
+ - **[LOW]** `enum` usage → prefer `as const` objects for better tree-shaking and JS interop.
46
+ - **[LOW]** Missing `readonly` on arrays/objects that shouldn't be mutated → accidental mutation.
47
+ - **[LOW]** Deeply nested generic types (3+ levels) → create intermediate type aliases for readability.
48
+
49
+ ---
50
+
51
+ ## Code Quality
52
+
53
+ - **[HIGH]** `// @ts-ignore` or `// @ts-expect-error` without comment explaining why → hidden bugs.
54
+ - **[HIGH]** Missing null/undefined checks on values from external sources → `Cannot read properties of undefined` at runtime.
55
+ - **[HIGH]** `!` non-null assertion on DOM queries (`document.getElementById('x')!`) → crashes if element missing.
56
+ - **[HIGH]** `keyof typeof obj` not used when iterating object keys → `Object.keys()` returns `string[]`, losing type info.
57
+ - **[MEDIUM]** `import` instead of `import type` for type-only imports → slightly larger bundles, breaks isolatedModules.
58
+ - **[MEDIUM]** Duplicate type definitions across files instead of shared types module → drift over time.
59
+ - **[MEDIUM]** Type assertions in tests (`as any`, `as unknown as T`) masking real type errors.
60
+ - **[MEDIUM]** `Record<string, any>` instead of specific type → index signature hides structure.
61
+ - **[MEDIUM]** `Function` type instead of specific signature → loses parameter and return type info.
62
+ - **[MEDIUM]** `object` type instead of `Record<string, unknown>` → too broad, no property access.
63
+ - **[LOW]** Missing JSDoc on exported public API functions → poor IDE experience for consumers.
64
+ - **[LOW]** Large barrel `index.ts` exporting everything → circular dependency risk, slow compilation.
65
+ - **[LOW]** `namespace` used instead of ES modules → legacy pattern, avoid in new code.
66
+
67
+ ---
68
+
69
+ ## Common Bugs & Pitfalls
70
+
71
+ - **[HIGH]** Optional chaining `?.` used but result not checked before use → defeats the purpose; still need null check.
72
+ - **[HIGH]** `async` function in array `.map()` → returns `Promise[]` not resolved values. Use `Promise.all(arr.map(async ...))`.
73
+ - **[HIGH]** Spreading typed object onto untyped base `{ ...defaults, ...userInput }` where `userInput: any` → loses type safety.
74
+ - **[HIGH]** `as unknown as T` double assertion → bypasses all type checking; red flag in code review.
75
+ - **[HIGH]** Generic constraint not tight enough → function accepts invalid types without error.
76
+ - **[MEDIUM]** `Object.keys(obj)` returns `string[]` not `(keyof typeof obj)[]` → type-unsafe iteration.
77
+ - **[MEDIUM]** `parseInt` / `parseFloat` return `NaN` on invalid input, not caught → NaN propagates silently.
78
+ - **[MEDIUM]** Conditional type `extends` not distributing over union as expected → wrap in `[]` to prevent distribution.
79
+ - **[MEDIUM]** `infer` in complex conditional types causing `never` unexpectedly → simplify or test with `ts-expect-error`.
80
+ - **[MEDIUM]** Declaration merging on interfaces used inadvertently → confusing for maintainers.
81
+ - **[MEDIUM]** Mapped type modifiers (`-readonly`, `-?`) not understood → removing optionality unintentionally.
82
+ - **[LOW]** `satisfies` operator (TS 4.9+) not used where it would be clearer than `as`.
83
+ - **[LOW]** Template literal types used for validation logic that should be runtime validation.