Журнал разработки Николая Ланца

9 сент. 2026 г.

Уточнение по подписи

Здесь нужен не копирайт в смысле права собственности, а видимая профессиональная подпись со ссылкой на страницу Николая Ланца, например:

Техническая архитектура и разработка — Николай Ланец

Для HTML-ссылки можно использовать rel="author" и title с описанием технической роли. Не писать © Николай Ланец, если правообладатель сайта, бренда и контента — клиент.

Центральная постановка: Связать профессиональную идентичность Николая Ланца с реализованными проектами через JSON-LD.

Добавить копирайт

9 сент. 2026 г.

Новое требование: связать HappyBaby2000 с персональной сущностью Николая Ланца

На сайте happybaby2000.ru добавить Organization + WebSite JSON-LD и указать техническое участие Николая через contributor с единым @id:

https://fi1osof.ru/about

Сущность должна ссылаться на персональную страницу Николая Ланца.

Правообладателем (copyrightHolder) и publisher остаётся организация клиента. Дополнительно использовать creditText по фактической роли. Не объявлять Николая владельцем, издателем или основателем клиентского бизнеса.

Центральная постановка: Связать профессиональную идентичность Николая Ланца с реализованными проектами через JSON-LD.

Проработать микроразметку

8 сент. 2026 г.

Новый личный кабинет использует действующую авторизацию MODX-пользователя

В production-версии нового личного кабинета реализован принципиально важный сценарий: новый frontend работает с текущей авторизацией пользователя MODX, а не вводит отдельную систему логина.

Пользователь, уже авторизованный в существующей системе, может перейти в новый кабинет и продолжить работу со своими данными и заявками. Это особенно важно для поэтапного запуска, потому что старый и новый личные кабинеты сейчас работают параллельно и должны восприниматься как две оболочки над одной учетной записью и одним backend.

Текущий результат подтверждает жизнеспособность схемы интеграции нового frontend с MODX authentication/session. На этой авторизации уже работает новый раздел заявок на пропуска.

При этом отдельная задача по корректной обработке context-specific авторизации mgr/web остается актуальной: production-интеграция использует текущего MODX-пользователя, но нюансы раздельных context tokens и неоднозначных состояний сессии необходимо довести до полностью формализованной и протестированной схемы.

Доработать MODX-авторизацию с учетом контекстов mgr/web

8 сент. 2026 г.

Унифицировал заявки на пропуска в GraphQL и новом личном кабинете

Исторически в системе Kilfor существовали три разных вида заявок на пропуска:

  • заявки на посетителей;
  • заявки на материальный внос/вынос;
  • заявки на въезд автомобилей.

Для этих типов используются разные наборы таблиц в базе данных, а в отдельных сценариях различается и набор полей. Структуру БД и существующую бизнес-логику я намеренно не менял, чтобы не затрагивать стабильный legacy backend.

Унификацию сделал на уровне GraphQL API и frontend. В GraphQL добавлен union type и единые резолверы, которые позволяют получать разные типы пропусков через общий интерфейс. В результате заявки из разных источников теперь читаются и выводятся единым списком независимо от того, в каких таблицах они физически хранятся.

На frontend реализована единая форма создания заявки с переключателем типа пропуска. Пользователь работает с одним интерфейсом, а нужный набор полей и логика формы адаптируются под выбранный сценарий: посетитель, материальный внос/вынос или автомобиль.

Это убрало историческое раздробление интерфейса на несколько отдельных страниц и форм, при этом сохранило существующую структуру данных и права доступа. Получился единый UX для заявок на пропуска без рискованной миграции данных и переписывания MODX backend.

Унифицировать интерфейсы заявок

8 сент. 2026 г.

Интеграция нового frontend с действующим MODX backend доведена до рабочего production-сценария

Новый личный кабинет подключен к существующей системе Kilfor без переноса или ломки текущей бизнес-логики MODX. Старый кабинет сохранен, а новый frontend подключен через отдельный маршрут, поэтому оба интерфейса работают параллельно.

Ключевой момент интеграции — новый интерфейс использует текущую авторизацию MODX-пользователя. Пользователю не требуется создавать отдельную учетную запись или повторно входить в новую систему: frontend работает в рамках существующей MODX-сессии и получает данные текущего авторизованного пользователя.

