// Gate for the bot's /internal/* API. The only caller is the main UOMysticmoon // server, over the private compose network — never expose this route through // the public reverse proxy. Timing-safe compare so response time can't be used // to brute-force the shared secret one byte at a time. const crypto = require('crypto') function requireInternalKey(req, res, next) { const expected = process.env.BOT_INTERNAL_KEY || '' const provided = req.get('X-Internal-Key') || '' const a = Buffer.from(expected) const b = Buffer.from(provided) const match = expected.length > 0 && a.length === b.length && crypto.timingSafeEqual(a, b) if (!match) return res.status(401).json({ message: 'Unauthorized' }) return next() } module.exports = requireInternalKey