RRestoria
Открытый журнал

Отчёт о развитии системы Restoria

Работы по сайту, CRM, ботам и интеграциям пошагово и постоянно сохраняются на этой странице.

Последнее обновление: Записей: 24
Безопасность и RBAC

Усилены границы уведомлений, заказов, интеграций и полномочий

Выполнено

Финальный аудит чтения и записи API/CRM выявил дополнительные строгие границы для уведомлений dashboard, приватности заказа, профиля курьера, делегирования полномочий сотрудников и публичных callback Instagram. Исправления опираются на серверные permissions, а UI больше не показывает и не вызывает действия без действующего права.

  • API уведомлений отдаёт только канал DASHBOARD и безопасные поля без recipient; аудитории admin, manager и receptionist разделены
  • Текст WebSocket-уведомления не транслируется: только код события уходит в комнату соответствующего permission
  • Колокольчик CRM без dashboard.view скрыт и не вызывает API уведомлений
  • Мастер получает только заказ, назначенный напрямую, через stage или task; ОТК — только заказы своей очереди и истории задач ОТК
  • Для мастера и ОТК сервер удаляет телефон/каналы/адрес клиента, delivery-details, payments и клиентские цены
  • Order search, карточка, allowed transitions, этапы и event feed используют одну row-level проверку; финансовые события не попадают в feed без права
  • Excel-экспорт привязан к reports.finance, PDF — к receipts.print, payment-link — к orders.finance, каталог и прайс — к price.view
  • Карточка заказа открывается после загрузки прав и показывает только разрешённые finance/status/assign/courier/payment/discount/document блоки
  • Приёмщик сохраняет список курьеров и заявки доставки; создание, редактирование и деактивация профиля курьера требуют routes.manage
  • Точка доставки проверяется DTO и service по существующему заказу, ISO-дате, слоту, координатам, stage и активному курьеру; завершённая точка не редактируется
  • Делегированный users.manage не может выдать роль или permission выше собственных; защищены SUPERADMIN и последний активный владелец
  • Instagram POST webhook закрыт без HMAC raw-body; public manual/mock fallback удалён, OAuth state хранится хешем, живёт 10 минут и одноразовый
  • Сервисные ключи PBX, ботов и tracking используют общее constant-time сравнение
  • Новый и сменяемый пароль валидируется как 8–128 символов на DTO и service; существующие логин и пароль не менялись
  • Успешно: 34 backend suites, 265/265; все production-сборки, Prisma validate, npm audit 0 и Flutter format/analyze/test
  • Production RBAC API-приёмка 19/19: проверены поля notification, scope/redaction мастера, 403 приёмщика и unsigned webhook без записи в БД
  • Общая read-only production-приёмка 17/17: работают API/DB health, HTTPS и fail-closed интеграции
  • Browser smoke через реальный HTTPS 73/73: разрешённые и запрещённые страницы 8 активных ролей, persistence resize заказа и 3 публичные страницы
  • API, CRM, сайт и оба бота online в PM2; milestone виден в публичном отчёте, код отправлен в удалённую Git-ветку
Roadmap P1–P3

Завершены мобильный рабочий поток, порядок маршрута и удобство таблицы

Выполнено

