perlsky is a Perl 5 implementation of an AT Protocol Personal Data Server.
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

Align resolveHandle miss semantics with reference

alice 09d5739a 2e0c5946

+21 -5
+1
docs/TEST_AUDIT.md
··· 51 51 - Account email handling needs consistent normalization on write, lookup, session creation, and confirmation checks; treating email case inconsistently leaves both tests and user-facing auth behavior brittle. 52 52 - `app.bsky.actor.putPreferences` and `app.bsky.notification.putPreferencesV2` now have explicit shape validation plus focused regression coverage, turning an earlier hardening concern into a pinned contract. 53 53 - `com.atproto.identity.resolveHandle` should reject malformed handles with `400 InvalidHandle`, not quietly treat them as misses. 54 + - `com.atproto.identity.resolveHandle` should treat well-formed but unresolved handles as `400 InvalidRequest` with `Unable to resolve handle`, matching the official runtime instead of returning a local `404 HandleNotFound`. 54 55 - Remote `did:web` DID docs, conservative `resolveIdentity` handle validation, and external handle adoption all need explicit coverage because small resolver-policy drifts turn into visible interop bugs quickly. 55 56 - Remote `did:plc` DID docs should resolve through the PLC directory defaults even when `plc_url` is not explicitly configured; gating that path on local config silently breaks federated identity lookups. 56 57 - `com.atproto.repo.getRecord` must honor `cid` when present, and `putRecord` / `deleteRecord` must actually enforce `swapRecord`; those negative edges are now covered directly.
+3 -3
lib/ATProto/PDS/API/Builtins.pm
··· 74 74 } 75 75 76 76 die { 77 - status => 404, 78 - error => 'HandleNotFound', 79 - message => "No DID found for handle $handle", 77 + status => 400, 78 + error => 'InvalidRequest', 79 + message => 'Unable to resolve handle', 80 80 }; 81 81 }); 82 82
+14
script/differential-validate
··· 560 560 check(($res->json->{did} // q()) eq $server{$name}{did}, "$name resolveHandle returns the created DID"); 561 561 } 562 562 563 + for my $name (sort keys %server) { 564 + my $res = get_form( 565 + $server{$name}{origin}, 566 + 'com.atproto.identity.resolveHandle', 567 + { handle => 'missing.test' }, 568 + ); 569 + $server{$name}{resolve_handle_missing} = normalize_xrpc_error($res); 570 + } 571 + 572 + check( 573 + same_hash($server{reference}{resolve_handle_missing}, $server{perlsky}{resolve_handle_missing}), 574 + 'resolveHandle missing-handle semantics match the official reference PDS', 575 + ); 576 + 563 577 note('Comparing subscribeRepos bootstrap backfill'); 564 578 for my $name (sort keys %server) { 565 579 my $frames = frames_until_quiet("$server{$name}{origin}/xrpc/com.atproto.sync.subscribeRepos?cursor=0");
+3 -2
t/remote-handle-resolution.t
··· 129 129 ->json_is('/did' => $remote_did); 130 130 131 131 $t->get_ok('/xrpc/com.atproto.identity.resolveHandle?handle=missing.example.test') 132 - ->status_is(404) 133 - ->json_is('/error' => 'HandleNotFound'); 132 + ->status_is(400) 133 + ->json_is('/error' => 'InvalidRequest') 134 + ->json_is('/message' => 'Unable to resolve handle'); 134 135 } 135 136 136 137 $t->get_ok("/xrpc/com.atproto.identity.resolveDid?did=$remote_did_web")