// check-relay-silence — verifica que Cayce NO publique a relays desde . // Uso: node check-relay-silence.mjs [horas-ventana] // Eventos permitidos: kind 10050 (inbox relays, autorizado), kind 4/1059 // (DMs AL SUPERVISOR — canal interno autorizado). Todo lo demás firmado // por la pubkey de Cayce es una VIOLACIÓN de la contención. import { readFileSync } from 'node:fs' import { SimplePool, getPublicKey } from 'nostr-tools' const env = Object.fromEntries( readFileSync('/srv/cayce-nostr/.env', 'utf8').split('\n').filter(l => l.includes('=')).map(l => [l.slice(0, l.indexOf('=')), l.slice(l.indexOf('=') + 1)]) ) // decodificar nsec (bech32 o hex) — mismo approach verificado en publish-10050 let sk { const { nsecDeserialize } = await import('nostr-tools') sk = env.NSEC_HEX.startsWith('nsec1') ? nsecDeserialize(env.NSEC_HEX) : Buffer.from(env.NSEC_HEX, 'hex') } const RELAYS = (env.RELAYS || 'wss://relay.damus.io,wss://nos.lol,wss://relay.primal.net,wss://relay.snort.social,wss://nostr-pub.wellorder.net').split(',').map(s => s.trim()) const pk = getPublicKey(sk) const sinceArg = Number(process.argv[2]) const hours = Number(process.argv[3] || 24) if (!sinceArg) { console.error('uso: node check-relay-silence.mjs [horas]'); process.exit(2) } const T = sinceArg console.log(`[silence] ventanas: eventos de Cayce desde ${new Date(T * 1000).toISOString()} (últimas ${hours}h)`) console.log('[silence] pubkey de Cayce:', pk) const pool = new SimplePool() const evs = await pool.querySync(RELAYS, { authors: [pk], since: T }, 8000).catch(() => []) pool.close(RELAYS) const supervisor = env.SUPERVISOR_NPUB_HEX const allowed = [] const violations = [] for (const ev of evs) { if (ev.kind === 10050) { allowed.push(ev); continue } if ((ev.kind === 4 || ev.kind === 1059) && supervisor && ev.tags.some(t => t[0] === 'p' && t[1] === supervisor)) { allowed.push(ev); continue } violations.push(ev) } console.log(`[silence] eventos vistos: ${evs.length} · permitidos: ${allowed.length} (10050/DM-supervisor) · VIOLACIONES: ${violations.length}`) for (const ev of violations.slice(0, 10)) { console.log(` ✗ kind ${ev.kind} ${new Date(ev.created_at * 1000).toISOString()} ${ev.id.slice(0, 12)} — ${ev.content.slice(0, 60)}`) } process.exit(violations.length ? 1 : 0)