Это позволило реализовать постепенную миграцию личного кабинета с legacy frontend MODX на новый движок без дублирования пользователей и без отдельной системы аутентификации. Архитектурно новый frontend остается отдельным приложением, но использует существующий backend, текущие данные и авторизационный контекст MODX.

Первым полноценно перенесенным бизнес-сценарием стал раздел заявок на пропуска: посетители, материальный внос/вынос и автомобили теперь доступны через новый единый интерфейс.

Организовать интеграцию нового frontend с существующим MODX backend

8 сент. 2026 г.

Выкатил новый личный кабинет Kilfor на новом движке

Развернут и подключен новый frontend личного кабинета Kilfor на новом движке. Полная замена старого интерфейса пока сознательно не выполнялась: проект связан с действующими бизнес-процессами арендаторов и требует аккуратного поэтапного перехода без риска остановить привычные сценарии пользователей.

На текущем этапе реализован дополнительный роутинг на отдельный подраздел нового приложения и добавлена ссылка на новый личный кабинет. В результате старый личный кабинет MODX продолжает работать параллельно, а пользователи могут выбрать старый или новый интерфейс.

Такой режим позволяет постепенно переводить функциональность на новый frontend, проверять реальные пользовательские сценарии в production и сохранять возможность быстрого возврата к legacy-интерфейсу для тех разделов, которые еще не перенесены.

Уже перенесён и существенно переработан раздел заявок на пропуска. Новый личный кабинет используется не как статичная оболочка, а как рабочий интерфейс поверх существующего MODX backend и действующих данных.

Разработать новый frontend kilfor.ru на haih-agent

6 сент. 2026 г.

Assets Proxy Middleware для legacy-ассетов

В новой реализации добавлен middleware для обслуживания статических файлов legacy-сайта по пути /assets/.

Исходная проблема

Rails Asset Pipeline исторически разрешал ссылки на ассеты не напрямую по физическому расположению файла, а через собственный механизм поиска и manifest. В результате фактические файлы могут находиться в разных подкаталогах, тогда как HTML и CSS продолжают ссылаться на них через упрощённые пути.

На практике обнаружены как минимум следующие варианты хранения:

  • shared/assets/ — основные ассеты;
  • shared/assets/stylesheets/ — CSS и связанные файлы;
  • shared/assets/stylesheets/fonts/ — шрифты.

При этом клиентские ссылки могут выглядеть как /assets/filename.css или относительные url(font.woff2) без указания реального подкаталога. В старом Rails-приложении это скрывалось логикой Asset Pipeline.

Реализованное решение

Добавлен middleware server/middleware/assetsProxy.ts, который перехватывает запросы к /assets/ и последовательно ищет запрошенный файл в нескольких известных legacy-каталогах.

Порядок поиска:

  1. shared/assets/
  2. shared/assets/stylesheets/
  3. shared/assets/stylesheets/fonts/

Клиенту отдаётся первый найденный подходящий файл. Таким образом новая система воспроизводит необходимую часть поведения Rails Asset Pipeline без переноса самого pipeline.

Безопасность

В middleware предусмотрены базовые ограничения против выхода за пределы каталога ассетов:

  • блокируются пути с ..;
  • блокируются двоеточия в пути;
  • после нормализации проверяется, что resolved path остаётся внутри shared/assets/.

Значение для миграции

Это решение позволяет корректно отображать legacy-страницы и стили во время переходного периода без ручного переписывания большого количества исторических ссылок на ассеты. При этом compatibility-логика изолирована в одном месте и не проникает в основную модель данных или маршрутизацию haih-cms.

Дальнейшая проверка

  • проверить корректные MIME-типы для CSS, JS, шрифтов и изображений;
  • проверить cache headers;
  • проверить поведение при совпадающих именах файлов в нескольких каталогах;
  • убедиться, что middleware не позволяет читать файлы вне разрешённого дерева;
  • по мере нормализации ассетов решить, нужен ли proxy как постоянный слой или только как миграционная совместимость.
Сделать универсальный рендеринг и маршрутизацию Concepts

6 сент. 2026 г.

Legacy-дефект: социальная авторизация в форме обратной связи не работает

В интерфейсе формы обратной связи пользователю предлагаются четыре варианта социальной авторизации:

  • Google+ (/auth/gplus)
  • ВКонтакте (/auth/vkontakte)
  • Twitter (/auth/twitter)
  • Facebook (/auth/facebook)

