diff --git a/server/src/lib/validators.test.ts b/server/src/lib/validators.test.ts
index faaae3b..86113b4 100644
--- a/server/src/lib/validators.test.ts
+++ b/server/src/lib/validators.test.ts
@@ -360,3 +360,54 @@ describe('attack inputs', () => {
expect(httpUrlSchema.safeParse('data:text/html,
hi
').success).toBe(false)
})
})
+
+describe('auth & registration edge cases', () => {
+ it('unicode bot name rejected', () => {
+ expect(botNameSchema.safeParse('ビットコイン').success).toBe(false)
+ expect(botNameSchema.safeParse('café').success).toBe(false)
+ expect(botNameSchema.safeParse('bot🚀').success).toBe(false)
+ expect(botNameSchema.safeParse('böt').success).toBe(false)
+ })
+
+ it('bot name with spaces rejected', () => {
+ expect(botNameSchema.safeParse('my bot').success).toBe(false)
+ })
+
+ it('bot name with special chars rejected', () => {
+ expect(botNameSchema.safeParse('bot!@#').success).toBe(false)
+ expect(botNameSchema.safeParse('bot.name').success).toBe(false)
+ expect(botNameSchema.safeParse('bot/name').success).toBe(false)
+ })
+
+ it('valid bot names accepted', () => {
+ expect(botNameSchema.safeParse('SatoshiBot').success).toBe(true)
+ expect(botNameSchema.safeParse('bot-1').success).toBe(true)
+ expect(botNameSchema.safeParse('bot_2').success).toBe(true)
+ expect(botNameSchema.safeParse('A1').success).toBe(true)
+ })
+
+ it('two bots with same webhook URL: both pass validation (uniqueness enforced at DB level)', () => {
+ const pub1 = 'a'.repeat(64)
+ const pub2 = 'b'.repeat(64)
+ const sharedUrl = 'https://example.com/webhook'
+ const r1 = registerSchema.safeParse({ pubkey: pub1, name: 'Bot1', webhookUrl: sharedUrl })
+ const r2 = registerSchema.safeParse({ pubkey: pub2, name: 'Bot2', webhookUrl: sharedUrl })
+ expect(r1.success).toBe(true)
+ expect(r2.success).toBe(true)
+ // Note: same webhook URL is allowed — uniqueness is on name, not URL
+ })
+
+ it('pubkey must be exactly 64 hex chars', () => {
+ expect(pubkeySchema.safeParse('a'.repeat(63)).success).toBe(false) // too short
+ expect(pubkeySchema.safeParse('a'.repeat(65)).success).toBe(false) // too long
+ expect(pubkeySchema.safeParse('g'.repeat(64)).success).toBe(false) // non-hex
+ expect(pubkeySchema.safeParse('A'.repeat(64)).success).toBe(false) // uppercase (not lowercase hex)
+ expect(pubkeySchema.safeParse('a'.repeat(64)).success).toBe(true) // valid
+ })
+
+ it('register rejects missing required fields', () => {
+ expect(registerSchema.safeParse({}).success).toBe(false)
+ expect(registerSchema.safeParse({ pubkey: 'a'.repeat(64) }).success).toBe(false) // missing name
+ expect(registerSchema.safeParse({ name: 'Bot1' }).success).toBe(false) // missing pubkey
+ })
+})