Tailrace
Guides

Block secrets in a NestJS app

Register TailraceModule so OpenAI-compatible routes respect Tailrace policy on Nest + Express.

Use @tailrace/nestjs to enforce data policy on OpenAI-compatible chat routes in NestJS - in-process, with no proxy.

Prerequisites

  • Quickstart or equivalent createTailrace setup
  • NestJS (@nestjs/common / @nestjs/core >=10) with the Express adapter (primary CI target)
  • reflect-metadata loaded before Nest bootstraps

Step 1: Install

pnpm add @tailrace/core @tailrace/nestjs @nestjs/common @nestjs/core reflect-metadata

Step 2: Import TailraceModule

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"),
      workflowId: (req) => String(req.headers["x-workflow-id"] ?? "default"),
    }),
  ],
})
export class AppModule {}

Nest 11 route globs use named splats (v1/*path, not v1*). Prefer scoping forRoutes to your chat proxy paths instead of the default all-routes matcher.

How it works

TailraceModule.forRoot registers TailraceMiddleware on the routes you pass. The middleware applies the same openai-compat contract as Hono and Express:

LocationTailrace boundaryDirection
Chat request messages{ kind: "model", provider } (model field as-is)Outbound to upstream
JSON chat completionsame model boundaryInbound
SSE text/event-streamsame; carry-buffer across chunksInbound

When policy resolves to block, the middleware returns 422 with { error: { type: "policy_violation", entity, rule } } - never the raw value. That maps from PolicyViolationError.

Only mode: "openai-compatible" is supported. Shared helpers live in @tailrace/http.

Common variations

Nest + Fastify

For Nest's Fastify adapter, register @tailrace/fastify on the underlying Fastify instance rather than relying on Express-shaped Nest middleware.

Scope agent and workflow ID

Pass agent and workflowId as functions of the Express Request (or a static string for workflowId). Defaults are "default" when omitted.

Verify with a synthetic key

Send a chat completion body whose messages include sk_test_…FAKE. Expect 422. An example.com email should tokenize under the default policy.

See also

On this page