fix(nip05): allow hyphens and periods in usernames per NIP-05 spec
NIP-05 spec states local-part MUST only use characters a-z0-9-_. The previous regex /^[a-z][a-z0-9_]*$/ rejected hyphens and periods. Updated to /^[a-z][a-z0-9._-]*[a-z0-9]$/ and added support for the root identifier "_" (_@domain) as described in the spec. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a5cf1d8ceb
commit
4191bb11f4
1 changed files with 13 additions and 5 deletions
|
|
@ -55,10 +55,12 @@ function generateId(): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate username format
|
* Validate username format per NIP-05 spec
|
||||||
* - Lowercase alphanumeric and underscore only
|
* - Characters allowed: a-z, 0-9, hyphen (-), underscore (_), period (.)
|
||||||
* - Must start with a letter
|
* - Must start with a letter
|
||||||
|
* - Must not end with a hyphen, underscore, or period
|
||||||
* - Length within bounds
|
* - Length within bounds
|
||||||
|
* - Special case: "_" alone is the root identifier (_@domain)
|
||||||
*/
|
*/
|
||||||
function validateUsername(username: string, config: Required<Nip05Config>): UsernameValidation {
|
function validateUsername(username: string, config: Required<Nip05Config>): UsernameValidation {
|
||||||
if (!username) {
|
if (!username) {
|
||||||
|
|
@ -67,6 +69,11 @@ function validateUsername(username: string, config: Required<Nip05Config>): User
|
||||||
|
|
||||||
const normalized = username.toLowerCase().trim()
|
const normalized = username.toLowerCase().trim()
|
||||||
|
|
||||||
|
// Special case: root identifier "_" per NIP-05
|
||||||
|
if (normalized === '_') {
|
||||||
|
return { valid: true }
|
||||||
|
}
|
||||||
|
|
||||||
if (normalized.length < config.min_username_length) {
|
if (normalized.length < config.min_username_length) {
|
||||||
return { valid: false, error: `Username must be at least ${config.min_username_length} character(s)` }
|
return { valid: false, error: `Username must be at least ${config.min_username_length} character(s)` }
|
||||||
}
|
}
|
||||||
|
|
@ -75,9 +82,10 @@ function validateUsername(username: string, config: Required<Nip05Config>): User
|
||||||
return { valid: false, error: `Username must be at most ${config.max_username_length} characters` }
|
return { valid: false, error: `Username must be at most ${config.max_username_length} characters` }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only lowercase letters, numbers, and underscores
|
// NIP-05 spec: local-part MUST only use characters a-z0-9-_.
|
||||||
if (!/^[a-z][a-z0-9_]*$/.test(normalized)) {
|
// Must start with a letter, must not end with separator
|
||||||
return { valid: false, error: 'Username must start with a letter and contain only lowercase letters, numbers, and underscores' }
|
if (!/^[a-z][a-z0-9._-]*[a-z0-9]$/.test(normalized) && !/^[a-z]$/.test(normalized)) {
|
||||||
|
return { valid: false, error: 'Username must start with a letter, end with a letter or number, and contain only a-z, 0-9, hyphens, underscores, and periods' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check reserved usernames
|
// Check reserved usernames
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue