Предполагаемая топология сети заказчика, целевой стек и порядок замены складской программы на Delphi 7 / InterBase — без остановки работы склада.
Обследование ещё не проводилось. Точных сведений о топологии сети нет: схема ниже построена на типовом устройстве сети предприятия такого размера и на предположении, что шлюзом служит MikroTik. Количество рабочих мест — оценка по четырём названным ролям и объёму в 20 000 позиций. Версия InterBase и структура базы не установлены.
Что от этого не изменится: выбор технологий — он опирается на подтверждённые факты (Delphi 7, InterBase, Windows XP на рабочих местах) и на три принципа заказчика; необходимость отдельной машины под сервер; порядок поэтапного перехода без остановки склада.
Что будет уточнено: схема сети и число сегментов, количество рабочих мест и оборудования, объём работ по переносу данных, а вместе с ним — сроки и стоимость. Оценивать последние две величины до того, как станет известно содержимое базы, было бы неточно.
Оранжевым отмечено то, что пока принято как предположение. Эти пункты подтверждаются или заменяются фактами при обследовании — на них опирается значительная часть документа, поэтому просьба к заказчику прочитать их первыми и поправить, где не так.
192.168.88.0/24 (дефолт MikroTik)..gdb на локальном диске.3050, без сервера приложений.WIN1251 или, хуже, NONE..gdb при работающем сервере — а не через gbak.Схема ниже предположительная: она построена на типовом устройстве сети предприятия такого размера, а количество рабочих мест выведено из четырёх названных ролей. После обследования числа и сегменты будут уточнены, но замысел останется тем же — вынести XP-машины в отдельные сегменты без выхода в интернет, а всё новое поставить на один сервер Debian. Пока хотя бы одна XP-машина имеет одновременно и доступ в интернет, и доступ к базе, защита остальной сети не имеет смысла.
Адресация предлагаемая: нынешняя, скорее всего, плоская и на заводских настройках роутера. Конкретные подсети значения не имеют и могут быть любыми — важно само разделение на сегменты и правила между ними.
| VLAN | Сегмент | Подсеть | Кому и куда разрешено | Интернет |
|---|---|---|---|---|
| 10 | Серверы | 10.10.10.0/24 | Debian-сервер ходит в InterBase :3050; входящие — только 443 и SSH из VLAN 99 | исходящий, для обновлений |
| 20 | Офис | 10.10.20.0/24 | 10.10.10.10:443, 10.10.10.20:3050, сетевые принтеры | да, с фильтрацией DNS |
| 30 | Склад | 10.10.30.0/24 | 10.10.10.10:443, 10.10.10.20:3050, принтер этикеток :9100 | запрещён |
| 40 | Wi-Fi склада | 10.10.40.0/24 | только 10.10.10.10:443 | запрещён |
| 50 | Гости | 10.10.50.0/24 | ничего внутри сети | да, с ограничением полосы |
| 99 | Управление | 10.10.99.0/24 | доступ ко всему оборудованию; попасть можно с места админа и по WireGuard | нет |
Сам роутер и версия RouterOS пока тоже предположительны, но список ниже от модели не зависит — так же он выглядел бы на любом другом оборудовании. Снаружи открыт ровно один порт, и тот не TCP; всё остальное живёт внутри периметра. Правила делятся на две цепочки: обращения к самому роутеру и прохождение трафика между сегментами.
| Откуда | Порт | Куда и зачем | Решение |
|---|---|---|---|
| Из интернета | UDP 13231 | WireGuard — единственный вход снаружи. Через него заходят администратор и разработчик | разрешено |
| Из интернета | всё прочее | Winbox, SSH, RDP, веб-интерфейс роутера, порт базы. Правил проброса нет ни одного | запрещено |
| VLAN 99 и WireGuard | TCP 8291, 22 | Winbox и SSH на самом роутере — управление | разрешено |
| Все внутренние VLAN | UDP 53 | DNS. Рабочие места спрашивают у роутера, какому имени какой адрес соответствует. Здесь же живёт внутреннее имя сервера | разрешено |
| Все внутренние VLAN | UDP 67, 68 | DHCP. Выдача адреса, маски, шлюза и адреса DNS при включении компьютера. Роутер слушает 67, компьютер отвечает с 68 | разрешено |
| Все внутренние VLAN | ICMP | Отклик на пинг. Нужен для проверки связи и для корректной работы протоколов; отключать его — распространённая ошибка, создающая трудноуловимые сбои | разрешено |
| VLAN 20 · офис | TCP 443 TCP 3050 TCP 9100 |
Новая система, база InterBase, сетевые принтеры. Плюс выход в интернет | разрешено |
| VLAN 30 · склад | TCP 443 TCP 3050 TCP 9100 |
То же, но без интернета — только эти три направления и ничего больше | строго по списку |
| VLAN 40 · ТСД | TCP 443 | Только веб-приложение. Ни базы, ни принтеров, ни интернета | строго по списку |
| VLAN 50 · гости | — | Внутрь сети — ничего. Наружу — интернет с ограничением полосы | изоляция |
| VLAN 10 · серверы | TCP 3050 исходящие 443, 587, 53 |
Сервер ходит в InterBase, за обновлениями, за почтой заказчика и в DNS | разрешено |
InterBase использует порт 3050 для соединения, но для событий открывает второй порт, выбираемый случайно. Пока сеть плоская, этого никто не замечает. Как только между рабочими местами и сервером базы появляется фильтрация, старая программа начинает вести себя странно: соединение есть, а списки не обновляются или клиент подвисает.
Поэтому до включения правил нужно выяснить, использует ли Delphi-клиент события базы, и если да — зафиксировать этот порт в настройках InterBase и открыть его наравне с 3050. Проверять это следует на паре рабочих мест до того, как сегментация распространится на весь склад.
DHCP не проходит между сегментами. Выдача адресов работает широковещательно в пределах своего VLAN, поэтому в каждом сегменте нужен свой пул адресов на роутере. И правило, разрешающее эти пакеты, должно стоять до общего запрета: типичная картина после включения сегментации — сеть настроена верно, но компьютеры не получают адрес, потому что запрещающее правило отработало раньше.
Серверу нужно имя, а не адрес. Сертификат выписывается на имя, поэтому на роутере заводится статическая запись — например sklad в домене заказчика указывает на 10.10.10.10. Пользователь открывает адрес по имени, браузер не ругается на сертификат. Снаружи то же имя ведёт на сайт заказчика: внутренняя запись видна только внутри сети.
По умолчанию RouterOS держит включёнными службы, которые здесь не нужны и лишь расширяют поверхность атаки: telnet, ftp, www, api, api-ssl. Оставляем winbox и ssh, ограничив их адресами VLAN 99.
Отдельно — доступ по MAC-адресу: mac-server и mac-winbox. Через них к роутеру подключаются в обход всех правил фильтрации по адресам, и об этом регулярно забывают. Оставить их следует только на интерфейсе управления. Туда же — обнаружение соседей, bandwidth-test и romon выключить полностью.
Порядок правил обычный для RouterOS: сначала пропуск установленных соединений, затем отбрасывание недействительных, затем разрешающие правила по списку, и последним — запрещающее всё остальное с записью в журнал. Именно последнее правило и делает список выше исчерпывающим.
Не проброшены ли наружу RDP (3389) и сам порт InterBase (3050). Проброшенный 3050 означает, что базу склада может скачать кто угодно: аутентификация InterBase старых версий ломается перебором за часы. Если проброс есть — закрыть его в первый же день и выдать вместо него WireGuard.
Принцип простоты применим и здесь. Сложная защита, которую никто не понимает и не проверяет, надёжнее не делает — она лишь создаёт ощущение защищённости и мешает работать. Ниже — короткий список того, что даёт основной эффект и не требует постоянного внимания.
| Мера | Что даёт | Хлопоты |
|---|---|---|
| Наружу не смотрит ничего | Главная мера, обесценивающая большинство атак. Ни SSH, ни база, ни панель управления не имеют внешнего адреса: снаружи попасть можно только через WireGuard | Настраивается один раз |
| Вход по ключу, без пароля | Парольный вход и вход под root отключены. Подобрать нечего |
Две строки в конфигурации SSH |
| PostgreSQL слушает только себя | listen_addresses = 'localhost'. База недоступна по сети даже изнутри — к ней ходит только приложение на той же машине |
Одна строка |
| Автоматические обновления безопасности | unattended-upgrades ставит исправления Debian сам. Это то, чего принципиально нет на XP, и главное преимущество Linux-машины в повседневности |
Установка одной командой |
| Приложение работает не от root | Свой системный пользователь, свой пользователь базы с правами только на свою схему. Ошибка в коде не становится доступом ко всей машине | Часть установки |
| Ограничение попыток входа в приложении | Штатное средство Laravel: после нескольких неудач вход по этой учётной записи тормозится. Работает точнее сетевых блокировок, потому что видит имя пользователя, а не только адрес | Встроено |
| Журнал действий пользователей | Кто провёл документ, кто изменил цену, кто списал позицию. Нужен не столько для защиты, сколько для разбора спорных ситуаций на складе — а это происходит регулярно | Проектируется сразу, дописать потом дороже |
| fail2ban | Блокирует адреса после серии неудачных попыток. Подробнее ниже: при правильной сегментации это второй рубеж, а не первый | Установка и один файл настроек |
Честно говоря, при работающей сегментации сети ловить ему почти нечего — SSH закрыт за туннелем, база слушает только себя. Ставить его стоит по другой причине: он защищает от собственной ошибки. Правило на роутере однажды поправят «на пять минут, чтобы проверить», забудут вернуть, и порт останется открытым на месяцы. Вот тогда fail2ban и отработает — молча, без чьего-либо участия.
Настройка ровно одна: отслеживание неудачных входов по SSH, блокировка на час после пяти попыток. Внутренние подсети — в исключениях, иначе сотрудник, трижды опечатавшийся в пароле, останется без работы до конца обеда, и звонить будут вам. Веб-форму входа сторожит не он, а штатное ограничение Laravel: оно видит, к какой учётной записи подбирают пароль, а не только с какого адреса.
Антивирус на сервере Linux, системы обнаружения вторжений, сбор и анализ журналов в отдельной подсистеме, доменная служба каталогов на двенадцать человек, политика обязательной смены паролей раз в месяц. Первые четыре — это постоянная работа по обслуживанию без соразмерной пользы на таком масштабе. Последняя и вовсе вредна: она надёжно приводит к паролям на бумажках под клавиатурой.
Вместо этого — то, что перечислено выше, плюс две вещи вне сервера: ИБП и место для машины, куда не заходят посторонние. Сервер, стоящий в проходе склада, — риск более вероятный, чем сетевая атака.
Работы ведутся удалённо, и это накладывает два условия. Первое: нужно как-то получить доступ в сеть, где пока нет ни сервера, ни VPN. Второе, и более важное: нужно устроить всё так, чтобы этот доступ нельзя было потерять одной неудачной командой — потому что восстанавливать его будет некому.
Установка системы на месте. Кто-то должен физически поставить Debian: загрузиться с флешки и дойти до конца установщика. Это делает сотрудник заказчика или поставщик оборудования — по короткой письменной инструкции, либо с подготовленной флешки, где установка проходит автоматически и от человека требуется только выбрать загрузку с неё.
полчаса времени одного человека на объекте
Сервер сам звонит наружу. В установку включается готовый файл настройки: сразу после первого запуска сервер поднимает исходящее соединение до внешней точки встречи. Дальше подключение идёт по этому туннелю.
Ключевое свойство: исходящему соединению не нужен ни один открытый порт на роутере. Ничего настраивать в MikroTik на этом этапе не требуется вовсе — а значит, не требуется и человек, умеющий это делать.
доступ появляется без единой правки в сети заказчика
Полноценный VPN на роутере. Когда сервер уже доступен, с него же настраивается WireGuard на MikroTik — это и становится постоянным способом подключения, принадлежащим заказчику. Временный туннель после этого остаётся вторым, запасным путём.
постоянный доступ на инфраструктуре заказчика
Главный риск удалённой настройки — заблокировать себя самому: одно правило межсетевого экрана, одна ошибка в настройке сети, и машина жива, но недосягаема. Меры простые и стоят почти ничего.
WireGuard на роутере и обратный туннель с сервера работают по-разному и ломаются от разных причин. Потерять оба одновременно почти невозможно, а вернуться по любому из них достаточно.
Winbox умеет применять изменения с автоматической отменой: если связь с роутером пропадёт, все правки откатятся сами. При удалённой настройке правил это не рекомендация, а обязательный порядок работы.
Перед рискованной правкой сети или экрана ставится задание, возвращающее прежнюю настройку через десять минут. Всё прошло удачно — задание отменяется вручную. Не прошло — сервер чинит себя сам.
Нужна договорённость заранее: кто именно может подойти к серверу, включить его или подключить монитор, и по какому телефону он доступен. Один человек и его номер — этого достаточно, но выяснять это в момент аварии уже поздно.
Серверные платы умеют отдавать экран и клавиатуру по сети независимо от операционной системы — с ними машину видно, даже когда она не загружается. Удорожает покупку, но для удалённой работы окупается первым же случаем. Существуют и недорогие внешние устройства с той же функцией.
Установка описывается сценарием, а не выполняется руками по памяти. Сервер можно повторить с нуля за час — на новом железе или после серьёзной поломки. Для одной машины достаточно одного простого сценария, без сложной оснастки.
Немного: один человек на объекте, который поставит систему по инструкции и будет на связи на случай, если к серверу придётся подойти физически. Всё остальное делается удалённо — включая настройку роутера, перенос данных и обновления. Приезд на объект нужен только если оборудование окажется с сюрпризом.
Сама по себе эта связка ещё не говорит, как устроена программа внутри. Она задаёт три вопроса, и ответы на них определяют объём работ сильнее, чем что-либо ещё в этом документе. Все три выясняются в первые дни обследования.
Предположительно его нет — так устроено подавляющее большинство программ этого поколения: каждое рабочее место открывает собственное соединение и пишет в таблицы напрямую. Тогда новую систему нельзя вставить в середину — она может только читать ту же базу рядом, а затем забирать участки работы себе.
Реже встречается трёхзвенная схема с сервером приложений посередине. Если окажется так — это хорошая новость: появляется место, куда можно встроиться.
Здесь три расклада. Логика может быть в базе — в хранимых процедурах и триггерах; тогда правила читаются прямо из неё, и это лучший случай. Может быть в формах Delphi — тогда база лишь хранилище, и без исходников правила придётся восстанавливать по данным и расспросам сотрудников. Предположительно здесь третий вариант — и там, и там: он встречается чаще прочих.
Проверяется просто: выгрузить перечень объектов базы. Две сотни процедур на тысячи строк означают одно, пять простых вставок — совсем другое.
Здесь предположений нет, только развилка. InterBase 6.0 читается свободным Firebird — тогда копию базы можно поднять на Debian и работать с ней как угодно. InterBase 7 и новее — уже нет: понадобится либо InterBase под Linux, либо оставить чтение на Windows-машине.
От них зависит не выбор технологий — он уже сделан и от них не меняется, — а сроки и стоимость. Логика в хранимых процедурах читается за дни; логика в утерянных исходниках Delphi восстанавливается неделями, через наблюдение за работой людей. Разброс между лучшим и худшим раскладом здесь кратный, и до обследования любая названная цифра была бы догадкой.
На сервере базы выполнить gstat -h имя_базы.gdb. Вывод покажет версию ODS (структуру файла), кодировку по умолчанию, размер страницы и объём. По ODS сразу понятно, читается ли база свободным Firebird, а по кодировке — насколько больно будет переносить кириллицу. Делать это на копии файла, снятой через gbak, а не на боевом файле.
Возраст системы сам по себе мало о чём говорит: она работает и делает свою работу уже много лет. Значение имеет другое — какие именно риски она создаёт сегодня и сколько дней склад не сможет отгружать, если эти риски сработают. Ниже — проверяемые факты и последствия каждого из них для склада.
Одна машина в офисе ловит шифровальщика — через почту, флешку или сайт с «прошивкой для сканера». У этой машины есть сетевой доступ к файлу базы склада. Через несколько минут .gdb зашифрован. Дальше всё зависит ровно от одного: есть ли копия, из которой действительно можно восстановиться.
Ежедневная копия на внешний диск от этого сценария не спасает. Шифровальщики специально ищут подключённые тома — внешний диск, висящий на USB сервера, шифруется вместе с базой в том же проходе. А если копия одна и перезаписывается каждый день, то повреждение, замеченное через двое суток, к этому моменту уже уехало в копию поверх исправной.
Это не гипотеза про будущее: именно так в 2017 году останавливались предприятия, где остался SMBv1, — а XP не умеет ничего, кроме SMBv1.
| Факт | Что это значит на складе | Уровень |
|---|---|---|
| Поддержка закончилась 8 апреля 2014 Продлённые обновления по ветке POSReady — до 9 апреля 2019 |
Уязвимости, найденные после этой даты, не закрываются никогда. Их число только растёт, и они публичны — эксплойты лежат в открытом доступе. | критично |
| Только SMBv1 | Протокол, по которому WannaCry и NotPetya прошли по сетям целых предприятий. Заражение одной машины расходится на все остальные автоматически, без участия человека. | критично |
| Современные антивирусы не ставятся | Производители прекратили выпуск версий под XP. То, что стоит на машинах сейчас, не получает баз и не видит ничего нового. | критично |
| Нет современной защиты памяти | В новых системах эксплойт чаще всего просто не срабатывает. На XP он срабатывает почти всегда. | критично |
| TLS 1.0 | Банк-клиенты, платёжные шлюзы, порталы поставщиков и госсервисы один за другим отказываются работать. Это уже происходит и будет происходить дальше — просто в неудобный момент. | срочно |
| Пользователи работают администраторами | Так исторически настроено почти везде, где остался XP. Любая запущенная программа получает полные права на машину. | срочно |
| Драйверов под новое оборудование нет | Новый принтер этикеток, сканер или сетевая карта могут просто не заработать. Выбор техники ограничен вторичным рынком. | срочно |
| Современное ПО не поддерживает XP | 1С 8.3, актуальные банк-клиенты, ЭДО, любая новая программа — всё это на XP не встанет. Развитие бизнеса упирается в операционную систему. | срочно |
| Железу пятнадцать лет и больше | Диски, блоки питания и память отрабатывают ресурс. Запчастей нет, а выход из строя машины кладовщика — это остановка отгрузок на день-два. | срочно |
| Персональные данные клиентов | Они хранятся и обрабатываются на системе, которая по определению не может считаться защищённой. Для проверяющих это не спорный вопрос. | срочно |
Это не вопрос вкуса и не «потому что разработчик так привык». Без отдельного сервера половина работ по проекту физически негде выполнить, а самый острый риск — отсутствие резервных копий — не закрывается вообще ничем.
Ежедневная копия у заказчика уже есть — не хватает второго адреса, глубины хранения и проверки. Ночной gbak уезжает на сервер, оттуда зашифрованным — на внешнюю площадку, и раз в неделю автоматически разворачивается обратно. Копия, из которой ни разу не восстанавливали, копией не считается.
Всю разработку и разбор старой схемы можно вести на копии, не касаясь боевой базы. Без этого любой эксперимент идёт на живых данных склада.
Обновления безопасности прилетают автоматически и бесплатно до 2030 года. Всё, что должно ходить наружу — обмен с поставщиками, магазин, почта, — ходит отсюда, а не с XP-машины.
PostgreSQL, веб-приложение, очереди — на XP это не запускается ни в каком виде. Сервер нужен в любом случае, вопрос только в том, купить его в начале проекта или в середине.
База, веб, резервные копии, наблюдение, конец VPN-туннеля наружу — всё на одном системном блоке. Лицензии Windows Server не нужны, а под нагрузку в 12 человек и 20 000 позиций запаса хватит на годы вперёд.
Сегодня никто не знает, сделалась ли копия и жив ли сервер базы. Появляется наблюдение и оповещение в почту или Telegram: место кончается, копия не прошла, сервис упал.
Ежедневная копия на внешний диск — это уже больше, чем бывает на таких объектах, и отталкиваться есть от чего. Но между «копия делается» и «из копии можно восстановиться в понедельник утром» лежат семь свойств, и внешний диск закрывает из них одно.
| Свойство | Сейчас | Что добавляем |
|---|---|---|
| Способ снятия | проверить в первую очередь Если файл .gdb просто копируется при работающем сервере — копия несогласованна. Она может открыться, отработать месяцы и развалиться позже |
gbak — штатная выгрузка InterBase, согласованная по транзакциям |
| Глубина хранения | Похоже, одна копия, перезаписываемая ежедневно | 30 суточных точек плюс недельные и месячные. Порча, замеченная через неделю, всё ещё поправима |
| Число экземпляров | Один — внешний диск | Три: сервер, внешний диск, зашифрованная копия на внешней площадке |
| Копия вне здания | Нет. Пожар, кража или залив уносят сервер и диск вместе | Внешняя площадка, оформленная на заказчика: арендованный сервер или облачное хранилище |
| Устойчивость к шифровальщику | Нет. Постоянно подключённый диск шифруется вместе с базой | Отдельный доступ на внешней площадке, где копии можно только дописывать, но не переписывать и не удалять |
| Проверка восстановления | скорее всего не проводилась | Еженедельный автоматический разворот копии в отдельную базу с отчётом об итоге |
| Оповещение о сбое | Нет. Скрипт может не отрабатывать месяцами, и никто не узнает | Сообщение в Telegram или письмо, если копия не прошла или кончается место |
| Шифрование носителя | Нет. Вынесенный диск — это готовая база клиентов на руках | Копии шифруются при создании, на диск и на внешнюю площадку попадают уже зашифрованными |
| Потери при сбое | До суток работы: всё, что сделано после ночной копии | Для новой базы — журнал транзакций PostgreSQL, восстановление на любую минуту |
Ночной дамп отвечает на вопрос «что было вчера в три часа». Журнал предзаписи отвечает на вопрос «что было сегодня в 14:31, за минуту до того, как удалили не тот документ». Для боевого склада нужен именно второй ответ, поэтому физическое резервирование с непрерывным архивированием WAL включается сразу, а не откладывается на потом.
| Уровень | Что это | От чего защищает | Частота |
|---|---|---|---|
| Базовая копия pg_basebackup через pgBackRest |
Побайтовый снимок кластера целиком — точка отсчёта, к которой применяются журналы | Потеря диска, повреждение кластера, отказ сервера | Полная — раз в неделю, разностная — каждую ночь |
| Непрерывный архив WAL | Каждый сегмент журнала предзаписи сразу уезжает в хранилище. Это и есть непрерывность: между копиями нет дыр | Ошибка человека и приложения: удалили документ, испортили справочник, выполнили не тот запрос | Непрерывно, archive_timeout = 60 — сегмент закрывается минимум раз в минуту |
| Логический дамп pg_dump |
Текстовая выгрузка структуры и данных, независимая от версии и формата хранения | Повреждение самого формата и потребность вытащить одну таблицу, не разворачивая весь кластер | Еженедельно, хранится дольше остальных |
| Копия InterBase gbak |
Штатная согласованная выгрузка старой базы | Всё то же самое, пока источником истины остаётся InterBase | Ежедневно, до конца миграции |
Потеря данных при сбое — не более минуты вместо суток. Время восстановления — порядка получаса на разворот кластера из базовой копии плюс проигрывание журналов.
Сегодня оба показателя — «сутки» и «сколько получится».
Восстановление задаётся временем: развернуть состояние на 14:31 и посмотреть, что было в документе до правки. Инвентаризацию, испорченную неверным пересчётом, можно поднять отдельно и сверить, не трогая боевую базу.
Архив на том же сервере шифровальщик зашифрует вместе с базой. Поэтому копия обязательно уходит на внешний носитель и на внешнюю площадку — архив WAL это дополняет, но не отменяет.
И это не реплика: физическое резервирование про восстановление, а не про доступность.
Он закрывает ровно эту задачу: параллельная выгрузка, сжатие, шифрование, разностные копии, контроль целостности и команда check, проверяющая, что архивирование действительно работает. Самописный archive_command — это те же функции, только без проверок и без автора рядом. Здесь готовый инструмент работает на простоту, а не против неё.
Раз в неделю сервер сам разворачивает вчерашнюю копию в отдельный экземпляр, проигрывает журналы, выполняет несколько контрольных запросов — число позиций, сумма остатков — и присылает результат. Если разворот не удался, вы узнаёте об этом в спокойный вторник, а не в тот день, когда копия понадобилась по-настоящему.
Когда появится вторая машина, тот же архив WAL превращается в постоянную реплику — данные едут на неё непрерывно, и при отказе основного сервера склад продолжает работать. Но это уже про доступность и отдельные деньги; резервирование нужно раньше и в любом случае.
| Компонент | Минимум | Комфортно | Почему |
|---|---|---|---|
| Процессор | 4 ядра | 6–8 ядер | PostgreSQL, PHP-FPM, служба синхронизации и отчёты работают одновременно |
| Память | 16 ГБ | 32 ГБ ECC | База целиком помещается в кэш — отчёты по 20 000 позиций отвечают мгновенно |
| Диски | 2 × 500 ГБ NVMe, зеркало | 2 × 1 ТБ NVMe, зеркало | Зеркало — чтобы отказ одного диска не был событием. Это не замена резервным копиям |
| ИБП | обязательно | с корректным завершением работы | Внезапное отключение питания — самый частый способ повредить базу |
| Внешний диск | 1 ТБ USB | плюс копия на внешней площадке | Третий экземпляр копии, физически отдельный от сервера |
Схеме нужна точка вне офиса: там лежит третий экземпляр резервных копий — зашифрованный, вне здания, чтобы пожар или кража не унесли всё сразу. Оттуда же уходит почта, и туда же на пятой фазе переезжает обмен с интернет-магазином.
Оформляется всё это на заказчика: его домен, его учётная запись, его оплата. Личный сервер разработчика на этой роли выглядит удобно ровно до первого отпуска — подробнее в следующем разделе.
Связь между офисом и внешней площадкой — только туннель WireGuard. Ни PostgreSQL, ни тем более InterBase наружу не открываются никогда.
Уведомления заложены в работу склада, значит почта — не дополнительная опция, а часть системы. И здесь важно с самого начала развести два совершенно разных потока писем: их путают почти всегда, а требования у них противоположные.
Не прошла резервная копия, кончается место, сервис не отвечает, сбой синхронизации. Получателей один-два, объём — единицы сообщений в день. Никого снаружи они не касаются.
Лучше вообще не почтой, а ботом в Telegram: доходит мгновенно, не попадает в спам и не требует почтового сервера. Для «копия не сделалась» это точнее любого письма.
Подтверждение заказа, счёт, накладная, статус отгрузки. Это письма от лица фирмы, и уходить они обязаны с её домена, с её подписью и реквизитами.
Письмо о заказе автозапчастей, пришедшее с личного домена постороннего человека, выглядит как мошенничество — и почтовые службы обойдутся с ним соответственно.
| Вариант | Когда подходит | Цена и хлопоты | Оценка |
|---|---|---|---|
| Использовать почту, которая у них уже есть | Почти наверняка этот случай: раз есть интернет-магазин, есть и корпоративная почта на своём домене. Приложение отправляет через их SMTP как обычный почтовый клиент | Ноль. Настройка — полчаса | начать отсюда |
| Сервис транзакционной отправки | Если писем много или своя почта плохо доходит. Письма уходят с домена заказчика, а доставляемость и репутация — забота сервиса | На их объёмах бесплатно или символически. Аккаунт оформляется на заказчика | если понадобится |
| Свой почтовый сервер у заказчика | Только если есть требование держать переписку внутри периметра | Постоянная работа: репутация IP, чёрные списки, PTR-запись, антиспам, обновления, резервирование | на 12 человек не окупается |
Почта оформляется на заказчика: его домен, его учётная запись, его оплата. Настройка выполняется исполнителем и входит в состав работ. Проверка простая: если завтра исполнителя не станет в проекте, у заказчика ничего не должно сломаться. Инфраструктура, привязанная к конкретному подрядчику, — это риск для обеих сторон.
И отдельно: отправка и приём — разные задачи. Складу почти наверняка нужна только отправка. Если же программа должна ещё и разбирать входящие письма — заказы от клиентов, прайсы поставщиков, — это совсем другой объём работы, и его нужно оценивать отдельно.
Первый вопрос — не «какой зарегистрировать», а какой у них уже есть. Раз работает интернет-магазин, домен почти наверняка существует, и почту нужно поднимать на нём: единый домен для магазина, сайта и писем — это узнаваемость, а два разных домена у одной фирмы только путают клиентов. Регистрировать новый есть смысл, только если магазин стоит на чужой площадке или конструкторе с их доменом.
Прямо называет дело: детали и склад. Транслитерируется однозначно, по телефону диктуется без «а как это пишется». Рабочий вариант по умолчанию.
Солиднее и шире по смыслу — подойдёт, если фирма оптовая и планирует расти за пределы одной товарной группы.
Короче и современнее, но смешивает английское parts с русским складом — часть клиентов прочтёт как «партсклад». Годится, если аудитория помоложе.
Занятость всех трёх нужно проверять у регистратора — вероятность, что короткое имя в зоне .ru свободно, невелика. Если все заняты, работает приём «слово плюс город»: detalsklad-nsk.ru. Дефис в почтовом адресе неудобен, но лучше дефиса только своё короткое имя.
Владельцем и администратором в реквизитах указывается фирма-заказчик. Исполнителю достаточно технического доступа к DNS — этого хватает для любой настройки. Домен, оформленный на подрядчика, рано или поздно становится предметом спора, и спор этот некрасив для обеих сторон независимо от того, кто прав.
Сразу включите автопродление. Домен, потерянный из-за неоплаченного счёта, уводит вместе с собой и почту, и магазин, а выкупать его обратно приходится уже у перекупщиков.
Три записи обязательны, иначе почтовые службы отправят письма в спам независимо от их содержания: SPF — перечень серверов, которым разрешено слать от имени домена; DKIM — подпись, подтверждающая, что письмо не подменили; DMARC — правило, что делать с письмами, не прошедшими первые две проверки. Если почта поднимается на своём сервере, добавляется PTR — обратная запись для IP, её настраивает хостер.
При отправке через существующую почту заказчика или через сервис рассылки всё это либо уже настроено, либо делается по их инструкции за полчаса. Это ещё один довод не поднимать почтовый сервер с нуля.
Заказчик назвал три принципа, и они не украшение — это готовый критерий, по которому отбрасывается лишнее. Прогон стека через них убрал из первого варианта четыре компонента, включая один язык программирования.
Считается не строчками кода, а числом того, что может сломаться и что нужно уметь чинить. Один язык, один сервер, минимум служб. И проверка на человеке: сможет ли посторонний специалист разобраться в системе без вас — от этого зависит, не станет ли заказчик заложником.
Не «не падает», а предсказуемо восстанавливается. Проверенные копии, откат за минуту, понятные журналы, оповещение о сбое. Чем меньше движущихся частей, тем меньше способов сломаться — поэтому надёжность здесь прямо следует из простоты, а не спорит с ней.
Для кладовщика это не время ответа сервера, а число нажатий на приёмку одной позиции. Delphi-программы в этом сильны, и веб проигрывает им не скоростью сети, а лишними кликами. Требование: работа с клавиатуры, без мыши, с горячими клавишами — как привыкли.
Второй язык. В первом варианте синхронизация с InterBase была отдельной службой на Node — ради драйвера, не требующего клиентских библиотек. Выигрыш реальный, но небольшой, а плата — второй язык, вторая среда, вторые зависимости и вдвое больше того, в чём придётся разбираться постороннему специалисту. Против принципа простоты это не проходит: остаётся один PHP.
Docker. Для одного приложения на одной машине контейнеры добавляют слой между вами и проблемой. Всё ставится из репозиториев Debian и управляется systemd — так проще диагностировать и так сможет разобраться любой линуксовый администратор.
Отдельный сервер очередей. На двенадцать человек очереди прекрасно живут в PostgreSQL. Это минус одна служба, которая могла упасть.
Центр сертификации как служба. Вместо него — самоподписанный корневой сертификат, выпущенный один раз на десять лет и один раз установленный на рабочие места.
Одна машина под Debian 13, PostgreSQL на ней же — как вы и предложили. Всё ставится нативно из репозиториев и управляется systemd, без контейнеров: меньше слоёв между администратором и неисправностью. Обновление системы — git pull, установка зависимостей и миграции; откат — возврат на предыдущую версию в git.
| Слой | Выбор | Почему именно так | Статус |
|---|---|---|---|
| ОС сервера | Debian 13 «trixie» | Поддержка до 2030, свежие PHP 8.4 и PostgreSQL 17 прямо в базовых репозиториях, минимум лишнего. | решено |
| База | PostgreSQL 17 (PGDG) | 20 000 позиций — мелочь, но кроссы и аналоги дают миллионы связей. pg_trgm закрывает поиск по артикулу с опечатками и по части номера — главный сценарий в автозапчастях. |
решено |
| Основной бэкенд | PHP 8.4 + Laravel 12 | Складской учёт — это документы, справочники, права и печатные формы. Laravel даёт очереди, миграции, авторизацию и админку из коробки. Один язык на весь проект — прямое следствие принципа простоты. | решено |
| Синхронизация с InterBase | Команда Laravel + pdo_firebird |
Не отдельная служба, а обычная задача по расписанию внутри того же приложения. Опрос раз в минуту вместо мгновенных событий — для зеркала этого достаточно, зато нет второй среды выполнения. Клиентская библиотека ставится из репозитория Debian одной строкой. | решено |
| Фронтенд | Blade + htmx 1.9 | Страницы собираются на сервере. Никакого React и Vue: на XP они либо не запустятся, либо потребуют горы полифилов. htmx 1.x собран под IE11 — на XP-браузерах работает гарантированно. | рекомендация |
| Веб-сервер | Nginx + самоподписанный сертификат | Let's Encrypt на XP не заработает (об этом ниже). Корневой сертификат выпускается openssl один раз на десять лет и один раз ставится в Firefox на рабочих местах. Отдельный центр сертификации как служба здесь — лишняя движущаяся часть. |
решено |
| Очереди | Таблица в PostgreSQL | Фоновая печать этикеток и выгрузки. На двенадцати пользователях отдельный сервер очередей не нужен — это минус одна служба, которая могла бы упасть. Redis добавим, если объёмы вырастут. | решено |
| Терминалы склада | ТСД на Android 10+ | Тот же веб-интерфейс в Chrome, отдельная «крупнокнопочная» вёрстка. Сканер работает как клавиатура — писать нативное приложение не нужно. | рекомендация |
| Печать этикеток | ZPL прямо в принтер, TCP 9100 | Сервер отправляет готовый ZPL на сетевой принтер. Драйверы печати под XP не нужны вообще — а это один из главных источников ежедневной боли. | рекомендация |
| Резервные копии | pgBackRest + restic | PostgreSQL — база плюс журнал транзакций, восстановление на любой момент. InterBase — ночной gbak. Копии уезжают на второй носитель и наружу. |
обязательно |
| Удалённый доступ | WireGuard на MikroTik | Взамен любых пробросов портов. RouterOS 7 умеет его штатно. | обязательно |
| Наблюдение | Скрипт по расписанию → Telegram | Проверяются три вещи: прошла ли ночная копия, сколько осталось места, отвечает ли сайт. Молчание означает, что всё в порядке. Zabbix и панели мониторинга на 25 устройств — избыточны. | решено |
| Развёртывание | systemd, без контейнеров | PHP-FPM, Nginx и PostgreSQL — обычные службы Debian. Обновление: git pull и миграции, откат — возврат к предыдущей версии. Разобраться сможет любой линуксовый администратор, не только автор. |
решено |
Не в выборе языка. Двадцать тысяч позиций — крошечный объём: PostgreSQL отвечает на такие запросы за миллисекунды на любом стеке. Скорость системы решают три другие вещи.
Индексы под поиск по артикулу. Главный запрос на складе — найти деталь по куску номера, с опечаткой, с чужим написанием. Расширение pg_trgm с индексом GIN отвечает на такое мгновенно; без него тот же запрос перебирает таблицу целиком. Разница — сотни раз, и она важнее всего остального в этом документе про скорость.
Отсутствие лишнего на странице. Страницы собираются на сервере и приходят готовыми. Списки — постранично: двадцать тысяч строк не выгружаются в браузер никогда, тем более на XP.
Число нажатий. Приёмка позиции должна занимать столько же действий, сколько в Delphi, или меньше. Фокус сам встаёт в поле ввода, сканирование сразу добавляет строку, сохранение — с клавиатуры. Если новая система окажется медленнее в руках кладовщика, все технические достоинства не будут стоить ничего — и именно на этом такие проекты чаще всего и проваливаются.
Это и есть план. Новая система — внутренний веб-сайт: сотрудник открывает браузер, вводит логин и работает. Ничего устанавливать на рабочие места не нужно, парк менять сейчас не нужно, и именно поэтому фронтенд собирается на сервере, а не на React.
Новая версия выкладывается на сервер — и она у всех. Сегодня обновить Delphi-клиент значит обойти двенадцать машин; отсюда же берутся ситуации, когда у половины сотрудников версия разная.
Ни библиотек InterBase, ни драйверов печати, ни настройки соединения с базой. Браузер и сетевой кабель — всё. Новое рабочее место заводится за пять минут.
Страницы собираются на сервере, браузеру достаётся готовый HTML. Машине с гигабайтом памяти этого достаточно — при условии, что мы не пишем одностраничное приложение и не грузим 20 000 строк в одну таблицу.
USB-сканер отдаёт штрихкод как набранный текст. Он работает в браузере ровно так же, как в Delphi, — переучивать кладовщика не придётся.
Этикетки печатает сервер напрямую в сетевой принтер, минуя браузер и драйверы XP. Кривые печатные формы и «а у меня не печатает» как класс исчезают.
Браузер не чинит саму XP: без обновлений, без антивируса и с SMBv1 машина остаётся уязвимой. Поэтому веб-доступ работает только в связке с выносом XP в сегмент без интернета.
Бухгалтерия. Банк-клиент, 1С и ЭДО веб-страницами не станут и XP уже не поддерживают. Эти одну-две машины придётся обновить отдельно и раньше остальных — независимо от нашего проекта.
Железо. Машины продолжат выходить из строя, и купить замену под XP негде. Правильная политика: сломавшуюся машину заменяем на новую с современной системой, а не ищем ещё один такой же системный блок. Через два-три года парк обновится сам, без разговора о единовременной закупке.
XP определяет не «дизайн посовременнее», а список технологий, которые просто не запустятся. Хорошая новость: если зафиксировать один браузер, ограничения оказываются мягче, чем кажется.
| Браузер на XP | TLS | Что умеет | Вывод |
|---|---|---|---|
| Firefox 52.9 ESR | TLS 1.2 | ES6, fetch, Promise, CSS-переменные, flexbox, grid. Своё хранилище сертификатов — корневой CA ставится в профиль. | целевой браузер |
| Chrome 49 | TLS 1.2 | ES6 частично, CSS grid нет. Берёт корневые сертификаты из хранилища Windows — а там нет ни одного современного корня. | запасной |
| Internet Explorer 8 | TLS 1.0 | Практически ничего из современного. | исключить |
Ставим на все рабочие места Firefox 52.9 ESR и целимся в него одного. Тогда: собирать JS под ES2015 без модулей — одним файлом-бандлом; CSS-переменные и flexbox можно; полифилов почти не нужно. Сертификат берём от своего внутреннего CA и ставим корень в профиль Firefox — Let's Encrypt здесь бесполезен, потому что кросс-подпись, которой доверяли старые системы, истекла в 2021 году.
XP живёт в VLAN 20 и 30 без интернета, единственный браузер — Firefox ESR. Стоит ноль. Пока работает Delphi-клиент, это единственный реалистичный вариант.
на время миграции
То же железо, но грузится лёгкий Debian с современным браузером. Актуальный TLS, обновления безопасности, ноль затрат на технику. Возможно только после того, как Delphi-клиент перестанет быть нужен.
после фазы 4
Правильно, но это деньги заказчика и отдельный разговор. Заводить его стоит не «потому что XP старый», а под конкретную дату отключения Delphi-клиента.
решение заказчика
Это самая техничная часть проекта и главный источник скрытых сроков. Ошибка здесь обнаруживается не сразу, а через месяц — когда кто-то замечает, что остаток по позиции разошёлся на три штуки. Поэтому перенос строится так, чтобы его можно было запускать сколько угодно раз и каждый раз проверять результат.
raw — сырьё как естьТочная копия таблиц InterBase, поле в поле, без единого улучшения. Сюда данные просто перекладываются. Задача этого слоя одна: получить содержимое старой базы внутри PostgreSQL, чтобы дальше работать привычными запросами, а не через мост.
Нормальная схема, спроектированная под задачу, наполняется преобразованием из raw. Здесь разбираются текстовые флаги, склеиваются дубли, наводится порядок в справочниках.
Разделение превращает одну необратимую операцию в две повторяемые. Перекладывание проверяется на совпадение количества строк, преобразование — на бизнес-правила, и каждое можно переделать, не трогая другое. При одном слое любая найденная ошибка означает повторный перенос всего с самого начала.
И второе. Схема старой базы несёт двадцать лет заплаток: поля-заглушки, флаги буквами, следы давно отменённых решений. Копировать её в новую систему — значит унаследовать всё это навсегда: обещание «перенесём как есть, а отрефакторим потом» не выполняется никогда. Слой raw позволяет опереться на старую структуру, не пуская её в новую систему.
| InterBase | PostgreSQL | В чём подвох |
|---|---|---|
| VARCHAR(n) CHARACTER SET WIN1251 |
text | Перекодировка в UTF-8. Если у базы кодировка NONE, сервер отдаёт байты как есть — придётся распознавать кодировку самостоятельно и сверять результат глазами на выборке |
| DATE | date или timestamp | зависит от диалекта В первом диалекте DATE хранит ещё и время. Перенести его в date — молча потерять часы и минуты у всех документов |
| NUMERIC(15,2) | numeric(15,2) | Переносится верно. Но если суммы хранили в DOUBLE PRECISION, там уже накоплена погрешность округления — переносить нужно, зная об этом, и сверять итоги с отчётами старой системы |
| CHAR(1) 'Y' / 'N' SMALLINT 0 / 1 |
boolean | Почти всегда это логические поля. Проверить каждое: среди них попадаются трёхзначные, где третье состояние значимо, а NULL означает не то же самое, что «нет» |
| BLOB SUB_TYPE 1 BLOB SUB_TYPE 0 |
text bytea |
Текстовые блобы — те же вопросы с кодировкой. Двоичные — это картинки и вложения; их объём стоит оценить заранее, он может оказаться больше самой базы |
| GENERATOR | sequence | Последовательность выставляется на текущее значение генератора плюс запас. Забыть про это — получить конфликт ключей в первый же день записи |
| Триггеры и процедуры | Код приложения | Не переносятся, а прочитываются: в них записана часть бизнес-правил, и это самый достоверный их источник. Реализуются заново в Laravel |
Первая полная загрузка — простая часть. Сложность в том, чтобы дальше подхватывать изменения, пока в InterBase продолжают работать. Способы, по убыванию предпочтительности:
По собственному полю таблицы. Если есть дата изменения или растущий идентификатор из генератора — забираем всё, что больше запомненного значения. Ничего в боевой базе менять не нужно, риск нулевой. Проверить наличие таких полей — первое, что делается по схеме.
не трогаем чужую базу вообще
Триггеры в отдельный журнал. На нужные таблицы вешаются триггеры, пишущие в новую таблицу-журнал: что за таблица, какая запись, какая операция, когда. Синхронизация читает журнал и вычищает обработанное.
Ключевое различие в рисках: новые таблицы и триггеры Delphi-клиент не видит и не замечает — они безопасны. Опасно другое: добавлять поля в существующие таблицы. Программы того времени часто обращаются к полям по номеру, а не по имени, и лишняя колонка ломает форму. Этого не делаем.
сначала на копии, затем на боевой в нерабочее время, с готовым откатом
Полная сверка по расписанию. Для небольших справочников — просто перечитывать целиком раз в ночь. Двадцать тысяч позиций читаются за секунды, и никакой механики отслеживания не нужно вовсе. Самый простой способ там, где он проходит по объёму.
для справочников — предпочтительнее двух предыдущих
Каждую ночь считаются и сравниваются: число строк по каждой таблице, суммы остатков по складу, итоги документов за период. Расхождение приходит письмом с указанием таблицы и записи. Пока цифры сходятся неделями подряд, разговор о переключении вообще возможен; без такой сверки любое расхождение всплывёт в самый неудобный момент и обнулит доверие ко всей новой системе.
Отсюда же берётся дата переключения: не «когда всё написано», а когда сверка не показывает расхождений заданное время подряд.
С третьей фазы новая система пишет результат обратно в InterBase, чтобы Delphi видел согласованную картину. Здесь два правила. Идентификаторы берутся только у генераторов InterBase — присвоить их самостоятельно значит рано или поздно столкнуться с чужой записью. Вставка идёт теми же путями, что у Delphi, чтобы отработали существующие триггеры и проверки: обойти их — получить данные, которые старая программа считает испорченными.
Поэтому первым для записи выбирается замкнутый участок вроде приёмки: у него понятные границы, немедленная польза кладовщику и обозримые последствия, если что-то пойдёт не так.
Переписать всё и переключиться в одну ночь — верный способ остановить отгрузки. Вместо этого новая система сначала только читает данные рядом со старой, а потом по одному забирает участки работы себе, пока от старой не останется ничего.
Обследование и резервная копия. Снять gbak с боевой базы и увезти копию к себе. Определить версию InterBase, ODS, кодировку, объём. Выгрузить схему: таблицы, индексы, триггеры, хранимые процедуры. Пересчитать машины, порты и пробросы. До этого момента ничего на объекте не менять.
Итог: копия базы поднята локально, схема выписана, список неизвестного закрыт
Инфраструктура. Сервер на Debian 13, VLAN и правила экрана, WireGuard вместо пробросов, ночной gbak InterBase на Linux с проверкой восстановления. Порядок важен: резервные копии старой базы делаются до любых работ по сети.
Итог: сеть сегментирована, копии снимаются и проверяются, доступ снаружи закрыт
Зеркало для чтения. служба синхронизации переносит данные в PostgreSQL. Веб даёт поиск по артикулам и кроссам, остатки, отчёты директору. Риск для склада нулевой: запись по-прежнему только через Delphi. Здесь же выясняется настоящее качество данных — дубли, битая кириллица, склад «в никуда».
Итог: первые пользователи в новой системе, доверие заработано на чтении
Первый модуль с записью. Обычно это приёмка или инвентаризация на ТСД: замкнутый процесс, понятный результат, немедленная польза кладовщику. С этого места по выбранному участку источник истины — PostgreSQL, а синхронизация возвращает результат в InterBase, чтобы Delphi продолжал видеть согласованную картину.
Итог: двусторонняя синхронизация обкатана на одном безопасном участке
Менеджерский контур. Заказы, резервы, цены, клиенты, отгрузка. Самая объёмная фаза и самая спорная по требованиям: именно здесь всплывают правила, которых нет ни в одной документации — только в головах менеджеров.
Итог: менеджеры работают в вебе, Delphi остаётся у бухгалтерии
Бухгалтерия и обмен. Документы, взаиморасчёты, выгрузка в 1С. Плюс подключение интернет-магазина к новому API — до сих пор он, скорее всего, ходил в базу своим отдельным способом.
Итог: у обмена данными один источник вместо нескольких
Отключение. Delphi-клиент снимается с рабочих мест, InterBase переводится в архив и хранится в копиях, код синхронизации удаляется. Только теперь имеет смысл разговор о замене или переводе XP-машин на тонкие клиенты.
Итог: одна система, один сервер, один язык интеграции
| Риск | Чем грозит | Что делать |
|---|---|---|
| InterBase 7 и новее | Копию базы не поднять свободным Firebird — вся схема чтения усложняется | Проверить ODS в фазе 0. Запасной путь — оставить чтение на Windows-машине через мост ODBC |
Кодировка базы NONE |
Кириллица переносится мусором, и обнаруживается это в самый неподходящий момент | Определить фактическую кодировку по данным, перекодировать побайтово при переносе, сверить на выборке |
| Нет исходников Delphi | Часть правил не восстановить чтением базы | Разбирать по данным и опросам. Заложить время на это в фазе 4 — там оно и понадобится |
| Триггеры на боевой базе | Delphi-приложения нередко ломаются от изменения схемы: они рассчитывают на точный состав и порядок полей | Все триггеры — сначала на копии, потом на боевой, и только новые таблицы. Существующие не трогать |
| Один сервер | Отказ железа останавливает и склад, и магазин | Диски в зеркале, ИБП, проверенное восстановление из копии. Отдельно обсудить второй сервер про запас |
| Лицензии InterBase | Возможен неприятный сюрприз при разговоре о легальности | Выяснить в фазе 0. На результат проекта не влияет — это довод в пользу перехода |
| Качество данных | 20 000 позиций за годы работы — это дубли, кроссы «в никуда», отрицательные остатки | Чистка идёт в фазе 2, на зеркале, где ничего не сломается. Правила чистки утверждает заказчик |
Заказчик предложил выделить отдельный компьютер с XP и рабочей программой. Предложение правильное по сути, но избыточное по форме: нужна не машина, а её содержимое. И одних скриншотов при этом не хватит — они показывают, из чего состоят формы, но не показывают, что программа делает.
| Что просить | Зачем именно это | Важность |
|---|---|---|
Копия базы через gbakбоевая, не урезанная |
Даёт схему, данные, хранимые процедуры, триггеры, реальные объёмы и настоящее качество данных. Это примерно две трети всей нужной информации. Урезанная выборка скроет ровно те аномалии, ради которых обследование и затевается. | без этого нельзя |
| Программа в виртуальной машине образ диска или комплект установки |
Показывает поведение, которого в базе нет: что подставляется само, что проверяется, что происходит при нехватке товара, как ищутся аналоги. XP отлично живёт в VirtualBox на Linux — отдельное железо держать не нужно. | почти обязательно |
| Запись экрана, 20–30 минут кладовщик и менеджер, вслух |
Приёмка от начала до конца и оформление заказа — с комментариями, что и почему нажимают. Одна такая запись полезнее сотни скриншотов: видно порядок действий, горячие клавиши и скорость работы. | очень желательно |
| Печатные формы в PDF или живые распечатки |
Их потребуют воспроизвести один в один. Нужны точные поля, размеры, шрифты и расположение — по скриншоту это не восстановить, особенно для этикеток и накладных. | очень желательно |
| Скриншоты форм | Полезны как дополнение и как оглавление. Но пять экранов — это оценка снаружи: за каждой формой стоят справочники, фильтры, окна подбора и сообщения об ошибках, и в реальности состояний окажется в разы больше. | дополнение |
| Исходники Delphi | Если сохранились — снимают половину вопросов по бизнес-правилам. Если нет, ничего страшного: правила восстанавливаются по базе и по записи экрана, просто дольше. | если есть |
Она снимает возражение «потом это будет не нужно»: виртуалка удаляется одной командой, а железо надо где-то держать и потом возвращать. Она запускается на вашем Linux в любой момент, её можно откатить к исходному состоянию после любого эксперимента и скопировать столько раз, сколько нужно. Физическая машина понадобится только в одном случае: если программа привязана к аппаратному ключу или конкретному железу — это стоит проверить сразу.
И одна поправка к формулировке «потом не нужна»: старая программа нужна до самого конца миграции. На фазах 2–5 по ней сверяются цифры — остаток по позиции в Delphi против того же остатка в новом отчёте. Без запущенного эталона каждый спор «раньше считалось иначе» выигрывает заказчик.
В копии базы — персональные данные клиентов и вся коммерческая история. Условия обращения с ней: хранение в виртуальной машине без выхода в сеть, на шифрованном диске, удаление по окончании работ. Это фиксируется письменно до передачи копии, а не после.
Три вопроса из этого списка способны изменить план работ и смету, поэтому задать их следует раньше остальных. Прочее — организация, но без неё установка встанет на полдня из-за отсутствующего монитора.
Если провайдер выдаёт адрес за своим общим шлюзом, входящее VPN-подключение к сети поднять невозможно в принципе. Тогда либо белый адрес за доплату провайдеру, либо весь удалённый доступ строится на исходящих соединениях от сервера.
Проверяется за минуту: сравнить адрес в настройках роутера с тем, что показывает любой сайт определения адреса. Совпадают — белый.
Разделение сети на сегменты требует управляемых коммутаторов. Если стоят простые, разделение либо не сделать вовсе, либо оно упирается в замену оборудования — а это отдельная статья расходов, которую лучше обнаружить сейчас, а не в середине работ.
Встроенный VPN появился только в седьмой версии RouterOS. На шестой понадобится либо обновление, либо другой способ подключения. Заодно — есть ли вообще пароль от роутера и у кого он.
Первые пять пунктов закрывают почти всю неопределённость этого документа. Остальное можно выяснять по ходу.
gstat -h по базе. Определяет, читается ли копия свободным Firebird..gdb, число таблиц и хранимых процедур.DATE ещё и время. Ошибиться здесь — молча потерять часы у всех документов при переносе.gbak или простое копирование файла .gdb. Посмотреть сам скрипт или задание в планировщике.Различие не формальное. Предложение отвечает на вопрос «как будет устроено» и пишется исполнителем. Задание отвечает на вопрос «что система должна делать», пишется от лица заказчика и подписывается им. По этому документу нельзя ни принять работу, ни назвать её стоимость: в нём нет ни одного проверяемого требования к тому, как работает приёмка или как считается резерв.
| Документ | Отвечает на вопрос | Когда | Состояние |
|---|---|---|---|
| Техническое предложение этот документ |
Как будет устроено решение: сеть, стек, порядок перехода, риски. Что нужно узнать и купить | До обследования, на допущениях | на согласовании |
| Отчёт об обследовании | Что есть на самом деле: версия и диалект базы, схема, качество данных, реальная топология, как работают люди | Фаза 0, по копии базы и записи экрана | впереди |
| Техническое задание | Что система обязана делать: процессы, роли и права, печатные формы, отчёты, измеримые требования к скорости, критерии приёмки, границы работ | По итогам обследования, подписывается заказчиком | впереди |
Прочитать раздел с исходными данными и поправить допущения, ответить на вопросы из последнего раздела и передать копию базы. После этого предложение превращается в отчёт об обследовании с точными цифрами, а из него — в техническое задание со сроками и стоимостью.