Фактически ни один из этих сценариев сейчас не работает.

Почему это важно

Это ещё один показательный пример деградации legacy-функциональности: интерфейс продолжает обещать пользователю возможности, которые технически уже не существуют или не поддерживаются. Для посетителя это выглядит как поломка сайта, а для сопровождения создаёт ложный объём функциональности, который приходится отдельно исследовать.

Отдельно примечательно наличие Google+ — сервиса, давно закрытого для потребительского использования. Сам факт сохранения такого пункта в актуальном интерфейсе показывает, насколько легко внешние интеграции превращаются в технический долг, если их не пересматривать регулярно.

Вывод для новой версии

Социальную авторизацию нельзя переносить только потому, что она присутствует в старом интерфейсе. Для haih-cms нужно заново определить, нужна ли пользователю авторизация вообще, и если нужна — реализовать только актуальные и реально поддерживаемые сценарии.

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

Практический эффект для миграции

Legacy OAuth-маршруты следует рассматривать как исторический функционал, а не как обязательное требование к новой реализации. Их наличие нужно учитывать при инвентаризации, но не воспроизводить без подтверждённой пользовательской ценности.

Реализовать формы и актуальные публичные интеграции заново

6 сент. 2026 г.

Вывод по внутреннему качеству legacy-сайта

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

Характерный пример: основной контент обычной страницы хранится в поле description, тогда как контент главной страницы находится уже в системных настройках сайта. Такая структура неочевидна без изучения исходников и фактического поведения приложения.

Почему это важно

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

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

Вывод для новой реализации

Удобная и предсказуемая механика управления контентом — не декоративное улучшение CMS, а обязательная часть жизнеспособности сайта. Новая реализация должна снижать стоимость повседневных изменений и делать структуру данных понятной без необходимости каждый раз исследовать внутренности системы.

Хороший сайт должен быть не только удобен посетителю, но и не вызывать сопротивления у тех, кто его сопровождает и наполняет.

Инвентаризация текущего Ruby-сайта

5 сент. 2026 г.

Наблюдение по текущему legacy-сайту: Mixed Content

На публичной HTTPS-странице обнаружена загрузка внешнего JavaScript-ресурса по небезопасному HTTP:

http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js

Современный браузер блокирует такой запрос как Mixed Content. В результате часть клиентской логики, зависящая от этого скрипта, потенциально может не работать.

Значение для проекта

Это наглядный пример того, почему даже работающий сайт нельзя считать системой, которую можно однажды запустить и затем годами не обслуживать. Внешние зависимости, браузерные требования, TLS-политики, CDN, библиотеки и стандарты безопасности со временем меняются, даже если код самого сайта остаётся неизменным.

При новой реализации на haih-cms стоит закладывать регулярную техническую проверку публичного сайта: отсутствие Mixed Content, состояние внешних зависимостей, ошибки браузера, актуальность сертификатов, корректность форм, sitemap и других критических компонентов.

Практический вывод

Legacy-сайт использовать только как источник данных и reference. В новой версии избегать жёстко зашитых небезопасных внешних URL и по возможности минимизировать зависимость от сторонних ресурсов, которые могут со временем изменить поведение или стать недоступными.

Миграция bizneshelper.ru с Ruby на haih-cms

5 сент. 2026 г.

Изменение сценария запуска

Постоянная параллельная эксплуатация Ruby- и haih-cms-версий не требуется. План запуска теперь предполагает разовое переключение на новую систему после переноса данных и тестирования.

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

Подготовить переключение на haih-cms и резервный откат

5 сент. 2026 г.

Изменение SEO-подхода

SEO новой версии строится как самостоятельный слой haih-cms. Старые метаданные и маршруты не копируются механически. Поисковая преемственность обеспечивается точечно для ограниченного набора реально значимых legacy-страниц через SEO-карту и прямые 301-редиректы.

Сформировать SEO-слой нового сайта и обеспечить поисковый переезд

5 сент. 2026 г.

Изменение подхода к формам и интеграциям

Legacy-реализация форм, OAuth и внешних интеграций не переносится автоматически. На новом сайте будут заново реализованы только фактически нужные пользовательские сценарии.

Это позволяет избавиться от зависимости от старых Rails-гемов и устаревших провайдеров и не переносить функциональность только ради совместимости.

