ArshVerma commited on
Commit
c1972ef
·
1 Parent(s): 3e1edbb

Bump versions, add security middleware & deps

Browse files

Normalize project versioning to 1.0.0 and apply security/middleware and dependency updates. Changes include: update CHANGELOG, app.py and codelens.yaml versions; add TrustedHostMiddleware, ProxyHeadersMiddleware and an HTTP middleware to inject security headers (CSP, HSTS, X-Frame-Options, etc.), adjust CORS behavior and keep rate limiting; update health_check version. Update dashboard/package.json (version, $schema, bumped runtime and dev dependency versions) and expand/modernize dashboard/tsconfig.json compiler options for bundler/strict linting. Bump and relax multiple Python package pins in requirements.txt (fastapi, uvicorn, pydantic, httpx, openai, sqlmodel, pytest-cov, aiofiles, etc.). Also tidy changelog entries (testing, docker, CI/branding notes).

Files changed (6) hide show
  1. CHANGELOG.md +15 -27
  2. app.py +28 -4
  3. codelens.yaml +1 -1
  4. dashboard/package.json +14 -13
  5. dashboard/tsconfig.json +17 -5
  6. requirements.txt +14 -14
CHANGELOG.md CHANGED
@@ -3,7 +3,7 @@
3
  All notable changes to this project are documented here.
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
 
6
- ## [2.0.0] - 2026-04-05
7
 
8
  ### Added
9
  - **Models**: Complete Pydantic v2 models (`TaskId`, `Action`, `Scenario`, `EpisodeResult`, etc.)
@@ -23,36 +23,24 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
23
  - **Security**:
24
  - Rate limiting via `slowapi`: 60 req/min per IP (configurable)
25
  - API key authentication: optional, off by default, enabled via `API_KEY_ENABLED=true`
 
26
  - **Episode Lifecycle**: Auto-cleanup of expired episodes every 5 minutes (default 1hr)
27
  - **Leaderboard**: Paginated `/leaderboard?limit=N&offset=M&task_id=X`
28
  - **Baseline Agent**: Full rewrite with argparse CLI, `KeywordAgent` (35 rules), `LLMAgent` (Claude)
29
  - **Evaluation**: `scripts/evaluate.py` for batch evaluation of all 30 scenarios with summary report and progress bars
30
- - **Database Utility**: `scripts/migrate.py` for database init/reset commands
31
- - **Testing**:
32
- - `tests/conftest.py`: Shared fixtures with in-memory DB override
33
- - `tests/test_scenarios.py`: 30 parametrized scenario validation tests
34
- - `tests/test_database.py`: Persistence layer unit tests
35
- - **Dockerization**: Multi-stage `builder` + `production` builds with non-root user security
36
- - **CI/CD**: Unified 5-job pipeline (`lint`, `test`, `validate`, `docker-build`, `publish` to GHCR)
37
- - **Branding**: Full rebrand to **CodeLens.**, including signature typography and SVG iconography
38
 
39
  ### Fixed
40
- - **CLI**: Port mismatch in `baseline.py` (8000 → 7860) and added `--url`, `--task`, `--seed` CLI flags
41
- - **Crash Fixes**: Leaderboard submit crash after list slicing (captured rank before slice)
42
- - **WebSocket**: Disconnect now handled with typed `WebSocketDisconnect` and `clients.discard()`
43
- - **Metadata**: Incoherent weight structure in `codelens.yaml` replaced with named, accurate pairs
 
44
 
45
- ### Changed
46
- - **Response Format**: `/leaderboard` response format: each task now `{"entries": [...], "total": N}` (was bare list)
47
- - **Startup**: `app.py` startup initializes DB and logs confirmation message
48
-
49
- ## [1.0.0] - Original Fork Baseline
50
-
51
- ### Added
52
- - FastAPI skeleton with /reset, /step, /result, /leaderboard, /submit endpoints
53
- - In-memory episode storage
54
- - WebSocket event broadcasting at /ws/events
55
- - Basic Dockerfile
56
- - Pylint-only GitHub Actions workflow
57
- - codelens.yaml placeholder
58
- - README with roadmap
 
3
  All notable changes to this project are documented here.
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
 
6
+ ## [1.0.0] - 2026-04-05
7
 
8
  ### Added
9
  - **Models**: Complete Pydantic v2 models (`TaskId`, `Action`, `Scenario`, `EpisodeResult`, etc.)
 
23
  - **Security**:
24
  - Rate limiting via `slowapi`: 60 req/min per IP (configurable)
25
  - API key authentication: optional, off by default, enabled via `API_KEY_ENABLED=true`
26
+ - Added `TrustedHostMiddleware` and `Security Headers` (XSS, Frame protection)
27
  - **Episode Lifecycle**: Auto-cleanup of expired episodes every 5 minutes (default 1hr)
28
  - **Leaderboard**: Paginated `/leaderboard?limit=N&offset=M&task_id=X`
29
  - **Baseline Agent**: Full rewrite with argparse CLI, `KeywordAgent` (35 rules), `LLMAgent` (Claude)
