125 Commits
Author SHA1 Message Date
germondai f08f5a2b44 chore(release): prepare v1.2.0 2026-07-26 16:18:47 +02:00
germondai 6d49011114 refactor(web): simplify GitHub stars fallback 2026-07-26 15:12:09 +02:00
germondai a71f1ac8d3 docs(proxy): add setup and operation guides 2026-07-26 13:18:27 +02:00
germondai eff5760ef5 feat(api): wire proxy lifecycle and context cache 2026-07-25 17:42:11 +02:00
germondai e62e73554c feat(proxy): route traffic through tiered fallback 2026-07-25 15:13:58 +02:00
germondai d7cca3ec44 feat(proxy): add challenge-aware response policy 2026-07-25 12:47:26 +02:00
germondai ce028e201c feat(proxy): add adaptive direct forwarding 2026-07-25 10:22:39 +02:00
germondai 2840af1d13 chore(release): bump all packages to v1.1.0 2026-07-22 23:13:17 +02:00
germondai 7107b2f224 feat(proxy): make host required + universal challenge wall detection 2026-07-22 23:13:16 +02:00
germondai 3b3b643904 fix(proxy): bind listener to loopback by default with MITM_PROXY_HOST override 2026-07-22 19:50:30 +02:00
germondai 331df98dca feat(proxy): rotate proxy pool in fetchRaw on CF challenge 2026-07-22 19:50:08 +02:00
GermondandGitHub 28eda7ca57 Merge branch 'dev' into feat/mitm-proxy-mode 2026-07-22 16:38:18 +02:00
germondai 6223a4e593 perf: release v1.0.1 - slimmer image, faster boot, firefox telemetry/dead-feature prefs 2026-07-21 18:31:26 +02:00
aziz66andClaude Fable 5 aa719dd1fa feat(proxy): browser-backed MITM forward-proxy mode
The FlareSolverr /v1 contract only returns cookies + user-agent. Clients like
Prowlarr take those and re-fetch the target with their own HTTP stack, which is
re-challenged on sites whose Cloudflare clearance is bound to the solving
browser's connection fingerprint (e.g. 1337x) — no cookie is portable to a
plain HTTP client, so those indexers can't be used at all.

Add an optional HTTP(S) forward proxy (MITM_PROXY_ENABLED). Point such a client's
proxy at it (per-indexer HTTP proxy in Prowlarr) and every request — search and
the .torrent/magnet grab — is transparently re-issued through the browser pool,
returning the RAW response bytes so binary downloads pass through intact.

- ca.ts: self-generated CA (persisted) + on-demand per-host leaf certs
- server.ts: per-host loopback-TLS termination (Bun's node:tls can't drive a
  handshake via emit("connection") or honor SNICallback, so one listening TLS
  server per host is the reliable path); raw-byte capture via page.goto response
  body, with the download-event path for binaries; scrape() fallback solves CF
- /proxy-ca.crt route to fetch the CA for the client's trust store
- New env: MITM_PROXY_{ENABLED,PORT,CA_DIR,MAX_TIER,DEBUG}

Off by default; localhost-only by design (a MITM proxy can impersonate any host
to a client that trusts its CA).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 01:13:45 +04:00
germondai f8c90f0c49 docs: replace dragonflydb references with redis 8.8 and reformat markdown 2026-07-11 17:00:29 +02:00
germondai f746206de9 docs: update trawl docker image size in compare table 2026-07-11 16:37:25 +02:00
germondai 6f96285544 chore(release): bump to 1.0.0 and backfill versioned changelog history
Splits the single [Unreleased] CHANGELOG block into dated 0.1.0-1.0.0
sections matching the milestone commits being tagged for issue #24
(numeric release tags), and bumps every package.json to 1.0.0.
2026-07-10 21:11:04 +02:00
germondai 040c7352fb chore(deps): bump typescript to v7 and update workspace dependencies 2026-07-10 19:19:35 +02:00
germondai 9311cb38a4 fix(a11y): drop redundant role attribute and update biome lint config 2026-07-10 19:17:37 +02:00
germondai 1f1a45ee0b style: use shallowRef for primitive refs in web nav 2026-07-10 17:35:25 +02:00
germondai 09bdd18b30 docs: update docs and README for Dragonfly and new structure 2026-07-10 08:31:54 +02:00
germondai a40eb1708b feat(web): show live GitHub star count in navbar 2026-07-09 17:57:42 +02:00
germondai 613b41ad23 refactor(api): split index.ts into config, deps, routes, and add root status route 2026-07-09 10:40:36 +02:00
germondai 7f2dc4fb8e docs(web): bump docker image size to 1.14 GB in comparison table 2026-07-08 15:48:48 +02:00
germondai 9fb92d9809 fix(docker): bake GeoLite2 mmdb into api image to prevent geoip startup crash 2026-07-08 15:48:48 +02:00
germondai 52cd0ce3ac fix(docker): install curl in api runtime image so healthcheck works 2026-07-08 15:48:48 +02:00
GermondandGitHub a8eaf8f843 Merge pull request #19 from edasque/fix/tier-detection-and-proxy-wiring
Fix silent false-successes in tier detection, add Tier 4 captcha parity, surface proxy/timing info
2026-07-08 03:36:55 +02:00
germondai 1da2a021b4 docs(web): update comparison benchmarks with measured latency + infra specs 2026-07-08 01:25:00 +02:00
Erik Dasque 7d3204351c fix(tiers): recognize more block/error page variants, add Tier 4 captcha parity, surface proxy/timing info
Found while running trawl against a large batch of real-world URLs: several
cases where the API returned 200 with content that was actually a blocked
page, an empty challenge stub, or Firefox's own error page. Each was a
detection gap where a tier didn't recognize the failure and reported it as a
successful scrape.

