README.MD

GlassFrame Protocol

A layered, self-contained security engine for discord.js v14 bots. Four independently-toggleable layers - AntiRaid, AntiNuke, Basic Security, and Groq-powered AI Moderation - share one threat-scoring and punishment pipeline instead of each reacting on its own, so the same member never gets hit by four different modules for one incident, and a single soft flag never turns into an auto-ban.

Everything is per-server: one bot process can run GlassFrame across many Discord servers, each with its own independent set of active layers and its own whitelist, persisted across restarts. See docs/STATE.md.

No slash commands - prefix commands only. No legacy EmbedBuilder - every log message renders through Discord's Components V2 system. No emoji anywhere in code or output.

Install

GlassFrame Protocol is published on npm. From your bot project:

npm install glassframe-protocol

discord.js is a listed dependency and installs automatically alongside it. If your project doesn't already have its own copy, install it explicitly too:

npm install glassframe-protocol discord.js

Requires discord.js v14.16+ (Components V2 support and the guildAuditLogEntryCreate event) and Node.js 18+ (global fetch, used only by the optional AI layer). New to Node/npm? See Getting Started, Step 1.

Required intents

const { Client, GatewayIntentBits } = require("discord.js");

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.GuildModeration
  ]
});

Required bot permissions

Manage Roles, Kick Members, Ban Members, Manage Channels, Manage Webhooks, View Audit Log, Moderate Members (timeout), Manage Messages. GlassFrame's own role must sit above any role/member it needs to act on - RoleAnalyzer checks this before every action instead of attempting and failing.

Usage

const GlassFrame = require("glassframe-protocol");

client.once("ready", () => {
  const frame = new GlassFrame(client, {
    getLogChannel: async (guild) =>
      guild.channels.cache.find((c) => c.name === "security-logs") ?? null,
    whitelist: ["123456789012345678"], // trusted everywhere, seeded into every guild on first run
    autoStart: ["basicSecurity"], // starting layers for every guild - not a global on/off
    config: {
      antiRaid: { joinThreshold: 8 },
      aiModeration: { apiKeys: [process.env.GROQ_KEY_1, process.env.GROQ_KEY_2].filter(Boolean) }
    }
  });

  frame.on("warning", (w) => console.warn(`[GlassFrame:${w.layer}]`, w.message));
});

client.login(process.env.BOT_TOKEN);

Send !gf panel in any channel (Manage Server permission required) to get the 5-button control panel and arm layers from there instead of in code.

The four layers

  • Basic Security - spam rate, duplicate flood, mention spam, a dedicated trust-aware @everyone/@here guard, local NLP scam/phishing/ raid-recruitment scoring (including a specific invite-link + raid-language combo check), and link checks via PhishingDatabase (a server-editable blocklist plus raw-IP/punycode/brand-look-alike/shortener heuristics - !gf phishing add/remove/list).
  • AntiRaid - join-velocity lockdown with automatic verification-level raise/restore, a composite alt-account score (account age, username entropy, missing avatar), and creation-time cluster correlation that catches a raid trickling in too slowly to trip the rate counter.
  • AntiNuke - audit-log burst detection across channels, roles, bans, kicks, webhooks, emoji, and stickers per executor; a dangerous permission-grant watchdog covering both a role's own permissions changing and a member being quietly handed an already-dangerous role (with optional auto-revert); a channel permission-overwrite watchdog (catches @everyone getting locked out of, or let into, a channel without anything being deleted); a server-identity watchdog (name/icon/vanity URL changes); an invite-abuse watchdog (unrestricted invites from non-staff); and webhook-flood containment (deletes an abusive webhook and traces it back to its creator, since webhook messages carry no guild member for other layers to see).
  • AI Moderation (optional, off by default) - Groq-powered second opinion for messages the local NLP scores as "gray zone": not clean, not clearly over threshold. Supports a pool of API keys with automatic per-key cooldown on rate limits. See config.aiModeration and docs/CACHE_ARCHITECTURE.md for how verdicts get cached and keys rotated.

Every layer starts disabled, per guild. Nothing runs until you list it in autoStart, call frame.enableLayer(name, guildId), or arm it from the control panel. Add your own layer alongside these four with frame.registerLayer() - see Extending it below.

Performance under load

Every Discord mutation PunishmentEngine performs and every outbound Groq request go through a bounded-concurrency queue (frame.actionQueue / frame.aiQueue) instead of firing unbounded, so a burst can't trip a rate limit by hammering it all at once. !gf metrics shows this server's numbers by default (open cases, flagged members, active layers), with a button on the message to switch to bot-wide totals across every server (frame.getMetrics() / frame.getGuildMetrics(guildId)). Full write-up in docs/PERFORMANCE.md.

How punishment works

Layers never ban/kick/timeout directly - they report a signal ({ layer, weight, reason }) to a shared ThreatEngine, which keeps one decaying risk score per member. PunishmentEngine turns that score into an action, but only after RoleAnalyzer confirms the bot can actually act on the member and checks their real trust level (a genuine admin is flagged for human review, never auto-banned), and only if there isn't already an open case for that member from a moment ago. Full write-up in docs/PROTOCOL_LAYERS.md.

Extending it

  • frame.registerLayer(name, layerInstance) - add your own security layer to the same pipeline the built-in four use (per-guild enable/state/ persistence come free from extending core/Layer). Doesn't get a button on the panel automatically - the panel stays fixed at exactly 5.
  • frame.registerAction(name, handler) - add a custom punishment action beyond ban/kick/timeout/quarantine, referenceable from config.punishment.ladder.
  • !gf prefix set <newPrefix> - each server can run its own prefix; config.prefix always still works everywhere as a fallback.
  • getLogChannel(guild, layerName) - route different layers to different channels, if you want; the second parameter is optional and backward compatible.
  • !gf engine - an owner-only, bot-wide dashboard (busiest server, AI usage, live cross-server activity feed), gated separately from every other command and not listed in !gf help. See docs/ENGINE.md.

Docs

  • GETTING_STARTED.md - adding GlassFrame to a bot you already have running.
  • docs/PROTOCOL_LAYERS.md - full architecture: containment vs. punishment, how a signal becomes an action, registerLayer/registerAction.
  • docs/STATE.md - per-guild layer/whitelist state and how persistence across restarts works.
  • docs/CACHE_ARCHITECTURE.md - every cache in the library, its key shape, its TTL, and how to turn on cache-level debug logging.
  • docs/PERFORMANCE.md - the bounded-concurrency queues and internal metrics collector, and what !gf metrics shows.
  • docs/ENGINE.md - the owner-only bot-wide dashboard: the password/lockout system and what each of its 5 pages shows.
  • docs/COMMANDS.md - the full prefix command reference and the control panel's five buttons.
  • CHANGELOG.md - version history.

Tuning

Every threshold lives in config.js. Start with the defaults, watch the security log channel for a week, and adjust - a very active server needs higher spam/mention thresholds than a quiet one, though config is one merged object for the whole bot process rather than settable per guild. frame.threatEngine and frame.punishmentEngine are both plain properties on the returned instance if you want to inspect scores or open cases at runtime - both are also EventEmitters (signal and case respectively), alongside frame's own warning, layerToggled, and layerRegistered events. See Events and Scope in Protocol Layers for the full picture - layer on/off, the whitelist, and (as of v2.1.0) the per-server command prefix are correctly per-guild; the phishing blocklist and config itself are the two things still shared across every guild.