Skip to content

v0.5.1

Latest

Choose a tag to compare

@jrandolf jrandolf released this 28 Jun 20:47
83d3088

protovalidate-buffa v0.5.1

#[connect_impl] now speaks fluent Connect 0.7 — and still hits 2872 / 2872 (100%) on the upstream conformance suite.

This patch release rounds out the Connect integration story. The #[connect_impl] macro previously understood only buffa's OwnedView<T> handler signatures; it now recognises connectrpc::ServiceRequest<'_, T> as well, so teams that have adopted the Connect 0.7 owned-message wrapper get automatic validation out of the box — no per-handler boilerplate, no forgetting a req.validate()?.


🐛 Bug Fixes

#[connect_impl] validates Connect ServiceRequest handlers

Prior to this release, applying #[connect_impl] to a service impl that used Connect 0.7's ServiceRequest<'_, T> parameter type silently skipped those handlers — the macro only injected validation when it spotted an OwnedView<T>. Any handler written in the newer style received no automatic validation at all.

The macro now detects both shapes:

Handler signature Validated?
request: OwnedView<pb::FooView<'static>> ✅ (was already working)
request: connectrpc::ServiceRequest<'_, pb::Foo> ✅ (fixed in v0.5.1)

Both types expose to_owned_message(), so the injected code is uniform and zero-surprise:

// Apply once at the impl level — every handler is covered, now and in future.
#[protovalidate_buffa::connect_impl]
impl UserService for UserServiceImpl {
    async fn create_user(
        &self,
        ctx: Context,
        // Connect 0.7 ServiceRequest — now fully validated automatically.
        request: connectrpc::ServiceRequest<'_, pb::CreateUserRequest>,
    ) -> Result<(pb::CreateUserResponse, Context), ConnectError> {
        // Validation runs before this line.
        // Invalid requests are rejected as InvalidArgument before reaching here.
        let req = request.into_message();
        // ...
    }
}

Validation failures surface as a structured ConnectError::invalid_argument carrying the full set of rule violations, powered by ValidationError::into_connect_error. The typed error fields let you distinguish failure modes cleanly:

match msg.validate() {
    Ok(()) => { /* proceed */ }
    Err(e) if e.compile_error.is_some() => {
        // Schema mismatch caught at codegen time; this is a bug in the .proto or plugin config.
        tracing::error!(compile_error = %e.compile_error.as_deref().unwrap_or(""));
    }
    Err(e) if e.runtime_error.is_some() => {
        // Rule precondition couldn't be evaluated (e.g. non-UTF-8 bytes under `pattern`).
        tracing::warn!(runtime_error = %e.runtime_error.as_deref().unwrap_or(""));
    }
    Err(e) => {
        // The common case: one or more field-level rule violations.
        for v in &e.violations {
            tracing::debug!(field = %v.field_path, message = %v.message);
        }
    }
}

Conformance

2872 / 2872 (100%) — all cases in the upstream protovalidate-conformance harness pass, covering proto2, proto3, and editions 2023. Nothing regressed.


Installation

Library consumers

[dependencies]
protovalidate-buffa = "0.5.1"

Enable the connect feature (on by default) to get ValidationError::into_connect_error and the #[connect_impl] macro.

Codegen plugin

cargo install \
  --git https://github.com/mathematic-inc/protovalidate-buffa \
  --tag v0.5.1 \
  protoc-gen-protovalidate-buffa

Then wire it into your buf.gen.yaml:

plugins:
  - local: protoc-gen-protovalidate-buffa
    out: gen/protovalidate
    strategy: all

Dual-licensed Apache-2.0 / MIT.