feat(sdk): users::email_available for anonymous registration pre-check (S1)
`users::find_by_email` requires an authenticated principal (F-S-003, anti-enumeration), so the natural check-then-create register pattern 502s for anonymous public scripts. Add `users::email_available(email) -> bool`, gated like `create` (the registration write path) but without the anonymous rejection: it leaks only a single boolean — no more than `create`'s own uniqueness error already does — so self-serve register scripts can pre-check. Also document find_by_email's principal requirement in the SDK doc-comment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -200,6 +200,15 @@ pub trait UsersService: Send + Sync {
|
||||
email: &str,
|
||||
) -> Result<Option<AppUser>, UsersError>;
|
||||
|
||||
/// Anonymous-safe existence probe for self-serve registration.
|
||||
/// Returns `true` when the email is free to register, `false` when
|
||||
/// it's taken. Unlike [`find_by_email`](Self::find_by_email) (which
|
||||
/// requires an authenticated principal to prevent user enumeration),
|
||||
/// this leaks only a single boolean — no id, profile, or timing
|
||||
/// distinction beyond "exists / doesn't" — so a public registration
|
||||
/// script can pre-check before calling `create`.
|
||||
async fn email_available(&self, cx: &SdkCallCx, email: &str) -> Result<bool, UsersError>;
|
||||
|
||||
async fn update(
|
||||
&self,
|
||||
cx: &SdkCallCx,
|
||||
@@ -387,6 +396,9 @@ impl UsersService for NoopUsersService {
|
||||
) -> Result<Option<AppUser>, UsersError> {
|
||||
Err(UsersError::Backend(NOOP_MSG.into()))
|
||||
}
|
||||
async fn email_available(&self, _cx: &SdkCallCx, _email: &str) -> Result<bool, UsersError> {
|
||||
Err(UsersError::Backend(NOOP_MSG.into()))
|
||||
}
|
||||
async fn update(
|
||||
&self,
|
||||
_cx: &SdkCallCx,
|
||||
|
||||
Reference in New Issue
Block a user