Skip to content

Repository files navigation

Nest

License

Nest is a content moderation rules engine that evaluates user-submitted items against Starlark-based rules, producing verdicts (approve, block, review) with optional webhook actions and manual review routing. It is a single Go binary backed by PostgreSQL.

Prerequisites

  • Go 1.25+
  • PostgreSQL 16+
  • Python 3.11+ (for the admin UI only)

Quick Start

1. Database Setup

Create a PostgreSQL database:

createdb nest

2. Run Migrations

DATABASE_URL="postgres://user:pass@localhost:5432/nest?sslmode=disable" make migrate

Check migration status:

DATABASE_URL="..." go run ./cmd/migrate/ status

3. Seed Default Data (Development)

The seed tool creates a default org, admin user, and MRT queues for development/testing:

DATABASE_URL="..." go run ./cmd/seed/

Or with make:

DATABASE_URL="..." make seed

This creates:

Entity ID Details
Org org-default "Default Org"
Admin User usr-admin-default Email: admin@nest.local, Password: admin123, Role: ADMIN
MRT Queue mrtq-default "default"
MRT Queue mrtq-urgent "urgent"
MRT Queue mrtq-escalation "escalation"

WARNING: Do not use these credentials in production.

All seed operations are idempotent (safe to run multiple times).

4. Set Environment Variables

Required:

export DATABASE_URL="postgres://user:pass@localhost:5432/nest?sslmode=disable"
export SESSION_SECRET="your-secret-key-at-least-32-chars"

Optional (with defaults):

Variable Default Description
PORT 8080 HTTP listen port
WORKER_COUNT runtime.NumCPU() Starlark worker pool size
RIVER_WORKER_COUNT 100 Background job worker count
RULE_TIMEOUT 1s Per-rule evaluation timeout
EVENT_TIMEOUT 5s Per-event total evaluation timeout
LOG_LEVEL info Logging level (debug, info, warn, error)
DEV_MODE false Enable development mode
COUNTER_BACKEND memory Counter storage: memory or postgres
OPENAI_API_KEY (empty) OpenAI API key (enables moderation signal adapter, empty = disabled)
OPENAI_MODERATION_MODEL omni-moderation-latest OpenAI moderation model name
OPENAI_MODERATION_TIMEOUT 5s HTTP timeout for OpenAI moderation requests
OPENAI_MODERATION_MAX_INPUT 102400 Max input bytes for OpenAI moderation

5. Build and Run the Server

make build
./nest

Or run directly:

go run ./cmd/server/

6. Run the Admin UI (Optional)

cd nest-ui
pip install nicegui httpx
NEST_API_URL="http://localhost:8080" python main.py

The UI runs on http://localhost:8090 by default. Optional environment variables:

Variable Default Description
UI_PORT 8090 UI server port
UI_SECRET change-me-in-production NiceGUI storage secret

Key Commands

make build      # Compile binary (CGO_ENABLED=0)
make test       # Run full test suite
make vet        # Run go vet
make lint       # Run go vet (alias for vet)
make docker     # Build Docker image
make migrate    # Apply database migrations
make seed       # Seed default org, admin user, and MRT queues
make run        # Run server directly with go run
make clean      # Remove compiled binary

Run a single test:

go test ./internal/engine/... -run TestCompiler -v

Jetstream Test (Bluesky Firehose Integration)

The Jetstream test connects to the live Bluesky AT Protocol firehose via WebSocket, consumes real posts and likes, submits them to a local Nest instance for rule evaluation, and validates the results. This is an end-to-end integration test using real-world data.

