---
name: vakhunter_profiles_e2e_and_gaps
description: VakHunter — как тестировать профили (бот+сайт+оплата) + проверенная гейт-матрица тарифов + указатель на дорожную карту бесплатных фич против конкурентов
metadata: 
  node_type: memory
  type: project
  originSessionId: 805ead91-dfa3-49d2-a5e6-01a980e715fd
---

VakHunter — аудит под профилями + конкурент-гэпы (2026-06-29).

**Проверенная гейт-матрица (авторитетно, `check_tariff_limits` + API сайта):** источники **Trial 5 / Standard 12 / Pro 20**; подписки **1 / 2 / 3** (лимит принудительно стопает); заказы 🛒 — **Trial НЕТ (гейт), со Standard да** (фриланс-биржи fl/kwork/profi на Standard, freelancehunt на Pro). Новый юзер `add_user` → пробный Pro ровно 7д. Pro обещает «20 площадок», но фильтры сайта кажут 18 (нет данных hh_kz/hh_by/hh_uz) — косметика.

**Как тестировать профили (recipe, переиспользуй):**
- **Сайт:** секрет сессии в `~/.vakhunter_web_secret` (32 байта). Минтить cookie `vh_session` standalone (urllib, без aiohttp): payload `{user_id,name,exp}` base64 + HMAC-SHA256[:32]. Бэкенд `web.webapp` на :20452 (`/api/*`), Next на :20412 (`/api/vh/*`→rewrite). Фейк-юзеры в диапазоне -98765x (вне реальных). DB_PATH = `~/Services/vakhunter/vakhunter.db` (общая с ботом).
- **Бот:** реальный аккаунт **8688355181** через web.telegram.org (Playwright, proxy :2081, сессия `~/.gaechkin/tg_test_session.json`). `/start` и `/search` — CommandHandler'ы, FSM-онбординг (`MessageHandler & ~COMMAND`) их НЕ перехватывает → «с нуля» = удалить строку users + /start. Тариф меняется правкой `users.tariff_id` в БД (гейт читается per-request, рестарт не нужен).
- **Оплата (без денег):** POST CONFIRMED на публичный Funnel `https://cebers-mini.tail2f8be2.ts.net/payment/platega` с заголовками `X-MerchantId`/`X-Secret` из `.env`, тело `{id,amount,status,payload:"uid:tid"}`. Проверено: активация Standard/Pro, идемпотентность, bad-sig→403 (fail-closed), CHARGEBACKED→сброс на Trial. Скрипты: scratchpad `vh_site_matrix.py`/`vh_pay_sim.sh`/`vh_bot_journey.py`/`vh_site_shots.py`.
- **ОБЯЗАТЕЛЬНО** чистить тест-данные после: фейки, sim-платежи (`invoice_id LIKE 'sim-%'`), вернуть тест-юзера на исходный тариф+профиль. Бэкап БД `*.bak-pre-*`.

**Конкурент-гэпы → бесплатные фичи:** полная дорожная карта в Obsidian `Projects/VakHunter/Competitor-Gaps.md`. Ставки: (1) отзывы/рейтинг работодателей + анти-гостинг (единств. high-diff); (2) пакет видимого ума — %совпадения+skill-gap+дашборд воронки (score уже считается, невидим); (3) resume-аудит под HH/SuperJob. Автоотклик/продвижение резюме НЕ берём (чужие креды/шадоубан/152-ФЗ). См. [[vakhunter_monetization]], [[vakhunter_overview]], [[vakhunter_web_ai_tariff]].

