# Vellum.ai авторег — django-allauth + WorkOS AuthKit (recon+live 2026-09-20) ## Архитектура auth (подтверждено live) - Vellum = **django-allauth browser API** + **WorkOS AuthKit** (OIDC, PKCE). - `GET https://www.vellum.ai/_allauth/browser/v1/config` (открытый, без auth): `login_methods:["email"]`, `is_open_for_signup:true`, провайдер `workos-oidc`, client_id `client_01KJ6H931J7TKPPH5RERWW6DXJ`, `openid_configuration_url: https://login.platform.vellum.ai/.well-known/openid-configuration`. - Капчи на allauth-уровне НЕТ (turnstile-хиты в JS-бандле были из чужого модуля 2nd.js — всегда проверять, из какого бандла grep-хит). - **WorkOS делает СВОЙ email-OTP**, несмотря на `email_verification_by_code_enabled:false` в allauth-конфиге (это про allauth-верификацию, не про AuthKit). Шаг: `login.platform.vellum.ai/email-verification` с 6-значным кодом из письма. ## Рабочая точка входа (form-encoded, не JSON!) ``` POST https://www.vellum.ai/_allauth/browser/v1/auth/provider/redirect Content-Type: application/x-www-form-urlencoded csrfmiddlewaretoken=<из cookie __Secure-csrftoken после GET /_allauth/browser/v1/config> provider=workos-oidc callback_url=https://www.vellum.ai/account/provider/callback process=login&intent=signup → 302 Location: https://login.platform.vellum.ai/oauth2/authorize?client_id=...&state=...&code_challenge=... ``` ## Мёртвые пути (не повторять) - `/_allauth/browser/v1/auth/password/sign_up|signup`, `auth/email/*`, `auth/code/*`, `auth/password` — все 404 (headless JSON API не торчит, только browser v1 provider redirect). - `POST /account/signup/` form-encoded → **405 nginx** (SPA-роут, серверного обработчика нет). ## Recon-методика (reusable для любого SPA) 1. `curl -s /account/signup -o page.html` → `grep -oE 'src="[^"]+\.js"'` → скачать бандлы. 2. `grep -ohE '(_allauth[a-zA-Z0-9/._-]*|`/[a-z0-9/._-]*auth[a-z0-9/._-]*`|https://[a-z0-9.-]+(workos|clerk|auth0)[a-z0-9.-]*)' bundle.js | sort -u`. 3. Всегда смотреть КОНТЕКСТ хита: `grep -ohE '.{300}.{100}'` — иначе легко приписать сайту чужой код (минифицированные вендор-чанки). ## Anti-bot WorkOS AuthKit (live 2026-09-20, ГЛАВНОЕ) Симптом: после email+password AuthKit показывает **«Access blocked, please contact support.»** прямо в форме (без капчи, без явного реджекта). Блокирует: - headless bundled Chromium — всегда; - headed bundled Chromium (`p.chromium.launch(headless=False)`) — тоже. **Решение (проверено — блок снят, дошли до OTP):** ```python browser = p.chromium.launch(headless=False, channel="chrome", args=["--disable-blink-features=AutomationControlled"]) page.add_init_script("Object.defineProperty(navigator,'webdriver',{get:()=>undefined});") ``` Т.е. реальный системный Chrome (`channel="chrome"`), не Playwright-сборка + снятие webdriver-флага. ## Скрипт `C:\Users\User\Desktop\vellum_autoreg\vellum_autoreg.py` — Playwright sync (Python 3.11, PYTHONPATH=""), Gmail +alias (`[REDACTED-NAME]+vellumN@gmail.com`), IMAP OTP-поллер, выхлоп `vellum_accounts.jsonl` (+скриншоты fail_N.png). Запуск: `PYTHONPATH="" Python311/python.exe vellum_autoreg.py N`. Флоу: goto /account/signup → click button.signup__btn → wait_for_url login.platform.vellum.ai → fill email + Enter → sign-up/password: fill password (`:visible`) + unhide first_name через evaluate → **клик button[type=submit]** (Enter не работает) → email-verification: IMAP 6-digit → сабмит. ## Pitfalls (live-подтверждённые) 1. **`input[name=first_name]` на AuthKit sign-up/password — HIDDEN.** `locator.fill()` виснет 30с. Обход: `page.evaluate` → `f.type='text'; f.value='Alex'; dispatchEvent(input)`; остальные поля филить только `:visible`. 2. **Enter НЕ сабмитит AuthKit-форму** — нужен клик `button[type=submit]`. 3. **«Access blocked» = детект bundled Chromium** (см. секцию выше) → `channel="chrome"` + init-script. 4. **Ложный успех:** `status=done` при final_url всё ещё на `login.platform.vellum.ai/...sign-up/password`. Success-критерий: final_url на `www.vellum.ai`/app + cookie `__Secure-sessionid` + `GET /_allauth/browser/v1/auth/session` → `data.user` не null. 5. **Новый фейл после OTP: `error=invalid_authorization_state`** на возвратном редиректе. OAuth-state протухает пока IMAP-поллинг ждёт код (5с циклы, до 120с). Не подтверждено, создался ли аккаунт на стороне WorkOS. Кандидаты-фиксы: (a) сократить poll-interval до 2с и сразу читать последнее письмо по alias-тегу; (b) после ввода OTP НЕ ждать — проверить `auth/session`; (c) при invalid_state попробовать повторный логин теми же креденшелами (аккаунт в WorkOS может уже существовать — тогда flow = login, а не signup). 6. **Ранний `return` в except/детект-ветке пропускал запись в jsonl** (запись стояла после try/finally). Правило: запись рекорда — только в `finally` или через `raise` с обработкой снаружи; детект-ветки не должны `return` мимо логгера. 7. Детект form_error: после сабмита URL всё ещё содержит `sign-up` → снимать `page.inner_text("body")` (в нём виден «Access blocked») + скриншот fail_N.png. ## Статус на 2026-09-20 (конец сессии) - Access-block снят (real Chrome), email→password→OTP шаги проходят, OTP из IMAP читается. - **Аккаунт НЕ подтверждён**: финальный редирект падает с `invalid_authorization_state`; логин-чекер `vellum_login_check.py` написан, но не запущен. - Следующий шаг: прогнать `vellum_login_check.py` (логин теми же креденшелами + goto app.vellum.ai) — если логин проходит, аккаунты создаются и остаётся только чинить хвост редиректа (или вообще забить на него: ценность = аккаунт+API-ключ, а не landing page). ## Статус на 2026-09-21 (сессия 2) — IP-БАН - Тот же фикс (`channel="chrome"` + AutomationControlled off, persistent context) больше НЕ снимает блок: форма доходит до «Все требования к паролю выполнены» → Continue → **«Доступ заблокирован, обратитесь в службу поддержки»** (= русская локализация «Access blocked»). Вывод: блок теперь IP-репутационный, не браузерный. Домашний IP [REDACTED-IP] засидирован (тот же IP ловил Clerk-бан на OdysseyAPI). - ZTE 4G мёртв (192.168.0.4:8080 не отвечает — модем отключён). Нужен свежий residential/mobile IP; free-пулы не годятся (HTTPS-CONNECT к CF режет). - **UI РУССКИЙ по IP-локали.** Все лейблы матчить на обоих языках: `["Продолжить","Continue"]`, `["Email","Почта"]`, `["Зарегистрироваться","Sign up"]`. Лендинг `vellum.ai/account/signup` = маркетинговый экран («Знакомство с новым продакт-лидом») — сперва клик «Продолжить», только потом форма. Sign-up URL новой сессии: `login.platform.vellum.ai/sign-up?client_id=client_01KHCWWJMQ27T1WEPTWV4KV1Z0` (client_id отличается от recon-значения выше — не хардкодить, брать из редиректа). - Форма регистрации теперь двухшаговая: email → Continue → password (live-валидация требований) → Continue → блок. OTP не запрашивался (до него не дошло). - IMAP: `m.search(None, "word")` БЕЗ скобок → `BAD Could not parse command`. Правильно: `m.search(None, '(TO "alias@gmail.com")')`. Письма Vellum OTP: `From: no-reply@vellum.ai`, `Subject: Verify your email address`, To = полный алиас. ## Ключи Gmail IMAP: `[REDACTED-NAME]@gmail.com` / app-password в памяти (IMAP_APP_PASSWORD). Пароль акков в скрипте (`Vl7mQ2xR9wKp!zX4nB8`).