Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Claude Code Review

on:
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"

jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}

Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage

Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.

Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.

# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

8 changes: 8 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"mcpServers": {
"supabase": {
"type": "http",
"url": "https://mcp.supabase.com/mcp?project_ref=urudpbfiqeqwezcbhjdy&features=docs%2Caccount%2Cdatabase%2Cdebugging%2Cdevelopment%2Cfunctions%2Cbranching%2Cstorage"
}
}
}
100 changes: 100 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

RedFlag is a monorepo that monitors Sui blockchain smart-contract deployments, runs AI-powered risk analysis via OpenRouter, and displays results in a React dashboard. It identifies potential rug pulls and risky contract patterns.

## Commands

```bash
# Development
yarn install # Install all dependencies (both workspaces)
yarn dev # Run frontend (3000) + backend (3001) concurrently
yarn dev:frontend # Frontend only
yarn dev:backend # Backend only (uses tsx watch for hot reload)

# Production builds
yarn build # Build both workspaces
yarn build:frontend # Next.js production build
yarn build:backend # TypeScript compile to dist/

# Testing & Linting
yarn workspace frontend lint # ESLint with core-web-vitals
yarn workspace backend test # Run backend tests (tsx --test)
```

## Architecture

### Monorepo Structure (Yarn Workspaces)

- **frontend/**: Next.js 16 + React 19 dashboard with Tailwind CSS v4
- **backend/**: Express API with Sui RPC integration, Supabase persistence, and OpenRouter LLM analysis

### Backend Flow (`backend/src/`)

1. `index.ts` - Express server with CORS, routes, and graceful shutdown
2. `workers/sui-monitor.ts` - Background polling worker (configurable via `POLL_INTERVAL_MS`)
3. `lib/sui-client.ts` - Sui RPC wrapper for deployment queries
4. `lib/supabase.ts` - Database operations for deployments and analyses
5. `lib/llm-analyzer.ts` - Orchestrates 3-agent chain with Map-Reduce for large contracts
6. `lib/langchain-analyzer.ts` - LangChain implementation with parallel module analysis
7. `lib/langchain-llm.ts` - OpenRouter LLM configuration and model presets
8. `lib/risk-patterns.ts` - Security pattern knowledge base for Move contracts

### LLM Analysis Chain

The analyzer uses a 3-agent architecture via OpenRouter (default: `openai/gpt-oss-120b` via DeepInfra):
- **Agent 1 (Analyzer)**: Technical security audit matching against risk patterns
- **Agent 2 (Scorer)**: Quantitative risk score (0-100) with severity modifiers
- **Agent 3 (Reporter)**: User-friendly translation of findings

**Map-Reduce for Large Contracts**: Contracts with multiple modules are automatically chunked and analyzed in parallel using `Promise.allSettled`. Findings are aggregated, sorted by severity, and passed to the scorer/reporter.

Results are persisted to `contract_analyses` table and cached.

### Frontend Structure (`frontend/app/`)

- Uses `@/` path alias rooted at `frontend/`
- `providers.tsx` - Global providers (Privy auth, theme, data context)
- `dashboard/` - Main dashboard route with types and risk utilities
- `components/` - UI components (PascalCase filenames)

### Database Tables (Supabase)

- `sui_package_deployments` - Raw deployment metadata from Sui
- `contract_analyses` - LLM-generated safety cards with risk scores

## Key Patterns

### Environment Flags

Backend uses `envFlag()` helper for boolean env vars:
- `ENABLE_AUTO_ANALYSIS` - Toggle background monitor + auto analysis
- `ENABLE_SUI_RPC` - Master kill switch for all Sui RPC calls

### Network Detection

Network is determined from `SUI_NETWORK` env var or inferred from `SUI_RPC_URL`.

### LLM Configuration

- `OPEN_ROUTER_KEY` - Required for LLM analysis
- `LLM_MODEL_ANALYZER`, `LLM_MODEL_SCORER`, `LLM_MODEL_REPORTER` - Optional model overrides
- Default model: `openai/gpt-oss-120b` via DeepInfra with FP4 quantization

### Map-Reduce Analysis

Large contracts (multiple modules) trigger automatic parallel analysis:
1. Contract chunked by module boundaries
2. Each module analyzed independently in parallel
3. Findings aggregated and sorted by severity (Critical → Low)
4. Single scorer and reporter run on combined findings

## Conventions

- **Backend modules**: kebab-case (`sui-client.ts`, `llm-analyzer.ts`)
- **Frontend components**: PascalCase (`AnalyzedContractCard.tsx`)
- **TypeScript**: Strict mode enabled in both workspaces
- **Styling**: Tailwind utility grouping (layout → color → typography)
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RedFlag

RedFlag monitors new Sui smart-contract deployments, persists on-chain metadata to Supabase, runs Gemini-powered risk analysis, and presents the results in a React 19 dashboard.
RedFlag monitors new Sui smart-contract deployments, persists on-chain metadata to Supabase, runs AI-powered risk analysis via OpenRouter, and presents the results in a React 19 dashboard.

## Monorepo Layout

Expand Down Expand Up @@ -28,7 +28,8 @@ The frontend uses the `@/` alias (rooted at `frontend/`) for cross-module import

- Configurable CORS-protected Express API served from `backend/src/index.ts`.
- Background worker (`startMonitoring`) polls the Sui RPC (`POLL_INTERVAL_MS`, default 15s), stores new deployments in Supabase, and triggers LLM analysis for unseen packages.
- Gemini 2.5 Flash chain (Analyzer → Scorer → Reporter) with automatic fallback API key rotation and retry/backoff logic.
- **3-Agent LLM Chain** (Analyzer → Scorer → Reporter) via OpenRouter with retry/backoff logic.
- **Map-Reduce Chunked Analysis**: Large contracts with multiple modules are analyzed in parallel, then findings are aggregated. This enables analysis of contracts of any size without token limit issues.
- Supabase persistence for both raw deployment metadata (`sui_package_deployments`) and generated safety cards (`contract_analyses`).
- JSON REST endpoints for health checks, Sui telemetry, LLM analysis, and monitor status.

Expand All @@ -44,7 +45,7 @@ The frontend uses the `@/` alias (rooted at `frontend/`) for cross-module import
- Node.js 20.x (Next.js 16 and React 19 require ≥18.18; we target 20 LTS).
- Yarn Classic (1.22+) with workspaces enabled.
- A Supabase project (PostgreSQL) for storing deployments and analyses.
- Google Generative AI API key(s) for Gemini (`GOOGLE_API_KEY`, optional fallback `GOOGLE_API_KEY_FALLBACK`).
- OpenRouter API key (`OPEN_ROUTER_KEY`) - get one at https://openrouter.ai/keys.
- Sui RPC endpoint (defaults to `https://fullnode.testnet.sui.io:443`).
- Privy application ID when enabling authentication flows.

Expand Down Expand Up @@ -96,9 +97,11 @@ The frontend uses the `@/` alias (rooted at `frontend/`) for cross-module import
| `SUPABASE_URL` | Yes | Supabase project URL. | – |
| `SUPABASE_SERVICE_KEY` | Yes | Supabase service role key for privileged queries. | – |
| `SUPABASE_ANON_KEY` | No | Optional anon key; retained for future read-only client use. | – |
| `GOOGLE_API_KEY` | Yes (for analysis) | Primary Gemini 2.5 Flash key. Required to run the analyzer and background worker. | – |
| `GOOGLE_API_KEY_FALLBACK` | No | Secondary Gemini key used automatically when the primary hits quota. | – |
| `ENABLE_AUTO_ANALYSIS` | No | Enables the background Sui monitor + automatic Gemini analysis. Flip to `false` while developing UI without hitting external services. | `true` |
| `OPEN_ROUTER_KEY` | Yes (for analysis) | OpenRouter API key for LLM analysis. Get one at https://openrouter.ai/keys. | – |
| `LLM_MODEL_ANALYZER` | No | Override the analyzer model (default: `openai/gpt-oss-120b`). | – |
| `LLM_MODEL_SCORER` | No | Override the scorer model. | – |
| `LLM_MODEL_REPORTER` | No | Override the reporter model. | – |
| `ENABLE_AUTO_ANALYSIS` | No | Enables the background Sui monitor + automatic LLM analysis. Flip to `false` while developing UI without hitting external services. | `true` |
| `ENABLE_SUI_RPC` | No | Master kill switch for all Sui RPC calls (health checks, monitor, manual analysis). Set to `false` to avoid network calls locally. | `true` |
| `SUI_RPC_URL` | No | Sui RPC endpoint (testnet by default). | `https://fullnode.testnet.sui.io:443` |
| `POLL_INTERVAL_MS` | No | Worker polling interval in milliseconds. | `15000` |
Expand Down Expand Up @@ -138,9 +141,10 @@ The frontend uses the `@/` alias (rooted at `frontend/`) for cross-module import

1. `startMonitoring()` (bootstrapped in `src/index.ts`) loads the last processed checkpoint from Supabase.
2. The worker polls the Sui RPC with adaptive filters, deduplicates deployments, and upserts them into `sui_package_deployments`.
3. For each new package the worker requests a Gemini safety card via `runFullAnalysisChain`.
4. Results are persisted in `contract_analyses` (idempotent upsert) and exposed through `/api/llm/*` endpoints.
5. High-risk packages are logged with elevated console output for operational awareness.
3. For each new package the worker requests an LLM safety card via `runFullAnalysisChain`.
4. **Map-Reduce for Large Contracts**: Contracts with multiple modules are chunked and analyzed in parallel, then findings are aggregated. This ensures contracts of any size can be fully analyzed without token limit truncation.
5. Results are persisted in `contract_analyses` (idempotent upsert) and exposed through `/api/llm/*` endpoints.
6. High-risk packages are logged with elevated console output for operational awareness.

Set `ENABLE_AUTO_ANALYSIS=false` to skip this worker entirely, or `ENABLE_SUI_RPC=false` to short-circuit every Sui RPC call while working offline.

Expand Down Expand Up @@ -202,10 +206,11 @@ Adjust column types as needed for your Supabase project (e.g., replace `gen_rand
## Troubleshooting

- **CORS errors**: ensure `FRONTEND_URL` matches the requesting origin exactly (protocol + host + port).
- **LLM analysis skipped**: check that `GOOGLE_API_KEY` is set; the worker logs `⚠️ GOOGLE_API_KEY not configured` otherwise.
- **LLM analysis skipped**: check that `OPEN_ROUTER_KEY` is set; the worker logs `⚠️ OPEN_ROUTER_KEY not configured` otherwise.
- **No deployments stored**: verify Supabase tables exist and the service role key has `insert`/`upsert` permissions.
- **Monitor idle**: inspect `/api/sui/monitor-status` and server logs; adjust `POLL_INTERVAL_MS` if rate-limited.
- **Frontend 500s**: confirm `NEXT_PUBLIC_BACKEND_URL` is reachable and HTTPS when deployed to Vercel.
- **Large contract analysis**: Contracts with multiple modules are automatically chunked and analyzed in parallel. Check logs for `[MapReduce]` messages to monitor progress.

## Contributing

Expand Down
35 changes: 30 additions & 5 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,43 @@ SUPABASE_URL=your_local_supabase_url
SUPABASE_ANON_KEY=your_local_supabase_anon_key # optional; not currently required by the app
SUPABASE_SERVICE_KEY=your_local_supabase_service_key

GOOGLE_API_KEY=your_local_primary_google_api_key
GOOGLE_API_KEY_FALLBACK=your_local_fallback_google_api_key
# ========================================
# LLM Configuration (OpenRouter)
# ========================================

# Feature toggles (set to false to skip background analysis or Sui RPC calls locally)
# OpenRouter API Key - Get yours at https://openrouter.ai/keys
# Uses Map-Reduce pattern for large contracts: modules analyzed in parallel
OPEN_ROUTER_KEY=your_openrouter_api_key_here

# ========================================
# Model Selection (Optional - Defaults Provided)
# ========================================
# Default: openai/gpt-oss-120b via DeepInfra FP4 quantization
# - Low cost: ~$0.0005 per analysis
# - High uptime: 99.98%
# - Fast: parallel module analysis

# LLM_MODEL_ANALYZER=openai/gpt-oss-120b
# LLM_MODEL_SCORER=openai/gpt-oss-120b
# LLM_MODEL_REPORTER=openai/gpt-oss-120b
# LLM_MODEL_FALLBACK=meta-llama/llama-3.3-70b-instruct:free

# ========================================
# Feature Toggles
# ========================================
# Set to false to skip background analysis or Sui RPC calls locally
ENABLE_AUTO_ANALYSIS=true
ENABLE_SUI_RPC=true

# ========================================
# Sui Configuration
# ========================================
SUI_RPC_URL=https://fullnode.testnet.sui.io:443
SUI_NETWORK=testnet
SUI_PRIVATE_KEY=your_local_sui_private_key

# Polling interval for new deployments (in ms)
# Default: 300000 (5 minutes)
POLL_INTERVAL_MS=300000

# ---------- Production ----------
Expand All @@ -30,8 +56,7 @@ POLL_INTERVAL_MS=300000
# SUPABASE_SERVICE_KEY=your_prod_supabase_service_key
# SUPABASE_ANON_KEY=your_prod_supabase_anon_key
#
# GOOGLE_API_KEY=your_prod_primary_google_api_key
# GOOGLE_API_KEY_FALLBACK=your_prod_fallback_google_api_key
# OPEN_ROUTER_KEY=your_prod_openrouter_api_key
#
# SUI_RPC_URL=https://fullnode.mainnet.sui.io:443
# SUI_NETWORK=mainnet
Expand Down
Loading