Пакет в client/ (зависимость — httpx), установка через pip из git или
wheel (make client-build). Тесты против api и воркера из harness.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- loadtest: у каждого запроса своя сессия, режим --mode v2 (задача + опрос),
X-API-Key; замер v1/v2 в docs/Deployment.md.
- make push ver=... — образы robotex-api и robotex-worker в docker.sokolab.xyz;
prod-compose и make release ссылаются на образы реестра.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Postgres в compose; пакет db (SQLAlchemy async): clients, windows, requests.
- Все эндпоинты, кроме /health, — только с ключом в X-API-Key, иначе 401; без
выпущенных ключей доступа нет. В базе — только sha256 ключа.
- Задача и окно сессии привязаны к клиенту: чужой ключ их не видит.
- Воркер пишет журнал: окно (открыто, последнее обращение, закрыто) и задачу
(в очереди, начало, конец, итог, данные без секретов). Сбой записи не роняет задачу.
- python -m db.cli create|list|revoke|stats; make key-create/key-list/key-revoke/stats.
- smoke и loadtest с ключом.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Минимальный init-script (src/api/js/canvas_noise.js): младший бит у ~1/64 непрозрачных
пикселей при toDataURL/toBlob/getImageData, детерминирован от seed профиля. Пустой
canvas не меняется, подменённые функции неотличимы по toString и length. Старые
профили получают seed, экран сохраняется.
Проверено: 4 профиля — 4 разных хеша canvas; Cloudflare 6/6 на новых профилях.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Отметка последнего использования — mtime файла в профиле, ставится при открытии и
закрытии окна. Очистка при старте воркера и раз в час; профили с открытым окном
(на этом воркере или по ключу сессии в Redis) не трогаются.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fill остаётся мгновенным. typing подводит курсор по кривой, кликает в поле, стирает
старое значение и набирает текст посимвольно с паузами; символы вне раскладки
(кириллица) больше не роняют ввод. Значение typing маскируется в логах.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Сервис api (FastAPI, без Chrome): POST /v2/tasks, GET /v2/tasks/{id} (доступ по cookie
сессии), DELETE /v2/sessions/current; /v1/solve — прежний контракт поверх очереди.
- Сервис worker (dramatiq + RabbitMQ): слоты браузера, окна сессий между задачами
(browser_idle_timeout 0–120 мин, простой — TTL ключа в Redis), heartbeat.
- Маршрутизация задач сессии в персональную очередь воркера с открытым окном.
- Redis: задачи, результаты (RESULT_TTL_HOURS), окна, воркеры. Прокси и ключ 2captcha
в Redis не сохраняются.
- Движок: AsyncStealthySession.run() — действия на текущей странице без навигации.
- Два образа (robotex-api, robotex-worker), compose с rabbitmq и redis,
make up/down/logs/smoke, релиз собирает все образы.
- Тесты: api + worker в одном процессе (fakeredis), настоящий воркер dramatiq на
StubBroker, браузерные тесты на новой схеме, smoke для запущенного стенда.
- Документация: README, API (v2), Deployment, Usage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- user_agent в запросе → 422 с подсказкой брать UA из ответа: UA, отличный от реального
Chrome, расходится с userAgentData и движком, Cloudflare такой браузер не пропускает
(замер: родной 3/3, Chrome 147 и Windows — 0) (#87)
- профиль хранит только отпечаток (экран, DPR), UA не подменяется (#89)
- docs/Usage.md: практики для клиентов API — тот же UA и прокси, что у браузера, сессии,
cookies, ошибки и повторы, таймауты, пример на httpx
- README, docs/API.md, docs/Introduction.md; тесты под новый контракт
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tests/unit (make test, без браузера, ~5 с): схемы и валидация, /v1/solve с подменённым
движком (коды ошибок, слоты, сессии, UA и cookies профиля, маскирование секретов в логах),
действия, оркестратор антибота, профиль и отпечаток
- tests/browser (make test-browser, в Docker): example.com, UA один раз и замена cookies
на httpbin, применение и стабильность отпечатка, прохождение Cloudflare
- requirements-dev.txt, make sync-dev; Makefile вызывает pip через python -m pip
(у перенесённого .venv битый shebang bin/pip)
- fix: в CloudflareSolver вызов bounding_box() у неожиданной корутины — ветка без iframe
всегда падала с AttributeError
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- user_agent записывается в профиль при первом запросе сессии, дальше игнорируется (#87)
- переданные cookies заменяют cookies профиля (clear_cookies перед add_cookies) (#88)
- без user_agent профилю генерируется отпечаток browserforge (Linux Chrome): UA с версией
установленного Chrome, экран и devicePixelRatio; только нативная эмуляция, без JS (#89)
- make fp-check: проверка, что отпечаток применяется и стабилен, и доля различий профилей
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- слоты браузеров: asyncio.Semaphore, размер из BROWSER_SLOTS, при нехватке — 503 + Retry-After;
устранена утечка счётчика при отказе (#12, #49)
- session_id принимается только как UUID, путь профиля проверяется (#5)
- секреты клиента в логах маскируются, полный дамп — только на DEBUG (#6)
- ответ: status всегда "ok"/"err", поле code (no_slots / request_failed / challenge_failed /
action_failed), response_model (#7)
- непройденный антибот → challenge_failed, действия не выполняются (#8)
- таймауты провайдеров в мс вынесены в константы; detect переживает навигацию посреди
проверки; пауза между неудачными solve вместо холостого цикла (#9)
- обязательные поля действий и формат прокси проверяются схемой → 422 до запуска браузера (#13)
- прокси необязателен (#15)
- user_agent сохраняется в профиле сессии и реально передаётся в браузер (#16)
- duration_ms у действий и у запроса (#18), опция screenshot (#19)
- общий конфиг логирования (LOG_LEVEL), print → логгер, CloudflareProvider,
удалён cached_persistent, GET /health (#22)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- docker-compose: cpus/mem_limit через API_CPUS/API_MEM_LIMIT, прокси gost в профиле loadtest
- tests/loadtest.py: параллельные запросы к /v1/solve + пики docker stats
- docs/API.md: справочник по запросу, действиям, ответу и сессиям
- docs/Deployment.md: результаты замеров и правило подбора BROWSER_SLOTS
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- без captcha_type шаг антибота пропускается, на неизвестный тип — понятная ошибка
- wait_for и pass_challenge при неудаче падают, а не возвращают текст ошибки как результат
- status "err" ставится по упавшему действию (раньше проверялся несуществующий ключ error)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Dockerfile: python 3.12, Google Chrome (patchright), Xvfb, tini как PID 1 против зомби-процессов
- docker-compose: volume для extra/, shm_size 2gb, порт через API_PORT
- requirements: добавлены playwright и camoufox
- docs: Deployment.md, README и доки актуализированы под Chrome
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>