Skip to content

pitbot: pit.world's own crawler and index (0.13.0) - #91

Merged
sh1pt-actions-fleet[bot] merged 2 commits into
mainfrom
feat/crawler
Nov 2, 2026
Merged

sh1pt-actions-fleet[bot] merged 2 commits into
mainfrom
feat/crawler

Conversation

@sh1pt-actions-fleet

@sh1pt-actions-fleet sh1pt-actions-fleet Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Adds services/crawler (a Bun workspace): pitbot, a BullMQ spider that builds pit.world's own index and publishes it to nichedb.dev, plus a pit engine that fuses that index into every search.

Crawl

  • Queues on pit.world's own Redis: pit-crawl-site (robots.txt, sitemaps, home page), pit-crawl-page (shallow first), pit-crawl-render (JS shells re-read in Obscura, one page per server), pit-crawl-publish (outbox → POST nichedb.dev/api/v1/sites/records every 5 s; hourly recrawl after the 30-day cycle).
  • Up to 1,000 pages per site, exact under races (one Lua call). A site inside its request gap is moved back to delayed, not held, so thousands of sites interleave. Any number of workers on any number of boxes share one crawl.
  • Manners: robots.txt (pitbot group, Crawl-delay ≤30 s), noindex/nofollow, no nofollow/sponsored/ugc links, no private addresses at any redirect hop (name + DNS), media/traps skipped. /bot page explains it and how to opt out.
  • Enrichment: language, keywords (→ topic: tags), main-text excerpt (→ summary), word/link counts, rendered flag, depth, text hash (unchanged pages are not rewritten).
  • Backfill: seed --from nichedb (every site nichedb's /c/sites keeps), --from ring, files, names.

Search: pit provider ("pit.world index") last in PRIMARY, reading nichedb.dev/api/v1/search?collection=sites. On by default; PIT_INDEX_URL=off disables, PIT_INDEX_KEY adds a bearer.

/status (like rssamplifier's /crawlstats): health verdict (healthy/idle/degraded/stalled/offline), stat grid, pages per hour for 24 h, jobs table (backlog, rate, errors, time to clear), live log with each page linked to its nichedb record; refreshes every 15 s, JSON at /api/status. The crawler keeps minute/hour counter buckets and a 200-line event log in Redis and serves them on loopback /stats; pit.world reads that (CRAWLER_STATUS_URL, default 127.0.0.1:8807).

Deploy: deploy/crawler/docker-compose.yml (crawler + Redis + 2 Obscura, loopback only, healthcheck), poll.sh rebuilds on new commits to main. Already booted from this branch on dev2 (~/www/pit-crawler, /healthz on 127.0.0.1:8807).

Tests: 242 pass (bun test), including the real-Redis frontier/queue tests (CI gets a Redis service) and a real Obscura render of react.dev locally. Both typechecks clean. ThreatCrush --deps --fail-on medium clean; this also suppresses the false positive that has kept main red since #90 (deploy.yml rebuilds the secret's key armour; nothing committed).

Depends on profullstack/niche-db#265 (merged, v0.57.0).

🤖 Generated with Claude Code

A BullMQ spider in a new services/ workspace: up to 1,000 pages per site,
JavaScript-only pages rendered in Obscura, each page enriched (language,
keywords, excerpt, counts, text hash) and published as an OpenSite record
to nichedb.dev/c/sites through POST /api/v1/sites/records (nichedb 0.57.0).

- Four queues on pit.world's own Redis: site (robots.txt, sitemaps, home),
  page (shallow first; a site inside its request gap is delayed, not held),
  render (one page per Obscura server), publish (outbox to nichedb every 5 s,
  hourly recrawl of sites whose 30-day cycle ran out).
- Exact per-site admission and page cap in one Lua call; any number of
  workers on any number of boxes share the crawl.
- robots.txt (pitbot group, Crawl-delay), noindex/nofollow, no private
  addresses at any redirect hop, media/traps skipped.
- Backfill: seed --from nichedb (every site /c/sites keeps) or --from ring.
- Search: 'pit' engine fused with the others, reading nichedb's sites
  collection (PIT_INDEX_URL, on by default; PIT_INDEX_URL=off disables).
- /bot page; privacy page names the index.
- Deploy: deploy/crawler docker compose (crawler + Redis + 2 Obscura),
  poll.sh rebuilds on new commits to main.
- CI: Redis service for the crawler's integration tests, crawler typecheck;
  ThreatCrush false positive on deploy.yml's key armour suppressed (main
  was red on it since #90).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@socket-security

socket-security Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednode-html-parser@​9.0.69810010091100
Addedioredis@​5.11.19410010093100
Addedbullmq@​5.81.59410010096100

View full report

The crawler now keeps its counters in minute and hour buckets and a
200-line event log in Redis, and answers /stats on loopback with queue
depths, hour/day rates, the hourly curve, the log tail and its settings.
pit.world reads that (CRAWLER_STATUS_URL, default 127.0.0.1:8807, 3 s
leash, 5 s cache) and draws /status: a health verdict (healthy, idle,
degraded, stalled, offline), a stat grid, pages per hour for 24 hours,
a jobs table with backlog, rate, errors and time to clear, and the live
log with each page linked to its nichedb record. Refreshes every 15 s;
/api/status is the same as JSON. A crawler that does not answer shows as
offline, never as an error page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sh1pt-actions-fleet
sh1pt-actions-fleet Bot merged commit 514dbd1 into main Nov 2, 2026
4 checks passed
@sh1pt-actions-fleet
sh1pt-actions-fleet Bot deleted the feat/crawler branch November 2, 2026 04:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant