Initial Commit
This commit is contained in:
88
openspec/changes/swap-testing-e2e-cloakbrowser/proposal.md
Normal file
88
openspec/changes/swap-testing-e2e-cloakbrowser/proposal.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# swap-testing-e2e-cloakbrowser
|
||||
|
||||
## Why
|
||||
|
||||
`@playwright/test` ships a stock Chromium that is trivially fingerprinted as
|
||||
automation (`navigator.webdriver === true`, `HeadlessChrome` UA, missing
|
||||
`window.chrome`, GPU/canvas/audio leaks, CDP detection). E2E suites that
|
||||
exercise production-like flows against bot-aware infrastructure
|
||||
(Cloudflare Turnstile, reCAPTCHA v3, ShieldSquare, FingerprintJS,
|
||||
BrowserScan) either fail outright or skew metrics on the first request.
|
||||
|
||||
[CloakBrowser](https://github.com/CloakHQ/cloakbrowser) (`cloakbrowser`,
|
||||
v0.3.28) is a real Chromium binary with 49 source-level C++ patches
|
||||
covering canvas, WebGL, audio, fonts, GPU, screen, WebRTC, network
|
||||
timing, automation signals, and CDP input behaviour. It is a drop-in
|
||||
replacement at the browser-launch layer: the returned object is a
|
||||
`playwright-core` `Browser` and works with every existing Playwright
|
||||
test, fixture, page-object, and helper without API changes.
|
||||
|
||||
This proposal swaps every browser-launch call inside
|
||||
`@suaveplan/testing-e2e` to `cloakbrowser`, retains `@playwright/test`
|
||||
as the test runner (CloakBrowser does not provide one), and exposes the
|
||||
stealth-specific knobs (`humanize`, `proxy`, `geoip`,
|
||||
`launchPersistentContext`, extension support) as first-class API surface.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **ADDED:** `CLOAK_LAUNCH_FAILED`, `CLOAK_BINARY_MISSING`,
|
||||
`CLOAK_PROXY_INVALID` error codes + `CloakLaunchError` class +
|
||||
`classifyCloakError` helper that turns raw cloakbrowser errors into
|
||||
classified `TestingE2eError` instances with remediation hints.
|
||||
- **ADDED:** `@suaveplan/testing-e2e/cloakserve` subpath —
|
||||
`connectCloakServe(options, chromium?)` + `buildCloakServeUrl(options)`
|
||||
pair that wraps `chromium.connectOverCDP(...)` for the
|
||||
[cloakserve](https://github.com/CloakHQ/CloakBrowser#cdp-server-mode)
|
||||
CDP multiplexer. Strongly-typed query-parameter surface
|
||||
(`fingerprint`, `timezone`, `locale`, `platform`, GPU vendor /
|
||||
renderer, hardware concurrency, device memory, screen dimensions,
|
||||
`proxy`, `geoip`). Errors wrapped in `CloakLaunchError`.
|
||||
- **ADDED:** `@suaveplan/testing-e2e/presets` subpath — stealth
|
||||
presets matching the upstream README's "Recommended config for
|
||||
anti-bot sites" block. `STEALTH_DEFAULT_CLOAK`,
|
||||
`STEALTH_HEADED_CLOAK`, `stealthMax(proxy)`,
|
||||
`stealthMaxHeadless(proxy)`.
|
||||
- **ADDED:** `tests/no-disallowed.test.ts` rule against
|
||||
`waitForTimeout` / `wait_for_timeout`. Both forms emit CDP traffic
|
||||
that reCAPTCHA v3 / Enterprise behavioural scorers detect; the
|
||||
upstream README documents this explicitly. Test files excluded.
|
||||
- **ADDED:** `docker/` bundle — `Dockerfile.cloakserve` (extends
|
||||
`cloakhq/cloakbrowser`, adds the Kasada / Akamai font set, runs
|
||||
`cloakserve` on 9222), `Dockerfile.manager` (extends
|
||||
`cloakhq/cloakbrowser-manager`, exposes 8080 with a `cloakprofiles`
|
||||
named volume), `docker-compose.yml` binding both to `127.0.0.1`
|
||||
with the manager gated behind the `manager` compose profile,
|
||||
`.env.example` for pinned tags + `AUTH_TOKEN`, operator `README.md`.
|
||||
- **MODIFIED:** `extendedTest`'s `browser` fixture now launches via
|
||||
`cloakbrowser.launch()` instead of the stock Playwright chromium
|
||||
fixture. `freshPage` and any downstream fixture composition keep
|
||||
the same signature. The launcher is unit-test-injectable via the
|
||||
`launchBrowserWithCloak(opts, injectedLaunch?)` helper.
|
||||
- **MODIFIED:** `launchWithExtension` accepts an injectable
|
||||
`launchPersistentContext` function (default: cloakbrowser's). The
|
||||
legacy `chromium: BrowserType` parameter is removed.
|
||||
- **MODIFIED:** `packages/testing/testing-e2e/package.json` adds
|
||||
`cloakbrowser: ^0.3.28` as a direct dependency. (The dep is pinned
|
||||
in-package rather than added to `workspaces.catalogs.testing` to
|
||||
keep this change isolated from concurrent in-flight work that also
|
||||
touches the root catalog; promote to the testing catalog as a
|
||||
follow-up if other packages start consuming `cloakbrowser`.)
|
||||
- **MODIFIED:** Package description, README updated. **No public
|
||||
re-exports of cloakbrowser symbols** — per CLAUDE.md rule 4,
|
||||
consumers `import { launch } from "cloakbrowser"` directly when
|
||||
bypassing the fixture layer.
|
||||
|
||||
## Impact
|
||||
|
||||
- **Affected specs:** `testing-e2e`.
|
||||
- **Affected code:** all six consumer packages currently importing from
|
||||
`@suaveplan/testing-e2e` continue to work unchanged — the browser
|
||||
launcher swap is transparent to existing tests because the returned
|
||||
`Browser` object is the same `playwright-core` `Browser` type.
|
||||
- **Binary footprint:** CI runners gain a ~200MB stealth Chromium
|
||||
download on first run (cached under `~/.cache/cloakbrowser/`).
|
||||
Acceptable: the alternative is `playwright install chromium` (~170MB)
|
||||
on every `@playwright/test` consumer.
|
||||
- **Out of scope:** Python flavour (`cloakbrowser` PyPI), `cloakserve`
|
||||
CDP multiplexer, `cloakbrowser-manager` Docker profile UI — none are
|
||||
consumed by the genesis monorepo today.
|
||||
Reference in New Issue
Block a user