diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..f87655e --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,170 @@ +language: en-US +tone_instructions: >- + Be extremely concise. Only flag bugs, security issues, and logic errors. + Skip style nits, naming suggestions, and minor refactors. + Avoid em dashes in review comments. + One sentence per comment. No pleasantries. +early_access: true + +reviews: + profile: assertive + request_changes_workflow: false + base_branches: + - main + - deep-agent + - rc-.* + high_level_summary: false + poem: false + review_status: false + collapse_walkthrough: false + estimate_code_review_effort: false + related_issues: false + changed_files_summary: false + sequence_diagrams: false + assess_linked_issues: false + abort_on_close: true + slop_detection: + enabled: true + label: "ai-generated" + auto_review: + enabled: true + drafts: false + auto_incremental_review: true + auto_pause_after_reviewed_commits: 0 + ignore_usernames: + - "dependabot[bot]" + - "renovate[bot]" + - "github-actions[bot]" + path_filters: + - "!**/*.md" + - "!**/*.txt" + - "!**/package-lock.json" + - "!**/.gitignore" + - "!**/LICENSE" + - "!.env*" + - "!**/dist/**" + - "!**/playwright-report/**" + path_instructions: + - path: "src/server/**/*.ts" + instructions: >- + Focus on correctness and security: unvalidated user input, missing + auth checks, SQL/NoSQL injection, SSRF, missing rate limiting, + unhandled promise rejections, missing error responses, Redis + connection leaks, and missing request validation. Skip style and + naming feedback. + - path: "src/components/**/*.{ts,tsx}" + instructions: >- + Focus on correctness: missing key props, stale closures, incorrect + dependency arrays in hooks, XSS via dangerouslySetInnerHTML, + memory leaks from missing cleanup in useEffect, and incorrect + Redux state mutations. Skip style feedback. + - path: "src/frontend/**/*.{ts,tsx}" + instructions: >- + Focus on correctness: missing key props, stale closures, incorrect + dependency arrays in hooks, XSS via dangerouslySetInnerHTML, + memory leaks from missing cleanup in useEffect, and incorrect + Redux state mutations. Skip style feedback. + - path: "e2e/**/*.ts" + instructions: >- + Only flag flaky selectors, missing awaits on Playwright actions, + and tests that would pass when they should fail. + - path: "Containerfile" + instructions: >- + Flag security issues only: secrets in layers, running as root, + or missing OpenShift compatibility. + - path: ".github/workflows/**" + instructions: >- + Flag unpinned actions, overly broad permissions, and secret leaks. + Skip cosmetic suggestions. + - path: "deployment/**" + instructions: >- + Flag missing resource limits, privileged containers, and missing + security contexts. + - path: "config/**" + instructions: >- + Flag hardcoded secrets, insecure defaults, and missing validation. + - path: "compose.yml" + instructions: >- + Flag exposed ports, missing health checks, and hardcoded credentials. + - path: "vite.config.ts" + instructions: >- + Flag insecure proxy configs, missing HTTPS in production, and + exposed source maps. + - path: "package.json" + instructions: >- + Flag unpinned dependencies and known vulnerable version ranges. + tools: + hadolint: + enabled: true + actionlint: + enabled: true + shellcheck: + enabled: true + gitleaks: + enabled: true + ast-grep: + essential_rules: true + rule_dirs: + - ".coderabbit/rules" + + post_merge_actions: + - name: "Update changelog" + enabled: true + prompt: | + Review the PR title, description, and full diff. + Append a new entry to CHANGELOG.md at the top of the "Unreleased" section. + + Format: `- (): (#)` + - Derive type from the changes: feat, fix, refactor, docs, chore + - Derive scope from the primary directory or package touched + - Keep the description under 80 characters in plain language + + Only proceed if the PR is a notable user-facing or API change. + Skip for dependency bumps, typo fixes, and CI-only changes. + Do not modify anything else in the file. + +chat: + auto_reply: true + +issue_enrichment: + auto_enrich: + enabled: true + labeling: + auto_apply_labels: true + labeling_instructions: + - label: bug + instructions: >- + Issues reporting bugs, errors, crashes, incorrect behavior, or + unexpected results. This includes runtime errors, logic errors, + broken functionality, regressions, and any deviation from expected + or documented behavior. + - label: enhancement + instructions: >- + Feature requests, improvements to existing functionality, performance + optimizations, refactoring suggestions, UI/UX enhancements, and any + suggestions to make the project better or add new capabilities. + - label: documentation + instructions: >- + Documentation updates, additions, corrections, or clarifications + needed. This includes missing docs, outdated information, unclear + instructions, API documentation, code examples, README improvements, + and any requests for better explanations or guides. + +knowledge_base: + learnings: + scope: auto + issues: + scope: auto + pull_requests: + scope: auto + web_search: + enabled: true + linked_repositories: + - repository: "redhat-data-and-ai/template-agent" + instructions: "Backend agent service that this UI connects to" + - repository: "redhat-data-and-ai/template-mcp" + instructions: "MCP server template with tool definitions and protocol handlers" + code_guidelines: + filePatterns: + - "**/CONTRIBUTING.md" + - "**/SECURITY.md" diff --git a/.coderabbit/rules/no-any-type-annotation.yml b/.coderabbit/rules/no-any-type-annotation.yml new file mode 100644 index 0000000..cfebedd --- /dev/null +++ b/.coderabbit/rules/no-any-type-annotation.yml @@ -0,0 +1,11 @@ +id: no-any-type-annotation +language: typescript +message: "Avoid explicit 'any' type; use a specific type or 'unknown'" +severity: warning +rule: + kind: predefined_type + regex: "^any$" + not: + inside: + kind: catch_clause + stopBy: end diff --git a/.coderabbit/rules/no-console-log.yml b/.coderabbit/rules/no-console-log.yml new file mode 100644 index 0000000..a7459d4 --- /dev/null +++ b/.coderabbit/rules/no-console-log.yml @@ -0,0 +1,11 @@ +id: no-console-log +language: typescript +message: "Use a structured logger instead of console.log() for observability" +severity: warning +rule: + pattern: console.log($$$) + not: + inside: + kind: function_declaration + regex: "test|spec|describe|it" + stopBy: end diff --git a/.coderabbit/rules/no-dangerously-set-innerhtml.yml b/.coderabbit/rules/no-dangerously-set-innerhtml.yml new file mode 100644 index 0000000..8658a8e --- /dev/null +++ b/.coderabbit/rules/no-dangerously-set-innerhtml.yml @@ -0,0 +1,9 @@ +id: no-dangerously-set-innerhtml +language: typescript +message: "dangerouslySetInnerHTML is an XSS risk; use a sanitizer or avoid raw HTML" +severity: error +rule: + kind: jsx_attribute + has: + kind: property_identifier + regex: "^dangerouslySetInnerHTML$" diff --git a/.coderabbit/rules/no-direct-env-access.yml b/.coderabbit/rules/no-direct-env-access.yml new file mode 100644 index 0000000..f55dd74 --- /dev/null +++ b/.coderabbit/rules/no-direct-env-access.yml @@ -0,0 +1,8 @@ +id: no-direct-env-access +language: typescript +message: "Use a validated config module instead of direct process.env access" +severity: warning +rule: + any: + - pattern: process.env[$KEY] + - pattern: process.env.$VAR diff --git a/.coderabbit/rules/no-empty-useeffect-deps.yml b/.coderabbit/rules/no-empty-useeffect-deps.yml new file mode 100644 index 0000000..4a458bd --- /dev/null +++ b/.coderabbit/rules/no-empty-useeffect-deps.yml @@ -0,0 +1,8 @@ +id: no-empty-useeffect-deps +language: typescript +message: "useEffect without a dependency array runs on every render; add dependencies or an empty array" +severity: warning +rule: + pattern: useEffect($CALLBACK) + not: + pattern: useEffect($CALLBACK, $DEPS) diff --git a/.coderabbit/rules/no-unhandled-promise.yml b/.coderabbit/rules/no-unhandled-promise.yml new file mode 100644 index 0000000..04e6790 --- /dev/null +++ b/.coderabbit/rules/no-unhandled-promise.yml @@ -0,0 +1,18 @@ +id: no-unhandled-promise +language: typescript +message: "Floating promise without await or .catch() will silently swallow errors" +severity: error +rule: + kind: expression_statement + has: + kind: call_expression + has: + kind: member_expression + not: + has: + kind: property_identifier + regex: "^(then|catch|finally)$" + inside: + kind: function_declaration + regex: "^async " + stopBy: end