Follow-up from #3418 (the GH-3380 OpenAPI work), which fixed the general "derive parameters from the full binding chain" problem but explicitly does not close this one.
The shape
[AggregateHandler]
[WolverinePost("/orders/{id}/confirm")]
public static OrderConfirmed Handle(ConfirmOrder command, Order order) { ... }
The route has no constraint ({id}, not {id:guid}), and id appears nowhere in the handler's method signature — it's bound by the Marten aggregate frame, which resolves during codegen.
Result: the OpenAPI operation declares id as string rather than uuid.
Why #3418's fix doesn't reach it
#3418 resolves a route parameter's type as: route variable → binding chain → route constraint → string. For this shape all four rungs come up empty of type information — the binding happens inside a Marten-specific frame, and the id's real type (Guid, or a strongly-typed id) is Marten domain knowledge that Wolverine.Http cannot infer from method signatures. It correctly falls back to string.
Adding the constraint ({id:guid}) fixes it today, so there's a clean workaround, and the parameter is declared — it's the type that's wrong, not the presence. That's why this is a follow-up and not a blocker.
Direction
Wolverine.Http.Marten knows the aggregate's identity type. The fix probably belongs there — a seam letting the aggregate frame contribute its bound route parameter's CLR type back to the chain's ApiDescription, rather than Wolverine.Http trying to guess.
Now cheaply testable: the shape-test harness added in #3418 (src/Http/Wolverine.Http.Tests/openapi_shape_tests.cs) renders the real OpenAPI document without starting a host, so this is one endpoint plus one [Fact].
Refs #3380, #3418.
Follow-up from #3418 (the GH-3380 OpenAPI work), which fixed the general "derive parameters from the full binding chain" problem but explicitly does not close this one.
The shape
The route has no constraint (
{id}, not{id:guid}), andidappears nowhere in the handler's method signature — it's bound by the Marten aggregate frame, which resolves during codegen.Result: the OpenAPI operation declares
idasstringrather thanuuid.Why #3418's fix doesn't reach it
#3418 resolves a route parameter's type as: route variable → binding chain → route constraint →
string. For this shape all four rungs come up empty of type information — the binding happens inside a Marten-specific frame, and the id's real type (Guid, or a strongly-typed id) is Marten domain knowledge thatWolverine.Httpcannot infer from method signatures. It correctly falls back tostring.Adding the constraint (
{id:guid}) fixes it today, so there's a clean workaround, and the parameter is declared — it's the type that's wrong, not the presence. That's why this is a follow-up and not a blocker.Direction
Wolverine.Http.Martenknows the aggregate's identity type. The fix probably belongs there — a seam letting the aggregate frame contribute its bound route parameter's CLR type back to the chain's ApiDescription, rather thanWolverine.Httptrying to guess.Now cheaply testable: the shape-test harness added in #3418 (
src/Http/Wolverine.Http.Tests/openapi_shape_tests.cs) renders the real OpenAPI document without starting a host, so this is one endpoint plus one[Fact].Refs #3380, #3418.