Files
autoreg-skills-max/skills/ai-provider-autoreg/references/viktor-com-reverse.md

59 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Viktor.com (app.viktor.com) — reverse + РАБОЧИЙ Slack-регер (2026-10)
API base: `https://api.viktor.com`. SPA: Vite/React, 380 chunks (dump: `~/tmp/viktor/assets/`, report: `~/tmp/viktor/VIKTOR_API_REVERSE.md`).
Репа с инструментом: `gbonnet65923/viktor-autoreg` (`tools/slack_reger.py` — полный флоу, `SETUP.md` — все точки конфигурации). Локальная рабочая копия: `~/tmp/viktor/slack_full.py`.
## Signup doors
1. **email-code** (`POST /api/auth/email-code/request`) — LOGIN-ONLY: новый адрес получает "No Viktor account for this address".
2. **Google OAuth** — HARD-DISABLED серверно (`/signup?error=signup-unavailable`).
3. **Microsoft Teams** — нужен work/school tenant.
4. **Slack** (`/api/coworker/slack/signin`, client_id 5770720430932.10097753943189) — **РАБОЧИЙ ПУТЬ**: создать свой workspace через createnew → OAuth → JWT. Проверено вживую до `GET /api/me` 200.
## РАБОЧИЙ ЧЕЙН (Slack door, проверен end-to-end)
Порядок шагов (всё в ОДНОЙ cloakbrowser-сессии — токен капчи должен жить в той же странице, где жмётся Continue; отдельный solve+inject не работает):
1. Почта из пула t-online (`working_mails.txt`, 17895 шт, формат email:password; offset-файл для ротации). Consumer-домены (gmail) Slack режет, work-домены принимает.
2. `app.slack.com/get-started#/createnew` → fill email → submit.
3. **reCAPTCHA v2 решается ЛОКАЛЬНО, $0** — in-process `solve_recaptcha_v2_realpage(classifier='mistral')` из `cs_sidecar` (vision keypool mistral/qwen3-vl через локальный OpenAI-совместимый прокси). Старое утверждение «ONNX-классификатор не решает Slack, нужен платный solver» — НЕВЕРНО: решает vision-классификатор сетки. Критично:
- НЕ через sidecar HTTP `/solve` — `_solve_lock` занимают cron-задачи (turnstile-джобы), recaptcha-запрос голодает 400+ сек. Только in-process import.
- `image_solve.py`: цикл раундов — `while`, НЕ `for range(rounds)` (range фиксируется на входе, апгрейд rounds внутри тела не расширяет итерации). Динамика детектится по `.rc-imageselect-dynamic-selected`.
- Лимит раундов ≥25: Slack Enterprise ре-эскалирует челлендж дольше, чем Google demo (8 мало).
- `humanize=0` (frame_locator-цепочки несовместимы с humanize), `.first` после frame_locator при двух reCAPTCHA-iframes.
- NO TOKEN после N раундов = Google зациклил challenge на этой почте → перезапуск берёт следующую.
4. Код из письма по IMAP (secureimap.t-online.de:993): формат `XXX-XXX` (НЕ `\d{6}`). UI `#/confirmemail` — **6 отдельных боксов `input[maxlength="1"]`** (aria "digit N of 6"): вбивать по одному символу, без тире; целым куском в одно поле = вечное «Checking your code…».
5. Magic-link из письма (`go.slack.com/get-started...`) — ТУПИК: ведёт в `#/workspaces` join-лист, не в создание. Игнорировать, только код.
6. Авторитет успеха = сетевой ответ `POST app.slack.com/api/signin.confirmCode` → `{"ok":true,"has_workspace":false}`. SPA при этом может остаться висеть на confirmemail — это баг навигации, не отказ: форс-навигация `#/createnew` → multi-step создание workspace (name → your name → password, кнопки Next/Continue).
7. Workspace URL: regex `https://([a-z0-9-]+)\.slack\.com` по странице/ссылкам, фолбэк — поле `domain` из cookie `d`. Куки + state сохранять в JSON.
8. **Viktor OAuth**: `api.viktor.com/api/coworker/slack/signin?app_url=https%3A%2F%2Fapp.viktor.com` в той же сессии с куками → страница выбора аккаунта (`button[type=submit]`) → ВТОРАЯ страница консента «Where do you want to use Viktor?» → ещё один submit → callback `app.viktor.com/signin/callback?exchange_token=...&user_id=...`.
9. **exchange_token ОДНОРАЗОВЫЙ**: ручной urllib-запрос `/api/auth/jwt_token` может словить 429, а повтор с тем же токеном — 400 (сожжён). НЕ дёргать jwt_token руками — вешать `page.on("response")` на `/api/auth/jwt_token` и перехватывать JSON-ответ, который делает сам SPA (`{"jwts":[...]}`).
10. Пруф авторизации: `GET /api/me` с `Authorization: Bearer <jwt>` + Cookie `session` → 200 с профилем. `session`-кука `api.viktor.com` снимается с контекста после callback.
## Token flow
OAuth callback → `{exchange_token}` (одноразовый) → `GET /api/auth/jwt_token?exchange_token=` → `{jwts:[...]}` → cookie `session` = JWT. `post-signin-state?jwt=` → `{provider:'slack', slack_connected:false}` (не блокирует /api/me).
## Мёртвое (не тратить время)
- `jwt_bypass` — серверно задизейблен (production → `?error=bypass-disabled`), роут жив но обхода нет.
- `/docs /redoc /openapi.json` — 404, схемы нет, только статика чанков.
- Thread-эндпоинты web-chat (`thread-info?thread=`) — 404 на REST; тред живёт в WS-потоке гейтвея (`tools/viktor_gateway.py`, REST `POST /threads` + WS `tok_delta`).
## Кредиты и модели (проверено живым JWT)
- **Fresh Slack-workspace = 0 кредитов**: sendMessage → HTTP 402 «This workspace is out of credits». Заданий/тасков за кредиты НЕТ (user-research опросник `eligible:false`).
- **Starter credit 16 000** — единственный подтверждённый бесплатный путь: `POST /api/coworker/starter-credit-unlock-session {"return_to":"onboarding"}` (литералы: onboarding|dashboard|billing) → `{outcome:"redirect", credits:16000, destination:"https://pay.viktor.com/c/pay/cs_live_..."}` → верификация карты ($0 auth, VCC). `outcome:"unlocked"` = карта уже верифицирована.
- Кредит-статус акка: `GET /api/coworker/getting-started-status` → `starter_credit_amount`, `starter_card_required`, `chat_platform_connect_bonus_credits` (поле живое, сейчас 0 — периодически перепроверять: бонус за Discord/MSTeams connect). `GET /subscription` (null=free), `GET /auto-top-up` (прайс: 10000 cr = $25).
- **Google-дверь**: `POST /api/auth/google_one_tap {credential, user_type, ph_session_id, anon_session_id}` → JWT напрямую. По отчётам юзеров Gmail-рега даёт стартовые кредиты БЕЗ карты, но с нашего IP дверь отвечала signup-unavailable — перед массовкой нужен один ручной тест через UI «Continue with Google».
- Referral: кредиты = % от revenue платящих рефералов, tiers Connector 15% / Advocate 20% (@$750) / Insider 25% (@$2500). Partner offer `claude_startups` (cookie `vk_partner` или `?partner=`, живёт 720ч) + промокоды `?code=` проходят в checkout через `POST /api/coworker/partner-offers/preflight`.
- **Модели**: `GET /api/coworker/model-settings` (200, ~17KB) — весь каталог: пресеты Ultra/Smart/Balanced = Claude Opus 5.5 (high/medium/low), Cheap = GPT-6 Luna; прямые модели GPT-6 Astra/Sol/Luna, GPT-6.1 Sol, GPT-5.6 Terra/Sol/Luna, Claude Fable 5.1, Opus 5.5/5/4.8, Sonnet 5.5/5, Grok 4.7; deprecated: Kimi K3, Gemini Flash 3, Fable 5, Opus 4.7. Default `smart`. Infinity-режим: Opus 5 + GPT-6 Astra. Скрипты-пруфы: репа `tools/credits_probe.py`, `tools/starter_unlock.py`, `docs/CREDITS.md`.
## Gateway → IDE
`tools/viktor_gateway.py` (:8700, stdlib+websockets, OpenAI-compat `/v1/chat/completions|/v1/models`, pool accounts.jsonl hot-reload, round-robin, 401/403 авто-дизейбл в gw_pool.json) — проверен вживую: health/models/chat работают, 402 от Viktor пробрасывается текстом в content (не маскировать — клиент должен видеть причину). Проводка в Cursor/Cline/Continue/Claude Code/MCP + Cloudflare Tunnel наружу: репа `docs/IDE-GUIDE.md`. Tool-calls из IDE не работают (Viktor сам агент, function-calling наружу не отдаёт) — только чат-режим.
## Антибот
Verisoul (`verisoul_session_id` в email-code body, nulls проходят). PostHog server-side eval.
## Pitfalls
- Google cookies v20 (App-Bound Encryption) не расшифровываются DPAPI — только v10; сессию между профилями не перенести.
- `cloakbrowser.launch_async()` НЕ принимает `user_data_dir` (TypeError) — профиль эфемерный; куки переносить через `context.add_cookies()`.
- Workspace ToS speedbump: кнопка «Понятно»/«I understand» (локализована).
- patchright headed обходит Google identifier-блок; headless — нет.
- `asyncio.run()` внутри уже работающего event loop (родительский поток) — конфликт; оборачивать solve в `threading.Thread` с результатом в dict.
- IMAP-заголовки Slack: `From`/`Subject` декодировать через `email.header.make_header(decode_header(...))`, иначе код не найдётся.