voro-web
The web product. A thin orchestration layer that queues scans, calls voro-scan and voro-brain via subprocess, stores reports, and renders them at scan.voro.security.
Purpose
voro-web does not scan code or score vulnerabilities. It orchestrates the pipeline: accept user input, queue a job, run both tools in a Docker worker container, store the ThreatReport, and render it in a Next.js frontend with full report visualization.
Architecture
User → Next.js frontend → Express API → BullMQ queue → Worker container
Worker:
1. agent-builder audit <target> --format json --scan-mode combined
2. Find audit JSON (stdout → CWD → ~/.agent-builder/audit/)
3. voro-brain report <target> --audit-json <path> --repo-path <path>
4. Parse ThreatReport JSON from stdout
5. Verify trust lock (fail-closed in strict mode)
6. Save report to filesystem
7. Cleanup quarantine repo
Docker Services
| Service | Image | Purpose |
|---|---|---|
| nginx | nginx:alpine | Reverse proxy + SSL termination |
| web | Dockerfile.web | Next.js standalone build (node:20-slim) |
| api | Dockerfile.api | Express server (node:20-slim) |
| worker | Dockerfile.worker | Python 3.12 + Node.js 20 + agent-builder + voro-brain + external scanners |
| redis | redis:7-alpine | BullMQ job queue + rate limiting |
| postgres | postgres:16-alpine | Optional report store (behind feature flag) |
API Routes
| Method | Route | Purpose |
|---|---|---|
| POST | /api/scan | Queue a scan job (returns 202 with jobId) |
| GET | /api/report/:id | Get scan report (ThreatReport JSON or status) |
| POST | /api/upload | Upload file for scanning (.sol, .zip, .tar.gz) |
| POST | /api/feedback | Submit finding feedback → voro-brain CLI |
| GET | /api/health | Health check (redis, database, degraded modes) |
| POST | /api/webhook/github | GitHub App webhook (push/PR events → auto-scan) |
Rate limit: 10 scans/day per IP (Redis-backed, fail-open)
Frontend Components
packages/web/src/components/
├── report/ # 18 components
│ ├── verdict-banner # Overall scan verdict display
│ ├── threat-map # 6-dimension risk visualization
│ ├── finding-card # Individual finding detail
│ ├── security-report-card # 4-tab layout (Static Analysis, SCA, Secrets, AI Triage)
│ ├── dimension-card # Per-dimension score + findings
│ ├── confidence-meter # Bayesian confidence visualization
│ └── ...12 more
├── scan/ # 5 components
│ ├── github-url-input # GitHub URL scan input
│ ├── contract-address-input # Etherscan contract fetch
│ ├── file-upload-input # Direct file upload
│ └── scan-progress # Real-time scan progress
└── ui/ # 10 shadcn/ui primitives
Scan Input Modes
| Mode | Description |
|---|---|
| GitHub URL | Paste a repo URL, worker clones and scans |
| Contract Address | Enter an Etherscan contract address, fetches verified source |
| File Upload | Upload .sol, .zip, or .tar.gz files directly (10MB limit) |
Key Capabilities
- Three scan modes: GitHub URL, Etherscan contract, file upload
- Full report visualization: 6-dimension threat map, finding cards, confidence meters, standards badges
- GitHub App integration: Webhook handler for push/PR events, Check Runs with scan results
- OG image generation: Dynamic Open Graph images via Satori for link previews
- SSR for reports: Server-side rendering for SEO and social sharing
- Fail-closed trust: Worker verifies voro-brain lock file before saving reports (configurable strict/warn)
- Type-safe contract: TypeScript types are direct mirrors of voro-brain Pydantic models (snake_case in both)
Type Alignment Contract
TypeScript types in voro-web mirror voro-brain's Pydantic models exactly:
| Concept | agent-builder | voro-brain | voro-web (TS) |
|---|---|---|---|
| File location | file | file_path | file_path |
| Line number | line | line_number | line_number |
| Categories | VulnCategory (46) | VulnerabilityCategory (18) | string |
| Report | ScanResult | ThreatReport | ThreatReport interface |
Source of truth: voro-brain/src/models/threat_report.py → JSON Schema → TypeScript types.
Build & Run
# Development
pnpm install
docker run -d -p 6379:6379 redis:7-alpine # Redis for BullMQ
pnpm --filter @voro/api dev # Express API (port 3000)
pnpm --filter @voro/web dev # Next.js (port 3001)
# Docker (full stack)
./scripts/build-worker.sh # Build worker image
docker compose up --build # All 6 services
# Verification
pnpm typecheck # Type checking
pnpm run test:api # 171 API tests
pnpm run test:web # 14 web tests
./scripts/smoke-test.sh # E2E: health → scan → poll → report
Current State
- Version: 0.1.0
- Tests: 180+ total (171 API + 14 web)
- Domain: scan.voro.security
- Stack: TypeScript, pnpm monorepo (packages/api + packages/web)
- Deployment: Docker Compose 6-service stack, VPS with SSL via Let's Encrypt
- Status: Local production rehearsal passed. VPS deployment next.
Implemented
- Express API with all routes + BullMQ worker pipeline
- Next.js frontend with full report viewer (18 report components)
- All 3 scan modes, rate limiting, GitHub App integration
- OG images, JSON Schema validation, 5 example reports
- Production hardening: env validation, graceful shutdown, health checks
- CI quality gate, release verification workflow
Not Yet Built
- Paywall gate (UI renders "Coming Soon")
- Stripe/payments integration
- User accounts/sessions
- Authentication (rate limit by IP only for now)