Comments — Reference
The Comments surface is the direct-response plane for content published through SGEN. It owns every visitor reply attached to a post, page, or other commentable content type — the moderation queue, the spam filter outcome, the reply thread, and the action menu that lets an operator approve, hide, flag, or delete. Anything that lands as a reader response under a piece of content traces back to a record managed here.
This page is a reference for platform engineers and integrators who need to understand the surface before extending it, scripting against it, or scoping a moderation workflow. Customer-facing how-tos live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Comments live under the Comments module in SG-Admin. The module renders three primary views — the moderation queue (pending), the all-comments list (every status), and the per-content detail view — and exposes a small set of write operations for approve, hide, mark spam, reply, edit, and delete.
The module is paired by convention: one half renders the views and prepares the data, the other half handles writes and returns AJAX responses. Engineers reading the SG-Admin source will see this split across two controller files; the reference below describes the combined surface as it appears to a calling integration.
Comments and Discussions are distinct surfaces and should not be confused. Comments carries direct replies anchored to a single piece of content (post or page) — short-form, moderated, often anonymous, surfaced under the content itself on the public site. Discussions carries threaded conversation surfaces that exist as their own entities (forum-style boards, support threads, AMA sessions) — longer-form, attributed to logged-in identities, surfaced on their own pages. A discussion is its own destination; a comment is content on someone else's destination.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Comments
- URL prefix:
/sg-admin/comments/ - View templates:
application/views/Admin/Comments/
┌────────────────────────────────────────────────────────────────────────────┐│ SG-Admin → Comments → Pending (4) [Filter: Pending ▾]│├────────────────────────────────────────────────────────────────────────────┤│ Author On Posted Spam score Action ││ ───────────── ──────────────────────── ──────────── ────────── ────── ││ Sarah K. Post: 5 Migration Steps 2 min ago 0.04 — clean ││ "Step 3 saved us a week. We were doing the manual version of..." ││ [✔ Approve] [✕ Hide] [⚠ Mark spam] [↩ Reply] [⋯ Delete] ││ ││ visitor_2419 Post: Pricing Update 12 min ago 0.91 — likely spam ││ "Buy cheap watches at..." ││ [✔ Approve] [✕ Hide] [⚠ Mark spam] [↩ Reply] [⋯ Delete] ││ ││ Tomas R. Page: Pricing 18 min ago 0.11 — clean ││ "Is the Builder included in the $99 tier or does it..." ││ [✔ Approve] [✕ Hide] [⚠ Mark spam] [↩ Reply] [⋯ Delete] │└────────────────────────────────────────────────────────────────────────────┘Actions
The Comments surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List and filter
Returns the comment records visible to the current operator, paginated, with author, on-content, posted, status, and spam-score columns. Supports column sort, free-text filter across author and body, status filter (pending / approved / hidden / spam / trashed), spam-score range, content-type filter (post / page / custom type), and per-page count. The default view scopes to pending so the moderation queue surfaces first.
Approve
Transitions a comment from pending to approved. Approved comments render on the public site under their attached content. The action is idempotent — approving an already-approved comment is a no-op and returns success.
Hide
Transitions a comment from any status to hidden. Hidden comments are retained in the database (queryable via the hidden filter) but do not render on the public site. Useful for legitimate replies that are off-topic, contain personally identifying information about a third party, or temporarily need to come down pending operator review.
Mark spam
Transitions a comment to spam and submits the body, author identifiers, and originating IP to the configured spam-classifier feedback loop (if the integration is set up). Spam comments are hidden from the public site and from the default queue view. Repeated marks against the same author or IP are factored into the classifier's future scoring.
Reply
Posts an operator reply attached to the target comment. The reply is itself a comment record with a parent_id pointing to the original. Operator replies bypass the moderation queue — they enter directly as approved. The author identity on an operator reply is the calling User record, displayed with an operator badge on the public side.
Edit
Loads an existing comment body into an inline editor. Submit replaces the stored body and stamps an edited_at timestamp. The edit-history is captured as an append-only audit trail — every prior body is retained server-side, accessible from the comment's detail view. Authors are notified by email when their comment is edited if the notification preference is enabled.
Delete (soft)
Transitions a comment to trashed. Trashed comments disappear from the default list view but remain in the database, queryable via the trash filter. Replies to a trashed comment remain attributed to the trashed parent and continue to render on the public site (as orphan replies) unless they are also trashed.
Delete (permanent)
Hard-removes the comment row. Available only after a soft delete (i.e., from the trash view). The action is irreversible. Replies to a permanently deleted comment have their parent_id rewritten to the next ancestor that still exists, preserving the visible thread structure on the public site.
Bulk action
Applies a single action (approve / hide / mark spam / trash) to a checked set of comments in one request. The surface returns a per-row pass / fail report. Useful for sweeping the moderation queue after a coordinated spam wave or for retroactively hiding all comments under a retracted post.
Spam-classifier feedback
When the spam-classifier integration is configured, every Approve and every Mark-spam emits a feedback signal to the classifier — Approve marks the example as not-spam, Mark-spam as spam. The classifier uses these signals to re-tune its scoring for future incoming comments. The signal is fire-and-forget; classifier downtime never blocks the moderation action.
Data model
A comment record carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
content_type | enum | post, page, or a configured custom commentable type. |
content_id | integer | Foreign key into the target content surface. |
parent_id | integer | Set when the comment is a reply. Null for top-level comments. |
author_name | string | Display name supplied at post time. Required for anonymous comments. |
author_email | string | Optional for anonymous; required if the site requires notification routing. |
author_user_id | integer | Set when the author is a logged-in User. Null for anonymous. |
body | text | Plain-text or restricted-markdown depending on site configuration. |
status | enum | pending, approved, hidden, spam, trashed. |
spam_score | float | 0.0-1.0. Set by the spam-classifier at post time. Null if no classifier configured. |
ip_address | string | Originating IP. Used for spam classification and rate limiting. |
user_agent | string | Originating user agent string. Same usage as IP. |
posted_at | timestamp | Set on first submission, immutable. |
edited_at | timestamp | Set on every body edit. Null until first edit. |
approved_at | timestamp | Set on transition to approved. Used for sort order on the public side. |
parent_id always points to a top-level comment or null. Reply-to-reply is supported in the model but the public-side renderer collapses depth beyond two levels — replies to replies render at the second level with a citation of the deeper parent. This is a render concern, not a data concern.Edit-history retention. Every body edit captures the prior body in an append-only edit-history table. The detail view surfaces the full history; the public side shows only the current body with an "edited" badge.
Spam-score lifecycle. The score is set once at post time. It is not re-computed on subsequent operator action. Marking a clean-scored comment as spam writes the new status but does not overwrite the original score — the operator decision and the classifier opinion are both retained for downstream audit and tuning.
COMMENT RECORD├── id integer primary key├── content_type enum post | page | custom commentable├── content_id integer FK into target content├── parent_id integer set on reply (else null)├── author name, email, optional author_user_id (logged-in)├── body text plain or restricted-markdown├── status enum pending | approved | hidden | spam | trashed├── spam_score float 0.0-1.0, set once at post time├── origin ip_address, user_agent (audit + rate limit)├── posted_at timestamp immutable submission time├── edited_at timestamp last body edit└── approved_at timestamp transition to approved↓ on body editEDIT HISTORY ROW(append-only, full prior body)↓ on Approve / Mark-spamSPAM CLASSIFIER FEEDBACK(fire-and-forget signal,tunes future scoring)Permissions
Access to the Comments surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Comments surface.
Layer 2 — per-action capability. Within SG-Admin, each Comments action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List comments | ✔ | ✔ | ✔ |
| Approve | ✔ | ✔ | — |
| Hide | ✔ | ✔ | — |
| Mark spam | ✔ | ✔ | — |
| Reply as operator | ✔ | ✔ | — |
| Edit comment body | ✔ | — | — |
| Soft delete (trash) | ✔ | ✔ | — |
| Permanent delete | ✔ | — | — |
| Bulk action | ✔ | ✔ | — |
| Configure spam classifier | ✔ | — | — |
Content-author allowance. A User who authored the content a comment is attached to may approve, hide, and reply to comments under that content without holding the broader Comments capability. The allowance applies only to comments under their own posts and pages, not to other content. Edit-body and delete still require the broader capability.
PII gate. Comment bodies that match a configured PII pattern (email address, phone number, government ID format) are flagged on display with a moderation prompt. The flag is advisory — the operator can still approve. A comment approved with a PII flag emits an Activity Log entry tagged comments.pii_approved for downstream review.
Audit. Every write — approve, hide, mark spam, reply, edit, trash, permanent delete, bulk action, spam-classifier configuration change — emits an Activity Log entry. The log records the acting operator, the target comment, the before / after status (or body diff for edits), and the spam-classifier feedback signal when fired.
MODERATION REQUEST│▼┌───────────────────────────┐│ Admin gate │ unauth → reject│ (every /sg-admin/* call) │└─────────────┬─────────────┘│ authed▼┌───────────────────────────┐│ Capability check │ role lacks cap → check│ (per-action) │ content-author allowance└─────────────┬─────────────┘│┌──────┴──────┐│ has cap │ no cap, but│ │ owns content▼ ▼└──────┬──────┘│ allowed▼┌───────────────────────────┐│ PII gate │ body matches PII pattern →│ │ surface moderation prompt└─────────────┬─────────────┘│ resolved▼action executes│▼Activity Log entry +spam-classifier feedback(on Approve / Mark-spam)Related references
- Posts — Reference. Comments attach to post records via
content_type = post+content_id. Post deletion cascades to comment soft-delete by default; the cascade behavior is configurable under Settings. - Pages — Reference. Same — pages are commentable when the page record carries
comments_enabled = true. - Discussions — Reference. The threaded-conversation surface. Distinct from Comments — discussions are their own destinations, comments live under other content.
- Users — Reference. Logged-in commenters carry an
author_user_idpointing to the Users surface. Operator replies attribute via the same field. - Settings — Reference. Owns the commentable-content-type list, the spam-classifier integration configuration, the PII pattern catalog, the default-moderation-state per content type (auto-approve vs queue), and Activity Log retention.
- Activity Log — Reference. Source of the comments audit trail. Every write emits an entry; the
comments.pii_approvedtag is the bridge for downstream review. - Notifications — Reference. Author-notification on edit and operator-reply-notification resolve through the notification template surface.
/docs/comments.