Hidden words.
Two layers of term-based moderation, enforced server-side on the comment write path. A community-wide blocked-terms lexicon (admin lane) plus an author-side 'hold my muted words for review' control — no need to fan the term list out to every client.
1
Community lexicon (admin)
Add hidden words on the moderation admin lane. Each term carries an action: hide lands a matching comment hidden (nobody sees it); pending_approval routes it into the approve lane, where only the commenter and the post owner can see it until it is approved. Matching is a case-insensitive substring. The post owner's own comments on their own post are never hidden or held.
# Add a term (action defaults to "hide")
curl -X POST -H "Authorization: Bearer pcft_live_..." \
-H "Content-Type: application/json" -d '{"term":"spoiler","action":"pending_approval"}' \
"https://social.productcraft.co/v1/workspaces/<ws>/communities/<c>/moderation/blocked-terms"
# List the lexicon (cursor-paginated)
curl -H "Authorization: Bearer pcft_live_..." \
"https://social.productcraft.co/v1/workspaces/<ws>/communities/<c>/moderation/blocked-terms"
# Remove a term — idempotent, 204 whether or not it existed
curl -X DELETE -H "Authorization: Bearer pcft_live_..." \
"https://social.productcraft.co/v1/workspaces/<ws>/communities/<c>/moderation/blocked-terms/spoiler"These routes need social.config.update (write) / social.config.read (list). Re-POSTing a term updates its action. Lexicon changes take effect within ~60s (a short in-process cache keeps the per-comment check off the hot DB path).
2
Author-side muted-term holds
An actor's muted terms gain an optional action. The default mute is the existing feed-filter behaviour. Set pending_approval and a stranger's comment on that actor's posts containing the term is held for review — an IG-style “hide comments with these words”. Enforcement is server-side, so your clients never fetch the term list to apply it.
curl -X POST -H "Authorization: Bearer pcft_live_..." \
-H "Content-Type: application/json" \
-d '{"term":"ex","action":"pending_approval"}' \
"https://social.productcraft.co/v1/communities/<c>/actors/<actorId>/muted-terms"3
Precedence
- A community
hidematch is the strongest — the comment landshidden. - Otherwise a community
pending_approvalmatch, a restrict edge, or one of the post-author'spending_approvalmuted terms holds it in the approve lane. - Held comments clear via the existing comment approve endpoint — reserved to the post owner.
curl -X POST -H "Authorization: Bearer pcft_live_..." \
-H "Content-Type: application/json" -d '{"approver_actor_id":"<postAuthorId>"}' \
"https://social.productcraft.co/v1/communities/<c>/posts/<postId>/comments/<commentId>/approve"To surface held comments for review, list a post's comments with ?actor_id=<postAuthorId> — without a viewer, pending_approval rows are omitted entirely.