# NestJS

URL: https://tailrace.dev/docs/integrations/nestjs

> TailraceModule for Nest + Express - OpenAI-compatible middleware with 422 on policy block.



Enforce data policy on OpenAI-compatible chat routes in NestJS (Express adapter). Scan request messages before upstream, scan JSON and SSE responses on the way back.

## Quickstart [#quickstart]

```ts
import { createTailrace } from "@tailrace/core";
import { TailraceModule } from "@tailrace/nestjs";
import { Module } from "@nestjs/common";

@Module({
  imports: [
    TailraceModule.forRoot({
      tailrace: createTailrace(),
      forRoutes: ["v1/*path"],
      agent: (req) => String(req.headers["x-agent-id"] ?? "default"),
    }),
  ],
})
export class AppModule {}
```

Peer: `@nestjs/common` `>=10`. Primary CI target: Nest + **Express**. For Nest + Fastify, register
[`@tailrace/fastify`](/docs/integrations/fastify) on the underlying Fastify instance.

Only `mode: "openai-compatible"` in v0.1. Nest 11 route globs use named splats (`v1/*path`).

## Boundaries covered [#boundaries-covered]

| Location                | Tailrace boundary                                   | Direction            |
| ----------------------- | --------------------------------------------------- | -------------------- |
| Chat request messages   | `{ kind: "model", provider }` (`model` field as-is) | Outbound to upstream |
| JSON chat completion    | same model boundary                                 | Inbound              |
| SSE `text/event-stream` | same; carry-buffer across chunks                    | Inbound              |

Block → **422** `{ error: { type: "policy_violation", entity, rule } }`. SSE: cancel upstream, emit one error `data:` event, close (abort-only; no `streamBlockBehavior` in v0.1).

## Guides [#guides]

* [Block secrets in a NestJS app](/docs/guides/block-secrets-in-nestjs)
* [Boundaries](/docs/concepts/boundaries)

## Reference [#reference]

* [NestJS package](/docs/reference/nestjs)
* [HTTP shared pipeline](/docs/reference/http)