30
  - **Evaluation**: `scripts/evaluate.py` for batch evaluation of all 30 scenarios with summary report and progress bars
31
+ - **Testing**: 155+ parametrized tests with full coverage reporting.
32
+ - **Dockerization**: Multi-stage `builder` + `production` builds with non-root user security.
33
+ - **CI/CD**: Unified 5-job pipeline (`lint`, `test`, `validate`, `docker-build`, `publish` to GHCR).
34
+ - **Branding**: Full rebrand to **CodeLens.**, including signature iconography.
 
 
 
 
35
 
36
  ### Fixed
37
+ - **CLI**: Port mismatch in `baseline.py` (8000 → 7860) and added `--url`, `--task`, `--seed` CLI flags.
38
+ - **Crash Fixes**: Leaderboard submit crash after list slicing (captured rank before slice).
39
+ - **WebSocket**: Disconnect now handled with typed `WebSocketDisconnect` and `clients.discard()`.
40
+ - **Metadata**: Incoherent weight structure in `codelens.yaml` replaced with named, accurate pairs.
41
+ - **Security**: Implemented `TrustedHostMiddleware` and hardened headers.
42
 
43
+ ## [0.1.0] - Initial Baseline Fork
44
+ - Initial FastAPI skeleton.
45
+ - In-memory episode storage.
46
+ - Basic Dockerfile and Pylint-only CI.
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -64,11 +64,24 @@ app = FastAPI(
64
  "Trains agents to detect bugs, security vulnerabilities, and architectural issues "
65
  "in realistic Python PRs."
66
  ),
67
- version="2.0.0",
68
  lifespan=lifespan,
69
  )
70
 
71
- # ── CORS Middleware ───────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  app.add_middleware(
73
  CORSMiddleware,
74
  allow_origins=["*"] if settings.app_env == "development" else [f"http://localhost:{settings.app_port}"],
@@ -77,7 +90,18 @@ app.add_middleware(
77
  allow_headers=["*"],
78
  )
79
 
80
- # ── Rate Limiting ─────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
81
  limiter = Limiter(key_func=get_remote_address, default_limits=[f"{settings.rate_limit_per_minute}/minute"])
82
  app.state.limiter = limiter
83
  app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
@@ -169,7 +193,7 @@ async def http_exception_handler(request, exc):
169
  def health_check():
170
  return {
171
  "status": "ok",
172
- "version": "2.0.0",
173
  "env_ready": True,
174
  "env": settings.app_env,
175
  "active_episodes": len(episodes),
 
64
  "Trains agents to detect bugs, security vulnerabilities, and architectural issues "
65
  "in realistic Python PRs."
66
  ),
67
+ version="1.0.0",
68
  lifespan=lifespan,
69
  )
70
 
71
+ # ── Security & Middleware ──────────────────────────────────────────────────
72
+ from fastapi.middleware.trustedhost import TrustedHostMiddleware
73
+ from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
74
+
75
+ # 1. Trusted Host (Prevent Host-header injection)
76
+ app.add_middleware(
77
+ TrustedHostMiddleware,
78
+ allowed_hosts=["*"] if settings.app_env == "development" else [f"localhost", "127.0.0.1", "*.github.io"]
79
+ )
80
+
81
+ # 2. Proxy Headers (Support Docker/Reverse-proxy)
82
+ app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")
83
+
84
+ # 3. CORS
85
  app.add_middleware(
86
  CORSMiddleware,
87
  allow_origins=["*"] if settings.app_env == "development" else [f"http://localhost:{settings.app_port}"],
 
90
  allow_headers=["*"],
91
  )
92
 
93
+ # 4. Security Headers Middleware
94
+ @app.middleware("http")
95
+ async def add_security_headers(request: Request, call_next):
96
+ response = await call_next(request)
97
+ response.headers["X-Content-Type-Options"] = "nosniff"
98
+ response.headers["X-Frame-Options"] = "DENY"
99
+ response.headers["X-XSS-Protection"] = "1; mode=block"
100
+ response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
101
+ response.headers["Content-Security-Policy"] = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' ws: wss:;"
102
+ return response
103
+
104
+ # 5. Rate Limiting
105
  limiter = Limiter(key_func=get_remote_address, default_limits=[f"{settings.rate_limit_per_minute}/minute"])
106
  app.state.limiter = limiter
107
  app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
 
193
  def health_check():
