Finding
Paroche's route modules repeatedly redefine the same transport-neutral support primitives instead of consuming one crate-owned implementation. The largest families are pagination DTOs and database-UUID projection, with smaller exact copies for constant-time secret comparison, token extraction, JSON test requests, and XML escaping.
These are not domain-specific route rules. Each copy exists only because the helper was declared inside the first endpoint file that needed it.
Verified against main 65644113e47814c87eaba14a6f322820974b8780.
Evidence
PaginationQuery is defined independently in 10 route modules: audiobook, wanted, podcast, comic, indexer, book, tv, news, music, and movie. Each carries the same page/per-page shape and default semantics.
bytes_to_uuid_str is byte-equivalent in 12 locations across Paroche routes plus OPDS catalog: it runs Uuid::from_slice, warns on malformed database bytes, and returns an empty string on failure.
routes/kosync.rs:14-21 and subsonic/auth.rs:11-18 each define the same constant_time_str_eq implementation with subtle::ConstantTimeEq; only the comment's expected digest length differs.
routes/curation.rs:151 and routes/plex.rs:153 duplicate the same user_token helper; other route-local test/request helpers show the same pattern (json_request in podcast/news, body_json in podcast/indexer).
subsonic/types.rs:29-34 and opds/types_v1.rs:29-34 independently implement the same XML escaping transform.
No open issue currently owns this Paroche-internal utility duplication. The correction can stay entirely inside Paroche; it does not require a new fleet/shared crate.
Why this matters
These helpers encode common API behavior: pagination defaults, malformed-ID handling, constant-time comparison, response escaping, and test request construction. A route added or corrected in isolation can silently acquire different behavior from its siblings because there is no canonical primitive to import.
The 12 identical UUID helpers are especially strong evidence that endpoint-local placement has stopped buying locality: the same error policy is now spread across most of the serving surface.
Desired correction
Create a small Paroche support surface for genuinely shared route mechanics rather than a generic framework. Move pagination, database-UUID projection, constant-time string comparison, and XML escaping there; consolidate the repeated token/test-request helpers where their contracts are actually identical.
Keep domain request/response DTOs and authorization decisions in their owning endpoint modules. The goal is one owner for mechanics, not one mega-router abstraction.
Done when:
- the default pagination DTO/normalization has one definition used by every applicable route;
- database UUID bytes have one projection/error policy;
- constant-time string comparison is implemented once in Paroche;
- Subsonic and OPDS use one XML escaping primitive;
- exact token/test-request helpers are shared where their semantics match; and
- a source scan no longer finds route-local copies of those primitives.
Finding
Paroche's route modules repeatedly redefine the same transport-neutral support primitives instead of consuming one crate-owned implementation. The largest families are pagination DTOs and database-UUID projection, with smaller exact copies for constant-time secret comparison, token extraction, JSON test requests, and XML escaping.
These are not domain-specific route rules. Each copy exists only because the helper was declared inside the first endpoint file that needed it.
Verified against
main65644113e47814c87eaba14a6f322820974b8780.Evidence
PaginationQueryis defined independently in 10 route modules: audiobook, wanted, podcast, comic, indexer, book, tv, news, music, and movie. Each carries the same page/per-page shape and default semantics.bytes_to_uuid_stris byte-equivalent in 12 locations across Paroche routes plus OPDS catalog: it runsUuid::from_slice, warns on malformed database bytes, and returns an empty string on failure.routes/kosync.rs:14-21andsubsonic/auth.rs:11-18each define the sameconstant_time_str_eqimplementation withsubtle::ConstantTimeEq; only the comment's expected digest length differs.routes/curation.rs:151androutes/plex.rs:153duplicate the sameuser_tokenhelper; other route-local test/request helpers show the same pattern (json_requestin podcast/news,body_jsonin podcast/indexer).subsonic/types.rs:29-34andopds/types_v1.rs:29-34independently implement the same XML escaping transform.No open issue currently owns this Paroche-internal utility duplication. The correction can stay entirely inside Paroche; it does not require a new fleet/shared crate.
Why this matters
These helpers encode common API behavior: pagination defaults, malformed-ID handling, constant-time comparison, response escaping, and test request construction. A route added or corrected in isolation can silently acquire different behavior from its siblings because there is no canonical primitive to import.
The 12 identical UUID helpers are especially strong evidence that endpoint-local placement has stopped buying locality: the same error policy is now spread across most of the serving surface.
Desired correction
Create a small Paroche support surface for genuinely shared route mechanics rather than a generic framework. Move pagination, database-UUID projection, constant-time string comparison, and XML escaping there; consolidate the repeated token/test-request helpers where their contracts are actually identical.
Keep domain request/response DTOs and authorization decisions in their owning endpoint modules. The goal is one owner for mechanics, not one mega-router abstraction.
Done when: