Block secrets in an Encore service
Add Tailrace middleware to raw OpenAI-compatible Encore endpoints so chat bodies and SSE streams respect policy.
Use @tailrace/encore to enforce data policy on OpenAI-compatible proxy endpoints in Encore.ts -
in-process, with no proxy.
Prerequisites
- Quickstart or equivalent
createTailracesetup encore.dev>=1.46
Step 1: Install
pnpm add @tailrace/core @tailrace/encore encore.devStep 2: Register service middleware
import { createTailrace } from "@tailrace/core";
import { tailraceEncore } from "@tailrace/encore";
import { Service } from "encore.dev/service";
export default new Service("api", {
middlewares: [
tailraceEncore(createTailrace(), {
agent: "api",
workflowId: "default",
}),
],
});Step 3: Expose the chat proxy as api.raw
Define the OpenAI-compatible proxy with api.raw so request/response bodies and SSE are available
via req.rawRequest / req.rawResponse. Typed Encore APIs that return structured chat payloads
still get a check when the body shape matches openai-compat, but raw endpoints are the supported
path for streaming proxies.
How it works
| 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 |
When policy resolves to block, the middleware returns 422 with
{ error: { type: "policy_violation", entity, rule } } - never the raw value. That maps from
PolicyViolationError.
For SSE, Tailrace cancels the upstream stream, emits one error data: event, and closes
(abort-only in v0.1).
Only mode: "openai-compatible" is supported. Shared helpers live in @tailrace/http.
Common variations
Derive agent from the request
tailraceEncore(tailrace, {
agent: (req) => String(req.data?.agentId ?? "api"),
workflowId: (req) => String(req.requestMeta?.path ?? "default"),
});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
- Encore integration
- Encore reference
- Hono - same openai-compat contract on a different host
- Boundaries
- Spec:
docs/integrations.md§13