Реализовать формы и актуальные публичные интеграции заново

5 сент. 2026 г.

Изменение стратегии URL

Отказались от идеи сохранять полную обратную совместимость со всей legacy-структурой адресов. Поскольку в поисковом индексе находится порядка 85 страниц, задача теперь ограничена управляемой SEO-картой значимых URL: старый адрес → новая страница → сохранить/301/удалить.

Новая структура haih-cms считается основной и канонической; Rails-маршрутизация целиком не воспроизводится.

Подготовить SEO-карту значимых URL и редиректы

5 сент. 2026 г.

Корректировка границ инвентаризации

Полный reverse engineering Ruby-приложения больше не является целью. Инвентаризация должна отвечать на практический вопрос: какие сущности, поля, медиа, URL и пользовательские сценарии действительно нужны для нового сайта и миграции данных.

Legacy-сайт используется как reference и backup. Неиспользуемые части старого кода и исторические маршруты исследуются только если они влияют на данные или публичный функционал, который нужно перенести.

Инвентаризация текущего Ruby-сайта

5 сент. 2026 г.

Корректировка стратегии миграции

После успешного локального запуска legacy Ruby-сайта уточнён подход к проекту. Старое Rails-приложение не рассматривается как система, которую необходимо поддерживать параллельно с новой версией. Его роль — резервная копия, источник данных и эталон для сверки.

Ключевое решение: выполнить одноразовую миграцию нужных данных и публичного контента в haih-cms, после чего новая версия становится единственным актуальным production-сайтом.

Полная обратная совместимость со всей исторической маршрутизацией не требуется. В поисковом индексе находится ограниченное число страниц — порядка 85, поэтому SEO-преемственность будет обеспечиваться точечно для реально значимых URL.

В связи с этим пересмотрены задачи по инвентаризации, модели данных, URL и редиректам, формам, SEO, тестированию и запуску. Добавлена отдельная задача по воспроизводимому импорту данных из legacy MySQL в haih-cms.

Миграция bizneshelper.ru с Ruby на haih-cms

5 сент. 2026 г.

Уточнение по воспроизводимости Docker-запуска

При перезапуске контейнера обнаружена типичная для legacy Rails проблема: приложение пишет runtime-файлы непосредственно внутрь дерева проекта, которое целиком подключено в контейнер как bind-mount.

Обнаруженная ошибка

Rails отказывался стартовать с сообщением A server is already running, потому что после предыдущего запуска в tmp/pids/ сохранялся server.pid. При аварийной остановке или пересоздании контейнера этот файл оставался на хостовой файловой системе вместе с проектом.

Причина

В контейнер монтируется весь каталог сайта. Это создаёт сразу два эффекта:

  1. Содержимое, подготовленное в образе внутри каталога приложения, может быть перекрыто bind-mount содержимым хоста после старта контейнера. Поэтому установку зависимостей, завязанную на состояние смонтированного проекта, нельзя надёжно считать завершённой только на этапе сборки Dockerfile.
  2. Runtime-файлы Rails (tmp/pids и потенциально другие временные данные) сохраняются внутри смонтированного каталога и переживают жизненный цикл контейнера. Старый PID-файл затем блокирует новый запуск.

Принятое решение

Команда запуска сервиса дополнена подготовительным шагом:

rm -rf /app/tmp/pids/ && (bundle check || bundle install --frozen) && bundle exec rails server -b 0.0.0.0

Логика запуска теперь такая:

  • перед стартом удаляются старые PID-файлы Rails;
  • bundle check быстро проверяет наличие нужных гемов;
  • bundle install --frozen выполняется только если зависимости отсутствуют или неполны;
  • после подготовки запускается Rails-сервер, слушающий интерфейс контейнера.

Архитектурный вывод

Текущая Docker-схема ориентирована на максимально прямое воспроизведение legacy-проекта через bind-mount исходников, а не на полностью immutable-образ. Для исследовательской миграционной среды это допустимо, но важно учитывать, что состояние проекта и runtime-контейнера частично смешиваются.

При дальнейшем использовании окружения стоит отдельно контролировать каталоги tmp, log, загружаемые файлы и зависимости, чтобы временные файлы legacy-приложения не влияли на повторяемость запуска. Если окружение потребуется использовать длительно или передавать другим разработчикам, имеет смысл вынести изменяемые runtime-каталоги в отдельные volumes либо исключить их из bind-mount схемы.

