Install Sentinel

Civic-AI intrusion counter-measure for Node.js sites. Free to install. Connects to the WellSpr.ing collective blocklist.

Optimised for Replit. DATABASE_URL is already set on every Replit project. Add the Resend integration in one click for email. Tables are created on first startup.

What Sentinel does

Step 1 — Download the middleware

Download one file. No package installation required.

GET https://netsentinel.org/sentinel.ts — TypeScript / ESM (Replit standard, tsx, Hono, Express)

GET https://netsentinel.org/sentinel.js — Node.js CommonJS (plain JS, require(), older Express)

Step 2 — Mount the middleware

Add these three lines to your server file before your application routes:

import { sentinelMiddleware, sentinelAdminRouter, sentinelPublicHandler }
  from './sentinel.js';   // .js extension required in ESM

// Mount BEFORE your routes
app.use(sentinelMiddleware);
app.use('/api/admin/sentinel', sentinelAdminRouter);
app.get('/api/sentinel/public', sentinelPublicHandler);

Step 3 — Set environment variables

DATABASE_URL=...              # Replit: already set automatically
SENTINEL_ADMIN_EMAIL=you@yoursite.com
SENTINEL_DOMAIN=yoursite.com
SENTINEL_NETWORK_KEY=...      # Optional — from Step 4 below
RESEND_API_KEY=...            # Replit: install the Resend integration

Step 4 — Get a free partner API key (optional)

A partner key joins the WellSpr.ing collective blocklist — your server blocks IPs caught by others and contributes its catches to the network.

POST https://netsentinel.org/api/sentinel/register
Content-Type: application/json

{ "name": "Your Name", "email": "you@example.com", "domain": "yoursite.com" }

Returns { "apiKey": "ns_..." }. Set SENTINEL_NETWORK_KEY=<apiKey> in your environment.

Database setup (automatic)

On first startup Sentinel creates two tables automatically:

bot_incidents     — every probe event: IP, path, probe type, abuse report status
sentinel_blocklist — auto-blocked IPs with first/last seen timestamps

If you prefer to create them manually:

psql $DATABASE_URL -c "
CREATE TABLE IF NOT EXISTS bot_incidents (
  id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
  ip VARCHAR NOT NULL, path VARCHAR, domain VARCHAR,
  user_agent TEXT, method VARCHAR DEFAULT 'GET',
  probe_type VARCHAR, ip_org VARCHAR, ip_country VARCHAR,
  ip_range VARCHAR, abuse_contacts TEXT, report_sent_at TIMESTAMPTZ,
  report_email VARCHAR, action_taken VARCHAR DEFAULT 'blocked',
  source VARCHAR, created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sentinel_blocklist (
  id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
  ip VARCHAR UNIQUE NOT NULL, probe_count INT DEFAULT 1,
  ip_org VARCHAR, ip_country VARCHAR, block_reason VARCHAR,
  first_seen TIMESTAMPTZ, last_seen TIMESTAMPTZ,
  blocked_at TIMESTAMPTZ DEFAULT now(), unblocked_at TIMESTAMPTZ
);"

Public API

Discovery files