Skip to content

core: filter pipeline ordering validation doesn't see cross-crate filter dependencies #812

Description

@jordigilh

FilterPipeline::ordering_errors() in praxis-core hard-fails at startup on
misordered core filters, but it only checks core's own built-in filter
names — it has no visibility into filters defined in downstream crates
(e.g. ai's identity_header_guard, external_metering).

Concretely: external_metering depends on identity_header_guard running
first in the pipeline so identity ends up in filter_metadata before
metering reads it (see ai#709,
ai#581). If a deployment
config puts them in the wrong order today, nothing fails at startup — every
event just ships with token: 0 (or unmetered) silently, forever. This is
invisible to both tests and operators until someone notices the numbers are
wrong in production.

Proposal

Let filters declare their own ordering constraints (e.g. "must run after
X" / "must run before Y") through a small trait method or config
attribute, and have FilterPipeline's existing startup validation collect
constraints from every registered filter — core and downstream crates alike
— rather than special-casing a fixed list of core filter names.

Why not a filter-local workaround

A filter-local check (e.g. external_metering inspecting the configured
pipeline order at startup) would only catch this one pair, not the general
problem, and every future cross-crate dependency would need its own bespoke
check. A single pipeline-level mechanism instead:

  • Fails closed at startup instead of degrading silently at runtime.
  • Generalizes to every current and future cross-crate filter dependency.
  • Keeps the enforcement in one place (FilterPipeline) rather than
    duplicated per filter.

Scope

  • Design the constraint-declaration API (trait method vs. config attribute).
  • Extend ordering_errors() (or an equivalent build-time check) to consult
    declared constraints from all registered filters, not just core's.
  • Migrate identity_header_guard / external_metering to declare their
    existing implicit ordering requirement as the first real usage.

Follow-up from review discussion on
ai#581.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions