import type { Handler } from 'hono'; import { blacklistToken, cleanupExpiredTokens } from 'officerdb'; import { emitAccountLifecycle } from '@@/account-lifecycle'; import { clientIp } from './client-ip'; // Distress: blacklist the current token (same as signout) but log it as a security event. export const revokeHandler: Handler = async (ctx) => { const user = ctx.get('user') as { id: number; jti: string; exp: number; email?: string }; const origin = ctx.get('origin') as string | undefined; console.warn( `[SECURITY] token revoked (distress) — user=${user.email || '?'}, origin=${origin || '-'}, ip=${clientIp(ctx)} — ${new Date().toISOString()}`, ); await blacklistToken(user.jti, user.exp); // Distress means "someone got in": listeners drop everything reconstructible, not just live sessions. // Deliberately harsher than signout — convenience material goes too, even where that costs the owner a // one-time re-setup on their next login. emitAccountLifecycle(user.id, 'distress'); cleanupExpiredTokens().catch(() => {}); return ctx.json({ ok: true }); };