ОТ ИНТЕРФЕЙСА ДО ХРАНИЛИЩА

Как устроен Estate

Публичный сайт и кабинет написаны на Next.js, React и TypeScript. Go обслуживает прикладные API. Отдельные процессы отвечают за PostgreSQL, Estate CRM и локальную модель поиска. Файлы хранятся отдельно от базы с шифрованием.

Один объект — единый контекст

Объект недвижимости связан со сделкой, поручениями и обращением из чата через property_id. Сделки опираются на существующий модуль заявок: сохраняются календарь, исполнители, документы, версии и аудит. Покупатели используют модуль физических лиц, ИП, компаний и представителей.

Основные маршруты API

  • GET /api/v1/properties — публичный каталог.
  • GET /api/v1/properties/:slug — карточка объекта.
  • POST /api/v1/demo/login — вход staff / staff только при DEMO_MODE=true.
  • GET, POST /api/v1/estate/deals — список и создание сделки.
  • GET, PATCH /api/v1/estate/deals/:id — карточка и история изменений.
  • GET, POST /api/v1/estate/deals/:id/documents — версии и формирование документов.
  • POST /api/v1/estate/deals/:id/crm — постановка обмена в очередь.
  • GET /api/v1/estate/crm — попытки обмена и сохранённые записи.
  • POST /api/v1/estate/crm/:id/retry — безопасный повтор.

Прикладные маршруты покупателей, календаря, поручений, чатов, сотрудников и сессий сохранены. Защищённые запросы требуют заголовок Authorization: Bearer …. У каждой сессии есть срок действия; документы проверяют права на связанную сделку.

Шифрование файлов

Для каждой версии генерируется случайный 256-битный ключ данных. AES-256-GCM шифрует файл и проверяет его целостность. Ключ данных отдельно шифруется мастер-ключом. Зашифрованный ключ хранится в базе, мастер-ключ — в закрытой конфигурации сервиса. Схема применяется к документам, графическим подписям и вложениям, включая превью.

Это шифрование файлов на сервере. Авторизованный сервис расшифровывает их для пользователей с доступом; это не сквозное шифрование переписки.

Обмен с Estate CRM

Go отправляет событие в отдельный HTTP-сервис. Получатель сохраняет его с уникальным event_id. Запрос и ответ каждой попытки остаются в журнале. При повторе после потери ответа CRM сообщает о существующей записи. Сценарии отказа работают только в демо.

Локальный поиск и OCR

Модель intfloat/multilingual-e5-small работает локально через ONNX. Векторы имеют размерность 384, индексируются PostgreSQL / pgvector. Для запроса и записи используются соответствующие префиксы query: и passage:.

OCR извлекает поля из изображения локально через Python и Tesseract. Сотрудник проверяет результат до сохранения карточки. При нераспознанном изображении интерфейс сообщает об ошибке; незашифрованные отладочные копии не создаются.

Каналы подтверждения и desktop

В исходной реализации обычный вход использует email-код и уведомление Telegram. В демо внешние отправки отключены: сообщения остаются в локальном журнале. MAX — вариант дополнительного подключения при внедрении. Упрощённый вход staff / staff отделён от обычного сценария.

Desktop-клиент использует C++ и Qt, авторизацию через браузер, WebSocket и системные уведомления. Фактически проверенные сборки указаны на странице приложений. Поддержка macOS не заявлена.

Публикация и восстановление

Каждый релиз хранится отдельно. Переключение current сопровождается проверкой здоровья API, сайта, CRM и поиска. При ошибке возвращается предыдущий релиз. Сервисы запускаются пользовательским systemd; обновления и откаты не требуют sudo. На диске сохраняются действующий и два предыдущих релиза.

База содержит только синтетические данные и восстанавливается ежедневно в 04:00 по Москве. Платежи, юридически значимая электронная подпись и государственная регистрация не входят в демонстрацию.