Description
The backend already ships a machine-readable OpenAPI 3.1 contract at docs/openapi.json, which is loaded at module init (src/routes/index.ts:11-12) and served verbatim as JSON from GET /api/openapi.json (src/routes/index.ts:38-42). There is no human-facing way to browse it: swagger-ui-express is absent from package.json and no /docs route exists. Developers integrating with Callora must hand-read raw JSON to discover routes such as POST /api/billing/deduct and GET /api/usage. This issue adds an interactive Swagger UI mounted on top of the contract the app already publishes.
Requirements and context
- Mount an interactive API explorer (e.g.
swagger-ui-express) at GET /api/docs, backed by the same openApiSpec object already parsed in src/routes/index.ts:12 so the UI never drifts from /api/openapi.json.
- Wire the new route inside
createApiRouter in src/routes/index.ts (the function that already serves /openapi.json), keeping the existing GET /api/openapi.json endpoint unchanged.
- Respect the existing Helmet Content Security Policy configured in
src/app.ts:112-140 (note scriptSrc: ["'self'"] and styleSrc: ["'self'", "'unsafe-inline'"]); relax the CSP for the docs route only if Swagger UI assets require it, without weakening the global policy.
- Non-functional: do not load the UI assets in
NODE_ENV=production unless explicitly enabled via a new opt-in env var documented in README.md; keep startup time unaffected for non-docs traffic.
- Update
README.md (which currently documents GET /api/health, GET /api/apis, etc.) to mention the new GET /api/docs explorer.
Acceptance criteria
Suggested execution
1. Fork the repo and create a branch
git checkout -b feature/swagger-ui-docs
2. Implement changes — add the dependency and mount the explorer in src/routes/index.ts (reusing openApiSpec); add the optional production flag to src/config/env.ts / src/config/index.ts; update README.md.
3. Write/extend tests — add tests/integration/openapi-docs.test.ts (Jest + supertest, matching the existing *.test.ts convention used by tests/integration/health.test.ts).
4. Test and commit
npm run lint
npm run typecheck
npm test -- tests/integration/openapi-docs.test.ts --runInBand
npm run build
Example commit message
feat(docs): serve interactive Swagger UI for OpenAPI 3.1 contract
Guidelines
This repo targets 90%+ line coverage (see README.md "Target Coverage: 90%+"); keep new code at or above that bar. Add JSDoc to any new route handler and config field, and document the endpoint in README.md. Timeframe: 96 hours.
Description
The backend already ships a machine-readable OpenAPI 3.1 contract at
docs/openapi.json, which is loaded at module init (src/routes/index.ts:11-12) and served verbatim as JSON fromGET /api/openapi.json(src/routes/index.ts:38-42). There is no human-facing way to browse it:swagger-ui-expressis absent frompackage.jsonand no/docsroute exists. Developers integrating with Callora must hand-read raw JSON to discover routes such asPOST /api/billing/deductandGET /api/usage. This issue adds an interactive Swagger UI mounted on top of the contract the app already publishes.Requirements and context
swagger-ui-express) atGET /api/docs, backed by the sameopenApiSpecobject already parsed insrc/routes/index.ts:12so the UI never drifts from/api/openapi.json.createApiRouterinsrc/routes/index.ts(the function that already serves/openapi.json), keeping the existingGET /api/openapi.jsonendpoint unchanged.src/app.ts:112-140(notescriptSrc: ["'self'"]andstyleSrc: ["'self'", "'unsafe-inline'"]); relax the CSP for the docs route only if Swagger UI assets require it, without weakening the global policy.NODE_ENV=productionunless explicitly enabled via a new opt-in env var documented inREADME.md; keep startup time unaffected for non-docs traffic.README.md(which currently documentsGET /api/health,GET /api/apis, etc.) to mention the newGET /api/docsexplorer.Acceptance criteria
GET /api/docsreturns an HTML page that renders Swagger UI against the existing spec.openApiSpecused byGET /api/openapi.json(no second copy of the contract).src/app.tsis not weakened for non-docs routes.README.mddocuments the new endpoint and the production flag.GET /api/docsresponds200withtext/htmland thatGET /api/openapi.jsonstill returns the unchanged spec.Suggested execution
1. Fork the repo and create a branch
2. Implement changes — add the dependency and mount the explorer in
src/routes/index.ts(reusingopenApiSpec); add the optional production flag tosrc/config/env.ts/src/config/index.ts; updateREADME.md.3. Write/extend tests — add
tests/integration/openapi-docs.test.ts(Jest +supertest, matching the existing*.test.tsconvention used bytests/integration/health.test.ts).4. Test and commit
npm run lint npm run typecheck npm test -- tests/integration/openapi-docs.test.ts --runInBand npm run buildExample commit message
Guidelines
This repo targets 90%+ line coverage (see
README.md"Target Coverage: 90%+"); keep new code at or above that bar. Add JSDoc to any new route handler and config field, and document the endpoint inREADME.md. Timeframe: 96 hours.