Musl is tier 2 on rust support, and glibc is tier 1.
https://doc.rust-lang.org/nightly/rustc/platform-support.html
Generally, glibc rust is reported to be more performant. Could vary due
to any other reason, but in my testing, builds were up to 50% faster
(for docker cross-compilation amd64->arm64 at least).
Collapse the three ad-hoc short-code generators into one canonical generator
plus a shared normalizer:
- util::generate_token_code now emits the uppercase base32 XXXXX-XXXXX display
form; new util::normalize_token_code canonicalizes user input (uppercase,
strip hyphen/whitespace).
- email_token and legacy_2fa now generate via util, store the normalized form,
and compare normalized input. Their private generate_short_token/generate_code
(and BASE32_CHARS/CODE_LENGTH) are removed.
- PLC (request/sign) and password reset inline util::generate_token_code,
persist the normalized form, email the display form, and normalize input
before lookup. The generate_plc_token/generate_reset_code wrappers are removed.
Behavior changes: legacy login-2FA codes go from 8-digit numeric to XXXXX-XXXXX;
PLC and password-reset codes go from lowercase to uppercase. All four code types
are now accepted case-/hyphen-insensitively. OAuth web-login 2FA, account
deletion, and the long verification_token blobs are intentionally untouched.
Tests: add util normalize tests + email_token/legacy_2fa case/hyphen tests;
update integration tests to expect the canonical stored form and the new
emailed format.
RFC 7519 §5.1 recommends the uppercase "JWT" typ for compatibility with
legacy implementations, and it matches the reference @atproto/pds. Parsing
already lowercases, so existing lowercase "jwt" tokens still verify.
Permission-set expansion resolved the lexicon's DNS authority using a
fixed `parts[..2]`, which only works for three-segment NSIDs. For a
four-segment NSID such as community.lexicon.bookmarks.authManageBookmarks
this dropped a segment and queried _lexicon.lexicon.community instead of
_lexicon.bookmarks.lexicon.community, failing with "DNS resolution
failed: ... no record found".
The authority is every NSID segment except the last (the name),
reversed. Use parts[..parts.len() - 1] to match the spec and the
existing extract_namespace_authority helper, and update the DNS
authority test with three/four-segment and bookmarks regression cases.