A better Rust ATProto crate

made handle parsing more permissive in specific 'invalid.handle' case

Orual b65973b5 055e547e

Changed files
+20 -4
crates
jacquard-common
src
+1 -1
CHANGELOG.md
··· 27 27 28 28 ### Changed 29 29 30 - - Import cleanup across all crates 31 30 - Dependency updates (upgraded various crypto and serialization dependencies) 32 31 - Documentation improvements throughout 32 + - Made handle parsing a bit more permissive for a common case ('handle.invalid' when someone has a messed up handle), added a method to confirm syntactic validity (the correct way to confirm validity is resolve_handle() from IdentityResolver, and comparing to the DID document). 33 33 34 34 ## [0.7.0] - 2025-10-19 35 35
+3 -1
README.md
··· 16 16 - repository CAR file read/write support 17 17 - CAR file write order compatible with streaming mode from the [sync iteration proposal](https://github.com/bluesky-social/proposals/blob/main/0006-sync-iteration/README.md#streaming-car-processing) 18 18 - Big rewrite of all the errors in the crate, improvements to context and overall structure 19 + - Made handle parsing a bit more permissive for a common case ('handle.invalid' when someone has a messed up handle), added a method to confirm syntactic validity (the correct way to confirm validity is resolve_handle() from the IdentityResolver trait, then fetching and comparing to the DID document). 19 20 20 21 > [!WARNING] 21 22 > A lot of the streaming code is still pretty experimental. The examples work, though.\ 22 - The modules are also less well-documented, and don't have code examples. There are also a lot of utility functions for conveniently working with the streams and transforming them which are lacking. Use [`n0-future`](https://docs.rs/n0-future/latest/n0_future/index.html) to work with them, that is what Jacquard uses internally as much as possible. I would also note the same for the repository crate until I've had more third parties test it. 23 + The modules are also less well-documented, and don't have code examples. There are also a lot of utility functions for conveniently working with the streams and transforming them which are lacking. Use [`n0-future`](https://docs.rs/n0-future/latest/n0_future/index.html) to work with them, that is what Jacquard uses internally as much as possible.\ 24 + >I would also note the same for the repository crate until I've had more third parties test it. 23 25 24 26 ### Changelog 25 27
+1 -1
crates/jacquard-common/src/types.rs
··· 47 47 pub const DISALLOWED_TLDS: &[&str] = &[ 48 48 ".local", 49 49 ".arpa", 50 - ".invalid", 50 + ".invalid", // NOTE: if someone has a screwed up handle, this is what's returned 51 51 ".localhost", 52 52 ".internal", 53 53 ".example",
+15 -1
crates/jacquard-common/src/types/handle.rs
··· 58 58 SmolStr::new_static("invalid"), 59 59 )) 60 60 } else if ends_with(stripped, DISALLOWED_TLDS) { 61 - Err(AtStrError::disallowed("handle", stripped, DISALLOWED_TLDS)) 61 + // speicifically pass this through as it is returned in instances where someone 62 + // has screwed up their handle, and it's awkward to fail so early 63 + if handle == "handle.invalid" { 64 + Ok(Self(CowStr::Borrowed(stripped))) 65 + } else { 66 + Err(AtStrError::disallowed("handle", stripped, DISALLOWED_TLDS)) 67 + } 62 68 } else { 63 69 Ok(Self(CowStr::Borrowed(stripped))) 64 70 } 71 + } 72 + 73 + /// confirm that this is a (syntactically) valid handle (as we pass-through 74 + /// "handle.invalid" during construction) 75 + pub fn is_valid(&self) -> bool { 76 + self.0.len() <= 253 77 + && HANDLE_REGEX.is_match(&self.0) 78 + && !ends_with(&self.0, DISALLOWED_TLDS) 65 79 } 66 80 67 81 /// Fallible constructor, validates, takes ownership