Issue Description
Most inbound API payloads must reject empty strings and empty collections at the boundary. Current types allow deserialising empty strings/vectors, pushing validation deeper into business logic. We need a consistent, centralised approach so inputs fail fast (e.g. Url-like deserialisation error) and lists are guaranteed non-empty (e.g. via nonempty crate).
Options Comparison
| Scope |
Approach |
Pros |
Cons |
| Deserialisation layer |
Custom serde validators / newtypes (NonEmptyString, TrimmedNonEmptyString) and #[serde(deserialize_with = ...)] |
Fails fast at boundary; keeps invariants in types; minimal call-site changes |
Requires newtype coverage of all string fields; migration effort |
| Collection enforcement |
nonempty::NonEmpty<T> for lists in request types |
Compile-time non-empty guarantee; good serde support; clear invariant in type |
Type churn on existing structs; iterator ergonomics differ slightly |
| Mixed validation |
Smart constructors post-deserialisation |
Centralised logic; fewer type changes |
Errors shift deeper; risks partial validation |
User Story
As a client or service integrating with our APIs, I want invalid empty strings or empty lists to be rejected immediately at request parsing, so I get clear errors and the system maintains strong invariants.
Acceptance Criteria
Documentation and References
Issue Description
Most inbound API payloads must reject empty strings and empty collections at the boundary. Current types allow deserialising empty strings/vectors, pushing validation deeper into business logic. We need a consistent, centralised approach so inputs fail fast (e.g.
Url-like deserialisation error) and lists are guaranteed non-empty (e.g. vianonemptycrate).Options Comparison
serdevalidators / newtypes (NonEmptyString,TrimmedNonEmptyString) and#[serde(deserialize_with = ...)]nonempty::NonEmpty<T>for lists in request typesUser Story
As a client or service integrating with our APIs, I want invalid empty strings or empty lists to be rejected immediately at request parsing, so I get clear errors and the system maintains strong invariants.
Acceptance Criteria
Documentation and References