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.

Validate supplied createAccount emails

alice 2b302427 c918be30

+24 -3
+2 -1
docs/TEST_AUDIT.md
··· 13 13 The current baseline for saying "the audited suite is green" is: 14 14 15 15 - `prove -lr t` 16 - - latest full green result in the realigned Meridian worktree: `Files=48, Tests=2918` 16 + - latest full green result in the realigned Meridian worktree: `Files=48, Tests=2922` 17 17 - `prove -lv t/server-auth.t` 18 18 - `perl -c script/differential-validate` 19 19 - `PERLSKY_RUN_REFERENCE_DIFF=1 prove -lv t/reference-differential.t` ··· 50 50 - Local `app.bsky.*` emulation must be conservative: only synthesize owner-local feed/thread data when the PDS can answer authoritatively, and proxy upstream instead of inventing partial global state. 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 - `com.atproto.server.requestEmailConfirmation`, `requestEmailUpdate`, and `requestAccountDelete` should reject accounts with no stored email using the official `400 InvalidRequest` / `account does not have an email address` shape, and `updateEmail` should reject unsupported syntax with the official `This email address is not supported, please use a different email.` message. 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. 53 54 - `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. 54 55 - `com.atproto.identity.resolveHandle` should reject malformed handles with `400 InvalidRequest`, not quietly treat them as misses or return a local `InvalidHandle` variant. 55 56 - `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`.
+8 -2
lib/ATProto/PDS/API/Server.pm
··· 77 77 if length($password) < 8; 78 78 xrpc_error(400, 'InvalidRequest', "Password too long. Maximum length is $NEW_PASSWORD_MAX_LENGTH characters.") 79 79 if length($password) > $NEW_PASSWORD_MAX_LENGTH; 80 + my $email = undef; 81 + if (defined($body->{email}) && length($body->{email})) { 82 + $email = _supported_email($body->{email}); 83 + xrpc_error(400, 'InvalidRequest', 'This email address is not supported, please use a different email.') 84 + unless defined $email; 85 + } 80 86 81 87 my $invite; 82 88 if (defined($body->{inviteCode}) && length($body->{inviteCode})) { ··· 135 141 account_id => $account_id, 136 142 did => $did, 137 143 handle => $handle, 138 - email => $body->{email}, 139 - email_confirmed_at => _initial_email_confirmed_at($c, $body->{email}), 144 + email => $email, 145 + email_confirmed_at => _initial_email_confirmed_at($c, $email), 140 146 password_hash => $password_record->{hash}, 141 147 password_salt => $password_record->{salt}, 142 148 deactivated_at => $deactivated_at,
+6
script/differential-validate
··· 567 567 email => "toolong-$name-" . substr(random_hex(3), 0, 6) . '@test.com', 568 568 password => ('x' x 257), 569 569 }); 570 + my $invalid_email_create = post_json($server{$name}{origin}, 'com.atproto.server.createAccount', { 571 + handle => "bademail-$name-" . substr(random_hex(3), 0, 6), 572 + email => 'not-an-email', 573 + password => 'hunter22', 574 + }); 570 575 my $too_long_session = post_json($server{$name}{origin}, 'com.atproto.server.createSession', { 571 576 identifier => $server{$name}{handle}, 572 577 password => ('x' x 513), ··· 577 582 578 583 $server{$name}{password_boundaries} = { 579 584 create_too_long => normalize_xrpc_error($too_long_create), 585 + create_bad_email => normalize_xrpc_error($invalid_email_create), 580 586 session_too_long => normalize_xrpc_error($too_long_session), 581 587 reset_uppercase => { 582 588 status => $password_reset_upper->code // 0,
+8
t/app.t
··· 90 90 ->json_is('/error' => 'InvalidRequest') 91 91 ->json_is('/message' => 'Password too long. Maximum length is 256 characters.'); 92 92 93 + $fresh->post_ok('/xrpc/com.atproto.server.createAccount' => json => { 94 + handle => 'bademail.localhost', 95 + email => 'not-an-email', 96 + password => 'hunter22', 97 + })->status_is(400) 98 + ->json_is('/error' => 'InvalidRequest') 99 + ->json_is('/message' => 'This email address is not supported, please use a different email.'); 100 + 93 101 $fresh->get_ok("/xrpc/com.atproto.identity.resolveHandle?handle=alice.localhost") 94 102 ->status_is(200) 95 103 ->json_is('/did' => $user_did);