Результат

После изменения команды запуска контейнер корректно переживает повторные старты и сам восстанавливает недостающие зависимости без ручного удаления Rails PID-файлов.

Локально развернуть исходный Ruby-сайт

5 сент. 2026 г.

Уточнение по результатам локального запуска

Локальное развёртывание legacy-сайта завершено успешно, что позволило подтвердить часть ранее предположительных данных.

Подтверждено

  • Исходная серверная среда использовала Ruby 2.2.5 через Passenger.
  • Rails 3.2.21 совместим с запуском в контейнере на Ruby 2.2.10.
  • Legacy-приложение использует MySQL по сетевому подключению при явном указании host.
  • Более новая ветка ckeditor несовместима с Rails 3.2; рабочий вариант требует фиксации совместимой версии 4.0.x.
  • В проекте присутствуют каталоги и файлы, характерные для Rails 5 (app/channels, app/jobs), хотя основное приложение остаётся Rails 3.2. Это важно учитывать при анализе структуры исходников: не все файлы в дереве проекта являются частью реально работающего legacy-runtime.

Вывод для инвентаризации

Теперь проект можно исследовать не только статически по коду и дампу, но и динамически через локально работающую копию. Это позволяет сверять модели, маршруты и содержимое с фактическим поведением сайта и снижает риск ошибочной миграции неиспользуемых или исторически оставшихся компонентов.

Следующий приоритет — пройти по публичным маршрутам, проверить media-связи, поиск, формы и административную часть, сопоставляя наблюдаемое поведение с routes.rb, моделями и схемой БД.

Инвентаризация текущего Ruby-сайта

5 сент. 2026 г.

Локальный запуск legacy Ruby-сайта выполнен

Старый bizneshelper.ru успешно запущен локально в Docker.

Подтверждённая конфигурация legacy-среды

  • Ruby on Rails 3.2.21.
  • На исходном сервере использовался Ruby 2.2.5 через Passenger.
  • Для контейнера использован Ruby 2.2.10 как совместимая версия той же ветки.
  • Bundler 1.15.4.
  • MySQL используется как внешняя уже поднятая служба.
  • Сайт запускается в production-окружении.

Что было сделано

  • Подготовлен Dockerfile для старого Ruby-стека на базе Ruby 2.2.10.
  • Для Debian Jessie переключены apt-источники на архивные репозитории, так как штатные репозитории этой версии больше недоступны.
  • Установлены необходимые системные зависимости для сборки legacy-гемов и работы MySQL/libv8.
  • Сервис bizneshelper добавлен в docker-compose и подключён к существующей MySQL-службе через переменные окружения.
  • Настроен отдельный локальный порт для доступа к приложению.
  • В database.yml добавлена поддержка подключения к MySQL по host вместо локального Unix socket.
  • Версия ckeditor понижена до совместимой с Rails 3.2 ветки.
  • Подтверждено, что наличие Rails 5-ориентированных каталогов app/channels и app/jobs не блокирует запуск при текущей production-конфигурации с отключённой агрессивной загрузкой классов.

Обнаруженные особенности и риски

  1. Debian Jessie требует использования архивных репозиториев и специальных параметров установки пакетов.
  2. Часть legacy-гемов несовместима с современными версиями библиотек и требует фиксации старых версий.
  3. mysql2 старой ветки чувствителен к окружению и способу подключения к MySQL.
  4. ckeditor в более новой версии использует API Rails 4+ и поэтому должен быть зафиксирован на совместимой версии.
  5. В исходном проекте присутствуют артефакты более новых Rails-версий, что указывает на исторические изменения проекта и требует осторожности при автоматической миграции кода.

Результат

Legacy-сайт воспроизводимо запускается локально и доступен как эталон для дальнейшей инвентаризации, сравнения поведения и миграции на haih-cms.

Что проверить далее

  • Полноту отображения ключевых страниц и форм.
  • Работу поиска с Solr.
  • Корректность загрузки legacy-медиа.
  • Поведение админки.
  • Фактические маршруты, friendly_id и редиректы.
  • Соответствие локальной базы исходной структуре данных.

В открытом worklog не фиксируются пароли, локальные абсолютные пути и иные чувствительные параметры среды.

Локально развернуть исходный Ruby-сайт

Написать мне