**Реализация фич (2026-06-29, фазами, Changelog (5)):**
- **AI-лимиты по тарифу** (`9e1697b`): таблица `ai_usage`, `db.try_consume_ai`, `AI_DAILY_LIMITS={1:3,2:10,3:25}` (копия в web/webapp.py, drift-тест). Гейт на cover_letter/recommendations/ask/fit/compare/resume_template/resume_build (бот+веб). EXEMPT: составление профиля (`ai_resume`+онбординг) и фоновые score/rerank. Истёкший платный=лимит Trial. Веб-отказ=429 `ai_limit`.
- **Площадки честно** (`93f01b0`): **superjob ЖИВ** (не чинить, 0 в БД = состав подписчиков). Формулировка везде **«20 площадок: 17 РФ + 3 СНГ»**. `region_gate_sources(sources,city)` в vacancy_filters убирает hh_kz/by/uz для не-СНГ городов (cmd_search ×2 + scheduler ×2).
- **Лендинг :20412 теперь launchd-сервис `local.vakhunter-frontend`** (был orphaned `npm start`). Деплой лендинга: `cd ~/Разработки/kodoceh-web/apps/vakhunter && rm -rf .next && npm run build` → `launchctl kickstart -k gui/$(id -u)/local.vakhunter-frontend`. Зарегистрирован в `ops_dashboard/dashboard_config.json` (id `vakhunter_frontend`). См. [[kodoceh_web_build_gotcha]].
- **Фаза 3 видимый ум** (`a1b1a2e`, фронт `1b79455`): `local_scoring.match_card()`+`skill_gap()` → `📊 NN%`+`📚 Подтянуть` в карточке бота (handlers+scheduler push) и веб-ленте (`_vac_dto` отдаёт `match_pct`/`skill_gap` при персонализации; фронт `VacancyRow`). `db.career_funnel()` → сводка-воронка в шапке Карьерного трекера. Живьём: бот 36%+gap, веб 74%-топ Django, 17/20 чипов. Тесты `test_match_card` (7+2 воронка), 165 passed.
- **Фаза 4 отзывы работодателя** (`bc8a2f8`, фронт `3da4091`): источник = **Хабр Карьера**, НЕ orabote.top (тот 0/25 на наших + чужие матчи — разведка в Decisions D43). `bot/company_reviews.py`: резолвер (поиск→лучший матч по имени/слагу, не первый; Ozon→Ozon Tech) парсит meta-description `/companies/<slug>/scores` (оценка/5, рекомендация %, лучшие качества, K отзывов) + `cached_review` (таблица company_reviews, негативы тоже, TTL 21/7д, любая ошибка→None). Бот: ⭐ в карточке + кнопка «Подробнее об отзывах»→handle_reviews (роут `reviews_`). Веб: `vacancy_detail.reviews` (через `_DBShim`) → блок в VacancyDrawer. Живьём: бот Avito 3.7/68%, веб Ozon 4.5/87%. Только вакансии с компанией (не фриланс); не-IT честно без строки. Тесты test_company_reviews, 170 passed.
- **Сортировка ленты** (`adb1986`, фронт `46425fc`): `/api/vacancies?sort=rating_asc|rating_desc|salary_asc|salary_desc` (отдельная ветка, перебивает персонализацию, nulls-last). Рейтинг из кэша `company_reviews` (`_bulk_ratings`, без сети), зарплата `normalized_salary_*`. `_vac_dto.company_rating` → ★-чип в карточке списка. Фронт-селектор в панели фильтров. Нормализация валют (`e9f49cc`): `bot/salary_fx.py` (`detect_currency`+`to_rub`, приблизит. курсы ТОЛЬКО для ключа сортировки) — ветка `salary_*` строит ключ в рублях, UZS-миллионы больше не всплывают выше RUB. Живьём ✓ (300k₽ во главе desc).
- **Фаза 5 (scope «три без резюме», `e9f49cc`/`4f6ebe5`/`143f25f`/`412a57f`/фронт `6a7c413`):** юзер отверг «резюме-под-вакансию» (дублирует сопроводительное + жжёт AI-лимит). (1) **Дедуп ленты** `web._dedup_fp` по fingerprint во всех 4 путях, после WHERE, свежую копию, NULL не трогаем; plain-путь → 600+python-пагинация. (2) **Hard-фильтры** `?must=`/`?exclude=` (SQL LIKE title/skills/description в общем where, `_split_terms` кап 6) + фронт-инпуты в панели фильтров. (3) **ЗП-дашборд УЖЕ был** (карточка «Аналитика рынка»), доделал только валюту: `/api/market` lo/hi через `to_rub`. (+нормализация сортировки `salary_fx` из доп-задачи). 182 passed, живьём ✓ (дедуп 0 дублей, exclude=senior 0, market python 190k₽).
- **Фаза 6 авто-перевод (`10081b7`, фронт `0e0696f`) — ЗАВЕРШАЕТ дорожную карту 1–6.** `bot/translator.py`: `is_foreign` (детект по телу: кириллица<30% И длина≥40, отсекает telegram-шум и англ-тайтл-русское-тело), `translate_vacancy` (LLM `asst.model`=llama-3.3-70b free NIM, дословный промпт; 8b fast_model браковал — выдумывал/протекал), `cached_translation` (таблица `vacancy_translations`, негативы тоже, сбой LLM не кэшируем). **Лениво** при открытии карточки, **НЕ в AI-лимит**. Бот: RU title+desc + маркер 🌐; веб `vacancy_detail.translation`; фронт drawer + тоггл оригинала. Живьём ✓ (remoteok «AI Filmmaker»→«Кинематографист ИИ», веб Playwright тоггл, бот real-run). 186 passed.
