Moderator Handbook

If you're reading this, you're about to help keep the EmDash community safe. Thank you.

Your role

Moderators review flagged versions, respond to reports, and apply admin actions (approve, reject, revoke, ban). You are not expected to be a security expert — our static scanner does the deterministic work. Your job is judgement on ambiguous cases and fair, consistent handling of reports.

Moderation queue

The queue at /dashboard/admin/queue shows every version that's pending, flagged, or rejected. Filter by status using the tabs. Each row has inline actions:

  • Approve — publishes a pending/flagged version immediately. Use when you've reviewed and decided it's safe.
  • Reject — sends the version to rejected state. Always write a clear, actionable reason. The reason is visible to the author on their dashboard and (if you leave the "Post publicly" checkbox on) on the public plugin detail page.
  • Static — re-run just the static scanner. Free, no neurons.
  • AI — re-run the AI audit. Costs neurons from the daily budget. Use when you want a second opinion on a flagged version.

When to approve

  • Scanner findings are low-severity (e.g. bundled CJS require(), undeclared hosts pointing to legitimate services) and you've read enough of the source to be confident.
  • AI verdict is pass with a low risk score and no security findings.
  • The plugin has a clear purpose, a linked repository, and the code matches the description.

When to reject

  • The code does something the manifest doesn't declare (e.g. network calls to undeclared hosts that look like data exfiltration).
  • The plugin is deceptive — the description doesn't match what the code does.
  • Obvious license violations (copying another plugin verbatim with a different name).
  • The plugin is a framework or boilerplate with no meaningful functionality.
  • The manifest declares capabilities the plugin clearly doesn't need (over-scoping for data collection).

Writing a good rejection reason: be specific, point to a file and line if possible, describe the fix. Reasons are public by default — assume installers will read them. If you need to reference private context (a Discord conversation, an email), uncheck "Post publicly" before submitting.

When to revoke a published version

Use revoke version (on the admin plugin detail page) when a version that previously passed review is later discovered to be harmful — a backdoor shipped in an update, a maintainer account compromise, a post-publish CVE.

  • Revocation is at the version level — earlier good versions stay downloadable.
  • Downloads are blocked immediately. The version keeps its tombstone row in the history.
  • A reason is required and defaults to public. The author sees it on their dashboard.

When to revoke a whole plugin

Use the plugin-level revoke action when the plugin is fundamentally unfit — the author is banned, the plugin is a malicious fork, or every version has been found unsafe. Plugin-level revocation hides the plugin from search, stops downloads for all versions, and renders the detail page with a prominent "This plugin has been revoked" tombstone banner and a noindex meta.

When to ban an author

Banning is reserved for repeated bad-faith behaviour, not one-off mistakes. Reach for it when:

  • The author has submitted multiple malicious plugins (backdoors, stealers, cryptominers).
  • The author re-registers after a previous plugin was revoked for cause.
  • The author is harassing other community members per the Code of Conduct.
  • The author is impersonating another project or maintainer.

A banned author can still browse the marketplace but cannot sign in as a publisher or submit new content. Use the Ban author action in the admin interface; a reason of at least 5 characters is required and the ban is logged.

Reports queue

The reports queue at /dashboard/admin/reports shows user-filed reports. Status lifecycle: open → investigating → resolved | dismissed.

  • Move a report to investigating to signal you've seen it and are working on it.
  • Resolve when you've taken action (revoked a version, banned an author, fixed a bug) and optionally include a note.
  • Dismiss when the report doesn't describe a real problem — e.g. a misunderstanding, a mistaken attribution, or a duplicate of a prior report.

Report triage

  1. Security reports first. If the category is "Security" and the description sounds credible, act immediately — revoke the affected version while you investigate, rather than wait.
  2. Broken/abandoned reports. Check if the plugin's repository has been updated recently. If it's truly abandoned, consider flagging the latest version with a public admin note rather than revoking.
  3. License reports. Compare the plugin against the claimed source. If confirmed, revoke and notify the rightful author if you can identify them.
  4. Abuse reports. Apply the Code of Conduct. Escalate to the superadmin if the situation is sensitive or involves legal threats.

Transparency is the default

Our policy is that scanner findings and moderator rejection reasons are public by default. This matters:

  • Authors learn what not to do, which reduces repeat mistakes.
  • Installers can see why a version was refused and decide whether to trust the plugin's future versions.
  • Other moderators can see how past cases were handled and apply consistent standards.

Uncheck the "Post publicly" checkbox only when your note genuinely references something that should not be public — private correspondence, personal information, or a vulnerability that hasn't been patched upstream yet.

Escalation

Contact the superadmin when:

  • You receive a legal threat or DMCA takedown request.
  • A vulnerability has been responsibly disclosed and needs embargo coordination.
  • The situation involves repeated harassment and may need a Code of Conduct escalation.
  • You're unsure — better to ask than to make a controversial decision alone.

The superadmin can be reached via a private GitHub security advisory at github.com/chrisjohnleah/emdashcms-org/security/advisories/new.

Your obligations

  • Follow the Code of Conduct.
  • Apply policy consistently. If two similar cases produce different outcomes without a principled reason, that's a problem.
  • Write clear, kind rejection reasons. A rude moderator creates more work downstream.
  • Respect contributor privacy — never share private correspondence or personal details in public notes.
  • When in doubt, err on the side of the users' safety over the author's convenience.