Artifact dacdba7b065c84d8c3f980102e32adc374c1cbdcec1642de2033a57759fc1b6c:
- File
internal/oltp/moderation_test.go
— part of check-in
[1b5f71c338]
at
2026-08-21 19:45:11
on branch quarry-forum
— forum moderation + AI hooks: pre-commit staging, public append-only log
Approval births the artifact (nothing to un-sync); synced-in posts get hide-with-reason. Hook (--forum-hook) is advisory, async, fails open to hold-for-human; automated actions logged publicly as 'hook'. (user: dmestas, size: 2758) [annotate] [blame] [check-ins using]
package oltp import "testing" func TestModerationGate(t *testing.T) { db := testDB(t) if db.ModerationEnabled("r") { t.Fatal("moderation on by default") } if err := db.SetModeration("r", true); err != nil { t.Fatal(err) } if !db.ModerationEnabled("r") || db.ModerationEnabled("other") { t.Fatal("gate scope wrong") } id, err := db.StagePost("r", "post", "", "Hi", "body", "text/x-markdown", "eve") if err != nil { t.Fatal(err) } pending, err := db.StagedPending("r") if err != nil || len(pending) != 1 || pending[0].Author != "eve" { t.Fatalf("pending = %v err=%v", pending, err) } // Two moderators race: exactly one resolution wins. if err := db.ResolveStaged("r", id, "approved"); err != nil { t.Fatal(err) } if err := db.ResolveStaged("r", id, "rejected"); err == nil { t.Fatal("double resolution accepted") } if pending, _ := db.StagedPending("r"); len(pending) != 0 { t.Fatalf("resolved entry still pending: %v", pending) } // The hook verdict is advisory data on the row. id2, _ := db.StagePost("r", "reply", "roothash", "", "spam?", "", "mallory") if err := db.SetStagedAI("r", id2, "reject", 0.97, "link farm"); err != nil { t.Fatal(err) } if s, ok, _ := db.StagedByID("r", id2); !ok || s.AIAction != "reject" || s.AIScore != 0.97 { t.Fatalf("verdict lost: %+v", s) } } func TestModLogAppendsAndHiddenPosts(t *testing.T) { db := testDB(t) must := func(err error) { t.Helper() if err != nil { t.Fatal(err) } } must(db.AppendModLog("r", "dan", "reject", "staged:4", "spam")) must(db.AppendModLog("r", "hook", "ai-hold", "staged:5", "uncertain")) log, err := db.ModLog("r", 10) if err != nil || len(log) != 2 { t.Fatalf("log = %v err=%v", log, err) } if log[0].Actor != "hook" || log[1].Action != "reject" { t.Fatalf("order/content: %v", log) } must(db.HidePost("r", "posthash", "flamebait", "dan")) if h, _ := db.HiddenPosts("r"); h["posthash"] != "flamebait" { t.Fatalf("hidden = %v", h) } must(db.UnhidePost("r", "posthash")) if h, _ := db.HiddenPosts("r"); len(h) != 0 { t.Fatalf("unhide left state: %v", h) } } func TestPurgeRepoSweepsModeration(t *testing.T) { db := testDB(t) db.SetModeration("gone", true) db.StagePost("gone", "post", "", "t", "b", "", "eve") db.AppendModLog("gone", "dan", "approve", "staged:1", "") db.HidePost("gone", "p", "r", "dan") if err := db.PurgeRepo("gone"); err != nil { t.Fatal(err) } if db.ModerationEnabled("gone") { t.Fatal("gate survived purge") } if p, _ := db.StagedPending("gone"); len(p) != 0 { t.Fatal("staged survived purge") } if l, _ := db.ModLog("gone", 10); len(l) != 0 { t.Fatal("log survived purge") } if h, _ := db.HiddenPosts("gone"); len(h) != 0 { t.Fatal("hidden survived purge") } }