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.
- package/LICENSE +1 -1
- package/README.md +260 -235
- package/docs/assets/banner.svg +30 -248
- package/docs/assets/how-it-works.svg +87 -0
- package/package.json +60 -60
- package/src/core/agents/prr-master.agent.yaml +18 -7
- package/src/core/tasks/clear.md +140 -0
- package/src/core/tasks/help.md +15 -13
- package/src/core/workflows/clear/workflow.md +6 -0
- package/src/core/workflows/help/workflow.md +6 -0
- package/src/core/workflows/party-mode/steps/step-01-load-reviewers.md +35 -24
- package/src/core/workflows/party-mode/steps/step-02-discussion.md +45 -25
- package/src/core/workflows/party-mode/workflow.md +2 -2
- package/src/prr/agents/architecture-reviewer.agent.yaml +65 -45
- package/src/prr/agents/business-reviewer.agent.yaml +66 -0
- package/src/prr/agents/general-reviewer.agent.yaml +64 -48
- package/src/prr/agents/performance-reviewer.agent.yaml +65 -45
- package/src/prr/agents/security-reviewer.agent.yaml +67 -43
- package/src/prr/config-template.yaml +97 -0
- package/src/prr/data/stacks/actix.md +55 -0
- package/src/prr/data/stacks/alpine.md +47 -0
- package/src/prr/data/stacks/android.md +53 -0
- package/src/prr/data/stacks/angular.md +96 -0
- package/src/prr/data/stacks/ansible.md +55 -0
- package/src/prr/data/stacks/apollo.md +54 -0
- package/src/prr/data/stacks/astro.md +48 -0
- package/src/prr/data/stacks/aws-cdk.md +55 -0
- package/src/prr/data/stacks/axum.md +56 -0
- package/src/prr/data/stacks/babylonjs.md +55 -0
- package/src/prr/data/stacks/bash.md +53 -0
- package/src/prr/data/stacks/bevy.md +53 -0
- package/src/prr/data/stacks/bootstrap.md +52 -0
- package/src/prr/data/stacks/bun.md +55 -0
- package/src/prr/data/stacks/cpp.md +57 -0
- package/src/prr/data/stacks/csharp.md +95 -0
- package/src/prr/data/stacks/css.md +55 -0
- package/src/prr/data/stacks/cypress.md +53 -0
- package/src/prr/data/stacks/d3.md +53 -0
- package/src/prr/data/stacks/deno.md +49 -0
- package/src/prr/data/stacks/django.md +92 -0
- package/src/prr/data/stacks/docker.md +79 -0
- package/src/prr/data/stacks/drizzle.md +54 -0
- package/src/prr/data/stacks/dynamodb.md +55 -0
- package/src/prr/data/stacks/electron.md +44 -0
- package/src/prr/data/stacks/elixir.md +53 -0
- package/src/prr/data/stacks/expo.md +53 -0
- package/src/prr/data/stacks/expressjs.md +82 -0
- package/src/prr/data/stacks/fastapi.md +88 -0
- package/src/prr/data/stacks/fastify.md +60 -0
- package/src/prr/data/stacks/fiber.md +55 -0
- package/src/prr/data/stacks/firebase.md +43 -0
- package/src/prr/data/stacks/flask.md +46 -0
- package/src/prr/data/stacks/flutter.md +75 -0
- package/src/prr/data/stacks/gin.md +57 -0
- package/src/prr/data/stacks/github-actions.md +71 -0
- package/src/prr/data/stacks/go.md +88 -0
- package/src/prr/data/stacks/godot.md +56 -0
- package/src/prr/data/stacks/graphql.md +76 -0
- package/src/prr/data/stacks/grpc.md +56 -0
- package/src/prr/data/stacks/haskell.md +48 -0
- package/src/prr/data/stacks/helm.md +54 -0
- package/src/prr/data/stacks/hono.md +54 -0
- package/src/prr/data/stacks/htmx.md +38 -0
- package/src/prr/data/stacks/java.md +87 -0
- package/src/prr/data/stacks/jest-vitest.md +87 -0
- package/src/prr/data/stacks/jquery.md +50 -0
- package/src/prr/data/stacks/junit.md +53 -0
- package/src/prr/data/stacks/kotlin.md +89 -0
- package/src/prr/data/stacks/kubernetes.md +148 -0
- package/src/prr/data/stacks/langchain.md +56 -0
- package/src/prr/data/stacks/laravel.md +56 -0
- package/src/prr/data/stacks/libgdx.md +46 -0
- package/src/prr/data/stacks/lit.md +49 -0
- package/src/prr/data/stacks/love2d.md +51 -0
- package/src/prr/data/stacks/lua.md +51 -0
- package/src/prr/data/stacks/mobx.md +54 -0
- package/src/prr/data/stacks/mongodb.md +85 -0
- package/src/prr/data/stacks/monogame.md +51 -0
- package/src/prr/data/stacks/mysql.md +57 -0
- package/src/prr/data/stacks/nestjs.md +95 -0
- package/src/prr/data/stacks/nextjs.md +88 -0
- package/src/prr/data/stacks/nginx.md +55 -0
- package/src/prr/data/stacks/node.md +56 -0
- package/src/prr/data/stacks/nuxtjs.md +91 -0
- package/src/prr/data/stacks/openai-api.md +54 -0
- package/src/prr/data/stacks/opengl.md +54 -0
- package/src/prr/data/stacks/phaser.md +54 -0
- package/src/prr/data/stacks/phoenix.md +55 -0
- package/src/prr/data/stacks/php.md +56 -0
- package/src/prr/data/stacks/playwright.md +86 -0
- package/src/prr/data/stacks/postgresql.md +60 -0
- package/src/prr/data/stacks/prisma.md +81 -0
- package/src/prr/data/stacks/pygame.md +52 -0
- package/src/prr/data/stacks/pytest.md +53 -0
- package/src/prr/data/stacks/python.md +94 -0
- package/src/prr/data/stacks/pytorch.md +54 -0
- package/src/prr/data/stacks/qwik.md +50 -0
- package/src/prr/data/stacks/rails.md +48 -0
- package/src/prr/data/stacks/react-native.md +77 -0
- package/src/prr/data/stacks/react.md +104 -0
- package/src/prr/data/stacks/redis.md +76 -0
- package/src/prr/data/stacks/redux.md +107 -0
- package/src/prr/data/stacks/remix.md +51 -0
- package/src/prr/data/stacks/rust.md +88 -0
- package/src/prr/data/stacks/sass.md +51 -0
- package/src/prr/data/stacks/scala.md +50 -0
- package/src/prr/data/stacks/scikit-learn.md +53 -0
- package/src/prr/data/stacks/sequelize.md +54 -0
- package/src/prr/data/stacks/socket-io.md +54 -0
- package/src/prr/data/stacks/solidity.md +53 -0
- package/src/prr/data/stacks/solidjs.md +45 -0
- package/src/prr/data/stacks/spring-boot.md +92 -0
- package/src/prr/data/stacks/sql.md +85 -0
- package/src/prr/data/stacks/sqlite.md +55 -0
- package/src/prr/data/stacks/styled-components.md +51 -0
- package/src/prr/data/stacks/supabase.md +57 -0
- package/src/prr/data/stacks/svelte.md +77 -0
- package/src/prr/data/stacks/sveltekit.md +54 -0
- package/src/prr/data/stacks/swift.md +61 -0
- package/src/prr/data/stacks/tailwindcss.md +10 -0
- package/src/prr/data/stacks/tanstack-query.md +48 -0
- package/src/prr/data/stacks/tauri.md +52 -0
- package/src/prr/data/stacks/terraform.md +53 -0
- package/src/prr/data/stacks/three.md +53 -0
- package/src/prr/data/stacks/trpc.md +49 -0
- package/src/prr/data/stacks/typeorm.md +40 -0
- package/src/prr/data/stacks/typescript.md +83 -0
- package/src/prr/data/stacks/unity.md +61 -0
- package/src/prr/data/stacks/unreal.md +58 -0
- package/src/prr/data/stacks/vite.md +48 -0
- package/src/prr/data/stacks/vue3.md +95 -0
- package/src/prr/data/stacks/vulkan.md +53 -0
- package/src/prr/data/stacks/wasm.md +49 -0
- package/src/prr/data/stacks/webpack.md +48 -0
- package/src/prr/data/stacks/zig.md +51 -0
- package/src/prr/data/stacks/zustand.md +56 -0
- package/src/prr/workflows/1-discover/select-pr/steps/step-05-confirm.md +1 -0
- package/src/prr/workflows/1-discover/select-pr/workflow.md +1 -1
- package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-01-analyze-files.md +334 -0
- package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-02-collect-sources.md +451 -0
- package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-03-build-knowledge-base.md +337 -0
- package/src/prr/workflows/2-analyze/collect-pr-context/workflow.md +123 -0
- package/src/prr/workflows/2-analyze/describe-pr/steps/step-02-classify.md +12 -6
- package/src/prr/workflows/2-analyze/describe-pr/steps/step-03-walkthrough.md +59 -1
- package/src/prr/workflows/3-review/architecture-review/checklist.md +4 -0
- package/src/prr/workflows/3-review/architecture-review/instructions.xml +32 -4
- package/src/prr/workflows/3-review/architecture-review/workflow.yaml +17 -18
- package/src/prr/workflows/3-review/business-review/checklist.md +27 -0
- package/src/prr/workflows/3-review/business-review/instructions.xml +153 -0
- package/src/prr/workflows/3-review/business-review/workflow.yaml +17 -0
- package/src/prr/workflows/3-review/general-review/checklist.md +5 -1
- package/src/prr/workflows/3-review/general-review/instructions.xml +39 -8
- package/src/prr/workflows/3-review/general-review/workflow.yaml +17 -18
- package/src/prr/workflows/3-review/performance-review/checklist.md +3 -1
- package/src/prr/workflows/3-review/performance-review/instructions.xml +10 -3
- package/src/prr/workflows/3-review/performance-review/workflow.yaml +17 -18
- package/src/prr/workflows/3-review/security-review/checklist.md +2 -1
- package/src/prr/workflows/3-review/security-review/instructions.xml +8 -3
- package/src/prr/workflows/3-review/security-review/workflow.yaml +18 -19
- package/src/prr/workflows/4-improve/improve-code/workflow.yaml +17 -18
- package/src/prr/workflows/6-report/generate-report/steps/step-01-collect.md +9 -2
- package/src/prr/workflows/6-report/generate-report/steps/step-02-organize.md +28 -7
- package/src/prr/workflows/6-report/generate-report/steps/step-03-write.md +6 -4
- package/src/prr/workflows/6-report/generate-report/templates/review-report.template.md +124 -78
- package/src/prr/workflows/6-report/post-comments/steps/step-01-format.md +104 -13
- package/src/prr/workflows/6-report/post-comments/steps/step-02-post.md +92 -21
- package/src/prr/workflows/6-report/post-comments/workflow.md +6 -0
- package/src/prr/workflows/quick/workflow.md +138 -32
- package/src/prr/workflows/0-setup/collect-project-context/steps/step-01-scan-configs.md +0 -106
- package/src/prr/workflows/0-setup/collect-project-context/steps/step-02-extract-rules.md +0 -131
- package/src/prr/workflows/0-setup/collect-project-context/steps/step-03-ask-context.md +0 -194
- package/src/prr/workflows/0-setup/collect-project-context/steps/step-04-save-context.md +0 -161
- package/src/prr/workflows/0-setup/collect-project-context/workflow.md +0 -58
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Bootstrap — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `bootstrap`, `from 'bootstrap'`, `class="btn`, `class="container`, `data-bs-`, `navbar-`, `modal`, `bootstrap.bundle`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
- **[HIGH]** Bootstrap tooltip or popover initialized with `html: true` and content sourced from user input → XSS via `data-bs-content`, `data-bs-title`, or the `content` option. Set `html: false` (default) and encode all user content before use; sanitize with DOMPurify if HTML is required.
|
|
10
|
+
- **[HIGH]** Bootstrap JavaScript loaded from a public CDN without a Subresource Integrity (SRI) hash → compromised CDN serves malicious script. Add `integrity` and `crossorigin="anonymous"` attributes to all CDN `<script>` and `<link>` tags.
|
|
11
|
+
- **[MEDIUM]** Modal body dynamically populated via `innerHTML` with unencoded user data → XSS inside the modal. Use `textContent` for user data or sanitize with DOMPurify before inserting into modal content.
|
|
12
|
+
- **[MEDIUM]** Bootstrap's sanitizer (`allowList`) not configured when using `html: true` → default allowlist may permit dangerous attributes. Review and restrict the `allowList` to only the HTML tags and attributes your application requires.
|
|
13
|
+
- **[LOW]** Form `action` or `href` attributes dynamically constructed from user input in Bootstrap form components → open redirect or injection. Validate and encode all dynamic URL values used in Bootstrap component attributes.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Performance
|
|
18
|
+
- **[HIGH]** Entire Bootstrap bundle imported `import 'bootstrap'` instead of only the required components → full ~150KB JS bundle loaded even when only a few components are used. Import specific components: `import { Modal } from 'bootstrap'` or use tree-shaking-friendly imports.
|
|
19
|
+
- **[HIGH]** Bootstrap CSS not purged of unused styles in production → Bootstrap's full CSS is ~230KB; most projects use under 20% of it. Configure PurgeCSS or the Sass `@use` per-component approach to include only used styles.
|
|
20
|
+
- **[MEDIUM]** Bootstrap utility classes (`d-none`, `d-block`) toggled via JavaScript for show/hide animations → no CSS transitions, jarring UX. Use Bootstrap's built-in transition utilities or `collapse`/`fade` classes with the JavaScript component API.
|
|
21
|
+
- **[MEDIUM]** Bootstrap CSS custom properties not leveraged for theming → overriding compiled Bootstrap CSS with higher-specificity rules. Use Bootstrap's CSS custom property overrides (`--bs-primary`, `--bs-font-size-base`) in `:root` instead of overriding classes.
|
|
22
|
+
- **[MEDIUM]** `bootstrap.bundle.min.js` (includes Popper) loaded when Popper is also imported separately → Popper loaded twice, increasing bundle size and causing potential conflicts. Use `bootstrap.min.js` (without Popper) if Popper is managed separately.
|
|
23
|
+
- **[LOW]** Bootstrap grid mixed with custom CSS Grid or Flexbox on the same container → layout conflicts from competing systems. Pick one layout system per container; use Bootstrap grid OR custom CSS, not both on the same element.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
- **[HIGH]** Bootstrap JavaScript component initialized multiple times on the same DOM element → duplicate event listeners causing double modal opens, double tooltips, or broken dismiss behavior. Check for an existing instance with `bootstrap.Modal.getInstance(el)` before calling `new bootstrap.Modal(el)`.
|
|
29
|
+
- **[MEDIUM]** Bootstrap default classes overridden with higher-specificity custom selectors (`.btn.btn-primary { ... }`) → specificity arms race making future Bootstrap upgrades painful. Use Bootstrap's SCSS variable/map customization system at build time rather than overriding compiled CSS.
|
|
30
|
+
- **[MEDIUM]** Bootstrap SCSS not customized via its provided variables and maps → colors, spacing, and breakpoints duplicated in custom CSS. Import Bootstrap SCSS after overriding `_variables.scss` values to customize via the source.
|
|
31
|
+
- **[MEDIUM]** JavaScript component lifecycle not managed (not destroyed before re-initialization) → stale component instances accumulate in single-page applications during navigation. Destroy components with `instance.dispose()` before removing their DOM elements.
|
|
32
|
+
- **[LOW]** Bootstrap 4 data attributes (`data-toggle`, `data-target`) used in a Bootstrap 5 project → components silently fail to initialize in Bootstrap 5 which uses `data-bs-toggle`, `data-bs-target`. Audit all `data-` attributes and update to the `data-bs-*` namespace.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Code Quality
|
|
37
|
+
- **[HIGH]** Interactive Bootstrap components (modals, dropdowns, accordions) missing required ARIA attributes (`aria-expanded`, `aria-controls`, `role`) → screen readers cannot navigate or announce component state. Follow Bootstrap's documented accessibility markup for each component type.
|
|
38
|
+
- **[MEDIUM]** Non-`<button>` elements (e.g., `<div>`, `<a>`) used as interactive Bootstrap triggers without `role="button"` and `tabindex="0"` → keyboard navigation broken, not focusable. Use `<button>` for all click-triggered Bootstrap interactions, or add required ARIA and keyboard event handlers.
|
|
39
|
+
- **[MEDIUM]** Bootstrap CSS loaded from both CDN (in HTML `<head>`) and npm (via bundler) simultaneously → styles applied twice, specificity becomes unpredictable. Choose one loading strategy; prefer npm + bundler for projects that build a bundle.
|
|
40
|
+
- **[MEDIUM]** Bootstrap JS components controlled via jQuery's `$().modal()` API in a Bootstrap 5 project → Bootstrap 5 dropped jQuery; the jQuery API does not exist. Use the vanilla JS API: `new bootstrap.Modal(el).show()`.
|
|
41
|
+
- **[LOW]** Bootstrap icons or images referenced by hardcoded CDN paths in templates → broken assets after CDN changes or in offline environments. Host assets locally or configure asset paths via the build system.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Common Bugs & Pitfalls
|
|
46
|
+
- **[HIGH]** Modal appearing behind a fixed or sticky navbar due to `z-index` conflict → modal backdrop covers the navbar but the modal itself renders below it. Set the modal's `z-index` above the navbar, or move the modal to a direct child of `<body>` to escape stacking context issues.
|
|
47
|
+
- **[HIGH]** `data-bs-dismiss="modal"` placed on a non-interactive element that does not receive focus or click events correctly → close button appears but does not function. Ensure `data-bs-dismiss` is placed on a `<button>` element inside the modal.
|
|
48
|
+
- **[MEDIUM]** Bootstrap's `position: relative` on `.container` or `.row` breaking `position: fixed` children → fixed elements position relative to the container instead of the viewport. Remove `position: relative` from ancestor containers or restructure the DOM so fixed elements are direct children of `<body>`.
|
|
49
|
+
- **[MEDIUM]** Form validation class `was-validated` added to the `<form>` element before the user attempts submission → browser validation errors shown immediately on page load. Only add `was-validated` after a submit attempt; listen for the `submit` event before toggling the class.
|
|
50
|
+
- **[MEDIUM]** Bootstrap collapse component target has an `id` that does not match the `data-bs-target` value → accordion or collapse silently fails to open/close. Verify that `data-bs-target="#myId"` exactly matches `id="myId"` on the collapsible element.
|
|
51
|
+
- **[LOW]** Tooltip not initialized via `new bootstrap.Tooltip(element)` → elements with `data-bs-toggle="tooltip"` do not activate automatically; Bootstrap 5 requires explicit JS initialization. Initialize all tooltips with `document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => new bootstrap.Tooltip(el))`.
|
|
52
|
+
- **[LOW]** Bootstrap responsive breakpoint classes (`col-md-6`) used without understanding the mobile-first cascade → desktop layout applied at all sizes because `col-` (xs) not set. Always define the smallest breakpoint first and add larger breakpoint classes to override upward.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Bun — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: bun, Bun.serve(, Bun.file(, bunfig.toml, bun.lockb, from 'bun'
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
- **[HIGH]** Bun.serve used without TLS in production → HTTP traffic transmitted in plaintext. Configure TLS with tls: { cert, key } in Bun.serve options or terminate TLS at a reverse proxy.
|
|
10
|
+
- **[CRITICAL]** Bun.spawn with user-controlled arguments → attacker injects shell metacharacters or additional arguments to run arbitrary commands. Use a fixed command array and never interpolate user input into spawn arguments.
|
|
11
|
+
- **[HIGH]** Bun.file(userPath) without path validation → path traversal allows reading arbitrary files on the server. Resolve the full path and verify it falls within the intended base directory before serving.
|
|
12
|
+
- **[CRITICAL]** eval() or new Function() with user-provided input → arbitrary code execution on the server. Never evaluate user input; restructure logic to avoid dynamic code evaluation.
|
|
13
|
+
- **[HIGH]** Missing CORS configuration on the Bun HTTP server → cross-origin requests accepted or rejected without policy. Add explicit CORS response headers based on allowed origins in the fetch handler.
|
|
14
|
+
- **[HIGH]** Passwords stored or compared without hashing → plaintext passwords exposed on DB breach. Use Bun.password.hash() and Bun.password.verify() for all password storage and comparison.
|
|
15
|
+
- **[MEDIUM]** Secrets read from process.env without validation at startup → missing secrets cause runtime errors deep in request handling. Validate all required environment variables at server startup and fail fast with a clear message.
|
|
16
|
+
- **[MEDIUM]** WebSocket handlers not validating the origin header → cross-origin WebSocket connections accepted from attacker-controlled pages. Validate the Origin header in the upgrade handler.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Performance
|
|
21
|
+
- **[MEDIUM]** Not using Bun.file() streaming for file responses → entire file loaded into memory before sending. Use Bun.file(path) directly as a Response body to enable zero-copy streaming.
|
|
22
|
+
- **[HIGH]** Blocking or CPU-heavy synchronous operations in fetch handlers → Bun runs on a single thread per worker; blocking stalls all concurrent requests. Offload CPU-bound work to Bun Worker threads.
|
|
23
|
+
- **[MEDIUM]** Not using Bun.build for production bundling → development-mode imports resolved at runtime, increasing startup latency and file read overhead. Run Bun.build as part of the production build step.
|
|
24
|
+
- **[MEDIUM]** bun:sqlite not using prepared statements → SQL queries re-parsed on every execution, adding overhead. Create prepared statements with db.prepare() and reuse them across requests.
|
|
25
|
+
- **[LOW]** Not using Bun.CryptoHasher for batch hashing instead of Web Crypto API → Web Crypto adds async overhead for simple hashing tasks. Use Bun.CryptoHasher for synchronous, high-throughput hashing.
|
|
26
|
+
- **[MEDIUM]** WebSocket message handlers performing synchronous I/O → Bun WS handler blocks the event loop during I/O. Use async handlers and await all I/O operations within WebSocket message handlers.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
- **[MEDIUM]** Mixing Bun-specific APIs with Node.js compatibility APIs inconsistently → codebase is harder to reason about and may fail when running on Node.js in tests. Choose a target runtime and use its native APIs consistently; isolate compat shims.
|
|
32
|
+
- **[LOW]** Not using Bun built-in test runner (bun:test) and relying on Jest or Vitest instead → additional dependencies add to install time and binary size. Migrate to bun:test for native, fast test execution without extra packages.
|
|
33
|
+
- **[LOW]** Using process.env instead of Bun.env for environment variable access → Bun.env is typed and faster; process.env is the compat shim. Prefer Bun.env.VARIABLE_NAME in Bun-native code.
|
|
34
|
+
- **[MEDIUM]** Not using Bun.serve route patterns instead of manual URL parsing → manual routing is error-prone and slower. Use static: {} for static file serving and routes for API endpoints in Bun.serve config.
|
|
35
|
+
- **[MEDIUM]** Not exporting a Bun.serve object from the main file for hot reload compatibility → hot reload does not work with programmatic listen patterns. Export the server config object directly for Bun hot reload to work correctly.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Code Quality
|
|
40
|
+
- **[LOW]** Not taking advantage of Bun native TypeScript support and using an extra transpilation step → unnecessary build complexity and slower iteration. Remove tsc/esbuild from the pipeline; Bun runs TypeScript natively.
|
|
41
|
+
- **[HIGH]** Bun.password.hash not used for password hashing, using a custom or weaker approach instead → passwords stored with weak or no hashing are exposed on DB breach. Always use Bun.password.hash() which uses bcrypt or argon2 under the hood.
|
|
42
|
+
- **[HIGH]** bun.lockb not committed to version control → reproducible installs are broken across environments, leading to dependency version drift. Commit bun.lockb and install with bun install --frozen-lockfile in CI.
|
|
43
|
+
- **[MEDIUM]** Not using Bun.sleep instead of setTimeout/Promise-based delays in Bun-native code → minor overhead from wrapping. Use await Bun.sleep(ms) for cleaner async delays in Bun environments.
|
|
44
|
+
- **[LOW]** TypeScript strict mode not enabled → implicit any and unsafe type operations go uncaught. Enable strict: true in tsconfig.json to catch type errors at compile time.
|
|
45
|
+
- **[MEDIUM]** Not setting Content-Type on manual Response objects → clients may misinterpret the response body. Always set the Content-Type header explicitly on responses that are not created via the Bun Response helpers.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Common Bugs & Pitfalls
|
|
50
|
+
- **[HIGH]** Node.js __dirname and __filename undefined in Bun ESM modules → code using these globals fails at runtime. Replace with import.meta.dir and import.meta.file in Bun ESM context.
|
|
51
|
+
- **[HIGH]** bun:sqlite transactions not using db.transaction() for multi-step writes → partial writes not rolled back on failure, corrupting data. Wrap all multi-statement writes in db.transaction() for atomicity.
|
|
52
|
+
- **[MEDIUM]** Hot reload not working with certain module patterns (e.g., top-level side effects, non-exported servers) → code changes require a full restart. Structure the entry point with an exported default and avoid top-level side effects.
|
|
53
|
+
- **[HIGH]** Not handling Bun.serve fetch handler errors → unhandled exceptions in the fetch handler crash the request with a generic error. Wrap the handler body in try/catch and return an appropriate error Response.
|
|
54
|
+
- **[MEDIUM]** WebSocket publish called before client subscriptions are established → messages lost because the client is not yet subscribed to the topic. Subscribe the client in the open handler before publishing any messages.
|
|
55
|
+
- **[MEDIUM]** Not configuring Bun.serve maxRequestBodySize → default body size limit may be too large or too small for the use case. Set maxRequestBodySize explicitly based on expected payload sizes.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# C++ — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `*.cpp` · `*.cc` · `*.cxx` · `*.hpp` · `*.h` with `#include <` · `namespace` · `std::` · `CMakeLists.txt` · `Makefile`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
|
|
10
|
+
- **[CRITICAL]** `strcpy`, `sprintf`, `gets`, `strcat` with user-controlled input → buffer overflow. Use `strncpy`, `snprintf`, `fgets`, `strncat` with explicit size limits, or C++ `std::string`.
|
|
11
|
+
- **[CRITICAL]** `system(userInput)` → command injection. Avoid `system()`; use `exec*()` family with sanitized argv array.
|
|
12
|
+
- **[HIGH]** Integer overflow in buffer size calculation (e.g., `malloc(count * sizeof(T))`) → heap overflow if multiplication wraps. Use checked arithmetic or `std::vector`.
|
|
13
|
+
- **[HIGH]** `printf(userInput)` — untrusted string used as format specifier → format string attack. Always use `printf("%s", userInput)`.
|
|
14
|
+
- **[MEDIUM]** Reading from uninitialized memory → undefined behavior, potential info leak. Initialize all variables at declaration.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Performance
|
|
19
|
+
|
|
20
|
+
- **[HIGH]** Large object passed by value to function → unnecessary copy. Use `const T&` or `T&&` (move semantics).
|
|
21
|
+
- **[HIGH]** `new` / `delete` in tight loop → heap fragmentation and allocator overhead. Use stack allocation, `std::vector` with `reserve()`, or a pool allocator.
|
|
22
|
+
- **[HIGH]** Virtual function calls in performance-critical inner loop → vtable dispatch per call. Consider templates (CRTP) or `final` to enable devirtualization.
|
|
23
|
+
- **[MEDIUM]** `std::map` / `std::set` where `std::unordered_map` / `std::unordered_set` suffices → O(log n) vs O(1) average lookup.
|
|
24
|
+
- **[MEDIUM]** Missing `std::move` when returning named local variable (before NRVO applies) → unnecessary copy.
|
|
25
|
+
- **[LOW]** `std::endl` in output loop → flushes buffer every iteration. Use `'\n'` unless flush is explicitly needed.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
|
|
31
|
+
- **[CRITICAL]** Raw owning pointer without RAII wrapper → manual `delete` easily missed, double-free, or leak. Use `std::unique_ptr` for exclusive ownership, `std::shared_ptr` for shared.
|
|
32
|
+
- **[HIGH]** Memory leak: `new` allocated object not `delete`d on all code paths (including exceptions) → use smart pointers or stack allocation.
|
|
33
|
+
- **[HIGH]** Use-after-free: accessing pointer after `delete` → undefined behavior. Set pointer to `nullptr` after delete (or eliminate raw `delete` entirely).
|
|
34
|
+
- **[HIGH]** Double-free: `delete` called twice on same pointer → heap corruption. Smart pointers prevent this automatically.
|
|
35
|
+
- **[MEDIUM]** Global / static mutable state → thread safety issues without synchronization. Use `std::mutex` or `thread_local`.
|
|
36
|
+
- **[LOW]** Deep inheritance hierarchy → prefer composition over inheritance for non-polymorphic designs.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Code Quality
|
|
41
|
+
|
|
42
|
+
- **[HIGH]** `using namespace std;` in a header file → pollutes namespace of every translation unit that includes it. Limit to `.cpp` files or use explicit `std::` prefix.
|
|
43
|
+
- **[MEDIUM]** Member function that doesn't modify state not marked `const` → prevents use with `const` objects, hides intent.
|
|
44
|
+
- **[MEDIUM]** Implicit conversion between signed and unsigned integers without explicit cast → subtle overflow or wrap-around bugs. Enable `-Wsign-conversion`.
|
|
45
|
+
- **[MEDIUM]** Missing `override` on virtual method override → if base signature changes, override silently becomes a new function.
|
|
46
|
+
- **[LOW]** Long function > 50 lines with complex control flow → decompose into smaller functions.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Common Bugs & Pitfalls
|
|
51
|
+
|
|
52
|
+
- **[CRITICAL]** Undefined behavior: signed integer overflow, null pointer dereference, out-of-bounds array access, data race → UB cannot be relied upon to "just work" even if it appears to.
|
|
53
|
+
- **[HIGH]** Iterator invalidation: modifying `std::vector` / `std::map` while iterating (erase, push_back) → UB. Collect indices/iterators first or use erase-remove idiom.
|
|
54
|
+
- **[HIGH]** `std::vector::operator[]` without bounds check in production code → UB on out-of-bounds. Use `.at()` during development/testing; add assertion in production.
|
|
55
|
+
- **[MEDIUM]** Object slicing: assigning derived-class object to base-class by value → vtable and derived members are lost silently.
|
|
56
|
+
- **[MEDIUM]** `#pragma once` vs include guards mixed in same codebase → inconsistency. Pick one convention.
|
|
57
|
+
- **[LOW]** Comparing floating-point values with `==` → imprecise. Use epsilon comparison: `std::abs(a - b) < epsilon`.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# C# / .NET — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `*.cs` files · `*.csproj` · `*.sln` · `using System` · `namespace` · `dotnet` CLI · `appsettings.json` · ASP.NET Core · Entity Framework
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
|
|
10
|
+
- **[CRITICAL]** SQL built with string interpolation: `$"SELECT * WHERE id = {id}"` → SQL injection. Use parameterized queries (`SqlParameter`) or EF Core.
|
|
11
|
+
- **[CRITICAL]** `Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = input })` with user input → command injection. Use argument arrays, not shell strings.
|
|
12
|
+
- **[CRITICAL]** `BinaryFormatter.Deserialize()` on untrusted data → arbitrary code execution (CVE-class). Use `System.Text.Json` or `XmlSerializer` with safe settings.
|
|
13
|
+
- **[HIGH]** Missing `[ValidateAntiForgeryToken]` on ASP.NET Core POST/PUT/DELETE → CSRF.
|
|
14
|
+
- **[HIGH]** Hardcoded connection strings / API keys in `appsettings.json` committed to VCS → use `dotnet user-secrets`, Azure Key Vault, or environment variables.
|
|
15
|
+
- **[HIGH]** `Path.Combine(baseDir, userInput)` without `Path.GetFullPath()` + prefix check → path traversal.
|
|
16
|
+
- **[HIGH]** `JsonConvert.DeserializeObject<T>(input)` with `TypeNameHandling.All` → remote code execution via `$type`.
|
|
17
|
+
- **[HIGH]** Sensitive data logged via `_logger.LogInformation()` with string interpolation → log injection.
|
|
18
|
+
- **[HIGH]** `RNGCryptoServiceProvider` deprecated → use `RandomNumberGenerator.Fill()` (static, .NET 6+).
|
|
19
|
+
- **[MEDIUM]** `Math.Random` used for security purposes → use `RandomNumberGenerator` from `System.Security.Cryptography`.
|
|
20
|
+
- **[MEDIUM]** CORS configured too permissively (`AllowAnyOrigin + AllowCredentials`) → CORS misconfiguration.
|
|
21
|
+
- **[MEDIUM]** `HttpContext.Request.Headers["X-Forwarded-For"]` trusted without proxy validation → IP spoofing.
|
|
22
|
+
- **[MEDIUM]** Passwords stored as `string` → immutable, lingers in memory. Use `SecureString` or clear char arrays.
|
|
23
|
+
- **[LOW]** Exception details returned in API response in production → configure `app.UseExceptionHandler` properly.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Performance
|
|
28
|
+
|
|
29
|
+
- **[HIGH]** `async void` method (not event handler) → exceptions unobservable, swallowed silently. Use `async Task`.
|
|
30
|
+
- **[HIGH]** `.Result` or `.Wait()` on Task in ASP.NET context → deadlock on synchronization context. Always `await`.
|
|
31
|
+
- **[HIGH]** `string +=` in loop → O(n²). Use `StringBuilder` or `string.Join`.
|
|
32
|
+
- **[HIGH]** `await` inside loop instead of batching with `Task.WhenAll()` → sequential async = unnecessary latency.
|
|
33
|
+
- **[HIGH]** Entity Framework `Include()` loading entire related collection when only count or single field needed → select projection.
|
|
34
|
+
- **[HIGH]** Synchronous EF Core calls (`.ToList()` without `Async`) in ASP.NET Core → blocking thread pool thread.
|
|
35
|
+
- **[HIGH]** Missing `AsNoTracking()` on read-only EF Core queries → change tracker overhead.
|
|
36
|
+
- **[MEDIUM]** `.ToList()` called on `IQueryable` before further LINQ operations → materializes entire result prematurely.
|
|
37
|
+
- **[MEDIUM]** Missing `ConfigureAwait(false)` in library code → captures unnecessary sync context.
|
|
38
|
+
- **[MEDIUM]** `IEnumerable<T>` iterated multiple times → if `IQueryable`, triggers multiple DB calls. Materialize once.
|
|
39
|
+
- **[MEDIUM]** Large object allocation in hot path without pooling → GC pressure. Use `ArrayPool<T>` or `MemoryPool<T>`.
|
|
40
|
+
- **[MEDIUM]** Not using `Span<T>` / `Memory<T>` for buffer operations → unnecessary heap allocations.
|
|
41
|
+
- **[MEDIUM]** LINQ `GroupBy` on large in-memory collections → O(n) memory → push to DB if possible.
|
|
42
|
+
- **[LOW]** Not using `HttpClient` with `IHttpClientFactory` → socket exhaustion with `new HttpClient()`.
|
|
43
|
+
- **[LOW]** `Task.Run` wrapping CPU-bound work then awaiting → thread pool overhead for short tasks.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Architecture
|
|
48
|
+
|
|
49
|
+
- **[HIGH]** `static` mutable fields in ASP.NET Core services → shared across requests, race conditions without sync.
|
|
50
|
+
- **[HIGH]** `IDisposable` object created without `using` or `await using` → resource leak (DB connections, streams).
|
|
51
|
+
- **[HIGH]** Service registered with wrong DI lifetime: `Scoped` injected into `Singleton` → captive dependency.
|
|
52
|
+
- **[HIGH]** `DbContext` used as singleton → EF Core `DbContext` is not thread-safe, designed for scoped lifetime.
|
|
53
|
+
- **[HIGH]** Business logic in ASP.NET Core controllers → move to service/domain layer.
|
|
54
|
+
- **[HIGH]** Not using Repository/Unit of Work pattern with EF Core → testability and coupling issues.
|
|
55
|
+
- **[MEDIUM]** Catching `Exception` too broadly → masks unrelated bugs. Catch specific exceptions.
|
|
56
|
+
- **[MEDIUM]** `HttpClient` instantiated per request → socket exhaustion. Use `IHttpClientFactory`.
|
|
57
|
+
- **[MEDIUM]** Not using `CancellationToken` propagation in async chain → operations can't be cancelled.
|
|
58
|
+
- **[MEDIUM]** God class with >500 lines → decompose by responsibility.
|
|
59
|
+
- **[MEDIUM]** Domain model leaking persistence concerns (EF navigation properties in API contracts).
|
|
60
|
+
- **[LOW]** Not using `record` types (C# 9+) for DTOs and value objects → verbose boilerplate equality.
|
|
61
|
+
- **[LOW]** Not using `sealed` on classes not designed for inheritance → unintended extension.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Code Quality
|
|
66
|
+
|
|
67
|
+
- **[HIGH]** Nullable reference types disabled (`<Nullable>disable</Nullable>`) → NullReferenceException not caught at compile time. Enable and fix warnings.
|
|
68
|
+
- **[HIGH]** `throw ex` instead of `throw` in catch block → resets stack trace, hides origin.
|
|
69
|
+
- **[HIGH]** `int.Parse(input)` without `TryParse` → `FormatException` on invalid input crashes request.
|
|
70
|
+
- **[HIGH]** Not using `pattern matching` for type checks → verbose `is`/`as` + null check.
|
|
71
|
+
- **[MEDIUM]** `var` used where type not obvious from RHS → readability suffers.
|
|
72
|
+
- **[MEDIUM]** Missing cancellation token propagation in async call chain.
|
|
73
|
+
- **[MEDIUM]** Magic strings for configuration keys instead of typed options with `IOptions<T>`.
|
|
74
|
+
- **[MEDIUM]** `?.` null conditional chaining producing `null` result silently used without null check.
|
|
75
|
+
- **[MEDIUM]** Not using C# 10+ features (`record struct`, global using, file-scoped namespace) in modern projects.
|
|
76
|
+
- **[MEDIUM]** Event subscription not unsubscribed → memory leak via event handler reference.
|
|
77
|
+
- **[LOW]** Public method without XML doc comment on public API.
|
|
78
|
+
- **[LOW]** Not using `nameof()` for property names in validation/logging → typo-prone string literals.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Common Bugs & Pitfalls
|
|
83
|
+
|
|
84
|
+
- **[HIGH]** `DateTime.Now` for storage/cross-system → timezone-dependent. Use `DateTime.UtcNow` or `DateTimeOffset.UtcNow`.
|
|
85
|
+
- **[HIGH]** `LINQ` deferred execution not understood → query executed multiple times or after `DbContext` disposed.
|
|
86
|
+
- **[HIGH]** EF Core `SaveChangesAsync()` not called after mutations → changes not persisted silently.
|
|
87
|
+
- **[HIGH]** `lock(this)` or `lock(typeof(Foo))` → public lock objects can be acquired externally → deadlock.
|
|
88
|
+
- **[HIGH]** `Task.WhenAll()` not awaited → exceptions swallowed.
|
|
89
|
+
- **[MEDIUM]** Struct implementing `IDisposable` boxed via interface → `Dispose` called on copy.
|
|
90
|
+
- **[MEDIUM]** Enum default value (0) not explicitly named → uninitialized enum has valid meaningless value.
|
|
91
|
+
- **[MEDIUM]** `string.Compare` for equality → use `string.Equals` with `StringComparison`.
|
|
92
|
+
- **[MEDIUM]** EF Core lazy loading enabled without understanding → N+1 queries via navigation property access.
|
|
93
|
+
- **[MEDIUM]** `ConcurrentDictionary.GetOrAdd` with factory that has side effects → factory may run multiple times.
|
|
94
|
+
- **[LOW]** `StringBuilder.Append()` returning `this` for chaining not used → verbose multi-line appends.
|
|
95
|
+
- **[LOW]** `Encoding.UTF8.GetString` on bytes from wrong encoding → mojibake.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# CSS / SCSS / SASS — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `*.css`, `*.scss`, `*.sass`, `*.less`, `*.styl` files
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
|
|
10
|
+
- **[HIGH]** `url()` with user-controlled value → CSS injection loading external resources. Never interpolate user data into CSS.
|
|
11
|
+
- **[MEDIUM]** `expression()` (IE legacy) in CSS → executes JavaScript. Never use.
|
|
12
|
+
- **[MEDIUM]** Missing `Content-Security-Policy: style-src 'self'` allowing inline styles that could be injected.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Performance
|
|
17
|
+
|
|
18
|
+
- **[HIGH]** Universal selector `*` with expensive properties (`box-shadow`, `transform`) → applied to every element, layout thrash.
|
|
19
|
+
- **[HIGH]** `@import` in CSS (not SCSS) → blocking serial HTTP requests. Use `<link>` or bundler imports.
|
|
20
|
+
- **[HIGH]** Triggering layout thrash — reading layout properties (`offsetWidth`, `getBoundingClientRect`) then writing in same frame (JS + CSS combo). Use `transform` for animations.
|
|
21
|
+
- **[MEDIUM]** Overly specific selectors (`div > ul > li > a.link`) → slow browser matching, hard to override.
|
|
22
|
+
- **[MEDIUM]** `position: fixed` elements on scroll-heavy pages without `will-change: transform` → repaints entire page.
|
|
23
|
+
- **[MEDIUM]** Animating `width`/`height`/`top`/`left` → triggers layout recalculation. Use `transform: translate()` / `scale()` instead.
|
|
24
|
+
- **[LOW]** Large unused CSS from third-party libraries not purged → bundle bloat.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
- **[HIGH]** Deeply nested SCSS selectors (>4 levels) → high specificity, hard to override, fragile.
|
|
31
|
+
- **[MEDIUM]** Color/spacing values duplicated as magic numbers instead of CSS custom properties / SCSS variables.
|
|
32
|
+
- **[MEDIUM]** `!important` overuse → specificity war, maintainability nightmare.
|
|
33
|
+
- **[MEDIUM]** Class names not following a convention (BEM, utility-first) → inconsistent, hard to predict.
|
|
34
|
+
- **[LOW]** Vendor prefixes added manually instead of using Autoprefixer → out-of-date, missing prefixes.
|
|
35
|
+
- **[LOW]** SCSS `@extend` used with placeholder selectors — can cause unexpected selector bloat.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Accessibility
|
|
40
|
+
|
|
41
|
+
- **[HIGH]** `outline: none` / `outline: 0` on focusable elements without alternative focus indicator → keyboard navigation broken (WCAG 2.4.7).
|
|
42
|
+
- **[HIGH]** Text contrast below WCAG AA (4.5:1 for normal text, 3:1 for large text).
|
|
43
|
+
- **[MEDIUM]** `display: none` used on content that should be accessible to screen readers → use visually-hidden pattern instead.
|
|
44
|
+
- **[MEDIUM]** `pointer-events: none` on interactive elements without disabling them in HTML → keyboard still reaches them.
|
|
45
|
+
- **[LOW]** `user-select: none` on body/large containers → breaks copy-paste for users.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Common Bugs & Pitfalls
|
|
50
|
+
|
|
51
|
+
- **[HIGH]** `z-index` wars — arbitrary large values (`z-index: 9999`) without documented stacking context.
|
|
52
|
+
- **[MEDIUM]** Margin collapsing not accounted for — `margin-top` on child collapses with parent without overflow/padding/border.
|
|
53
|
+
- **[MEDIUM]** `height: 100%` on child without parent having explicit height → renders as 0.
|
|
54
|
+
- **[MEDIUM]** Flexbox/Grid item `flex: 1` without `min-width: 0` → overflow issues with long text content.
|
|
55
|
+
- **[LOW]** `calc()` with missing spaces around operators (`calc(100%-20px)`) → invalid in some browsers.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Cypress — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `cypress`, `cy.visit(`, `cy.get(`, `cy.intercept(`, `cypress.config.*`, `describe(` in `cypress/`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
- **[HIGH]** Hardcoded test credentials in Cypress test files committed to the repository → credentials exposed in version control and CI logs. Use `Cypress.env()` with environment variables injected at CI time; store secrets in your CI secret manager.
|
|
10
|
+
- **[HIGH]** `cy.request()` calling authenticated API endpoints without proper auth token setup → tests may inadvertently call real external services or bypass auth unexpectedly. Always set the auth token via `cy.session()` or `Authorization` header in `cy.request()` explicitly.
|
|
11
|
+
- **[MEDIUM]** Secrets placed in `cypress.env.json` and committed to the repository → sensitive values in version control. Add `cypress.env.json` to `.gitignore` and inject values via CI environment variables only.
|
|
12
|
+
- **[MEDIUM]** Test data including PII from seeded users not cleaned up after test runs → leftover PII accumulates in the staging database. Add an `afterEach` or `after` hook that deletes or resets test data via a `cy.task()` DB call.
|
|
13
|
+
- **[LOW]** `chromeWebSecurity: false` set in `cypress.config` to allow cross-origin requests → disables browser same-origin protections, letting cross-origin attacks go undetected. Remove `chromeWebSecurity: false` and use `cy.origin()` for legitimate cross-origin testing.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Performance
|
|
18
|
+
- **[HIGH]** `cy.wait(5000)` hard-coded time waits instead of waiting on network requests → tests are slow and flaky; the wait may not be enough on slow CI. Replace with `cy.intercept()` aliases and `cy.wait('@aliasName')` to wait for the actual request.
|
|
19
|
+
- **[HIGH]** `cy.session()` not used for authentication state → login UI flow executed on every test, adding seconds per test. Cache login state with `cy.session('user', loginFn)` so auth is established once per session.
|
|
20
|
+
- **[HIGH]** `cy.visit()` called for every test when tests could share a single page load → full navigation and app initialization overhead per test. Visit once in `before()` and reset state between tests without full reloads where possible.
|
|
21
|
+
- **[MEDIUM]** `cy.get('.selector')` traversing the entire DOM when a scoped query is possible → selector resolution slows on large DOMs. Chain `.within()` to scope: `cy.get('#parent').within(() => { cy.get('button') })`.
|
|
22
|
+
- **[MEDIUM]** `cy.task()` not used for database seeding → seeding done via UI or `cy.request()`, which depends on the app being fully functional. Use `cy.task('db:seed', data)` to insert directly into the DB via Node.js.
|
|
23
|
+
- **[LOW]** Screenshots and videos enabled in CI without artifact retention policy → disk fills up and artifact uploads slow pipelines. Set `video: false` in CI and enable `screenshotOnRunFailure: true` only.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
- **[HIGH]** Selectors based on CSS classes or visible text → tests break whenever the UI is restyled or copy changes. Use `data-cy` attributes: `cy.get('[data-cy="submit-button"]')`.
|
|
29
|
+
- **[HIGH]** Repeated auth, navigation, or interaction logic not extracted to custom commands → duplication across tests; one UI change breaks dozens. Extract sequences to `Cypress.Commands.add('login', ...)`.
|
|
30
|
+
- **[MEDIUM]** Tests not organized by feature or page → test files become hundreds of lines, slow to scan. Organize into subdirectories: `cypress/e2e/auth/login.cy.ts`, `cypress/e2e/dashboard/overview.cy.ts`.
|
|
31
|
+
- **[MEDIUM]** Cypress commands chained after native Promises without returning the Cypress chain → commands run out of order. Always return the Cypress chain from inside `.then()` callbacks; avoid mixing native Promises with Cypress commands.
|
|
32
|
+
- **[MEDIUM]** No page object pattern for complex multi-step user flows → test code directly manipulates selectors; refactoring requires editing every test. Create helper functions or custom commands that encapsulate multi-step flows.
|
|
33
|
+
- **[LOW]** Cypress configuration not split into base config plus environment-specific overrides → CI and local configs are identical; developers must manually change settings. Use `defineConfig` with environment-specific override files.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Code Quality
|
|
38
|
+
- **[HIGH]** `cy.get(sel).then(el => cy.get(sel2))` anti-pattern instead of `.within()` → creates unnecessary nested chains that are hard to read. Use `cy.get('#container').within(() => { cy.get('button').click() })`.
|
|
39
|
+
- **[HIGH]** Assertions missing from tests → test passes even when the feature is broken because no assertion checks the expected state. Every test must end with at least one `.should()` assertion verifying the intended UI state.
|
|
40
|
+
- **[MEDIUM]** `.should('be.visible')` not asserted before interacting with an element → Cypress may try to click a hidden or detached element, causing flaky failures. Use `cy.get(sel).should('be.visible').click()`.
|
|
41
|
+
- **[MEDIUM]** Test data hardcoded inline instead of using fixtures → same data duplicated across tests; changing it requires editing multiple files. Extract to `cypress/fixtures/` JSON files and load with `cy.fixture()`.
|
|
42
|
+
- **[MEDIUM]** No TypeScript types for custom commands in `cypress/support/index.d.ts` → custom commands typed as `any`; autocomplete absent. Extend the `Chainable` interface with type declarations for every custom command.
|
|
43
|
+
- **[LOW]** No Cypress lint rules (eslint-plugin-cypress) configured → Cypress-specific anti-patterns not caught automatically. Add `eslint-plugin-cypress` with the recommended rule set to the ESLint config.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Common Bugs & Pitfalls
|
|
48
|
+
- **[HIGH]** `cy.get()` matching multiple elements when only one is expected → Cypress acts on the first match silently; tests pass against the wrong element. Assert `.should('have.length', 1)` or use a more specific selector.
|
|
49
|
+
- **[HIGH]** Async code (Promises, async/await) in `before()` or `beforeEach()` without returning the Cypress chain → setup completes after tests begin; state is missing when tests run. Return the Cypress chain from setup hooks or use `cy.wrap(promise)`.
|
|
50
|
+
- **[MEDIUM]** `cy.intercept()` alias defined after `cy.visit()` → network request fires before intercept is registered; alias never resolves. Always define `cy.intercept()` aliases before `cy.visit()` or the action that triggers the request.
|
|
51
|
+
- **[MEDIUM]** `cy.contains()` matching hidden text nodes (e.g., inside a tooltip or offscreen element) → test passes but the visible text the user sees is different. Add `.should('be.visible')` after `cy.contains()`.
|
|
52
|
+
- **[MEDIUM]** "detached from DOM" error when an element re-renders between `cy.get()` and the subsequent action → element reference becomes stale after React or Vue re-render. Re-query the element inside `.then()` after re-render-triggering actions.
|
|
53
|
+
- **[LOW]** `cy.clock()` and `cy.tick()` not restored after tests that manipulate timers → fake clock bleeds into subsequent tests causing unexpected timing behavior. Call `cy.clock().then(c => c.restore())` in `afterEach`.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# D3.js — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `from 'd3'`, `import * as d3`, `d3.select`, `d3.scaleLinear`, `d3.axisBottom`, `.enter().append`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
- **[CRITICAL]** `.html(userContent)` called on a D3 selection with unencoded user data → XSS; D3 sets `innerHTML` directly. Use `.text(userContent)` for text content, or sanitize HTML with DOMPurify before passing to `.html()`.
|
|
10
|
+
- **[HIGH]** `d3.json(userUrl)` or `d3.csv(userUrl)` called with a URL derived from user input without validation → SSRF or loading of malicious data. Validate and allowlist URLs before passing to D3 fetch helpers.
|
|
11
|
+
- **[HIGH]** Dynamic SVG `<foreignObject>` elements populated with user-controlled HTML → XSS vector that bypasses SVG's normal escaping. Sanitize all HTML content placed inside `<foreignObject>` elements.
|
|
12
|
+
- **[MEDIUM]** Axis tick labels or tooltip content bound directly to raw user data values → unencoded strings rendered as SVG `text` content. D3 `.text()` is safe, but `.html()` or `innerHTML` on tooltip containers is not; sanitize before inserting.
|
|
13
|
+
- **[LOW]** D3 charts embedding data from external sources in SVG `<title>` or `<desc>` elements without encoding → minor content injection risk. Encode all external data used in SVG metadata.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Performance
|
|
18
|
+
- **[HIGH]** Not using `selection.join()` (D3 v5+) for enter/update/exit pattern → manual three-phase code is verbose, error-prone, and slower to execute. Replace `.selectAll().data().enter().append()` chains with `.join()`.
|
|
19
|
+
- **[HIGH]** Rebuilding the entire chart (re-running enter/append on all elements) on every data update instead of updating existing elements → O(n) DOM operations on each change. Use the update selection to modify existing elements; only enter new ones and exit removed ones.
|
|
20
|
+
- **[HIGH]** No transition throttling or debouncing on resize-driven re-renders → chart redraws on every pixel of window resize. Debounce resize handlers with at least 100ms delay.
|
|
21
|
+
- **[MEDIUM]** Rendering thousands of SVG `<circle>` or `<path>` elements for large datasets → SVG DOM overhead causes frame drops. Switch to `<canvas>` rendering (D3 + Canvas API) or use `d3-tile` with WebGL for datasets above ~5,000 points.
|
|
22
|
+
- **[MEDIUM]** D3 scale functions (`d3.scaleLinear`, `d3.scaleBand`) recreated on every render without memoization in React → recalculation overhead and new references causing child re-renders. Memoize scales with `useMemo` keyed on data and dimensions.
|
|
23
|
+
- **[LOW]** `d3.csv` or `d3.json` called inside a render or effect without caching result → network request repeated on every render cycle. Load data once, store in state or ref, pass as prop.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
- **[HIGH]** D3 DOM manipulation (`.append()`, `.attr()`, `.style()`) running alongside React rendering on the same elements → virtual DOM and actual DOM desync causing lost updates and React warnings. Let React own the DOM; use D3 only for math (scales, axes, path generators) and render SVG elements via JSX.
|
|
29
|
+
- **[MEDIUM]** Chart dimensions hardcoded as magic numbers instead of measured from the container → chart overflows or underutilizes space on different screen sizes. Use `ResizeObserver` on the container element and pass measured `width`/`height` to the chart.
|
|
30
|
+
- **[MEDIUM]** Data transformation (filtering, aggregation, normalization) mixed with rendering logic in the same function → hard to test and reuse. Separate data pipeline (pure functions) from rendering (D3/SVG operations).
|
|
31
|
+
- **[MEDIUM]** Axes, legends, and tooltips tightly coupled to chart internals → cannot reuse or test independently. Extract as separate components or factory functions receiving scales as arguments.
|
|
32
|
+
- **[LOW]** Using deprecated D3 v4 or v5 API patterns (`.on('zoom')` without `d3.zoom()`, old nest API) in a v7 codebase → subtle behavioral differences. Audit imports and replace deprecated patterns with v7 equivalents.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Code Quality
|
|
37
|
+
- **[HIGH]** `d3.select<ElementType, Datum>()` called without TypeScript generics → selection typed as `Selection<BaseType, unknown, ...>`, losing all type safety on datum and element properties. Always provide element and datum type parameters.
|
|
38
|
+
- **[MEDIUM]** Chart margins defined as magic numbers inline → hardcoded values repeated across multiple chart files. Extract to a named config object `const margin = { top: 20, right: 30, bottom: 40, left: 50 }`.
|
|
39
|
+
- **[MEDIUM]** Transitions across charts using inconsistent durations and easing → jarring UX. Define shared transition presets and apply via `d3.transition('name')` named transitions.
|
|
40
|
+
- **[MEDIUM]** Tooltip element created via `d3.select('body').append('div')` without cleanup → orphaned tooltip `<div>` elements accumulate in the DOM. Remove tooltip in component cleanup/teardown.
|
|
41
|
+
- **[LOW]** Not using D3's built-in color schemes (`d3.schemeTableau10`, `d3.interpolateViridis`) → custom color arrays duplicated and inconsistent across charts. Use D3 ordinal and sequential color scales with built-in schemes.
|
|
42
|
+
- **[LOW]** SVG not given explicit `viewBox` and `preserveAspectRatio` attributes → SVG does not scale correctly in flexible containers. Always set `viewBox="0 0 ${width} ${height}"` on the root SVG element.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Common Bugs & Pitfalls
|
|
47
|
+
- **[HIGH]** Data join key function omitted from `.data(dataset, d => d.id)` → D3 matches elements by index, causing wrong enter/exit assignment when data order changes. Always provide a key function that uniquely identifies each datum.
|
|
48
|
+
- **[HIGH]** `d3.scaleLinear().domain([d3.min(data), d3.max(data)])` when `data` contains non-numeric or `undefined` values → domain becomes `[NaN, NaN]`, all positions render at 0. Validate and filter data before computing domain; use `d3.extent` for safety.
|
|
49
|
+
- **[MEDIUM]** SVG y-axis inverted (y increases downward) not accounted for in scale range → chart renders upside down. Set scale range as `[height, 0]` for y-axis scales to flip the coordinate system.
|
|
50
|
+
- **[MEDIUM]** Tooltip not hidden on `mouseleave` from chart element → tooltip stays visible indefinitely after cursor exits. Always pair `mouseover`/`mouseenter` handlers with `mouseleave` handlers that hide the tooltip.
|
|
51
|
+
- **[MEDIUM]** `d3.zoom` transform applied to the wrong parent element → pan/zoom causes jumpy or offset behavior. Apply the transform to the inner `<g>` element, not the `<svg>`, and account for margin offset.
|
|
52
|
+
- **[MEDIUM]** `d3.brushX` selection not cleared when data updates → stale brush extent filters new data unexpectedly. Reset brush programmatically with `brush.move(brushGroup, null)` on data change.
|
|
53
|
+
- **[LOW]** `path.attr('d', lineGenerator)` called before data is bound to the selection → generator receives `undefined`, rendering an empty or broken path. Ensure data is joined before calling path generators.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Deno — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `deno.json` / `deno.jsonc` · `deno.lock` · `Deno.` namespace usage · `import_map.json` · `jsr:` / `npm:` / `https://` import specifiers · `deno run` scripts
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
|
|
10
|
+
- **[CRITICAL]** Running with `--allow-all` (or `-A`) flag → defeats Deno's permission model entirely. Grant only the minimum required permissions (`--allow-net=api.example.com`, `--allow-read=./data`).
|
|
11
|
+
- **[HIGH]** `--allow-run` without specifying allowed commands → grants permission to execute any process. Restrict with `--allow-run=git,node` allowlist.
|
|
12
|
+
- **[HIGH]** Dynamic `import()` from a user-controlled URL or string → arbitrary code execution. Never construct import URLs from external input.
|
|
13
|
+
- **[MEDIUM]** `--allow-net` without domain restriction → can connect to any host. Restrict to required domains.
|
|
14
|
+
- **[MEDIUM]** `--allow-env` without variable allowlist → exposes all environment variables including secrets to the script. Use `--allow-env=SPECIFIC_VAR`.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Performance
|
|
19
|
+
|
|
20
|
+
- **[HIGH]** `Deno.readFileSync` / `Deno.writeFileSync` on large files in an async context → blocks the event loop. Use async `await Deno.readFile()` / `Deno.writeFile()`.
|
|
21
|
+
- **[MEDIUM]** `for await ... of` on `Deno.readDir` without early exit → iterates entire directory. Break early when target is found.
|
|
22
|
+
- **[LOW]** Not using Deno's native `Deno.serve()` (Deno 1.35+) → older `serve()` from `std/http` has more overhead. Prefer the native API for new code.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
- **[HIGH]** Node.js `require()` used without `npm:` specifier → `require` is not available in Deno by default. Use `import` with `npm:package-name` or `jsr:@scope/package`.
|
|
29
|
+
- **[HIGH]** Dependencies imported from raw `https://` URLs without version pinning → non-reproducible builds; upstream URL changes silently break code. Use `jsr:` or `npm:` specifiers with versions.
|
|
30
|
+
- **[MEDIUM]** `deno.lock` file not committed to version control → dependency versions not reproducible across environments. Commit the lockfile.
|
|
31
|
+
- **[MEDIUM]** Permissions requested at CLI level too broadly for a library → libraries should not prescribe permissions; they should document what permissions callers must grant.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Code Quality
|
|
36
|
+
|
|
37
|
+
- **[HIGH]** `// @ts-nocheck` or `any` type used extensively → Deno enforces strict TypeScript by default; suppressing type checking defeats the safety guarantee.
|
|
38
|
+
- **[MEDIUM]** `Deno.env.get("VAR")` result used without null check → returns `undefined` for missing variables. Always validate or use a default: `Deno.env.get("PORT") ?? "8000"`.
|
|
39
|
+
- **[LOW]** `import * as foo from "module"` when only one or two exports are needed → increases bundle size in compiled output. Use named imports.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Common Bugs & Pitfalls
|
|
44
|
+
|
|
45
|
+
- **[HIGH]** Network request attempted without `--allow-net` → `Deno.errors.PermissionDenied` thrown at runtime, not at startup. Test with the exact set of permissions you intend to deploy with.
|
|
46
|
+
- **[HIGH]** Top-level `await` in a module imported by many others → delays the entire import chain. Use `await` inside functions or limit top-level `await` to entry points.
|
|
47
|
+
- **[MEDIUM]** `import 'https://deno.land/...'` from the Deno third-party module registry → `deno.land/x` is no longer receiving new modules; prefer `jsr:` for new dependencies.
|
|
48
|
+
- **[MEDIUM]** `Deno.cwd()` used to construct file paths → returns the working directory at runtime, which may differ from the script's location. Use `import.meta.url` + `new URL('./file', import.meta.url).pathname` for script-relative paths.
|
|
49
|
+
- **[LOW]** `Deno.exit()` called in a library function → terminates the entire process; callers cannot handle the error. Throw an error instead.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Django — Stack-Specific Review Rules
|
|
2
|
+
|
|
3
|
+
> Applies to: GR · SR · PR · AR · BR
|
|
4
|
+
> Detection signals: `from django`, `models.Model`, `views.py`, `urls.py`, `settings.py`, `manage.py`, `INSTALLED_APPS`, DRF `serializers.py`, `djangorestframework`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security
|
|
9
|
+
|
|
10
|
+
- **[CRITICAL]** Raw SQL via `raw()` or `cursor.execute()` with string formatting → SQL injection. Use `%s` parameterized or ORM.
|
|
11
|
+
- **[CRITICAL]** `mark_safe()` on user-controlled content → XSS. Only use on strings you fully control.
|
|
12
|
+
- **[CRITICAL]** `DEBUG = True` in production → detailed error pages with source code exposed.
|
|
13
|
+
- **[CRITICAL]** `SECRET_KEY` hardcoded in `settings.py` → version control exposure. Use `os.environ.get()` or `django-environ`.
|
|
14
|
+
- **[HIGH]** Missing `@login_required` or DRF `permission_classes` → unauthenticated access.
|
|
15
|
+
- **[HIGH]** `@csrf_exempt` without justification on state-changing endpoints.
|
|
16
|
+
- **[HIGH]** `ALLOWED_HOSTS = ['*']` in production → HTTP Host header injection.
|
|
17
|
+
- **[HIGH]** Object-level permission not checked → `get_object_or_404` without ownership verification → IDOR.
|
|
18
|
+
- **[HIGH]** Missing `is_staff`/`is_superuser` check on admin-equivalent views.
|
|
19
|
+
- **[HIGH]** File upload without content-type validation → execute malicious file via misconfigured server.
|
|
20
|
+
- **[HIGH]** Open redirect via unvalidated `next` parameter in login views.
|
|
21
|
+
- **[MEDIUM]** Missing `HttpOnly`/`Secure`/`SameSite` flags on session cookie (`SESSION_COOKIE_*` settings).
|
|
22
|
+
- **[MEDIUM]** `MEDIA_ROOT` served by Django in production → should be served by Nginx/CDN with correct content-type.
|
|
23
|
+
- **[MEDIUM]** DRF `TokenAuthentication` over HTTP → tokens transmitted in plaintext. Enforce HTTPS.
|
|
24
|
+
- **[LOW]** Django admin accessible at default `/admin/` path in production → known attack target; change with custom URL.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Performance
|
|
29
|
+
|
|
30
|
+
- **[CRITICAL]** N+1 ORM queries — accessing related objects in loop without `select_related()` or `prefetch_related()`.
|
|
31
|
+
- **[HIGH]** `QuerySet.all()` without filtering → loads entire table.
|
|
32
|
+
- **[HIGH]** Missing database indexes on frequently filtered/ordered fields (`db_index=True` or `Meta.indexes`).
|
|
33
|
+
- **[HIGH]** `len(queryset)` instead of `queryset.count()` → loads all records into memory.
|
|
34
|
+
- **[HIGH]** Synchronous external API calls in view → blocks Django worker. Use Celery for async work.
|
|
35
|
+
- **[HIGH]** DRF serializer with `many=True` on unfiltered QuerySet → serializing entire table.
|
|
36
|
+
- **[HIGH]** Missing Celery/task queue for email sending, image processing in request-response cycle.
|
|
37
|
+
- **[MEDIUM]** Missing pagination on list views (ListView or DRF `pagination_class`).
|
|
38
|
+
- **[MEDIUM]** Missing `only()` / `defer()` on queries that don't need all fields → SELECT *.
|
|
39
|
+
- **[MEDIUM]** `values()` / `values_list()` not used for read-only aggregation → full ORM overhead.
|
|
40
|
+
- **[MEDIUM]** QuerySet not cached via `django.core.cache` for expensive repeated reads.
|
|
41
|
+
- **[MEDIUM]** Database queries in template rendering (lazy ORM evaluation).
|
|
42
|
+
- **[LOW]** `annotate()` not used for counting related objects → N+1 Python-side counting.
|
|
43
|
+
- **[LOW]** Not using `bulk_create()` / `bulk_update()` for batch DB operations.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Architecture
|
|
48
|
+
|
|
49
|
+
- **[HIGH]** Business logic in views or templates → move to model methods, managers, or service layer.
|
|
50
|
+
- **[HIGH]** Fat models >500 lines → split into service classes or managers.
|
|
51
|
+
- **[HIGH]** Django signals used for critical business logic → hard to trace, test. Prefer explicit service calls.
|
|
52
|
+
- **[HIGH]** Not using `AbstractBaseUser` for custom auth → `AUTH_USER_MODEL` migration headaches later.
|
|
53
|
+
- **[HIGH]** `settings.py` not split by environment (base/dev/prod) → debug settings leaked to production.
|
|
54
|
+
- **[MEDIUM]** Missing `related_name` on FK/M2M → reverse accessor is `<model>_set`, confusing.
|
|
55
|
+
- **[MEDIUM]** Direct `settings` import in reusable apps → use `AppConfig`.
|
|
56
|
+
- **[MEDIUM]** Missing migration for model change → `makemigrations` not run, production schema drift.
|
|
57
|
+
- **[MEDIUM]** DRF `ModelSerializer` used with `fields = '__all__'` → over-exposing fields.
|
|
58
|
+
- **[MEDIUM]** DRF view doing too much (validation + business logic + serialization) → extract to service.
|
|
59
|
+
- **[LOW]** Not using Django's `AbstractModel` for common fields (created_at, updated_at).
|
|
60
|
+
- **[LOW]** App-level URLs not included in project `urls.py` via `include()`.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Code Quality
|
|
65
|
+
|
|
66
|
+
- **[HIGH]** Missing `__str__` on Model → `<Model object (1)>` in admin and logs.
|
|
67
|
+
- **[HIGH]** Missing `Meta.ordering` on models used in list views → non-deterministic order.
|
|
68
|
+
- **[HIGH]** DRF serializer `validate_<field>` not raising `serializers.ValidationError` → validation silently ignored.
|
|
69
|
+
- **[MEDIUM]** `get_or_create` without checking `created` flag → unaware if object was newly created.
|
|
70
|
+
- **[MEDIUM]** `filter().get()` instead of `get()` → extra unnecessary query.
|
|
71
|
+
- **[MEDIUM]** Hardcoded URLs in templates/views instead of `{% url %}` or `reverse()`.
|
|
72
|
+
- **[MEDIUM]** Not using `get_object_or_404` in views → raw `Model.objects.get()` raises 500 on miss.
|
|
73
|
+
- **[MEDIUM]** `null=True` on `CharField`/`TextField` → two empty values (empty string + NULL). Use `blank=True` only.
|
|
74
|
+
- **[MEDIUM]** DRF not using `@action` decorator for custom actions → awkward URL patterns.
|
|
75
|
+
- **[LOW]** Missing `verbose_name`/`verbose_name_plural` on models → ugly admin.
|
|
76
|
+
- **[LOW]** Missing `app_name` in `urls.py` → namespace conflicts.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Common Bugs & Pitfalls
|
|
81
|
+
|
|
82
|
+
- **[HIGH]** QuerySet as default argument (`def fn(qs=Model.objects.all())`) → evaluated once at definition, stale data.
|
|
83
|
+
- **[HIGH]** Transaction not used around multiple related DB writes → partial failure leaves inconsistent state.
|
|
84
|
+
- **[HIGH]** `update()` on QuerySet bypasses `save()` and signals → `pre_save`/`post_save` not triggered.
|
|
85
|
+
- **[HIGH]** `delete()` on QuerySet bypasses model `delete()` and `post_delete` signals.
|
|
86
|
+
- **[HIGH]** `request.user` accessed in model or service layer → breaking separation of concerns and testability.
|
|
87
|
+
- **[MEDIUM]** Timezone-naive `datetime.now()` instead of `timezone.now()` → bugs in non-UTC deployments.
|
|
88
|
+
- **[MEDIUM]** `get_or_create` in concurrent requests → race condition, unique constraint violations.
|
|
89
|
+
- **[MEDIUM]** Signal `sender` not specified → signal fires for all models of that event.
|
|
90
|
+
- **[MEDIUM]** Migration squashing not done → extremely slow migration history.
|
|
91
|
+
- **[LOW]** `on_delete=models.CASCADE` default assumed without considering orphan behavior.
|
|
92
|
+
- **[LOW]** `choices` on CharField not enforced at DB level → only validated in forms/serializers.
|