v0.2.4
Added
- Comment spam filtering and submission throttling. Public comment
submissions now go through a local heuristic scorer (links, keywords,
repeated text, disposable email domains, a render-age token, and terms
learned from "mark as spam") that auto-approves, holds, or auto-marks spam
per configurable score thresholds in Settings → Discussion → Spam
protection. Signed-in commenters get a separate rate-limit bucket alongside
the existing per-IP one. Admins get author/domain/IP/phrase block and allow
lists (with one-click "Block email/domain/IP" actions from the moderation
queue), a "hold a first-time commenter" option, an "auto-approve a
returning commenter" option, and a configurable spam retention/purge
window. A newcomments.spamBackendSDK filter lets a plugin attach an
external spam-scoring service (Akismet-style) without becoming a hard
dependency — the host always applies its own thresholds. All checks run
server-side; blocklist/allowlist changes are audit-logged.
(#109)
Fixed
-
Admin content list and menu/content pickers hid content in non-default languages. Admin → Content, the "add items" picker in Menus, and the page picker in the menu designer all scoped their
/api/contentrequests to the site's default published language, so editors couldn't find or select pages/posts written in any other language. These admin views now list content across every language; Admin → Content gained a language filter chip row (shown once the site has more than one language), and the menu content picker shows each item's locale next to its slug. -
Replying to a comment on a translated post could fail with "Cannot reply to that comment". The public comment thread lists comments from every translation of a post — a comment left on one language shows under every locale of that post — but submitting a reply checked the parent comment's content id against only the page currently being viewed, rejecting replies to a comment that lived under a sibling translation. Reply submission now matches the parent against the whole translation group, the same grouping already used to render the thread.