fix: address Phase 2 code review feedback
## Critical Issues
C1: resolve_handle was calling dns.txt_lookup() twice. Changed to call once
via match expression, capturing error for fallback path.
C2: resolve_handle silently swallowed non-200 HTTPS responses. Now constructs
HandleHttpFallbackFailed error for all non-200 responses.
C3: resolve_handle accepted empty/whitespace body as valid DID. Added validation
to require body starts with "did:" prefix.
C4: percent_decode_str corrupted non-ASCII UTF-8. Replaced home-rolled decoder
with percent_encoding crate which properly handles UTF-8.
C5: find_service had wrong matcher pattern and used unanchored ends_with causing
false-positives. Changed to extract fragment after '#' and compare exactly.
Added test case covering false-positive scenario.
C6: parse_multikey_wrong_length test had catch-all that prevented test failure.
Changed to strictly assert MultikeyLengthInvalid variant.
## Important Issues
I1: parse_multikey_k256/p256 tests now include hex literal comparison against
actual decoded SEC1 bytes.
I2: resolve_did now documents that did:plc identifiers are URL-safe without
requiring additional percent-encoding.
I3: HttpTransport error variant now uses typed reqwest::Error via #[from]
instead of opaque Box<dyn Error>, enabling downstream typed matching.
I4: RealDnsResolver now uses dedicated DnsBackend variant for hickory errors
instead of wrapping in HttpTransport. Added debug logging for non-UTF-8
TXT record data instead of silent unwrap_or_default.
I5: RealHttpClient explicitly calls .use_rustls_tls() on builder with comment
documenting the rustls feature usage.
I6: RealHttpClient now sets User-Agent header "atproto-devtool/0.0.0" on all
HTTPS requests.
I7: Added AnyVerifyingKey::verify_prehash() helper that dispatches to
curve-specific implementations. Includes AnySignature enum and
AnySignatureError for result types. Added three tests covering k256,
p256, and curve-mismatch cases.
## Minor Issues
M1: Fixed fully-qualified std::fmt::Display to use fmt::Display after
importing std::fmt.
M3: Removed double z-prefix in multikey tests (multibase::encode already
returns z-prefixed string for Base58Btc).
## Dependencies
- Added percent-encoding 2.3 to [dependencies] for proper percent-decoding.
All tests pass (16 total). No clippy warnings. Format verified.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>