Express 5 API. Entry: index.ts → createApp() in app.ts. Tests: tests/README.md (unit + tests/integration/).
Mounted in app.ts:
| Prefix | Router | Endpoints (examples) |
|---|---|---|
/api |
routes/health.ts |
GET /health |
/api |
routes/meta.ts |
GET /capabilities, /sources, /openapi.json |
/api |
routes/scan.ts |
POST /scan, /watch, /scan/validate |
/api |
routes/translateLocale.ts |
POST /translate |
/api/v1 |
routes/v1.ts |
Same handlers under versioned prefix |
Middleware (scan/watch): middleware/rateLimit.ts, middleware/scanTimeout.ts.
Rate limits (v1.1.0): separate in-memory buckets per IP for POST /scan (default 12/min) and POST /watch (default 120/min). Env: RATE_LIMIT_SCAN_PER_MIN, RATE_LIMIT_WATCH_PER_MIN. POST /scan/validate is exempt. Returns HTTP 429 with code: "RATE_LIMITED". Tests: tests/server/rateLimit.test.ts.
| Module | Role |
|---|---|
services/scan.ts |
Orchestrates full scan |
services/nvd.ts |
NVD API |
services/osv.ts |
OSV |
services/github.ts |
GitHub Advisories |
services/cisa.ts |
CISA KEV |
services/rss.ts |
Security RSS |
services/translate.ts |
Optional EN→FA translation |
services/enrich.ts |
Merge/dedupe findings |
npm run build:server # → dist-server/ (server/ + shared/ + entry shim)Production (non-Docker): node dist-server/index.js after npm run build (static UI in dist/).
API types live in shared/. server/types.ts re-exports them for route handlers.
Source of truth: openapi/spec.json. Keep in sync with extended-docs/docs/assets/cve-openapi.json — run npm run check:openapi.