import { strict as assert } from 'node:assert'; import { createHash } from 'node:crypto'; import { describe, it } from 'node:test'; import { schnorr } from '@noble/curves/secp256k1.js'; import { getPublicKey, nip19, verifyEvent, type Event } from 'nostr-tools'; import { buzzWorkspaceId } from '../src/routes/buzz'; import { BuzzNotifier, decodeBuzzAuthorization, normaliseBuzzRelayUrl, parseAndVerifyBuzzAuthTag, } from '../src/services/buzz'; import { NotificationDeliveryError } from '../src/services/notifier'; import { loadConfig } from '../src/lib/config'; const AGENT_KEY = `${'0'.repeat(63)}1`; const CHANNEL = '10000000-0000-4000-8000-000000000001'; const envelope = { idempotencyKey: 'buzz:link:stage-event', destination: CHANNEL, workspaceId: 'buzz.example.com', notification: { kind: 'stage_change' as const, accountId: '20000000-0000-4000-8000-000000000002', dealId: '30000000-0000-4000-8000-000000000003', dealSide: 'demand' as const, dealName: 'Reserved H100 cluster', fromStage: 'proposal', toStage: 'procurement', changedAt: '2026-08-13T12:00:00.000Z', }, }; describe('Buzz relay identity', () => { it('normalises the WebSocket URL used by Buzz clients into its HTTP bridge community', () => { assert.equal(normaliseBuzzRelayUrl('wss://buzz.example.com/'), 'https://buzz.example.com'); assert.equal(buzzWorkspaceId('wss://buzz.example.com/'), 'buzz.example.com'); }); it('accepts official hex and nsec representations as the same identity', () => { const nsec = nip19.nsecEncode(Uint8Array.from(Buffer.from(AGENT_KEY, 'hex'))); const fromHex = new BuzzNotifier({ relayUrl: 'https://buzz.example.com', privateKey: AGENT_KEY }); const fromNsec = new BuzzNotifier({ relayUrl: 'https://buzz.example.com', privateKey: nsec }); assert.equal(fromHex.workspaceId, fromNsec.workspaceId); }); }); describe('Buzz configuration', () => { const base = { DATABASE_URL: 'postgres://pig:pig@localhost:5432/pig', NODE_ENV: 'test' }; it('requires relay and private identity together', () => { assert.throws( () => loadConfig({ ...base, BUZZ_RELAY_URL: 'https://buzz.example.com' }), /BUZZ_PRIVATE_KEY/, ); assert.throws( () => loadConfig({ ...base, BUZZ_PRIVATE_KEY: AGENT_KEY }), /BUZZ_RELAY_URL/, ); }); it('keeps the Buzz private identity in server configuration only', () => { const config = loadConfig({ ...base, BUZZ_RELAY_URL: 'https://buzz.example.com', BUZZ_PRIVATE_KEY: AGENT_KEY, }); assert.equal(config.BUZZ_RELAY_URL, 'https://buzz.example.com'); assert.equal(config.BUZZ_PRIVATE_KEY, AGENT_KEY); }); }); describe('Buzz signed delivery', () => { it('reuses the signed message event id while refreshing NIP-98 replay nonces', async () => { const requests: { event: Event; auth: Event }[] = []; let nonce = 0; const notifier = new BuzzNotifier({ relayUrl: 'https://buzz.example.com', privateKey: AGENT_KEY, now: () => new Date('2026-08-13T12:00:01.000Z'), nonce: () => `nonce-${++nonce}`, fetchImpl: async (_input, init) => { const event = JSON.parse(String(init?.body)) as Event; const headers = new Headers(init?.headers); const auth = decodeBuzzAuthorization(headers.get('authorization') ?? ''); assert.ok(auth); requests.push({ event, auth }); return Response.json({ event_id: event.id, accepted: true, message: '' }); }, }); await notifier.send(envelope); await notifier.send(envelope); await notifier.send({ ...envelope, idempotencyKey: 'buzz:link:different-event' }); assert.equal(requests[0]?.event.id, requests[1]?.event.id); assert.notEqual(requests[0]?.event.id, requests[2]?.event.id); assert.notEqual(requests[0]?.auth.id, requests[1]?.auth.id); assert.equal(requests[0]?.event.kind, 9); assert.ok(verifyEvent(requests[0]!.event)); assert.deepEqual(requests[0]?.event.tags[0], ['h', CHANNEL]); const payloadTag = requests[0]?.auth.tags.find((tag) => tag[0] === 'payload'); assert.equal( payloadTag?.[1], createHash('sha256').update(JSON.stringify(requests[0]!.event)).digest('hex'), ); }); it('refuses to route a link from another relay community', async () => { let called = false; const notifier = new BuzzNotifier({ relayUrl: 'https://buzz.example.com', privateKey: AGENT_KEY, fetchImpl: async () => { called = true; return Response.json({}); }, }); await assert.rejects( notifier.send({ ...envelope, workspaceId: 'other.example.com' }), (error: unknown) => error instanceof NotificationDeliveryError && error.code === 'buzz_workspace_mismatch' && !error.retryable, ); assert.equal(called, false); }); it('marks relay throttling retryable without exposing response content', async () => { const notifier = new BuzzNotifier({ relayUrl: 'https://buzz.example.com', privateKey: AGENT_KEY, fetchImpl: async () => new Response('{"error":"rate-limited: private detail"}', { status: 429, headers: { 'retry-after': '9' }, }), }); await assert.rejects( notifier.send(envelope), (error: unknown) => error instanceof NotificationDeliveryError && error.code === 'buzz_rate_limited' && error.retryable && error.retryAfterMs === 9_000 && !error.message.includes('private detail'), ); }); }); describe('Buzz owner attestation', () => { it('verifies NIP-OA against the configured agent before sending it', () => { const ownerKey = Uint8Array.from(Buffer.from(`${'0'.repeat(63)}2`, 'hex')); const agentPublicKey = getPublicKey(Uint8Array.from(Buffer.from(AGENT_KEY, 'hex'))); const conditions = 'kind=9'; const digest = createHash('sha256') .update(`nostr:agent-auth:${agentPublicKey}:${conditions}`) .digest(); const tag = JSON.stringify([ 'auth', getPublicKey(ownerKey), conditions, Buffer.from(schnorr.sign(digest, ownerKey)).toString('hex'), ]); assert.deepEqual(parseAndVerifyBuzzAuthTag(tag, agentPublicKey), JSON.parse(tag)); const tampered = JSON.parse(tag) as string[]; tampered[3] = `${tampered[3]![0] === '0' ? '1' : '0'}${tampered[3]!.slice(1)}`; assert.throws( () => parseAndVerifyBuzzAuthTag(JSON.stringify(tampered), agentPublicKey), /BUZZ_AUTH_TAG/, ); }); });