Open Fusion NestJS API
Required Context
Before editing API code, read:
docs/PRD.md
docs/specs/001-openai-compatible-api.md
docs/specs/005-streaming-tools-response-normalization.md
docs/adrs/0001-use-nestjs-backend.md
docs/adrs/0002-openai-compatible-public-api.md
Also read docs/specs/007-observability-resilience-security.md when touching auth, errors, logs, limits, health checks, or request ids.
API Contract
Preserve these MVP endpoints:
POST /v1/chat/completions
GET /v1/models
Treat OpenAI compatibility as the public contract. A client should be able to change baseURL and token without learning Open Fusion internals.
NestJS Structure
Prefer modules with clear ownership:
- API/controller layer: HTTP shape, status codes, headers, SSE response framing.
- Application services: route resolution, orchestration request lifecycle, response normalization.
- Config services: validated configuration access only.
- Provider services: call adapters, never import provider SDKs in controllers.
- Guards/interceptors/filters: auth, request id, logging, error normalization.
Do not let controllers import OpenRouter, Vercel provider packages, or raw configuration files directly.
Chat Completions Rules
- Validate
model and messages before orchestration.
- Reject non-finite numeric request fields (
NaN, Infinity, -Infinity) with an OpenAI-style validation error.
- Enforce configured payload, message-count, and message-content limits before orchestration.
- Preserve compatible request fields when supported.
- Reject or ignore unsupported fields consistently with the configured compatibility policy.
- Return OpenAI-style error envelopes.
- For
stream: true, use text/event-stream and terminate with data: [DONE].
- Do not stream internal delegation traces unless a future spec explicitly allows it.
Controller Logging Rules
- Put context creation, validation, route lookup, model access checks, and tools policy checks inside the failure logging path.
- If a request fails before route/orchestrator resolution, log a minimal
chat_completion.failed event with requestId, client id when known, stream flag when known, latency, and normalized error.
- Never open SSE before all pre-stream validation and routing failures that should return JSON have been handled.
Testing
Add focused tests for:
- request validation;
NaN/Infinity numeric rejection;
- message count, message content, and payload limits;
- auth failures;
- unknown public model;
- failure logs for validation/model/tool-policy errors before SSE starts;
- non-streaming response envelope;
- streaming chunk shape and
[DONE];
- provider/orchestration errors mapped to OpenAI-style errors.
When API behavior changes, update the owning spec before or with the implementation.
1---2name: open-fusion-nestjs-api3description: Build and maintain the Open Fusion NestJS backend API. Use when Codex implements or changes OpenAI-compatible HTTP endpoints, NestJS modules/controllers/services, request validation, streaming SSE responses, OpenAI-style error envelopes, model listing, authentication guards, or API tests for the Open Fusion LLM gateway.4---56# Open Fusion NestJS API78## Required Context910Before editing API code, read:1112- `docs/PRD.md`13- `docs/specs/001-openai-compatible-api.md`14- `docs/specs/005-streaming-tools-response-normalization.md`15- `docs/adrs/0001-use-nestjs-backend.md`16- `docs/adrs/0002-openai-compatible-public-api.md`1718Also read `docs/specs/007-observability-resilience-security.md` when touching auth, errors, logs, limits, health checks, or request ids.1920## API Contract2122Preserve these MVP endpoints:2324- `POST /v1/chat/completions`25- `GET /v1/models`2627Treat OpenAI compatibility as the public contract. A client should be able to change `baseURL` and token without learning Open Fusion internals.2829## NestJS Structure3031Prefer modules with clear ownership:3233- API/controller layer: HTTP shape, status codes, headers, SSE response framing.34- Application services: route resolution, orchestration request lifecycle, response normalization.35- Config services: validated configuration access only.36- Provider services: call adapters, never import provider SDKs in controllers.37- Guards/interceptors/filters: auth, request id, logging, error normalization.3839Do not let controllers import OpenRouter, Vercel provider packages, or raw configuration files directly.4041## Chat Completions Rules4243- Validate `model` and `messages` before orchestration.44- Reject non-finite numeric request fields (`NaN`, `Infinity`, `-Infinity`) with an OpenAI-style validation error.45- Enforce configured payload, message-count, and message-content limits before orchestration.46- Preserve compatible request fields when supported.47- Reject or ignore unsupported fields consistently with the configured compatibility policy.48- Return OpenAI-style error envelopes.49- For `stream: true`, use `text/event-stream` and terminate with `data: [DONE]`.50- Do not stream internal delegation traces unless a future spec explicitly allows it.5152## Controller Logging Rules5354- Put context creation, validation, route lookup, model access checks, and tools policy checks inside the failure logging path.55- If a request fails before route/orchestrator resolution, log a minimal `chat_completion.failed` event with `requestId`, client id when known, stream flag when known, latency, and normalized error.56- Never open SSE before all pre-stream validation and routing failures that should return JSON have been handled.5758## Testing5960Add focused tests for:6162- request validation;63- `NaN`/`Infinity` numeric rejection;64- message count, message content, and payload limits;65- auth failures;66- unknown public model;67- failure logs for validation/model/tool-policy errors before SSE starts;68- non-streaming response envelope;69- streaming chunk shape and `[DONE]`;70- provider/orchestration errors mapped to OpenAI-style errors.7172When API behavior changes, update the owning spec before or with the implementation.