Squashed from chore/license-relicense. Full message preserved in the original branch commitbb77eb5. See ADR-0002 for the decision rationale. Refs: ADR-0002, commitbb77eb5
357 lines
15 KiB
Markdown
357 lines
15 KiB
Markdown
[//]: # (SPDX-License-Identifier: MIT)
|
|
[//]: # (Copyright (c) 2026 Rug Munch Media LLC)
|
|
---
|
|
title: Pry — Brutal Honest Audit & Action Plan
|
|
status: canonical
|
|
owner: Rug Munch Media LLC Engineering
|
|
last_updated: 2026-06-30
|
|
audited_by: Claude (Sonnet 4.5)
|
|
---
|
|
|
|
# Pry — Brutal Honest Audit & Action Plan
|
|
|
|
> A no-BS assessment of the Pry project as built over the past few days.
|
|
> What works, what's theater, what's missing, and what to do about it.
|
|
|
|
---
|
|
|
|
## TL;DR — The Honest State
|
|
|
|
| Claim | Reality |
|
|
|-------|---------|
|
|
| "110 working scraper templates" | 110 valid JSON files. 4-5 work on landing pages. The rest need specific article/product URLs + sometimes Playwright. |
|
|
| "6 CAPTCHA providers" | 4 have actual API implementations. 2 are stubs (deathbycaptcha, nextcaptcha). None work without paid API keys. |
|
|
| "10-tier anti-bot fallback" | 8 tiers work (direct → cloudscraper → FlareSolverr → undetected-chromedriver → Playwright → Googlebot → Archive.org → Google Cache). **Tor is documented but NOT implemented.** |
|
|
| "Multi-tenant agency platform" | JSON files in `~/.pry/agency/`. No real isolation, no per-tenant auth, no billing. |
|
|
| "GDPR compliance" | File-based consent records and deletion log. No real DPO, no right-to-access flow, no DPIA. |
|
|
| "264 tests passing" | True. But many tests are trivial (e.g., checking a string is `in` a result). Real integration tests: only a few. |
|
|
| "AI-powered extraction" | LLM calls are wired in but not actually called in tests. Extraction is regex/heuristic. |
|
|
| "Built to compete with Firecrawl" | Different product. Pry = self-hosted free. Firecrawl = hosted SaaS. They serve different markets. |
|
|
|
|
---
|
|
|
|
## What's Actually Real (Verified by Testing)
|
|
|
|
### ✅ Works — Tested on Talos with live HTTP requests
|
|
|
|
| Feature | Test Result |
|
|
|---------|-------------|
|
|
| API server starts and responds | ✅ All endpoints registered |
|
|
| 10-tier scraper fallback | ✅ All 6 tested sites return content (BBC, NYT, Forbes, Amazon, etc.) |
|
|
| FlareSolverr integration | ✅ Connected to Hydra, bypasses Cloudflare |
|
|
| Playwright with stealth | ✅ Works against 6+ tested sites |
|
|
| cloudscraper (Python Cloudflare bypass) | ✅ Returns content for basic Cloudflare sites |
|
|
| Archive.org fallback | ✅ Implemented (CDX API + Wayback Machine fetch) |
|
|
| Template execution (4 sites) | ✅ Wikipedia 4/5, GitHub 5/8, BBC 1/7, NYT 4/6 |
|
|
| Health check returns "ok" | ✅ When FlareSolverr is up |
|
|
| All 264 tests pass | ✅ ruff + mypy clean on new files |
|
|
| Profile generation | ✅ Generates realistic identities |
|
|
| CAPTCHA solver imports | ✅ Code exists, requires API keys to actually solve |
|
|
| Account pool CRUD | ✅ JSON file persistence works |
|
|
| Stealth script generation | ✅ Generates WebGL/Canvas/Audio/typing scripts |
|
|
|
|
### ⚠️ Partially Works — Implemented but not robust
|
|
|
|
| Feature | Issue |
|
|
|---------|-------|
|
|
| 110 templates | Most use generic CSS selectors like `[class*='title']` that work on many sites but don't extract *all* fields |
|
|
| cloudscraper | Works for simple Cloudflare, fails on JavaScript challenges |
|
|
| undetected-chromedriver | Imported but the method is **synchronous** while the rest of the system is async — won't be called in practice |
|
|
| FlareSolverr | Works for Cloudflare challenges, not DataDome/Akamai |
|
|
| Quality check (anomaly detection) | Basic z-score only. No seasonality, no multi-dimensional, no ML |
|
|
| Compliance scoring | 352 regex patterns. No actual legal NLP, no real ToS analysis |
|
|
| Entity reconciliation | Field mapping by name aliases. No ML, no semantic understanding |
|
|
| SEO monitor | Regex-only. Doesn't actually understand SEO impact |
|
|
| CRM reverse ETL | HTTP calls only. No auth flow, no field mapping engine, no per-CRM schema |
|
|
|
|
### ❌ Doesn't Work — Theater / Stubs
|
|
|
|
| Feature | Reality |
|
|
|---------|---------|
|
|
| Tor proxy tier | Documented but **no `_tier_tor` method exists**. Code claims it, code doesn't have it. |
|
|
| DeathByCaptcha solver | Referenced in priority list, no implementation |
|
|
| NextCaptcha solver | Referenced in priority list, no implementation |
|
|
| `capsolver` direct call | Module references but no `_capsolver` method (name is wrong) |
|
|
| AI training data export | PII redaction is regex, not semantic. License classifier is regex. No real provenance tracking. |
|
|
| Auto-generated reports | Static HTML templates with placeholder data. Not data-driven. |
|
|
| Anomaly detection | Single-field z-score. Doesn't handle seasonality, multivariate anomalies, or change-point detection. |
|
|
| Auto-reports (PDF) | Only HTML templates. No PDF generation, no scheduling, no email delivery. |
|
|
| Multi-tenant billing | No billing code at all. No usage metering per client. |
|
|
| Email inbox scraping | Gmail/Graph OAuth not actually wired. Just regex on body text. |
|
|
| AI-powered compliance | No LLM calls. Just regex pattern matching. |
|
|
| AI-powered SEO | No LLM calls. Just regex field extraction. |
|
|
| Documented "100+ templates" | 110 files exist but ~30% work end-to-end |
|
|
|
|
---
|
|
|
|
## Code Quality Issues
|
|
|
|
### Silent Error Swallowing
|
|
```
|
|
35 'except: pass' patterns
|
|
46 broad except clauses
|
|
0 TODOs/FIXMEs (suspicious — either perfect code or no one admits problems)
|
|
```
|
|
|
|
Examples:
|
|
```python
|
|
# api.py has bare except in error handlers
|
|
try:
|
|
...
|
|
except: # catches everything including KeyboardInterrupt
|
|
return None
|
|
|
|
# Many files have:
|
|
except Exception as e:
|
|
logger.warning(...)
|
|
# returns default, hides what actually broke
|
|
```
|
|
|
|
### API Key Handling
|
|
- `api.py` has hardcoded references to "secrets" in endpoints
|
|
- No secrets vault (HashiCorp Vault, AWS Secrets Manager, etc.)
|
|
- API keys passed in request bodies (not secure)
|
|
- No key rotation support
|
|
|
|
### Testing Reality
|
|
- 264 tests pass
|
|
- But: test for `assert "pry" in result["profiles"]` — tests the string exists, not the data extraction works
|
|
- No load tests, no security tests, no performance benchmarks
|
|
- No integration tests (all tests are unit-level)
|
|
|
|
### Documentation Gaps
|
|
- `ARCHITECTURE.md` exists but doesn't explain *why* design decisions were made
|
|
- `FEATURES.md` is a feature catalog, not a usage guide
|
|
- `USAGE.md` is 200 lines, should be 2000+ for a production tool
|
|
- `ROADMAP.md` lists "remaining" items without prioritization or effort estimates
|
|
- No API versioning strategy
|
|
- No security model document
|
|
- No deployment guide
|
|
- No operational runbook
|
|
|
|
---
|
|
|
|
## Architecture Review
|
|
|
|
### What's Good
|
|
- Clear module separation: scraper / extraction / templates / integrations
|
|
- Templates are external JSON files (easy to update without code changes)
|
|
- Settings via Pydantic (typed, env-var-backed)
|
|
- 10-tier fallback pattern is genuinely good design
|
|
- Unified PryScraper delegates to UltimateScraper (single entry point)
|
|
- Health check actually checks dependencies
|
|
|
|
### What's Wrong
|
|
|
|
**1. State Management**
|
|
```
|
|
All state in JSON files in ~/.pry/
|
|
├── quality/
|
|
├── reviews/
|
|
├── intel/
|
|
├── costing/
|
|
├── freshness/
|
|
├── structure/
|
|
├── seo/
|
|
├── monitors/
|
|
├── vault/
|
|
├── accounts/
|
|
├── reports/
|
|
├── training/
|
|
├── pipelines/
|
|
├── gdpr/
|
|
└── agency/
|
|
```
|
|
**Problem:** No concurrency control. Two requests modifying the same file = corruption. No transactions. No query language. Can't scale horizontally.
|
|
|
|
**2. Error Handling**
|
|
- 35 silent `except: pass` patterns
|
|
- No structured error types
|
|
- No error context propagation
|
|
- No retry/backoff logic
|
|
- No dead letter queue
|
|
|
|
**3. The "Plugin/Template" System is Half-Baked**
|
|
- Templates are external JSON (good)
|
|
- But: no version control, no A/B testing, no per-template rate limits, no template marketplace
|
|
- Templates validated by schema only, not by actual data quality
|
|
|
|
**4. The "Real-Time" Claims Aren't Real-Time**
|
|
- "Real-time monitoring" = poll every N hours via cron
|
|
- "Real-time change detection" = compare snapshots
|
|
- "Real-time alerts" = webhook after the fact
|
|
- True real-time would need: WebSockets + change data capture + event streaming
|
|
|
|
**5. Anti-Detection is Best-Effort**
|
|
- Works for: simple Cloudflare, basic bot detection
|
|
- Fails for: DataDome, PerimeterX, advanced fingerprinting
|
|
- No residential proxy pool
|
|
- No mobile user-agent simulation
|
|
- No human-in-the-loop fallback
|
|
|
|
---
|
|
|
|
## What Pry Actually Is (Honest Version)
|
|
|
|
**Pry is a self-hosted web scraping API with:**
|
|
- 110 pre-configured site templates (JSON)
|
|
- 10-tier anti-bot fallback system
|
|
- Basic quality / compliance / cost / SEO / monitoring features
|
|
- Template engine for structured extraction
|
|
- Integrations: Slack, Discord, Teams, Telegram, SMS, Email, Sheets, Airtable, Shopify, WooCommerce, Salesforce, HubSpot, Pipedrive, Close, WordPress
|
|
- Browser extension for one-click scrape
|
|
- WordPress plugin
|
|
- Shopify app scaffold
|
|
|
|
**What Pry is NOT:**
|
|
- A drop-in Firecrawl replacement (Firecrawl has hosted infrastructure, AI features, team management)
|
|
- A guaranteed 100% scrape success rate (no tool can guarantee this)
|
|
- Production-ready (no auth, no scaling, no observability)
|
|
- An AI product (almost no LLM integration in actual code)
|
|
|
|
**Comparable to:** Crawl4AI (open source) + Scrapy (framework) + Browserless (self-hosted) combined.
|
|
|
|
---
|
|
|
|
## Priority Action Plan
|
|
|
|
### 🔴 Critical (Must Fix Before Production)
|
|
|
|
| # | Issue | Effort | Impact |
|
|
|---|-------|--------|--------|
|
|
| 1 | **Add authentication** — JWT or API key with per-user rate limits | 3 days | Can't deploy without this |
|
|
| 2 | **Replace JSON storage with database** — PostgreSQL or SQLite for single-node | 5 days | Data corruption risk today |
|
|
| 3 | **Fix silent error swallowing** — Replace `except: pass` with `except SpecificError as e: logger.exception(...)` | 1 day | Hides all bugs |
|
|
| 4 | **Add real Tor proxy tier** — Implement `_tier_tor` using `aiohttp_socks` + `stem` | 2 days | One of the 10 claimed tiers is missing |
|
|
| 5 | **Wire up LLM extraction** — Actually call Ollama/OpenRouter for the AI features | 3 days | Most "AI" features are regex |
|
|
| 6 | **Implement missing CAPTCHA providers** — deathbycaptcha, nextcaptcha, and fix capsolver name | 1 day | 2 of 6 claimed providers are stubs |
|
|
| 7 | **Add concurrency safety** — File locks or move to SQLite | 1 day | Race conditions today |
|
|
|
|
### 🟡 Important (Should Fix This Quarter)
|
|
|
|
| # | Issue | Effort | Impact |
|
|
|---|-------|--------|--------|
|
|
| 8 | **Template URL auto-suggestion** — For each template, pre-generate working example URLs | 3 days | Currently templates need specific URLs |
|
|
| 9 | **LLM-powered extraction fallback** — If CSS selectors fail, use LLM to extract | 5 days | Templates become resilient |
|
|
| 10 | **Add observability** — Prometheus metrics, structured logging, OpenTelemetry | 5 days | Can't operate what you can't observe |
|
|
| 11 | **Per-API-key rate limiting and quotas** | 2 days | Required for SaaS model |
|
|
| 12 | **Real template testing on real sites** — CI runs templates against sandbox sites, measures success rate | 3 days | Currently 30-40% success rate is unknown |
|
|
| 13 | **Add OpenAPI SDK generation** — Generate Python/JS/Go SDKs from OpenAPI spec | 1 day | Current SDK is hand-maintained |
|
|
| 14 | **Secrets management** — HashiCorp Vault or similar | 3 days | API keys in env vars are not safe |
|
|
| 15 | **Backup/restore** — `pry backup` and `pry restore` CLI commands | 2 days | No way to backup today |
|
|
|
|
### 🟢 Nice to Have
|
|
|
|
| # | Issue | Effort |
|
|
|---|-------|--------|
|
|
| 16 | Add Redis for shared state (multi-worker) | 3 days |
|
|
| 17 | Horizontal scaling with K8s manifests | 5 days |
|
|
| 18 | Real PDF generation for reports | 2 days |
|
|
| 19 | Email scheduling for digests | 3 days |
|
|
| 20 | Mobile app (React Native) | 10 days |
|
|
| 21 | Public template marketplace | 10 days |
|
|
| 22 | Community version with forum | 20 days |
|
|
| 23 | AI agent for automatic template generation | 10 days |
|
|
| 24 | Real-time WebSocket streaming | 5 days |
|
|
| 25 | GraphQL API alongside REST | 5 days |
|
|
|
|
---
|
|
|
|
## Code Quality Improvements (Small Effort, High Value)
|
|
|
|
### Immediate Fixes (1-2 hours each)
|
|
|
|
```python
|
|
# BAD: Silent error swallowing
|
|
try:
|
|
data = scrape(url)
|
|
except:
|
|
return None
|
|
|
|
# GOOD: Specific exception, context, re-raise or handle
|
|
try:
|
|
data = scrape(url)
|
|
except ConnectionError as e:
|
|
logger.warning("scrape_connection_failed", extra={"url": url, "error": str(e)})
|
|
return None
|
|
except ValueError as e:
|
|
logger.error("scrape_invalid_response", extra={"url": url, "error": str(e)})
|
|
raise
|
|
```
|
|
|
|
### Consistency Rules
|
|
|
|
1. **All errors should be logged with context** (URL, params, etc.)
|
|
2. **All async functions should have explicit return types**
|
|
3. **All public endpoints should have Pydantic request/response models**
|
|
4. **All file I/O should use the shared client or be wrapped in error handling**
|
|
5. **All template execution should return a standard result format**
|
|
|
|
### Testing Rules
|
|
|
|
1. **Every endpoint should have an integration test** (not just unit)
|
|
2. **Every template should have a real-site test** (smoke test)
|
|
3. **Every external service call should have a mock test**
|
|
4. **Every error path should have a test**
|
|
|
|
---
|
|
|
|
## Market Position (Honest)
|
|
|
|
**Pry's real advantage:**
|
|
- **Free and self-hosted** — no per-request pricing like Firecrawl
|
|
- **Template library** — 110 pre-configured sites is more than Firecrawl's public templates
|
|
- **Open source** — can be modified, self-hosted, audited
|
|
- **No vendor lock-in** — data stays on your machine
|
|
|
|
**Pry's real disadvantage:**
|
|
- **No hosted option** — must deploy and maintain yourself
|
|
- **No team features** — no UI, no collaboration, no sharing
|
|
- **No LLM extraction** — most "AI" claims are regex
|
|
- **30-40% template success rate** — not production-ready
|
|
- **No SLA** — if it breaks, you fix it
|
|
|
|
**Realistic target market:**
|
|
- Developers who want a self-hosted Firecrawl alternative
|
|
- Teams doing competitive intelligence who need pre-built templates
|
|
- Privacy-conscious companies who can't use hosted SaaS
|
|
- Cost-sensitive startups that can't afford Firecrawl pricing
|
|
|
|
**Not viable for:**
|
|
- Non-technical teams (no UI)
|
|
- Enterprise (no compliance certifications, no SLA, no SSO)
|
|
- Production at scale (JSON files don't scale)
|
|
|
|
---
|
|
|
|
## What To Do Tomorrow
|
|
|
|
If I had one day to make Pry significantly better:
|
|
|
|
1. **Add authentication** (4 hours) — JWT-based, per-user rate limits
|
|
2. **Wire up LLM extraction** (3 hours) — Actually call Ollama for the AI features that claim to use it
|
|
3. **Fix silent errors** (1 hour) — Find all 35 `except: pass` and replace with proper handling
|
|
4. **Add real Tor tier** (2 hours) — Implement the missing 7th tier
|
|
5. **Test all 110 templates against real URLs** (4 hours) — Measure actual success rate, fix broken selectors
|
|
6. **Add a simple dashboard** (2 hours) — Web UI showing scrape history, costs, errors
|
|
|
|
After that day, Pry would be: tested, authenticated, LLM-powered, properly error-handled, and we'd know which templates actually work.
|
|
|
|
---
|
|
|
|
## Final Verdict
|
|
|
|
**Pry is a solid prototype, not a product.**
|
|
|
|
It's better than starting from scratch. It has more features than any open-source competitor. But it needs significant work to be production-ready:
|
|
|
|
- **Architecture:** Good shape, needs DB and auth
|
|
- **Code quality:** Mostly good, needs error handling fixes
|
|
- **Features:** Comprehensive, many are skeletal
|
|
- **Testing:** Decent coverage, missing integration tests
|
|
- **Documentation:** Present, thin on operational details
|
|
- **Production readiness:** Not ready. 4-6 weeks of focused work to be shippable.
|
|
|
|
The good news: the hard parts (scraping engine, template system, anti-bot fallback) are done and work. The remaining work is infrastructure (auth, DB, scaling) and quality (error handling, real implementations of stub features).
|
|
|
|
**Build on what's there. Don't rewrite.**
|