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.

Expand handle conflict differential coverage

alice d9aac332 70188765

+47
+1
docs/TEST_AUDIT.md
··· 53 53 - perlsky intentionally still allows test-friendly no-email local accounts, but once an email is supplied `com.atproto.server.createAccount` now follows the same unsupported-syntax rejection shape as `updateEmail` and the official runtime. 54 54 - `com.atproto.server.createAccount` must not turn duplicate-email requests into a `500`; it now follows the official client-visible `400 InvalidRequest` / `Email already taken: ...` shape instead. 55 55 - Local handle-conflict flows now use the reference runtime’s client-visible `400 InvalidRequest` / `Handle already taken: ...` shape on `createAccount`, `com.atproto.identity.updateHandle`, and `com.atproto.admin.updateAccountHandle`, instead of the older local `HandleNotAvailable` variant. 56 + - The executable differential harness now proves that handle-conflict shape directly for both user and admin handle-update flows, not just local regression tests. 56 57 - `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. 57 58 - `com.atproto.identity.resolveHandle` should reject malformed handles with `400 InvalidRequest`, not quietly treat them as misses or return a local `InvalidHandle` variant. 58 59 - `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`.
+46
script/differential-validate
··· 560 560 if $diff_account_did_method eq 'did:plc'; 561 561 } 562 562 563 + note('Creating secondary accounts for conflict checks'); 564 + for my $name (sort keys %server) { 565 + my $res = post_json($server{$name}{origin}, 'com.atproto.server.createAccount', { 566 + handle => $name eq 'reference' ? 'bob-ref.test' : 'bob-perl.test', 567 + email => $name eq 'reference' ? 'bob-ref@test.com' : 'bob-perl@test.com', 568 + password => 'hunter22', 569 + }); 570 + check($res->is_success, "$name secondary createAccount succeeds"); 571 + next unless $res->is_success; 572 + my $json = $res->json || {}; 573 + $server{$name}{secondary_did} = $json->{did}; 574 + $server{$name}{secondary_handle} = $json->{handle}; 575 + } 576 + 563 577 note('Comparing account password boundary semantics'); 564 578 for my $name (sort keys %server) { 565 579 my $too_long_create = post_json($server{$name}{origin}, 'com.atproto.server.createAccount', { ··· 610 624 fail_check('account password boundary and reset-email semantics match the official reference PDS'); 611 625 } else { 612 626 pass('account password boundary and reset-email semantics match the official reference PDS'); 627 + } 628 + 629 + note('Comparing handle conflict semantics'); 630 + for my $name (sort keys %server) { 631 + my $duplicate_identity_handle = post_json( 632 + $server{$name}{origin}, 633 + 'com.atproto.identity.updateHandle', 634 + { handle => $server{$name}{secondary_handle} }, 635 + auth_header($server{$name}{access}), 636 + ); 637 + my $duplicate_admin_handle = post_json( 638 + $server{$name}{origin}, 639 + 'com.atproto.admin.updateAccountHandle', 640 + { 641 + did => $server{$name}{did}, 642 + handle => $server{$name}{secondary_handle}, 643 + }, 644 + admin_auth_header($server{$name}{admin_password}), 645 + ); 646 + 647 + $server{$name}{handle_conflicts} = { 648 + identity_update_dup => normalize_xrpc_error($duplicate_identity_handle), 649 + admin_update_dup => normalize_xrpc_error($duplicate_admin_handle), 650 + }; 651 + } 652 + 653 + if (!same_hash($server{reference}{handle_conflicts}, $server{perlsky}{handle_conflicts})) { 654 + note('reference handle conflicts: ' . encode_json($server{reference}{handle_conflicts})); 655 + note('perlsky handle conflicts: ' . encode_json($server{perlsky}{handle_conflicts})); 656 + fail_check('handle conflict update semantics match the official reference PDS'); 657 + } else { 658 + pass('handle conflict update semantics match the official reference PDS'); 613 659 } 614 660 615 661 note('Comparing resolveHandle');