Prerequisites

  • Docker (for PostgreSQL via docker-compose)
  • Go 1.25+ (to build all binaries)
  • Internet access (the consumer connects to wss://jetstream2.us-east.bsky.network/subscribe)
  • Ports 8080 and 9090 must be free (Nest API and webhook receiver respectively)

Running the Test

There are two modes:

Count-limited mode (run.sh)

Consumes a fixed number of items from the firehose, then validates:

# Default: 1000 items
./jetstream/run.sh

# Custom count: 500 items
./jetstream/run.sh 500

This script runs through 8 steps:

  1. Starts PostgreSQL via docker-compose (port 5433)
  2. Builds all binaries (nest server, migrate, seed, setup, consumer, receiver, validate)
  3. Runs migrations, seeds default data, and cleans test tables
  4. Starts a webhook receiver on port 9090
  5. Starts the Nest server on port 8080
  6. Runs test setup (creates item types, rules, actions, API key)
  7. Runs the Jetstream consumer until the item count is reached
  8. Waits for the pipeline to drain, then runs validation

Time-limited mode (run_timed.sh)

Consumes from the firehose for a fixed duration, then validates:

# Default: 2 minutes
./jetstream/run_timed.sh

# Custom duration: 5 minutes
./jetstream/run_timed.sh 5

Same setup steps as run.sh, but the consumer runs continuously in the background for the specified number of minutes. Progress is printed every 30 seconds. After the timer expires, the consumer is stopped and validation runs.

What Gets Set Up

The test scripts automatically create the following via the seed and setup tools:

Entity Details
Org Default Org (ID: org-default)
Admin User Email: admin@nest.local, Password: admin123, Role: ADMIN
MRT Queues default, urgent, escalation
Item Types post (text + entity_id), like (entity_id + subject_uri)
Actions webhook-notify (WEBHOOK to :9090), mrt-review (ENQUEUE_TO_MRT to default queue)
Rules Loaded from loadtest/rules/*.star (catchall, spam detection, content filters, etc.)
API Key nest-test-key (auto-generated, saved to /tmp/nest_test_api_key.txt)

Seeded Credentials

To log in to the Nest API or UI during a test run:

Field Value
Email admin@nest.local
Password admin123

WARNING: These credentials are for development and testing only. Do not use them in production.

Accessing Nest During a Test Run

While a test is running (especially useful with run_timed.sh for longer durations):

  • Nest API: http://localhost:8080 (e.g., http://localhost:8080/api/v1/health)
  • Login: POST http://localhost:8080/api/v1/auth/login with {"email": "admin@nest.local", "password": "admin123"}

You can create additional rules, inspect items, review MRT queues, and observe verdicts in real time against live Bluesky data.

OpenAI Moderation (Optional)

If you set OPENAI_API_KEY before running the test, the setup will load additional rules from loadtest/rules/optional/ that use the OpenAI moderation signal adapter. An openai MRT queue is also created for flagged content review.

export OPENAI_API_KEY="sk-..."
./jetstream/run_timed.sh 5

Docker Demo (All-in-One)

For a fully self-contained demo with PostgreSQL, Nest, Jetstream consumer, and the NiceGUI admin UI in a single container:

docker build -f Dockerfile.demo -t nest-demo .
docker run -p 8080:8080 -p 8090:8090 nest-demo

After startup completes:

  • Nest API: http://localhost:8080
  • Admin UI: http://localhost:8090
  • Login: admin@nest.local / admin123

The demo container automatically runs migrations, seeds data, starts the Nest server, begins consuming from the Bluesky firehose, and launches the admin UI.

Cleanup

The test scripts clean up automatically on exit (processes are killed, temp binaries removed). To stop the PostgreSQL container started by docker-compose:

docker compose -f loadtest/docker-compose.yml down

To also remove the persisted data volume:

docker compose -f loadtest/docker-compose.yml down -v

Architecture

Nine Go packages under internal/:

domain   -- Pure types, zero imports
config   -- Environment configuration
store    -- PostgreSQL data access (pgx)
auth     -- Sessions, API keys, RBAC, password hashing, webhook signing
signal   -- Signal adapter framework (TextRegex, TextBank, HTTP)
engine   -- Starlark rule evaluation: Pool, Workers, Snapshots
service  -- Business logic orchestration
worker   -- Background jobs via river (item processing, snapshot rebuild)
handler  -- HTTP handlers and chi routing

Dependency flow: domain -> store -> auth/signal -> engine -> service -> worker/handler. No cycles.

Documentation

License

Copyright 2026 Vinay Rao. Licensed under the Apache License, Version 2.0.

About

Content moderation rules engine — Starlark rules, PostgreSQL, Go backend, NiceGUI frontend

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages