Навигация по фазам
Быстрый переход к любой из 25 фаз. Клик — прыжок к нужному разделу.
🎯 Порядок приоритетов внутри стадии 1
Фазы упорядочены по приоритету исполнения. Используйте эту таблицу для навигации.
| № | Фаза | Приоритет | Комментарий |
| 1.1 | Admin Visual Redesign + Branding | 🔴 Priority #1 | Брендбук разблокирует всю визуальную работу |
| 1.2 | Self-Serve Onboarding + Quick Build | 🔴 Critical | Trial signup → builder → first project published на per-project domain. Зависит от 1.3 (модель доступа) и 1.7 (billing). |
| 1.3 | Tenancy & Permission Model ⭐ | 🔴 Critical (foundational) | Архитектурная основа: 5 ролей, multi-tenant scoping, Closed pool stock allocation, hybrid login. Cross-cutting в 1.2 / 1.4 / 1.7 / 1.10 / 1.11. |
| 1.4 | Operator Dashboard [OPL] | 🔴 Critical | Расширение существующей Super Admin Panel. Без него нет инструмента управлять студиями с момента первой регистрации. |
| 1.5 | MCP Server Wrapper | 🟡 High | Архитектурная основа self-serve, но не блокирует запуск. Если scope большой → итерация в Стадию 2 |
| 1.6 | Admin UX Critical Blockers | 🟡 Conditional | Большинство багов — dev-env. Требует верификации tech team на проде |
| 1.7 | Платёжная инфраструктура + Sales Page | 🔴 Critical | + flat-fee tier альтернатива subscription |
| 1.8 | Security & Infrastructure Foundation | 🔴 Critical | Foundation для всего остального — изоляция, rate limits, backup, error tracking, transactional email |
| 1.9 | Legal & Compliance | 🔴 Critical | EU + UAE + Australia. База: VV T&Cs (AU) + Stripe/Cloudflare шаблоны (EU) |
| 1.10 | Sales-app UX redesign | 🟠 Critical-conditional | Filter-based selection. MVP (1.10.1) обязателен; остальное по эстимейту tech team |
| 1.11 | Sales Presentation Layer ⭐ | 🔴 Critical | Buyer-facing flow: tokenised unit links, attribution Sales Agent'у, lead capture. Завершает sales loop. Зависит от 1.3 + 1.10. |
📚 Foundational decisions · v4.4 · CONV-17 · 2026-05-06 (обновлялось CONV-33 / CONV-34 — см. callouts ниже)
Tenancy, permissions, onboarding & access — read this first
Эта секция — synthesis закрытого /plan permission-and-tenancy-model interview (Blocks A-G). Её решения — cross-cutting: применяются в Фазах 1.2, 1.3, 1.4, 1.7, 1.9, 1.10, 1.11. Прочитайте её до того как уйдёте в детали отдельных фаз — она объясняет «кто есть кто», «как работает подписка», «как раздаются доступы», «что видят разные люди». Каждая Фаза ниже ссылается на конкретные пункты этой секции через CONV-17 callouts.
Foundational · 1 / 7
Кто есть кто (entity glossary)
Платформа разделяет людей (с логином) и сущности (бизнес-структуры). Один человек может управлять несколькими бизнесами и быть приглашённым в чужие — поэтому Client (identity) и Organisation (tenant) — две разные вещи.
Client (человек с логином)
└─→ создаёт / приглашён в → Organisation (tenant — бизнес-сущность)
├─ subdomain ({slug}.offplan.online)
├─ subscription (tier)
├─ team (Clients with roles)
└─ Project (off-plan здание/комплекс)
└─ Unit (квартира)
Сущности
| Сущность | Что это |
| Client | Человек с логином (email + password / Google / Microsoft). Один Client = одна identity (один email). Может быть в нескольких Organisations одновременно с разными ролями. Organisation switcher в шапке переключает контекст. |
| Organisation | Tenant — бизнес-сущность. Создаётся Client'ом при signup (Client становится Owner). Имеет subdomain, subscription, team, projects. Один или несколько types (multi-select): Studio / Agency / Developer — можно совмещать (например, VV = Studio + Agency). |
| Project | Off-plan проект (здание / квартал / комплекс таунхаусов) внутри Organisation. Содержит floorplates, юниты, gallery, settings. URL: {slug}.offplan.online/projects/{project-slug}. |
| Unit | Одна квартира / таунхаус внутри Project. Имеет status (available / reserved / sold), price, attributes, attribution к buyer'у и Sales Agent'у. |
| Buyer | Конечный покупатель квартиры. Не Client — без логина, без своей Organisation. Получает email от Sales Agent'а с tokenised ссылками на отобранные ему юниты. Token expiry — 90 дней; после expiry buyer-record и attribution к Sales Agent'у остаются в DB (если потом купит — комиссия Sales Agent'у). |
Роли — per Organisation per Organisation
Один Client может иметь разные роли в разных Organisations. Role assignment — отдельная запись membership на каждой Organisation.
| Роль | Что может |
| Owner | Client, создавший Organisation (или принявший ownership transfer — см. §3 Ownership transfer). Единственный с billing access — полный контроль (transfer, cancel, tier change). |
| Admin | Всё что Owner, кроме billing/cancel/transfer. Может приглашать/удалять Clients, менять roles, устанавливать external agency relationships. |
| Sales Manager | Operational sales lead = Content Editor + stock allocation + buyer flow. Не управляет командой и billing'ом, но имеет полный operational контроль над контентом, stock allocation, buyer flow. Приглашает Sales Agents. |
| Content Editor | Контент: gallery, renders, floorplates, descriptions, переводы, цены юнитов. Не презентует, не приглашает. Видит всё в проекте (assignment не блокирует content access). |
| Sales Agent | Buyer / presentation flow. Меняет status assigned units через verification form (см. §6.1). Не редактирует контент. Делится на Internal (Client из команды самой Organisation) и External (Client из другой Organisation, приглашён через guest-organisation invite) — operational различия в §4.5. |
| Free Guest | Property of Organisation: бесплатный tier. Organisation на Free Guest tier может быть guest organisation в чужих проектах (приглашена по reverse invite), не может создавать свои проекты. Path к upgrade'у — лениво при попытке «+ Create project». |
Real-world примеры — как одна Organisation может играть разные роли (3)
- Volume Vision (Studio + Agency): в проекте Cote (итальянский девелопер — его Organisation платит за подписку) VV приглашена как guest organisation в роли Studio (рендеры + admin контент). В проекте Marina (другой девелопер — отдельная Organisation) VV приглашена как guest organisation в роли Agency (продаёт квартиры). У VV одна Organisation в системе — в своих проектах она owning Organisation (плательщик), в чужих — guest с нужной ролью.
- Иван (Content Editor + Sales Agent): один Client с email
ivan@gmail.com, два membership'а: Content Editor в Organisation Volume Vision и Sales Agent в Organisation Evgenia Realty (его подработка). Organisation switcher показывает обе организации в шапке.
- Italian developer (Free Guest Organisation): VV сделала ему весь проект как «reverse invite» — Italian developer зарегистрировался Client'ом, создал свою Organisation на Free Guest tier, получил guest access к Cote. Если потом захочет создать свой собственный проект — нажмёт «+ Create project», увидит upgrade modal, выберет tier, заплатит — и Organisation станет full на Tier 1+, его existing guest membership в Cote сохранится.
Что вне Stage 1: secondary emails per Organisation (Stage 2), self-service Client identity merge (Stage 2), self-service Organisation ownership transfer после первого payment (Stage 2/3 — Stage 1 разрешает только до payment, см.
§3 Ownership transfer).
Foundational · ⭐ Сценарии пользователей · читать после §1
Четыре сценария — что делает каждый актёр
Краткий нарратив — путь каждого ключевого актёра от первого касания до завершения работы. Эта секция нужна, чтобы за пять минут понять как платформа работает целиком. Технические детали — в задачах фаз и Foundational-секциях, на которые здесь ссылки. Эта секция — оглавление, не источник истины.
🏢 Owner — от регистрации Client'а до публикации первого проекта
- Регистрируется на
app.offplan.online — email и Google-логин или email с паролем. Форма минимальная: только идентификация.
- Сразу после регистрации попадает в Object Builder. Слева форма, справа живой превью страницы — обновляется по мере загрузки файлов.
- Заполняет: название проекта → поддомен (платформа предлагает вариант, проверяет занятость) → три файла: внешний рендер, поэтажные планы (платформа сама расставит теги), галерея.
- Жмёт Save & Continue — проект опубликован на
{slug}.offplan.online/projects/{project-slug}. Ссылку можно сразу отправлять.
- На триале остаётся в Object Builder до момента подписки. С подпиской открывается полный админ-интерфейс.
- В Settings выбирает Public Visibility (по умолчанию Discovery — анонимный посетитель видит проекты и юниты, но без цен).
- Приглашает команду: сейлз-менеджер, контент-редактор, сейлз-агент. Каждое приглашение — одноразовая ссылка на 7 дней.
- По желанию — подключает свой домен (доступно с Tier 2).
→ Object Builder: 1.2.4 · Регистрация: 1.3.11 · Видимость: §5
📋 Сейлз-менеджер — раздача стока сейлз-агентам
- Логинится — на брендированной странице
{slug}.offplan.online/login или через общий вход app.offplan.online/login.
- Если состоит в нескольких Organisations — переключатель организаций в шапке (как в Slack).
- Открывает проект → раздел Units в админке.
- Выбирает юниты галочками (массово через фильтры), нажимает Assign to и выбирает агентство или конкретного сейлз-агента.
- По умолчанию работает Closed pool: назначенные юниты эксклюзивно у того, кому отдали; неназначенные не видны никому. Можно включить Open pool на проект — тогда гости видят общий «Internal pool» как у брокеров.
- Может пригласить гостевую организацию (девелопера-клиента) — Forward invite, тоже 7 дней.
- Если человека или агентство удаляют из системы — их назначения не сбрасываются в общий пул, а эскалируются вверх (к сейлз-менеджеру или админу).
→ Раздача стока: §4.4 · Назначения: 1.3.4 · Приглашения: 1.3.6
🎯 Сейлз-агент — от приглашения до продажи
- Получает приглашение от сейлз-менеджера на email — одноразовая ссылка, действует 7 дней.
- Принимает приглашение, попадает в организацию в составе своей Organisation.
- Открывает страницу проекта по обычному адресу — например,
tapestry.offplan.online. Видит публичную версию, как любой другой посетитель.
- В правом верхнем углу — иконка логина. Кликает, входит через Google или email/пароль.
- Та же страница перезагружается — теперь со своим набором квартир. Это и есть его «scope».
- По умолчанию видит только те юниты, которые сейлз-менеджер ему лично назначил. Ничего больше.
- Может менять статус своих квартир:
available → reserved → sold. Каждое изменение пишется в audit log.
- На встрече с покупателем создаёт buyer profile (email, имя, телефон). Платформа генерирует ссылку с токеном для покупателя.
- После встречи покупатель получает email с подборкой квартир, которые он лайкнул. Контактом везде указан этот сейлз-агент.
- Когда нужно — выходит из аккаунта, страница возвращается в публичный вид.
→ Иконка логина: 1.10.0 · Сток сейлз-агента: §4.4 · Buyer flow: §6
🛒 Покупатель — от ссылки сейлз-агента до пересылки семье
- Получает email с подборкой квартир от сейлз-агента. В каждой ссылке зашит токен — он привязывает покупателя к этому сейлз-агенту.
- Открывает страницу юнита — видит цены, наличие, контакт сейлз-агента; кнопки «Лайк» и «Связаться со мной» работают.
- Лайкает квартиры, листает альтернативы.
- Жмёт «Связаться со мной» — заявка падает сейлз-агенту в админку, привязанная к этому покупателю.
- Пересылает ссылку жене или другу — токен валиден 90 дней. Привязки к одному устройству нет, пересылка работает.
- После 90 дней токен истекает: покупатель попадает на основную страницу проекта без персонализации, но в базе привязка к сейлз-агенту сохраняется. Если в итоге купит — комиссия всё равно идёт этому сейлз-агенту.
- (Stage 2) Если в будущем добавим логин для покупателей — он сможет вернуться к своим лайкам, сейлз-агент остаётся прежний.
→ Buyer flow: §6 · Состояния посетителя: §5 · Buyer profile: 1.11.1-4
Не описано здесь: оператор платформы (Сергей, Рома, Илья) — у него отдельный staff-дашборд, см. Phase 1.4. Контент-редактор работает почти как сейлз-менеджер, но без раздачи стока. Разница между владельцем и сейлз-менеджером — в §4.2.
Foundational · 2 / 7
Регистрация и онбординг
Три точки входа в систему. Каждая ведёт к разному результату. После регистрации на платный tier (path A) — экран-развилка из 3 опций (см. ниже), не сразу в Object Builder. Аккаунт создаётся один раз (по email) и работает во всех Organisations, к которым Client подключается в будущем.
| Путь | Кто и когда | Куда попадает |
| (A) Регистрация — платный tier | Студия / агентство / девелопер хочет свою организацию для своих проектов. Заходит на offplan.online, нажимает «Get started» → выбирает тариф → попадает в Object Builder. Карта не привязывается на этом шаге — даётся 14-дневный trial T1 (см. §3 Trial period). | Своя организация на {slug}.offplan.online. Роль Owner. Может создавать проекты, приглашать команду и гостевые организации. После trial без оплаты — auto-downgrade → Free Guest, projects read-only. |
| (B) Регистрация гостя (Free) | Кто-то получил обратное приглашение — например, VV сделала проект и приглашает итальянского девелопера. Девелопер регистрируется на бесплатном тарифе по ссылке-приглашению. | Своя организация (бесплатный тариф) с уже подключённым гостевым доступом к нужному проекту. Может смотреть и редактировать контент по правам, но не может создавать свои проекты до перехода на платный тариф. |
| (C) Приглашение в команду | Владелец Organisation приглашает человека в свою команду — например, Ивана как контент-редактора, сейлз-агента или сейлз-менеджера. Иван получает email от {slug}@offplan.online. | Иван присоединяется к организации в указанной роли (на уровне всей компании или конкретного проекта). Если у Ивана уже есть аккаунт на этом email — к нему добавляется участие в новой компании. Если нет — создаётся новый аккаунт. |
Entry-point choice — что Client видит сразу после signup (path A) (3 опции)
После signup'а на платный tier Client попадает не сразу в Object Builder, а на screen с выбором — у разных Client'ов разный intent: одни хотят один проект быстро, другие сначала собирают команду на 50 проектов вперёд. Дефолт-cursor на (1).
- (1) «Start your first project» (primary CTA) — открывает Object Builder (см. Phase 1.2.4). Single-project Client'ы регистрируются именно так. Самый частый путь.
- (2) «Set up your organisation» — мини-визард: types (Studio/Agency/Developer multi-select) + brand (logo + accent color) + invite команды. После — landing на Organisation dashboard, Client сам решит когда создавать первый проект.
- (3) «Skip» — landing на empty dashboard. Всё доступно через меню (invite, create project, settings). Для опытных или «я зашёл посмотреть».
Public Visibility preset спрашивается при создании каждого проекта (внутри Object Builder + дублируется в Project Settings) — 4 варианта (Private / Discovery / Full sales / PIN-protected, см. §5). Дефолт = Discovery.
Login UX — где живёт login form и куда редиректит (3)
- По умолчанию: приглашённый попадает на
{slug}.offplan.online/login — страница входа с брендингом Organisation (логотип, цвета). Альтернатива — общий вход app.offplan.online/login («не помню свой адрес?») — показывает все организации для этого email.
- Вход через поддомен: сразу попадает в организацию. Если состоит в нескольких компаниях — переключатель в шапке (как в Slack).
- Вход через общий адрес: одна компания = автоматический переход. Несколько компаний = страница выбора организации.
Auth methods — Google + email/password (4)
- Google OAuth: кнопка «Войти через Google» — primary, рекомендуемый CTA на login screen.
- Email + пароль: equal-weight fallback («Sign in with email»). Минимум 12 символов (NIST SP 800-63B), проверка по haveibeenpwned при регистрации + смене пароля.
- Сброс пароля: одноразовая magic-link ссылка на email, валидна 60 минут, single-use, invalidates все active sessions.
- Сессия: 30 дней с обновлением при активности (один cookie на
*.offplan.online).
Microsoft (Azure AD / Entra ID) + Custom SSO (SAML 2.0 / OIDC) — Stage 2 Tier 3 (Enterprise) gate per ADR 0005 v3. Trigger: первый Tier 3 customer commitment (revenue trigger). Stage 1 ограничен Google + email/password на всех tier'ах.
2FA scheme — opt-in Stage 1, mandatory для Owner+Admin Stage 2 (3)
- Stage 1: 2FA optional для всех Clients с ролями. TOTP (Google Authenticator) или SMS fallback.
- Operator dashboard (
staff.offplan.online): 2FA mandatory всегда (внутренний tooling).
- Stage 2 (после 100 проектов / первой compliance проверки): mandatory 2FA для Owner+Admin (роли с billing access). Content Editor/Sales Agent остаются optional.
Несовпадение email при приглашении: владелец ввёл ivan@gmail.com, а у Ивана аккаунт на ivan.test@gmail.com → Stage 1: ошибка «email приглашения не совпадает, свяжитесь с тем, кто пригласил». Stage 2: самостоятельное объединение аккаунтов.
Foundational · 3 / 7
Подписка — Модель 4 (тарифная система + бесплатные гостевые компании)
Главное решение по оплате: подписка живёт на уровне Organisation. Каждая Organisation на своём tier — один из четырёх: Free Guest + три платных (T1, T2, T3). Tier 2+ может приглашать guest organisations бесплатно (они работают на бесплатном тарифе). Это покрывает обратный сценарий (студия приглашает девелопера в своё пространство) и самостоятельный рост (девелопер пробует как гость → переходит на платный тариф).
Какие модели рассматривались и почему выбрали Модель 4 (4)
- ❌ Модель 1 — каждая организация платит сама. Высокий барьер для входа в реальном рынке офф-план недвижимости. Девелопер обычно сам оплачивает весь набор инструментов для продаж и не хочет просить свои guest organisations ещё дополнительно подписываться.
- ❌ Модель 2 — подписка платящего покрывает всю экосистему бесплатно. Низкий доход на пользователя, риск злоупотребления (один платящий приводит 100 бесплатных).
- ❌ Модель 3 — оплата за каждое место (как в Figma). Сложный биллинг, трение при каждом добавлении пользователя. Команды в офф-план продажах часто меняются (фрилансеры на проект) — постоянные изменения подписки.
- ✅ Модель 4 — каждая организация на своём тарифе, гостевые компании бесплатно. Покрывает обратный сценарий (агентство хочет видеть проекты нескольких девелоперов) + самостоятельный переход (гость пробует → переходит на платный тариф). Одна платная подписка от одной организации.
| Тариф | Что доступно (ориентировочно) | Цена |
| Free Guest | Может быть гостевой компанией в чужих проектах (по обратному приглашению). Может приглашать пользователей в свою организацию (но они тоже видят только гостевой контент). Не может создавать собственные проекты. Не может приглашать гостевые компании. | $0 |
| Tier 1 | Свои проекты с базовым лимитом. Все 5 ролей. Настройки видимости. Поддомен по умолчанию {slug}.offplan.online. Может приглашать гостевые компании. | TBD → ADR 0008 |
| Tier 2 | Всё из Tier 1 + собственный домен (настройка через CNAME) + DKIM на свой домен + повышенные лимиты на проекты / команду / гостевые компании. | TBD → ADR 0008 |
| Tier 3 (Enterprise) | Всё из Tier 2 + единый вход для всей студии (Google Organisation / Microsoft / Custom SSO — SAML/OIDC), SLA, индивидуальные лимиты, дополнительные модули по запросу. | По договорённости |
⚠️ Это ориентировочный вид, не финальные тарифы. Конкретные цены, лимиты (X проектов, Y участников команды) и возможное переименование линейки (T1/T2/T3 vs Starter/Studio/Enterprise) — фиксируются в ADR 0008 (Tier model, Skeleton) + sub-plan plans/onboarding-trial-mode.md. В рамках этого плана зафиксирована только структура: 4 tier'а с описанным выше назначением.
Trial period — первые 14 дней для Path A signup (7)
- Триггер: Client регистрируется через
offplan.online, выбирает tier на pricing page → попадает в Object Builder с 14-дневным бесплатным доступом к T1 функционалу. Карта не привязывается на этом шаге.
- Не применяется: Path B (guest invite — сразу Free Guest, без trial) и Path C (team invite — роль в чужой Organisation, без своей подписки).
- Что доступно во время trial: полный T1 функционал — создание projects, invite guest organisations, default subdomain
{slug}.offplan.online, все 5 ролей, настройки видимости.
- Что НЕ доступно: T2/T3 фичи (custom domain, DKIM, SSO) — они нужны для production-deploy студии, повод для upgrade. Trial = T1 only, не выбор.
- UI: в шапке админки — badge
TRIAL — N days left. Только Object Builder доступен; Full Admin залочен пока нет активной подписки (см. Phase 1.2 v4.5).
- Email reminders: день 7, день 12, день 14 — нагретые CTA «выбрать tier и оплатить».
- По истечении без оплаты: auto-downgrade → Free Guest. Все trial-projects остаются в аккаунте, но read-only (нельзя редактировать, нельзя создавать новые). Публичный сайт проекта работает 30 дней, потом freeze («временно недоступно, свяжитесь с
{operator-email}»). Оплатил в любой момент — полный доступ возвращается мгновенно (включая re-edit existing projects).
Abuse mitigation Stage 1: email verification (already required) + rate-limit per IP. Если pattern злоупотребления появится — расширим в ADR 0008 / sub-plan.
Ownership transfer — до first payment self-serve, после — через support (5)
Use case (главный sales motion): студия создаёт Organisation на trial, собирает контент проекта, передаёт ownership девелоперу. Девелопер регистрируется / принимает invite → ownership flips → девелопер делает first payment со своей карты → его billing с этого момента.
- Когда self-serve доступен: на Organisation, где не было ни одного payment (trial period или Free Guest state). Owner может trigger'ить transfer самостоятельно.
- Flow (4 шага):
- Owner идёт в
Settings → Transfer Ownership. Вводит email получателя.
- System отправляет email-инвайт с одноразовым токеном (7d expiry).
- Получатель открывает email, регистрируется (если ещё нет аккаунта на этот email) или logs in, видит acceptance screen с описанием Organisation: slug, projects count, current tier (Trial / Free Guest).
- На acceptance: получатель выбирает что произойдёт со старым Owner — стать Admin или быть удалённым из команды. Confirm → ownership flips, audit log entry «Ownership transferred from X to Y».
- После first payment: UI кнопки скрыт. Settings page показывает: «Ownership transfer для Organisations с активной подпиской — через
support@offplan.online. Self-serve версия — Stage 2/3 backlog.»
- Edge cases: если получатель отказывается / token expires — invite cancelled, ownership остаётся у текущего Owner. Если получатель уже Owner другой Organisation — ничего не ломается, у Client'а становится N memberships.
- Cross-link: §1 Owner role · ADR 0009 (Tenancy) — transfer mechanic учитывается в RBAC дизайне.
Что происходит при просрочке / отмене подписки (после first payment) (5)
- Льготный период: 14 дней между просрочкой оплаты и блокировкой. Применяется только к Organisations с активной подпиской — для trial expiry см. §3 Trial period.
- Частичная блокировка: вход в аккаунт работает, проекты видны, но редактирование / приглашения / публикация отключены. Публичный сайт проекта работает ещё 30 дней после блокировки. После 30 дней — сайт заморожен («временно недоступен, свяжитесь с
{operator-email}»).
- Статусы юнитов не меняются: юниты в статусе
reserved или sold остаются как есть, мы ничего не сбрасываем автоматически. Organisation после восстановления продолжает работать с тем что было.
- Ссылки для покупателей: работают 30 дней после блокировки. Потом страницы юнитов показывают «временно недоступно» с контактом оператора.
- Восстановление: оплатил → полный доступ сразу + запись в audit log «reactivated» + уведомления всем участникам команды и гостевым компаниям.
Как гость / trial переходит на платный тариф (4)
- Path A (trial → paid): в badge «TRIAL — N days left» — клик → pricing modal → выбор tier (по умолчанию выбран тот что был при signup) → Stripe → first payment записан → trial badge исчезает, Full Admin открывается.
- Path B (Free Guest → paid): гость в своей организации видит «Ваши проекты (0)» + кнопку «+ Создать первый проект».
- Нажатие → всплывающее окно: «Для создания проектов нужна подписка. Выберите тариф:» → оплата через Stripe.
- После оплаты (любой path): подписка активируется. Все существующие гостевые участия сохраняются. Trial-projects (если были) переходят из read-only в editable. Ownership transfer self-serve UI скрывается (см. §3 Ownership transfer).
Foundational · 4 / 7
Раздача доступов — invitations + permissions + stock allocation
Самая сложная часть архитектуры — 3 ортогональные системы которые работают вместе: (1) invitations определяют кто попал в систему; (2) permissions matrix определяет что роль может делать; (3) stock allocation определяет кто видит/может продать конкретный unit.
4.1 — Invitations: 4 типа
| Тип | Когда используется | Token |
| Personal invite | Внутри своей Organisation — Иван как Content Editor / Sales Agent в команду. Org-level (все проекты) или project-level (один проект). | Single-use, 7 days expiry |
| Organisation invite (forward) | Developer создал project, приглашает Studio / Agency как guest organisation. Permissions per project + scope. | Multi-use, 7 days expiry |
| Reverse invite | Studio (e.g., VV) сделала project, приглашает Developer'а как guest organisation (сценарий VV → Italian developer). Если у developer'а нет аккаунта — Free Guest tier signup path. | Multi-use, 7 days expiry |
| Buyer email link | Sales Agent отправляет presentation email со shortlist'ом. Не invitation в строгом смысле — buyer не joining organisation, просто получает tokenised URLs. | Per-unit token в URL, 90 days expiry |
Token format: opaque random string + DB row (invitations table: token, type, client_id, invitee_email, role, scope, status, expires_at). Server-side lookup на каждый клик. Простой revoke (status='revoked'), full audit trail.
4.2 — Permissions matrix (5 ролей)
Иерархия: Owner ⊃ Admin ⊃ {Sales Manager, Content Editor, Sales Agent} — Sales Manager / Content Editor / Sales Agent параллельны. Один Client = одна role per Organisation (если нужно и контент и продажи → Admin).
Sales Agent column применяется к обоим Internal и External SA — базовые permissions идентичны (operational различия — в §4.5 ниже).
| Действие | Owner | Admin | Sales Manager | Content Editor | Sales Agent |
| Billing / cancel / transfer | ✅ | — | — | — | — |
| Add/remove team members | ✅ | ✅ | — | — | — |
| Invite/remove internal Sales Agents (own team) | ✅ | ✅ | ✅ | — | — |
| Invite/remove External Sales Agents (via guest organisation) | ✅ | ✅ | — | — | — |
| Invite guest organisations | ✅ | ✅ | — | — | — |
| Edit content (gallery, renders, floorplates, descriptions, переводы) | ✅ | ✅ | ✅ | ✅ | — |
| Edit unit pricing | ✅ | ✅ | ✅ | ✅ | — |
| Manage stock allocation (assign / unassign units) | ✅ | ✅ | ✅ | — | — |
| Create / edit buyer profiles | ✅ | ✅ | ✅ | — | ✅ (own) |
| Send presentation emails to buyers | ✅ | ✅ | ✅ | — | ✅ (own) |
| Change unit status (available → reserved → sold) | ✅ | ✅ | ✅ | — | ✅ (own assigned) |
| Public Visibility settings (Private / Discovery / Full sales / PIN-protected) | ✅ | ✅ | — | — | — |
| Branding / theme customisation (project-level) | ✅ | ✅ | — | ✅ | — |
| Branding / theme customisation (Organisation-level) | ✅ | ✅ | — | — | — |
Reverse-flip note (CONV-26): reverse направление status change (Sold → Reserved/Available, Reserved → Available) — same permissions как forward (Owner / Admin / SM / SA own assigned). Каждый reverse-flip → audit log + email notification к одному уровню выше (SA → SM, SM → Admin/Owner). Forward-flip — audit only, без notification (standard workflow). См. §6.1 — reverse direction policy.
4.3 — Scoping: в каких проектах у user'а есть membership
«Scope» здесь = в каких проектах Organisation'ы у Client'а есть доступ. Что user видит и может внутри конкретного проекта — отдельная ось (роль §4.2 + stock allocation §4.4).
- Personal invite — org-level по умолчанию. Иван как Sales Agent в Volume Vision видит все проекты VV. Одна membership покрывает всю Organisation.
- Personal invite — project-level через toggle. Для случая фрилансера на один проект: Иван как Content Editor только в Cote, остальные проекты VV ему не видны. Переключатель в invite form.
- Organisation invite (guest org) — всегда project-level. VV приглашена как guest в Cote (проект Developer'а X) — все VV-members наследуют доступ только к Cote, не к остальным проектам Developer'а X.
- Owner / Admin / Sales Manager своей Organisation — bypass scope. Всегда видят все проекты в своей Organisation независимо от per-project assignments (это team-management роли). Content Editor / Sales Agent / guest org members — подчиняются scope.
4.4 — Stock allocation S·1 (Closed pool default + per-project Open mode toggle)
Решение Романа на anti-double-sale: каждый unit имеет один правовой owner на момент reserve. Default mode — Closed pool (secure by default): guest organisations не видят юниты пока им явно не assign'нули. Это ответ на real-world паттерн «Organisation пригласила external сейлз-агента → не хочет чтобы он сразу увидел pricing на 100 квартир».
Stock allocation mode — per-project setting в Project Settings, рядом с Public Visibility (см. §5). Дефолт = Closed pool. Open pool = opt-in для проектов с «open competition» моделью (multiple agencies на одной inventory).
🔒 Closed pool mode (default)
| Состояние unit'а | Кто видит | Кто может продать |
| Internal pool (default, не присвоено) | Owner / Admin / Sales Manager / Content Editor / любой internal Sales Agent. Guest org-members — НЕТ. | Owner / Admin / Sales Manager / любой internal Sales Agent |
| Assigned to guest org (e.g., Agency A) | Только members этой guest org + Owner/Admin/Sales Manager owning Organisation + Content Editor (всегда) | Только members этой guest org |
| Assigned to user (e.g., Иван) | Только Иван + Owner/Admin/Sales Manager owning Organisation + Content Editor (всегда) | Только Иван |
🔓 Open pool mode (per-project opt-in)
Единственное отличие от Closed mode: «Internal pool» юниты видят и могут продать ВСЕ Sales Agent'ы с project access, включая members guest organisations. Assigned-to-user и Assigned-to-org остаются exclusive как в Closed mode.
Use case: multiple agencies competing на full inventory (broker-style). Bulk «assign all to Agency X» не нужен — все видят всё по дефолту.
Bulk operations Stage 1: filter list view + multi-select checkboxes + dropdown «Assign to» (grouped: organisations / users). CSV import → Phase 1.5.6 (AI file upload endpoint, MCP wrapper). Range-select на floorplate → Stage 2. Critical UX в Closed mode — Sales Manager часто будет делать «дать этой agency 30 юнитов одной кнопкой».
Cascade при удалении target'а — escalate up, never auto-revert в Internal pool. User leaves → revert assignments к Sales Manager/Admin Organisation'ы. Guest org removed → revert к Owner-team. Auto-revert в Internal pool rejected — риск нежелательного widening доступа без явного согласия Owner'а.
Что вне Stage 1 — multi-allocation, custom roles, sub-project scoping (5)
- Multi-allocation (один unit нескольким parties одновременно) — Stage 2 if demand. Увеличивает risk double-sale, требует conflict-resolution UI.
- Specific user inside guest org (Маша из E&V персонально, не вся E&V) — Stage 2.
- Personal role group (all Senior Sales Agents) — Stage 2.
- Custom roles (e.g., «Compliance Sales Manager» с custom permissions) — Stage 2.
- Per-action scope (Иван может edit Buildings но не Branding) — Stage 2/3.
4.5 — Internal vs External Sales Agent
Sales Agent — одна role с двумя operational контекстами: Internal (Client из team самой Organisation) и External (Client из guest organisation, приглашённой через guest-org invite). Базовые permissions в §4.2 одинаковы; различия — на orbital осях:
| Ось | Internal SA | External SA |
| Stock pool default (Closed mode, см. §4.4) | Видит Internal pool | Не видит Internal pool — только assigned |
| Cross-team visibility | Видит коллег-Internal SA в своей Organisation | Видит только своих в guest organisation |
| Invitation source | Personal invite (см. §4.1) от Owner / Admin / Sales Manager | Член guest organisation, добавлен через org-invite от Owner / Admin |
| Removal authority | Owner / Admin / Sales Manager (revoke personal invite) | Admin owning Organisation (revoke guest-org membership) или Admin guest organisation удаляет user'а |
| Reports / analytics | Видит aggregate Organisation-level (own performance + team performance, без других guest orgs) | Видит только свои продажи + own guest organisation aggregate |
Cross-link: §1 Sales Agent definition · §4.4 Stock allocation Closed pool table.
4.6 — View-as-Agent (admin debug + training)
Use cases: Sales Manager хочет проверить что Иван видит правильно после assignment'ов; Admin отлаживает permissions setup перед onboarding нового члена команды; обучение нового Sales Manager'а («давайте посмотрим как видит работу новый коллега»).
- Кому доступен: Owner / Admin / Sales Manager. Sales Agent — нет (свой view = normal login, см. viewer state #4 в §5).
- UI: в шапке админки toggle/dropdown «View as…» → выбрать Sales Agent / другого Sales Manager. После выбора admin panel перерисовывается с perspective этого user'а; вверху страницы фиксированный banner: «Viewing as Иван (Sales Agent) · Exit view-as-mode →».
- Read-only mode: в view-as-режиме все действия залочены (Save / Edit / Delete / Send / Assign — disabled с тултипом «Disabled in view-as mode»). Это explicit decision — НЕ impersonation. Для actual impersonation (login as user) — отдельный operator flow в Phase 1.4, deferred to Stage 4.
- Что показывается: stock filtered как для target user, list юнитов с их visibility/availability, buyer profiles target user'а, его сейлз-метрики. Permissions matrix фильтрует UI элементы.
- Audit log: entry «User X viewed as User Y at TIMESTAMP, duration N min». Compliance — important чтобы знать кто и когда смотрел чужие views. Schema-level дизайн — Phase 1.3 implementation level.
- Cross-link: Preview-as-Buyer — отдельная фича в presentation builder (не часть §4) для проверки как выглядит email-презентация для конкретного buyer'а перед отправкой. См. Phase 1.11.
Foundational · 5 / 7
Что кому видно (4 viewer states + Public Visibility)
На любой странице Organisation subdomain'а ({slug}.offplan.online/...) поведение определяется 4-мя viewer states:
| Viewer state | Identification | Что видит |
| 1. Anonymous visitor | Нет login, нет buyer-token в URL. Нашёл ссылку через Google / friend forward / social media. | Зависит от Public Visibility setting Organisation'ы: Private / Discovery (default) / Full sales. |
| 2. Buyer с tokenised ссылкой | URL содержит ?b=<token>. Token валиден (не expired). | Полная unit-page: цены, availability, contact = атрибутированный Sales Agent, кнопки «Heart unit» / «Связаться со мной» работают. |
| 3. Buyer с expired token | Token есть в URL, но прошло >90 дней. | Редирект на main project page с сохранённой attribution. Видит то же что anonymous, но если потом купит — комиссия Sales Agent'у X (atribuция в DB остаётся). |
| 4. Organisation team member (logged in) | Залогинен в Organisation, открыл публичную страницу subdomain'а. | Видит страницу всегда как Full sales preset — независимо от Public Visibility setting. Stock allocation (§4.4) фильтрует какие юниты ему видны (Sales Agent = только assigned; Content Editor/Sales Manager/Admin/Owner = всё). Admin-панель / edit-overlay — отдельная surface, не описывается в этой таблице. |
Substate (PIN-protected projects): visitor в state #1 может иметь valid pin_<project_id> cookie от предыдущего входа — рендер тогда такой же как у соответствующего After-PIN preset (Discovery или Full sales), без blur. См. §5.1.
Login entry surface (state #1 → state #4): на каждой странице sales-app — маленькая иконка в правом верхнем углу. Anonymous viewer (state #1) видит её как «Sign in». Click → modal с Google / email login (re-use auth backend из 1.3.3). После логина та же страница перезагружается в state #4 (Organisation team member). Logout → возврат к anonymous view. Buyer-token URL'ы (state #2/#3) — отдельный механизм, не требуют логина. Реализация: Phase 1.10.0.
Public Visibility settings — 4 preset'а (per-project)
Per-project setting (Object Builder при создании проекта + Project Settings → Public Visibility). Определяет какие поля видит anonymous visitor (state #1 из таблицы выше) на публичной странице конкретного проекта — цены, availability, floorplates, или (для PIN-protected) blurred тизер с PIN-gate. На Buyer-flow (state #2) и team members (state #4) не влияет. Org-default Visibility — deferred to Stage 2 (если многопроектные студии попросят).
Не путать со Stock allocation (§4.4) — это две разные оси:
- Public Visibility = какие поля показываем anonymous'у (цены? availability badges? floorplates?). Применяется ко всем юнитам.
- Stock allocation = какие юниты показываем залогиненным team members и guest orgs внутри admin/sales views. На anonymous не влияет — anonymous видит все юниты per выбранный preset.
| Preset | Что видит anonymous |
| Private | Только hero (logo, branding, tagline) + «Request access» CTA. Никаких проектов, юнитов, рендеров. |
| Discovery (по умолчанию для нового проекта) | Все проекты Organisation'ы видны — hero, рендеры, 360°, floorplates, список юнитов. Цены и индивидуальные статусы юнитов скрыты — отображается только counter «N units available» на проект. CTA «Request access» открывает запрос на доступ к Full sales view. |
| Full sales | Всё что в Discovery + цены per unit + availability badges per unit (available / reserved / sold). Полноценный public sales-сайт — anonymous видит каждый юнит во всех проектах Organisation'ы независимо от stock allocation assignments. |
| PIN-protected | Содержимое проекта показывается с CSS blur (силуэты + цвета без деталей); поверх — PIN entry overlay с «Enter PIN» + «Contact us» CTA. Правильный PIN → 30-day cookie + разблокируется выбранный After-PIN view (Discovery или Full sales — Owner выбирает). Buyer-token (?b=...) bypass'ит PIN. Полный spec — см. §5.1 ниже. |
Granular field-level overrides — deferred to Stage 2 (deferred)
В первой итерации planning'а §5 предполагался «Custom» preset с granular toggle'ами (show prices / availability / floorplates / price range / inquiry / heart actions). На 2026-05-08 (CONV-25) этот preset удалён из Stage 1 — 4 базовых preset'а (Private / Discovery / Full sales / PIN-protected) покрывают MVP-needs студий. Granular per-field overrides вернутся в Stage 2 если многопроектная студия запросит гибрид (например, «Discovery + show prices» — между Discovery и Full sales). Heart / «Связаться» actions для anonymous всегда скрыты (требуют buyer-token).
5.1 — PIN-protected preset (deep spec)
Use case: застройщик / студия хочет показать проект приватно (pre-launch teaser, VIP-listing, ранний preview для investor'ов) — отдаёт URL + PIN устно или в одном email. Anonymous, не зная PIN, видит только blurred тизер; знающие PIN — открывают полную страницу.
Anonymous visitor flow (без правильного cookie)
- URL:
{slug}.offplan.online/projects/{project-slug} — обычный sales-app URL.
- Содержимое проекта рендерится в полном объёме (как After-PIN preset выглядел бы) с CSS
filter: blur(12-16px) на content wrapper — силуэты hero, рендеров, floorplate, units list видны, но не читаемы.
- Поверх blur'а — fixed PIN entry overlay (centered card, brandbook v2 styling) с:
- Заголовок: «Project Name» (project-name виден, чтобы пользователь понял на что зашёл) + строка «Эта страница защищена. Введите PIN для доступа.»
- Input field — PIN (free-format string min 4 char — Owner определяет numeric или alphanumeric при setup'е)
- Кнопка «Open project» (submit)
- Sub-block «Не знаете PIN?» с двумя actions: Email us (
mailto:<contact_email>?subject=Access request: <Project name>) + Call us (tel:<contact_phone> если phone не пустой; иначе кнопка скрыта).
- Submit → server validates PIN → если correct → set cookie
pin_<project_id>=<random_token> на 30 дней, redirect на same URL → теперь user видит After-PIN preset (Discovery или Full sales — what Owner выбрал). Если incorrect → form shows error «Wrong PIN» + tracks attempt в audit log; rate-limit 5 attempts → 30s cooldown.
PIN bypass cases (visitor видит After-PIN preset напрямую)
- Valid 30-day cookie на этом проекте — re-entry не нужен.
- Buyer-token URL (
?b=<token>) — token = pre-auth со стороны Sales Agent'а, который buyer'у эту ссылку прислал. Buyer не должен знать PIN (он его не должен видеть). Token валиден → bypass PIN entirely → render полная unit-page (state #2 в viewer states таблице).
- Logged-in team member owning Organisation — Owner / Admin / Sales Manager / Content Editor / Sales Agent → state #4 в таблице, всегда Full sales (PIN не нужен). Logged-in member guest organisation — same: bypass PIN (он уже authenticated в системе с правом на этот проект).
- Owner изменил PIN → все existing cookies invalidated (security default — изменение PIN это «отозвать access у тех кто PIN знает»). Visitors с invalid cookie возвращаются на blurred PIN entry screen.
PIN config UI (Project Settings → Public Visibility = PIN-protected)
Когда Owner / Admin выбирает «PIN-protected» preset для проекта (в Object Builder при создании ИЛИ в Project Settings потом) — разворачиваются 4 поля:
- PIN (required) — text input, free-format string (min 4 char). Hashed at rest (bcrypt / argon2 — implementation Phase 1.3).
- After PIN: visitor sees (required) — radio / dropdown:
Discovery (по умолчанию) | Full sales. Pre-launch без финальных цен → Discovery. С готовыми ценами → Full sales.
- Contact email (required) — visitor который не знает PIN отправит запрос на доступ. Default = Owner email; editable. Per-project — может быть отдельный «секретарь / менеджер / агент» на каждый проект.
- Contact phone (optional) — phone number в международном формате. Если заполнен — на PIN screen появляется кнопка «Call us» рядом с «Email us».
Permission to set / change PIN: Owner / Admin (matching §4.2 row «Public Visibility settings»). Sales Manager / Content Editor / Sales Agent — нет.
Audit log
- PIN set / changed: «User X set / changed PIN for Project Y at TIMESTAMP» — visible to Owner / Admin (НЕ показывает сам PIN value).
- Failed PIN attempts (>3 в час с одного IP) — flag в operator panel (Phase 1.4) для anti-brute-force monitoring.
- Successful PIN entry — НЕ per-attributed event (anonymous visitor); только aggregate counter «N PIN-passed views в day» для analytics.
Schema-level дизайн audit таблицы — Phase 1.3 implementation level (consistent с pattern §4.6 View-as-Agent audit).
Cross-link: Phase 1.2 Object Builder — surface этих 4 полей в creation flow · Phase 1.10 Sales App — routing logic для blur + PIN entry + cookie + buyer-token bypass · Phase 1.4 Operator Dashboard — operator может видеть «Project X is PIN-protected» (для support troubleshooting) но не PIN value.
Foundational · 6 / 7
Buyer flow — Variant E2 (tokenised unit links, no dedicated dashboard)
Решение архитектуры buyer-presentation'а: email = и есть presentation. Никакой dedicated buyer-dashboard'а / shortlist-страницы в Stage 1. Каждый «лайк» во время презентации становится отдельной tokenised ссылкой в email'е.
Внутри §6: существующие <details> блоки покрывают buyer entity model и token mechanics. Подробные subsections ниже: §6.1 — Sales Agent status-change form (D+E unified mechanism) + §6.2 — Channels (Email + WhatsApp + Copy link).
Email content + token mechanics (5)
- URL pattern:
{slug}.offplan.online/projects/{project-slug}/units/{unit-id}?b=<buyer_token>
- Email body: auto-generated summary («3 units in Cote project, prices €450K-680K, 2BR») + agent free-text editable перед send'ом + N tokenised unit-links.
- Token expiry: 90 дней. После expiry — redirect на main project page с сохранённой attribution. Buyer-record не «умирает».
- Buyer-record creation: при отправке email'а Sales Agent создаёт buyer-record в DB. Token attributes click → Sales Agent X. Один buyer-record per (Sales Agent, presentation).
- Sold/reserved unit при клике: open unit-page нормально, status badge показывает «Sold» / «Reserved». Buyer возвращается к другим ссылкам в email'е или гуляет по сайту с сохранённой attribution. Никаких 404 / hard blocks.
Buyer-actions на unit-page (только с валидным token'ом) (2)
- Heart additional units — buyer может «лайкнуть» quartirы которые Sales Agent не выделил. Sales Agent видит в админке («Buyer X added unit Y»), может позвонить.
- Request callback / Связаться со мной — buyer жмёт CTA на unit-page → notification к Sales Agent'у с unit context'ом. Это lead-trigger, не reservation: buyer ничего не резервирует и не lock'ает. Дальнейший процесс (callback, переговоры, booking deposit) — off-platform / в external CRM Organisation'ы. Status юнита члены Organisation меняют вручную в админке когда сами решат.
Forward email / shared token — feature, не bug (3)
- Один token = один buyer-record, multi-session OK. Если жена / партнёр / друг Buyer'а кликают по той же ссылке — каждый клик идентифицируется как тот же buyer-record. Атрибуция сохраняется.
- Защита cheap: rate-limit на «Связаться со мной» (max 1 active per token, cooldown между submissions). Audit log по token'у с IP + timestamp.
- Никакого device-pinning / cookie-binding — это убило бы legit forwarding (жена с телефона). Stage 2 (если попросят): opt-in checkbox «restrict to first device».
6.1 — Sales Agent status-change form (D + E unified mechanism)
Use case: Sales Agent проводит встречу с buyer'ом, договорился о reservation / sold deal'е, нужно поставить unit в Reserved / Sold + связать buyer'а с unit'ом для attribution / commission. Decision (CONV-22): D (status protection) и E (buyer↔unit linkage) объединены в один mechanism — заполнение status-change form auto-links buyer-record by email lookup (smart-match). Альтернатива (2 separate UI: status form + manual unit-buyer link в карточке) отвергнута как излишняя ручная работа.
Form shape (augmented single-click verification)
- Trigger: Sales Agent в админке Project → unit card → нажимает кнопку «Mark as Reserved» (амбер) или «Mark as Sold» (red). Status выбирается кликом, не dropdown'ом — reduces clicks, кнопки чётко разделены.
- Required field:
buyer email (с autocomplete'ом из buyer-records этого Sales Agent'а — recent first).
- Conditional required: если email НЕ matches existing buyer-record →
buyer name + phone становятся required (создаётся новый record). Если email matches existing record → name + phone displayed read-only (auto-fill из existing).
- Optional:
notes (free text — deal value, conditions, comment) + file upload (PDF / JPG: signed booking letter, deposit receipt, photo подписанного контракта, etc.).
- Submit: server validates → создаёт/links buyer-record → flips unit status → audit log entry → email notification (см. ниже).
Smart-match logic (email lookup, E side)
- Lookup в buyer-records этого Sales Agent'а (org-scope, recent first) — если email match → display banner «Buyer found: Иван Петров, +971 50 123 45 67 — ваш buyer от 12 апреля» + auto-link к существующему record'у.
- Lookup в Organisation-wide buyer-records (если в (1) match не найден) — если match → display warning «Buyer Иван Петров existing, attributed to Алексей Иванов. New buyer-record will be created для вашей attribution. Continue?». Решение per CONV-22: разные buyer-records под одним email = разная attribution; новый record создаётся для текущего SA.
- Если match не найден ни там, ни там → form требует name + phone, создаётся new buyer-record (attribution = текущий SA), unit↔buyer link создаётся.
Triggers + reverse direction policy
- Forward triggers: Available → Reserved · Available → Sold · Reserved → Sold (с pre-fill «same buyer?» — если в Reserved уже есть linked buyer-record, форма pre-fill'ит email).
- Reverse triggers: Sold → Reserved · Sold → Available · Reserved → Available. Симметричная policy — same permissions per §4.2 «Change unit status» row (Owner / Admin / SM / SA own-assigned). Sales Agent fixes own mistakes без эскалации к manager'у. Audit log + email notification catches abuse.
- Email notification на reverse-flip: к Sales Manager'у (если SA откатывает); к Admin / Owner (если SM откатывает). Forward-flip — без notification (standard workflow); reverse — «interesting event» worth surfacing.
- Buyer-record fate при reverse: buyer-record остаётся в DB (history + attribution preserved для commission). Unit↔buyer link воидится (audit log entry: «User X reverted Sold → Reserved at TIMESTAMP, voided link to Buyer Y»). Re-flip forward (Reserved → Sold снова) — SA re-fills форму; если same email — auto-link recreates от existing buyer-record. Никаких stale link'ов в DB.
Audit log
- Forward-flip: «User X marked unit Y as Reserved/Sold; linked to Buyer Z (existing | new) at TIMESTAMP. Notes: «...». File: foo.pdf (если приложен)».
- Reverse-flip: «User X reverted unit Y from Sold → Reserved at TIMESTAMP. Voided link to Buyer Z. Reason: «...» (notes если заполнено)».
- Visible to: Owner / Admin / Sales Manager (full audit trail per Project в Project Settings → Activity log). Sales Agent — own actions only (own assigned units history).
- Schema-level дизайн — Phase 1.3 implementation level (consistent с pattern §4.6 View-as-Agent + §5.1 PIN-protected audit).
Cross-link: Phase 1.10 — verification form UI build + WhatsApp button (см. §6.2) · Phase 1.4 — operator dashboard sees flip audit + reverse-flip emails · §4.2 — permission row для status changes (forward + reverse symmetric).
6.2 — Channels — Email + WhatsApp + Copy link
Use case: Sales Agent после встречи / звонка отправляет buyer'у tokenised presentation link через подходящий канал. UAE / MENA reality — WhatsApp dominant (~80% delivery), Email — деловой / formal, SMS — устаревает. Stage 1 covers 3 channels через light deep-link approach (zero vendor integrations).
3 channels (Stage 1)
| Channel | Mechanic | Tracking |
| Email | Native send из platform'ы через Phase 1.8 infra (SES / Mailgun). Default sender = Organisation's verified email; subject = «Presentation: <Project name>»; body = composed message + tokenised links. Phase 1.8 handles delivery, bounces, opens. | URL: ?ch=email. Opens counted в analytics. |
| WhatsApp | Deep-link to SA's own WhatsApp client: https://wa.me/<phone>?text=<encoded message>. SA жмёт кнопку «Send via WhatsApp» в admin'е → browser открывает web.whatsapp.com (или native app если на mobile) с предзаполненным message; SA жмёт «Send» уже там. Никаких vendor integrations — никакого WhatsApp Business API, никакой compliance approval, никаких monthly fees. | URL: ?ch=wa. Opens counted. |
| Copy link | Кнопка «Copy buyer link» в admin'е → clipboard'у копируется tokenised URL с ?ch=link. SA pastes куда хочет — Telegram / iMessage / LinkedIn DM / SMS / etc. Универсальный fallback. | URL: ?ch=link. Opens counted (без знания target channel). |
UI flow в Sales Agent admin'е
- SA в Project admin'е → buyer-record card (или после Object Builder при создании презентации) → «Send to buyer» button.
- Modal: compose message (default text editable: «Hi <buyer_name>, here's the presentation we discussed: <link>») + selected units (chips, removable) + 3 channel buttons:
- 📧 Send via Email — disabled if buyer email is empty.
- 💬 Send via WhatsApp — disabled if buyer phone is empty (tooltip «Phone required for WhatsApp»).
- 🔗 Copy link — always enabled.
- Click → action: Email отправляется с backend'а; WhatsApp / Copy открывают browser handlers.
- Multi-channel в одну операцию — SA может click Email AND WhatsApp одновременно («не уверен какой канал buyer чаще проверяет»). Same buyer-token URL, разный
?ch= param на каждой версии — multi-channel attribution counter в analytics.
Default message text + locale
- Pre-filled на Org locale (Stage 1 supports English + Russian per ADR 0007 i18n; Arabic Stage 2 если рынок попросит).
- Template (English): «Hi <buyer_name>, here's the presentation we discussed: <link>». Russian: «Привет <buyer_name>, вот презентация о которой мы говорили: <link>».
- SA редактирует inline в admin'е перед клик'ом «Send» — full freedom для personalisation.
- Per-channel templates (different text для Email vs WhatsApp) — Stage 2 если попросят. В Stage 1 — same text для всех channels (SA может вручную подкорректировать перед каждым send'ом).
Cross-link: Phase 1.10 — UI flow build + 3 channel buttons · Phase 1.8 — Email infra (already in plan) · Phase 1.4 — operator dashboard channel analytics aggregate.
Stage 2 channels backlog: SMS via Twilio (carrier compliance, monthly fee), centralised WhatsApp via Business API (от platform'ы send not from SA's phone — pretty UX, audit log, opt-in flows; vendor onboarding required).
Foundational · 7 / 7
Edge cases (suspension / GDPR / conflicts / referrals)
⏸ Parking-lot (CONV-27): §7.2 GDPR / ADGM right-to-erasure + §7.3 Multi-jurisdiction compliance — DEFERRED до (1) lock'а jurisdiction (Cyprus default по memory, под review awaiting Roman ratification); (2) подключения юриста (Cyprus / EU / UAE); (3) активации sub-plan'а plans/legal-multi-party-framework.md. До этого момента не править. Архитектурные edge cases (§7.1 deactivation / §7.4 conflicts / §7.5 referrals) — closed in Chunk 6.
User deactivation — что происходит когда Owner убирает member'а (7)
- Active sessions: immediate logout (security paramount).
- Assignments cascade: escalate up к Sales Manager/Admin owning Organisation + audit + email notification (см. секция 4.4).
- Audit log retention: per ADR 0004 v2 (12mo active + 7yr Cyprus archive + pseudonymisation post-12mo + insert-only DB role + monthly hash-chain seal).
- Re-invite после удаления: new invitation flow (single-use token, full personal-invite process). «Restore deleted user» button → Stage 2. При re-invite того же email → fresh membership; assignments и buyer-records НЕ auto-restore (manual reassignment by Sales Manager / Admin) — защита от accidental restore'ов после подозрительных деактиваций.
- Buyer-records деактивированного Sales Agent'а: остаются в DB, attribution к SA preserved (commission через handoff к другому SA per CONV-22 attribution rules). Link не воидится — удаление только через GDPR erasure (см. §7.2).
- Login attempt после deactivation: деактивированный = анонимный посетитель. Логин fail'ится generic'ом («не получилось войти», без причины — security: не leak'аем «kicked by colleague»). Прямые ссылки на проекты работают по правилам Public Visibility per §5 (Private = 404, Discovery = limited, Full sales = full, PIN-protected = PIN gate). Никаких спецбаннеров про suspension.
- Self-leave (user-initiated): Settings → Leave Organisation — confirmation modal с consequences (lose access to N projects, M assigned units cascade up to SM/Admin per §4.4). Same downstream flow что Owner-removes — разница только в trigger / actor в audit log. Owner self-leave disabled — single Owner per Organisation, требуется ownership transfer first per §3.
GDPR / ADGM right-to-erasure (Buyer data) (4)
- Что удаляется immediately: PII (email, name) anonymized to placeholder; magic link tokens revoked + deleted; buyer-record sets to anonymized stub.
- Что retain'им (legal basis): reservation history (если deal completed — anti-fraud + tax requirement); audit log entries (pseudonymised actor_user_id post-12mo, kept до 7yr Cyprus statutory limitation по ADR 0004 v2); aggregate analytics без PII.
- Erasure flow: email request → operator manual processing Stage 1. Self-service «Privacy → Delete my data» button → Stage 2.
- SLA: 30 дней (GDPR + ADGM требование совпадают). Privacy schema jurisdiction-agnostic — работает в Cyprus / ADGM / UAE Federal / DIFC, никаких переписываний при смене jurisdiction'а.
Multi-jurisdiction compliance (KYC, AML, hosting) (3)
- KYC: платформа НЕ собирает KYC сама Stage 1. Даём export каждого buyer-record'а через admin (CSV/JSON) — Sales Agent передаёт свой KYC процессор.
- Hosting region: EU-DC Stage 1 (AWS Frankfurt / Cloudflare EU). GDPR-clean даже если ADGM entity. Re-evaluate если confirmed pivot to ADGM (см. Open Questions ниже).
- Privacy / Terms: generic templates (Iubenda / Termly) Stage 1, custom legal review Stage 2 после первой compliance-проверки.
Conflict resolution edge cases (7)
- Two Organisations претендуют на один unit: не должно быть в S·1 (assignment exclusive). Admin-error bug → manual reconciliation через operator dashboard (Phase 1.4).
- Buyer в двух Sales Agent'ах одновременно: OK by design — разные buyer-records под одним email, разная attribution. Кто из Sales Agent'ов закроет deal — тот получит attribution.
- Deactivated Sales Agent с assigned units: cascade per секция 4.4 — escalate up к Sales Manager/Admin, manual redistribute.
- Owner lockout (forgot 2FA): manual operator reset Stage 1 — recovery flow: email + identity verification → operator manually resets MFA. Automated recovery → Stage 2.
- Race condition при Mark as Reserved (Open pool): два Sales Agent'а одновременно жмут «Mark as Reserved» на тот же unit (Open pool — оба видят и могут). First-click-wins: победитель — первый запрос дошедший до server. Loser получает modal «Только что зарезервировал Алексей в 14:23 — обнови страницу». Audit log записывает обе попытки + winner. Появилось после CONV-26 §6.1 verification form — раньше status-change формы не было.
- Suspension Organisation с активными buyer-tokens: Organisation заморожена (неуплата / chargeback) — tokens продолжают работать read-only до 90d expiry. CTA «Связаться со мной» disabled с tooltip «Project temporarily unavailable, contact your Sales Agent directly». Полный block ударил бы по buyer experience и сорвал active deal flow.
- Visibility setting flip с активными tokens: Owner меняет Public Visibility (Discovery → Private или PIN-protected → Full sales) пока есть active buyer-tokens. Tokens = pre-auth'ed visitor, bypass'ят Visibility setting (consistent с §5.1 PIN bypass + §6 token mechanics). Новый Visibility применяется только к новым anonymous посетителям; existing token holders работают до 90d expiry по своему правилу.
Referral architecture (data model only Stage 1) (7)
- Sponsor scope: any user (Free Guest и paying Client равно могут рефить). Free Guest credit активируется только если Organisation sponsor'а upgrade'нется на платный tier.
- Attribution: URL param (
?ref=ABC123) primary + signup form input backup. No cookie tracking (избегаем consent banner / EU compliance overhead).
- Schema:
referral_codes (user_id, code) + referrals (sponsor, referee, attribution_method, signup_at, upgraded_to_client_at, payout_status, payout_amount). Stage 1 = storage + dashboard stats only; payouts → Phase 4.2.
- Levels: flat — single level only (no MLM-style chains). Schema extensible для multi-level если потом решим (миграция, не rebuild).
- Multi-Organisation referee: Client создал несколько Organisations через одну signup-сессию (с
?ref=). Только первая Organisation с заполненным referred_by_user_id триггерит payout. Schema: Organisation.referred_by_user_id (nullable, set один раз при create). Защита от gaming: создал 5 Org'ов → payout × 1, не × 5.
- Cycle prevention: self-ref (
sponsor_id == new_organisation.owner_id) или reverse-ref (sponsor_id ранее уже был referee этого owner'а) → запись в referrals создаётся с payout_status: ineligible_cycle. Audit запись остаётся для visibility / detection — не блокируем insert hard.
- Sponsor visibility: отдельный экран Settings → Referrals в Client'овой админке.
Top block: свой ref-код + готовая URL https://app.offplan.online/?ref=<code> + кнопка «Скопировать ссылку». Агрегированные метрики «приглашено: N · апгрейднулись: M · в платном статусе: K».
Таблица referees (sort: signup_at desc):
| Колонка | Что показано |
| Organisation | Anonymized Org #abc12 (5-char hash от Organisation id) |
| Зарегистрирован | дата signup |
| Текущий статус | Free Guest / Trial / Paid Tier 1 / Paid Tier 2 |
| Апгрейд | дата первого upgrade на paid tier (или «—») |
| Payout | pending / paid / ineligible_cycle / refunded |
НЕ показываем (privacy): email / имя Owner'а referee, имя Organisation / subdomain, проекты / юниты / metrics, activity log.
Stage 1 не в scope: генератор invite-ссылок (sponsor копирует URL вручную из top block); ручной revocation / edit
payout_status; pagination (Stage 2 если >50 referrals). Payout-логика →
§3 Billing + Phase 4.2.
🔴 Priority #1.
Брендбук + визуальный язык — фундамент всей последующей работы. Без этого админка выглядит cheap для первых студий, и каждое последующее визуальное изменение придётся переделывать.
Фаза 1.1Admin Visual Redesign + Branding [OPL] [BL]
Выровнять визуальный язык и information architecture админки — добавить informational блоки, progress indicator для онбординга, применить премиальную палитру. Brandbook v1.1 создан (draft, на review — не утверждён). Этой фазой применяем токены брендбука к admin: цветовая палитра, typography, button styles, component direction внедряются в код параллельно с финализацией брендбука. Детальная визуальная концепция: Visual Appendix.
💡 Suggestion: before dev implements the redesign, build a complete HTML/CSS mockup together (product owner approves it), then hand off to the tech team to wire up — faster implementation, fewer visual revisions.
1.1.1Informational blocks (contextual help)
КритичноDesign+Tech⏱
Добавить контекстные info-блоки «Heads up» на каждой секции admin — объясняют что сделать, в каком порядке, какие форматы/размеры принимаются, где типичные ошибки. Снимает большую часть onboarding friction: студия понимает что делать без обращения в поддержку. См. визуальный пример в Visual Appendix (Wizard body section).
Что конкретно нужно сделать (6)
- Info-блоки на каждой ключевой секции admin (Buildings, Levels, Floor Plates, Floor Plans, Units, Panoramas, Hotspots, Branding)
- Content: порядок действий, формат файлов, размеры, ссылки на KB
- Стиль callout — sand palette с золотой левой полосой (по Brandbook v1.1, draft)
- Dismissable: можно свернуть per user / per project для power-users
- Контент-writer готовит тексты (~2-3 предложения на секцию + ссылка на детальный guide)
- Testing: первые пилот-студии не должны спрашивать «а куда идти дальше»
Открытые вопросы (2)
- Кто пишет содержание info-блоков (Content team / product team)?
- Динамический контент (reacts to empty state) или статика?
Зависит от: 1.6.2 · Блокирует: —
1.1.2Progress indicator in sidebar (numbered wizard)
КритичноDesign+Tech⏱
Встроить numbered wizard 1→10 прямо в sidebar — студия всегда видит «где я сейчас» и «что дальше» по шагам настройки проекта. Решает главный UX gap из аудита — отсутствие порядка действий. См. Visual Appendix — Numbered Wizard.
Что конкретно нужно сделать (7)
- 10 шагов в sidebar: Theme → Features → Labels & Terms → Buildings → Levels → Floor Plates → Floor Plans → Units → Panoramas → Hotspots
- Состояния каждого шага: done (галочка, green), active (голд outline + fill), upcoming (серый number)
- Хранение progress per project (не per user) — переключение проектов показывает правильный статус
- Клик на любой шаг → навигация к соответствующей секции admin
- Визуальная палитра: sand/gold/navy (консистентно с Brandbook v1.1, draft)
- Автоматическая детекция «шаг выполнен» (есть хотя бы 1 entity в секции) или manual mark?
- Collapsible sidebar (mobile + power-users могут скрыть wizard)
Открытые вопросы (3)
- Auto-detect completion или manual mark done?
- Поведение если студия прыгает между шагами вне порядка (например, создаёт Units до Floor Plans)?
- Показывать ли wizard после завершения всех 10 шагов, или скрыть?
Зависит от: 1.2.4 (onboarding wizard) · Блокирует: —
1.1.3Visual language refresh (palette + typography)[OPL]
ВысокийDesign⏱
Минимальный refresh визуального языка до pilot — убрать «cheap-looking» traffic-light dots и заменить на sand/gold status tags как в v4 mockup. Это не полный редизайн (тот в Фазе 4.3), а pre-pilot upgrade чтобы admin выглядел premium для первых студий. Палитра, типографика и токены — в Brandbook v1.1.
Что конкретно нужно сделать (6)
- Status indicators: available / reserved / sold — переход с яркой светофорной точки на мягкий tag (sand background + subtle color bar)
- Acсент-цвета: gold вместо неоновых green/red в primary actions
- Typography audit: font-size consistency, letter-spacing, heading hierarchy
- Spacing / padding consistency по всем секциям
- Component library: унифицировать кнопки, карточки, input'ы
- Icons: пройтись по текущим иконкам, заменить cheap / inconsistent на единый набор (Phosphor / Lucide / Heroicons)
Открытые вопросы (2)
- Дизайнер для refresh — внутренний или подрядчик?
- Iconset: какой выбираем (Phosphor / Lucide / Heroicons / custom)?
Зависит от: — · Блокирует: —
1.1.4i18n foundation — externalise strings, RTL-ready CSS[BL]
ВысокийTech team
offplan.online targets EN at launch, AR (UAE) in Stage 2, and broader EU/APAC languages in Stage 3. To avoid retrofitting later (touching ~500+ files when AR is added), the codebase must be i18n-shaped from day one — even shipping English-only at launch. This is a foundational discipline, not a feature: every UI string externalised, every CSS file using logical properties, every date/number/currency formatted via Intl. Design rules in Brandbook v1.3 § Internationalisation.
Что конкретно нужно сделать (6)
- Install i18next (React) — все UI-строки живут в
src/i18n/en.json, никогда хардкодятся в компонентах. Даже "Sign up" — это translatable key.
- Locale switcher infrastructure существует с первого дня — на запуске возвращает только
"en", но плумбинг готов. Добавление AR в Stage 2 — это новый JSON-файл, не правки кода.
- CSS использует logical properties (
padding-inline-start, margin-block-end) везде — никаких -left / -right. RTL-layout для AR будет zero extra CSS.
Intl.NumberFormat и Intl.DateTimeFormat обёрнуты в shared helpers — никаких хардкоднутых разделителей тысяч, форматов дат, символов валют.
- IBM Plex Arabic загружается в
<head> лениво — активируется при переключении локали на AR. Fallback: Noto Naskh Arabic → system Arabic.
<html dir="..."> устанавливается программно по выбранной локали (LTR для EN/EU, RTL для AR).
Зависит от: Brandbook v1.3 § Internationalisation (ratified) · Блокирует: 1.2 (Onboarding — первая фаза с UI-формами; должна стартовать на готовом i18n-фундаменте)
Фаза 1.2Self-Serve Onboarding + Quick Build [OPL]
Путь от регистрации до первого опубликованного проекта без обращения в support. Это то, что превращает продукт из «нужно звонить» в SaaS.
✅ Sub-plan ratified CONV-35 (2026-05-11) — plans/onboarding-trial-mode.md
Phase 1.2 sub-plan ratified after 5 steps: Step 1 interview (CONV-34, 14 picks) · Step 2 Research (Perplexity Sonar Deep Research → docs/research/stripe-billing-onboarding-stage1-2026-05-11.md) · Step 3 Approaches (single approach + 3 ratifications: ADR 0017 Stripe Stage 1 formal, Trial daily abuse caps DROPPED, Cyprus e-invoicing DROPPED on Abu Dhabi jurisdiction shift) · Step 4 Plan body (~1750 lines + 13 Implementation Steps incl. NEW Step 13 Operator playbook) · Step 4.4 Business review (5 concern agents → 76 findings → 16 Category A applied + 13 Category B ratified → docs/research/business-review-sub-plan-2-2026-05-11.md) · Step 5 Workstream workstreams/onboarding-trial-implementation.md.
Key ratifications: Trial = Full Pro 14d (B4 — Stripe Price tier_2_monthly; ADR 0008 amended) · 3 seats Trial (B1) · Free Guest × host-project Model B Edit-content-no-publish (B2) · Optional invoice reference field (B3) · Current advertised price + transparent reactivation modal (B5) · 3 success-moment upsell modals Stage 1 (B6) · Enterprise mailto Stage 1 / Cal.com Stage 1.5 if ≥3 inquiries (B7) · Checkout redirect для Free Guest → first paid (B8) · 4-email Trial cadence (T-7/T-3/T-1/T+0) · 14 webhook events (expanded from 8) · Stripe Customer creation DEFERRED to trial-init (F2) · `subscriptions.update` для existing-Customer upgrade (Finance H1 fix) · `create_preview` for tier preview (Finance H2 fix, ADR 0013 v1.1) · 7-stage deletion_journal atomic cascade (Security H1) · Custom domain DNS verification (Security H2) · Token URL §1.7.J header hardening (Security H3) · Host allowlist + `requireMembership` + CSP/HSTS/`__Host-` cookies baseline (Security M1/M6).
ADR cross-refs: ADR 0008 amended (Trial T2 default note + config-driven pricing) · ADR 0009 (Tenancy) · ADR 0013 v1.1 (endpoint rename) · ADR 0017 NEW (Stripe Stage 1 formal ratification) · ADR 0005 v3 (Microsoft + Custom SSO scope Tier 3 Stage 2).
Pre-launch blockers: ADR 0011 ratified CONV-36 ✅ (Resend + 2 own domains audience split — offplan.online customer-facing / offplanonline.com buyer-facing reserved; verify-both-now phasing; task card T1-T7 в ADR body) · ADR 0014 (MCP wrapper auth) — separate /plan session before Phase 1.5.6 AI Floor Plan tags · Legal entity lock (Abu Dhabi likely candidate per CONV-35) → triggers UAE-specific tax research · Roman pricing strategy → pricing-config.ts numbers · Designer email copy (7 React Email templates) + 8-12 upgrade modal templates + 3 success modals.
📌 v4.5 — CONV-21 (Atelier onboarding model — supersedes parts of v4.3):
- ✅ Object Builder = onboarding. После регистрации Client сразу попадает на Object Builder — никакого отдельного wizard'а. Visual ref:
admin-quick-build-atelier-standalone.html (заменяет admin-quick-build-v2.html как canonical ref для Phase 1.2).
- Split-screen UX: слева — форма (Project Name → Subdomain auto-suggest + availability → Required Uploads 1/3); справа — Live Preview обновляется по мере загрузки (Desktop/Tablet/Mobile переключатель). Три загрузки: i. Exterior, ii. Floor Plans («Drop a folder — AI tags pages»), iii. Gallery.
- [SAVE & CONTINUE] — публикует проект. [SKIP] — переходит в full admin без создания проекта (только для Paid; на Trial недоступен).
- Trial (TRIAL — N days left badge в шапке): 14 дней T1 без привязки карты. Только Object Builder доступен; Full Admin залочен пока нет активной подписки. По истечении: auto-downgrade → Free Guest, projects read-only (см. §3 Trial period).
- Paid subscription: Object Builder + Full Admin. Переключение в обе стороны из Full Admin.
- 1.2.Z update: не «Quick Build only для Free» — а «Object Builder only для Trial (full admin залочен) + Object Builder + Full Admin для Paid».
- ❌ 1.2.4 (wizard) DEPRECATED — Object Builder заменяет 4-шаговый wizard. Studio profile setup (logo, brand color) перенесён в Settings → опциональный.
- ❌ 1.2.5 (demo-project vs empty-state) DEPRECATED — Live Preview в правой панели даёт time-to-first-value без шаблонного demo-проекта.
- v4.8 (CONV-25): PIN-protected preset config — 4 conditional поля в Object Builder (и Project Settings). Когда Owner / Admin выбирает Public Visibility = «PIN-protected» — разворачиваются: PIN (required, free-format string min 4 char), After-PIN view (Discovery | Full sales), Contact email (required, default = Owner email), Contact phone (optional). См. §5.1 для полного UX flow + §5 для preset table.
Sub-plan plans/onboarding-trial-mode.md нужно обновить с учётом Atelier model. Связано с ADR 0008 (Tier model + admin mode coupling, Skeleton — pricing/limits defer to sub-plan). CONV-34 v4.17 cross-link: auth / invitation token entropy spec теперь живёт в plans/permission-and-tenancy-model.md § 1.4.D (≥128-bit CSPRNG + hashed storage + constant-time compare + per-IP rate-limit) — Phase 1.2 onboarding flows используют этот же token primitive.
1.2.2URL architecture — Org subdomain + project path [v4.19 CONV-35]
КритичноTech+Ops⏱
Amended CONV-35 (v4.19 — resolves CONV-33 Phase 1.3 sub-plan §1.7.J × Phase 1.2.2 conflict + Sub-plan 2 Pick #5 ratification). Canonical URL model — Organisation owns subdomain; projects sit на path within Org subdomain. Не per-project subdomain (legacy, replaced).
Canonical URL pattern table
| Surface | URL pattern |
| Public sales-app (default) | {org-slug}.offplan.online/{project-slug}/... |
| Public sales-app (Tier 2+ custom domain) | palmresidences.com/... |
| Admin panel (central) | app.offplan.online |
| Operator dashboard | staff.offplan.online |
| Buyer tokenised unit URL | {org-slug}.offplan.online/{project-slug}/units/{unit-slug}?b={token} |
| Custom domain buyer URL | palmresidences.com/units/{unit-slug}?b={token} |
Что конкретно нужно сделать (11)
- Wildcard DNS
*.offplan.online → origin (Cloudflare per CONV-30 infrastructure)
- Automatic SSL (Let's Encrypt wildcard или per-subdomain via Cloudflare ACME)
- Subdomain resolution middleware:
{slug}.offplan.online → organisation_id lookup (NOT project_id as in legacy v4.18 — Pick #5 amendment)
- Project path resolution:
/{project-slug} на Org subdomain → project_id within Organisation namespace
- Host header canonicalisation (Security M1 fix): allowlist regex
^([a-z0-9-]+\.)?offplan\.online$ + verified custom domains; reject otherwise; NEVER trust X-Forwarded-Host unless from whitelisted proxy
requireMembership(user, resolved_org_id) pattern на every admin route (Security M6 — tenant-boundary enforcement re-check past subdomain middleware)
- Org slug validation: 58+ reserved subdomains list per §2.7 + brand-relevant extensions; length, char rules
[a-z0-9-], global uniqueness across all Organisations
- Project slug validation: per-Org uniqueness (within Organisation namespace); length, char rules; reserved chars only
- Org slug change cooldown: 12 calendar months; 301 redirect old→new for 90d (per Pick #7)
- Project slug change: free (no cooldown), но invalidates active buyer URLs per Phase 1.3 sub-plan §1.7.J rotation rules; pre-change warning modal
- Security baseline headers: CSP (admin + sales-app) · HSTS ·
__Host- cookies on admin · X-Frame-Options: DENY on admin (tenant sales-app frame-ancestors 'none') · X-Content-Type-Options: nosniff universal
Открытые вопросы — ✅ resolved CONV-35 (Pick #6 + #7)
- ✅ Slug change: Org slug — раз в 12mo (cooldown); project slug — свободно с buyer URL invalidation warning per Pick #7
- ✅ Slug uniqueness: Org slug — global (58 reserved); project slug — per-Org namespace per Pick #6
1.2.3Custom domain self-serve (для проектов)[BL]
КритичноTech⏱
Для конкретного проекта студия (или девелопер через студию) хочет свой домен — например palmresidences.com или marina.developer.ae. В админке инструкции что прописать в DNS, verification flow, SSL автоматом. Premium feature (paid tier).
Что конкретно нужно сделать (8)
- Форма «добавить custom domain» — на уровне проекта (не tenant'a студии)
- Показать две записи DNS (CNAME + TXT)
- Автоматическая проверка propagation (5 мин в первый час, потом реже)
- Статусы: pending / verified / SSL provisioning / active
- SSL provisioning (Let's Encrypt — автоматом после верификации)
- Error states: «DNS не пропагировался», «CNAME указывает не туда», «SSL выдача упала»
- Возможность откатиться на default поддомен если проблемы
- Tier-gating: custom domain доступен на Studio+ tier или paid add-on
Открытые вопросы (3)
- Сколько custom domains per project (1 + redirects)?
- Что если домен уже использовался другим проектом?
- Можно ли transfer custom domain между проектами?
Зависит от: 1.2.2 · Блокирует: —
1.2.4Object Builder onboarding screen (Atelier model)
КритичноDesign+Tech⏱
После регистрации Client сразу видит Object Builder — это первый экран, он же онбординг. Split-screen: слева форма (проект + загрузки), справа Live Preview обновляется в реальном времени. Три загрузки + subdomain = готовый опубликованный проект. Visual ref: admin-quick-build-atelier-standalone.html
Что конкретно нужно сделать (8)
- Split-screen layout: левая панель — Object Builder form (~50%); правая панель — Live Preview с переключателем Desktop/Tablet/Mobile
- Project setup: PROJECT NAME (text field) → SUBDOMAIN (auto-генерируется из name, editable, availability check inline: «Available · live in seconds» / «Already taken»)
- Required uploads (прогресс X/3): i. Exterior (hero image); ii. Floor Plans («Drop a folder — AI tags pages»); iii. Gallery («Renders, lifestyle, brochure pages»). Загруженные файлы — checkmark + Replace.
- Live Preview: правая панель рендерит реальный preview проекта по мере загрузки. Разделы с pending-контентом показывают «AWAITING UPLOAD →».
- [SAVE & CONTINUE]: публикует проект на subdomain → переходит в full admin (Paid) или остаётся в Object Builder (Trial, до апгрейда)
- [SKIP]: пропускает Object Builder → переходит в full admin без созданного проекта. Доступен только для Paid. На Trial отсутствует.
- Trial-gate: 14 дней T1 без карты.
TRIAL — N days left badge в шапке. Full admin недоступен / залочен пока нет подписки. Object Builder — единственная рабочая поверхность. По истечении без оплаты — auto-downgrade → Free Guest, projects read-only (детали: §3 Trial period).
- Studio profile setup (logo, brand color) — не блокирует первый проект. Перенесён в full admin → Settings, опциональный.
Открытые вопросы (3)
- AI tags для Floor Plans — на чьей инфраструктуре? (VV backend vs отдельный pipeline) — критично для Phase 1.5
- Что показывать в Live Preview до первого uploaded файла? (placeholder / gradient / пустой каркас с брендом)
- Object Builder доступен для создания второго проекта или только для первого? (новый проект из full admin — отдельный flow?)
Зависит от: 1.3.11, 1.2.2 (subdomain provisioning) · Блокирует: —
1.2.5Demo-проект vs Empty-state — DEPRECATED (CONV-21)
ОтмененоProduct+Design
Отменено. Live Preview в правой панели Object Builder (1.2.4) даёт time-to-first-value без шаблонного demo-проекта — студия видит свой реальный контент уже в процессе загрузки. Mockup-сравнение и demo-проект не нужны.
Superseded by: 1.2.4 (Object Builder — Live Preview правая панель)
1.2.6Email onboarding sequence (отложено в Стадию 3)[BL]
Низкий → отложеноMarketing+Tech
Отложено в Стадию 3. Сергей: «Не нужно об этом париться, пока мы не знаем флоу.» Email sequence строится после того как мы поймём реальный путь пользователя на пилоте. До этого — преждевременная оптимизация.
Что вместо этого в Стадии 1 (3)
- Один welcome email после signup (минимум — verification + ссылка на Object Builder)
- Один email-уведомление о приглашении team member (для 1.2.7)
- Простые transactional emails (billing, password reset) — без onboarding sequence
Перенесено в: Стадия 3 — будет добавлено как новая фаза после анализа пилота
🎯 Порядок приоритетов внутри стадии 1
Фазы упорядочены по приоритету исполнения. Используйте эту таблицу для навигации.
| № | Фаза | Приоритет | Комментарий |
| 1.1 | Admin Visual Redesign + Branding | 🔴 Priority #1 | Брендбук разблокирует всю визуальную работу |
| 1.2 | Self-Serve Onboarding + Quick Build | 🔴 Critical | Trial signup → builder → first project published на per-project domain. Зависит от 1.3 (модель доступа) и 1.7 (billing). |
| 1.3 | Tenancy & Permission Model ⭐ | 🔴 Critical (foundational) | Архитектурная основа: 5 ролей, multi-tenant scoping, Closed pool stock allocation, hybrid login. Cross-cutting в 1.2 / 1.4 / 1.7 / 1.10 / 1.11. |
| 1.4 | Operator Dashboard [OPL] | 🔴 Critical | Расширение существующей Super Admin Panel. Без него нет инструмента управлять студиями с момента первой регистрации. |
| 1.5 | MCP Server Wrapper | 🟡 High | Архитектурная основа self-serve, но не блокирует запуск. Если scope большой → итерация в Стадию 2 |
| 1.6 | Admin UX Critical Blockers | 🟡 Conditional | Большинство багов — dev-env. Требует верификации tech team на проде |
| 1.7 | Платёжная инфраструктура + Sales Page | 🔴 Critical | + flat-fee tier альтернатива subscription |
| 1.8 | Security & Infrastructure Foundation | 🔴 Critical | Foundation для всего остального — изоляция, rate limits, backup, error tracking, transactional email |
| 1.9 | Legal & Compliance | 🔴 Critical | EU + UAE + Australia. База: VV T&Cs (AU) + Stripe/Cloudflare шаблоны (EU) |
| 1.10 | Sales-app UX redesign | 🟠 Critical-conditional | Filter-based selection. MVP (1.10.1) обязателен; остальное по эстимейту tech team |
| 1.11 | Sales Presentation Layer ⭐ | 🔴 Critical | Buyer-facing flow: tokenised unit links, attribution Sales Agent'у, lead capture. Завершает sales loop. Зависит от 1.3 + 1.10. |
📚 Foundational decisions · v4.4 · CONV-17 · 2026-05-06 (обновлялось CONV-33 / CONV-34 — см. callouts ниже)
Tenancy, permissions, onboarding & access — read this first
Эта секция — synthesis закрытого /plan permission-and-tenancy-model interview (Blocks A-G). Её решения — cross-cutting: применяются в Фазах 1.2, 1.3, 1.4, 1.7, 1.9, 1.10, 1.11. Прочитайте её до того как уйдёте в детали отдельных фаз — она объясняет «кто есть кто», «как работает подписка», «как раздаются доступы», «что видят разные люди». Каждая Фаза ниже ссылается на конкретные пункты этой секции через CONV-17 callouts.
Foundational · 1 / 7
Кто есть кто (entity glossary)
Платформа разделяет людей (с логином) и сущности (бизнес-структуры). Один человек может управлять несколькими бизнесами и быть приглашённым в чужие — поэтому Client (identity) и Organisation (tenant) — две разные вещи.
Client (человек с логином)
└─→ создаёт / приглашён в → Organisation (tenant — бизнес-сущность)
├─ subdomain ({slug}.offplan.online)
├─ subscription (tier)
├─ team (Clients with roles)
└─ Project (off-plan здание/комплекс)
└─ Unit (квартира)
Сущности
| Сущность | Что это |
| Client | Человек с логином (email + password / Google / Microsoft). Один Client = одна identity (один email). Может быть в нескольких Organisations одновременно с разными ролями. Organisation switcher в шапке переключает контекст. |
| Organisation | Tenant — бизнес-сущность. Создаётся Client'ом при signup (Client становится Owner). Имеет subdomain, subscription, team, projects. Один или несколько types (multi-select): Studio / Agency / Developer — можно совмещать (например, VV = Studio + Agency). |
| Project | Off-plan проект (здание / квартал / комплекс таунхаусов) внутри Organisation. Содержит floorplates, юниты, gallery, settings. URL: {slug}.offplan.online/projects/{project-slug}. |
| Unit | Одна квартира / таунхаус внутри Project. Имеет status (available / reserved / sold), price, attributes, attribution к buyer'у и Sales Agent'у. |
| Buyer | Конечный покупатель квартиры. Не Client — без логина, без своей Organisation. Получает email от Sales Agent'а с tokenised ссылками на отобранные ему юниты. Token expiry — 90 дней; после expiry buyer-record и attribution к Sales Agent'у остаются в DB (если потом купит — комиссия Sales Agent'у). |
Роли — per Organisation per Organisation
Один Client может иметь разные роли в разных Organisations. Role assignment — отдельная запись membership на каждой Organisation.
| Роль | Что может |
| Owner | Client, создавший Organisation (или принявший ownership transfer — см. §3 Ownership transfer). Единственный с billing access — полный контроль (transfer, cancel, tier change). |
| Admin | Всё что Owner, кроме billing/cancel/transfer. Может приглашать/удалять Clients, менять roles, устанавливать external agency relationships. |
| Sales Manager | Operational sales lead = Content Editor + stock allocation + buyer flow. Не управляет командой и billing'ом, но имеет полный operational контроль над контентом, stock allocation, buyer flow. Приглашает Sales Agents. |
| Content Editor | Контент: gallery, renders, floorplates, descriptions, переводы, цены юнитов. Не презентует, не приглашает. Видит всё в проекте (assignment не блокирует content access). |
| Sales Agent | Buyer / presentation flow. Меняет status assigned units через verification form (см. §6.1). Не редактирует контент. Делится на Internal (Client из команды самой Organisation) и External (Client из другой Organisation, приглашён через guest-organisation invite) — operational различия в §4.5. |
| Free Guest | Property of Organisation: бесплатный tier. Organisation на Free Guest tier может быть guest organisation в чужих проектах (приглашена по reverse invite), не может создавать свои проекты. Path к upgrade'у — лениво при попытке «+ Create project». |
Real-world примеры — как одна Organisation может играть разные роли (3)
- Volume Vision (Studio + Agency): в проекте Cote (итальянский девелопер — его Organisation платит за подписку) VV приглашена как guest organisation в роли Studio (рендеры + admin контент). В проекте Marina (другой девелопер — отдельная Organisation) VV приглашена как guest organisation в роли Agency (продаёт квартиры). У VV одна Organisation в системе — в своих проектах она owning Organisation (плательщик), в чужих — guest с нужной ролью.
- Иван (Content Editor + Sales Agent): один Client с email
ivan@gmail.com, два membership'а: Content Editor в Organisation Volume Vision и Sales Agent в Organisation Evgenia Realty (его подработка). Organisation switcher показывает обе организации в шапке.
- Italian developer (Free Guest Organisation): VV сделала ему весь проект как «reverse invite» — Italian developer зарегистрировался Client'ом, создал свою Organisation на Free Guest tier, получил guest access к Cote. Если потом захочет создать свой собственный проект — нажмёт «+ Create project», увидит upgrade modal, выберет tier, заплатит — и Organisation станет full на Tier 1+, его existing guest membership в Cote сохранится.
Что вне Stage 1: secondary emails per Organisation (Stage 2), self-service Client identity merge (Stage 2), self-service Organisation ownership transfer после первого payment (Stage 2/3 — Stage 1 разрешает только до payment, см.
§3 Ownership transfer).
Foundational · ⭐ Сценарии пользователей · читать после §1
Четыре сценария — что делает каждый актёр
Краткий нарратив — путь каждого ключевого актёра от первого касания до завершения работы. Эта секция нужна, чтобы за пять минут понять как платформа работает целиком. Технические детали — в задачах фаз и Foundational-секциях, на которые здесь ссылки. Эта секция — оглавление, не источник истины.
🏢 Owner — от регистрации Client'а до публикации первого проекта
- Регистрируется на
app.offplan.online — email и Google-логин или email с паролем. Форма минимальная: только идентификация.
- Сразу после регистрации попадает в Object Builder. Слева форма, справа живой превью страницы — обновляется по мере загрузки файлов.
- Заполняет: название проекта → поддомен (платформа предлагает вариант, проверяет занятость) → три файла: внешний рендер, поэтажные планы (платформа сама расставит теги), галерея.
- Жмёт Save & Continue — проект опубликован на
{slug}.offplan.online/projects/{project-slug}. Ссылку можно сразу отправлять.
- На триале остаётся в Object Builder до момента подписки. С подпиской открывается полный админ-интерфейс.
- В Settings выбирает Public Visibility (по умолчанию Discovery — анонимный посетитель видит проекты и юниты, но без цен).
- Приглашает команду: сейлз-менеджер, контент-редактор, сейлз-агент. Каждое приглашение — одноразовая ссылка на 7 дней.
- По желанию — подключает свой домен (доступно с Tier 2).
→ Object Builder: 1.2.4 · Регистрация: 1.3.11 · Видимость: §5
📋 Сейлз-менеджер — раздача стока сейлз-агентам
- Логинится — на брендированной странице
{slug}.offplan.online/login или через общий вход app.offplan.online/login.
- Если состоит в нескольких Organisations — переключатель организаций в шапке (как в Slack).
- Открывает проект → раздел Units в админке.
- Выбирает юниты галочками (массово через фильтры), нажимает Assign to и выбирает агентство или конкретного сейлз-агента.
- По умолчанию работает Closed pool: назначенные юниты эксклюзивно у того, кому отдали; неназначенные не видны никому. Можно включить Open pool на проект — тогда гости видят общий «Internal pool» как у брокеров.
- Может пригласить гостевую организацию (девелопера-клиента) — Forward invite, тоже 7 дней.
- Если человека или агентство удаляют из системы — их назначения не сбрасываются в общий пул, а эскалируются вверх (к сейлз-менеджеру или админу).
→ Раздача стока: §4.4 · Назначения: 1.3.4 · Приглашения: 1.3.6
🎯 Сейлз-агент — от приглашения до продажи
- Получает приглашение от сейлз-менеджера на email — одноразовая ссылка, действует 7 дней.
- Принимает приглашение, попадает в организацию в составе своей Organisation.
- Открывает страницу проекта по обычному адресу — например,
tapestry.offplan.online. Видит публичную версию, как любой другой посетитель.
- В правом верхнем углу — иконка логина. Кликает, входит через Google или email/пароль.
- Та же страница перезагружается — теперь со своим набором квартир. Это и есть его «scope».
- По умолчанию видит только те юниты, которые сейлз-менеджер ему лично назначил. Ничего больше.
- Может менять статус своих квартир:
available → reserved → sold. Каждое изменение пишется в audit log.
- На встрече с покупателем создаёт buyer profile (email, имя, телефон). Платформа генерирует ссылку с токеном для покупателя.
- После встречи покупатель получает email с подборкой квартир, которые он лайкнул. Контактом везде указан этот сейлз-агент.
- Когда нужно — выходит из аккаунта, страница возвращается в публичный вид.
→ Иконка логина: 1.10.0 · Сток сейлз-агента: §4.4 · Buyer flow: §6
🛒 Покупатель — от ссылки сейлз-агента до пересылки семье
- Получает email с подборкой квартир от сейлз-агента. В каждой ссылке зашит токен — он привязывает покупателя к этому сейлз-агенту.
- Открывает страницу юнита — видит цены, наличие, контакт сейлз-агента; кнопки «Лайк» и «Связаться со мной» работают.
- Лайкает квартиры, листает альтернативы.
- Жмёт «Связаться со мной» — заявка падает сейлз-агенту в админку, привязанная к этому покупателю.
- Пересылает ссылку жене или другу — токен валиден 90 дней. Привязки к одному устройству нет, пересылка работает.
- После 90 дней токен истекает: покупатель попадает на основную страницу проекта без персонализации, но в базе привязка к сейлз-агенту сохраняется. Если в итоге купит — комиссия всё равно идёт этому сейлз-агенту.
- (Stage 2) Если в будущем добавим логин для покупателей — он сможет вернуться к своим лайкам, сейлз-агент остаётся прежний.
→ Buyer flow: §6 · Состояния посетителя: §5 · Buyer profile: 1.11.1-4
Не описано здесь: оператор платформы (Сергей, Рома, Илья) — у него отдельный staff-дашборд, см. Phase 1.4. Контент-редактор работает почти как сейлз-менеджер, но без раздачи стока. Разница между владельцем и сейлз-менеджером — в §4.2.
Foundational · 2 / 7
Регистрация и онбординг
Три точки входа в систему. Каждая ведёт к разному результату. После регистрации на платный tier (path A) — экран-развилка из 3 опций (см. ниже), не сразу в Object Builder. Аккаунт создаётся один раз (по email) и работает во всех Organisations, к которым Client подключается в будущем.
| Путь | Кто и когда | Куда попадает |
| (A) Регистрация — платный tier | Студия / агентство / девелопер хочет свою организацию для своих проектов. Заходит на offplan.online, нажимает «Get started» → выбирает тариф → попадает в Object Builder. Карта не привязывается на этом шаге — даётся 14-дневный trial T1 (см. §3 Trial period). | Своя организация на {slug}.offplan.online. Роль Owner. Может создавать проекты, приглашать команду и гостевые организации. После trial без оплаты — auto-downgrade → Free Guest, projects read-only. |
| (B) Регистрация гостя (Free) | Кто-то получил обратное приглашение — например, VV сделала проект и приглашает итальянского девелопера. Девелопер регистрируется на бесплатном тарифе по ссылке-приглашению. | Своя организация (бесплатный тариф) с уже подключённым гостевым доступом к нужному проекту. Может смотреть и редактировать контент по правам, но не может создавать свои проекты до перехода на платный тариф. |
| (C) Приглашение в команду | Владелец Organisation приглашает человека в свою команду — например, Ивана как контент-редактора, сейлз-агента или сейлз-менеджера. Иван получает email от {slug}@offplan.online. | Иван присоединяется к организации в указанной роли (на уровне всей компании или конкретного проекта). Если у Ивана уже есть аккаунт на этом email — к нему добавляется участие в новой компании. Если нет — создаётся новый аккаунт. |
Entry-point choice — что Client видит сразу после signup (path A) (3 опции)
После signup'а на платный tier Client попадает не сразу в Object Builder, а на screen с выбором — у разных Client'ов разный intent: одни хотят один проект быстро, другие сначала собирают команду на 50 проектов вперёд. Дефолт-cursor на (1).
- (1) «Start your first project» (primary CTA) — открывает Object Builder (см. Phase 1.2.4). Single-project Client'ы регистрируются именно так. Самый частый путь.
- (2) «Set up your organisation» — мини-визард: types (Studio/Agency/Developer multi-select) + brand (logo + accent color) + invite команды. После — landing на Organisation dashboard, Client сам решит когда создавать первый проект.
- (3) «Skip» — landing на empty dashboard. Всё доступно через меню (invite, create project, settings). Для опытных или «я зашёл посмотреть».
Public Visibility preset спрашивается при создании каждого проекта (внутри Object Builder + дублируется в Project Settings) — 4 варианта (Private / Discovery / Full sales / PIN-protected, см. §5). Дефолт = Discovery.
Login UX — где живёт login form и куда редиректит (3)
- По умолчанию: приглашённый попадает на
{slug}.offplan.online/login — страница входа с брендингом Organisation (логотип, цвета). Альтернатива — общий вход app.offplan.online/login («не помню свой адрес?») — показывает все организации для этого email.
- Вход через поддомен: сразу попадает в организацию. Если состоит в нескольких компаниях — переключатель в шапке (как в Slack).
- Вход через общий адрес: одна компания = автоматический переход. Несколько компаний = страница выбора организации.
Auth methods — Google + email/password (4)
- Google OAuth: кнопка «Войти через Google» — primary, рекомендуемый CTA на login screen.
- Email + пароль: equal-weight fallback («Sign in with email»). Минимум 12 символов (NIST SP 800-63B), проверка по haveibeenpwned при регистрации + смене пароля.
- Сброс пароля: одноразовая magic-link ссылка на email, валидна 60 минут, single-use, invalidates все active sessions.
- Сессия: 30 дней с обновлением при активности (один cookie на
*.offplan.online).
Microsoft (Azure AD / Entra ID) + Custom SSO (SAML 2.0 / OIDC) — Stage 2 Tier 3 (Enterprise) gate per ADR 0005 v3. Trigger: первый Tier 3 customer commitment (revenue trigger). Stage 1 ограничен Google + email/password на всех tier'ах.
2FA scheme — opt-in Stage 1, mandatory для Owner+Admin Stage 2 (3)
- Stage 1: 2FA optional для всех Clients с ролями. TOTP (Google Authenticator) или SMS fallback.
- Operator dashboard (
staff.offplan.online): 2FA mandatory всегда (внутренний tooling).
- Stage 2 (после 100 проектов / первой compliance проверки): mandatory 2FA для Owner+Admin (роли с billing access). Content Editor/Sales Agent остаются optional.
Несовпадение email при приглашении: владелец ввёл ivan@gmail.com, а у Ивана аккаунт на ivan.test@gmail.com → Stage 1: ошибка «email приглашения не совпадает, свяжитесь с тем, кто пригласил». Stage 2: самостоятельное объединение аккаунтов.
Foundational · 3 / 7
Подписка — Модель 4 (тарифная система + бесплатные гостевые компании)
Главное решение по оплате: подписка живёт на уровне Organisation. Каждая Organisation на своём tier — один из четырёх: Free Guest + три платных (T1, T2, T3). Tier 2+ может приглашать guest organisations бесплатно (они работают на бесплатном тарифе). Это покрывает обратный сценарий (студия приглашает девелопера в своё пространство) и самостоятельный рост (девелопер пробует как гость → переходит на платный тариф).
Какие модели рассматривались и почему выбрали Модель 4 (4)
- ❌ Модель 1 — каждая организация платит сама. Высокий барьер для входа в реальном рынке офф-план недвижимости. Девелопер обычно сам оплачивает весь набор инструментов для продаж и не хочет просить свои guest organisations ещё дополнительно подписываться.
- ❌ Модель 2 — подписка платящего покрывает всю экосистему бесплатно. Низкий доход на пользователя, риск злоупотребления (один платящий приводит 100 бесплатных).
- ❌ Модель 3 — оплата за каждое место (как в Figma). Сложный биллинг, трение при каждом добавлении пользователя. Команды в офф-план продажах часто меняются (фрилансеры на проект) — постоянные изменения подписки.
- ✅ Модель 4 — каждая организация на своём тарифе, гостевые компании бесплатно. Покрывает обратный сценарий (агентство хочет видеть проекты нескольких девелоперов) + самостоятельный переход (гость пробует → переходит на платный тариф). Одна платная подписка от одной организации.
| Тариф | Что доступно (ориентировочно) | Цена |
| Free Guest | Может быть гостевой компанией в чужих проектах (по обратному приглашению). Может приглашать пользователей в свою организацию (но они тоже видят только гостевой контент). Не может создавать собственные проекты. Не может приглашать гостевые компании. | $0 |
| Tier 1 | Свои проекты с базовым лимитом. Все 5 ролей. Настройки видимости. Поддомен по умолчанию {slug}.offplan.online. Может приглашать гостевые компании. | TBD → ADR 0008 |
| Tier 2 | Всё из Tier 1 + собственный домен (настройка через CNAME) + DKIM на свой домен + повышенные лимиты на проекты / команду / гостевые компании. | TBD → ADR 0008 |
| Tier 3 (Enterprise) | Всё из Tier 2 + единый вход для всей студии (Google Organisation / Microsoft / Custom SSO — SAML/OIDC), SLA, индивидуальные лимиты, дополнительные модули по запросу. | По договорённости |
⚠️ Это ориентировочный вид, не финальные тарифы. Конкретные цены, лимиты (X проектов, Y участников команды) и возможное переименование линейки (T1/T2/T3 vs Starter/Studio/Enterprise) — фиксируются в ADR 0008 (Tier model, Skeleton) + sub-plan plans/onboarding-trial-mode.md. В рамках этого плана зафиксирована только структура: 4 tier'а с описанным выше назначением.
Trial period — первые 14 дней для Path A signup (7)
- Триггер: Client регистрируется через
offplan.online, выбирает tier на pricing page → попадает в Object Builder с 14-дневным бесплатным доступом к T1 функционалу. Карта не привязывается на этом шаге.
- Не применяется: Path B (guest invite — сразу Free Guest, без trial) и Path C (team invite — роль в чужой Organisation, без своей подписки).
- Что доступно во время trial: полный T1 функционал — создание projects, invite guest organisations, default subdomain
{slug}.offplan.online, все 5 ролей, настройки видимости.
- Что НЕ доступно: T2/T3 фичи (custom domain, DKIM, SSO) — они нужны для production-deploy студии, повод для upgrade. Trial = T1 only, не выбор.
- UI: в шапке админки — badge
TRIAL — N days left. Только Object Builder доступен; Full Admin залочен пока нет активной подписки (см. Phase 1.2 v4.5).
- Email reminders: день 7, день 12, день 14 — нагретые CTA «выбрать tier и оплатить».
- По истечении без оплаты: auto-downgrade → Free Guest. Все trial-projects остаются в аккаунте, но read-only (нельзя редактировать, нельзя создавать новые). Публичный сайт проекта работает 30 дней, потом freeze («временно недоступно, свяжитесь с
{operator-email}»). Оплатил в любой момент — полный доступ возвращается мгновенно (включая re-edit existing projects).
Abuse mitigation Stage 1: email verification (already required) + rate-limit per IP. Если pattern злоупотребления появится — расширим в ADR 0008 / sub-plan.
Ownership transfer — до first payment self-serve, после — через support (5)
Use case (главный sales motion): студия создаёт Organisation на trial, собирает контент проекта, передаёт ownership девелоперу. Девелопер регистрируется / принимает invite → ownership flips → девелопер делает first payment со своей карты → его billing с этого момента.
- Когда self-serve доступен: на Organisation, где не было ни одного payment (trial period или Free Guest state). Owner может trigger'ить transfer самостоятельно.
- Flow (4 шага):
- Owner идёт в
Settings → Transfer Ownership. Вводит email получателя.
- System отправляет email-инвайт с одноразовым токеном (7d expiry).
- Получатель открывает email, регистрируется (если ещё нет аккаунта на этот email) или logs in, видит acceptance screen с описанием Organisation: slug, projects count, current tier (Trial / Free Guest).
- На acceptance: получатель выбирает что произойдёт со старым Owner — стать Admin или быть удалённым из команды. Confirm → ownership flips, audit log entry «Ownership transferred from X to Y».
- После first payment: UI кнопки скрыт. Settings page показывает: «Ownership transfer для Organisations с активной подпиской — через
support@offplan.online. Self-serve версия — Stage 2/3 backlog.»
- Edge cases: если получатель отказывается / token expires — invite cancelled, ownership остаётся у текущего Owner. Если получатель уже Owner другой Organisation — ничего не ломается, у Client'а становится N memberships.
- Cross-link: §1 Owner role · ADR 0009 (Tenancy) — transfer mechanic учитывается в RBAC дизайне.
Что происходит при просрочке / отмене подписки (после first payment) (5)
- Льготный период: 14 дней между просрочкой оплаты и блокировкой. Применяется только к Organisations с активной подпиской — для trial expiry см. §3 Trial period.
- Частичная блокировка: вход в аккаунт работает, проекты видны, но редактирование / приглашения / публикация отключены. Публичный сайт проекта работает ещё 30 дней после блокировки. После 30 дней — сайт заморожен («временно недоступен, свяжитесь с
{operator-email}»).
- Статусы юнитов не меняются: юниты в статусе
reserved или sold остаются как есть, мы ничего не сбрасываем автоматически. Organisation после восстановления продолжает работать с тем что было.
- Ссылки для покупателей: работают 30 дней после блокировки. Потом страницы юнитов показывают «временно недоступно» с контактом оператора.
- Восстановление: оплатил → полный доступ сразу + запись в audit log «reactivated» + уведомления всем участникам команды и гостевым компаниям.
Как гость / trial переходит на платный тариф (4)
- Path A (trial → paid): в badge «TRIAL — N days left» — клик → pricing modal → выбор tier (по умолчанию выбран тот что был при signup) → Stripe → first payment записан → trial badge исчезает, Full Admin открывается.
- Path B (Free Guest → paid): гость в своей организации видит «Ваши проекты (0)» + кнопку «+ Создать первый проект».
- Нажатие → всплывающее окно: «Для создания проектов нужна подписка. Выберите тариф:» → оплата через Stripe.
- После оплаты (любой path): подписка активируется. Все существующие гостевые участия сохраняются. Trial-projects (если были) переходят из read-only в editable. Ownership transfer self-serve UI скрывается (см. §3 Ownership transfer).
Foundational · 4 / 7
Раздача доступов — invitations + permissions + stock allocation
Самая сложная часть архитектуры — 3 ортогональные системы которые работают вместе: (1) invitations определяют кто попал в систему; (2) permissions matrix определяет что роль может делать; (3) stock allocation определяет кто видит/может продать конкретный unit.
4.1 — Invitations: 4 типа
| Тип | Когда используется | Token |
| Personal invite | Внутри своей Organisation — Иван как Content Editor / Sales Agent в команду. Org-level (все проекты) или project-level (один проект). | Single-use, 7 days expiry |
| Organisation invite (forward) | Developer создал project, приглашает Studio / Agency как guest organisation. Permissions per project + scope. | Multi-use, 7 days expiry |
| Reverse invite | Studio (e.g., VV) сделала project, приглашает Developer'а как guest organisation (сценарий VV → Italian developer). Если у developer'а нет аккаунта — Free Guest tier signup path. | Multi-use, 7 days expiry |
| Buyer email link | Sales Agent отправляет presentation email со shortlist'ом. Не invitation в строгом смысле — buyer не joining organisation, просто получает tokenised URLs. | Per-unit token в URL, 90 days expiry |
Token format: opaque random string + DB row (invitations table: token, type, client_id, invitee_email, role, scope, status, expires_at). Server-side lookup на каждый клик. Простой revoke (status='revoked'), full audit trail.
4.2 — Permissions matrix (5 ролей)
Иерархия: Owner ⊃ Admin ⊃ {Sales Manager, Content Editor, Sales Agent} — Sales Manager / Content Editor / Sales Agent параллельны. Один Client = одна role per Organisation (если нужно и контент и продажи → Admin).
Sales Agent column применяется к обоим Internal и External SA — базовые permissions идентичны (operational различия — в §4.5 ниже).
| Действие | Owner | Admin | Sales Manager | Content Editor | Sales Agent |
| Billing / cancel / transfer | ✅ | — | — | — | — |
| Add/remove team members | ✅ | ✅ | — | — | — |
| Invite/remove internal Sales Agents (own team) | ✅ | ✅ | ✅ | — | — |
| Invite/remove External Sales Agents (via guest organisation) | ✅ | ✅ | — | — | — |
| Invite guest organisations | ✅ | ✅ | — | — | — |
| Edit content (gallery, renders, floorplates, descriptions, переводы) | ✅ | ✅ | ✅ | ✅ | — |
| Edit unit pricing | ✅ | ✅ | ✅ | ✅ | — |
| Manage stock allocation (assign / unassign units) | ✅ | ✅ | ✅ | — | — |
| Create / edit buyer profiles | ✅ | ✅ | ✅ | — | ✅ (own) |
| Send presentation emails to buyers | ✅ | ✅ | ✅ | — | ✅ (own) |
| Change unit status (available → reserved → sold) | ✅ | ✅ | ✅ | — | ✅ (own assigned) |
| Public Visibility settings (Private / Discovery / Full sales / PIN-protected) | ✅ | ✅ | — | — | — |
| Branding / theme customisation (project-level) | ✅ | ✅ | — | ✅ | — |
| Branding / theme customisation (Organisation-level) | ✅ | ✅ | — | — | — |
Reverse-flip note (CONV-26): reverse направление status change (Sold → Reserved/Available, Reserved → Available) — same permissions как forward (Owner / Admin / SM / SA own assigned). Каждый reverse-flip → audit log + email notification к одному уровню выше (SA → SM, SM → Admin/Owner). Forward-flip — audit only, без notification (standard workflow). См. §6.1 — reverse direction policy.
4.3 — Scoping: в каких проектах у user'а есть membership
«Scope» здесь = в каких проектах Organisation'ы у Client'а есть доступ. Что user видит и может внутри конкретного проекта — отдельная ось (роль §4.2 + stock allocation §4.4).
- Personal invite — org-level по умолчанию. Иван как Sales Agent в Volume Vision видит все проекты VV. Одна membership покрывает всю Organisation.
- Personal invite — project-level через toggle. Для случая фрилансера на один проект: Иван как Content Editor только в Cote, остальные проекты VV ему не видны. Переключатель в invite form.
- Organisation invite (guest org) — всегда project-level. VV приглашена как guest в Cote (проект Developer'а X) — все VV-members наследуют доступ только к Cote, не к остальным проектам Developer'а X.
- Owner / Admin / Sales Manager своей Organisation — bypass scope. Всегда видят все проекты в своей Organisation независимо от per-project assignments (это team-management роли). Content Editor / Sales Agent / guest org members — подчиняются scope.
4.4 — Stock allocation S·1 (Closed pool default + per-project Open mode toggle)
Решение Романа на anti-double-sale: каждый unit имеет один правовой owner на момент reserve. Default mode — Closed pool (secure by default): guest organisations не видят юниты пока им явно не assign'нули. Это ответ на real-world паттерн «Organisation пригласила external сейлз-агента → не хочет чтобы он сразу увидел pricing на 100 квартир».
Stock allocation mode — per-project setting в Project Settings, рядом с Public Visibility (см. §5). Дефолт = Closed pool. Open pool = opt-in для проектов с «open competition» моделью (multiple agencies на одной inventory).
🔒 Closed pool mode (default)
| Состояние unit'а | Кто видит | Кто может продать |
| Internal pool (default, не присвоено) | Owner / Admin / Sales Manager / Content Editor / любой internal Sales Agent. Guest org-members — НЕТ. | Owner / Admin / Sales Manager / любой internal Sales Agent |
| Assigned to guest org (e.g., Agency A) | Только members этой guest org + Owner/Admin/Sales Manager owning Organisation + Content Editor (всегда) | Только members этой guest org |
| Assigned to user (e.g., Иван) | Только Иван + Owner/Admin/Sales Manager owning Organisation + Content Editor (всегда) | Только Иван |
🔓 Open pool mode (per-project opt-in)
Единственное отличие от Closed mode: «Internal pool» юниты видят и могут продать ВСЕ Sales Agent'ы с project access, включая members guest organisations. Assigned-to-user и Assigned-to-org остаются exclusive как в Closed mode.
Use case: multiple agencies competing на full inventory (broker-style). Bulk «assign all to Agency X» не нужен — все видят всё по дефолту.
Bulk operations Stage 1: filter list view + multi-select checkboxes + dropdown «Assign to» (grouped: organisations / users). CSV import → Phase 1.5.6 (AI file upload endpoint, MCP wrapper). Range-select на floorplate → Stage 2. Critical UX в Closed mode — Sales Manager часто будет делать «дать этой agency 30 юнитов одной кнопкой».
Cascade при удалении target'а — escalate up, never auto-revert в Internal pool. User leaves → revert assignments к Sales Manager/Admin Organisation'ы. Guest org removed → revert к Owner-team. Auto-revert в Internal pool rejected — риск нежелательного widening доступа без явного согласия Owner'а.
Что вне Stage 1 — multi-allocation, custom roles, sub-project scoping (5)
- Multi-allocation (один unit нескольким parties одновременно) — Stage 2 if demand. Увеличивает risk double-sale, требует conflict-resolution UI.
- Specific user inside guest org (Маша из E&V персонально, не вся E&V) — Stage 2.
- Personal role group (all Senior Sales Agents) — Stage 2.
- Custom roles (e.g., «Compliance Sales Manager» с custom permissions) — Stage 2.
- Per-action scope (Иван может edit Buildings но не Branding) — Stage 2/3.
4.5 — Internal vs External Sales Agent
Sales Agent — одна role с двумя operational контекстами: Internal (Client из team самой Organisation) и External (Client из guest organisation, приглашённой через guest-org invite). Базовые permissions в §4.2 одинаковы; различия — на orbital осях:
| Ось | Internal SA | External SA |
| Stock pool default (Closed mode, см. §4.4) | Видит Internal pool | Не видит Internal pool — только assigned |
| Cross-team visibility | Видит коллег-Internal SA в своей Organisation | Видит только своих в guest organisation |
| Invitation source | Personal invite (см. §4.1) от Owner / Admin / Sales Manager | Член guest organisation, добавлен через org-invite от Owner / Admin |
| Removal authority | Owner / Admin / Sales Manager (revoke personal invite) | Admin owning Organisation (revoke guest-org membership) или Admin guest organisation удаляет user'а |
| Reports / analytics | Видит aggregate Organisation-level (own performance + team performance, без других guest orgs) | Видит только свои продажи + own guest organisation aggregate |
Cross-link: §1 Sales Agent definition · §4.4 Stock allocation Closed pool table.
4.6 — View-as-Agent (admin debug + training)
Use cases: Sales Manager хочет проверить что Иван видит правильно после assignment'ов; Admin отлаживает permissions setup перед onboarding нового члена команды; обучение нового Sales Manager'а («давайте посмотрим как видит работу новый коллега»).
- Кому доступен: Owner / Admin / Sales Manager. Sales Agent — нет (свой view = normal login, см. viewer state #4 в §5).
- UI: в шапке админки toggle/dropdown «View as…» → выбрать Sales Agent / другого Sales Manager. После выбора admin panel перерисовывается с perspective этого user'а; вверху страницы фиксированный banner: «Viewing as Иван (Sales Agent) · Exit view-as-mode →».
- Read-only mode: в view-as-режиме все действия залочены (Save / Edit / Delete / Send / Assign — disabled с тултипом «Disabled in view-as mode»). Это explicit decision — НЕ impersonation. Для actual impersonation (login as user) — отдельный operator flow в Phase 1.4, deferred to Stage 4.
- Что показывается: stock filtered как для target user, list юнитов с их visibility/availability, buyer profiles target user'а, его сейлз-метрики. Permissions matrix фильтрует UI элементы.
- Audit log: entry «User X viewed as User Y at TIMESTAMP, duration N min». Compliance — important чтобы знать кто и когда смотрел чужие views. Schema-level дизайн — Phase 1.3 implementation level.
- Cross-link: Preview-as-Buyer — отдельная фича в presentation builder (не часть §4) для проверки как выглядит email-презентация для конкретного buyer'а перед отправкой. См. Phase 1.11.
Foundational · 5 / 7
Что кому видно (4 viewer states + Public Visibility)
На любой странице Organisation subdomain'а ({slug}.offplan.online/...) поведение определяется 4-мя viewer states:
| Viewer state | Identification | Что видит |
| 1. Anonymous visitor | Нет login, нет buyer-token в URL. Нашёл ссылку через Google / friend forward / social media. | Зависит от Public Visibility setting Organisation'ы: Private / Discovery (default) / Full sales. |
| 2. Buyer с tokenised ссылкой | URL содержит ?b=<token>. Token валиден (не expired). | Полная unit-page: цены, availability, contact = атрибутированный Sales Agent, кнопки «Heart unit» / «Связаться со мной» работают. |
| 3. Buyer с expired token | Token есть в URL, но прошло >90 дней. | Редирект на main project page с сохранённой attribution. Видит то же что anonymous, но если потом купит — комиссия Sales Agent'у X (atribuция в DB остаётся). |
| 4. Organisation team member (logged in) | Залогинен в Organisation, открыл публичную страницу subdomain'а. | Видит страницу всегда как Full sales preset — независимо от Public Visibility setting. Stock allocation (§4.4) фильтрует какие юниты ему видны (Sales Agent = только assigned; Content Editor/Sales Manager/Admin/Owner = всё). Admin-панель / edit-overlay — отдельная surface, не описывается в этой таблице. |
Substate (PIN-protected projects): visitor в state #1 может иметь valid pin_<project_id> cookie от предыдущего входа — рендер тогда такой же как у соответствующего After-PIN preset (Discovery или Full sales), без blur. См. §5.1.
Login entry surface (state #1 → state #4): на каждой странице sales-app — маленькая иконка в правом верхнем углу. Anonymous viewer (state #1) видит её как «Sign in». Click → modal с Google / email login (re-use auth backend из 1.3.3). После логина та же страница перезагружается в state #4 (Organisation team member). Logout → возврат к anonymous view. Buyer-token URL'ы (state #2/#3) — отдельный механизм, не требуют логина. Реализация: Phase 1.10.0.
Public Visibility settings — 4 preset'а (per-project)
Per-project setting (Object Builder при создании проекта + Project Settings → Public Visibility). Определяет какие поля видит anonymous visitor (state #1 из таблицы выше) на публичной странице конкретного проекта — цены, availability, floorplates, или (для PIN-protected) blurred тизер с PIN-gate. На Buyer-flow (state #2) и team members (state #4) не влияет. Org-default Visibility — deferred to Stage 2 (если многопроектные студии попросят).
Не путать со Stock allocation (§4.4) — это две разные оси:
- Public Visibility = какие поля показываем anonymous'у (цены? availability badges? floorplates?). Применяется ко всем юнитам.
- Stock allocation = какие юниты показываем залогиненным team members и guest orgs внутри admin/sales views. На anonymous не влияет — anonymous видит все юниты per выбранный preset.
| Preset | Что видит anonymous |
| Private | Только hero (logo, branding, tagline) + «Request access» CTA. Никаких проектов, юнитов, рендеров. |
| Discovery (по умолчанию для нового проекта) | Все проекты Organisation'ы видны — hero, рендеры, 360°, floorplates, список юнитов. Цены и индивидуальные статусы юнитов скрыты — отображается только counter «N units available» на проект. CTA «Request access» открывает запрос на доступ к Full sales view. |
| Full sales | Всё что в Discovery + цены per unit + availability badges per unit (available / reserved / sold). Полноценный public sales-сайт — anonymous видит каждый юнит во всех проектах Organisation'ы независимо от stock allocation assignments. |
| PIN-protected | Содержимое проекта показывается с CSS blur (силуэты + цвета без деталей); поверх — PIN entry overlay с «Enter PIN» + «Contact us» CTA. Правильный PIN → 30-day cookie + разблокируется выбранный After-PIN view (Discovery или Full sales — Owner выбирает). Buyer-token (?b=...) bypass'ит PIN. Полный spec — см. §5.1 ниже. |
Granular field-level overrides — deferred to Stage 2 (deferred)
В первой итерации planning'а §5 предполагался «Custom» preset с granular toggle'ами (show prices / availability / floorplates / price range / inquiry / heart actions). На 2026-05-08 (CONV-25) этот preset удалён из Stage 1 — 4 базовых preset'а (Private / Discovery / Full sales / PIN-protected) покрывают MVP-needs студий. Granular per-field overrides вернутся в Stage 2 если многопроектная студия запросит гибрид (например, «Discovery + show prices» — между Discovery и Full sales). Heart / «Связаться» actions для anonymous всегда скрыты (требуют buyer-token).
5.1 — PIN-protected preset (deep spec)
Use case: застройщик / студия хочет показать проект приватно (pre-launch teaser, VIP-listing, ранний preview для investor'ов) — отдаёт URL + PIN устно или в одном email. Anonymous, не зная PIN, видит только blurred тизер; знающие PIN — открывают полную страницу.
Anonymous visitor flow (без правильного cookie)
- URL:
{slug}.offplan.online/projects/{project-slug} — обычный sales-app URL.
- Содержимое проекта рендерится в полном объёме (как After-PIN preset выглядел бы) с CSS
filter: blur(12-16px) на content wrapper — силуэты hero, рендеров, floorplate, units list видны, но не читаемы.
- Поверх blur'а — fixed PIN entry overlay (centered card, brandbook v2 styling) с:
- Заголовок: «Project Name» (project-name виден, чтобы пользователь понял на что зашёл) + строка «Эта страница защищена. Введите PIN для доступа.»
- Input field — PIN (free-format string min 4 char — Owner определяет numeric или alphanumeric при setup'е)
- Кнопка «Open project» (submit)
- Sub-block «Не знаете PIN?» с двумя actions: Email us (
mailto:<contact_email>?subject=Access request: <Project name>) + Call us (tel:<contact_phone> если phone не пустой; иначе кнопка скрыта).
- Submit → server validates PIN → если correct → set cookie
pin_<project_id>=<random_token> на 30 дней, redirect на same URL → теперь user видит After-PIN preset (Discovery или Full sales — what Owner выбрал). Если incorrect → form shows error «Wrong PIN» + tracks attempt в audit log; rate-limit 5 attempts → 30s cooldown.
PIN bypass cases (visitor видит After-PIN preset напрямую)
- Valid 30-day cookie на этом проекте — re-entry не нужен.
- Buyer-token URL (
?b=<token>) — token = pre-auth со стороны Sales Agent'а, который buyer'у эту ссылку прислал. Buyer не должен знать PIN (он его не должен видеть). Token валиден → bypass PIN entirely → render полная unit-page (state #2 в viewer states таблице).
- Logged-in team member owning Organisation — Owner / Admin / Sales Manager / Content Editor / Sales Agent → state #4 в таблице, всегда Full sales (PIN не нужен). Logged-in member guest organisation — same: bypass PIN (он уже authenticated в системе с правом на этот проект).
- Owner изменил PIN → все existing cookies invalidated (security default — изменение PIN это «отозвать access у тех кто PIN знает»). Visitors с invalid cookie возвращаются на blurred PIN entry screen.
PIN config UI (Project Settings → Public Visibility = PIN-protected)
Когда Owner / Admin выбирает «PIN-protected» preset для проекта (в Object Builder при создании ИЛИ в Project Settings потом) — разворачиваются 4 поля:
- PIN (required) — text input, free-format string (min 4 char). Hashed at rest (bcrypt / argon2 — implementation Phase 1.3).
- After PIN: visitor sees (required) — radio / dropdown:
Discovery (по умолчанию) | Full sales. Pre-launch без финальных цен → Discovery. С готовыми ценами → Full sales.
- Contact email (required) — visitor который не знает PIN отправит запрос на доступ. Default = Owner email; editable. Per-project — может быть отдельный «секретарь / менеджер / агент» на каждый проект.
- Contact phone (optional) — phone number в международном формате. Если заполнен — на PIN screen появляется кнопка «Call us» рядом с «Email us».
Permission to set / change PIN: Owner / Admin (matching §4.2 row «Public Visibility settings»). Sales Manager / Content Editor / Sales Agent — нет.
Audit log
- PIN set / changed: «User X set / changed PIN for Project Y at TIMESTAMP» — visible to Owner / Admin (НЕ показывает сам PIN value).
- Failed PIN attempts (>3 в час с одного IP) — flag в operator panel (Phase 1.4) для anti-brute-force monitoring.
- Successful PIN entry — НЕ per-attributed event (anonymous visitor); только aggregate counter «N PIN-passed views в day» для analytics.
Schema-level дизайн audit таблицы — Phase 1.3 implementation level (consistent с pattern §4.6 View-as-Agent audit).
Cross-link: Phase 1.2 Object Builder — surface этих 4 полей в creation flow · Phase 1.10 Sales App — routing logic для blur + PIN entry + cookie + buyer-token bypass · Phase 1.4 Operator Dashboard — operator может видеть «Project X is PIN-protected» (для support troubleshooting) но не PIN value.
Foundational · 6 / 7
Buyer flow — Variant E2 (tokenised unit links, no dedicated dashboard)
Решение архитектуры buyer-presentation'а: email = и есть presentation. Никакой dedicated buyer-dashboard'а / shortlist-страницы в Stage 1. Каждый «лайк» во время презентации становится отдельной tokenised ссылкой в email'е.
Внутри §6: существующие <details> блоки покрывают buyer entity model и token mechanics. Подробные subsections ниже: §6.1 — Sales Agent status-change form (D+E unified mechanism) + §6.2 — Channels (Email + WhatsApp + Copy link).
Email content + token mechanics (5)
- URL pattern:
{slug}.offplan.online/projects/{project-slug}/units/{unit-id}?b=<buyer_token>
- Email body: auto-generated summary («3 units in Cote project, prices €450K-680K, 2BR») + agent free-text editable перед send'ом + N tokenised unit-links.
- Token expiry: 90 дней. После expiry — redirect на main project page с сохранённой attribution. Buyer-record не «умирает».
- Buyer-record creation: при отправке email'а Sales Agent создаёт buyer-record в DB. Token attributes click → Sales Agent X. Один buyer-record per (Sales Agent, presentation).
- Sold/reserved unit при клике: open unit-page нормально, status badge показывает «Sold» / «Reserved». Buyer возвращается к другим ссылкам в email'е или гуляет по сайту с сохранённой attribution. Никаких 404 / hard blocks.
Buyer-actions на unit-page (только с валидным token'ом) (2)
- Heart additional units — buyer может «лайкнуть» quartirы которые Sales Agent не выделил. Sales Agent видит в админке («Buyer X added unit Y»), может позвонить.
- Request callback / Связаться со мной — buyer жмёт CTA на unit-page → notification к Sales Agent'у с unit context'ом. Это lead-trigger, не reservation: buyer ничего не резервирует и не lock'ает. Дальнейший процесс (callback, переговоры, booking deposit) — off-platform / в external CRM Organisation'ы. Status юнита члены Organisation меняют вручную в админке когда сами решат.
Forward email / shared token — feature, не bug (3)
- Один token = один buyer-record, multi-session OK. Если жена / партнёр / друг Buyer'а кликают по той же ссылке — каждый клик идентифицируется как тот же buyer-record. Атрибуция сохраняется.
- Защита cheap: rate-limit на «Связаться со мной» (max 1 active per token, cooldown между submissions). Audit log по token'у с IP + timestamp.
- Никакого device-pinning / cookie-binding — это убило бы legit forwarding (жена с телефона). Stage 2 (если попросят): opt-in checkbox «restrict to first device».
6.1 — Sales Agent status-change form (D + E unified mechanism)
Use case: Sales Agent проводит встречу с buyer'ом, договорился о reservation / sold deal'е, нужно поставить unit в Reserved / Sold + связать buyer'а с unit'ом для attribution / commission. Decision (CONV-22): D (status protection) и E (buyer↔unit linkage) объединены в один mechanism — заполнение status-change form auto-links buyer-record by email lookup (smart-match). Альтернатива (2 separate UI: status form + manual unit-buyer link в карточке) отвергнута как излишняя ручная работа.
Form shape (augmented single-click verification)
- Trigger: Sales Agent в админке Project → unit card → нажимает кнопку «Mark as Reserved» (амбер) или «Mark as Sold» (red). Status выбирается кликом, не dropdown'ом — reduces clicks, кнопки чётко разделены.
- Required field:
buyer email (с autocomplete'ом из buyer-records этого Sales Agent'а — recent first).
- Conditional required: если email НЕ matches existing buyer-record →
buyer name + phone становятся required (создаётся новый record). Если email matches existing record → name + phone displayed read-only (auto-fill из existing).
- Optional:
notes (free text — deal value, conditions, comment) + file upload (PDF / JPG: signed booking letter, deposit receipt, photo подписанного контракта, etc.).
- Submit: server validates → создаёт/links buyer-record → flips unit status → audit log entry → email notification (см. ниже).
Smart-match logic (email lookup, E side)
- Lookup в buyer-records этого Sales Agent'а (org-scope, recent first) — если email match → display banner «Buyer found: Иван Петров, +971 50 123 45 67 — ваш buyer от 12 апреля» + auto-link к существующему record'у.
- Lookup в Organisation-wide buyer-records (если в (1) match не найден) — если match → display warning «Buyer Иван Петров existing, attributed to Алексей Иванов. New buyer-record will be created для вашей attribution. Continue?». Решение per CONV-22: разные buyer-records под одним email = разная attribution; новый record создаётся для текущего SA.
- Если match не найден ни там, ни там → form требует name + phone, создаётся new buyer-record (attribution = текущий SA), unit↔buyer link создаётся.
Triggers + reverse direction policy
- Forward triggers: Available → Reserved · Available → Sold · Reserved → Sold (с pre-fill «same buyer?» — если в Reserved уже есть linked buyer-record, форма pre-fill'ит email).
- Reverse triggers: Sold → Reserved · Sold → Available · Reserved → Available. Симметричная policy — same permissions per §4.2 «Change unit status» row (Owner / Admin / SM / SA own-assigned). Sales Agent fixes own mistakes без эскалации к manager'у. Audit log + email notification catches abuse.
- Email notification на reverse-flip: к Sales Manager'у (если SA откатывает); к Admin / Owner (если SM откатывает). Forward-flip — без notification (standard workflow); reverse — «interesting event» worth surfacing.
- Buyer-record fate при reverse: buyer-record остаётся в DB (history + attribution preserved для commission). Unit↔buyer link воидится (audit log entry: «User X reverted Sold → Reserved at TIMESTAMP, voided link to Buyer Y»). Re-flip forward (Reserved → Sold снова) — SA re-fills форму; если same email — auto-link recreates от existing buyer-record. Никаких stale link'ов в DB.
Audit log
- Forward-flip: «User X marked unit Y as Reserved/Sold; linked to Buyer Z (existing | new) at TIMESTAMP. Notes: «...». File: foo.pdf (если приложен)».
- Reverse-flip: «User X reverted unit Y from Sold → Reserved at TIMESTAMP. Voided link to Buyer Z. Reason: «...» (notes если заполнено)».
- Visible to: Owner / Admin / Sales Manager (full audit trail per Project в Project Settings → Activity log). Sales Agent — own actions only (own assigned units history).
- Schema-level дизайн — Phase 1.3 implementation level (consistent с pattern §4.6 View-as-Agent + §5.1 PIN-protected audit).
Cross-link: Phase 1.10 — verification form UI build + WhatsApp button (см. §6.2) · Phase 1.4 — operator dashboard sees flip audit + reverse-flip emails · §4.2 — permission row для status changes (forward + reverse symmetric).
6.2 — Channels — Email + WhatsApp + Copy link
Use case: Sales Agent после встречи / звонка отправляет buyer'у tokenised presentation link через подходящий канал. UAE / MENA reality — WhatsApp dominant (~80% delivery), Email — деловой / formal, SMS — устаревает. Stage 1 covers 3 channels через light deep-link approach (zero vendor integrations).
3 channels (Stage 1)
| Channel | Mechanic | Tracking |
| Email | Native send из platform'ы через Phase 1.8 infra (SES / Mailgun). Default sender = Organisation's verified email; subject = «Presentation: <Project name>»; body = composed message + tokenised links. Phase 1.8 handles delivery, bounces, opens. | URL: ?ch=email. Opens counted в analytics. |
| WhatsApp | Deep-link to SA's own WhatsApp client: https://wa.me/<phone>?text=<encoded message>. SA жмёт кнопку «Send via WhatsApp» в admin'е → browser открывает web.whatsapp.com (или native app если на mobile) с предзаполненным message; SA жмёт «Send» уже там. Никаких vendor integrations — никакого WhatsApp Business API, никакой compliance approval, никаких monthly fees. | URL: ?ch=wa. Opens counted. |
| Copy link | Кнопка «Copy buyer link» в admin'е → clipboard'у копируется tokenised URL с ?ch=link. SA pastes куда хочет — Telegram / iMessage / LinkedIn DM / SMS / etc. Универсальный fallback. | URL: ?ch=link. Opens counted (без знания target channel). |
UI flow в Sales Agent admin'е
- SA в Project admin'е → buyer-record card (или после Object Builder при создании презентации) → «Send to buyer» button.
- Modal: compose message (default text editable: «Hi <buyer_name>, here's the presentation we discussed: <link>») + selected units (chips, removable) + 3 channel buttons:
- 📧 Send via Email — disabled if buyer email is empty.
- 💬 Send via WhatsApp — disabled if buyer phone is empty (tooltip «Phone required for WhatsApp»).
- 🔗 Copy link — always enabled.
- Click → action: Email отправляется с backend'а; WhatsApp / Copy открывают browser handlers.
- Multi-channel в одну операцию — SA может click Email AND WhatsApp одновременно («не уверен какой канал buyer чаще проверяет»). Same buyer-token URL, разный
?ch= param на каждой версии — multi-channel attribution counter в analytics.
Default message text + locale
- Pre-filled на Org locale (Stage 1 supports English + Russian per ADR 0007 i18n; Arabic Stage 2 если рынок попросит).
- Template (English): «Hi <buyer_name>, here's the presentation we discussed: <link>». Russian: «Привет <buyer_name>, вот презентация о которой мы говорили: <link>».
- SA редактирует inline в admin'е перед клик'ом «Send» — full freedom для personalisation.
- Per-channel templates (different text для Email vs WhatsApp) — Stage 2 если попросят. В Stage 1 — same text для всех channels (SA может вручную подкорректировать перед каждым send'ом).
Cross-link: Phase 1.10 — UI flow build + 3 channel buttons · Phase 1.8 — Email infra (already in plan) · Phase 1.4 — operator dashboard channel analytics aggregate.
Stage 2 channels backlog: SMS via Twilio (carrier compliance, monthly fee), centralised WhatsApp via Business API (от platform'ы send not from SA's phone — pretty UX, audit log, opt-in flows; vendor onboarding required).
Foundational · 7 / 7
Edge cases (suspension / GDPR / conflicts / referrals)
⏸ Parking-lot (CONV-27): §7.2 GDPR / ADGM right-to-erasure + §7.3 Multi-jurisdiction compliance — DEFERRED до (1) lock'а jurisdiction (Cyprus default по memory, под review awaiting Roman ratification); (2) подключения юриста (Cyprus / EU / UAE); (3) активации sub-plan'а plans/legal-multi-party-framework.md. До этого момента не править. Архитектурные edge cases (§7.1 deactivation / §7.4 conflicts / §7.5 referrals) — closed in Chunk 6.
User deactivation — что происходит когда Owner убирает member'а (7)
- Active sessions: immediate logout (security paramount).
- Assignments cascade: escalate up к Sales Manager/Admin owning Organisation + audit + email notification (см. секция 4.4).
- Audit log retention: per ADR 0004 v2 (12mo active + 7yr Cyprus archive + pseudonymisation post-12mo + insert-only DB role + monthly hash-chain seal).
- Re-invite после удаления: new invitation flow (single-use token, full personal-invite process). «Restore deleted user» button → Stage 2. При re-invite того же email → fresh membership; assignments и buyer-records НЕ auto-restore (manual reassignment by Sales Manager / Admin) — защита от accidental restore'ов после подозрительных деактиваций.
- Buyer-records деактивированного Sales Agent'а: остаются в DB, attribution к SA preserved (commission через handoff к другому SA per CONV-22 attribution rules). Link не воидится — удаление только через GDPR erasure (см. §7.2).
- Login attempt после deactivation: деактивированный = анонимный посетитель. Логин fail'ится generic'ом («не получилось войти», без причины — security: не leak'аем «kicked by colleague»). Прямые ссылки на проекты работают по правилам Public Visibility per §5 (Private = 404, Discovery = limited, Full sales = full, PIN-protected = PIN gate). Никаких спецбаннеров про suspension.
- Self-leave (user-initiated): Settings → Leave Organisation — confirmation modal с consequences (lose access to N projects, M assigned units cascade up to SM/Admin per §4.4). Same downstream flow что Owner-removes — разница только в trigger / actor в audit log. Owner self-leave disabled — single Owner per Organisation, требуется ownership transfer first per §3.
GDPR / ADGM right-to-erasure (Buyer data) (4)
- Что удаляется immediately: PII (email, name) anonymized to placeholder; magic link tokens revoked + deleted; buyer-record sets to anonymized stub.
- Что retain'им (legal basis): reservation history (если deal completed — anti-fraud + tax requirement); audit log entries (pseudonymised actor_user_id post-12mo, kept до 7yr Cyprus statutory limitation по ADR 0004 v2); aggregate analytics без PII.
- Erasure flow: email request → operator manual processing Stage 1. Self-service «Privacy → Delete my data» button → Stage 2.
- SLA: 30 дней (GDPR + ADGM требование совпадают). Privacy schema jurisdiction-agnostic — работает в Cyprus / ADGM / UAE Federal / DIFC, никаких переписываний при смене jurisdiction'а.
Multi-jurisdiction compliance (KYC, AML, hosting) (3)
- KYC: платформа НЕ собирает KYC сама Stage 1. Даём export каждого buyer-record'а через admin (CSV/JSON) — Sales Agent передаёт свой KYC процессор.
- Hosting region: EU-DC Stage 1 (AWS Frankfurt / Cloudflare EU). GDPR-clean даже если ADGM entity. Re-evaluate если confirmed pivot to ADGM (см. Open Questions ниже).
- Privacy / Terms: generic templates (Iubenda / Termly) Stage 1, custom legal review Stage 2 после первой compliance-проверки.
Conflict resolution edge cases (7)
- Two Organisations претендуют на один unit: не должно быть в S·1 (assignment exclusive). Admin-error bug → manual reconciliation через operator dashboard (Phase 1.4).
- Buyer в двух Sales Agent'ах одновременно: OK by design — разные buyer-records под одним email, разная attribution. Кто из Sales Agent'ов закроет deal — тот получит attribution.
- Deactivated Sales Agent с assigned units: cascade per секция 4.4 — escalate up к Sales Manager/Admin, manual redistribute.
- Owner lockout (forgot 2FA): manual operator reset Stage 1 — recovery flow: email + identity verification → operator manually resets MFA. Automated recovery → Stage 2.
- Race condition при Mark as Reserved (Open pool): два Sales Agent'а одновременно жмут «Mark as Reserved» на тот же unit (Open pool — оба видят и могут). First-click-wins: победитель — первый запрос дошедший до server. Loser получает modal «Только что зарезервировал Алексей в 14:23 — обнови страницу». Audit log записывает обе попытки + winner. Появилось после CONV-26 §6.1 verification form — раньше status-change формы не было.
- Suspension Organisation с активными buyer-tokens: Organisation заморожена (неуплата / chargeback) — tokens продолжают работать read-only до 90d expiry. CTA «Связаться со мной» disabled с tooltip «Project temporarily unavailable, contact your Sales Agent directly». Полный block ударил бы по buyer experience и сорвал active deal flow.
- Visibility setting flip с активными tokens: Owner меняет Public Visibility (Discovery → Private или PIN-protected → Full sales) пока есть active buyer-tokens. Tokens = pre-auth'ed visitor, bypass'ят Visibility setting (consistent с §5.1 PIN bypass + §6 token mechanics). Новый Visibility применяется только к новым anonymous посетителям; existing token holders работают до 90d expiry по своему правилу.
Referral architecture (data model only Stage 1) (7)
- Sponsor scope: any user (Free Guest и paying Client равно могут рефить). Free Guest credit активируется только если Organisation sponsor'а upgrade'нется на платный tier.
- Attribution: URL param (
?ref=ABC123) primary + signup form input backup. No cookie tracking (избегаем consent banner / EU compliance overhead).
- Schema:
referral_codes (user_id, code) + referrals (sponsor, referee, attribution_method, signup_at, upgraded_to_client_at, payout_status, payout_amount). Stage 1 = storage + dashboard stats only; payouts → Phase 4.2.
- Levels: flat — single level only (no MLM-style chains). Schema extensible для multi-level если потом решим (миграция, не rebuild).
- Multi-Organisation referee: Client создал несколько Organisations через одну signup-сессию (с
?ref=). Только первая Organisation с заполненным referred_by_user_id триггерит payout. Schema: Organisation.referred_by_user_id (nullable, set один раз при create). Защита от gaming: создал 5 Org'ов → payout × 1, не × 5.
- Cycle prevention: self-ref (
sponsor_id == new_organisation.owner_id) или reverse-ref (sponsor_id ранее уже был referee этого owner'а) → запись в referrals создаётся с payout_status: ineligible_cycle. Audit запись остаётся для visibility / detection — не блокируем insert hard.
- Sponsor visibility: отдельный экран Settings → Referrals в Client'овой админке.
Top block: свой ref-код + готовая URL https://app.offplan.online/?ref=<code> + кнопка «Скопировать ссылку». Агрегированные метрики «приглашено: N · апгрейднулись: M · в платном статусе: K».
Таблица referees (sort: signup_at desc):
| Колонка | Что показано |
| Organisation | Anonymized Org #abc12 (5-char hash от Organisation id) |
| Зарегистрирован | дата signup |
| Текущий статус | Free Guest / Trial / Paid Tier 1 / Paid Tier 2 |
| Апгрейд | дата первого upgrade на paid tier (или «—») |
| Payout | pending / paid / ineligible_cycle / refunded |
НЕ показываем (privacy): email / имя Owner'а referee, имя Organisation / subdomain, проекты / юниты / metrics, activity log.
Stage 1 не в scope: генератор invite-ссылок (sponsor копирует URL вручную из top block); ручной revocation / edit
payout_status; pagination (Stage 2 если >50 referrals). Payout-логика →
§3 Billing + Phase 4.2.
🔴 Priority #1.
Брендбук + визуальный язык — фундамент всей последующей работы. Без этого админка выглядит cheap для первых студий, и каждое последующее визуальное изменение придётся переделывать.
Фаза 1.1Admin Visual Redesign + Branding [OPL] [BL]
Выровнять визуальный язык и information architecture админки — добавить informational блоки, progress indicator для онбординга, применить премиальную палитру. Brandbook v1.1 создан (draft, на review — не утверждён). Этой фазой применяем токены брендбука к admin: цветовая палитра, typography, button styles, component direction внедряются в код параллельно с финализацией брендбука. Детальная визуальная концепция: Visual Appendix.
💡 Suggestion: before dev implements the redesign, build a complete HTML/CSS mockup together (product owner approves it), then hand off to the tech team to wire up — faster implementation, fewer visual revisions.
1.1.1Informational blocks (contextual help)
КритичноDesign+Tech⏱
Добавить контекстные info-блоки «Heads up» на каждой секции admin — объясняют что сделать, в каком порядке, какие форматы/размеры принимаются, где типичные ошибки. Снимает большую часть onboarding friction: студия понимает что делать без обращения в поддержку. См. визуальный пример в Visual Appendix (Wizard body section).
Что конкретно нужно сделать (6)
- Info-блоки на каждой ключевой секции admin (Buildings, Levels, Floor Plates, Floor Plans, Units, Panoramas, Hotspots, Branding)
- Content: порядок действий, формат файлов, размеры, ссылки на KB
- Стиль callout — sand palette с золотой левой полосой (по Brandbook v1.1, draft)
- Dismissable: можно свернуть per user / per project для power-users
- Контент-writer готовит тексты (~2-3 предложения на секцию + ссылка на детальный guide)
- Testing: первые пилот-студии не должны спрашивать «а куда идти дальше»
Открытые вопросы (2)
- Кто пишет содержание info-блоков (Content team / product team)?
- Динамический контент (reacts to empty state) или статика?
Зависит от: 1.6.2 · Блокирует: —
1.1.2Progress indicator in sidebar (numbered wizard)
КритичноDesign+Tech⏱
Встроить numbered wizard 1→10 прямо в sidebar — студия всегда видит «где я сейчас» и «что дальше» по шагам настройки проекта. Решает главный UX gap из аудита — отсутствие порядка действий. См. Visual Appendix — Numbered Wizard.
Что конкретно нужно сделать (7)
- 10 шагов в sidebar: Theme → Features → Labels & Terms → Buildings → Levels → Floor Plates → Floor Plans → Units → Panoramas → Hotspots
- Состояния каждого шага: done (галочка, green), active (голд outline + fill), upcoming (серый number)
- Хранение progress per project (не per user) — переключение проектов показывает правильный статус
- Клик на любой шаг → навигация к соответствующей секции admin
- Визуальная палитра: sand/gold/navy (консистентно с Brandbook v1.1, draft)
- Автоматическая детекция «шаг выполнен» (есть хотя бы 1 entity в секции) или manual mark?
- Collapsible sidebar (mobile + power-users могут скрыть wizard)
Открытые вопросы (3)
- Auto-detect completion или manual mark done?
- Поведение если студия прыгает между шагами вне порядка (например, создаёт Units до Floor Plans)?
- Показывать ли wizard после завершения всех 10 шагов, или скрыть?
Зависит от: 1.2.4 (onboarding wizard) · Блокирует: —
1.1.3Visual language refresh (palette + typography)[OPL]
ВысокийDesign⏱
Минимальный refresh визуального языка до pilot — убрать «cheap-looking» traffic-light dots и заменить на sand/gold status tags как в v4 mockup. Это не полный редизайн (тот в Фазе 4.3), а pre-pilot upgrade чтобы admin выглядел premium для первых студий. Палитра, типографика и токены — в Brandbook v1.1.
Что конкретно нужно сделать (6)
- Status indicators: available / reserved / sold — переход с яркой светофорной точки на мягкий tag (sand background + subtle color bar)
- Acсент-цвета: gold вместо неоновых green/red в primary actions
- Typography audit: font-size consistency, letter-spacing, heading hierarchy
- Spacing / padding consistency по всем секциям
- Component library: унифицировать кнопки, карточки, input'ы
- Icons: пройтись по текущим иконкам, заменить cheap / inconsistent на единый набор (Phosphor / Lucide / Heroicons)
Открытые вопросы (2)
- Дизайнер для refresh — внутренний или подрядчик?
- Iconset: какой выбираем (Phosphor / Lucide / Heroicons / custom)?
Зависит от: — · Блокирует: —
1.1.4i18n foundation — externalise strings, RTL-ready CSS[BL]
ВысокийTech team
offplan.online targets EN at launch, AR (UAE) in Stage 2, and broader EU/APAC languages in Stage 3. To avoid retrofitting later (touching ~500+ files when AR is added), the codebase must be i18n-shaped from day one — even shipping English-only at launch. This is a foundational discipline, not a feature: every UI string externalised, every CSS file using logical properties, every date/number/currency formatted via Intl. Design rules in Brandbook v1.3 § Internationalisation.
Что конкретно нужно сделать (6)
- Install i18next (React) — все UI-строки живут в
src/i18n/en.json, никогда хардкодятся в компонентах. Даже "Sign up" — это translatable key.
- Locale switcher infrastructure существует с первого дня — на запуске возвращает только
"en", но плумбинг готов. Добавление AR в Stage 2 — это новый JSON-файл, не правки кода.
- CSS использует logical properties (
padding-inline-start, margin-block-end) везде — никаких -left / -right. RTL-layout для AR будет zero extra CSS.
Intl.NumberFormat и Intl.DateTimeFormat обёрнуты в shared helpers — никаких хардкоднутых разделителей тысяч, форматов дат, символов валют.
- IBM Plex Arabic загружается в
<head> лениво — активируется при переключении локали на AR. Fallback: Noto Naskh Arabic → system Arabic.
<html dir="..."> устанавливается программно по выбранной локали (LTR для EN/EU, RTL для AR).
Зависит от: Brandbook v1.3 § Internationalisation (ratified) · Блокирует: 1.2 (Onboarding — первая фаза с UI-формами; должна стартовать на готовом i18n-фундаменте)
Фаза 1.2Self-Serve Onboarding + Quick Build [OPL]
Путь от регистрации до первого опубликованного проекта без обращения в support. Это то, что превращает продукт из «нужно звонить» в SaaS.
✅ Sub-plan ratified CONV-35 (2026-05-11) — plans/onboarding-trial-mode.md
Phase 1.2 sub-plan ratified after 5 steps: Step 1 interview (CONV-34, 14 picks) · Step 2 Research (Perplexity Sonar Deep Research → docs/research/stripe-billing-onboarding-stage1-2026-05-11.md) · Step 3 Approaches (single approach + 3 ratifications: ADR 0017 Stripe Stage 1 formal, Trial daily abuse caps DROPPED, Cyprus e-invoicing DROPPED on Abu Dhabi jurisdiction shift) · Step 4 Plan body (~1750 lines + 13 Implementation Steps incl. NEW Step 13 Operator playbook) · Step 4.4 Business review (5 concern agents → 76 findings → 16 Category A applied + 13 Category B ratified → docs/research/business-review-sub-plan-2-2026-05-11.md) · Step 5 Workstream workstreams/onboarding-trial-implementation.md.
Key ratifications: Trial = Full Pro 14d (B4 — Stripe Price tier_2_monthly; ADR 0008 amended) · 3 seats Trial (B1) · Free Guest × host-project Model B Edit-content-no-publish (B2) · Optional invoice reference field (B3) · Current advertised price + transparent reactivation modal (B5) · 3 success-moment upsell modals Stage 1 (B6) · Enterprise mailto Stage 1 / Cal.com Stage 1.5 if ≥3 inquiries (B7) · Checkout redirect для Free Guest → first paid (B8) · 4-email Trial cadence (T-7/T-3/T-1/T+0) · 14 webhook events (expanded from 8) · Stripe Customer creation DEFERRED to trial-init (F2) · `subscriptions.update` для existing-Customer upgrade (Finance H1 fix) · `create_preview` for tier preview (Finance H2 fix, ADR 0013 v1.1) · 7-stage deletion_journal atomic cascade (Security H1) · Custom domain DNS verification (Security H2) · Token URL §1.7.J header hardening (Security H3) · Host allowlist + `requireMembership` + CSP/HSTS/`__Host-` cookies baseline (Security M1/M6).
ADR cross-refs: ADR 0008 amended (Trial T2 default note + config-driven pricing) · ADR 0009 (Tenancy) · ADR 0013 v1.1 (endpoint rename) · ADR 0017 NEW (Stripe Stage 1 formal ratification) · ADR 0005 v3 (Microsoft + Custom SSO scope Tier 3 Stage 2).
Pre-launch blockers: ADR 0011 ratified CONV-36 ✅ (Resend + 2 own domains audience split — offplan.online customer-facing / offplanonline.com buyer-facing reserved; verify-both-now phasing; task card T1-T7 в ADR body) · ADR 0014 (MCP wrapper auth) — separate /plan session before Phase 1.5.6 AI Floor Plan tags · Legal entity lock (Abu Dhabi likely candidate per CONV-35) → triggers UAE-specific tax research · Roman pricing strategy → pricing-config.ts numbers · Designer email copy (7 React Email templates) + 8-12 upgrade modal templates + 3 success modals.
📌 v4.5 — CONV-21 (Atelier onboarding model — supersedes parts of v4.3):
- ✅ Object Builder = onboarding. После регистрации Client сразу попадает на Object Builder — никакого отдельного wizard'а. Visual ref:
admin-quick-build-atelier-standalone.html (заменяет admin-quick-build-v2.html как canonical ref для Phase 1.2).
- Split-screen UX: слева — форма (Project Name → Subdomain auto-suggest + availability → Required Uploads 1/3); справа — Live Preview обновляется по мере загрузки (Desktop/Tablet/Mobile переключатель). Три загрузки: i. Exterior, ii. Floor Plans («Drop a folder — AI tags pages»), iii. Gallery.
- [SAVE & CONTINUE] — публикует проект. [SKIP] — переходит в full admin без создания проекта (только для Paid; на Trial недоступен).
- Trial (TRIAL — N days left badge в шапке): 14 дней T1 без привязки карты. Только Object Builder доступен; Full Admin залочен пока нет активной подписки. По истечении: auto-downgrade → Free Guest, projects read-only (см. §3 Trial period).
- Paid subscription: Object Builder + Full Admin. Переключение в обе стороны из Full Admin.
- 1.2.Z update: не «Quick Build only для Free» — а «Object Builder only для Trial (full admin залочен) + Object Builder + Full Admin для Paid».
- ❌ 1.2.4 (wizard) DEPRECATED — Object Builder заменяет 4-шаговый wizard. Studio profile setup (logo, brand color) перенесён в Settings → опциональный.
- ❌ 1.2.5 (demo-project vs empty-state) DEPRECATED — Live Preview в правой панели даёт time-to-first-value без шаблонного demo-проекта.
- v4.8 (CONV-25): PIN-protected preset config — 4 conditional поля в Object Builder (и Project Settings). Когда Owner / Admin выбирает Public Visibility = «PIN-protected» — разворачиваются: PIN (required, free-format string min 4 char), After-PIN view (Discovery | Full sales), Contact email (required, default = Owner email), Contact phone (optional). См. §5.1 для полного UX flow + §5 для preset table.
Sub-plan plans/onboarding-trial-mode.md нужно обновить с учётом Atelier model. Связано с ADR 0008 (Tier model + admin mode coupling, Skeleton — pricing/limits defer to sub-plan). CONV-34 v4.17 cross-link: auth / invitation token entropy spec теперь живёт в plans/permission-and-tenancy-model.md § 1.4.D (≥128-bit CSPRNG + hashed storage + constant-time compare + per-IP rate-limit) — Phase 1.2 onboarding flows используют этот же token primitive.
1.2.2URL architecture — Org subdomain + project path [v4.19 CONV-35]
КритичноTech+Ops⏱
Amended CONV-35 (v4.19 — resolves CONV-33 Phase 1.3 sub-plan §1.7.J × Phase 1.2.2 conflict + Sub-plan 2 Pick #5 ratification). Canonical URL model — Organisation owns subdomain; projects sit на path within Org subdomain. Не per-project subdomain (legacy, replaced).
Canonical URL pattern table
| Surface | URL pattern |
| Public sales-app (default) | {org-slug}.offplan.online/{project-slug}/... |
| Public sales-app (Tier 2+ custom domain) | palmresidences.com/... |
| Admin panel (central) | app.offplan.online |
| Operator dashboard | staff.offplan.online |
| Buyer tokenised unit URL | {org-slug}.offplan.online/{project-slug}/units/{unit-slug}?b={token} |
| Custom domain buyer URL | palmresidences.com/units/{unit-slug}?b={token} |
Что конкретно нужно сделать (11)
- Wildcard DNS
*.offplan.online → origin (Cloudflare per CONV-30 infrastructure)
- Automatic SSL (Let's Encrypt wildcard или per-subdomain via Cloudflare ACME)
- Subdomain resolution middleware:
{slug}.offplan.online → organisation_id lookup (NOT project_id as in legacy v4.18 — Pick #5 amendment)
- Project path resolution:
/{project-slug} на Org subdomain → project_id within Organisation namespace
- Host header canonicalisation (Security M1 fix): allowlist regex
^([a-z0-9-]+\.)?offplan\.online$ + verified custom domains; reject otherwise; NEVER trust X-Forwarded-Host unless from whitelisted proxy
requireMembership(user, resolved_org_id) pattern на every admin route (Security M6 — tenant-boundary enforcement re-check past subdomain middleware)
- Org slug validation: 58+ reserved subdomains list per §2.7 + brand-relevant extensions; length, char rules
[a-z0-9-], global uniqueness across all Organisations
- Project slug validation: per-Org uniqueness (within Organisation namespace); length, char rules; reserved chars only
- Org slug change cooldown: 12 calendar months; 301 redirect old→new for 90d (per Pick #7)
- Project slug change: free (no cooldown), но invalidates active buyer URLs per Phase 1.3 sub-plan §1.7.J rotation rules; pre-change warning modal
- Security baseline headers: CSP (admin + sales-app) · HSTS ·
__Host- cookies on admin · X-Frame-Options: DENY on admin (tenant sales-app frame-ancestors 'none') · X-Content-Type-Options: nosniff universal
Открытые вопросы — ✅ resolved CONV-35 (Pick #6 + #7)
- ✅ Slug change: Org slug — раз в 12mo (cooldown); project slug — свободно с buyer URL invalidation warning per Pick #7
- ✅ Slug uniqueness: Org slug — global (58 reserved); project slug — per-Org namespace per Pick #6
1.2.3Custom domain self-serve (для проектов)[BL]
КритичноTech⏱
Для конкретного проекта студия (или девелопер через студию) хочет свой домен — например palmresidences.com или marina.developer.ae. В админке инструкции что прописать в DNS, verification flow, SSL автоматом. Premium feature (paid tier).
Что конкретно нужно сделать (8)
- Форма «добавить custom domain» — на уровне проекта (не tenant'a студии)
- Показать две записи DNS (CNAME + TXT)
- Автоматическая проверка propagation (5 мин в первый час, потом реже)
- Статусы: pending / verified / SSL provisioning / active
- SSL provisioning (Let's Encrypt — автоматом после верификации)
- Error states: «DNS не пропагировался», «CNAME указывает не туда», «SSL выдача упала»
- Возможность откатиться на default поддомен если проблемы
- Tier-gating: custom domain доступен на Studio+ tier или paid add-on
Открытые вопросы (3)
- Сколько custom domains per project (1 + redirects)?
- Что если домен уже использовался другим проектом?
- Можно ли transfer custom domain между проектами?
Зависит от: 1.2.2 · Блокирует: —
1.2.4Object Builder onboarding screen (Atelier model)
КритичноDesign+Tech⏱
После регистрации Client сразу видит Object Builder — это первый экран, он же онбординг. Split-screen: слева форма (проект + загрузки), справа Live Preview обновляется в реальном времени. Три загрузки + subdomain = готовый опубликованный проект. Visual ref: admin-quick-build-atelier-standalone.html
Что конкретно нужно сделать (8)
- Split-screen layout: левая панель — Object Builder form (~50%); правая панель — Live Preview с переключателем Desktop/Tablet/Mobile
- Project setup: PROJECT NAME (text field) → SUBDOMAIN (auto-генерируется из name, editable, availability check inline: «Available · live in seconds» / «Already taken»)
- Required uploads (прогресс X/3): i. Exterior (hero image); ii. Floor Plans («Drop a folder — AI tags pages»); iii. Gallery («Renders, lifestyle, brochure pages»). Загруженные файлы — checkmark + Replace.
- Live Preview: правая панель рендерит реальный preview проекта по мере загрузки. Разделы с pending-контентом показывают «AWAITING UPLOAD →».
- [SAVE & CONTINUE]: публикует проект на subdomain → переходит в full admin (Paid) или остаётся в Object Builder (Trial, до апгрейда)
- [SKIP]: пропускает Object Builder → переходит в full admin без созданного проекта. Доступен только для Paid. На Trial отсутствует.
- Trial-gate: 14 дней T1 без карты.
TRIAL — N days left badge в шапке. Full admin недоступен / залочен пока нет подписки. Object Builder — единственная рабочая поверхность. По истечении без оплаты — auto-downgrade → Free Guest, projects read-only (детали: §3 Trial period).
- Studio profile setup (logo, brand color) — не блокирует первый проект. Перенесён в full admin → Settings, опциональный.
Открытые вопросы (3)
- AI tags для Floor Plans — на чьей инфраструктуре? (VV backend vs отдельный pipeline) — критично для Phase 1.5
- Что показывать в Live Preview до первого uploaded файла? (placeholder / gradient / пустой каркас с брендом)
- Object Builder доступен для создания второго проекта или только для первого? (новый проект из full admin — отдельный flow?)
Зависит от: 1.3.11, 1.2.2 (subdomain provisioning) · Блокирует: —
1.2.5Demo-проект vs Empty-state — DEPRECATED (CONV-21)
ОтмененоProduct+Design
Отменено. Live Preview в правой панели Object Builder (1.2.4) даёт time-to-first-value без шаблонного demo-проекта — студия видит свой реальный контент уже в процессе загрузки. Mockup-сравнение и demo-проект не нужны.
Superseded by: 1.2.4 (Object Builder — Live Preview правая панель)
1.2.6Email onboarding sequence (отложено в Стадию 3)[BL]
Низкий → отложеноMarketing+Tech
Отложено в Стадию 3. Сергей: «Не нужно об этом париться, пока мы не знаем флоу.» Email sequence строится после того как мы поймём реальный путь пользователя на пилоте. До этого — преждевременная оптимизация.
Что вместо этого в Стадии 1 (3)
- Один welcome email после signup (минимум — verification + ссылка на Object Builder)
- Один email-уведомление о приглашении team member (для 1.2.7)
- Простые transactional emails (billing, password reset) — без onboarding sequence
Перенесено в: Стадия 3 — будет добавлено как новая фаза после анализа пилота
🔴 Critical (повышено с High, ревизия 2026-04-28).
Без operator dashboard нет инструмента управлять студиями с момента первой регистрации — администрирование через консоль БД рискованно, не атрибутируемо и не масштабируется. Audit log дёшево добавить заранее, дорого встраивать через год. Так как Super Admin Panel уже существует — задача не "build from scratch", а надстройка (subscription / payment / audit log / multi-tenant client list).
Фаза 1.3
Tenancy & Permission Model [BL]
«Один tenant = одна Organisation, создаётся одним Client'ом» — фундаментальное решение multi-tenant архитектуры. Entity model + permission scoping + per-unit stock allocation + cross-entity invitation flows + referral architecture. Foundational: блокирует Phase 1.4 (Operator Dashboard), 1.7 (Sales Page billing scope), 1.10 (Sales-app), 1.11 (Sales Presentation Layer).
💡 Sub-plan: plans/permission-and-tenancy-model.md — детальная архитектурная проработка с ADR 0009 (Tenancy & Permission Architecture) + ADR 0010 (Stock allocation). Источник: CONV-15 (Roman call) + CONV-17 (sub-plan ratification).
📌 Ratified permission-and-tenancy decisions (CONV-17 + CONV-24 + CONV-32 + CONV-33 + CONV-34 SPEC-AMEND patches) — sub-plan ratified + 21 HIGH closed, ready для Phase 1.3 implementation
Authoritative spec — plans/permission-and-tenancy-model.md (status: ratified CONV-33 — Part 1 + Part 2 closed · SPEC-AMEND v4.17 + v4.18 patches CONV-34). Part 1 (10 разделов: Signup + onboarding · Login + auth-scoped views · Workspace switcher (Org + Project) · Cross-entity invitations · Role transitions · Stock assignment · Reserve unit flow + conflict modal · Tier transitions · Internal/External SA · Permission matrix) consolidates Foundational §2 + §4.1-4.6 + §5 + §6.1 + §7.1 + 14 picks. Part 2 (11 разделов Decision Log: Workspace switcher mechanics · Ownership transfer detail · Referral attribution rules · Audit log scope · Naming finalisation · Email mismatch wording · Subdomain reservation list (58 entries) · Free Guest → paid conversion · SA dual-Org membership + home_org formalisation · Open/Closed pool reversibility · Microsoft OAuth resolution) ratified pack-mode CONV-33 + 6 new picks + Risks section с 21 HIGH / 29 MED / 15 LOW findings из business review (6 concern agents). CONV-34 patch session closed 21 HIGH SPEC-AMEND findings via v4.17 (Themes 1+2 — Token mechanics hardening: TTL 7d→30d reverse-invite + buyer token mechanics (≥128-bit + scope-to-unit + rotation + noindex) + invite entropy + rate-limit; Session/permission re-eval policy: role-change cross-subdomain session revoke + per-action DB permission check + stock-wipe modal + cascade triage view + ownership transfer target-Org gate + SA project-switcher non-jarring banner) and v4.18 (Themes 3+4 — Audit immutability + GDPR retention: insert-only DB role + monthly hash-chain seal + off-box S3 archive + pseudonymisation post-12mo + 7yr Cyprus statutory horizon + ADR 0004 v2 + ADR 0014 placeholder MCP wrapper; Ownership transfer + billing precision: Stripe customer cleanup + chargeback overrides grace + cash-basis revenue + ADR 0013 proration + referral 12mo cap + referral Organisation-bound + 2FA recovery + operator dashboard lookup) patches. Workstream phase-1-3-implementation (P0) — Track A (SPEC-AMEND) closed; Track B (Roma scaffold) unblocked. Numbered tasks 1.3.1-1.3.12 ниже реализуют ratified decisions: Entity model (Client / Organisation / Buyer split, см. Foundational §1) · 5 ролей (Owner / Admin / Sales Manager / Content Editor / Sales Agent), Sales Manager = объединённая operational роль · Hybrid login surfaces (per-Organisation branded + central fallback, Google + email/password UAE/MENA, см. §2) · S·1 stock allocation (Closed pool default + Open mode opt-in, см. §4.4) · Scoped URL routing (subdomain + project slug + tokenised buyer URL) · Cross-entity invitations (Forward Developer→Studio + Reverse Studio→Developer = Free Guest tier path, см. §4.1) · Invitation token generation (≥128-bit CSPRNG + 7d/30d TTL per type — per v4.17) · Organisation type multi-select (Studio/Agency/Developer) · Content Editor vs Sales Agent distinction · Referral architecture (data model Stage 1, payouts Phase 4.2, см. §7) · Signup & tenant data model · Permission model + team management UI. v4.7 (CONV-24): Internal/External SA operational split formalised в §4.5 — RBAC должен экспонировать обе variants через API + UI permissions filter (membership_type derived через organisation_id link).
ADRs ratified: ADR 0009 (Tenancy & Permission Architecture, Full spec, CONV-31), ADR 0010 (Stock allocation strategy, Full spec, CONV-31), ADR 0005 v3 (Microsoft + Custom SSO scope для Tier 3 Stage 2, CONV-31), ADR 0004 v2 (audit retention 12mo active + 7yr archive + pseudonymisation, CONV-34), ADR 0013 (Tier change proration policy — asymmetric, CONV-34), ADR 0014 placeholder (MCP wrapper auth — Phase 1.5.6 implementation gate, CONV-34). Sub-plan ratified (CONV-33): Part 2 Decision Log + 6 picks + business review (Studios / Sales motion / Customer Success / Legal+Compliance / Security / Finance+Billing). SPEC-AMEND patches CONV-34: v4.17 (Themes 1+2 — 10 HIGH closed) + v4.18 (Themes 3+4 — 11 HIGH closed). 21/21 HIGH SPEC-AMEND findings = closed; 29 MED documented для post-launch; 15 LOW Stage 2 backlog.
1.3.1Entity model design
ВысокийTech+Product⏱
Иерархия сущностей: Organisation (tenant, subscription owner) с types Studio / Agency / Developer (multi-select), Client (login identity), Project, Unit, Sales Agent / Content Editor / Sales Manager (роли), Buyer. Одна Organisation может играть разные роли в разных проектах (например, Volume Vision = Studio в одном проекте и Agency в другом). Тип Organisation — галочка studio/agency/developer внутри карточки.
Зависит от:
ADR 0009 · Блокирует: 1.3.2-1.3.12
1.3.2Permission layers — RBAC + scoping
ВысокийTech⏱
Role-Based Access Control с двумя scope-уровнями: project-level (доступ к одному проекту) и all-projects (доступ ко всем проектам Organisation'ы). Permission matrix: какие действия разрешены каждой роли (view / edit / delete / invite / billing).
Зависит от: 1.3.1 · Блокирует: Phase 1.4
1.3.3Login / auth multi-role flow
ВысокийTech⏱
Один user может иметь разные роли в разных проектах. После логина показываем выбор контекста (если ролей >1) или прямой редирект (если одна роль). Session scoped to current selection.
Зависит от: 1.3.1, 1.3.2 · Блокирует: Phase 1.10
1.3.4Per-unit stock tagging
ВысокийTech+Product⏱
Каждый юнит при создании помечается: agency / developer / specific agent / shared. Это решает проблему conflict-of-sale между агентствами (Роман явно: без этого нас выгонят). Tag меняется через admin UI или batch-операцию.
Что конкретно нужно сделать (4)
- DB schema:
units.assigned_to — polymorphic FK (agency/agent/null=shared)
- Admin UI: при создании unit'а dropdown "Assigned to" + bulk-edit
- Validation: только members owning Organisation могут менять assignment
- Audit: каждое изменение assignment'а логируется
Зависит от: 1.3.1 · Блокирует: 1.3.5, Phase 1.10
1.3.5Scoped URL routing strategy
ВысокийTech+Product⏱
Решено (CONV-21): auth-scoped views. Один URL {slug}.offplan.online/projects/{project-slug} рендерит разный контент в зависимости от viewer state (см. Foundational §5): anonymous = Public Visibility preset; authed Organisation team member = full content фильтрованный S·1 stock allocation; buyer с tokenised URL = unit-aware view. Login entry surface — иконка top-right на каждой странице sales-app (см. 1.10.0). Зафиксировано в ADR 0009.
Открытые вопросы (2)
- Anonymous viewer на Private preset: показывать «Request access» CTA или login-wall?
- Buyer-share-link при истёкшем token (90d) — temp profile или просто attribution stays в DB?
Зависит от: 1.3.4 · Блокирует: Phase 1.10
1.3.6Cross-entity invitation flows (forward + reverse)
ВысокийTech+Product⏱
Два направления приглашений:
(1) Forward — Developer создаёт проект, приглашает Studio/Agency на конкретный проект или все проекты;
(2) Reverse — Studio создаёт проект, потом приглашает Developer (например, VV сделала весь проект для итальянского застройщика, отдаёт ему).
Зависит от: 1.3.1, 1.3.7 · Блокирует: Phase 1.4
1.3.7Invitation token generation
СреднийTech⏱
Token-based приглашения: link или email. Опции — project-scoped (один проект) или all-projects (вся компания). Token expires (например 7 дней). После acceptance создаётся membership с указанной ролью.
Зависит от: 1.3.6 · Блокирует: —
1.3.8Organisation type designation
НизкийProduct⏱
При создании Organisation — галочка "I am: Studio / Agency / Developer". Влияет на default-настройки, видимость секций админки, маркетинговые сегменты. Меняется через Settings.
Зависит от: 1.3.1 · Блокирует: —
1.3.9Content Editor vs Sales Agent role distinction
СреднийProduct⏱
Внутри Organisation — две разные роли с разными правами:
• Content Editor — может редактировать содержимое проекта (галереи, описания, planирование), не видит билинг и не приглашает;
• Sales Agent — может проводить презентации, создавать buyer-профили, но НЕ редактирует контент.
Зависит от: 1.3.1, 1.3.2 · Блокирует: Phase 1.11
1.3.10Referral relationship architecture
СреднийTech+Product⏱
Data model для будущей реф-программы: sponsor (кто привёл) → referee (кого привели) → revenue share %. Архитектура закладывается в Stage 1, UI и payouts реализуются в Stage 2 (или Phase 4.2 Продвинутая монетизация).
Зависит от: 1.3.1 · Блокирует: Stage 2 — реф. payouts
1.3.11Signup & tenant data model
КритичноTech+UX⏱❓
Регистрационный flow + архитектурный фундамент multi-tenant системы. Минимальная форма signup: email + пароль (или Google SSO). Название студии/страна — deferred в Settings; первый экран после регистрации = Object Builder (1.2.4). Permission model + team management UI — в 1.3.12.
Что конкретно нужно сделать (8)
- Форма signup: email + пароль — минимально. Название/страна → Settings post-onboarding
- Требования к паролю (NIST: 12+ символов, haveibeenpwned check)
- Verification email с токеном (expires 24h) + re-send
- Social SSO: Google primary + email/password fallback (UAE/MENA market)
- Rate limit на signup per IP
- Tenant-архитектура: Organisation = root tenant; guest organisations = invited через cross-entity invites
- Database schema: organisations (
id, name, subdomain, country, client_types, plan, status, owner_user_id), users — фундамент для 1.3.12 + 1.4
- Operator (OPL master) access — отдельный flow (impersonation / support mode), не обычный login
Implementation ideas
DB security checklist (reference, не директива): cross-tenant query scoping по org_id; mass assignment protection на PATCH-эндпоинтах; AuditLog append-only; sensitive fields исключены из логов; connection pool limits.
Открытые вопросы (2)
- ❓ Какие SSO обязательны на старте? (Google confirmed — Microsoft/Magic Link defer?)
- ❓ Готова ли существующая база к multi-tenant scoping или нужен рефактор?
Зависит от: 1.8.2,
ADR 0009 · Блокирует: 1.2.4, 1.3.12
1.3.12Permission model + team management UI
КритичноTech+Design⏱❓
Реализация 1.3.1-1.3.2 spec поверх tenant-схемы из 1.3.11: RBAC DB schema + UI/flow для приглашений, управления командой, granular доступа. Закрывает B2B-сценарии: студия → сотрудники; девелопер → сейлз-агенты.
5 уровней доступа
| Уровень | Кто | Видит | Может |
| 1. Operator (OPL) | Сергей, Рома, Илья | Всё (любой tenant) | Impersonate, support, audit |
| 2. Owner / Admin | Owner of Organisation | Свой tenant полностью | Всё: проекты, billing, инвайты |
| 3. Sales Manager / Content Editor | Members Organisation | По scope (per project / all) | Sales Manager = stock+buyers+content; Content Editor = content |
| 4. Developer client (guest org) | Клиент-девелопер | Assign'нутые проекты | Контент + приглашает своих Sales Agent'ов |
| 5. Sales Agent | Брокеры девелопера | По assign'у | Buyer/presentation flow, статус own units |
Что конкретно нужно сделать (9)
- DB schema (поверх 1.3.11): roles, permissions, user_role_assignments, memberships
- Invite-flow уровни 3-5 — не самостоятельный signup, только по invite (см. 1.3.6-1.3.7)
- UI «Invite team member» — выбор роли + scope (per project / org-wide)
- Email-invitations + принятие + expiration 7d + re-send (см. 1.3.7)
- Remove user (transfer ownership если owner)
- Granular permissions per project — доступ на конкретный проект, не на всю студию
- Seat limit per plan tier (совместимо с 1.7)
- Organisation switcher UI (Slack pattern) — для Clients с N Organisation memberships (детали в
plans/onboarding-trial-mode.md)
- Audit: кто изменил что (связано с 3.3.3 Audit log)
Открытые вопросы (3)
- ❓ Studio-level SSO (Google Organisation / Microsoft) — Stage 1 или defer в Enterprise tier?
- ❓ Что с контентом removed user — остаётся или «unassigned»?
- ❓ Жёсткая query-layer изоляция между разными Organisation tenant'ами для guest orgs?
Зависит от: 1.3.1, 1.3.2, 1.3.11 · Блокирует: Стадию 2 (без team management многие студии не смогут пилотировать)
Фаза 1.4Operator Dashboard (staff.offplan.online) — расширение существующей Super Admin Panel
Контекст (ревизия 2026-04-28): tech team подтвердила, что Super Admin Panel уже существует и работает в продакшене. Текущая панель имеет: список проектов, переключатели feature-флагов на каждый проект (13+ флагов), управление сейлз-менеджерами, загрузку ассетов (логотип, видео), action log. Фаза 1.4 = надстройка над этой панелью для multi-tenant управления клиентами-студиями: подписки, платежи, audit log, список клиентов с drawer'ом. Не строим с нуля. Поддомен staff.offplan.online, отдельная аутентификация, постоянный баннер "STAFF" в шапке. Визуальный preview (v3): operator-panel-v3.html.
💡 Suggestion: before dev builds the new screens, build a complete HTML/CSS mockup of the operator dashboard together (product owner approves it), then hand off to the tech team to wire up to real data and auth — faster implementation, fewer visual revisions.
📌 v4.13 (CONV-30 sweep) — Wave 2 operator surface implications:
- Operator dashboard читает audit log entries и shows status / suspension / token state per Foundational specs. Implications от Wave 2: (a) §4.6 View-as-Agent — team-level admin tool ≠ Stage 4 operator impersonation; (b) §5.1 PIN-protected — operator видит «PIN-protected» флаг для support, не PIN value; anti-brute-force aggregate (failed attempts >3/hr); (c) §6.1 status-flip audit + §6.2 channel analytics — forward + reverse flip timeline per Organisation, anti-abuse aggregate «>20 reverse-flips/30d», 3-channel send tracking; (d) §7 edge cases — self-leave distinct-actor logging, suspension token state, Visibility-flip token bypass, referrals
ineligible_cycle counter.
- v4.3 (CONV-15) + v4.4 (CONV-17) placeholder content → absorbed в numbered tasks 1.4.9-1.4.13 ниже (Fullscreen Org card, Suspension UI, GDPR erasure, Stock allocation conflict, Owner lockout). Reserved subdomain note (
staff blacklist) → absorbed в task 1.4.2.
Operator dashboard 2FA mandatory always (внутренний tooling). См. Foundational §2.
Зачем это нужно сейчас (а не позже)
- В момент когда первая студия зарегистрировалась — нужен инструмент чтобы её увидеть, помочь, при необходимости заблокировать (suspend)
- Без отдельной staff-панели администрирование идёт через консоль БД — рискованно, действия нельзя атрибутировать, не масштабируется на будущий найм support
- Audit log дёшево добавить заранее, дорого встраивать через год
- Adapter-pattern для платежей позволяет начать с manual entry и подключить Stripe / Paddle / Checkout.com позже без переделки UI
1.4.1Data model: Subscription + Payment + AuditLog[OPL]
КритичноTech⏱❓
Добавить три сущности к существующей DB: Subscription (план, статус, trial expiry, billing cycle), Payment (provider-neutral schema), AuditLog (actor, action, target, timestamp). Без этого dashboard нечего показывать.
Что конкретно нужно сделать (6)
- Subscription table:
org_id, plan (free/trial/pro/enterprise), status, trial_ends, cycle_start, next_billing_date
- Payment table:
org_id, subscription_id, amount, currency, date, status, provider, external_id — provider-neutral (Stripe / Paddle / Checkout.com / manual entry — все через один schema)
- AuditLog table:
actor_id, actor_type (operator / user / system), action, target_type, target_id, org_id, timestamp, metadata (JSON)
- Migrations + seed data: создать Subscription для существующих org как 'trial' / 'free' пока billing не подключён
- Indexes:
org_id на всех трёх, timestamp на AuditLog (для быстрого фильтра по периоду)
- Trial period: 7 дней (подтверждено)
Открытые вопросы (2)
- ❓ AuditLog retention: хранить вечно или archive после N месяцев?
- ✅
Payment provider — выбираем Stripe / PayTabs / Telr / hybrid? — Решено per payments-research: multi-provider по фазам — Stripe primary (Стадия 1), + Paddle EU B2C (Стадия 2), + Checkout.com UAE AED (Стадия 3). Adapter подключается в 1.7.3.
Зависит от: Фаза 1.2.1 (Organisation / Tenant entity — проектируется один раз и используется и в Onboarding, и в Operator Dashboard) · Блокирует: 1.4.3, 1.4.4, 1.4.6, 1.4.7
1.4.2Operator auth + subdomain[OPL][BL]
КритичноTech+DevOps⏱
Поддомен staff.offplan.online, отдельный логин, отдельный cookie. Оператор никогда не путается с клиентским аккаунтом. У каждого оператора (Sergey, Ilya, будущий support-хайр) свой индивидуальный логин — все действия можно атрибутировать. Итерация 1: базовая аутентификация (email + пароль + session). 2FA и IP allowlist — в Итерации 2 (после первых 5–10 платящих студий).
Что конкретно нужно сделать (Итерация 1) (5)
- Поддомен DNS + SSL:
staff.offplan.online указывает на тот же деплоймент что и app, но маршрутизируется на staff bundle. staff в reserved-subdomain blacklist при создании Organisation subdomain (вместе с app, api, admin, www, etc.).
- Отдельная таблица operator (не общая с User):
id, name, email, password_hash, last_login, status (active/disabled)
- Login flow: email + пароль (базовая аутентификация, без 2FA)
- Session cookie на
staff.offplan.online — не передаётся на app.offplan.online и обратно
- Постоянный баннер "STAFF" в верхней панели UI (золотой акцент по брендбуку v1.1) + политика logout / истечения сессии (короткий timeout — рекомендуется 8 часов)
Итерация 2 (после первых платящих студий) (2)
- 2FA: TOTP (Google Authenticator / 1Password) — обязательно для продакшена, когда команда вырастет
- IP allowlist: опциональная настройка в operator settings — ограничивать вход только известными IP (офисный VPN / домашний)
Зависит от: 1.8 (security baseline) · Блокирует: 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8
1.4.3Overview page (главный экран staff-панели)[OPL]
ВысокийTech+Design⏱
"Утренний экран" — открыл, увидел всё ли в порядке. KPIs + три фида.
Что конкретно нужно сделать (5)
- KPI row: Total clients · Active · Trials (с подсчётом ending soon) · Failed payments
- Recent signups feed: последние 7 дней — кто, когда, какой план
- Trials ending soon: следующие 7 дней — кто, дата, активность за trial
- Needs attention: failed payments, suspended accounts, неактивные клиенты
- Alert banner вверху если есть critical issues (failed payments, suspended)
Зависит от: 1.4.1, 1.4.2 · Блокирует: —
1.4.4Organisations list + detail drawer[OPL]
КритичноTech+Design⏱
Основной экран ежедневной работы. Сортируемая / фильтруемая таблица всех клиентов + slide-out drawer с детальной информацией. Вкладка Projects в drawer расширяет существующую Super Admin Panel: переключатели feature-флагов на каждый проект, секция Information (домен, тема, сейлз-менеджеры), секция Assets (логотип, видео). Визуальный референс (v3): operator-panel-v3.html.
Что конкретно нужно сделать (8)
- Список Organisations: колонки — Organisation, Plan, Status, Projects, Last active, Signed up, MRR contribution
- Filters: status (Active / Trial / Suspended / Churned / Failed payment), plan
- Search: name / email / subdomain
- Sortable columns (по умолчанию — Last active descending)
- Slide-out drawer на клик строки — 7 вкладок: Overview, Users, Projects, Subscription, Payments, Activity, Notes
- Drawer header: status pill, plan badge, action buttons (Send password reset, Extend trial, Edit notes, Suspend)
- "+ Add client manually" — для случаев когда онбординг через звонок / email
- Internal notes (timestamped, attributed к operator) — никогда не видны клиенту
Зависит от: 1.4.1, 1.4.2 · Блокирует: 1.4.5
1.4.5User management actions (reset / email / suspend)[OPL]
КритичноTech+Legal⏱
Действия operator на user: reset password (через email link, не setting password directly), change email (с notify-both), suspend user / org. Disclosed в ToS (см. 1.8).
Что конкретно нужно сделать (6)
- Send password reset: триггерит email с reset link на user (operator никогда не вводит пароль за user'a — это security red flag)
- Change email: новый email требует confirmation; notification отправляется на старый AND новый email (защита от account hijacking)
- Suspend user: блокирует login, не удаляет данные
- Suspend org: блокирует login для всех users в org, проекты переходят в read-only
- Reactivate: обратное действие
- Все действия логируются в AuditLog с operator_id (см. 1.4.7)
Открытые вопросы (2)
- ❓ Hard delete account — в Итерации 1 или Итерации 2? Recommend: только soft suspend в Итерации 1, hard delete с 30-дневным grace period — в Итерации 2
- ❓ Impersonation (login as user) — отложено в Стадию 4, требует обязательного обновления ToS
Зависит от: 1.4.4, 1.9 (Legal — ToS disclosure) · Блокирует: —
1.4.6Payments page (manual entry adapter — Итерация 1)[OPL]
ВысокийTech⏱
Сквозной просмотр платежей по всем клиентам. Итерация 1 (упрощён 2026-04-28): только manual entry adapter — оператор руками вносит записи о платежах, когда студия оплатила (банковский перевод / инвойс / разовая сделка с выставки). Реальный провайдер (Stripe / Paddle / Checkout.com — multi-provider per payments-research) подключается в Фазе 1.7 — UI здесь не меняется (provider-neutral schema). На странице Settings — placeholder-карточка "Payment Provider", указывающая на Фазу 1.7. Глубокая аналитика (MRR breakdown, churn, expansion, когорты) — Стадия 4.
Что конкретно нужно сделать (Итерация 1) (6)
- Селектор периода: эта неделя / этот месяц / этот год / произвольный диапазон
- Верхние карточки KPI: Total collected · Outstanding · Failed · количество платящих клиентов
- Блок "Failed payments" — отдельная секция выше таблицы (первое, на что смотришь когда выручка выглядит странно)
- Основная таблица: дата, клиент, план, сумма, статус, метод (Manual для всех в Итерации 1), действие
- Форма manual entry: оператор вручную вносит запись о платеже (amount, currency, client, период покрытия)
- Бейдж статуса провайдера на странице ("Provider: Manual entry · Change provider →") — ссылка ведёт в Settings → Payment Provider
Открытые вопросы (0)
- ✅
Валюты — только AED или USD + AED? — Решено per payments-research: multi-currency — USD / EUR / AED / AUD; pay.offplan.online/<slug> страница с выбором валюты, маршрутизация к нужному provider
Зависит от: 1.4.1, 1.4.2 · Связано: Фаза 1.7 (подключение провайдера) · Блокирует: —
1.4.7Audit log (basic capture + viewer)[OPL][BL]
ВысокийTech⏱
Логирование действий оператора и системных событий. Итерация 1 (упрощён 2026-04-28): базовое логирование + простой viewer. Расширенные возможности (multi-tenant search, full-text search, JSON diff display, real-time tail) — в Итерации 2. Дёшево добавить сейчас, дорого переделывать позже — поэтому базовое логирование в Итерации 1 обязательно.
Что конкретно нужно сделать (Итерация 1) (5)
- Логировать действия оператора: password reset, смена email, suspend, редактирование notes, смена плана, ручной ввод payment
- Логировать системные события: payment failed, trial expired, subscription created, project published
- Базовый viewer: хронологический feed, простые фильтры — actor (имя оператора), тип действия, организация, диапазон дат
- Фильтр per-org — на вкладке Activity в drawer показывает audit log одной организации
- Доступ: все операторы могут читать; на запись только система — нельзя редактировать вручную (immutable, append-only)
Итерация 2 (после первых платящих студий) (3)
- Full-text search по полю metadata
- JSON diff display для PATCH-событий (визуализация что именно изменилось)
- Экспорт в CSV (для compliance / legal-запросов)
Зависит от: 1.4.1, 1.4.2 · Блокирует: —
1.4.8Settings: operator team + email templates[OPL]
НизкийTech⏱
🟡 Перенесено в Стадию 2 (ревизия 2026-04-28). Для Итерации 1 (первые ~5–10 платящих студий) команда операторов = 1–2 человека (Sergey + Ilya). Управление через DB / конфиг достаточно. Шаблоны писем можно править захардкоженными в коде. Полноценный раздел Settings (управление командой операторов, редактирование шаблонов писем, ключи интеграций) — после того как команда вырастет, в Стадии 2.
Итерация 1 — minimal stub (2)
- Страница Settings есть в навигации (placeholder)
- Payment Provider placeholder-карточка на Settings — показывает текущий провайдер ("Manual entry · Active") + карточки Stripe / Paddle / Checkout.com (disabled, Phase 1.7 — multi-provider per payments-research)
Перенесено в Стадию 2 (5)
- Список команды операторов: приглашение (по email-ссылке), удаление, редактирование имени / email
- Редактируемые шаблоны писем: password reset, suspension notice, trial ending, failed payment
- Переменные в шаблонах:
{client_name}, {operator_name}, {expiry_date} и т.д.
- Preview отрендеренного шаблона перед сохранением
- UI для управления ключами интеграций (Stripe / аналитика)
Зависит от: 1.4.2 · Блокирует: —
1.4.9Fullscreen Organisation card (replaces drawer pattern)[OPL]
СреднийTech+Design⏱
Drawer pattern из 1.4.4 тесен — слишком много данных под Organisation (Subscription / Payments / Activity / Notes / Users / Projects). Полноэкранная карточка клиента: 7-tab layout, breadcrumb back, action buttons в header (Send password reset, Extend trial, Edit notes, Suspend). Drawer остаётся как quick-peek для overview/list, fullscreen — для deep work. Source: CONV-15 Roman call.
Зависит от: 1.4.4 (drawer baseline) · Блокирует: —
1.4.10Suspension management UI[OPL]
ВысокийTech⏱
Operator может suspend / reactivate Organisation. 14d grace period, hybrid block scope: login OK, edit blocked, public site работает 30d потом freeze. Unit статусы не трогаем при suspension. См. Foundational §3 — Suspension flow + §7.4 (token read-only behaviour). Source: CONV-17 permission-and-tenancy ratification.
Что конкретно нужно сделать (5)
- Suspend action button в Organisation card / drawer (Owner/Admin permission gated)
- Confirmation modal с консеквенциями (login still works, edit disabled, public site countdown 30d)
- Status badge в Organisations list:
Suspended (amber) + grace period countdown
- Reactivate flow — Owner/Admin one-click, audit log entry
- Middleware enforcement: edit endpoints возвращают 403 для suspended orgs; public sales-app fallback на read-only banner per §7.4
Зависит от: 1.4.1 (subscription status), 1.4.4 (Organisation card) · Блокирует: —
1.4.11GDPR/ADGM erasure processing (manual)[OPL]
ВысокийTech+Legal⏱
Operator manual flow Stage 1 для buyer right-to-erasure requests. SLA 30 дней per privacy clauses. Self-service erasure → Stage 2. См. Foundational §7 — GDPR + Phase 1.9 privacy clauses. Source: CONV-17 permission-and-tenancy ratification.
Что конкретно нужно сделать (4)
- Erasure request inbox (от support@ → operator queue), 30d SLA timer
- Anonymization process: buyer-record → email/name/phone обнулены, attribution preserved (audit + commission)
- Cascade: presentation_units / heart actions / contact requests с buyer_id остаются с anonymized buyer reference
- Audit log entry: «erasure processed for buyer X by operator Y at TIMESTAMP» — sans PII
Зависит от: 1.4.1, 1.4.7 (audit log) · Блокирует: —
1.4.12Stock allocation conflict reconciliation[OPL]
СреднийTech⏱
Manual UI для разрешения admin-error situations (two Organisations претендующих на один unit; orphan assignments после Org delete; etc.). См. Foundational §7 — Conflicts + §4.4 stock allocation. Source: CONV-17 permission-and-tenancy ratification.
Зависит от: 1.4.1, 1.3.4 (stock allocation model) · Блокирует: —
1.4.13Owner lockout recovery (manual MFA reset)[OPL]
СреднийTech+CS⏱
Manual operator MFA reset Stage 1 — Owner потерял 2FA / device. Email + identity verification (manual check), затем operator triggers MFA reset. Automated recovery (recovery codes + email confirmation chain) → Stage 2. Source: CONV-17 permission-and-tenancy ratification.
Что конкретно нужно сделать (4)
- Lockout request inbox (от support@ → operator queue)
- Identity verification checklist (email match + phone callback + ID document если запрашивается)
- Operator action: «Reset MFA for user X» button → user receives login email, 2FA disabled, must re-enrol
- Audit log: «MFA reset for user X by operator Y, verification method: [...]»
Зависит от: 1.4.1, 1.4.7 · Блокирует: —
Связи с другими фазами:
- 1.7 (Платёжная инфраструктура) — UI страницы Payments готов в 1.4, конкретные plug-in'ы провайдеров (Stripe → Paddle → Checkout.com per payments-research) подключаются в Фазе 1.7. Adapter-pattern позволяет добавлять провайдеров без переделки UI.
- 1.8 (Security) — аутентификация оператора должна соответствовать security baseline (password hashing, session policy, 2FA optional / required).
- 1.9 (Legal) — ToS должна раскрывать факт доступа оператора к данным клиентов; будущая impersonation потребует обязательного disclosure.
- Стадия 4 (отложено) — иерархия ролей оператора (sales / support / finance), глубокая аналитика выручки (MRR breakdown / churn / cohort retention), impersonation, mobile-responsive layout.
- Визуальный preview: operator-panel-v3.html — мульти-страничный мокап (v3). Также в Visual Appendix.
🟡 High (понижено с Critical, ревизия 2026-04-28).
Тонкий слой над существующим API: AI-клиенты (Claude Desktop, Cursor) могут управлять платформой через диалог. Self-serve становится действительно self-serve — admin UI не обязан быть идеален. Целевая аудитория (рендер-студии) уже использует AI-инструменты. Плюс — внутренняя команда работает с клиентами через Claude вместо UI. Понижение приоритета: MCP — мощный differentiator, но не блокирует запуск (студии могут работать через admin UI). Если эстимейт большой — итерация 2 переносится в Стадию 2.
Фаза 1.5MCP Server Wrapper [BL]
Что такое MCP: открытый стандарт от Anthropic для AI-моделей вызывать внешние API через стандартизированный интерфейс. MCP wrapper = тонкий слой над нашим существующим API, превращающий endpoints в "tools" для AI. Студия открывает Claude и говорит «создай новый проект Marina Residences с 80 юнитами 1BR/2BR» — Claude вызывает наши MCP tools, проект создан за 30 секунд. Пользователь открывает marina-residences.offplan.online, sales-app live.
⚠️ Implementation gate (CONV-34): Phase 1.5.6 — MCP wrapper auth + prompt-injection sanitisation — blocked до full ratification ADR 0014
ADR 0014 placeholder shell ratified CONV-34 — security gate явно зафиксирован, но full spec deferred к dedicated /plan session. Risks (per Phase 1.3 sub-plan § Architectural risks): (1) cross-tenant data leak через connection-scoped auth — каждый MCP tool call должен resolve org_id per-call, не из connection state; (2) prompt-injection laundering — user-controlled content (project names, unit descriptions, buyer notes, audit entries) returned through MCP может быть interpreted as LLM instruction. Tech team может включать org_id propagation interface в общий scaffold (Phase 1.3.2 multi-tenant scoping), но actual MCP wrapper code = blocked до ratification. См. Phase 1.3 sub-plan plans/permission-and-tenancy-model.md § Architectural risks + Learning «MCP wrapper prerequisites: tenant isolation + prompt-injection sanitisation» (2026-04-27).
Подход — две итерации
- Итерация 1 (Стадия 1): Read-only MCP — простая реализация (только GET endpoints), низкий риск, queries / reports / ответы на вопросы. ⏱ Требует эстимейт от tech team.
- Итерация 2 (Стадия 1 или 2 в зависимости от эстимейта): Read+write MCP — полная автоматизация (create / update / delete / upload), требует careful scoping. ⏱ Требует эстимейт от tech team.
1.5.1API audit + scope definition for MCP exposure[BL]
КритичноTech⏱❓
Полный audit существующих API endpoints, определение какие из них exposить через MCP в первой итерации (read-only) и второй (read+write). Документация в формате tool-friendly. Source: существующий VV API surface — Илья предоставляет исходники как starting reference (CONV-15 Roman call).
Что конкретно нужно сделать (5)
- Audit existing API endpoints (как 4.1.2, но scope для MCP)
- Категоризация: read-only safe / read+write / admin-only / never-expose
- Документация: для каждого endpoint — name, description, parameters, return shape (для MCP tool definition)
- Identify gaps: какие операции часто нужны, но нет endpoint
- Authentication scope (см. 1.5.4)
Открытые вопросы (2)
- ❓ Какие endpoints в первую итерацию (top 10 для read-only)?
- ❓ Есть ли API endpoints, которые не должны быть exposed через MCP вообще (admin-only)?
Зависит от: — · Блокирует: 1.5.2, 1.5.3
1.5.2MCP read-only wrapper (Iteration 1)[BL]
КритичноTech⏱
Первая итерация MCP server — read-only. Любой MCP-совместимый client (Claude Desktop, Cursor) может подключиться, запросить данные, получить ответы.
Что конкретно нужно сделать (6)
- MCP server (Node.js / Python — выбор Ильи)
- Tools для read-only операций: list_projects, get_project, list_units, get_unit, list_buildings, get_availability, list_team_members и т.д.
- Authentication: per-studio token, scoped to single tenant
- Rate limiting (отдельно от human API)
- Logs: что AI запрашивает, для security audit
- Hosting: отдельный subdomain
mcp.offplan.online или часть основного API
Открытые вопросы (2)
- Hosting: standalone server vs middleware на основном API?
- Token issuance: studio-admin генерит сам, или per-user?
Зависит от: 1.5.1 · Блокирует: 1.5.3
1.5.3MCP read+write wrapper (Iteration 2)[BL]
Критично-ВысокийTech⏱❓
Conditional: если эстимейт от Ильи окажется большой — переносим в Стадию 2. Read-only остаётся в Стадии 1 (1.5.2). Вторая итерация — Claude может создавать проекты, обновлять unit'ы, менять статусы, загружать ассеты. Полный admin power через диалог.
Что конкретно нужно сделать (7)
- Tools для write-операций: create_project, update_unit, set_unit_status, upload_floor_plan, create_team_invite, update_pricing и т.д.
- Permission checks per tool (учитывает 5-level access из 1.2.7)
- Idempotency для write-операций (защита от повторных вызовов)
- Audit log per write-операция (см. 3.3.3)
- Confirmation flow для destructive операций (delete project требует подтверждения)
- Bulk-operations API (важно для use case «обнови статусы 40 юнитов»)
- Streaming progress для long operations (upload, processing)
Открытые вопросы (3)
- ❓ Эстимейт от Ильи — определяет где остаётся (Стадия 1 vs 2)
- Confirmation для destructive: текстовое подтверждение Claude'у или second factor?
- Bulk-операции: одна tool с массивом или итерация Claude-side?
Зависит от: 1.5.2 · Блокирует: —
1.5.4Authentication + scoped tokens[BL]
КритичноTech+Security⏱
Безопасная аутентификация для MCP. Token для конкретной студии, ограниченный по permissions, ротируемый.
Что конкретно нужно сделать (7)
- Token issuance UI в admin (studio admin генерит per-MCP-client token)
- Scope: read-only / read+write, optional per-project scope
- Rotation: можно отозвать, перевыпустить
- Expiration: настраиваемая (дни / месяцы / never)
- Storage on user side: Claude Desktop config / Cursor settings
- Logging: каждый MCP-call с token id (для аудита и rate limiting)
- Brute-force protection (rate limit, unusual patterns alerts)
Открытые вопросы (2)
- Token format: JWT / opaque / OAuth2?
- Refresh tokens или просто long-lived tokens с rotation?
Зависит от: 1.8.1 (tenant isolation), 1.2.7 (permission model) · Блокирует: 1.5.2, 1.5.3
1.5.5Documentation + integration examples[BL]
ВысокийTech+Marketing⏱
Документация для разработчиков и студий — как подключить наш MCP server к Claude Desktop, Cursor, другим MCP clients.
Что конкретно нужно сделать (7)
- Quickstart guide: «Подключи offplan.online к Claude за 5 минут»
- Setup для Claude Desktop (config.json)
- Setup для Cursor / другие MCP clients
- 10 примеров запросов: «list available 2BR units», «show me sales report for last month», «update unit status», «create new project»
- Video walkthrough (Loom)
- Best practices: что НЕ нужно делать (например, не давать токен с write правами в shared environment)
- Troubleshooting
Открытые вопросы (2)
- Hosted docs vs README на GitHub?
- Public examples repo с типичными scripts/prompts?
Зависит от: 1.5.2, 1.5.4 · Блокирует: —
1.5.6AI file upload endpoint (PDF → JPEG splitter)[BL]
ВысокийTech⏱
Endpoint для drop-folder workflow Phase 1.2 Object Builder — клиент кладёт folder с PDF брошюрами / floor plans / gallery документами → AI разбивает каждую страницу в отдельный JPEG + авто-категоризация под Floor Plans / Gallery / Brochure. Используется Quick Build flow (1.2.4 «Drop a folder — AI tags pages»). Source: CONV-15 Roman call.
Что конкретно нужно сделать (5)
- Multipart upload endpoint (folder = ZIP / multi-file form)
- PDF page extraction → individual JPEG images per page (Ghostscript / pdf2image / PyMuPDF)
- AI classifier: floor plan vs render vs brochure vs lifestyle (vision model или metadata heuristics — TBD)
- Storage: уже-organised в S3 buckets per project + section
- Progress streaming: WebSocket / SSE для UI feedback во время processing
Открытые вопросы (3)
- ❓ AI classifier — на чьей инфраструктуре (VV backend / OpenAI / Anthropic)? Cost vs accuracy.
- ❓ Manual override — что если AI неправильно категоризовал страницу? (per-page edit UI в Object Builder)
- ❓ Re-run classifier — если studio загрузила новый PDF, можно ли «повторить» tagging?
Зависит от: 1.5.2 (read-only baseline), 1.5.3 (write capability) · Блокирует: 1.2.4 (Object Builder Floor Plans drop-folder)
🟡 Conditional — требует верификации tech team на проде.
Большинство багов из UX-аудита воспроизводятся преимущественно на dev-окружении. Перед началом работ — Илья и tech team подтверждают какие из них реально на продакшене, какие dev-only.
Фаза 1.6Admin UX Critical Blockers [BL]
Прямой результат UX-аудита (CONV-7) + заметок из ручного тестирования. Баги, которые потенциально будут блокировать студий в первую неделю — после верификации tech team на проде.
1.6.1Form reliability
КритичноTech+QA⏱🔬
Формы работают непредсказуемо: ввёл-сохранил-пропало, ошибка валидации стирает работу, уникальность проверяется криво.
Что конкретно нужно сделать (4)
- React re-render wipes text inputs при изменении dropdown — переписать state management
- Units form: при попытке сохранить юнит с уже существующим названием — показывается ошибка, и одновременно сбрасывается весь введённый прогресс (все поля формы). Должна оставлять данные нетронутыми и показывать inline error на поле «название». ✅ Подтверждено на проде 2026-04-30.
- Sticky error messages
- Автотесты на form reliability в Playwright (CI)
Открытые вопросы (2)
- Используется ли form library (react-hook-form / formik) или raw useState?
- Готовы переписать form architecture или только точечные fix?
Зависит от: — · Блокирует: 1.6.2
1.6.2Navigation + project creation path
КритичноTech+Design⏱🔬
Студия не может сама создать проект, post-save navigation прыгает на другой проект.
Что конкретно нужно сделать (3)
- UI для создания нового проекта (self-serve — сейчас отсутствует)
- Post-save navigation при создании building: не прыгать на другой проект (🔬)
- Project switcher — явно видимый, с «+ Create new project»
Открытые вопросы (1)
- Совместим ли project creation UI с multi-tenant лимитами по плану?
Зависит от: 1.6.1 · Блокирует: 1.2.4
1.6.3Asset upload clarity[BL]
Критично → возможно отпадаетTech+Design⏱
Tech team уже работает над backend-инфраструктурой, которая авто-обрабатывает любые форматы (PDF / HEIC / etc.). Если Илья подтвердит готовность — эта sub-phase может стать неактуальной. Дождаться апдейта. Текущее: неясно что можно загружать: PDF молча отвергается, размеры скрыты, форматы не указаны, preview нет.
Что конкретно нужно сделать (если backend не закроет) (7)
- Inline hints: «JPEG, PNG, WebP, до 5 MB» — рядом с кнопкой
- Floor plates: «PDF не поддерживается — конвертируйте в PNG (белый фон, ≤100 KB)»
- Panorama: «Spherical 360° JPEG, 2:1 aspect, 4096×2048»
- Welcome video: показать size limit явно
- PDF upload не должен silent fail — явное сообщение
- Click-to-preview на uploaded изображения (modal/lightbox)
- Сразу видеть thumbnail после загрузки
Открытые вопросы (2)
- Все лимиты известны команде? Если нет — нужен audit
- Когда backend выкатывает auto-обработку форматов (вопрос Илье)?
Зависит от: — · Блокирует: 1.6.4
1.6.4Preview + sticky validation UX
ВысокийTech+Design⏱
UX-улучшения поверх критичных блокеров — click-to-enlarge, valid validation feedback, предотвращение accidental loss.
Что конкретно нужно сделать (5)
- Click-to-enlarge на всех uploaded images
- «Unsaved changes» warning при попытке покинуть страницу
- Inline field validation (не ждать submit)
- Успешное сохранение — чёткий visual feedback
- Drag-and-drop upload с visual drop zone
Открытые вопросы (1)
- Cmd+S shortcuts для power users?
Зависит от: 1.6.3 · Блокирует: —
1.6.5Hotspot placement broken
КритичноTech⏱
На проде нельзя расставить hotspots на здании мышкой — клик/драг не регистрирует позицию. Блокер для любого проекта с building hotspots. ✅ Подтверждено на проде 2026-04-30.
Что конкретно нужно сделать (3)
- Починить mouse interaction в hotspot editor (click-to-place + drag-to-reposition)
- Visual feedback при наведении и активном dragging
- Регрессионный тест в Playwright (CI) — расстановка + перемещение
Открытые вопросы (1)
- Связано ли с canvas/SVG event handling или общей проблемой UI-слоя?
Зависит от: — · Блокирует: онбординг любого проекта с hotspots
Фаза 1.7Платёжная инфраструктура + Sales Page [OPL]
Студия проходит signup → trial → подписка полностью сама. Плюс публичная страница, которая продаёт. Помимо месячной подписки — flat-fee tier (оплата за настройку проекта + SLA на новые проекты), см. 1.7.8. Public Visibility + Stock allocation presets — спец живёт в Foundational §5 + §4.4; Phase 1.7 строит config UI и rendering layer (см. 1.7.12).
📌 v4.11 — CONV-27 (Chunk 7 deep rewrite):
- v4.3 (CONV-15 Roman call) + v4.4 (CONV-17 permission-and-tenancy) callouts absorbed в task body — 4 новых tasks (1.7.9 / 1.7.10 / 1.7.11 / 1.7.12) и updates в 1.7.1.
- Stock allocation toggle (was 1.7.EE in v4.4) — moved to Foundational §4.4; cross-link в phase desc, отдельная task'а нет.
- Public Visibility detail (was 1.7.BB in v4.4) — spec живёт в §5 + §5.1; Phase 1.7 keeps только config UI task (1.7.12).
- Stale resolved Q's в 1.7.5 + 1.7.7 — cleaned (resolved per §3 Trial / payments-research).
Sub-plan: plans/landing-pages-by-audience.md владеет 4-audience landing спекой. Plan: plans/stage1-chunk-7-phase17-rewrite.md.
1.7.1Landing pages (4 audiences)[OPL]
КритичноMarketing+Design⏱
📁 Мокапы (от 2026-04-29): v3 — выбранный (demo-led hybrid) · v1 · v2 · сравнение всех вариантов
Публичные landing pages на app.offplan.online которые конвертируют посетителя в trial signup. 4 audience-specific landings (general / studio / agency / developer) — каждой свой messaging и features. Детальная 4-audience спека — sub-plan plans/landing-pages-by-audience.md (status: stub, отдельная /plan-сессия после Wave 2).
Что конкретно нужно сделать (11)
- Hero: главный месседж + CTA «Start your 14-day trial — no card required» (см. §3 Trial period)
- Demo iframe embed pattern (CONV-15 Roman call: «нахрен убьёт конкурентов») — живой проект iframe'ом на странице, чтобы visitor сразу видел работающий продукт. Per audience: general → showcase project, studio → их собственный demo project (template), agency → multi-project view, developer → builder UX preview.
- Ценностное предложение (модули: Walkthroughs, floor plans, unit list, inline-editing roadmap)
- Кейс-стади с цифрами от реального клиента
- Сравнение с конкурентами (Matterport, Kuula) — честное
- Тарифные планы (prices, limits, features) — таблица
- FAQ (10-15 вопросов)
- Testimonials (после первых пилотных студий)
- CTA в нескольких местах
- Footer с Legal links (ToS, Privacy, DPA)
- Anonymous viewer rendering on per-Organisation sales page (
{slug}.offplan.online root) — Hero + branding + projects list (или скрыто per Public Visibility preset). «Request access» CTA для anonymous → отправка inquiry в Organisation-админку. Heart / «Связаться со мной» actions всегда hidden для anonymous (требуют buyer-token). Spec — §5.
Открытые вопросы (1)
- Стек (Webflow / Framer / Next.js)?
Зависит от: 1.7.2 · Блокирует: —
1.7.2Pricing plans[OPL]
КритичноProduct❓
Определить структуру тарифов для запуска. Фаза 4.2 — оптимизация; сейчас нужна базовая рабочая структура.
Что конкретно нужно сделать (4)
- 2-3 тарифа максимум (сложнее → хуже конверсия)
- Предварительная структура:
- Starter ~$99/мес: 3 проекта, 1 user, базовые фичи
- Studio ~$299/мес: 10 проектов, 5 users, Walkthroughs, Analytics
- Agency ~$699/мес: Unlimited, API, Priority support
- Enterprise: custom
- + Project-based (flat-fee): см. 1.7.8
- Trial: 14 дней T1 без карты (Path A signup, см. §3 Trial period)
- Annual discount (отложить в Фазу 4.2)
Открытые вопросы (3)
- ❓ Финальная цена и лимиты (→ ADR 0008 Skeleton — pricing defers to sub-plan
onboarding-trial-mode.md) - ✅
Trial без карты vs с картой — resolved (CONV-24): без карты, 14 дней T1 (см. §3 Trial period) - ❓ По проектам / рендерам / seats? (→ ADR 0008 Skeleton — limits defer to sub-plan)
Зависит от: — · Блокирует: 1.7.1
1.7.3Payment integration (multi-provider per phase)
КритичноTech+Legal⏱
📁 Ресерч: Stripe / Paddle / Checkout.com — детальное сравнение (валюты, комиссии, MoR, VAT, webhook coverage)
Платёжная инфраструктура с multi-provider стратегией по фазам — Stripe primary, Paddle + Checkout.com добавляются позже под конкретные рынки.
Что конкретно нужно сделать (7)
- ✅ Стратегия (resolved per payments-research): Стадия 1 — Stripe primary (USD / EUR / AUD; контроль, низкие комиссии, EU VAT сами). Стадия 2 — + Paddle (EU B2C через MoR — снимает VAT). Стадия 3 — + Checkout.com (UAE AED — Paddle не поддерживает AED).
- Subscribe flow (card capture или delayed-card trial)
- Webhook handler: subscription.created → активация, subscription.deleted → downgrade/block (см. 1.7.6)
- Retry logic для failed payments (базовый; dunning — Фаза 4.2)
- Test mode для staging (per provider)
- PCI compliance: никогда не видим номер карты (Stripe Checkout / Elements; Paddle hosted; Checkout.com Frames)
- Provider abstraction: единый internal API над несколькими providers (для smooth добавления Paddle / Checkout позже)
Открытые вопросы (1)
- ✅
Stripe vs Paddle — решение до начала работы — Решено: multi-provider per phase (Stripe primary в Стадии 1; Paddle + Checkout.com в Стадиях 2-3)
- Существующие Stripe / Paddle / Checkout аккаунты или заводим?
Зависит от: 1.7.2 · Блокирует: 2.6.4
Перенесено в Стадию 2: 1.7.4 Self-service billing UI → теперь
2.6.4.
Для пилота (бесплатный, 20 студий) self-service UI не нужен; студии становятся paying только в момент Pilot→Paid transition. UI логично делать там, где он реально активируется — в Фазе 2.6.
1.7.5Trial mechanics
КритичноProduct+Tech❓
Как работает 14-дневный trial — активация, limits, истечение. Mechanics locked в §3 Trial period (CONV-24); эта таска = implementation против фиксированного спека.
Что конкретно нужно сделать (6)
- Активация автоматом при signup (без карты?)
- Лимиты в trial: как Starter или урезанные?
- Банер «X дней до конца» в админке
- Email reminders: за 14/7/3/1 дня
- Поведение при истечении: block / read-only / downgrade
- Возможность продлить trial (кто решает — Operators (OPL admins) ручно?)
Открытые вопросы (0)
- ✅ Все Q's resolved через §3 Trial period (CONV-24): trial без карты, 14 дней T1, auto-downgrade к Free Guest read-only по истечении.
Зависит от: 1.7.3 · Блокирует: 2.6.4
1.7.6Webhook activation/deactivation
КритичноTech⏱
Надёжная обработка событий от платёжного провайдера.
Что конкретно нужно сделать (5)
- Idempotent handler (webhook может прийти дважды)
- Retry logic если endpoint упал
- Signature verification per provider (Stripe / Paddle / Checkout.com — у каждого свой webhook secret)
- Обработка всех критичных событий (subscription.created/deleted, invoice.payment_succeeded/failed, customer.updated)
- Logging каждого webhook для аудита
Открытые вопросы (1)
- Queue (RabbitMQ / SQS) или прямой handler?
Зависит от: 1.7.3 · Блокирует: —
1.7.7Billing edge cases (refunds / chargebacks / FX / tax invoices)
КритичноTech+Legal+Finance⏱❓
Набор edge-case сценариев биллинга, которые появляются сразу как только студия платит первый инвойс — refunds, chargebacks, multi-currency, tax-compliant invoicing.
Что конкретно нужно сделать (7)
- ✅ Refund policy (resolved): usage-based no-refund — B2B declaration убирает EU Consumer Rights Directive (14-day cooling-off неприменим), service commencement waiver (ToS §5), non-refundable если Projects created/published/shared (ToS §4.3). Опционально pro-rata account credit (не cash refund) для annual plans cancelled в первые 7 дней без созданных Projects.
- Refund flow: UI (self-serve или ticket?), approval, payment provider API integration (Stripe / Paddle / Checkout)
- Chargeback handling: webhook
charge.dispute.created → auto-freeze? Evidence submission (до 21 дня)
- ✅ Currency (resolved per payments-research): multi-currency — USD / EUR / AED / AUD; pay.offplan.online/<slug> страница с выбором валюты, маршрутизация к нужному provider
- Tax invoices: Cyprus VAT (19%), EU OSS, UAE TRN, AU GST 10%, compliant format per country
- Invoice numbering: sequential, compliant с local tax regulations
- Credit notes для refunds (не просто возврат)
Открытые вопросы (2)
- ❓ Chargeback handling — auto-freeze on dispute (per ADR 0006) или wait-and-see? Tentative: ADR 0006 default (auto-freeze) — accept unless reverted.
- ❓ Tax engine — Stripe Tax (built-in, US/EU/UK/AU coverage) / Avalara (mature, expensive) / Paddle handles (если provider Paddle)?
Зависит от: 1.7.3 · Блокирует: Стадию 2 (возможны refund-запросы)
1.7.8Flat-fee pricing tier (альтернатива subscription)
ВысокийProduct+Tech+Finance⏱❓
Альтернатива subscription — модель «оплата за настройку проекта + SLA». Сценарий: настроили проект один раз, контент почти не меняется, продажи идут с того что залито. Платить ежемесячно за продукт, который «просто крутится» — клиент не хочет.
Сценарий клиента (5)
- Студия покупает «настройку проекта» (one-time fee)
- Студия / Operator team настраивает проект на платформе (drag-and-drop, ~2 часа работы)
- Проект работает self-service
- Если нужны изменения — отдельный SLA: за фиксированную плату на новые проекты или за час работы на изменения существующих
- Никакой ежемесячной подписки
Что конкретно нужно сделать (6)
- Tier «Project-based» в pricing structure (рядом со Starter / Studio / Agency / Enterprise)
- One-time setup fee per проект (с лимитом изменений в месяц)
- SLA-tier: оплата за новые проекты + час работы для изменений (отдельный billing channel)
- Технически: subscription и flat-fee — разные billing flows в Stripe/Paddle (subscription vs invoice)
- В админке: tab «Project subscriptions» (per project) vs «Studio subscription» (общая)
- Решить: можно ли смешивать (одна студия с подпиской и flat-fee проектами)?
Открытые вопросы (4)
- ❓ Цена per проект (one-time): зависит от размера (юнитов / зданий)?
- ❓ Что включается в setup fee: количество правок, поддержка?
- ❓ SLA pricing: per-hour, per-incident, monthly retainer?
- ❓ Как студия / Operator team выбирает model в момент signup или per project?
Зависит от: 1.7.2, 1.7.3 · Блокирует: —
1.7.9Subdomain selection + Project URL structure
КритичноTech+Design⏱
При создании Organisation Owner выбирает subdomain (default {slug}.offplan.online). Validation: уникальность + reserved blacklist (app / api / admin / staff / www / blog / docs / help / support / status / auth / login / etc). Project URL — namespaced path: {slug}.offplan.online/projects/{project-slug}. Безопасно для будущих system pages (/login, /settings, etc.) которые не будут конфликтовать с project URLs.
Что конкретно нужно сделать (6)
- Subdomain input в Organisation creation form: real-time validation (availability check + reserved blacklist warning + format rules a-z/0-9/dash, 3-32 chars).
- Reserved blacklist в config (не хардкод) — расширяемо без релиза.
- Subdomain change UI в Organisation Settings (Owner / Admin) — после change: 30-day soft redirect от старого subdomain'а на новый, потом hard 410.
- Project slug input в Project creation form: validation (unique within Organisation + format rules) + auto-suggest from project name.
- Project URL pattern enforced на routing layer:
{slug}.offplan.online/projects/{project-slug} + system pages под app.offplan.online или namespaced под Organisation root но с reserved prefixes.
- Custom domain (Tier 2+) overrides default subdomain — см. 1.7.10.
Открытые вопросы (2)
- ❓ Subdomain change frequency limit (предотвратить abuse): hard cap «1 change / 90 days» или soft warning?
- ❓ После custom domain (1.7.10) — старый subdomain продолжает работать как fallback или disabled?
Зависит от: 1.3 (Tenancy) · Блокирует: 1.7.10, 1.10
1.7.10Custom domain self-serve flow + DKIM (Tier 2+)
ВысокийTech+Ops⏱
Tier 2+ feature — Organisation Owner подключает собственный domain (presentations.developer-x.com) вместо subdomain'а {slug}.offplan.online. Self-serve flow: wizard в Settings → Domain — Owner прописывает CNAME + DKIM записи в DNS своего регистратора, мы автоматически верифицируем. После activation: Sales App страницы рендерятся под custom domain; transactional emails (buyer presentations) уходят от {custom-domain}.
Что конкретно нужно сделать (7)
- Settings → Domain page (Owner / Admin only) — current domain status + «Connect custom domain» CTA.
- Domain wizard: 3 steps — (1) Owner вводит domain + paste запись «Add CNAME → ...» в clipboard; (2) Owner добавляет в DNS своего registrar'а; (3) Owner жмёт «Verify» — мы DNS-резолвим CNAME через 5 retry с exponential backoff.
- DKIM setup как часть wizard'а — auto-generate DKIM keypair, public key показываем Owner'у для копирования в DNS как TXT record.
- SSL/TLS provisioning automatic через Let's Encrypt (Cloudflare-fronted: API call → certificate within 5 min).
- Email sending updated — все transactional emails (presentation links, password resets) routes through Organisation's custom domain если configured (с fallback на default domain при failure).
- Domain change / removal flow — soft redirect (30d) от старого custom domain на default subdomain.
- Tier-gating — feature available только для Tier 2+ subscriptions; Tier 1 / Free Guest получают upgrade modal при попытке connect.
Открытые вопросы (1)
- ✅
Email sender architecture — single-domain vs per-org domain? Resolved CONV-36: ADR 0011 ratified — Resend Stage 1 ESP + 2 own domains audience split (offplan.online customer-facing transactional / offplanonline.com buyer-facing fallback reserved-dormant Phase 1.2; verify-both-now phasing). Decision #1 only. Decision #2 (Tier 2+ per-Org white-label client-domain sending) DEFERRED to follow-up ADR when this task (1.7.10) reaches /plan.
- ❓ Multiple custom domains per Organisation (apex + www + presentations.x.com) или single? — Phase 1.7.10 ratification scope (Decision #2 ADR follow-up).
- ✅
Two-domain setup для team-side roles split? Resolved CONV-36: offplan.online = customer-facing transactional (PRIMARY active sending — 7 trial cascade + signup verify + billing receipts + tier transitions); offplanonline.com = buyer-facing fallback (DORMANT Phase 1.2, активируется когда Tier 1 buyer-facing presentation invites ship Phase 1.7+). Roles ratified via ADR 0011 CONV-36 audience split.
Зависит от: 1.7.9 (Subdomain), 1.8.6 (Transactional email),
ADR 0011 ratified CONV-36 (Resend + 2 own domains audience split; Decision #2 white-label deferred to Phase 1.7.10 follow-up ADR) · Блокирует: —
1.7.11Free tier billing tracking
ВысокийProduct+Tech❓
No-charge tier для guest organisations (§1 Free Guest) — billing запись не выставляет invoice'ы, но всё равно tracked в billing system для metrics + conversion analytics («N Free Guest Orgs converted to paid в этом месяце»). Detailed scope (limits / expiry / conversion triggers) — see ADR 0008 (Skeleton — structure ratified, numbers/limits defer to sub-plan onboarding-trial-mode.md).
Что конкретно нужно сделать (numbers from sub-plan onboarding-trial-mode.md) (4)
- Billing system schema — tier
free_guest вместе со starter / tier_1 / tier_2 / tier_3_enterprise (per ADR 0008).
- Conversion funnel tracking — events «free_guest_signup» / «free_guest_to_paid» / «free_guest_churned».
- Free tier limits enforcement (лимиты на проекты / units / seats — exact numbers per sub-plan, structure per ADR 0008).
- Upgrade modal — trigger conditions per ADR 0008 + sub-plan (e.g., «trying to create 2-й project as Free Guest»).
Открытые вопросы (1)
- ❓ ADR 0008 open questions — Free tier limits (projects / units / seats), expiry policy (do Free Guest accounts expire?), conversion triggers (lazy «attempt to upgrade» или active «trial expired»?). ADR 0008 ratified Skeleton; numbers/limits defer to sub-plan
onboarding-trial-mode.md.
Зависит от: 1.7.3 (Payment integration),
ADR 0008 (Skeleton — numbers defer to sub-plan) · Блокирует: Free Guest tier shipping
1.7.12Public Visibility — config UI + anonymous render
КритичноTech+Design⏱
Реализация Foundational §5 Visibility presets (Private / Discovery / Full sales / PIN-protected) + §5.1 PIN-protected detailed spec. Spec живёт в Foundational — этот task = build против фиксированного спека. Two parts: (1) config UI для Owner / Admin (set preset per-project в Project Settings + Object Builder), (2) anonymous render на sales-page ({slug}.offplan.online/projects/{project-slug}) согласно selected preset.
Config UI (admin side) (4)
- Project Settings → Public Visibility section — radio с 4 presets (Private / Discovery / Full sales / PIN-protected) + preview text для каждого.
- PIN-protected — раскрываются 4 conditional fields (PIN required min 4 char, After-PIN view Discovery|Full sales, Contact email required, Contact phone optional) — см. §5.1.
- Same UI surface в Object Builder при создании проекта (default Discovery; Owner может сразу выбрать).
- Audit log entry на каждое изменение Public Visibility (audit visible to Owner / Admin / SM per §4.2).
Anonymous render (sales-page side) (5)
- Routing middleware: anonymous request → check Public Visibility preset:
- Private → 404 (project не существует для анонимных)
- Discovery → renders Hero + branding + projects list (без цен), heart / inquiry CTAs hidden
- Full sales → full content (renders + 360° + цены); inquiry CTA visible но требует buyer-token для submit
- PIN-protected → blur + PIN entry overlay (см. §5.1 routing sequence)
- «Request access» CTA для Discovery — отправка inquiry в Organisation-админку (creates lead).
- Buyer-token bypass'ит Visibility preset (per §7.4 Visibility flip с active tokens).
- Visibility flip с active tokens — existing tokens работают по своему правилу до 90d expiry, anonymous получают новый preset (см. §7.4 D).
- Heart / «Связаться со мной» actions — всегда hidden для anonymous, require valid buyer-token.
Открытые вопросы (2)
- ❓ «Request access» в Discovery preset — куда ведёт inquiry? Generic Organisation contact email или per-project contact (как в PIN-protected)? Скорее всего Owner email (как PIN-protected default).
- ❓ Stage 2 — granular per-field overrides (показать прайс но скрыть availability, etc) — сейчас deferred per §5.
Зависит от: 1.3 (Tenancy), 1.10 (Sales App routing), Foundational §5 + §5.1 (ratified) · Блокирует: —
🔴 Critical (приоритет повышен 2026-04-30, ревизия структуры).
Перенесена из 1.9 в 1.8 — Security должна идти раньше Legal: 1.8.1 (Tenant isolation) блокирует 1.9.3 (DPA), 1.8.4 (Backup) определяет SLA в ToS, 1.8.6 (Transactional email) обязателен для signup verification. Tech team работает параллельно с момента старта проекта.
Фаза 1.8Security & Infrastructure Foundation
Foundation для всего остального — без этой фазы нельзя давать продукт клиентам. Tenant isolation, rate limits, error tracking, backups, DDoS protection, transactional email — параллельный трек tech team с дня один.
1.8.1Tenant isolation audit & hardening
КритичноTech⏱❓
Audit существующей изоляции между студиями и fix любых найденных gaps. Студия A не должна видеть данные, медиа или метаданные студии B ни через UI, ни через API, ни через direct media URL, ни через search/autocomplete endpoints.
Что конкретно нужно сделать (6)
- Документировать как сейчас работает изоляция (database-level / application-level / оба?)
- Аудит каждого API endpoint на cross-tenant leak (включая GET/LIST с фильтрами)
- Аудит storage: могут ли медиа-URL одной студии быть угаданы / перебраны
- Автоматические регрессионные тесты изоляции (добавить в CI)
- Penetration test (внутренний или внешний — см. открытый вопрос)
- Fix любых gaps + документация security posture для DPA
Открытые вопросы (2)
- ❓ Внешний audit (объективность) или внутренний (дешевле, bias)?
- ❓ Бюджет на pen-test если внешний?
Зависит от: — · Блокирует: 1.9.3 (DPA)
1.8.2Rate limiting infrastructure
КритичноTech⏱
Защита от злоупотреблений: массовая загрузка больших файлов, DDoS на API, brute-force на auth. Сейчас лимитов скорее всего нет или они базовые.
Что конкретно нужно сделать (7)
- API rate limits per IP (anonymous / authenticated / per tenant)
- Upload rate limits: max размер файла, max файлов в минуту/час, max concurrent uploads
- Login attempts: exponential backoff + temporary lockout
- Password reset: лимит per email в день
- Abuse detection: unusual patterns (1000 unit-creations за минуту)
- Dashboard для Operators (OPL admins) чтобы видеть текущее использование по tenant
- Настройки лимитов в конфиге (не хардкод) — тюнить без релиза
Открытые вопросы (2)
- Какие числа сейчас хардкоджены / где?
- Готовое (Cloudflare / Redis / nginx) или кастомно?
Зависит от: — · Блокирует: 1.2.1, Стадию 2
1.8.3Error tracking + alerting
КритичноTech+Ops⏱
Мы должны узнавать о проблемах раньше клиентов. Сейчас если API 500-ит, мы узнаём когда клиент пишет — это неприемлемо для SaaS.
Что конкретно нужно сделать (7)
- Sentry (или аналог) на frontend и backend
- Source maps для frontend чтобы ошибки читались
- Tagging по tenant / environment / release
- Alert routing: Slack/Telegram/email для разных severity
- On-call rotation — кто получает пейджинг ночью
- Dashboard: топ ошибок за день / неделю
- Integration с релизами
Открытые вопросы (2)
- Основной alerting канал (Telegram / Slack / email)?
- 24/7 on-call или только working hours?
Зависит от: — · Блокирует: —
1.8.4Backup & disaster recovery
КритичноTech+Ops⏱
Если БД упала или студия случайно удалила проект — должны уметь восстановить. Сейчас backup может быть есть, но никто не знает процедуру restore.
Что конкретно нужно сделать (7)
- Daily database backups (hourly для критичной БД?)
- Media backups (S3/bucket versioning + regular snapshot)
- Retention policy: daily 7 дней, weekly 4 недели, monthly 12 месяцев
- Restore drill — провести учения: полное восстановление из backup, замерить время
- Документированная процедура restore (runbook)
- RTO и RPO — формальные цели
- «Undelete» для студий — grace period 30 дней на восстановление удалённого проекта
Открытые вопросы (2)
- Где хранить off-site backup (другой регион / провайдер)?
- RTO приемлем для пилота / для публичного?
Зависит от: — · Блокирует: 1.9.1 (SLA в ToS)
1.8.5DDoS / abuse protection
КритичноTech⏱❓
На публичной стороне (страницы проектов) и на admin — защита от volumetric attacks, bot scraping, credential stuffing.
Что конкретно нужно сделать (6)
- WAF (Cloudflare / AWS WAF / альтернатива)
- CDN-based DDoS protection для публичных страниц
- Bot detection на signup / login (reCAPTCHA / hCaptcha / Turnstile)
- IP reputation blocking (tor exit nodes, known abuse)
- Анти-scraping на публичных API (headers, patterns)
- Мониторинг необычных трафик-паттернов
Открытые вопросы (2)
- ❓ Cloudflare Pro/Business/Enterprise — какой план покрывает нужды?
- ❓ Стоимость приемлема для 20 студий? Для 200?
Зависит от: — · Блокирует: Стадию 3
1.8.6Transactional email infrastructure[NEW]
КритичноTech+Ops⏱❓
Transactional emails (verify, invite, password reset, billing alerts) — фундамент signup и онбординга. Без надёжной доставки регистрация ломается на день один. Marketing/onboarding sequences отдельно — отложены в Стадию 3 (1.2.6). Это — только базовый transactional layer.
Что конкретно нужно сделать (7)
- Provider selection: SendGrid / Postmark / Resend / AWS SES — решение по deliverability + цене + UAE/EU compliance (Q8)
- Domain authentication: SPF, DKIM, DMARC настроены на отправляющих доменах
- Базовые шаблоны (5-7 минимум): email verification, team invite, password reset, welcome, billing alert (failed payment), trial ending reminder
- Bounce + complaint handling: webhook от provider → suppression list → не отправлять повторно на bounced/complained addresses
- Dev/staging/prod separation: в dev — sandboxed (не отправляются реальные emails); в staging — отправка только на whitelist
- Logging + retry: каждый отправленный email в логе с status; retry для transient failures
- Deliverability мониторинг: open rate / bounce rate / complaint rate dashboard, alerting на падения
Открытые вопросы (3)
- ❓ Provider — какой выбираем (Q8 в таблице)? SendGrid (дешёво, плохая репутация в EU); Postmark (отлично для transactional, дороже); Resend (молодой, modern API); AWS SES (дёшево, нужно настраивать самим)
- ❓ Отдельный домен для отправки (mail.offplan.online) или с основного?
- ❓ Multi-language шаблоны на старте или EN-only?
Зависит от: — · Блокирует: 1.2.1 (verification email), 1.2.7 (invites), 1.7.5 (trial reminders)
1.8.7Two-domain email setup
ВысокийTech+Ops⏱
offplan.online — для team-коммуникаций (sergey@, ilya@, support@). offplanonline.com — для system / transactional emails (welcome / verification / password reset / billing / suspension / etc.). Разделение reputation: маркетинговые / спам complaints не убивают transactional deliverability. Source: CONV-15 Roman call.
Что конкретно нужно сделать (4)
- Регистрация / verification
offplanonline.com (если ещё не сделана) — DNS records preparation
- Configure transactional ESP (per 1.8.6) от
noreply@offplanonline.com или per-feature subdomain
- Team email через
offplan.online (Google Workspace / Fastmail / etc.) остаётся primary inbox
- Documentation: какой email откуда отправляется — для studio support troubleshooting
Зависит от: 1.8.6 (transactional infra), 1.8.8 (DKIM/SPF/DMARC) · Блокирует: 1.2.1, 1.2.6, 1.7.5
1.8.8DKIM + SPF + DMARC для системных рассылок
КритичноTech+Ops⏱
Без правильно настроенного DKIM + SPF + DMARC всё уйдёт в спам — особенно у Gmail / Outlook (drastic increase в spam classification после Feb 2024 rules). Source: CONV-15 Roman call.
Что конкретно нужно сделать (5)
- SPF record на
offplanonline.com: разрешает только ESP IPs (Postmark / Resend / SES — per 1.8.6)
- DKIM key generation + DNS publishing (per ESP setup)
- DMARC policy:
p=quarantine initially → p=reject после первой недели monitoring
- DMARC reporting endpoint (aggregate + forensic) — настроенный inbox или 3rd-party tool (postmark-dmarc / dmarcian)
- Custom domain emails (Tier 2+) — automated DKIM keypair + DNS records generation per studio (см. 1.7.10)
Зависит от: 1.8.7 · Блокирует: 1.8.6 (production sending)
1.8.9Hosting cost projection model
СреднийFinance+Tech⏱
Финансовая модель hosting расходов на 100 / 500 / 1000 Organisations — для unit economics + tier pricing decisions (ADR 0008 Skeleton — pricing defer to sub-plan). VV сейчас платит ~$900/мес AWS на текущем deployment. Нужна модель «cost per Organisation» на 3 уровнях scale, чтобы pricing tier coverage costs + healthy margin. Source: CONV-15 Roman call.
Что конкретно нужно сделать (5)
- Audit current AWS spend (RDS, EC2/Fargate, S3, CloudFront, Cloudflare, ESP, monitoring)
- Per-Organisation breakdown: storage (renders/photos avg), DB (rows/queries), bandwidth (sales-app traffic), email (transactional volume)
- Projection: 100 Orgs / 500 Orgs / 1000 Orgs — fixed costs (DB, monitoring) vs variable (storage, bandwidth, email)
- Cost per Organisation в каждой scale point — input для ADR 0008 + sub-plan
onboarding-trial-mode.md (Tier model pricing finalisation)
- Sensitivity analysis: heavy-user Organisation (e.g., 20 projects, 500 units, 100 buyer-records/мес) vs light user
Зависит от: — · Блокирует:
ADR 0008 + sub-plan
onboarding-trial-mode.md (Tier model pricing finalisation)
Было: 1.1.6 Secrets management + key rotation (старая нумерация).
Перенесено в Стадию 3 — Фаза 3.5.4.
Для пилота .env + CI env vars достаточно; Vault / AWS Secrets Sales Manager имеет смысл до публичного запуска, а не до пилота.
🔴 Critical · 🇨🇾 Cyprus base (decided 2026-04-30).
Основное юрлицо — Cyprus (EU member, 12.5% corp tax, GDPR-native). На Cyprus base накладываются UAE и Australia compliance layers (1.9.7, 1.9.8).
Черновики всех 11 документов написаны —
📋 Legal Documents (index). Источники: AU clauses из
VV T&Cs; EU/UAE layers из публичных шаблонов —
📖 Legal Sources & References.
Фаза 1.9Legal & Compliance [OPL]
Юридическая база для Cyprus-base SaaS, продающего в EU / UAE / Australia. Черновики всех 11 документов написаны — юрист доводит. Cyprus / EU GDPR-native; UAE clauses для UAE-резидентов; AU clauses для AU studios.
📌 Ratified legal multi-party + privacy decisions (CONV-15 + CONV-17) — детали в sub-plan
Полная spec — plans/legal-multi-party-framework.md (status: stub, awaits lawyer review + /plan ratification). Ratified additions to Phase 1.9 (4 multi-party documents + 5 privacy clauses): Permission delegation framework (правовое основание делегации A→B, без этого Phase 1.3 нелегальна) · Multi-party access agreement template (developer ↔ agency ↔ agent цепочка) · Data ownership matrix per actor type (project / unit / buyer profile / presentation analytics) · Liability allocation при делегации · GDPR/ADGM right-to-erasure для buyer data (30d SLA, jurisdiction-agnostic, см. Foundational §7) · Reverse invite legal framework (Studio → Developer, Free Guest tier clauses, no project transfer Stage 1) · Buyer data export для KYC (платформа не собирает KYC сама, liability на Organisation) · Hosting region disclosure (EU-DC Stage 1: AWS Frankfurt / Cloudflare EU; cross-border language если ADGM pivot) · Audit log retention notice (referencing ADR 0004 v2 — 12mo active + 7yr Cyprus archive + pseudonymised actor_user_id для tax/anti-fraud + PII classification на JSONB metadata + insert-only DB role + monthly hash-chain seal). Phase 1.9 grows from 11 → 15 documents pending lawyer review.
CONV-34 v4.17 / v4.18 sub-plan gates anchored в legal sub-plan: (1) Reverse-invite legal basis (§ 1.4.C в permission-and-tenancy sub-plan) — ToS warranty-of-rights clause + rate-limit + mandatory unsubscribe footer + takedown route abuse@offplan.online; (2) Buyer joint-controller framework (§ 2.4.C controller_org_id annotation в audit_events) — GDPR Art. 26 joint-controller agreement template для developer ↔ agency ↔ agent цепочки.
Privacy schema jurisdiction-agnostic (Cyprus GDPR / ADGM 2021 / UAE Federal / DIFC — все GDPR-aligned). Generic privacy-policy templates Stage 1 (Iubenda / Termly), custom legal review Stage 2.
1.9.1Terms of Service
КритичноLegal
Основной договор между offplan.online и студией. Защищает от проблемных клиентов и кейсов.
📄 Наши черновики: Terms of Service · AUP · SLA · Reseller Agreement · NDA Template · 📖 База: AU clauses из volume.vision/sla-tcs; EU/UAE layers — Legal Sources & References.
Что конкретно нужно сделать (8)
- ✅ 3-уровневая структура: offplan.online Ltd / Customer (studio/agency) / End User (property buyer) — §1 Definitions
- ✅ Liability cap: 12 месяцев оплаты — §13.1
- ✅ Intellectual property: offplan.online Ltd владеет платформой и лицензорами — §8; Customer — своим Content — §7
- ✅ Termination: 14 дней на remedy нарушения → immediate termination; 30 дней экспорт данных → удаление по DPA — §15
- ✅ Acceptable Use Policy: via AUP (отдельный документ), incorporated by reference — §6
- ✅ SLA: 99.5% uptime, via SLA doc incorporated by reference — §11
- ✅ Dispute resolution: exclusive jurisdiction courts of Cyprus (не arbitration) — §17.1
- ✅ Change of terms: 30 дней written notice, opt-out через cancellation — §16
Открытые вопросы (0)
- ✅
Юрисдикция: UAE / EU / UK / AU? — Решено: Cyprus governing law, exclusive Cyprus court jurisdiction (§17.1)
- ✅
Multi-jurisdiction routing — один договор или версии per-country? — Решено: один ToS + jurisdiction-specific sections (AU в §15, UAE в Privacy Policy §12)
Зависит от: 1.9.5 · Блокирует: Стадию 2
1.9.2Privacy Policy
КритичноLegal
Как мы обрабатываем персональные данные студий и их конечных пользователей. GDPR + UAE DPR + Australian Privacy Act.
📄 Наши черновики: Privacy Policy · End-User Notice · 📖 Шаблоны: Stripe Privacy Policy (multi-jurisdiction), Cloudflare Privacy.
Что конкретно нужно сделать (7)
- Layered approach: common section + jurisdiction-specific (EU / UAE / AU)
- 2-уровневая структура: offplan.online — controller данных студий; студии — controllers своих клиентов
- Lawful basis per category: договор (биллинг), легитимный интерес (аналитика), согласие (маркетинг)
- Retention: активный аккаунт / 90 дней после cancel / логи 12 месяцев
- Права субъектов: access, erasure, portability, right to object/restrict (per jurisdiction)
- Sub-processors list (актуализируется)
- Breach notification: 72 часа (GDPR), 30 дней (Australian NDB), 72 часа (UAE federal DPR)
Открытые вопросы (2)
- Где хранить данные (регион)?
- Нужен ли DPO?
Зависит от: 1.9.5 · Блокирует: 1.9.3
1.9.3Data Processing Agreement (DPA)
КритичноLegal
GDPR Art. 28 требует DPA между controller (студия) и processor (offplan.online). Без DPA студия технически нарушает GDPR.
📄 Наши черновики: DPA · ROPA · Breach Procedure · 📖 Шаблоны: Cloudflare DPA (gold standard), Stripe DPA, Vercel DPA. EU SCCs — официальные шаблоны.
Что конкретно нужно сделать (6)
- Покрывает: категории данных, цели обработки, сроки хранения, locations
- Sub-processors: Stripe/Paddle, Hotjar/Clarity, email provider (1.8.6), CDN, error tracking, AWS
- Security measures: ссылки на Фазу 1.8
- Audit rights студии
- Breach notification terms (offplan.online → студия)
- Sub-processor changes: notice period, opt-out
Открытые вопросы (2)
- ❓ Self-serve DPA (click «принимаю») vs signed agreement?
- ✅
Termly / iubenda vs custom by EU GDPR-юрист? — Решено: написан собственный черновик DPA v0.1; юрист доводит наш draft, не пишет с нуля
Зависит от: 1.8.1, 1.9.2 · Блокирует: Стадию 2
1.9.4Cookie consent
КритичноLegal+Tech⏱
Banner на публичных страницах + в admin перед загрузкой analytics/marketing cookies. Cookiebot / OneTrust / iubenda — готовое решение, не custom.
📄 Наш черновик: Cookie Policy — 4 категории, таблица cookies, white-label guidance. Нужно привязать к выбранному consent platform.
Что конкретно нужно сделать (6)
- Banner перед загрузкой Hotjar/Clarity/GA
- Категории: necessary / analytics / marketing
- Reject all / Accept all / Customize
- Consent logged для аудита
- Работает и в admin, и на публичных страницах
- Готовое (Cookiebot / OneTrust / iubenda) vs custom
Открытые вопросы (1)
- Готовое vs custom — стоимость vs flexibility?
Зависит от: 1.9.2 · Блокирует: Фазу 2.4
1.9.5Cyprus incorporation & setup
КритичноLegal+Finance⏱
✅ Решено 2026-04-30: основное юрлицо — Cyprus. EU member state → GDPR-native (EU Representative по Art. 27 не нужен — мы сами EU). Corporate tax 12.5% (один из самых низких в EU), банкинг и incorporation services развиты. UAE/AU compliance накладывается сверху для соответствующих рынков (1.9.7, 1.9.8).
Что конкретно нужно сделать (7)
- Регистрация компании (private limited / LTD) — через corporate services provider (~€1,500-3,000 setup)
- Beneficial Ownership Register filing (Cyprus BO Register, обязательно с 2021)
- Open business bank account (4-8 недель compliance-heavy процесса; топ banks: Bank of Cyprus, Hellenic Bank, Eurobank Cyprus)
- Cyprus VAT registration (если threshold €15,600 пройдён) — VAT 19% standard, 9% reduced
- EU OSS (One Stop Shop) registration — если cross-border B2C ≥€10K (упрощает VAT через одну Cyprus декларацию вместо 27)
- Tax registration + accountant retention (annual return, social insurance, IR4 form)
- Apostille / certified company documents для open accounts на других платформах (Stripe, Paddle)
Что НЕ нужно делать (Cyprus benefits) (3)
- EU Representative — не нужен (сами EU per GDPR Art. 27)
- Multiple VAT registrations — EU OSS заменяет 27 регистраций одной
- Adequacy decisions для transfer данных в EU — мы сами destination, не source
Открытые вопросы (3)
- ❓ Corporate services provider — кто (Eurofast / Oneworld / Vistra / local Cyprus firm)?
- ❓ Bank — Bank of Cyprus / Hellenic / Eurobank / EU neobank типа Wise Business?
- ❓ Substance requirement — где работают директора (для tax residency должна быть Cyprus management & control)?
Зависит от: — · Блокирует: 1.9.1, 1.9.2, 1.7.3, 1.9.6
1.9.6VAT / GST registration
ВысокийLegal+Finance❓
Регистрация по VAT/GST. Cyprus base упрощает EU-часть — через EU OSS одной декларацией покрываем все 27 EU-стран.
⚠️ Cyprus упрощения: Cyprus VAT (19%) — basic registration; EU OSS на Cyprus покрывает cross-border B2C во всех 27 странах через одну декларацию. Если выбираем Paddle (MoR) в 1.7.3 — UK/UAE/AU regs снимаются (Paddle handles). Если Stripe — нужны UK/UAE/AU отдельно. См. Legal Sources — VAT.
Что конкретно нужно сделать (5)
- Cyprus VAT (19%) — local registration (threshold €15,600 — обычно сразу)
- EU OSS — после €10K cross-border B2C threshold; одна декларация на все 27 EU-стран (Cyprus упрощение)
- UK VAT — после £90K threshold (или Paddle handles)
- UAE VAT (5%) — если есть UAE B2B (или Paddle handles)
- Australia GST (10%) — если AU B2B ≥AUD 75K (или Paddle handles)
- Invoice template per-jurisdiction (Cyprus EU-format, UAE TRN, Australian ABN)
Открытые вопросы (2)
- ❓ Реалистичная география первого года (EU-only / +GCC / +AU / global)?
- ❓ Paddle (MoR — снимает регистрации) vs Stripe (комиссия ниже, но регистрации сами)?
Зависит от: 1.9.5 · Блокирует: —
1.9.7Australian compliance (GST + APP)[NEW]
ВысокийLegal
Адаптация AU compliance — Privacy Act 1988 (Cth), 13 Australian Privacy Principles (APP), Notifiable Data Breach scheme, Spam Act, Australian Consumer Law, GST 10%. База готова — VV уже работает в AU и имеет полные T&Cs.
📄 AU-покрытие в черновиках: Privacy Policy §11 (AU Privacy Act 1988, 13 APPs, NDB scheme) · ToS §15 (Australian Consumer Law, GST) · 📖 База: volume.vision/sla-tcs — готовые AU clauses. Эстимейт адаптации: 1-2 недели.
Что конкретно нужно сделать (6)
- Адаптация Privacy Act 1988 (Cth) clauses из VV T&Cs — 13 APP compliance
- Notifiable Data Breach процесс — уведомление OAIC + affected individuals (per Privacy Act, max 30 дней)
- Australian Consumer Law (Schedule 2 of CCA 2010) — гарантии, ограничения ответственности
- Spam Act 2003 (Cth) — для marketing emails (consent + unsubscribe + sender ID)
- GST 10% handling — pattern из VV T&Cs (additional GST amount, GST-exclusive basis, tax invoices)
- AUD support в billing UI
Открытые вопросы (1)
- ❓ Если основное юрлицо не AU — нужен ли отдельный AU contract или достаточно AU clauses в общем T&Cs?
Зависит от: 1.9.5 · Блокирует: —
1.9.8UAE compliance (DPR / DIFC / ADGM)[NEW]
ВысокийLegal❓
UAE имеет 3 параллельных режима data protection — выбор зависит от 1.9.5 (юрлицо). Federal DPR (mainland), DIFC DP Law 2020, ADGM DPR 2021.
📄 UAE-покрытие в черновиках: Privacy Policy §12 (UAE PDPL notice, data subject rights) · 📖 Референсы: Property Finder T&Cs, Bayut Privacy, DIFC official guides. Legal Sources — UAE.
Что конкретно нужно сделать (5)
- Решение: какой режим (Federal DPR / DIFC / ADGM) — зависит от 1.9.5
- Privacy notices с UAE DPR clauses
- Notifiable breach процесс (UAE federal: 72 часа)
- AED support в billing UI + UAE TRN на инвойсах
- Если DIFC/ADGM — leverage GDPR-aligned формулировки (упрощает работу)
Открытые вопросы (2)
- ❓ Federal DPR vs DIFC vs ADGM (зависит от 1.9.5)?
- ❓ Данные UAE-резидентов хранить в UAE-region storage или допустимо EU/US?
Зависит от: 1.9.5 · Блокирует: —
🟠 Critical-conditional.
Архитектурное изменение sales-app — переход с хотспотов на filter-based выбор юнитов. MVP (1.10.1 фильтры) обязателен в Стадии 1. Остальные подзадачи переносятся в Стадию 2 или 3, если эстимейт от Ильи большой. Multi-source validation: фидбек Надежды (Dubai sales manager) + подтверждение Ромы — «не первый раз слышим, нужно было приоритизировать раньше».
Фаза 1.10Sales-app UX redesign — filter-based unit selection [OPL] [BL]
Sales-app переходит с хотспотов на филтры (bedrooms + view direction + price + ориентация). Текущий флоу — здание → хотспоты → юниты — ломается на больших проектах (300+ юнитов = 300 точек = хаос). Покупатели не выбирают по тому где квартира на фасаде — выбирают по типу, площади, виду, цене.
📌 v4.13 (CONV-30 sweep) — Wave 2 sales-app rendering implications:
- Sales-app middleware reads visibility / token / auth state и applies rendering per Foundational specs. Implications от Wave 2: (a) §4.6 View-as mode — render target user's stock-filtered view с persistent banner «Viewing as Иван — Exit»; (b) §5.1 PIN gate routing — least-to-most-invasive sequence (buyer-token / cookie / auth / blur+overlay); (c) §6.1 verification form UI + §6.2 3-channel send — button-driven status select with smart-match autocomplete, WhatsApp deep-link / Copy / Email; (d) §7.4 routing edges — Open pool optimistic lock 409 Conflict, Org-suspension read-only fallback, Visibility-flip token bypass до 90d.
- v4.3 (CONV-15) + v4.4 (CONV-17) placeholder content → absorbed в numbered tasks 1.10.8-1.10.14 ниже (360° rotation, Hotspot navigation, Buyer-aware pages, Anonymous pages, Status badge, Status change UI, Buyer attribution preservation). 1.10.X (3 access modes) covered by Phase 1.7.12 + §5 Visibility; 1.10.Y refinement (auth-scoped views per S·1) absorbed в 1.10.0 description.
Зависит от Phase 1.3 (ratified) и Phase 1.7 (Public Visibility settings). Buyer flow detailed в Phase 1.11 (Sales Presentation Layer).
1.10.0Login entry surface на sales-app (auth-scoped views) [NEW v4.5]
КритичноTech+Design⏱
Маленькая иконка в правом верхнем углу каждой страницы public sales-app ({slug}.offplan.online/projects/{project-slug} и все её sub-views — Exterior / Interior / Floor Plates / Gallery / Unit pages). Click → modal с Google / email login. После логина та же страница перезагружается в authed view с фильтрацией по S·1 stock allocation. Это primary entry point для Sales Agent / Sales Manager — они не идут через app.offplan.online/login, они логинятся прямо со страницы проекта.
Что конкретно нужно сделать (8)
- UI: persistent иконка top-right на каждой странице sales-app (header overlay). Anonymous = «Sign in» icon; Authed = avatar + dropdown (Organisation switcher + Logout)
- Login modal: Google primary + email/password fallback (re-use auth backend из 1.3.3). Re-use design Brandbook v2.
- Auth-scoped re-render: после успешного логина — same URL, page reloads в state #4 (Organisation team member). Server-side рендер в зависимости от viewer state. См. Foundational §5.
- Scope filtering: Sales Agent видит только assigned units (Closed pool S·1, см. §4.4) — фильтрация на уровне query layer, не client-side hide. Sales Manager / Content Editor / Admin / Owner видят полный сток.
- Cross-Organisation логин: если Client — member нескольких Organisations и логинится со страницы Organisation A — auto-resolve в context Organisation A (current subdomain). Organisation switcher в dropdown позволяет переключиться.
- Wrong organisation edge case: Sales Agent логинится на странице Organisation B, но он member только Organisation A — error «Вы не member этой организации. Открыть свою организацию →» (link на правильный subdomain).
- Logout: убирает session cookie (scoped
*.offplan.online), возврат к state #1 (anonymous) на той же странице.
- Buyer-token URL: если URL содержит
?b=<token> — login icon скрыт (buyer-flow не требует логина, см. state #2/#3 в §5).
Открытые вопросы (3)
- ❓ На Private preset (state #1 anonymous) — показывать иконку логина или прятать (login-wall стиль)?
- ❓ Mobile — иконка top-right остаётся persistent или убирается в hamburger menu?
- ❓ Должна ли иконка показывать notification badge (новые лиды для Sales Agent / pending invites для Owner)?
Зависит от: 1.3.3 (auth backend), 1.3.4 (stock tagging), 1.3.5 (auth-scoped routing) · Блокирует: 1.10.10, 1.10.11, 1.10.13
Правильный флоу (из звонка с Надеждой)
- Заходишь в проект → красивый лендинг (видео, 360°, галерея, виды)
- Клик «Apartments» / «Floor Plans»
- Фильтры: bedrooms (1BR / 2BR / 3BR / penthouse) + view direction (на море / город / парк) + price range + ориентация
- Показываются только подходящие floor plans
- Клик floor plan → вертикальный stack: все юниты этого типа на всех этажах, как меняется цена и вид по высоте
- Выбираешь конкретный юнит
1.10.1Filter-based unit selection (MVP — обязательно в Стадии 1)[BL]
КритичноTech+Design⏱❓
Filter-based выбор юнитов вместо хотспотов. Покупатель фильтрует по параметрам, видит подходящие варианты, выбирает. Минимум: фильтр по bedrooms + view direction + price + статус.
Что конкретно нужно сделать (7)
- Расширить существующий filter-component (сейчас только статусы): добавить bedrooms, view direction, price range, ориентация
- Filter UI: чекбоксы / sliders / dropdown — на боковой панели или в header
- Показывать только подходящие floor plans / units
- Counter: «X юнитов соответствуют фильтру»
- URL-параметры (shareable links:
?br=2&view=sea&price=1-2M)
- Reset filters
- Empty state: «нет подходящих» + suggest relaxing filter
Открытые вопросы (2)
- ❓ Эстимейт от Ильи — насколько готов текущий filter-component к расширению?
- Какие фильтры показывать по умолчанию vs скрытые в "more filters"?
Зависит от: — · Блокирует: —
1.10.2Floor plan → vertical unit stack view
ВысокийTech+Design⏱❓
Если сложно — переносим в Стадию 2. Когда пользователь выбрал тип floor plan, показать вертикальный стек: все юниты этого типа на всех этажах, как цена и вид меняется по высоте.
Что конкретно нужно сделать (5)
- Stack visualization: список юнитов одного типа, отсортированный по этажу (high to low)
- Per-unit info: floor number, price, view, status, area
- Дополнительно: сравнение по этажам (slider «slide up/down»)
- Click на юнит → unit detail page (existing)
- Альтернативный view: «show on floor plate» (где этот юнит на этажном плане)
Открытые вопросы (2)
- Visualization: list vs visual stack (вертикальная башня)?
- Производительность для 50+ floors?
Зависит от: 1.10.1 · Блокирует: —
1.10.3Per-project status visibility toggle
КритичноTech+Design⏱
Каждый проект может настроить, показывать или скрывать статусы юнитов (Available / Reserved / Sold). Некоторые девелоперы не хотят публично показывать sold-out (early-stage sales, prestige). Сейчас статусы хардкод — Надежда заплатила $12k чтобы их скрыть на одном проекте.
Что конкретно нужно сделать (5)
- Project setting: «Show unit statuses» (yes/no/partial)
- Если no — статусы скрыты на: building view, floor plate, unit list, unit detail
- Если partial — настраиваемо: показывать Available, скрывать Reserved/Sold
- Custom labels per project: «Available» → «Inquire», «Sold» → ничего, и т.д.
- Default: показывать (статус-кво для большинства)
Открытые вопросы (2)
- Granular: per-status custom labels или просто show/hide?
- Partial показывать «Inquire» или просто пустой статус?
Зависит от: — · Блокирует: —
1.10.4Status indicators redesign (kill traffic-light colors)
ВысокийDesign+Tech⏱
Текущие яркие зелёные/жёлтые/красные «светофоры» на статусах — выглядят дёшево и слишком навязчиво. Заменить на нейтральные tags. Уже частично в плане как 1.1.3 (Visual language refresh), но здесь explicit для sales-app side.
Что конкретно нужно сделать (3)
- Заменить bright dots на subtle tags (sand background + lower-saturation accent)
- Убрать "светофор" green/yellow/red в принципе — в дефолте no color, в alternative — gold/sand палитра (см. 1.1.3)
- Per-project visibility (см. 1.10.3) и кастомизация stays
Зависит от: 1.1.3 (visual language refresh — общая палитра) · Блокирует: —
1.10.5Window-based panoramic views
Средний-ВысокийTech+Content⏱❓
Если сложно — переносим в Стадию 3. Опциональная фича, сильно усиливает sales pitch. В floor plan можно кликнуть на конкретное окно — открывается 180°/270° панорамный вид из этого окна. Был в их Moscow-проекте, очень нравился клиентам. Сейчас в Abu Dhabi проекте отсутствует, Надежда сильно жалеет.
Что конкретно нужно сделать (5)
- В админке: для каждого юнита можно загрузить window-panoramas (180° для фасадных, 270° для угловых)
- В sales-app: на floor plan юнита окна — clickable
- Click → open panoramic viewer (existing 360° tech возможно reuse'нуть)
- Mobile-friendly (тач-управление)
- Pre-loading для smooth UX
Открытые вопросы (2)
- ❓ Контент-pipeline: как студия делает window panoramas? (renders / camera positions)
- Технически: 180°/270° viewer существует в текущей платформе или нужно с нуля?
Зависит от: 1.10.1, 1.10.2 · Блокирует: —
1.10.6Currency + units toggle (USD/AED, sqm/sqft)
ВысокийTech+Design⏱
Toggle для валюты и единиц измерения — критично для Dubai (часть рынка думает в sqft, часть в sqm; цены в USD vs AED).
Что конкретно нужно сделать (6)
- Header toggle: USD / AED (или другие per project)
- Header toggle: sqm / sqft
- Selection persists в session / localStorage
- Pricing API возвращает primary + conversion rates
- Sqm/sqft автоматический расчёт (фикс factor)
- Project setting: какие currencies доступны (одна / несколько)
Открытые вопросы (2)
- ❓ FX rates: snapshot per project (зафиксирован) vs live (обновляется ежедневно)?
- Default: какая валюта дефолтная — based on user IP / project setting?
Зависит от: — · Блокирует: —
1.10.7Custom Floor Plan section labels[BL]
СреднийTech+Design⏱
Возможность переименовывать названия секций в sales-app — у одних застройщиков "Units", у других "Apartments" / "Residences" / "Studios" / "Townhouses". Сейчас лейблы хардкоженые. Нужно сделать настраиваемыми per-project, чтобы студия могла подстроить терминологию под брендинг девелопера. В backlog у Ильи как «Custom Fields for Floor Plans» (Сергей: «это добавление возможности менять название в разделе, так как у кого-то юниты у кого-то апартаменты»).
Что конкретно нужно сделать (4)
- В admin: поля для переопределения лейблов на уровне проекта — label для unit / units list / floor plan section / unit type categories (1BR / 2BR / Studio / Townhouse)
- Sales-app использует переопределённые лейблы вместо хардкоженых
- Default fallback на текущие значения если поля не заполнены
- Опционально: i18n-aware лейблы (для будущей локализации в Фазе 4.4)
⚠️ Conditional
- Если эстимейт от Ильи > 2 недель — переносим в Стадию 2 вместе с остальными labelling / customisation работами (4.3.6).
Зависит от: — · Блокирует: —
1.10.8360° rotation на Exterior view (Pannellum / Marzipano)
ВысокийTech+Design⏱
Native 360° spherical rotation на Exterior view sales-app — port из VV если уже есть, иначе простая интеграция Pannellum или Marzipano (open-source WebGL viewers). Базовый walkthrough flow — full Kuula-replacement отложено в Stage 2 backlog. Source: CONV-15 Roman call + Сергей item #6 (вариант α: базовый в 1.10).
Зависит от: 1.10.1 (filter MVP) · Блокирует: 1.10.9
1.10.9Hotspot navigation между 360° сценами
СреднийTech+Design⏱
Базовый walkthrough — admin указывает hotspot pins на 360° сцене → click navigates на следующую сцену (Lobby / Pool Deck / Amenities). Используется в Foundational §5 / Phase 1.10 anchor badges flow. Full Kuula-replacement (transitions, depth, multi-floor navigation) — Stage 2 backlog. Source: CONV-15 Roman call.
Зависит от: 1.10.8 · Блокирует: —
1.10.10Buyer-aware unit pages (Variant E2)
КритичноTech+Design⏱
Каждая unit-страница детектит ?b=<buyer_token> query param и адаптирует UI: показывать атрибутированного Sales Agent'а как contact, активировать heart / «Связаться со мной» actions, applying buyer-context attribution к любому action'у. См. Foundational §6. Source: CONV-17 permission-and-tenancy ratification.
Зависит от: 1.3 (Tenancy ratified), Phase 1.11 (Buyer Profile) · Блокирует: 1.10.11
1.10.11Anonymous unit pages (no token)
ВысокийTech+Design⏱
Same URL без token = standard public preview per Organisation's Public Visibility preset (см. §5). Heart / «Связаться со мной» actions disabled, заменены на «Sign in to track favorites» / «Request access» CTAs. Source: CONV-17 permission-and-tenancy ratification.
Зависит от: 1.10.10, Phase 1.7.12 (Public Visibility config) · Блокирует: —
1.10.12Status badge rendering
ВысокийTech+Design⏱
На любой unit-page показ status'а (available / reserved / sold) per current visibility preset. Badges hidden в Discovery default, видны в Full sales. При reserved / sold — показать message + alternative units link. Anonymisable per project (см. 1.10.4 для status indicators design). Source: CONV-17 permission-and-tenancy ratification.
Зависит от: 1.10.4, 1.10.10, 1.10.11 · Блокирует: —
1.10.13Status change UI (manual flips per permission matrix)
КритичноTech+Design⏱
Sales Agent / Sales Manager / Admin / Owner меняют unit status (available ↔ reserved ↔ sold) вручную в админке per §4.2 permission matrix. Reason field optional. Audit log per change. Verification form UI (button-driven select + email-required + smart-match) — см. §6.1. Никаких system-managed timers / locks / reservation_request entity — Organisation решает когда менять status сама, reservation-процесс ведётся в его external CRM. Source: CONV-17 permission-and-tenancy ratification + CONV-26 verification form.
Зависит от: 1.3 (Tenancy + roles), §6.1 (verification form spec) · Блокирует: —
1.10.14Buyer attribution preservation (expired token redirect)
ВысокийTech⏱
После expired token (90d) — redirect на main project page сохраняет buyer-record attribution. Token decoder проверяет expiry status, не just presence. Buyer continues browsing as «attributed to Sales Agent X» (видно в admin / commission tracking). См. Foundational §6 — token mechanics. Source: CONV-17 permission-and-tenancy ratification.
Зависит от: 1.10.10, Phase 1.11 · Блокирует: —
Связи с другими фазами:
- 4.5.1 (Compare units) — связано: filter-based UX делает compare более ценным. Возможно подтягиваем 4.5.1 в Стадию 2.
- 3.3.3 (Audit log) — sales presentations в admin (для CRM integration) логгируются здесь.
- CRM integration depth (backlog для Стадии 2): во время разговора Надежды описана глубокая CRM-интеграция (Microsoft Dynamics) — отслеживать какие юниты показывались каким клиентам. Илья оценил в ~$100k. Не Стадия 1, но data model для "presentation events" нужно проектировать заранее.
Фаза 1.11
Sales Presentation Layer [OPL] [BL]
Buyer Profile + Remote Presentation. Buyer Profile — критическая UX-фича для сейлз-агентов (создание профиля во время встречи, лайки юнитов, summary email). Remote Presentation — real-time sync agent↔buyer device (Роман явно настаивал, но требует tech estimate Ильи).
💡 Sub-plans: plans/buyer-profile-and-presentation.md (subtasks 1.11.1-1.11.5) и plans/remote-presentation.md (subtasks 1.11.6-1.11.8 + ADR 0012). Если 1.11.6-8 не лезут в Stage 1 timeline — переносим в Stage 2.
📌 Ratified buyer-flow decisions (CONV-17 + CONV-24) — детали в sub-plan
Полная spec — plans/buyer-profile-and-presentation.md (status: stub, awaits /plan ratification). Ratified decisions for Phase 1.11.1-1.11.5 (Variant E2 = passwordless per-presentation): Buyer entity creation при отправке email'а Sales Agent'ом (identity = email + name + phone optional, token attribution → reserving SA, no global buyer accounts Stage 1, см. Foundational §6) · Email content composition (auto-summary + agent free-text editable + N tokenised unit-links per liked unit) · Token expiry handling 90d (buyer-record persists post-expiry, expired link redirects на main project page с preserved attribution) · Buyer self-service actions on unit-page (heart additional units + «Связаться со мной» CTA — notification к SA, не lock'ает unit) · Forward email handling (multi-session OK для shared token, rate-limit на «Связаться» submissions, audit log с IP+timestamp) · NO dedicated shortlist page Stage 1 (email = source of truth, central shortlist page → Stage 2) · Buyer schema (email, name, phone, agent_user_id FK, client_id FK, token_hash, created_at, expires_at, source_presentation_id; liked units в presentation_units table). v4.7 (CONV-24): Preview-as-Buyer (related but separate from §4.6 View-as-Agent) — кнопка в presentation builder перед «Send», render with тестовым preview-token'ом, heart / «Связаться» disabled (preview-only mode).
CONV-34 v4.17 buyer token security spec (§ 1.7.J в permission-and-tenancy sub-plan): ≥128-bit opaque CSPRNG token, hashed storage; scope = single (buyer, unit) pair (one row per unit, N units = N URLs, no org-wide / multi-unit tokens); 90d sliding window; forced rotation on SA loss / unit re-attribution / buyer email change / manual revoke; HTTP headers на buyer page response: X-Robots-Tag: noindex, nofollow, noarchive, nosnippet + Referrer-Policy: no-referrer + Cache-Control: private, no-store + Content-Security-Policy: frame-ancestors 'none'; buyer cookie scoped к single (buyer_id, org_id) request — никогда *.offplan.online; rate-limit 30 invalid hits / 10min per IP + burst alert. Suspension state: read-only до expiry, CTA disabled. Полная spec анкорена в plans/permission-and-tenancy-model.md § 1.7.J.
Зависит от Phase 1.3 (Tenancy ratified) — buyer entity model + permissions. Зависит от Phase 1.10 — buyer-aware unit pages.
📌 v4.12 (CONV-30 — parking lot для sub-plan):
- Agent-driven buyer onboarding с sales-page + persisted state. Второй путь buyer-record creation параллельный к существующему «email-send» (Variant E2): agent залогинен на sales-page → форма в panel'е (имя/фамилия/email/phone) → submit генерирует buyer-record + tokenised URL с already-persisted state (filters из Phase 1.10 + shortlist liked units). Buyer-side: открывает свою ссылку — видит filters + shortlist; может отдельно залогиниться (magic-link, расширение 1.11.5). Admin/agent-side: backup/restore buyer-state versions, toggle filters on/off на экране buyer'а, agent edits filters/shortlist уже-зарегистрированного buyer'а — open question: dual-login vs «Edit-as-Buyer» surface (extension §4.6 в обратную сторону) vs privileged-token URL. Detailed spec — `plans/buyer-profile-and-presentation.md` (sub-plan, ratify после Wave 2 close). Touches: §6 (второй путь creation), Phase 1.10 (filter persistence), Phase 1.3 (buyer auth), Phase 1.4 (backup/restore audit), §4.2 (permissions для buyer-state edit), §4.6 (Edit-as-Buyer extension if Option B chosen).
1.11.1Buyer entity + profile schema
ВысокийTech⏱
Buyer как сущность в системе. Profile: имя, контакты, предпочтения (тип юнита, этаж, вид, ценовой диапазон). Привязан к agent'у который его создал. Доступен через admin (сейлз-агент видит список своих buyers).
Зависит от: Phase 1.3 (Tenancy) · Блокирует: 1.11.2-1.11.5
1.11.2Profile creation UI (in-presentation)
ВысокийTech+Design⏱
Quick-form для сейлз-агента во время встречи: имя покупателя, что интересует. Можно обновлять preferences по ходу презентации (фильтры применяются live).
Зависит от: 1.11.1, Phase 1.10 · Блокирует: 1.11.4
1.11.3Heart / favorite units
СреднийTech+Design⏱
Сердечко/star на карточке юнита в sales-app. Лайки сохраняются в buyer profile. Видно сейлз-агенту в real-time (если remote presentation активна) и используется в summary email.
Зависит от: 1.11.1, Phase 1.10 · Блокирует: 1.11.4
1.11.4Summary email с deep-link
ВысокийTech⏱
После встречи — email покупателю с summary: что обсуждали, какие юниты понравились, контакты сейлз-агента. Ключевое: ссылка ведёт обратно в проект, уже отфильтрованный по preferences покупателя — он видит только релевантные юниты.
Зависит от: 1.11.2, 1.11.3, Phase 1.8 (Email infra) · Блокирует: —
1.11.5Buyer login (return flow)
НизкийTech⏱
Покупатель может вернуться через email-link и продолжить просмотр. Magic-link (без пароля) на email. Видит свой персонализированный view проекта.
Зависит от: 1.11.1 · Блокирует: —
1.11.6Remote session creation [needs-tech-estimate]
ВысокийTech⏱
Сейлз-агент в админке нажимает "Remote Presentation" → генерируется временный link → отправляется покупателю (email или ручной share). Session expires (1 час по дефолту).
Зависит от:
ADR 0012 (Real-time sync architecture, Shell — 4 architectures для Илья + команды), Илья estimate · Блокирует: 1.11.7
1.11.7Real-time state sync [needs-tech-estimate]
ВысокийTech⏱
Всё что сейлз-агент делает на своём экране — реплицируется у покупателя real-time. Polling / SSE / WebSocket / Managed (Pusher / Ably / Supabase Realtime) — 4 architectures расписаны в ADR 0012 для discussion с Илья + командой. State: текущий view (exterior/interior/floor plan), текущий unit, fillters.
Зависит от: 1.11.6,
ADR 0012 · Блокирует: 1.11.8
1.11.8Remote viewer rendering (mobile-first) [needs-tech-estimate]
ВысокийTech+Design⏱
Покупатель смотрит remote-сессию обычно с телефона. Optimised view: large touch targets, simplified UI, no edit controls. Может ставить лайки на юниты live.
Зависит от: 1.11.7 · Блокирует: —
⚠️ Open questions · v4.18 · CONV-34 (обновлено · 3 из 7 tech-questions resolved)
Нерешённые вопросы — для обсуждения с Романом и Ильёй
Эти вопросы не блокируют ratification Phase 1.3 (foundational decisions закрыты + SPEC-AMEND v4.17/v4.18 closed CONV-34), но требуют решения до final tech-estimate'а от Ильи и до launch'а Stage 1. Resolved вопросы помечены ✅ ниже с указанием куда ушла spec.
PRODUCT · parked
Jurisdiction: Cyprus vs Abu Dhabi (ADGM)?
Текущее decision (per memory/project_legal_entity_cyprus.md): Cyprus entity (12.5% corp tax, EU member, GDPR-native, no EU Rep needed). Sergey contemplating Abu Dhabi (ADGM) alternative — contemplating only, не reconsidering.
Privacy schema jurisdiction-agnostic — работает в Cyprus GDPR / ADGM 2021 / UAE Federal / DIFC (все GDPR-aligned, никаких переписываний). См. Foundational §7 — Multi-jurisdiction compliance.
Если pivot to ADGM в будущем — повлияет на: plans/onboarding-trial-mode.md + ADR 0008 (pricing/tier billing entity), Stripe entity name, contract templates governing law clause, hosting region (G.4.b EU-DC default может измениться на ME-DC). Резолвить отдельным ADR / сессией с Романом, не в Phase 1.3.
TECH · 7 unknowns для Ильи · обновлено CONV-34 (3 resolved · 4 остаются)
Tech architecture questions для Ильи
Это не product decisions, а технические development unknowns. Изначально 7 вопросов от CONV-17; после ratification Phase 1.3 sub-plan (CONV-32/33) + SPEC-AMEND v4.17/v4.18 (CONV-34) + ADR 0011 ratification (CONV-36) — 4 из 7 имеют spec и помечены ✅ resolved ниже. Оставшиеся 3 (Q1 wildcard SSL · Q5 Super Admin Panel stack · Q7 existing VV API inheritance) нужны Ильe до final estimate'а на Phase 1.3.
| # | Вопрос | Влияет на |
| 1 | Wildcard SSL для *.offplan.online — Cloudflare-managed или AWS ACM? | D.1 custom domain setup (CNAME + SSL provisioning per-Organisation) |
| 2 ✅ | Multi-tenant DB strategy — single DB с client_id columns + Row-Level Security, или DB-per-tenant? Resolved CONV-31: single DB с org_id scoping per ADR 0009 (Tenancy & Permission Architecture, Full spec). Row-Level Security рекомендуется на query layer. | Phase 1.8 tenant isolation — теперь spec'd |
| 3 ✅ | Token storage / hashing strategy — bcrypt? plain в DB? Different для invitations vs buyer-tokens? Resolved CONV-34 v4.17: opaque ≥128-bit CSPRNG, **hashed (SHA-256)** в DB column `token_hash`; raw token только в email URL; constant-time hash compare на lookup; per-IP rate-limit. Spec: plans/permission-and-tenancy-model.md § 1.4.D (invite tokens) + § 1.7.J (buyer tokens — отличаются scope-to-(buyer,unit) + forced rotation rules). | Security surface — spec'd |
| 4 ✅ | Magic-link email delivery — какой transactional email provider (SendGrid / Postmark / SES / Resend)? Resolved CONV-36: ADR 0011 ratified — Resend Stage 1 ESP; 2 own domains audience split (offplan.online customer-facing transactional + offplanonline.com buyer-facing fallback reserved-dormant Phase 1.2); verify-both-now phasing; task card T1-T7 в ADR body. Decision #2 (Tier 2+ white-label client-domain) deferred к Phase 1.7.10 follow-up ADR. | Domain rep / DKIM setup — spec'd |
| 5 | Existing Super Admin Panel — на каком стеке? Reuse его auth-логику для operator dashboard, или строим новую? | Phase 1.4 dependency, влияет на 1.3.3 (multi-role auth) estimate |
| 6 ✅ | Real-time sync для unit status (available ↔ reserved ↔ sold) между Sales Agent'ами — WebSocket / polling / Pusher? Resolved CONV-31: 4 architectures расписаны в ADR 0012 Shell для discussion с Илья + командой. Conflict UX (first-click-wins + pessimistic lock 500ms timeout fall-through) — spec'd в § 1.7.E + § 1.7.F. Implementation choice остаётся за тех-командой. | Phase 1.10 / 1.11 — UX поведение spec'd, transport layer открыт |
| 7 | Existing VV API — какие endpoints мы инхеритим, какие переписываем для multi-tenant модели? | Foundational scope question, всегда у Ильи |
Новые вопросы CONV-34 v4.18: (8) Stripe customer object retention policy при Free Guest auto-downgrade (см. ADR 0013 proration + § 1.8.B Stripe customer cleanup); (9) Audit log monthly hash-chain seal performance at scale (1.8-7.3M rows/year — см. Phase 1.3 sub-plan § Architectural risks); (10) MCP wrapper auth + prompt-injection sanitisation full spec (ADR 0014 placeholder — Phase 1.5.6 implementation gate).
DEFERRED · separate /plan
Pricing tier specifics — отдельный plan
Phase 1.3 закрыла структуру billing (Модель 4 — каждая Organisation подписана на свой tier, Free Guest tier exists, conversion path lazy) + qualitative shape 3 paid tier'ов (Tier 1 / Tier 2 / Custom — см. Foundational §3). Конкретные цены / лимиты per tier — отдельный /plan onboarding-trial-mode + ADR 0008 (Skeleton ratified CONV-31; numbers defer to sub-plan). Зависит от Phase 1.3 ratification (теперь готово), Romana input на pricing strategy, и payment-research результатов (payments-research.html).
⚠️ Naming namespace TBD: в плане сейчас сосуществуют два набора имён — «Tier 1 / Tier 2 / Custom» (Foundational §3, glossary) и «Starter / Studio / Agency / Enterprise» (фаза 1.7.8 в research-контексте). ADR 0008 + sub-plan onboarding-trial-mode.md должны выбрать один и привести план к консистентности. До тех пор Tier 1/2/Custom = scaffolding, не финальные имена.
Фаза 2.1Дизайн пилотной программы
Пилот — не «бесплатный доступ», а структурированная программа с чёткими обязательствами.
2.1.1Отбор 20 студий (критерии + outreach)
КритичноSales+Product⏱
Критерии отбора + конкретный список из 20 студий готовых к пилоту.
Что конкретно нужно сделать (5)
- Критерии: география, размер, специализация (residential / commercial)
- Long-list 50+ из существующих контактов
- Outreach: personalized email + демо-звонок
- Short-list 20 с NDA и коммитментом на weekly feedback
- Резерв 10 на случай отвалов
Открытые вопросы (2)
- Существующий CRM с кандидатами?
- Кто делает outreach?
Зависит от: — · Блокирует: —
2.1.2Условия пилота + NDA
КритичноLegal+Product
Формальные условия участия, защищающие обе стороны.
Что конкретно нужно сделать (5)
- Срок пилота: 3 месяца (с продлением)
- Free доступ в обмен на weekly feedback + case study/testimonial
- NDA о функциях до публичного
- Commitment: еженедельный 30-мин звонок
- Что после пилота: автопродление по оплате / отмена / migrate на paid
Открытые вопросы (2)
- Кейс-стади — opt-in или default?
- Право забрать контент после пилота (экспорт)?
Зависит от: 1.7.1 · Блокирует: 2.1.1
2.1.3Коммуникационный канал + cadence
ВысокийProduct+Ops
Где и как общаемся с пилот-студиями в течение 3 месяцев.
Что конкретно нужно сделать (5)
- Dedicated Slack / WhatsApp / Telegram group
- Weekly 30-мин check-in call (группа 4-5 или 1-on-1?)
- Monthly demo call: новые фичи + Q&A
- Shared public roadmap (read-only)
- Dedicated Customer Success (Project Lead изначально)
Открытые вопросы (2)
- Slack vs WhatsApp?
- Групповые vs 1-on-1?
Зависит от: — · Блокирует: —
2.1.4Pilot-specific documentation
ВысокийContent+Product
Приватная документация для пилот-студий — не то же что публичная KB.
Что конкретно нужно сделать (5)
- «Welcome to the pilot» guide
- Known issues page (актуализируется)
- Roadmap (что ожидается когда)
- Contact tree (кого пинговать по какому вопросу)
- Feedback submission guide
Открытые вопросы (1)
- На каком языке (EN / RU)?
Зависит от: — · Блокирует: —
Фаза 2.2Инфраструктура онбординга студий
White-glove onboarding первых 20 — помогаем вручную, чтобы потом автоматизировать на основе реального опыта.
2.2.1Assisted onboarding (white-glove)
КритичноProduct+Ops⏱
Для первых 5-10 студий — 1-hour kick-off call где мы помогаем настроить домен, создать первый проект, залить первый контент.
Что конкретно нужно сделать (6)
- 1-hour call скрипт (повторяемый)
- Pre-call checklist: что студия должна иметь готово
- Post-call checklist: что должно работать
- Recording для внутреннего обучения
- Gradually reduce: 5 первых — 1h, следующие 10 — 30min, последние 5 — self-serve + async
- Feedback: что стоит автоматизировать
Открытые вопросы (1)
- Кто проводит (Project Lead / отдельный CS)?
Зависит от: Фаза 1.2 · Блокирует: —
2.2.2Fast-track support channel
КритичноOps⏱
Для пилот-студий — прямой канал с ответом <2 часа в рабочее время.
Что конкретно нужно сделать (5)
- Priority в чате (Фаза 2.3)
- Dedicated email/Slack channel для pilot
- SLA: <2h в рабочее, <24h вне
- Escalation path: chat → engineer → tech team → product team
- Baseline: среднее тикетов в день для capacity planning
Открытые вопросы (1)
- Кто в on-call для пилота?
Зависит от: 2.3 · Блокирует: —
2.2.3Onboarding content (Loom + written guides)
ВысокийContent
Базовые гайды чтобы студия не обращалась за одним и тем же.
Что конкретно нужно сделать (5)
- Loom: «Создание первого проекта за 15 минут»
- Loom: «Загрузка panorama и hotspots»
- Loom: «Подключение custom domain»
- Written guides для каждого видео
- Embedded в admin (contextual)
Открытые вопросы (1)
- Кто делает видео (Product team / tech team / подрядчик)?
Зависит от: Фаза 1.2 · Блокирует: —
Фаза 2.3Support Infrastructure
Инфраструктура поддержки, которая работает в пилоте и продолжает работать в публичном запуске.
2.3.1AI chat platform (выбор + интеграция)
ВысокийProduct+Ops⏱❓
Основной канал поддержки — AI-чат на базе KB, с эскалацией на человека.
Что конкретно нужно сделать (6)
- Выбор: Crisp (дешевле, AI-addon) / Intercom (дороже, Fin AI) / Tawk.to (free, weaker AI)
- Интеграция в admin (widget) + публичные страницы
- Обучение AI на KB (2.3.2)
- Handoff к человеку: «talk to human» работает
- Ticket tracking: history, status, assignee
- Integration с Slack/email для escalation
Открытые вопросы (2)
- ❓ Crisp vs Intercom vs Tawk.to — cost/benefit
- Pricing: per seat / conversation / flat?
Зависит от: — · Блокирует: 2.3.3
2.3.2Knowledge Base (8 приоритетных статей)
ВысокийContent+Product
База знаний для AI-чата + публичного self-service.
Что конкретно нужно сделать (4)
- 8 приоритетных статей: быстрый старт, custom domain, добавление проекта, panorama/hotspots, floor plans, invite клиента ✅, биллинг, feature toggles
- Формат: 300-500 слов + скриншоты + checklist в конце
- Embedded search
- «Was this helpful?» voting
Открытые вопросы (2)
- CMS (Notion / Outline / GitBook / внутреннее)?
- Multi-язык или только EN?
Зависит от: — · Блокирует: 2.3.1
2.3.3Public FAQ + escalation
СреднийContent+Ops
Публичный FAQ на landing-page + механизм перехода от AI к человеку.
Что конкретно нужно сделать (5)
- FAQ на landing с топ-10 pre-sales вопросов
- Escalation flow: AI не знает → «connect with support»
- Office hours указаны (transparency)
- SLA публично объявленный (24h для non-urgent)
- Status page (uptime.com / statuspage.io) для incident communication
Открытые вопросы (1)
- Публичный status page с запуска или позже?
Зависит от: 2.3.1, 2.3.2 · Блокирует: —
Было: 2.3.4 Feedback loop: ticket → KB article.
Перенесено в Раздел 6.5 — это operational process (weekly review), не dev-задача.
Фаза 2.4Инструменты сбора фидбека
Количественный + качественный фидбек пока студии работают. Входит в договорённость с пилот-программой.
2.4.1Heatmap + session recordings
ВысокийProduct+Tech⏱❓
Инструмент который показывает где студии тыкают в пустоту, где останавливаются, откуда уходят.
Что конкретно нужно сделать (5)
- Выбор: Hotjar (платный, зрелый) vs MS Clarity (free, GDPR)
- Установка на admin + публичные страницы
- Session recordings для топ-5 journeys
- Cookie consent совместим (1.9.4)
- Retention setting (GDPR-compliant)
Открытые вопросы (1)
Зависит от: 1.9.4 (cookie consent) · Блокирует: —
2.4.2Product analytics (PostHog / Mixpanel)
ВысокийProduct+Tech⏱
События которые отслеживаем для понимания feature adoption и retention.
Что конкретно нужно сделать (6)
- Выбор: PostHog (self-hosted возможно) vs Mixpanel (managed)
- События: signup, wizard steps, project created, building/unit created, publish, share, payment
- User properties: plan tier, studio size, country
- Funnel: signup → wizard complete → first project → publish
- Retention cohorts
- Feature adoption: Walkthroughs / Price List / Unit Statuses
Открытые вопросы (2)
- PostHog vs Mixpanel?
- Self-hosted PostHog или cloud?
Зависит от: — · Блокирует: 2.4.4
2.4.3GA4 на публичных страницах[BL]
СреднийMarketing+Tech
Традиционная web analytics на landing + публичных проектных страницах.
Что конкретно нужно сделать (5)
- GA4 install на landing + project pages
- Goals: trial signup, pricing view, demo request
- UTM tracking для campaigns
- Search Console integration
- IP анонимизация (GDPR)
Открытые вопросы (1)
- GA4 vs Plausible / Simple Analytics?
Зависит от: 1.9.4 (cookie consent) · Блокирует: —
2.4.4Structured feedback form + weekly calls
ВысокийProduct+Ops⏱
Структурированная форма на каждый weekly call — чтобы фидбек был сопоставим.
Что конкретно нужно сделать (5)
- Weekly form: сработало / сломалось / missing / priority 1/2/3 wishlist
- Форма: Typeform / Notion / custom
- Weekly 30-мин call с заполнением формы прямо
- Aggregation: все ответы в одном dashboard
- Monthly summary: топ-3 паттерна для команды
Открытые вопросы (1)
- Typeform / Notion / Airtable?
Зависит от: 2.1.3 · Блокирует: —
2.4.5Beta metrics dashboard
ВысокийProduct+Tech⏱
Один экран где видны ключевые метрики пилота.
Что конкретно нужно сделать (3)
- Metabase / Grafana / custom
- Метрики: WAU/MAU, проекты/неделя, time to first project, support load, feature adoption, error rate, NPS
- Auto-refresh, доступ команде
Открытые вопросы (1)
- Tool: Metabase / Grafana / Notion?
Зависит от: 2.4.1, 2.4.2 · Блокирует: —
Фаза 2.5Итерации по фидбеку
Weekly sprint на основе фидбека. Не ждём конца пилота — делаем инкрементально.
2.5.1Weekly triage meeting
ВысокийProduct+Tech
Еженедельный 1-час meeting где команда смотрит фидбек, ранжирует и планирует спринт.
Что конкретно нужно сделать (5)
- Attendees: Project Lead, product team, tech team (lead), PM
- Input: feedback form aggregation (2.4.4), chat logs, bug reports
- Triage: critical / high / medium / low / wontfix
- Output: список задач на next sprint
- Communication к студиям: что взяли / не взяли и почему
Открытые вопросы (1)
- Fixed время (пятница 16:00 GST) или плавающее?
Зависит от: 2.4.4 · Блокирует: —
2.5.2Admin UX improvements по ходу
ВысокийDesign+Tech⏱
Улучшения admin которые не вошли в Стадию 1 — делаем в ответ на фидбек пилота.
Что конкретно нужно сделать (7)
- Buildings pagination + sorting (заметки #1, #10)
- Enable/disable toggles (buildings, levels, units) (#4)
- Click-to-preview (#5)
- File conversion on upload (jpeg→webp) (#12)
- Breadcrumbs everywhere
- Sticky forms (no progress loss)
- Labels & Terms UX cleanup
Открытые вопросы (1)
- Какие приоритетны по фидбеку пилотов?
Зависит от: 2.4 · Блокирует: —
2.5.3Bug triage & fix cadence
ВысокийTech+QA
Процесс как баги от пилот-студий попадают в работу.
Что конкретно нужно сделать (5)
- Bug report template (replication, expected, actual, screenshots, env)
- Severity: P0 (data loss / security) / P1 (blocker) / P2 (degraded) / P3 (cosmetic)
- SLA: P0 = 4h, P1 = 2 дня, P2 = sprint, P3 = backlog
- Tracker (Linear / Jira / GitHub Issues?)
- Regression tests для fix'нутых багов
Открытые вопросы (1)
- Какой tracker используется?
Зависит от: — · Блокирует: —
Фаза 2.6Критерии выхода из пилота
Когда можем сказать «готовы к публичному запуску»? Чёткие метрики.
2.6.1Go/no-go критерии
КритичноProduct
Метрики которые говорят «да, идём в public launch» или «нет, продлеваем пилот».
Что конкретно нужно сделать (7)
- 80%+ пилот-студий активны (еженедельно)
- 70%+ создали 3+ проекта
- Critical + High баги = 0 open
- Average NPS ≥ 30
- AI-chat resolution ≥60% без эскалации
- Error rate <1%
- Uptime ≥99.5% за последний месяц
Открытые вопросы (1)
- Финальные threshold'ы — требуют согласования
Зависит от: 2.4.5 · Блокирует: Стадию 3
2.6.2Post-pilot decision point
КритичноProduct+Sales
Формальная встреча (Project Lead + product team + tech team) где смотрим метрики, принимаем go/no-go.
Что конкретно нужно сделать (5)
- Presentation: pilot outcomes (метрики, кейсы, lessons learned)
- Decision: open doors сейчас / продлить пилот / stage 2 пилота
- Communication к пилот-студиям о переходе (paid / continue free / migration)
- Press release / blog post (если go)
- Case studies opt-in from пилот-студий
Открытые вопросы (1)
- Что если go/no-go неоднозначен?
Зависит от: 2.6.1 · Блокирует: Стадию 3
2.6.3Pilot → Paid transition (механика перехода)
КритичноProduct+Ops+Legal⏱❓
Когда пилот закончился и решение go — что конкретно происходит с 20 студиями? Без продуманного процесса теряем пилот-студий в момент когда они должны стать первыми paying customers.
Communication sequence (4)
- Day -30: «Пилот заканчивается. Вот что дальше». Персонализированное письмо от Project Lead
- Day -14: 1-on-1 звонок с каждой пилот-студией — пожелания, план перехода
- Day -7: финальный reminder с выбором действия
- Day 0: триггер действия
Опции для пилот-студии (3)
- A — Migrate to paid (с grandfathered discount 50% на первый год как благодарность)
- B — Продлить пилот на 1-3 месяца (ограниченное количество)
- C — Отменить, данные сохраняются 90 дней в read-only
Что ещё нужно сделать (4)
- Данные при отмене — 90-день retention, потом delete
- Reference / testimonial collection прежде чем студия уйдёт (если C)
- Case studies — публикация 3-5 success stories (см. 3.2.4)
- Automation — trigger emails через email provider
Открытые вопросы (4)
- ❓ Grandfathered discount — 50% / fixed price lock / другое?
- ❓ Продление пилота — для всех или только advocate-студий?
- Automatic billing start или manual confirmation?
- Что если студия просит продления >3 месяцев?
Зависит от: 2.6.1, 2.6.2 · Блокирует: Стадию 3
2.6.4Self-service billing UI[MOVED from 1.7.4]
КритичноTech+Design⏱
В админке студия сама управляет своей подпиской. Перенесено из 1.7.4 в Стадию 2 (ревизия 2026-04-30) — для пилота (бесплатный, 20 студий) UI самообслуживания не нужен; активируется только когда первые студии становятся paying в момент Pilot → Paid transition (2.6.3).
Что конкретно нужно сделать (8)
- Страница «Billing» в admin
- Текущий план + что он включает
- Следующая дата списания + сумма
- Сменить план (upgrade / downgrade) с proration
- Скачать invoice (PDF) за любой период
- Отмена подписки (grace period до конца оплаченного периода)
- Обновить способ оплаты
- История платежей
Открытые вопросы (1)
- При отмене: read-only access или полный block? (наш стратегический Q2)
Зависит от: 1.7.3, 1.7.5, 2.6.3 · Блокирует: Стадию 3
Фаза 4.1API / Webhooks / MCP [BL]
Основной запрос от агентств — интеграция с их CRM.
4.1.1Webhooks для ключевых событий
ВысокийTech⏱
Студии получают уведомления о событиях в их CRM через webhooks.
Что конкретно нужно сделать (5)
- Events: register_interest, unit.status_changed, unit.price_changed, project.created
- Configuration UI: webhook URL + secret
- Retry logic: exponential backoff, 3 attempts, DLQ
- Delivery logs
- Signature verification (HMAC)
Открытые вопросы (1)
- Какие события самые запрошенные (по фидбеку пилота)?
Зависит от: — · Блокирует: —
4.1.2API v1 documentation (Swagger/OpenAPI)
ВысокийTech⏱
Публичная API документация для интеграторов.
Что конкретно нужно сделать (5)
- Audit existing API endpoints
- OpenAPI 3.0 spec
- Interactive docs (Swagger UI / Redoc)
- Versioning (v1, v2 backwards compat)
- Authentication guide, rate limits doc, changelog
Открытые вопросы (1)
- Hosted docs (Stoplight / Readme) или self-hosted?
Зависит от: — · Блокирует: 4.1.4
4.1.3Sandbox environment
ВысокийTech⏱
Test environment для интеграторов / разработчиков — без влияния на prod.
Что конкретно нужно сделать (5)
- Отдельный sandbox domain (sandbox.offplan.online)
- Test-mode API keys
- Seeded sample data (fake studios / projects)
- Reset on demand
- Документация
Открытые вопросы (1)
- Reset автоматом или по запросу?
Зависит от: — · Блокирует: 4.1.4
4.1.4CRM integration examples
СреднийTech+Marketing❓
Готовые примеры интеграции с топ-3 CRM (HubSpot / Salesforce / Pipedrive).
Что конкретно нужно сделать (4)
- Выбор топ-3 по запросу пилот-студий
- Для каждого: GitHub repo с примером
- Blog post с пошаговой инструкцией
- Zapier / Make integration
Открытые вопросы (1)
Зависит от: 4.1.1, 4.1.2 · Блокирует: —
🔴 4.1.5 MCP server wrapper — перенесено в Стадию 1, Фаза 1.4.
Подробное описание, обоснование и подзадачи — см.
Фазу 1.4.
Фаза 4.2Продвинутая монетизация
Оптимизация revenue после того как базовая подписка уже работает.
4.2.1Full 3-tier launch
СреднийProduct+Tech
Полноценный запуск 3 планов (Starter / Studio / Agency) с правильными limits и features.
Что конкретно нужно сделать (4)
- Lock features per план (feature flags per tier)
- Over-limit warnings
- Auto-upgrade promptы
- A/B test pricing
Открытые вопросы (1)
Зависит от: 1.5 · Блокирует: 4.2.2
4.2.2Metered billing для рендеров
СреднийTech+Finance⏱
Если студия превысила quota рендеров — pay-per-use.
Что конкретно нужно сделать (5)
- Track renders per tenant
- Overage price per unit
- Alerts approaching quota
- Invoice lines per overage period
- Stripe / Paddle metered billing API
Открытые вопросы (1)
- Pricing: per render vs bundle?
Зависит от: 4.2.1 · Блокирует: —
4.2.3Annual billing + discount
СреднийTech
Годовая оплата с скидкой 20% (upfront payment + retention).
Что конкретно нужно сделать (4)
- UI выбора billing period
- Proration при monthly↔annual
- Renewal automation
- Communication (30 дней до renewal)
Открытые вопросы (1)
Зависит от: 4.2.1 · Блокирует: —
4.2.4Dunning (failed payment handling)
ВысокийTech+Ops⏱
Что происходит если карта expired или списание failed.
Что конкретно нужно сделать (5)
- 3 retry attempts за 7 дней
- Email sequence: Day 1 (failed), Day 3 (retry), Day 7 (final warning), Day 8 (downgrade)
- Grace period access (read-only)
- «Update card» flow в admin
- Recovery playbook
Открытые вопросы (1)
- Policy после 8 дней: downgrade / full block / данные через 90 дней?
Зависит от: 1.6.3, 1.6.6 · Блокирует: —
4.2.5Enterprise plan (custom quotes)
НизкийProduct+Sales
Для крупных агентств — custom pricing, SLA, dedicated support.
Что конкретно нужно сделать (4)
- «Contact sales» CTA на pricing page
- Quote workflow (CRM)
- Contract template (legal review per deal)
- Account manager assignment
Открытые вопросы (1)
- Sam Project Lead закрывает или нужен Sales rep?
Зависит от: — · Блокирует: —
Было: 4.2.6 Referral credits.
Объединено с Фазой 3.2.5 — referral program теперь включает credits system как одно целое.
Фаза 4.3Admin Redesign: 3 Views
Подход tech team: не переделываем всё с нуля — добавляем 2 новых view рядом с classic. Детали — в визуальном appendix.
4.3.1Classic view continuous improvement
СреднийDesign+Tech⏱
Текущий admin продолжает улучшаться инкрементально.
Что конкретно нужно сделать (5)
- Fold в текущие улучшения из pilot-фидбека
- Palette refresh: sand/gold вместо «cheap» светофоров
- Typography refresh
- Spacing / whitespace consistency
- Component library consolidation
Открытые вопросы (1)
- Дизайнер (внутренний / подрядчик)?
Зависит от: — · Блокирует: —
4.3.2Power Editor (Excel-like mass editing)[BL]
СреднийDesign+Tech⏱
Подход tech team: когда много изменений — открываешь Power Editor, видишь все units в grid'е как в Excel, редактируешь inline.
Что конкретно нужно сделать (7)
- Spreadsheet-like grid (react-data-grid / ag-grid / handsontable)
- Inline editing с валидацией
- Copy-paste (из Excel)
- Bulk actions (select all / mass update / mass delete)
- Import / Export CSV
- AI-prompt integration (4.3.4)
- Use cases: initial bulk setup, quarterly price updates, status sync
Открытые вопросы (2)
- Grid library — free vs paid?
- CSV format spec?
Зависит от: — · Блокирует: 4.3.4
4.3.3Visual Editor (inline на фронте)
Низкий-СреднийDesign+Tech⏱
Запрос product team: пользователь заходит на live-страницу проекта, включает Edit Mode, меняет заголовки / описания / цены прямо на фронте. Подход tech team: этот view — дополнение к classic, не замена.
Что конкретно нужно сделать (5)
- «Edit Mode» toggle (только для аутентифицированных с правом)
- Contenteditable + validation
- Save перед переключением секции
- Audit log integration
- Scope limit: только labels/prices (не floor plan geometry)
Открытые вопросы (2)
- Что именно editable в visual mode?
- Conflict resolution если несколько пользователей?
Зависит от: — · Блокирует: —
4.3.4AI editing mode
НизкийTech+Product⏱
AI-агент в Power Editor: «обнови цены всех 2BR юнитов на +5%».
Что конкретно нужно сделать (5)
- LLM integration (Anthropic / OpenAI)
- Context: полная structure текущего tenant
- Confirmation preview перед apply
- Audit log всех AI-actions
- Safety: read → suggest → user confirms → apply
Открытые вопросы (1)
- Bundled с MCP или отдельно?
Зависит от: 4.3.2, 1.4 (MCP) · Блокирует: —
4.3.5Full design system (расширение 1.1.3)
НизкийDesign⏱
На Стадии 1 (Фаза 1.1.3) — минимальный refresh для пилота. Эта фаза — полный формализованный design system: Figma library, tokens, documentation, component library как code package для всех admin views.
Разница с 1.1.3 (2)
- 1.1.3 = минимум для пилота: status indicators + accent colors + typography audit (~1-2 недели)
- 4.3.5 = полная design system: reusable component library, Figma, docs, guidelines (~4-6 недель)
Что конкретно нужно сделать (6)
- Figma library со всеми компонентами
- Design tokens в коде (CSS variables / Tailwind / Linaria)
- Documentation (Storybook или аналог)
- Migration всех existing UI на новый system
- Accessibility check (contrast, focus states) — связано с Q36
- Dark mode support (optional)
Открытые вопросы (3)
- Storybook vs alternative (Ladle, Histoire)?
- Tailwind utility-first или CSS modules?
- Dark mode — обязательно или opt-in per user?
Зависит от: 1.1.3 · Блокирует: —
4.3.6Customization (font + button roundness)[BL]
НизкийDesign+Tech⏱
Студия кастомизирует свои публичные страницы: шрифт, скругление кнопок, layout variants.
Что конкретно нужно сделать (4)
- Theme variables в admin (font family, button radius 0-20, primary, secondary)
- Preview в admin
- Применяется на публичных страницах (не admin)
- Sensible defaults
Открытые вопросы (1)
- Custom CSS для enterprise?
Зависит от: — · Блокирует: —
Фаза 4.4Локализация
Расширение на другие рынки через локализацию.
4.4.1i18n infrastructure
СреднийTech⏱
Ready для добавления языков.
Что конкретно нужно сделать (5)
- i18n library (react-i18next / formatjs)
- Extraction pipeline (все strings → translation keys)
- Pluralization / formatting rules
- Date/number locale
- RTL ready для будущего арабского
Открытые вопросы (1)
Зависит от: — · Блокирует: 4.4.3
4.4.2Translation pipeline
СреднийProduct+Tech
Как переводы появляются + обновляются.
Что конкретно нужно сделать (4)
- Source of truth: JSON / YAML в репо
- Translation service: Lokalise / POEditor / Crowdin / manual
- Reviewer workflow (native speaker approve)
- Continuous updates
Открытые вопросы (1)
Зависит от: 4.4.1 · Блокирует: 4.4.3
4.4.3EN baseline
СреднийContent
Полный английский перевод (source language).
Что конкретно нужно сделать (4)
- Audit всех hardcoded strings
- Extraction в translation keys
- Review quality + consistency
- Style guide (tone, terminology)
Зависит от: 4.4.1, 4.4.2 · Блокирует: 4.4.4
4.4.4Second language decision
СреднийProduct+Marketing❓
Какой второй язык добавить после EN.
Что конкретно нужно сделать (4)
- Data-driven decision: по signup geography + target markets
- Candidates: Arabic (UAE/GCC), German (DACH), French, Spanish, Russian
- Translation + review + launch
- Market-specific adjustments (RTL для арабского)
Открытые вопросы (1)
- ❓ Требует решения product team и marketing
Зависит от: 4.4.3 · Блокирует: 4.4.5
4.4.5RTL support (если арабский)
НизкийTech⏱
Bidi / RTL layout если выбран арабский.
Что конкретно нужно сделать (4)
- CSS logical properties (margin-inline-start etc.)
- Layout testing с RTL
- Icons mirroring
- Form inputs behaviour
Зависит от: 4.4.4 · Блокирует: —
Фаза 4.5Advanced Features
Features которые не обязательны для launch но сильные differentiators.
4.5.1Compare units (buyer-facing)
Низкий-СреднийTech+Design⏱
Покупатель выбирает 2-3 юнита → таблица сравнения.
Что конкретно нужно сделать (4)
- Multi-select из списка units
- Сравнительная таблица: area, price, floor, view, status
- Shareable link
- Mobile-friendly
Открытые вопросы (1)
- Scope: only same project или cross-project?
Зависит от: — · Блокирует: —
4.5.2Remote co-browse (WebRTC)[BL]
НизкийTech⏱
Агент ведёт покупателя удалённо по 3D-туру (shared cursor, voice).
Что конкретно нужно сделать (3)
- WebRTC / cursor sharing / voice chat
- Session management (пригласительная ссылка)
- Recording (optional)
Открытые вопросы (1)
- Build vs integrate (Calendly + Zoom)?
Зависит от: — · Блокирует: —
4.5.3PDF import + AI conversion для floor plans
Низкий-СреднийTech+Product⏱
Заметка #6 — PDF не принимается сейчас, но часто застройщики присылают именно PDF.
Что конкретно нужно сделать (4)
- PDF upload endpoint
- AI conversion pipeline (GPT-4V / Claude / specialized): vectorize + crop + background removal
- Human review step (optional для начала)
- Output: PNG/WebP с правильными параметрами
Открытые вопросы (2)
- Авто или manual review?
- AI-provider для vision?
Зависит от: — · Блокирует: —
4.5.4AI-assisted content generation
НизкийTech+Product⏱
AI помогает писать описания юнитов, amenities, projects.
Что конкретно нужно сделать (4)
- Prompts для разных entities
- Edit-review-approve UX
- Token consumption tracking
- Style adherence (studio tone)
Открытые вопросы (1)
- Free или per-token billing?
Зависит от: — · Блокирует: —
4.5.5AI Chat & Guidance for Sales App[BL]
НизкийTech+Product⏱
AI-чат на стороне sales-app — для покупателей и агентов. На ранних этапах (до 4.5.5) студии могут подключать сторонний чат-виджет (Intercom / Crisp / Tawk). Эта sub-phase = наша собственная реализация с product-context: AI знает структуру проекта, юниты, цены, доступность, может проводить пользователя по продукту, отвечать на вопросы про планировки. В backlog у Ильи как «AI Chat and Guidance for Sales App» (Сергей: «может есть смысл сделать на стороннем приложении»).
Что конкретно нужно сделать (5)
- Chat UI на sales-app (виджет или fullscreen)
- Контекст в prompt: данные проекта (units, prices, status, availability) + style guide студии
- Provider: OpenAI / Anthropic / open-source — выбор после prototype
- Token budgeting — кто платит (студия subscription tier vs offplan.online absorbs)
- Hand-off на живого агента, если AI не справляется (escalation в admin)
Открытые вопросы (2)
- ❓ Свой чат или интеграция с готовым (Intercom Fin / Crisp AI)?
- ❓ Per-tier feature или universal (free для всех студий)?
Зависит от: Фаза 4.1 (API surface для AI access) · Блокирует: —
4.5.6Backlog watch — items в Ilya's backlog не запланированные в стадии[BL]
НизкийTech
Items, которые есть в backlog у tech team, но scope / priority пока не firm enough чтобы вписать в конкретную стадию. Перечислены здесь чтобы план оставался синхронизирован с реальностью на стороне Ильи. Каждый — кандидат на promotion в numbered sub-phase когда созревает.
Items в наблюдении (9)
- Microservices Architecture — архитектурное направление Ильи (split проекта на мини-сервисы для resilience: упал интерьер — экстерьер живой). Cross-cutting, не отдельная фаза, но влияет на 1.8 / 3.1 / 3.5.
- Interior Minimap Functionality — миникарта в углу экрана интерьерного просмотра. На паузе у tech team.
- Multi-Storey Floor Plan Support — поддержка многоэтажных планировок (мезонины, дуплексы).
- Walkthrough Experience for Exterior — прогулка возле объекта (walkable exterior).
- Information Pins for Location — инфо-пины на локации (магазины / школы / транспорт рядом).
- Information Pins for Interiors — инфо-пины внутри юнитов (материалы / appliances / dimensions).
- 360-Degree Video Support — 360° видео-обзор внутри плеера.
- Exterior Level Highlighting in Admin Editor — подсветка этажей в редакторе экстерьера.
- Sales App / Admin Panel 3-Screen Prototype (R&D) — экспериментальный R&D трек у tech team, deliberately unbilled.
Зависит от: — · Блокирует: —
P.1Hotspot UX overhaul
✅ В активной разработке
Редизайн хотспотов на фасаде здания (см. Фаза 4.5.5 выше). В активной разработке у tech team.
P.2Новая админка с AI-assistance
✅ В активной разработке
Tech team ведёт отдельный трек по построению следующей версии admin с AI-assisted workflows. Когда этот трек дойдёт до релиза — 3-view концепция (Classic + Power Editor + Visual Editor) из Фазы 4.3 естественно ляжет в новый фундамент. План offplan.online синхронизируется со scope'ом и приоритетами этого трека на еженедельных встречах.
Практическое следствие: задачи из Фазы 4.3 не начинаются в старой админке, а интегрируются в новую по мере её готовности. Это влияет на порядок работ — продолжать обсуждать с tech team.
5. Команда и пропускная способность
5.1 — Текущая команда
| Роль | Фокус | Частота |
| Product team | Направление продукта, фичи, стратегия, приоритизация | — |
| PM (в product team) | Управление процессом | — |
| Tech team (lead) | Техническая координация, эстимирование, архитектура | Ежедневно |
| Frontend / Content (tech team) | Контент, frontend — основной драйвер | Ежедневно |
| Backend (tech team) | API endpoints, поддержка frontend | Несколько раз в неделю |
| QA | Тестирование перед деплоем | — |
| UI/UX | Дизайн | — |
Новая роль в этом плане
| Роль | Фокус |
| Project Lead (offplan.online) | Координация плана, обсуждение с командой, коммуникация с product team и tech team |
5.2 — Пропускная способность
Текущий цикл команды: 2 недели спринт → 1.7-2 недели QA → деплой. Два типа деплоев: мелкие правки (~40-50 за цикл) и большие логические изменения — всегда отдельно.
Вопрос к tech team: реальный эстимейт по Фазам Стадии 1 в разбивке по ролям. После этого ясно можно ли распределить нагрузку или нужно усиление (дополнительный frontend / backend / дизайнер / юрист).
6. Процесс эстимирования и взаимодействия
6.1 — Cadence Project Lead ↔ Tech Lead
- 2-3 звонка в неделю (согласовано на звонке 2026-04-24)
- Формат: 30-60 минут, повестка заранее
6.2 — Эстимирование
- Project Lead + AI-ассистент готовят task-level описание из плана
- Передают tech team на эстимейт
- Tech team (lead) разбивает по ролям (frontend / backend / design / QA) и возвращает дни
- Созваниваются, обсуждают что можно ускорить / распараллелить
- Результат → в план (замена ⏱ на конкретные дни)
6.3 — Backlog
Запрошен доступ к backlog tech team — чтобы понять что уже делается параллельно. ⏱ ожидается от tech team.
6.4 — Прод-подобное окружение
Запрошено teremki.offplan.online (или подобное) — prod-like environment где Project Lead может тестировать как клиент. ⏱ ожидается от tech team.
6.5 — Feedback loop: ticket → KB article
Если студия спрашивает — значит KB недостаточна. Каждый unanswered вопрос превращается в статью. Это operational process, не dev-задача — начинаем с первой недели пилота и продолжаем continuous.
Как работает:
- Weekly review (30 минут, Ops + Content lead): топ-5 вопросов в chat за неделю
- Missing answer → article: если AI не смог ответить и операторы отвечали manually — создаём KB-статью по шаблону
- Auto-suggestions: chat-platform предлагает «вы уже 5 раз отвечаете на этот вопрос, создать статью?»
- Метрика: % AI-answered без эскалации (цель ≥60% на выходе из пилота, ≥80% через 3 мес после publics)
Кто ведёт: CS/Ops lead. Связано с Фазой 2.3 (Support Infrastructure) — после развёртывания AI-чата процесс запускается сразу.
Полный визуальный референс с v4 mockup: launch-plan-v3-visual.html.
Кратко концепция (для обсуждения с product team и tech team):
Проблема: Текущий admin работает. Переделывать всё с нуля — слишком дорого и рискованно. Подход tech team: не переделываем, добавляем views.
Три view параллельно
- Classic view (текущий admin) — для детального редактирования отдельных entities. Продолжает улучшаться инкрементально.
- Power Editor (новый) — Excel-like grid для массового редактирования. Use cases: initial bulk setup, quarterly price updates, status sync. Также — платформа для AI-режима редактирования.
- Visual Editor (новый) — inline на публичной странице. Light-touch редактирование (labels, prices, descriptions). Не замена classic, а дополнение для quick edits.
Визуал: sand/gold/navy палитра — замена традиционного UI. Встроенный numbered wizard 1→10 в sidebar для онбординга.
Файл визуального референса: docs/launch-plan-v3-visual.html
Дополняют 44 вопроса из launch-plan-v2 (Appendix C). Акцент на security, rate limiting, reliability.
Security (7)
| # | Вопрос | Ответственный |
| N1 | Как устроена tenant isolation — database-level (per-tenant schemas) или application-level (WHERE tenant_id = ?)? Какой уровень защищённости? | Tech team |
| N2 | Есть ли автоматические регрессионные тесты изоляции в CI? | Tech team |
| N3 | Аудит auth flow: session fixation, CSRF, timing attacks, token leaks в URL? | Tech team + внешний security аудитор |
| N4 | Как хранятся пароли (bcrypt / argon2 / scrypt)? Соль + стоимость? | Tech team |
| N5 | Есть ли шифрование медиа на storage? Access control на S3/bucket? | Tech team |
| N6 | Политика rotation ключей и токенов (API keys, JWT signing, Stripe, OAuth)? | Tech team |
| N7 | Как детектим + отвечаем на suspicious activity? | Tech team + Ops |
Rate Limiting / DoS (3)
| # | Вопрос | Ответственный |
| N8 | Какие rate limits есть сейчас (per IP / user / tenant / endpoint)? Где хардкоджены? | Tech team |
| N9 | Upload rate limits: файл/минута, MB/час, concurrent uploads? | Tech team |
| N10 | Есть ли WAF или CDN-based DDoS protection? | Ops |
Reliability / Backup (3)
| # | Вопрос | Ответственный |
| N11 | RTO (Recovery Time Objective) и RPO (Recovery Point Objective) — формальные цели? | Ops + Product |
| N12 | Когда последний раз делали restore drill? | Ops |
| N13 | Backup retention: как долго, где, в одном регионе или off-site? | Ops |
Scaling / Performance (2)
| # | Вопрос | Ответственный |
| N14 | Capacity model: до какой нагрузки архитектура держит? | Tech team |
| N15 | Unit economics: стоимость инфраструктуры per studio? | Finance + Ops |
Monitoring / SLO (2)
| # | Вопрос | Ответственный |
| N16 | Какие SLI/SLO определены? Alert правила? | Ops |
| N17 | Runbooks для топ-5 инцидентов? | Ops |
Auth / SSO (2)
| # | Вопрос | Ответственный |
| N18 | Auth providers на старте (email/password / Google / Microsoft / Magic Link / SAML)? | Product team + Tech team |
| N19 | MFA: обязательный / опциональный / role-based? TOTP / SMS / WebAuthn? | Tech team |
Compliance (1)
| # | Вопрос | Ответственный |
| N20 | Roadmap compliance (SOC2, ISO27001, UAE DPR, GDPR audit) — когда критично для enterprise-deals? | Sales + Legal |
См. полный список в plans/launch-plan-v2.md (Блок 1, секции 1.1 и 1.2). Все остаются актуальными. Ключевые, требующие обновления ответов:
- Вопрос 4 (Invite клиента): ✅ закрыт — функция уже есть в админке
- Вопрос 11 (tenant isolation): раскрыт детально в N1-N2 Appendix B
- Вопросы 20 (ошибки), 21 (бэкапы): раскрыты в N11-N17 Appendix B
- Вопрос 12 (SSO): раскрыт в N18 Appendix B
| # | Описание | Статус | Где в плане |
| 1 | Buildings отображает только 10 зданий (11-е не видно) | ❌ Не воспроизвелось на проде 2026-04-30 | — |
| 2 | Levels: ограничения по размерам файлов — где и какие? | Audit нужен | Фаза 1.4.4 |
| 3 | Формат файлов не указан на upload полях | Подтверждено | Фаза 1.4.4 |
| 4 | Enable/disable зданий, этажей, юнитов | Feature request | Фаза 2.5.2 |
| 5 | Клик для preview фото в админке | Feature request | Фаза 1.4.6 |
| 6 | PDF support + AI для конвертации floor plans | Feature request | Фаза 4.5.3 |
| 8 | Tower 1 пропадает из dropdown (refresh спасает) | ❌ Не воспроизвелось на проде 2026-04-30 | — |
| 9 | Compass выключен — видно 2 башни, включён — все | 🔬 Прод | Фаза 1.4.1 |
| 10 | Sorting по колонкам (номер, дата обновления) | Feature request | Фаза 2.5.2 |
| 11 | После create building → photo → переход на другое здание | 🔬 Прод | Фаза 1.4.3 |
| 12 | File conversion на upload (jpeg/png → webp drag-and-drop) | Feature request | Фаза 3.1.4 |
| 13 | Локализация — первый EN, потом? | Планируется | Фаза 4.4.4 |
| 14 | Form validation сбрасывает прогресс ввода юнита (дублирующее название) | ✅ Подтверждено 2026-04-30 | Фаза 1.5.1 |
| 15 | Unit создан но не виден в меню | ❌ Не воспроизвелось на проде 2026-04-30 | — |
| 16 | Hotspots на здании — полупрозрачные + hover status | ✅ Tech team | Фаза 4.5.5 |
| 17 | Hotspots: расстановка мышкой вместо значений | ✅ Подтверждено 2026-04-30 | Фаза 1.5.5 |
Итого: 6 заметок 🔬 требуют проверки на продакшене прежде чем быть включёнными в sprint.
Вопросы, требующие решения прежде чем соответствующие задачи могут пойти в работу. Каждый помечен: чей ход + что нужно для закрытия.
| # | Тема | Что нужно | Кто | Фаза |
| Q1 ✅ | Stripe vs Paddle | Частично решено (CONV-13): Stage 1 = Stripe (primary), Stage 2 = +Paddle (EU B2C MoR), Stage 3 = +Checkout.com (UAE AED). Provider abstraction layer в 1.6.3. | — | 1.6.3 |
| Q2 ✅ | EU Rep vs EU-юрлицо | Решено (CONV-13): Cyprus entity (EU member) — EU Representative не нужен. Юрист задействован 2026-04-30. | — | 1.6.5 |
| Q3 | Внешний security audit vs внутренний | Бюджет + объективность | Tech team + Product team | 1.7.1 |
| Q4 | DDoS protection: Cloudflare план | Нагрузочный профиль + стоимость | Ops + Tech team | 1.7.5 |
| Q5 | Secrets manager | Vault self-hosted vs managed | Tech team | 3.5.4 |
| Q6 ✅ | SSO провайдеры на старте | Решено (CONV-14): Google only на старте. Microsoft/Azure AD добавить в Stage 2 по запросу студий. ADR 0005. | — | 1.2.1 |
| Q7 | MFA обязателен или опционален | Security posture | Tech team | 1.2.1 |
| Q8 | Email provider | SendGrid / Postmark / Resend | Marketing + Tech team | 1.7.6 |
| Q9 | Demo-проект vs empty-state tutorial | Product decision | Product team | 1.2.5 |
| Q10 | Финальные тарифы (цены и лимиты) | Pricing research | Product team + Finance | 1.6.2 |
| Q11 ✅ | Trial без карты vs с картой | Решено (CONV-14): Без карты — шире воронка. ADR 0001. | — | 1.6.5 |
| Q12 ✅ | Block vs read-only при истечении trial | Решено (CONV-14): Кастомная модель — admin полностью заблокирован; публичная страница проекта показывает только главную страницу здания, остальные секции заблокированы. ADR 0001. | — | 1.6.5 |
| Q13 | Chat platform | Crisp / Intercom / Tawk.to | Product team + Ops | 2.3.1 |
| Q14 | Heatmap: Hotjar vs MS Clarity | Бюджет + privacy | Product team + Legal | 2.4.1 |
| Q15 | Product analytics | PostHog vs Mixpanel | Product team + Tech team | 2.4.2 |
| Q16 | Web analytics | GA4 vs privacy alternatives | Marketing | 2.4.3 |
| Q17 | Feedback aggregation tool | Typeform / Notion / Airtable | Product team | 2.4.4 |
| Q18 🔧 | Dashboard tool | Metabase / Grafana / Notion | Tech-decision (tech team) | 2.4.5 |
| Q19 | Канал для пилота | Slack / WhatsApp / Telegram | Product team + Ops | 2.1.3 |
| Q20 | Pilot case studies compensation | Cash / credits / ничего | Marketing | 3.2.4 |
| Q21 | Приоритет CRM integrations | HubSpot / Salesforce / Pipedrive — по фидбеку | Product team + Tech team | 4.1.4 |
| Q22 🔧 | MCP scope | Read-only vs read+write | Tech-decision (tech team + security) | 1.4.3 |
| Q23 | Annual discount % | Pricing psychology | Product team | 4.2.3 |
| Q24 | Dunning policy после 8 дней | Downgrade / block / удаление | Product team + Legal | 4.2.4 |
| Q25 | Второй язык после EN | Geography priority | Product team + Marketing | 4.4.4 |
| Q26 🔧 | Grid library для Power Editor | Free vs paid | Tech-decision (tech team) | 4.3.2 |
| Q27 | Visual Editor scope | Какие поля editable | Product team | 4.3.3 |
| Q28 ✅ | Retention: активный / 90d / 12mo | Решено (CONV-14): Audit log — 12 месяцев активно, затем архив (cold storage). ADR 0004. | — | 1.6.2 |
| Q29 | DPA model | Self-serve click vs signed | Legal | 1.6.3 |
| Q30 | Status page | Готовое vs custom | Ops | 3.5.3 |
| Q31 ⚡ | Data export + Right to erasure (GDPR Art. 20 + 17) | Частично решено (CONV-14): Right to erasure = hard-delete request flow (manual Iteration 1, self-serve Iteration 2). ADR 0003. Data export scope + форматы — ещё открыто. | Product team + Legal + Tech team | 1.6 + новая |
| Q32 | Migration существующих VV-клиентов | Mandatory / optional / no migration | Product team + Legal | strategic |
| Q33 | Content moderation + DMCA | DMCA agent + moderation approach | Legal + Product team | 1.6 + новая |
| Q34 | Geographic data sovereignty | Default-region + multi-region roadmap | Tech team + Product team + Legal | 1.1 + арх. |
| Q35 | Channel strategy: direct / partners / marketplace | Channel mix + partner structure | Product team + Marketing + Sales | 3.2 |
| Q36 | Accessibility (WCAG) compliance | Уровень + timing + audit | Design + Tech team + Legal | 3.1 |
| Q37 | Incident communication + SLA credits | Структура credits + policy | Legal + Ops + Finance | 3.5 |
| Q38 | White label depth | Policy per tarif | Product team + Marketing + Legal | 4.3.6 |
Итого: 38 вопросов — 6 решено ✅, 1 решено частично ⚡, 31 открыто. (Обновлено CONV-14, 2026-05-01)
- 8 из них — критичные (блокируют Стадию 1):
Q1 ✅, Q2 ✅, Q3, Q6 ✅, Q10, Q11 ✅, Q13, Q37
- 4 — стратегические (требуют обсуждения прежде чем определять детальные задачи): Q31 ⚡, Q32, Q34, Q38
- 3 помечены 🔧 — tech-decisions, не требуют обсуждения менеджмента, решает tech team самостоятельно: Q18, Q22, Q26
Расширенные стратегические вопросы (Q31–Q38)
Для следующих вопросов таблица выше недостаточна — они требуют обсуждения с развёрнутым контекстом. Каждый блок — что за вопрос, почему важен, что нужно решить, кто закрывает.
Q31Data export + Right to erasure (GDPR Art. 20 + 17)
Product team + Legal + Tech teamФаза 1.6 + новая
В чём суть: Две парные GDPR-обязанности — Art. 20 (Data Portability: выгрузить все данные в машиночитаемом формате) + Art. 17 (Right to Erasure / «Right to be Forgotten»: полное удаление данных). Без обоих — нарушение GDPR + отсутствие business trust.
Почему важно: GDPR штрафы до 4% annual revenue. Плюс #1 sales objection в B2B SaaS: «что если я уйду — смогу забрать данные и закрыть аккаунт?»
Что входит в export (Art. 20) (6)
- Структура проектов (JSON) — buildings, levels, units, floor plans
- Медиа (ZIP с оригиналами)
- Users / permissions
- Лиды (CSV)
- Билинг-история + invoices (PDF)
- Audit log
Что входит в erasure (Art. 17) (4)
- Удаление всех personal data
- Retention log самого факта удаления (для audit, anonymous)
- Каскадное удаление в backups
- Exclusion: legal hold data (налоговые инвойсы — 7 лет независимо)
Варианты реализации (3)
- Basic (до пилота): кнопка «Export» + «Delete account» → async + email confirm (~1-2 недели)
- Full (до public launch): все данные, multiple formats, API endpoint, scheduled exports (~2-3 недели)
- Real-time (enterprise): webhook-driven sync в S3-бакет клиента
Что решить (6)
- Scope: project-level / tenant-level / всё
- Форматы export: наш JSON + стандартные (glTF / CSV / PDF)
- Когда: до пилота (GDPR с первого дня) или до публичного launch?
- Erasure — self-serve (кнопка) или только manual request (ticket)?
- Retention после erasure — какие данные остаются (legal hold)?
- Freemium — basic для всех / advanced для enterprise?
Q32Migration существующих VV-клиентов
Product team + LegalСтратегический
В чём суть: У VV есть текущая клиентская база — они на bespoke-контрактах (не self-serve SaaS). Как эти клиенты взаимодействуют с новой SaaS-платформой?
4 варианта (4)
- Mandatory migration — все мигрируют, bespoke контракты прекращаются. Чистый, болезненный
- Optional migration — клиент сам решает. Duality (обе модели параллельно)
- No migration — SaaS только для новых, существующие остаются. Нет потрясений, но бренд разделяется
- Hybrid — SaaS для новых, существующие мигрируют только если захотят (с compensation)
Что решить (5)
- Какой из 4 вариантов?
- Compensation для мигрирующих (скидка / credits / grandfathered price)?
- Timeline миграции (6 мес / 12 мес / indefinite)?
- Отдельные SLA / feature-set для legacy vs SaaS?
- Кто ведёт процесс (отдельный CS-менеджер)?
Риски если не решить (3)
- Существующие клиенты узнают о SaaS случайно → недовольство
- Dual-model создаёт комплексность для tech team (две кодовые базы)
- Возможно legal-обязательства перед существующими клиентами (notice period, price lock)
Q33Content moderation + DMCA
Legal + Product teamФаза 1.6 + новая
В чём суть: Защита от трёх рисков — copyright infringement (студия загружает чужие рендеры), AUP violations (неуместный / фейковый / malware контент), geographic restrictions (KSA требует content filtering).
DMCA specific (4)
- DMCA Designated Agent — регистрация в US Copyright Office ($6 fee) обязательна для Safe Harbor
- Takedown process — dmca@offplan.online + шаблон notice, 24-48h SLA
- Counter-notice — студия может оспорить (10-14 days safe harbor period)
- Repeat infringer policy — 3 обоснованных жалобы = terminate
AUP specific (4)
- Чёткий AUP в ToS (Фаза 1.6.1)
- Report button на публичных страницах
- Manual review queue для reports
- Suspension flow (temporary / permanent)
Что решить (4)
- DMCA agent регистрируем до пилота (safe) или до public launch (cheap)?
- Moderation: manual review (дешёво, медленно) или automated scanning (дорого, быстро)?
- NSFW / content filtering обязателен в Стадии 1 или откладываем?
- Content hash scanning (PhotoDNA) — overkill для нас или enterprise feature?
Q34Geographic data sovereignty
Tech team + Product team + LegalФаза 1.1 + арх.
В чём суть: Некоторые юрисдикции требуют физическое хранение данных локально. НЕ путать с GDPR (который разрешает export данных с SCCs).
Кто требует (4)
- EU GDPR — не требует «данные в EU», но strict control на transfer в third countries (UAE)
- UAE DPR — отдельные сектора требуют local storage (real estate пока нет)
- KSA PDPL — с 2024 требует local hosting для sensitive data
- China / Russia — не наши рынки, но примеры жёсткой localization
Архитектурные варианты (4)
- Single region — дёшево, одна default (EU-West). Отказываемся от клиентов с local-требованиями
- Multi-region read replicas — source of truth EU, replicas в UAE для latency
- Per-tenant region — дорого, сложно. Tenant выбирает регион при signup
- Per-tenant instance — очень дорого, enterprise-only
Что решить (4)
- Default region на старте (EU-West / US / UAE)?
- Multi-region roadmap — когда (6 мес / 12 мес / никогда)?
- Какие enterprise-требования мы готовы принимать (если да — на каком ценовом уровне)?
- Data residency как feature в контрактах — только enterprise или всем?
Q35Channel strategy: direct / partners / marketplace
Product team + Marketing + SalesФаза 3.2
В чём суть: Как продаём продукт — определяет go-to-market и влияет на структуру маркетинг-команды, pricing, tooling.
Возможные channels (5)
- Direct through landing — студия находит нас через Google Ads / SEO / PR → signup. Стандарт B2B SaaS.
- Partner program — рендер-студии приводят других за commission. Multiplicative effect.
- Marketplace listings — AppSumo / G2 / Capterra / PropTech маркетплейсы. Traffic + reviews.
- Direct sales (enterprise) — outreach к крупным агентствам, custom contracts. Высокий CAC, высокий ACV.
- Industry conferences — PropTech / real estate events. Expensive, network-heavy industry.
Типичный sequence B2B SaaS (5)
- 1. Direct landing + SEO/content (от запуска)
- 2. Referral program (после первых 50 customers)
- 3. Marketplace listing G2/Capterra (6 месяцев после launch)
- 4. Affiliate program (9-12 мес после launch)
- 5. Channel partners / reseller (after proof of product + $100k+ MRR)
Что решить (4)
- Channel mix (какие priority, какие можно отложить)
- Partner program structure (affiliate / referral / integration partner)
- Какие marketplaces priority (AppSumo = deal-hunters, G2 = enterprise research, Capterra = SMB)
- Budget allocation между каналами
Q36Accessibility (WCAG) compliance
Design + Tech team + LegalФаза 3.1
В чём суть: WCAG — стандарты доступности для людей с ограниченными возможностями. EU EAA обязателен с 2025-06-28 для B2C веб-сервисов. Публичные страницы проектов = B2C → попадают. Fines до €1M. ADA в США — основание для lawsuits.
Что больно в нашем продукте (5)
- 360° panorama — screen reader не может «прочитать» walkthrough. Нужны alt-описания
- Hotspots — mouse clicks OK, keyboard navigation?
- Floor plans — визуальный контент, нужны accessible descriptions
- Цвета статусов (sand/gold) — contrast ratio проверить
- Forms — signup, onboarding — labels, error messages для screen reader
Что решить (5)
- Target уровень: AA (стандарт) или AAA (premium)?
- Timing: до пилота / до public / отложено?
- Audit: внутренний или внешний ($5-15k)?
- Automated testing в CI (axe, pa11y) — да / нет?
- Scope: публичные страницы / admin / оба?
Q37Incident communication + SLA credits
Legal + Ops + FinanceФаза 3.5
В чём суть: Мы обещаем 99.5% uptime в ToS. Что происходит если не выполняем? Incident communication частично в плане (status page 3.5.3), но SLA credits — стандарт B2B SaaS, отсутствует.
Типичная структура SLA credits (4)
- 99.5%+ uptime → 0 credit
- 99.0-99.5% → 10% скидка на следующий месяц
- 95.0-99.0% → 25% скидка
- <95.0% → 50% скидка
Что решить (6)
- Заводим ли SLA credits вообще? (Некоторые SaaS дают «best effort guarantee»)
- Структура (tiered vs flat)?
- Applied автоматом или только по запросу клиента?
- Cap (max 100% или меньше)?
- Включено в Starter / Studio / Agency или только Enterprise?
- Communication policy — automated status page + manual email?
Q38White label depth
Product team + Marketing + LegalФаза 4.3.6
В чём суть: Сколько VV-бренда видит конечный покупатель квартиры на странице студии? От heavy branded («Powered by VV» в header) до полной invisibility.
3 уровня white-label (3)
- Heavy branded — Header с VV logo + «Powered by VV». Мы = маркетинг, студия = дистрибьютор. Бесплатный traffic
- Light branded — Мелкий «Powered by VV» в футере. Balance: студия premium, мы получаем mention
- Invisible — Никакого VV. Студия максимально premium, мы теряем visibility
Где ещё может всплывать brand (5)
- 360° walkthrough UI — кнопки / controls с нашим стилем?
- Email-уведомления покупателю — от студии или от @volumevision?
- Domain (studio.com vs studio.offplan.online)
- Meta tags / Open Graph (при share в WhatsApp/LinkedIn)
- Hard-coded footer copy?
Typical B2B SaaS pattern (4)
- Starter — «Powered by» обязательно (как Notion free)
- Studio — убирается
- Agency — убирается + кастомизация meta tags
- Enterprise — полная invisibility + custom domain + custom emails
Что решить (4)
- Policy per tarif — на каком tier'е убираем VV-брендинг?
- Scope — где видно брендинг (walkthrough / emails / meta / footer)?
- Mandatory vs removable — на базовом plan нельзя убрать или можно за доплату?
- Privacy policy линк — ведёт к студии или к VV?
Источник истины: markdown в git. Notion-зеркало — для обсуждения и комментариев. Если версии расходятся — git выигрывает.