[Relay] Event Moderation Queue + Timmy AI Review #48

Open
opened 2026-03-21 00:41:20 +00:00 by replit · 0 comments
Owner

What & Why

Every post arriving at the relay goes through a moderation queue before publishing. Timmy reviews them: he auto-approves clearly benign content and flags anything ambiguous for the relay admin. Elite accounts bypass the queue entirely.

Done looks like

  • relay_event_queue DB table: event_id, pubkey, kind, raw_event (JSON), status (pending/approved/rejected/auto_approved), reviewed_by (timmy_ai/admin/null), review_reason, created_at, decided_at
  • POST /api/relay/policy updated: whitelisted account → insert event into queue with pending status → return shadowReject to strfry (held pending approval); approved events injected via strfry HTTP import API
  • ModerationService: enqueue(event), autoReview(eventId) (Claude Haiku — returns approve or flag), decide(eventId, decision, reason)
  • Elite accounts bypass queue — events injected directly
  • Admin endpoints: GET /api/admin/relay/queue?status=pending, POST .../approve, POST .../reject
  • Background poll loop: every 30 seconds, process up to 10 pending events via autoReview

Note: This is the root cause of the P0 infinite re-review bug (#27) where processPending() never transitions events out of pending. The fix is adding a "flagged" status transition after AI flags an event.

Out of scope

  • Admin UI (see relay admin panel issue)
  • Spam/rate-limit heuristics
  • NIP-40 expiration handling

Tasks

  1. DB schema — Add relay_event_queue table. Run db:push.
  2. Policy endpoint update — For write access (non-elite): insert event → return shadowReject. For elite: inject event → return accept.
  3. strfry HTTP import helperinjectEvent(rawEvent) calling strfry POST /import endpoint.
  4. ModerationServiceenqueue, autoReview (Haiku call; on flag → set status to flagged not pending to prevent re-review loop), decide (updates DB + calls injectEvent on approval).
  5. Background poll loopsetInterval on startup; process up to 10 pending events every 30 s.
  6. Admin queue routes — GET/approve/reject under /api/admin/relay/queue. Admin auth middleware.

Relevant files

  • lib/db/src/schema/index.ts
  • artifacts/api-server/src/lib/agent.ts
  • artifacts/api-server/src/routes/index.ts
## What & Why Every post arriving at the relay goes through a moderation queue before publishing. Timmy reviews them: he auto-approves clearly benign content and flags anything ambiguous for the relay admin. Elite accounts bypass the queue entirely. ## Done looks like - `relay_event_queue` DB table: `event_id`, `pubkey`, `kind`, `raw_event` (JSON), `status` (pending/approved/rejected/auto_approved), `reviewed_by` (timmy_ai/admin/null), `review_reason`, `created_at`, `decided_at` - `POST /api/relay/policy` updated: whitelisted account → insert event into queue with `pending` status → return `shadowReject` to strfry (held pending approval); approved events injected via strfry HTTP import API - `ModerationService`: `enqueue(event)`, `autoReview(eventId)` (Claude Haiku — returns `approve` or `flag`), `decide(eventId, decision, reason)` - Elite accounts bypass queue — events injected directly - Admin endpoints: `GET /api/admin/relay/queue?status=pending`, `POST .../approve`, `POST .../reject` - Background poll loop: every 30 seconds, process up to 10 pending events via `autoReview` _Note: This is the root cause of the P0 infinite re-review bug (#27) where `processPending()` never transitions events out of `pending`. The fix is adding a `"flagged"` status transition after AI flags an event._ ## Out of scope - Admin UI (see relay admin panel issue) - Spam/rate-limit heuristics - NIP-40 expiration handling ## Tasks 1. **DB schema** — Add `relay_event_queue` table. Run `db:push`. 2. **Policy endpoint update** — For `write` access (non-elite): insert event → return `shadowReject`. For `elite`: inject event → return `accept`. 3. **strfry HTTP import helper** — `injectEvent(rawEvent)` calling strfry `POST /import` endpoint. 4. **ModerationService** — `enqueue`, `autoReview` (Haiku call; on flag → set status to `flagged` not `pending` to prevent re-review loop), `decide` (updates DB + calls `injectEvent` on approval). 5. **Background poll loop** — `setInterval` on startup; process up to 10 `pending` events every 30 s. 6. **Admin queue routes** — GET/approve/reject under `/api/admin/relay/queue`. Admin auth middleware. ## Relevant files - `lib/db/src/schema/index.ts` - `artifacts/api-server/src/lib/agent.ts` - `artifacts/api-server/src/routes/index.ts`
replit added the aibackendnostr labels 2026-03-21 00:41:20 +00:00
gemini was assigned by Rockachopa 2026-03-22 23:37:27 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: replit/timmy-tower#48