| summary | Security + moderation controls (reports, bans, upload gating). | |||
|---|---|---|---|---|
| read_when |
|
- user: upload skills/souls (subject to GitHub age gate), report skills/comments.
- moderator: hide/restore skills, view hidden skills, unhide, soft-delete, ban users (except admins).
- admin: all moderator actions + hard delete skills, change owners, change roles.
- Reports are unique per user + target (skill/comment).
- Report reason required (trimmed, max 500 chars). Abuse of reporting may result in account bans.
- Per-user cap: 20 active reports.
- Active skill report = skill exists, not soft-deleted, not
moderationStatus = removed, and the owner is not banned. - Active comment report = comment exists, not soft-deleted, parent skill still active, and the comment author is not banned/deactivated.
- Active skill report = skill exists, not soft-deleted, not
- Auto-hide: when unique reports exceed 3 (4th report):
- skill report flow:
- soft-delete skill (
softDeletedAt) - set
moderationStatus = hidden - set
moderationReason = auto.reports - set embeddings visibility
deleted - audit log entry:
skill.auto_hide
- soft-delete skill (
- comment report flow:
- soft-delete comment (
softDeletedAt) - decrement comment stat via
uncommentstat event - audit log entry:
comment.auto_hide
- soft-delete comment (
- skill report flow:
- Public queries hide non-active moderation statuses; staff can still access via staff-only queries and unhide/restore/delete/ban.
- Skills directory supports an optional "Hide suspicious" filter to exclude
active-but-flagged (
flagged.suspicious) entries from browse/search results.
- New skill publishes now persist a deterministic static scan result on the version.
- Skill moderation state stores a structured snapshot:
moderationVerdict:clean | suspicious | maliciousmoderationReasonCodes[]: canonical machine-readable reasonsmoderationEvidence[]: capped file/line evidence for static findingsmoderationSummary, engine version, evaluation timestamp, source version id
- Structured moderation is rebuilt from current signals instead of appending stale scanner codes.
- Legacy moderation flags remain in sync for existing public visibility and suspicious-skill filtering.
- Moderators/admins can run a comment backfill scanner to classify scam comments with OpenAI.
- Scanner stores per-comment moderation metadata:
scamScanVerdict:not_scam | likely_scam | certain_scamscamScanConfidence:low | medium | high- explanation/evidence/model/check timestamp fields on
comments.
- Auto-ban trigger is intentionally strict:
- only
certain_scamwithhighconfidence can trigger account ban. - moderator/admin accounts are never auto-banned by this pipeline.
- only
- Ban reason is bounded to 500 chars and includes concise evidence + comment/skill IDs.
- CLI run examples:
- one-shot:
npx convex run commentModeration:backfillCommentScamModeration '{"batchSize":25,"maxBatches":20}' - background chain:
npx convex run commentModeration:scheduleCommentScamModeration '{"batchSize":25}'
- one-shot:
- Banning a user:
- hard-deletes all owned skills
- soft-deletes all authored skill comments + soul comments
- revokes API tokens
- sets
deletedAton the user
- Admins can manually unban (
deletedAt+banReasoncleared); revoked API tokens stay revoked and should be recreated by the user. - Optional ban reason is stored in
users.banReasonand audit logs. - Moderators cannot ban admins; nobody can ban themselves.
- Report counters effectively reset because deleted/banned skills are no longer considered active in the per-user report cap.
- User-initiated deletion is irreversible.
- Deletion flow:
- sets
deactivatedAt+purgedAt - revokes API tokens
- clears profile/contact fields
- clears telemetry
- sets
- Deleted accounts cannot be restored by logging in again.
- Published skills remain public.
- Skill + soul publish actions require GitHub account age ≥ 14 days.
- Skill + soul comment creation also requires GitHub account age ≥ 14 days.
- Lookup uses GitHub
created_atfetched by the immutable GitHub numeric ID (providerAccountId) and caches on the user:githubCreatedAt(source of truth)
- Gate applies to web uploads, CLI publish, GitHub import, and comments.
- If GitHub responds
403or429, publish fails with:GitHub API rate limit exceeded — please try again in a few minutes
- To reduce rate-limit failures, set
GITHUB_TOKENin Convex env for authenticated GitHub API requests.
- Cleanup uses quality heuristics plus trust tier to identify very thin/templated skills.
- Word counting is language-aware (
Intl.Segmenterwith fallback), reducing false positives for non-space-separated languages.