Мастера получили в мобильном приложении приём этапа, возврат с причиной, безопасное внутреннее фото из камеры или галереи, завершение только после фото и просмотр собственного заработка. CRM атомарно сохраняет drag-and-drop порядок внутри маршрута, а ширина колонок заказов меняется мышью, касанием или клавиатурой и сохраняется в браузере. Одновременно закрыто несоответствие ownership, позволявшее сотруднику другой роли обратиться к действию чужой задачи или курьерской точки.

  • Действия этапа в мобильном приложении используют существующую role/owner-защиту backend и безопасное декодирование/перекодирование изображений
  • Экран заработка за месяц или всё время получает только профиль мастера из JWT; границы дат строго проверяются как полные локальные дни
  • Production API задан по HTTPS; release-manifest запрещает cleartext-трафик и не содержит ненужного разрешения геолокации
  • Android scaffold, Gradle wrapper и pubspec.lock добавлены в Git для воспроизводимой сборки; local property, key и keystore остаются секретными
  • Release AAB проверен с настоящим non-debug upload-key; при неполной настройке signing release-сборка завершается fail-closed
  • Внутренний порядок маршрута принимает только полный актуальный список UUID и записывает все sortOrder одной транзакцией
  • Точки TO_MASTER/FROM_MASTER включены в алгоритм и карту; завершение продолжает нужный stage и не переводит заказ ошибочно в статус «выдан»
  • Callback внешнего мастера сделан retry-safe: открытая задача не дублируется, этап повторно не уходит в ОТК, а при ошибке callback статус точки компенсируется
  • Ручной перенос не отменяет выбранного курьера повторным запуском алгоритма; старый и новый списки последовательно нормализуются
  • Действия курьера защищены по роли, владельцу точки, статусу, причине и сумме; чужой маршрут и action закрыты для остальных ролей tasks.my
  • Колонки заказов меняются в пределах 64–480 px мышью/клавиатурой, повреждённые значения storage очищаются, доступен reset
  • Успешно: 27 backend suites, 240/240; Flutter format/analyze/test, все production-сборки, Prisma validate и npm audit 0
  • Production read-only acceptance 17/17: подтверждены API health, БД, HTTPS, auth и fail-closed интеграции
  • Browser smoke через реальные HTTPS-домены 24/24: 20 страниц CRM, resize→reload persistence и 3 публичные страницы
  • Production API мастера: earnings 200, телефон клиента скрыт; чужие route/action дают 403, неполный order отклонён 400 без записи в БД
  • API, CRM, сайт и оба бота online в PM2; новый milestone виден в публичном отчёте, commit отправлен в удалённую Git-ветку
Production-приёмка

Доступная без внешних данных часть roadmap передана в production

Выполнено

Сайт, CRM, API, боты, media CMS, зависимости и fail-closed интеграции прошли единый финальный цикл приёмки. Старые acceptance/smoke-скрипты, записывавшие данные в production, заменены read-only проверками, устаревшие заявления о mock и открытых LAN-портах исправлены. Оставшиеся пункты требуют только внешних credentials, реальных медиа или sudo-доступа владельца.

  • Успешно: 230/230 backend-тестов, четыре production-сборки и npm audit 0
  • Read-only production acceptance: 17/17; тестовые user, lead, order, payment или call не создавались
  • Read-only browser smoke через реальные HTTPS-домены: 20 страниц CRM и 3 публичные, успешно 23/23
  • CRM→API→public media E2E: PNG→WebP, настоящий MP4, публичная выдача и полный cleanup БД/файлов
  • Два старых 4×4 тестовых PNG без связи с БД перемещены в восстанавливаемую Корзину; БД и каталог галереи чисты
  • Prisma 6.19.3 работает в production: health, 15 migrations и нулевой schema-diff
  • Финальный atomic snapshot: 339 объектов БД и 9 медиа; изолированный restore: 45 таблиц и 9/9 медиа
  • API, CRM, сайт и оба бота online в PM2; публичный сайт, отчёт и CRM отвечают HTTP 200
  • 3000/3001/3002 только на 127.0.0.1; payment mock/webhook 503, PBX без ключа 403, delivery 503 без изменения БД
  • Все commits кода и отчёта отправлены в удалённую Git-ветку
Слой данных

Prisma контролируемо обновлена с 5.22 до 6.19.3

Выполнено

Prisma ORM и Client переведены на единую версию 6.19.3. Официальный список breaking changes проверен по schema и коду, CLI-конфигурация перенесена в отдельный prisma.config.ts. К production-БД не применялось неизвестных изменений schema.

  • Node 22.14 и TypeScript 5.6 соответствуют требованиям Prisma 6
  • Не найдены Bytes-поля, старый NotFoundError, middleware $use и неявные PostgreSQL many-to-many связи
  • Prisma Client 6.19.3 успешно сгенерирован, schema валидна
  • Все 15 миграций production-БД актуальны, schema-diff: “No difference detected”
  • prisma.config.ts детерминированно задаёт root .env, schema, migration path и seed-команду
  • Пройдены 230 backend-тестов, все production-сборки и аудит с 0 уязвимостей
  • Prisma 7 одновременно меняет ESM, output клиента, PostgreSQL driver adapter и pool-семантику, поэтому вынесена в отдельную архитектурную миграцию
Безопасность интеграций

Delivery, АТС и платёжные адаптеры переведены в честный fail-closed режим

Выполнено

