🗺 Pronti — Roadmap
Обновлено: июль 2026 · прод: этот сервер · вопросы — к владельцу платформы
✅ Уже работает
✓Монетизация Stripe (спека §2.10/§7.5/§7.7/§8.6): весь денежный контур в проде за ключом. Эскроу — PaymentIntent с ручным захватом (холд карты на /platba, Stripe Elements); при приёме — capture в аккаунт платформы; при подтверждении работы — release исполнителю за вычетом комиссии 10% + DPH через Connect-transfer. Выплаты: онбординг исполнителя (Express, «Připojit výplaty»). Подписки PRO/MASTER — Stripe Checkout, автопродление, grace при неудаче списания, авто-даунгрейд на free при отмене (вебхук с проверкой подписи). Провайдер выбирается по STRIPE_SECRET_KEY; без ключа — заглушка. Проверено live-вызовом Stripe с сервера (secret рабочий, test-mode, CZK; pk в клиентском бандле)
✓Заказ без обязательной регистрации (спека §1.4/§2.9): гость проходит весь путь до публикации без логина — профиль заводится автоматически по контактам (имя+email+телефон), без пароля, выдаётся сессия. Если email уже с паролем — сессию не перехватываем, просим войти. Защита от спама — резерв средств (эскроу) + IP-rate-limit. guestSession под тестами
✓Прод на Hetzner: Docker, деплой одним push, smoke-check, ежедневные бэкапы БД
✓Заказы: state machine 11 статусов, escrow-логика (fake-провайдер), история, права сторон
✓AI-intake (Gemini): свободный текст на любом языке → категория из 269 подкатегорий, время, цена, уточняющие вопросы; fallback на правила
✓Внутренняя таксономия: 13 категорий / 269 подкатегорий, уровни допуска L1–L4 (чешская/EU легислатива), единицы измерения, лицензии
✓Матчинг: волны диспатча 30с со скорингом, ручной выбор, фильтр по уровню допуска и скиллам
✓Тендеры: ставки, выбор победителя, hold при выборе
✓Верификация: телефон (OTP), email, личность (документы → ревью админа, mojeID готов к домену), допуски L2–L4 (živnostenský list / koncese)
✓Споры: заморозка эскроу, AI-анализ (Gemini) как советник, решение — только человек
✓Чат сторон + автоперевод (DeepL): сообщения по кнопке, заказ переводится на чешский автоматически
✓Витрина: 3 языка UI (cs/en/uk), карта заказа + живое слежение, локатор заказов на «Práce»
✓Модерация: фильтр запрещенного (секс-услуги, наркотики, оружие, подделки, краденое) на 4 языках
✓Админка: метрики, споры, KYC-очереди, каталог услуг (добавление/скрытие), санкции; superadmin назначает админов
✓GDPR: экспорт данных, удаление аккаунта, retention чатов, страница /soukromi
✓Модерация 2.0: Gemini флагует пограничные заказы в очередь админа (решает человек)
✓Фото к заказу и вложения в чат; уведомления (колокольчик); контакт исполнителя (звонок после принятия)
✓B2B: кабинет + фактуры (нумерация, печать); цены по уровню сложности + ночной пересчёт по сделкам
✓Бренд Pronti (рабочее имя): логотип, палитра, продуктовый лендинг; тесты витрины (Vitest)
✓Модерация чата гибрид: словарь (жёсткий блок) + Gemini (пограничное) + автобан за N нарушений
✓Дизайн-полировка: тёмная тема, чистые карты (CARTO), скелетоны, пустые состояния, соц-доказательства, богатая карточка исполнителя
✓Security-аудит: закрыт CSWSH на WebSocket (Origin↔Host) и обход rate-limit через подделку X-Forwarded-For
✓Аудит ядра: OTP/email-verify лочится после 5 неверных попыток (анти-брутфорс кода, не зависит от IP); confirm() запрещён на disputed-заказе (спор закрывает только админ)
✓HTTPS на pronti.cz: свой домен, авто-TLS Let’s Encrypt (Caddy), secure-cookie, www→apex редирект — переезд с голого IP
✓Маскот Prontík + лого-локап (значок-робот + слоган «Pomoc na jedno kliknutí»); UI-хром переведён на инлайн-SVG иконки (навигация, статусы, кнопки)
✓Радар поиска: у клиента пульсирующий «сонар» с Prontíkом («Hledáme pracovníka…») + карта с кольцами волн диспатча (радиус реально растет ×1.5 за волну, пульс-«сонар» по адресу заказа); у исполнителя — таксишный оффер-баннер «заказ рядом» с отсчётом; спокойное «Naplánováno» для заказов далеко в будущем
✓Интерактивная карта на главной (спека v2.0 §3.7): клик по пину заказа → всплывающая ОБЕЗЛИЧЕННАЯ карточка (категория, грубая корзина цены «до 1 тыс / 1–3 / 3–5 / 5–10 / 10 тыс+», «сколько назад»). Ни адреса, ни имени, ни точной суммы — точная цена сделки вообще не покидает API (band считается на бэке), координаты по-прежнему «дрожат». Приватность сохранена, карта стала живее. priceBand + relAge под тестами
✓Добивка спеки без Stripe (§2–§9): §7.8 Master «Extended Tender Slot» (доп. слот в волне подбора), §2.11/§5.11 ETA поиска, §9.17 CSV-экспорт документов, §2.15 «повторить похожий заказ», §9.8 селектор периодов дашборда (today…year/custom), §4.11 история клиента в промпте AI (только для уточнений), §4.10 мультимодальный intake (фото проблемы → Gemini vision, меньше вопросов), §3.7 карта-фон hero с формой заказа поверх. Всё под тестами, где есть логика
✓Документы сделки (спека v2.0 §8, без Stripe): юр. профиль исполнителя — классификация Individual/OSVČ/Company + реквизиты (IČO с контрольной суммой, DIČ, IBAN, статус плательщика НДС). При завершении заказа авто-генерируется документ: Smlouva o dílo (ФЛ) или подклад к фактуре (OSVČ/Company) со снимком сторон/предмета/финансов и оговоркой «Pronti не сторона договора» (§8.3). Личный архив /dokumenty + печатная форма /dokument/[id] (готова к PDF). migration 038, buildDealSnapshot/isValidIco под тестами
✓Прозрачность поиска (спека v2.0 §2.12/§5.11): клиент на «Hledáme pracovníka» видит живую статистику подбора — «osloveno N · zobrazilo M · reagovalo K» (обновляется каждые 30с). offers.viewed_at фиксируется при показе офферов; summarizeDispatch под тестами. migration 037
✓AI-ассистент исполнителя (спека v2.0 §9.11/§9.9): рабочие часы/дни + авто-приём подходящих заказов (первый в волне с auto_accept сам берёт заказ без рассылки). Boost новичка §9.15 — приоритет в подборе первую неделю после регистрации (не влияя на рейтинг). Календарь §9.10 — ближайшие заказы + разовая блокировка дней (диспетчер их уважает). migration 039/040; withinWorkingHours/isNewcomer под тестами
✓Страховки к заказу (спека v2.0 §7.11): каталог страховых продуктов (тип, цена, провайдер, покрытие) как опциональный доп. сервис клиента. При оформлении заказа — выбор страховки; цена снимается снимком с продукта, входит в total_paid, но ВНЕ комиссии платформы (как материалы). В деталях заказа — отдельная строка «Pojištění». migration 036 (+ 2 стартовых продукта), GET /insurance/products, валидация активности продукта на бэке
✓Реклама на карте (спека v2.0 §7.10): location-based ads — рекламная точка (координаты, тематика, приоритет, окно кампании, счётчик кликов) показывается «спонсорским» пином на живой карте главной; клик открывает ссылку и учитывается. Управление из админки (создать/список/удалить). Отдельный revenue stream; наружу — обезличенный пин без внутренней статистики. migration 035, логика isAdActive под тестами
✓Атрибуты каталога → AI-intake (спека §4): у каждой из 269 услуг в таксономии есть ключевые атрибуты (тип, кол-во, материал стен, площадь…) — теперь они уходят в промпт Gemini, и AI задаёт уточняющие вопросы ТОЛЬКО про недостающие атрибуты выбранной услуги (а не общие). Каталог Pronti_Service_Catalog.xlsx уже был в БД (name_ru + attributes + unit); подключён к диалоговому разбору
✓Финансовая структура заказа (спека v2.0 §7.5–7.6): комиссия 10% + VAT только от работ, материалы (material_cost) вне комиссии; computeOrderFinance под тестами (migration 034). В форме заказа — опциональное поле «материалы»; в детали заказа — прозрачная разбивка (работа / материалы / итого; исполнителю — комиссия и выплата); в кабинете — чистый доход после комиссии. Само удержание — через Stripe (позже)
✓Тарифы исполнителя с лимитом дохода (спека v2.0 §7.3–7.4, решение владельца): FREE — потолок 25 000 Kč/мес, PRO (1999) — 60 000, MASTER (2999) — без лимита. При достижении потолка приём новых заказов блокируется (уже принятые можно завершить) — проверка в accept. В кабинете «Práce»: текущий тариф, использование лимита за месяц, переключение тарифа (оплата подписки — со Stripe). Прежнее решение «без потолков» отменено по спеке v2.0
✓Клиент без трения: гость на лендинге видит AI-разбор и цену БЕЗ регистрации (intake публичный, лимит по IP); аккаунт просят только при публикации, черновик переживает регистрацию
✓Роли при регистрации: «Chci zadávat úkoly / Chci pracovat» — исполнитель после входа попадает сразу в «Práce», клиент — к созданию заказа; аккаунт по-прежнему умеет обе роли
✓Geofence-автостарт: исполнитель делится позицией, при подъезде ≤150 м работа стартует сама (для scheduled — не раньше 30 мин до срока); кнопку «Zahájit práci» жать не нужно
✓Загрузка файлов: проверка по magic-байтам на всех аплоадах (фото заказа, чат, KYC-документы, лицензии) — файл обязан быть тем, чем называется; подделка удаляется с диска; X-Content-Type-Options: nosniff глобально
✓Онбординг по мокапам: восстановление пароля (одноразовый токен, выход со всех устройств), чеклист исполнителя «Dokončení profilu» с прогрессом, выбор роли карточками «Potřebuji služby / Chci pracovat», welcome-экран клиента после регистрации; уведомления о новых тендерах исполнителям рядом
✓Геоданные self-host: Photon-геокодер с чешским индексом на нашем VPS (вместо публичного Nominatim с его usage policy) + карты из собственного PMTiles-файла Чехии (Protomaps/ODbL, отдает Caddy) — без ключей, лимитов и внешних CDN; в dev-режиме авто-фолбэк
✓Email по-настоящему: своя почта Forpsi (SMTP smtp.forpsi.com:587 STARTTLS, ящик info@pronti.cz) за интерфейсом EmailProvider — письма подтверждения и сброса пароля уходят реально; Hetzner блокирует 25/465, поэтому 587
✓ID zakázky: сквозной человекочитаемый номер Z-000123 на каждом заказе (для поддержки, споров, фактур), клик копирует; UUID остаётся в URL
✓Продуктовый разбор: фикс протечки det.pay.undefined (у тендера до выбора победителя платежа нет), блок «Fotky problému» → универсальные «Přílohy» (фото + документы)
✓Фактуры на всю компанию: одна фактура за все заказы фирмы за период (owner/admin), реквизиты — из компании; сквозная нумерация CN-YYYY-NNNN общая с пользовательскими, заказ не биллится дважды. Фактуру компании видит любой участник (в /tym), печатная форма — та же /faktura/[id]
✓Командный доступ B2B: несколько пользователей на одну компанию. Роли owner/admin/member; приглашение по email одноразовым токеном (в БД — только sha256-хэш, ссылка /tym/pozvanka), принятие после входа. Заказ можно вести «от компании» (company_id) — тогда его видят все участники в общей ленте (изменять — только заказчик). Страница /tym: создать фирму, участники, пригласить/убрать; селектор «за фирму» при создании заказа. Права — чистые предикаты под тестами (canInvite/canRemove)
✓Фильтры предпочтений исполнителя (v1): исполнитель сам настраивает пуш офферов — «не беспокоить» (пауза), минимальная цена заказа, брать ли ночные заказы (22:00–6:00 по Праге). Dispatch отсекает нерелевантное ещё до отправки оффера (passesPreferences — чистая функция под тестами; фильтр только на пуш, ручной просмотр «рядом» не трогаем). Работа с детьми/животными добавится, когда intake начнёт собирать эти атрибуты заказа
✓Монохром категорий без исполнителей: на лендинге категории, где ещё нет ни одного мастера (нет skill в performer_skills), показываются блёкло (grayscale + прозрачность) с подсказкой «скоро» — гость сразу видит, что уже доступно. Флаг has_performers считает /categories одним EXISTS-подзапросом
✓Авто-язык + компактный переключатель: при первом заходе UI берёт язык устройства (navigator.languages → cs/en/uk, ru-спикеры → uk), ручной выбор по-прежнему побеждает и запоминается. Вместо всегда-видимого ряда флагов — компактное меню (глобус + код) в шапке «главной» и «Práce»; полный ряд остаётся на лендинге и в профиле. pickLang — чистая функция под тестами
✓Кабинет исполнителя (дашборд): домашний экран на «Práce» про его деятельность, а не про конкретный заказ — заработок всего, выполнено заказов, рейтинг, активные сейчас; помесячная динамика (мини-график за 6 мес), топ-услуги и активные районы (из адресов). Появляется с первым выполненным заказом; аналитику считает API (summarizePerformer), UI — чистые хелперы под тестами
✓Живая карта на главной: гость на лендинге видит карту активных заказов в реальном времени (опрос каждые 15 с, новые пины «выскакивают», выполненные исчезают) — ощущение работающей платформы. Приватность: координаты приблизительные (детерминированный сдвиг ~сотни метров), наружу только категория, ни адреса, ни клиента, ни цены; тайлы свои (PMTiles)
✓Sentry (трекинг ошибок) — включён на проде: API репортит неожиданные ошибки (5xx и баги в коде, бизнес-4xx игнорит), фронтенд ловит ошибки в браузере клиентов (глобальные обработчики + корневой error boundary с запасным экраном). Оба за общим DSN, включаются от секрета; без ключа — no-op. Проверено сквозным тестовым событием
✓Диалоговый AI-intake: вместо одноразового разбора — диалог. LLM возвращает флаг «ready» (достаточно ли деталей для точной цены); пока нет — задаёт уточняющие вопросы, ответы копятся и уходят следующим раундом, цена показывается как «расчёт» (спиннер), а не финал. Публикация обычного заказа открывается только когда заказ описан достаточно; иначе — сразу в тендер. Цена помечена «за работу, материал с исполнителем»
✓Статус «Jsem na místě» отдельным этапом (docs/05): accepted → arrived → pending_review. Клиенту приходит «исполнитель на месте» + кнопки Zavolat/Napsat; geofence-автоприезд при ≤150 м. Форма заказа переработана: нумерованные шаги (задача → уточнения AI → цена → дата → адрес → фото), видимые поля даты/адреса с валидацией перед оплатой, липкая нижняя панель «Shrnutí + Zveřejnit», тумблер тендера под ценой
✓Карточка заказа со стороны исполнителя — «статус-первая»: крупный блок текущего статуса с однозначными формулировками («Čeká na potvrzení zákazníka», не «vaše»), живой обратный отсчёт до авто-подтверждения (реальный AutoConfirmService, 24 ч), контакт заказчика сразу под статусом, свёрнутый timeline, компактная карта после сдачи, свой профиль убран. Вопросы-ответы AI-диалога сохраняются в описание и показываются исполнителю до приёма заказа
✓Материалы и доплаты (§7.6): исполнитель во время работ запрашивает согласование докупленного материала (сумма + описание + фото чека), заказчик подтверждает/отклоняет; согласованное идёт в material_cost как pass-through. Безопасность эскроу: материалы и страховка НЕ выплачиваются из эскроу (холд держит только labour) — закрыт канал вывода средств платформы через согласование материалов; выплата = работа − комиссия
✓«Nahlásit problém» для исполнителя: структурированный отчёт о проблеме (клиент не на месте / иной объём / не могу закончить / другое) вместо свободного текста — тот же механизм спора, заказ замораживается, уведомление маршрутизируется второй стороне. Фото выполненной работы (kind=after): исполнитель прикладывает перед «Práce hotová» (защита сторон при споре), мягкое напоминание если фото нет
✓Гео-подсказки адреса точнее: ранжирование результатов Photon по совпадению названия улицы (совпавшая улица всплывает над «номером в чужом кадастре») + добор улицы отдельным запросом, когда «улица+номер» вернул только номер. Поля ввода 16px — iOS Safari больше не зумит страницу при фокусе (частый кейс — поле даты)
✓Три уровня персонала (operator/admin/superadmin) по рангу поверх RoleGuard: оператор — первая линия (проверка документов, споры, мониторинг заказов), админ — деньги/санкции/конфиг, суперадмин — управление персоналом. Мониторинг «зависших» заказов для оператора: невзятые/незавершённые с фильтром по часам ожидания
✓Споры maker-checker (принцип «четырёх глаз»): оператор разбирает и оставляет рекомендацию (refund/release), финальную резолюцию с движением эскроу исполняет только админ (метод-гард строже классового) — одобряет рекомендацию или переопределяет. Audit-log персонала (санкции, роли, рекомендации/резолюции, ревью KYC) вынесен на отдельную страницу /admin/audit с фильтрами (действие, e-mail, период), доступ только superadmin. Журнал append-only: триггеры БД запрещают UPDATE/DELETE/TRUNCATE
🔑 Ждёт владельца (нужен ключ или аккаунт)
Код готов и задеплоен — включается сам, как только появится доступ к сервису.
Stripe: включить Connect + живой тест
⏳ нужен ключключи добавлены, весь код монетизации в проде. Осталось: включить Connect в дашборде Stripe (Connect → Get started, Czech Republic) для выплат исполнителям и прогнать сквозной тест картой 4242 4242 4242 4242 (эскроу → приём → выплата → подписка)
mojeID вход
⏳ нужен ключкод готов, HTTPS есть — осталось зарегистрировать regtest-клиента с redirect https://pronti.cz/api/v1/auth/mojeid/callback
SMS по-настоящему (GoSMS.cz)
⏳ нужен ключинтерфейс готов, шлём dev_code в ответе — нужен аккаунт GoSMS, и коды уйдут реальным SMS
Push-уведомления (FCM)
⏳ нужен ключколокольчик и лента уже есть; для push нужен Firebase-проект
Google / Apple вход (§9.3)
⏳ нужен ключкод входа по email/паролю готов; для соц-входа нужны OAuth client-id/secret Google и Apple (регистрация приложений)
📘 Спека v2.0
✅ Реализована полностью
Все пункты Разделов 1–9 и UX-ревью — в проде. Дальше только «ждёт владельца» (ключи) и развитие вне спеки.
🧭 Включим, когда упрёмся
Не задачи «на сейчас»: они дают смысл только при масштабе/объёме, раньше — лишний overhead.
Redis
· по мере ростанужен ТОЛЬКО когда инстансов API станет несколько: общий адаптер Socket.io (события между инстансами) + общий rate-limit store. Сейчас один инстанс — Redis не даёт ничего
Маскированные звонки
· по мере ростаproxy-номер вместо раскрытия телефона (приватность + анти-обход + запись для споров). Стоит денег (телефонный провайдер) — делать, когда утечка сделок «мимо платформы» начнёт бить по обороту
Эскроу: блокировка от гонки
· по мере ростаSELECT … FOR UPDATE в payments против двойного release — актуально только с реальным Stripe (сейчас провайдер-заглушка)
🗓 В конце
Раздельные аппки клиент / исполнитель
🗓 позжекак Uber / Uber Driver — два входа, когда дойдём до мобильных
Мобильные приложения
🗓 позжеReact Native (Expo), iOS + Android — финальный этап
Технический статус по модулям — docs/15 в репозитории. Эта страница обновляется с каждым релизом.