🗺 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 в репозитории. Эта страница обновляется с каждым релизом.