Пока нет договора и проверенного реального адаптера, production больше не создаёт фиктивный трек Yandex, запись «звонок отвечен» или результат упрощённого webhook Payme/Click/Uzum. CRM явно показывает состояние интеграции; собственные курьеры, подтверждённые вручную звонки и наличный/терминальный поток продолжают работать.

  • DELIVERY_PROVIDER в production установлен в disabled; mock возможен только в test/development
  • Один токен Yandex без реального API-вызова не может перевести задачу в статус «в пути»
  • Payme, Click и Uzum сохранены в CRM, показаны как «не подключены» и недоступны для выбора
  • Упрощённые методы invoice/webhook реальных платежей удалены и закрыты до contract-тестов
  • Ключ АТС отделён от bot-key, имеет минимум 32 символа и принимается только через заголовок X-PBX-Key
  • Ключ АТС сравнивается constant-time, webhook защищены rate-limit
  • Click-to-call без АТС больше не создаёт ложный ANSWERED; открывается набор номера устройства
Безопасность credentials

Безопасно ротированы production JWT и ключ внутреннего сервиса

Выполнено

Строгая проверка после deploy обнаружила, что в старой конфигурации сохранился шаблон ключей, характерный для development. Без публикации значений они были атомарно заменены отдельными криптографически случайными ключами; все сервисы одновременно перезагружены с новой конфигурацией. Ради безопасности прежние сессии CRM аннулированы, логин и пароль не менялись.

  • JWT и ключ bot-service раздельно созданы из 48 криптографически случайных байт
  • Замена выполнена через временный файл и atomic rename без вывода значений в терминал
  • Validator теперь отклоняет шаблоны local/development/sample/test и совпадение двух ключей
  • Проверено без показа значений, что активный процесс API загрузил именно обновлённые ключи
  • API, CRM, сайт и оба Telegram-бота online; health и публичные страницы отвечают 200
Основной сайт и CMS

Сайт дополнен, в CRM добавлено безопасное управление реальными медиа

Выполнено

На главную добавлены направления услуг, советы по уходу, удобная навигация, блок видео реальных работ, SEO structured data и улучшения accessibility. CRM теперь управляет текстами RU/UZ, парами «до/после», их порядком и видео процесса. Пока подтверждённых реальных медиа нет, сайт честно помечает текущую графику как иллюстрацию.

  • Главная дополнена 6 направлениями услуг, 4 советами по уходу и понятными CTA
  • В CRM создано управление двуязычными текстами сайта, галереей и видео
  • Изображения галереи декодируются на сервере, очищаются от EXIF/метаданных, уменьшаются до 2000 px и переводятся в WebP
  • Видео процесса принимается только по сигнатуре MP4/WebM, под UUID-именем и с лимитом 30 МБ
  • Для публикации финального фото заказа требуется реальное фото «до» и клиентский уровень видимости медиа
  • Проверены URL, координаты карты, lazy-loading, skip-link для клавиатуры, JSON-LD и двуязычные alt/aria-тексты
  • Успешно пройдены 222 backend-теста, все production-сборки и аудит зависимостей; уязвимостей: 0
Безопасность зависимостей

Next.js и NestJS контролируемо обновлены до безопасных версий

Выполнено

Сайт и CRM переведены на Next.js 15.5.20, API — на NestJS 11.1.28 и линию Express 5. Каждое breaking-изменение адаптировано в коде; аудит framework, upload и транзитивных пакетов доведён до нуля уязвимостей.

  • Исходный npm audit: 29 записей; итоговый аудит: 0
  • Все публичные страницы адаптированы к async API route-параметров Next.js
  • Peer-пакеты NestJS объединены в единый dependency-граф 11.1.28
  • Установлена production-линия Multer 2.2 и Express 5
  • Срок JWT проверяется в строгом формате и преобразуется в безопасное числовое значение
  • Успешно пройдены 216 backend-тестов и production-сборки всех четырёх приложений
Границы сервера

Закрыты внутренние порты и усилена production-конфигурация

Выполнено

API, CRM и сайт теперь слушают только loopback-интерфейс сервера; единственным внешним входом остаётся Nginx. PM2 детерминированно загружает root env и принудительно задаёт production, а backend не запускается с опасной конфигурацией.

  • Порты 3000, 3001 и 3002 слушают только адрес 127.0.0.1
  • NODE_ENV=production проверен у всех пяти сервисов PM2
  • Удалены development-fallback для JWT и внутренних сервисных ключей
  • Production CORS сокращён до официальных HTTPS-origin
  • Публичный домен возвращает 404 для внутренних stage-медиа и 200 для галереи
  • CSP/headers и границы uploads для Nginx готовы в Git; применение требует root-доступ сервера
Резервное копирование

Внедрены атомарный backup БД и медиа и реальный restore-тест

Выполнено

Ежедневная задача systemd объединяет PostgreSQL и локальные медиа в единый версионированный snapshot, проверяет SHA-256 и применяет daily/weekly/monthly retention. Еженедельный тест восстанавливает копию в отдельную временную БД и каталог.

  • В реальном snapshot сохранены 339 объектов БД и 11 медиафайлов
  • Изолированный тест успешно восстановил 45 таблиц и все 11 медиафайлов
  • Сервисы systemd backup и restore повторно проверены с exit-code 0
  • Добавлены lock от параллельного запуска и атомарный staging
  • Offsite не запускается без полного набора данных; готовый поток шифрует AES-256 и проверяет обратную расшифровку
Безопасность входа

Безопасно восстановлен SUPERADMIN-доступ владельца системы

Выполнено

После подтверждения владельца для единственной активной учётной записи SUPERADMIN установлен новый сильный временный пароль. Секретные данные не добавлялись в отчёт или код.

  • Сброс применён только к одной точно найденной активной учётной записи SUPERADMIN
  • Операция записана в audit-log сервера без секретных данных
  • Новые данные успешно проверены через реальный API входа
Безопасность медиа

Все потоки загрузки файлов переведены на единые безопасные правила

Выполнено

Медиа этапов, клиентов, галереи, Telegram и звонков больше не доверяют присланному имени или MIME. Сервер проверяет тип по содержимому, создаёт безопасное UUID-имя и применяет строгий лимит размера.

  • Изображения принимаются только с сигнатурой JPEG, PNG или WebP
  • Фото этапа может загрузить только назначенный мастер или администратор
  • Аудио проверяется и хранится только как MP3, WAV, OGG или M4A
  • Записи АТС загружаются только с отдельно разрешённого HTTPS-хоста, без redirect и до 50 МБ
  • Документы Telegram хранятся в неисполняемом бинарном формате, исходное имя — только для безопасного отображения
  • Существующее хранилище проверено: типы файлов соответствуют ожидаемым форматам
Следующий этап

Усиление резервного копирования и восстановления

В работе

Локальный snapshot БД+медиа, retention и реальный restore-тест завершены. Осталось включить AES-256 offsite-копию после получения внешнего S3 endpoint, bucket, access key и отдельного пароля шифрования.

  • БД и медиа включены в единый атомарный цикл копирования
  • Дневное/недельное/месячное хранение работает
  • Тест восстановления выполнен без воздействия на production-данные
  • Данные доступа к внешнему storage пока отсутствуют на сервере
Безопасность сервера

Усиление портов, security-заголовков и production-конфигурации

В работе

Loopback-порты, строгая production env-проверка и граница публичных медиа уже работают. Конфигурация CSP и дополнительных заголовков Nginx готова, но для установки в `/etc/nginx` требуется root-доступ.

  • Состояние портов и firewall повторно проверено
  • API, CRM и сайт переведены на loopback и прошли smoke-тест
  • Конфигурация Nginx подготовлена с rollback через Git
  • Осталось: установка с root, nginx -t, reload и smoke-тест заголовков
Технический долг

Контролируемое обновление framework и библиотек

Выполнено

Next.js, NestJS, Express, Multer и транзитивные пакеты обновлены до безопасных линий; миграция Prisma 6.19.3 завершена со schema-diff. Уязвимостей в аудите не осталось. Prisma 7 вынесена в безопасный отдельный цикл из-за архитектурных изменений ESM и driver-adapter.

  • 29 записей аудита сокращены до 0
  • Миграция Next.js и NestJS завершена с тестами и build
  • Миграция Prisma 6.19.3 завершена: 15 актуальных migrations и нулевой schema-diff
  • Зафиксирована безопасная граница отдельной архитектурной миграции Prisma 7
Основной сайт

Наполнение, развитие и улучшение удобства Restoria.uz

В работе