- Recognize Firefox's about:neterror/about:certerror page (browser never
  reached a server), Cloudflare's static "you have been blocked" WAF-deny
  page, and a lean CF challenge stub (blank title/body, just the bootstrap
  script) — the stub check is gated on page size since the same script
  snippet also appears on ordinary, fully-loaded CF pages as bot-management
  telemetry.
- Wire the existing isBlocked() status-code check (403/429/202) into Tiers 2
  and 3 — previously only Tier 1 checked status code, so a generic non-CF WAF
  deny that escalated to a browser tier was reported as a success.
- Bring Tier 4 up to parity with Tier 3: captcha solving and the same block
  detection. Sites that need Tier 4 for IP reputation can just as easily have
  an in-page captcha widget.
- Add proxyUsed: boolean to the response, set from the actual proxy used by
  the winning tier — previously the only signal was inferring from tier === 4,
  which doesn't distinguish "no proxy" from Tier 3's datacenter proxy.
- Attach the per-tier timings array to thrown errors via a new ScrapeError,
  and return it in /scrape's error response. The array was already being
  built in memory; it just never survived the throw, so failed requests gave
  a flat error string with no way to see which tier failed or why.
- Add process-level uncaughtException/unhandledRejection handlers. One target
  site's page threw a JS error that Camoufox/Firefox reports in a shape
  playwright-core's dispatcher doesn't expect, which crashed the entire
  process and dropped every in-flight request across all clients.
- Update the native API docs for the new response fields and error shape.

All additive — no existing fields changed shape. Full existing test suite
passes (58/58), and this is rebuilt/smoke-tested against latest dev.
2026-07-07 15:58:54 +00:00
germondai f44f7511f9 build(api): prune devDeps and impit platform binaries in deps stage 2026-07-06 23:41:53 +02:00
germondai fb620141f6 build(api): pin Camoufox version, strip symbols, prune deps, switch to debian-slim 2026-07-06 23:10:16 +02:00
germondai 444df08d00 docs: update CHANGELOG, README, and docs for recycle-on-blocked and content-processes 2026-07-06 20:11:08 +02:00
germondai da8f9261e1 feat(api): add BROWSER_CONTENT_PROCESSES env var 2026-07-06 20:09:30 +02:00
GermondandGitHub 47fc0fa647 Merge pull request #14 from CoolDotty/codex/fix-browser-process-leak
Recycle browser pool after temporary contexts
2026-07-06 19:41:42 +02:00
germondai e8129735b0 fix(api): normalize proxy field at /v1 boundary for Prowlarr input 2026-07-06 13:56:09 +02:00
CoolDotty 68ad2e0f1a Recycle browsers after temporary contexts 2026-07-06 00:47:32 -07:00
germondai da8008d200 feat(api): forward per-request proxy override to scrape handler 2026-07-06 02:29:51 +02:00
GermondandGitHub 8d69e660c3 Merge branch 'main' into fix/pr-8-hardening 2026-07-06 01:33:13 +02:00
germondai 59f78f38e7 docs: document method/body support and header sanitisation 2026-07-06 01:12:30 +02:00
germondai d8e0745662 feat(api): validate methods and sanitise headers at the boundary 2026-07-06 01:12:11 +02:00
germondai 9261d5d92f docs: update references to renamed PORT env var 2026-07-05 18:06:12 +02:00
germondai e05d9afee3 refactor(api): rename PORT_API env var to PORT 2026-07-05 18:06:02 +02:00
germondai 0d35b4d698 style(web): reformat cta section line wrap 2026-07-05 17:00:01 +02:00
germondai 0bbbb3f987 docs: document proxy pool config, rotation, and per-request override 2026-07-05 16:41:01 +02:00
germondai 8d78a1a6e1 feat(api): configure proxy pools from env and forward overrides 2026-07-05 16:40:42 +02:00
germondai d4bb9533c9 docs: document imperva/incapsula solving in tiered execution 2026-07-05 16:40:29 +02:00
whoshoe 5fde497e3a feat: add post method with postData parameter 2026-07-03 22:28:42 +08:00
germondai c2b328d841 docs: mention bun kernel version requirements for :baseline vs :latest 2026-07-01 19:04:43 +02:00
germondai a8ae937ba2 feat(web): mention :baseline image tag on landing page 2026-07-01 18:55:02 +02:00
germondai 182dd2e4f6 docs(deployment): document :baseline image variant and add crash-loop troubleshooting entry 2026-07-01 18:55:00 +02:00