/** * Peer invite / revoke / list ACL management (admin). */ import * as peerPolicy from '../core/peer-policy.js' import { peers } from '../core/peer-registry.js' import { Roles } from '../../shared/protocol.js' import * as validation from '../utils/validation.js' export function registerPeerHandlers(session) { session.respond('listPeers', async () => { const policy = peerPolicy.listPeers() const live = [] for (const s of peers) { live.push({ peerId: s.id, role: s.role, connected: !s.closed, clientInfo: s.clientInfo || null, }) } return { success: true, type: 'peers', ...policy, live, } }) session.respond('listInvites', async () => { return { success: true, type: 'invites', data: peerPolicy.listInvites(), } }) session.respond('invitePeer', async (args) => { // Either create redeemable token OR register known peer key if (args.peerId) { const peerId = validation.sanitizeString(args.peerId, 64).toLowerCase() if (!/^[0-9a-f]{64}$/.test(peerId)) throw new Error('peerId must be 64 hex characters') const role = args.role || Roles.operator const entry = peerPolicy.registerPeer(peerId, { role, alias: args.alias || null, note: args.note || null, }) return { success: true, type: 'peerRegistered', data: entry } } const invite = peerPolicy.createInvite({ role: args.role || Roles.operator, ttlHours: args.ttlHours, maxUses: args.maxUses, note: args.note, }) return { success: true, type: 'invite', data: invite } }) session.respond('revokePeer', async (args) => { const peerId = validation.sanitizeString(args.peerId || args.id, 64).toLowerCase() if (!peerId) throw new Error('peerId required') const result = peerPolicy.revokePeer(peerId) // Drop live session if connected const live = peers.get(peerId) if (live) { try { live.destroy() } catch { // ignore } } return { success: true, ...result } }) session.respond('unrevokePeer', async (args) => { const peerId = validation.sanitizeString(args.peerId || args.id, 64).toLowerCase() if (!peerId) throw new Error('peerId required') return { success: true, ...peerPolicy.unrevokePeer(peerId) } }) session.respond('setPeerRole', async (args) => { const peerId = validation.sanitizeString(args.peerId || args.id, 64).toLowerCase() const role = args.role if (!peerId || !role) throw new Error('peerId and role required') const entry = peerPolicy.setPeerRole(peerId, role) const live = peers.get(peerId) if (live) live.role = role return { success: true, data: entry } }) }