diff --git a/.ai-reviewignore b/.ai-reviewignore new file mode 100644 index 0000000..5ea9ba9 --- /dev/null +++ b/.ai-reviewignore @@ -0,0 +1,18 @@ +# Local/generated artifacts +node_modules/** +apps/web/node_modules/** +tmp/** + +# Build/test output +dist/** +build/** +coverage/** +apps/web/dist/** +apps/web/.vite/** + +# Runtime data and logs +*.db +*.sqlite +*.sqlite3 +*.log +deploy/data/** diff --git a/.github/ai-review.md b/.github/ai-review.md new file mode 100644 index 0000000..0c78db9 --- /dev/null +++ b/.github/ai-review.md @@ -0,0 +1,18 @@ +# LanQin Email AI Review Rules + +Review this repository as a security-sensitive email application. Focus on high-confidence issues that can affect production behavior. + +## Priorities + +- Authentication, authorization, ownership checks, session handling, and 2FA flows. +- Email sending/receiving behavior, including spoofing, header injection, unsafe templates, recipient disclosure, duplicate sends, retries, and idempotency. +- Input handling risks: SQL/NoSQL injection, command injection, path traversal, SSRF, XSS, CSRF, unsafe deserialization, and unsafe attachment uploads. +- Secret and privacy exposure: tokens, passwords, SMTP credentials, verification codes, session IDs, cookies, PII, and logs/API responses that leak sensitive data. +- Deployment changes: Docker, GitHub Actions, exposed ports, overly broad permissions, insecure defaults, missing health checks, and rollback-sensitive config. + +## Comment style + +- Prefer actionable, high-confidence findings over speculative comments. +- Include the risky file path/line, trigger condition, impact, and minimal safe fix. +- Do not comment on formatting-only issues unless they hide a real bug. +- Treat tests passing as useful signal, not as approval by itself. diff --git a/.github/workflows/ai-pr-review.yml b/.github/workflows/ai-pr-review.yml new file mode 100644 index 0000000..c2149c5 --- /dev/null +++ b/.github/workflows/ai-pr-review.yml @@ -0,0 +1,61 @@ +name: AI PR Review + +on: + pull_request: + branches: + - main + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +concurrency: + group: ai-pr-review-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + ai-review: + name: AI PR Review + runs-on: ubuntu-latest + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Skip when API key is not configured + if: ${{ env.OPENAI_API_KEY == '' }} + run: echo "::notice::OPENAI_API_KEY secret is not configured; skipping AI PR review." + + - name: Run AI PR reviewer + if: ${{ env.OPENAI_API_KEY != '' }} + run: npx --yes github-ai-pr-reviewer@latest --post + env: + OPENAI_API_KEY: ${{ env.OPENAI_API_KEY }} + OPENAI_MODEL: ${{ vars.OPENAI_MODEL || 'gpt-5.5' }} + OPENAI_API_MODE: ${{ vars.OPENAI_API_MODE || 'responses' }} + OPENAI_BASE_URL: ${{ vars.OPENAI_BASE_URL || 'https://api.openai.com/v1' }} + OPENAI_TIMEOUT_MS: ${{ vars.OPENAI_TIMEOUT_MS || '120000' }} + OPENAI_RETRIES: ${{ vars.OPENAI_RETRIES || '2' }} + GITHUB_TOKEN: ${{ github.token }} + GITHUB_REPOSITORY: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + REVIEW_RULES: .github/ai-review.md,AGENTS.md + REVIEW_IGNORE: .ai-reviewignore + REVIEW_SEVERITY_THRESHOLD: P3 + SUMMARY_MODE: review + REVIEW_EVENT: AUTO + REQUEST_CHANGES_ON: P1 + APPROVE_WHEN_CLEAN: 'false' + GITHUB_TIMEOUT_MS: '30000' + GITHUB_RETRIES: '2' + # 可选:发现 P1/P0 时让 CI 失败 + # FAIL_ON: P1 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 531326b..428b5c3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,13 +4,14 @@ on: push: branches: - main - - master tags: - "v*" paths-ignore: - "**/*.md" - "deploy/.env.example" pull_request: + branches: + - main paths-ignore: - "**/*.md" - "deploy/.env.example"