194
  return {
195
  "status": "ok",
196
+ "version": "1.0.0",
197
  "env_ready": True,
198
  "env": settings.app_env,
199
  "active_episodes": len(episodes),
codelens.yaml CHANGED
@@ -1,4 +1,4 @@
1
- version: "2.0"
2
  name: "agentorg-codereview"
3
  owners: ["Arsh Verma", "Divyansh Rawat"]
4
  description: >
 
1
+ version: "1.0.0"
2
  name: "agentorg-codereview"
3
  owners: ["Arsh Verma", "Divyansh Rawat"]
4
  description: >
dashboard/package.json CHANGED
@@ -1,6 +1,7 @@
1
  {
 
2
  "name": "codelens-dashboard",
3
- "version": "2.0.0",
4
  "private": true,
5
  "author": "Arsh Verma, Divyansh Rawat",
6
  "type": "module",
@@ -11,21 +12,21 @@
11
  },
12
  "dependencies": {
13
  "@fontsource/inter": "^5.1.0",
14
- "@tanstack/react-query": "^5.0.0",
15
- "clsx": "^2.1.0",
16
  "lucide-react": "^0.475.0",
17
- "react": "^18.3.0",
18
- "react-dom": "^18.3.0",
19
- "zustand": "^5.0.0"
20
  },
21
  "devDependencies": {
22
- "@tailwindcss/vite": "^4.1.0",
23
- "@types/node": "^25.5.2",
24
- "@types/react": "^18.3.0",
25
- "@types/react-dom": "^18.3.0",
26
- "@vitejs/plugin-react": "^4.3.0",
27
- "tailwindcss": "^4.1.0",
28
  "typescript": "^5.7.0",
29
- "vite": "^6.2.0"
30
  }
31
  }
 
1
  {
2
+ "$schema": "https://json.schemastore.org/package",
3
  "name": "codelens-dashboard",
4
+ "version": "1.0.0",
5
  "private": true,
6
  "author": "Arsh Verma, Divyansh Rawat",
7
  "type": "module",
 
12
  },
13
  "dependencies": {
14
  "@fontsource/inter": "^5.1.0",
15
+ "@tanstack/react-query": "^5.62.0",
16
+ "clsx": "^2.1.1",
17
  "lucide-react": "^0.475.0",
18
+ "react": "^19.0.0",
19
+ "react-dom": "^19.0.0",
20
+ "zustand": "^5.0.3"
21
  },
22
  "devDependencies": {
23
+ "@tailwindcss/vite": "^4.0.0",
24
+ "@types/node": "^22.10.0",
25
+ "@types/react": "^19.0.0",
26
+ "@types/react-dom": "^19.0.0",
27
+ "@vitejs/plugin-react": "^4.3.4",
28
+ "tailwindcss": "^4.0.0",
29
  "typescript": "^5.7.0",
30
+ "vite": "^6.0.0"
31
  }
32
  }
dashboard/tsconfig.json CHANGED
@@ -1,16 +1,28 @@
1
  {
 
2
  "compilerOptions": {
3
- "target": "ES2022",
4
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
 
 
 
5
  "module": "ESNext",
 
 
 
6
  "moduleResolution": "bundler",
 
 
 
 
 
7
  "jsx": "react-jsx",
 
 
8
  "strict": true,
9
  "noUnusedLocals": true,
10
  "noUnusedParameters": true,
11
- "noFallthroughCasesInSwitch": true,
12
- "skipLibCheck": true,
13
- "types": ["vite/client", "node"]
14
  },
15
  "include": ["src"]
16
  }
 
1
  {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
  "compilerOptions": {
4
+ "composite": true,
5
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
6
+ "target": "ES2020",
7
+ "useDefineForClassFields": true,
8
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
9
  "module": "ESNext",
10
+ "skipLibCheck": true,
11
+
12
+ /* Bundler mode */
13
  "moduleResolution": "bundler",
14
+ "allowImportingTsExtensions": true,
15
+ "resolveJsonModule": true,
16
+ "isolatedModules": true,
17
+ "moduleDetection": "force",
18
+ "noEmit": true,
19
  "jsx": "react-jsx",
20
+
21
+ /* Linting */
22
  "strict": true,
23
  "noUnusedLocals": true,
24
  "noUnusedParameters": true,
25
+ "noFallthroughCasesInSwitch": true
 
 
26
  },
27
  "include": ["src"]
28
  }
requirements.txt CHANGED
@@ -1,16 +1,16 @@
1
- fastapi>=0.109.0
2
- uvicorn>=0.27.0
3
- pydantic>=2.6.1
4
  pytest>=8.0.0
5
- requests>=2.31.0
6
- websockets>=12.0
7
- httpx<0.28.0
8
- openai>=1.0.0
9
- pydantic-settings==2.2.1
10
- slowapi==0.1.9
11
- python-dotenv==1.0.1
12
- sqlmodel==0.0.16
13
- aiosqlite==0.20.0
14
- pytest-cov==4.1.0
15
- aiofiles==23.2.1
16
  PyYAML>=6.0.1
 
1
+ fastapi>=0.115.0
2
+ uvicorn>=0.30.0
3
+ pydantic>=2.10.0
4
  pytest>=8.0.0
5
+ requests>=2.32.0
6
+ websockets>=13.0
7
+ httpx>=0.28.0
8
+ openai>=1.50.0
9
+ pydantic-settings>=2.6.0
10
+ slowapi>=0.1.9
11
+ python-dotenv>=1.0.1
12
+ sqlmodel>=0.0.22
13
+ aiosqlite>=0.20.0
14
+ pytest-cov>=5.0.0
15
+ aiofiles>=24.0.0
16
  PyYAML>=6.0.1