База контента, UX, SEO и CMS сайта завершена. Безопасный технический поток галереи и видео готов; оставшийся контентный этап — загрузить через CRM реальные фото «до/после» и видео процесса с разрешением клиентов.

  • Дополнены услуги, цены, сроки, уход, CTA Telegram/телефон и путь к отслеживанию
  • Готово управление RU/UZ-контентом, WebP-галереей, video poster и видео процесса из CRM
  • Проверены SEO structured data, lazy-loading и основные требования accessibility
  • Осталось: загрузить одобренные владельцем реальные медиа с описанием и категорией
Интеграции

Подключение реальных платёжных провайдеров и АТС по договору

В работе

Fail-closed защита production завершена: неподключённые Payme, Click, Uzum, Yandex Delivery и АТС не создают фиктивный результат. Оставшийся внешний этап — договоры с выбранными провайдерами, официальные credentials, sandbox и contract-тесты подписи/idempotency.

  • Неподключённые провайдеры видны в CRM, но недоступны для выбора
  • Production mock/fallback для payments, delivery и АТС закрыт
  • Осталось: официальные credentials провайдеров и sandbox contract-тесты
Защита данных

Защищены realtime-канал и границы публичного API

Выполнено

WebSocket CRM проверяет JWT, активность аккаунта и индивидуальные права. События отправляются только в соответствующие permission-room. Публичный endpoint текстов возвращает только необходимые сайту поля org.

  • WebSocket без токена не получает события
  • Событие звонка получают только роли с правом просмотра клиентов
  • Настройки AI и каналов исключены из public texts
  • Демо-отзывы и внутренние поля review исключены из публичного ответа
Безопасность Telegram

Защищены идентификация ботов и поток медиа

Выполнено

Клиентский и служебный боты теперь связывают профиль только через собственный Telegram-контакт пользователя. Существующая привязка не заменяется незаметно. Фото больше не сохраняются URL-адресом с токеном Telegram — они проверяются и копируются в хранилище Restoria.

  • Владелец контакта проверяется по Telegram user ID
  • К endpoint дохода сотрудника добавлена проверка сервисного ключа
  • Задачи и точки курьера проверяются на принадлежность исполнителю
  • Закрытие многоэтапной работы через бот без обязательного фото заблокировано
  • Тип изображения определяется по реальной сигнатуре байтов, а не имени файла
Безопасность платежей

Тестовые онлайн-платежи закрыты в production

Выполнено

Mock-ссылка и вебхуки без проверенной подписи больше не могут подтверждать оплату в production. До полноценных тестов подписи и транзакций реальных адаптеров Payme/Click система остаётся fail-closed.

  • Production PAYMENT_PROVIDER переведён в disabled
  • Mock-режим работает только вне production
  • В CRM провайдеры видны как неподключённые и заблокированы; Telegram-бот не выдаёт ссылку
  • С сайта удалены несоответствующие обещания Payme/Click
Безопасность входа

Закрыт публичный вход демо-администратора

Выполнено

С формы входа CRM удалены готовые телефон и пароль. Старый публично известный аккаунт отключён, его прежние сессии стали недействительными, а пароль заменён невосстанавливаемым значением.

  • Перед блокировкой проверено наличие другого активного SUPERADMIN
  • Старый демо-вход возвращает 401 на уровне API
  • Production-данные входа удалены из seed- и тестовых скриптов
  • Операция записана в серверный audit-log
Прозрачность

Создан постоянный отчёт о развитии

Выполнено

Внедрён постоянный двуязычный журнал, в котором по шагам сохраняются безопасные изменения сайта, CRM и интеграций.

  • Источник отчёта сохраняется в истории Git
  • Страница работает на русском и узбекском языках
  • Секреты и инструкции по эксплуатации уязвимостей не публикуются
Безопасное начало

Начат контролируемый процесс изменений

Выполнено

Остановлена автоматическая отправка непроверенного кода. До изменений созданы снимки базы данных и локальных медиа, работа вынесена в отдельную ветку.

  • Production-сервисы продолжили работать
  • Резервная копия БД успешно создана
  • Снимок медиа проверен контрольной суммой
Аудит

Проведён полный read-only аудит сайта и CRM

Выполнено

Проверены архитектура, API, конвейер заказов, боты, платежи, маршруты, резервное копирование, SEO и конфигурация сервера. Исправления расставлены по уровню риска.

  • Успешно пройдены 192 backend-теста
  • Все 15 миграций БД актуальны
  • Все production-сервисы находятся online
Вернуться на главную
Отчёт о развитии — Restoria