Skip to content

feat(filter): add identity header guard filter #698

Description

@yossiovadia

Summary

Add a filter that captures request headers matching a configurable prefix into filter_metadata and strips them before forwarding upstream. This prevents identity headers (e.g. x-tenant-username, x-tenant-group) from leaking to upstream LLM providers while making them available to downstream filters like external_metering.

Motivation

The external_metering filter (PR #581) reads tenant identity from request headers for per-user usage attribution. These headers are set by an upstream auth layer and must not reach the upstream provider. Currently there is no filter to capture these headers to metadata and strip them — reserved_headers in core only handles hardcoded x-praxis-* prefixes with no metadata capture and no configurable prefixes (core TODO #186).

Why not extend reserved_headers?

reserved_headers strips hardcoded internal prefixes (x-praxis-*, x-ext-protocol-*, x-ext-agent-*) at the protocol layer. It does two things this filter needs but doesn't have:

  1. No metadata capture — it strips headers but doesn't write their values anywhere. Downstream filters (metering, audit) need the captured values.
  2. No configurable prefixes — the prefix list is a compile-time constant. Operator-managed prefixes are tracked as core TODO Inference access policies #186 but not yet implemented.

This filter is complementary, not competing: reserved_headers protects proxy-internal routing headers; this filter protects operator-configured identity headers. If core #186 lands with metadata capture, this filter can be retired or become a thin wrapper.

Scope

  • Configurable header prefix (default: x-tenant-)
  • Captured headers written to filter_metadata under a configurable namespace
  • Matched headers marked for removal before upstream send
  • ~80 lines of filter code
  • Unit tests, integration test, example config
  • Working implementation with tests available on my fork (yossiovadia/ai, branch feat/metering-local) — ready to clean up and PR once assigned.

Non-goals

  • Not replacing reserved_headers
  • No authorization logic — capture and strip only

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions