···1313The current baseline for saying "the audited suite is green" is:
14141515- `prove -lr t`
1616- - latest full green result in the realigned Meridian worktree: `Files=48, Tests=2926`
1616+ - latest full green result in the realigned Meridian worktree: `Files=48, Tests=2943`
1717- `prove -lv t/server-auth.t`
1818- `perl -c script/differential-validate`
1919- `PERLSKY_RUN_REFERENCE_DIFF=1 prove -lv t/reference-differential.t`
···5252- `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.
5353- 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.
5454- `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.
5555+- 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.
5556- `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.
5657- `com.atproto.identity.resolveHandle` should reject malformed handles with `400 InvalidRequest`, not quietly treat them as misses or return a local `InvalidHandle` variant.
5758- `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`.
+1-1
lib/ATProto/PDS/API/Admin.pm
···145145 unless defined $resolved_did && lc($resolved_did) eq lc($account->{did});
146146 }
147147 my $existing = $c->store->get_account_by_handle($handle);
148148- xrpc_error(400, 'HandleNotAvailable', 'That handle is already registered')
148148+ xrpc_error(400, 'InvalidRequest', "Handle already taken: $handle")
149149 if $existing && ($existing->{did} // q()) ne $account->{did};
150150 my $updated = $c->store->update_account(
151151 $account->{did},
+1-1
lib/ATProto/PDS/API/Misc.pm
···180180 unless defined $resolved_did && lc($resolved_did) eq lc($account->{did});
181181 }
182182 my $existing = $c->store->get_account_by_handle($handle);
183183- xrpc_error(400, 'HandleNotAvailable', 'That handle is already registered')
183183+ xrpc_error(400, 'InvalidRequest', "Handle already taken: $handle")
184184 if $existing && ($existing->{did} // q()) ne $account->{did};
185185 xrpc_error(400, 'HandleNotAvailable', 'That handle is reserved')
186186 if $c->store->get_reserved_handle($handle);
+1-1
lib/ATProto/PDS/API/Server.pm
···6767 my $domain = $c->config_value('service_handle_domain', 'localhost');
6868 my $handle = normalize_handle($body->{handle}, $domain);
6969 xrpc_error(400, 'InvalidHandle', 'Requested handle is invalid') unless defined $handle;
7070- xrpc_error(400, 'HandleNotAvailable', 'That handle is already registered')
7070+ xrpc_error(400, 'InvalidRequest', "Handle already taken: $handle")
7171 if $c->store->get_account_by_handle($handle);
7272 xrpc_error(400, 'HandleNotAvailable', 'That handle is reserved')
7373 if $c->store->get_reserved_handle($handle);