Expand description
The rule every list filter on this listener shares: a control left at its “any” option is not a filter for the empty string.
An HTML <select> inside a submitted form always contributes its name, so
<option value="">every profile</option> arrives as profile= rather than
as an omitted key, and serde_urlencoded deserializes that into Some("").
Every predicate builder below then honours it — AND profile = '' matches
no row, and a status= reaches acme_proxy_store::status, which refuses an
unknown spelling by name and turns the page into a 400. The CLI never sees
this shape at all: clap yields None for an omitted --profile, which is
why order list --expiring-in was right where /ui/expiring was empty.
Normalizing here rather than in the model layer is deliberate. This is the
boundary that produces the empty string, and it is already the boundary
that strips it back out: [crate::webadmin::pages::pager] drops an empty
filter when it assembles the previous/next URLs. A guard in
push_predicates would be a second definition of the same rule, sitting
where nothing in the query string can be seen.