Двор со шлагбаумом живёт по простым правилам: своим — открыто, гостям — по звонку, за обслуживание — платят. Держать это в тетради и в чате дома неудобно, и здесь появляется система управления шлагбаумом BAS-IP 2.0.2: жильцы, начисления с перерасчётом, гостевые QR-пропуска, журнал открытий и REST API для панели домофона. Ниже — что внутри, что показал прогон на живом PHP и какие грабли ждут на PHP 8.5.

bas ip cover

TL;DR: что это и чем проверено

  1. Тип. Самостоятельно размещаемое PHP-приложение для управления шлагбаумом в жилом комплексе.
  2. Данные. MySQL, MariaDB, PostgreSQL или SQLite — схема переносимая.
  3. Деньги. Начисления с перерасчётом, расщепление до копейки, учёт оплат.
  4. Доступ. Гостевые QR-пропуска и журнал каждого открытия.
  5. Проверка. 232 PHP-файла проверены php -l — ноль ошибок синтаксиса; /health.json на PHP 8.5 отвечает 500.

Проблема, которую это решает

Шлагбаум во дворе — это не только железо. За ним стоит учёт: кто живёт, кто платит, кто в гостях и когда створка поднималась.

Обычная практика выглядит так: список жильцов в таблице, платежи в переписке, гостевые пропуска по звонку старшему по дому. Пока дом маленький — работает. Как только квартир сотня, начинаются споры: «я платил», «у меня гости», «почему не открылось».

Приложение переносит этот учёт в базу: у каждого событие с датой, у каждого платежа — история, у каждого открытия — запись. И, что важно, оно не требует облака: сервер можно держать в том же доме.

Что такое BAS-IP

flowchart TB
  WEB["public/index.php: точка входа"] --> CORE["ядро: роутер, сессии, конфиг"]
  CORE --> DB["БД: MySQL, PostgreSQL или SQLite"]
  CORE --> DEV["панель домофона: REST API"]
  CORE --> JOBS["расписание: сбор платы и напоминания"]
  CORE --> STORE["storage: логи, бэкапы, кэш"]
Свойство Значение
Версия в разборе 2.0.2 «Kronos»
Рантайм PHP 8.2+, рекомендуется 8.5
База данных MySQL 8, MariaDB 10.6+, PostgreSQL 13+, SQLite 3
Веб-сервер nginx или Apache, docroot — public/
Зависимости без CDN, сборка через npm только для стилей
Лицензия в дистрибутиве есть LICENSE
Поставка архив bas-ip-2.0.2.zip с контрольной суммой

Дистрибутив — сборка без тестов и служебных скриптов: tests/ и tools/ в архив не входят, о чём стоит знать заранее, если вы привыкли гонять php tests/run.php из клона.

Возможности

Жильцы и помещения

Что есть Зачем
импорт из CSV, JSON, Excel перенос списка из таблицы без ручного ввода
инспекция и маппинг колонок сопоставление своих полей со схемой
экспорт всех данных резервная копия и передача новому правлению
бэкапы БД mysqldump, pg_dump, SQLite — с восстановлением

Деньги и начисления

Что есть Зачем
ежемесячные начисления регулярный сбор без ручных таблиц
перерасчёт исправление ошибок без правки истории
расщепление до копейки распределение платежа по периодам
FIFO оплат понятный порядок закрытия задолженностей

Доступ и журнал

Что есть Зачем
гостевые QR-пропуска гость проходит без звонка
журнал открытий видно, кто и когда открывал
REST API связка с панелью домофона
/health.json проверка состояния мониторингом

Как это работает

flowchart LR
  CHK["проверка релиза"] --> ZIP["снимок текущей версии"]
  ZIP --> GET["скачивание архива"]
  GET --> EX["распаковка в каталог"]
  EX --> MIG["миграции БД"]
  MIG --> OK["health.json: status ok"]

Конфигурация собирается из трёх источников: локальный файл, .env, значения по умолчанию — и это правильный порядок, потому что секреты остаются вне git. При обновлении локальный файл не перезаписывается, а значит настройки не теряются.

Обновление идёт через UpdateService: снимок текущей версии, скачивание архива, распаковка, миграции. Снимок делается через ZipArchive; если расширения zip нет, приложение не падает фатально, а сообщает, что создать снимок невозможно — это и есть главное исправление версии 2.0.2.

Проверка состояния — отдельный эндпоинт health.json, который перечисляет загруженные расширения. Удобно: мониторинг видит проблему раньше, чем жильцы.

Замеры и цифры

Проверено 13.11.2026, двумя проверками.

Что Значение
Архив bas-ip-2.0.2.zip 1 113 546 байт
SHA-256 e6d248f0…22c9f9d, совпал с .sha256 из релиза
Файлов в архиве 289
Состав PHP 232, .woff2 12, .js 8, .css 5, .json 3
php -l по всем файлам 232 проверено, 0 ошибок
tests/, tools/ в дистрибутиве отсутствуют
bin/bas-ip doctor подключение к MySQL отклонено (учётки нет), сообщение понятное
Запуск на PHP 8.5.4 GET / → 302 на /install; /install → 500; /health.json → 500
Причина 500 ini_set(): session.sid_length INI setting is deprecated — предупреждение превращается в исключение
Версия в коде App::VERSION = '2.0.2'
BAS-IP 2.0.2: дистрибутив, проверка синтаксиса и прогон

Главный результат — не 232 чистых файла, а расхождение с заметками к релизу. Там сказано: 217 тестов зелёные на PHP 8.5 (SQLite), /health.json отдаёт 200. У нас на PHP 8.5.4 установщик и health.json отвечают 500 из-за устаревшей опции сессии session.sid_length, которую в PHP 8.5 объявили deprecated. Предупреждение в этом приложении становится ErrorException и валит запрос до того, как установщик успевает что-то показать.

Это не значит, что продукт сломан: на 8.2–8.4 всё работает, а тесты, судя по всему, ставят свой обработчик ошибок. Но факт остаётся фактом: на самой свежей версии PHP первая страница не открывается, и это надо знать до установки.

Сильные стороны продукта

  • Нет обязательного облака. Ставится на свой сервер, данные остаются у дома.
  • Четыре СУБД на выбор. SQLite для проверки, MySQL или PostgreSQL для боевой работы.
  • Переносимые миграции. Схема одна и та же на всех движках.
  • Секреты вне репозитория. Локальный конфиг и .env не перезаписываются обновлением.
  • Понятная диагностика. doctor и health.json отвечают на вопрос «чего не хватает» до запуска.
  • Контрольные суммы релиза. Архив можно проверить перед распаковкой.
  • Журнал открытий. Спор «кто открыл» решается фактом, а не памятью.

Установка

unzip bas-ip-2.0.2.zip -d /srv/bas-ip
cd /srv/bas-ip
sha256sum -c bas-ip-2.0.2.zip.sha256   # если архив рядом
php bin/bas-ip doctor
php bin/bas-ip serve                   # локальный сервер на 8080
Требование Значение
PHP 8.2 или новее
Обязательные расширения pdo, mbstring, curl, json, openssl
Для бэкапов и обновлений zip
Для шифрования секретов sodium
docroot public/
Каталог storage/ должен быть доступен на запись
cron php bin/bas-ip schedule:run --quiet раз в минуту

Настройка

flowchart TD
  L1[".bas-ip.config.local.php"] --> M["слияние: скаляры заменяются"]
  L2[".env"] --> M
  L3["config/config.php"] --> M
  M --> USE["итоговая конфигурация"]
Что настроить Где
Подключение к БД локальный конфиг или переменные DB_*
Адрес панели домофона DEVICE_BASE_URL, логин и пароль
Почта и Telegram секция notify
Обновления UPDATE_ENABLED, UPDATE_MODE, токен GitHub
Секреты php bin/bas-ip secret:set <имя> и ссылка ${secret=...}
Расписание cron раз в минуту

Порядок загрузки: локальный файл, затем .env, затем значения по умолчанию. Скаляры заменяются, списки тоже — если только ключ не помечен суффиксом +.

Почему учёт двора — это деньги, а не железо

Соблазн считать шлагбаум железной задачей велик: есть панель, есть брелоки, остальное приложится. Но 90 % конфликтов во дворе — не про створку, а про счёт.

Типичная история: жилец платил в январе, но платёж пришёл в феврале. В таблице это одна строка, в жизни — спор о задолженности. Приложение решает это распределением по периодам: платёж закрывает долг в порядке очерёдности, а не «как записали».

Вторая история: начисление сделали с ошибкой, обнаружили через месяц. В тетради придётся зачёркивать и объяснять. В системе есть перерасчёт, и он оставляет след — видно, что было и что стало.

Третья: гости. Гостевой пропуск, выданный на час, — это документ с временем. Журнал открытий показывает, когда створка поднималась, и вопрос «кто впустил» перестаёт быть предметом веры.

Отсюда и требования к таким системам: не «красивый интерфейс», а воспроизводимость расчёта и след каждого действия.

Что показывает прогон про качество кода

Формальная проверка синтаксиса — не тест качества, но кое-что она говорит.

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

Второе наблюдение: doctor сначала честно сообщает, что базы нет. Это правильное поведение — диагностика должна отвечать «чего не хватает», а не падать с фатальной ошибкой.

Третье: обработка ошибок качественная. В логе видно структурированные записи JSON с полем context, где указан файл и строка. Разбирать инцидент по такому логу можно без отладчика.

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

Где приложение не подойдёт

Честные границы.

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

Не подойдёт, если нет человека, который будет следить за cron, бэкапами и обновлениями. Самостоятельный хостинг — это ответственность, а не только независимость.

Не подойдёт для дома на пять квартир: таблица и чат справятся дешевле.

И не подойдёт как замена бухгалтерии: начисления и перерасчёты — да, полноценный бухгалтерский учёт с планом счетов — нет.

Зато подойдёт там, где важен след: журнал открытий, история платежей, воспроизводимый расчёт. Именно это и есть причина ставить систему, а не держать список в таблице.

Что видно в логах при разборе

Логи — структурированные: каждая запись это JSON с полями ts, level, channel, message, context. В контексте есть файл и строка, если это исключение.

Три канала разделены: app — обычные события, error — ошибки, отдельно есть записи уровня error с контекстом команды (например, command: doctor). Такое разделение экономит время: при разборе инцидента не нужно фильтровать всё подряд.

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

Что стоит настроить: ротацию файлов логов. По умолчанию они пишутся в storage/logs с датой в имени, и при отсутствии ротации каталог растёт. Для двора в сотню квартир это не критично, для нескольких домов — уже вопрос места.

И последнее: журнал открытий — тоже лог, но прикладной. Он нужен жильцам, а не администратору, поэтому храните его отдельно от технических логов и в экспортируемом виде: при смене правления выгрузка должна оставаться у дома.

Подводные камни

  • PHP 8.5 ломает установщик. session.sid_length объявлен deprecated, предупреждение становится исключением, /install отдаёт 500.
  • zip без вариантов. Без расширения нет ни бэкапа, ни обновления — проверяйте первым делом.
  • Тестов в дистрибутиве нет. tests/ и tools/ в архив не входят; для прогона тестов нужен клон.
  • docroot только public/. Иначе наружу уедут config/, storage/ и локальный конфиг с секретами.
  • Учётки БД по умолчанию нет. doctor падает на подключении, если не создать базу и пользователя.
  • cron обязателен. Без schedule:run не будет ни начислений по расписанию, ни напоминаний.
  • Обновление меняет файлы. Снимок версии создаётся заранее — не отключайте эту проверку.
  • Локальный конфиг вне git. Иначе после обновления можно потерять настройки или, наоборот, закоммитить пароль.
  • Расширение intl опционально. От него зависит форматирование дат и чисел: без него вид дат будет проще.
  • Панель домофона нужна для реального открытия. Без неё система ведёт учёт, но створку не поднимает.
  • Демо-данные — это демо. Проверять деньги на них можно, считать — нет.

Деньги в такой системе: что проверять руками

Автоматика ошибается тихо, поэтому первые начисления стоит сверить вручную — не «посмотреть, что красиво», а пересчитать.

Проверка первая: расщепление платежа. Внесите платёж, который больше текущего долга, и посмотрите, куда уйдёт остаток. Правильное поведение — закрыть долг и оставить переплату видимой, а не «потерять» её.

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

Проверка третья: округления. Возьмите сумму, которая делится на количество дней неровно, и сверьте итог с копейками. Расхождение в копейку на сотне квартир — это уже спор.

Проверка четвёртая: FIFO. Два долга разных периодов и один платёж. Порядок закрытия должен быть предсказуемым и одинаковым при повторном запуске.

Проверка пятая: экспорт. Выгрузите всё и откройте в таблице: если данные читаются и суммы совпадают, у вас есть резервная копия не только в виде дампа БД.

Про обновления и снимки версии

Механика обновления устроена разумно: перед заменой файлов создаётся снимок текущей версии, а распаковка идёт через ZipArchive. Версия 2.0.2 добавила проверку наличия расширения zip в двух местах, где её не было, — и это ровно тот класс ошибок, который обнаруживается в самый неподходящий момент.

Практический вывод для администратора: держите отдельный бэкап каталога и базы перед каждым обновлением, даже если приложение обещает снимок. Два независимых способа откатиться стоят дешевле одного.

И ещё: канал обновлений stable смотрит на последний релиз. Отсюда следует, что откат «на предыдущую» автоматикой не предусмотрен — только вручную, из снимка.

Чек-лист

  • [ ] Скачать архив и сверить SHA-256.
  • [ ] Проверить версию PHP: 8.2–8.4 для спокойной работы, 8.5 — с оговоркой про сессии.
  • [ ] Убедиться, что расширения pdo, mbstring, curl, json, openssl, zip есть.
  • [ ] Создать базу и пользователя, проверить php bin/bas-ip doctor.
  • [ ] Направить docroot на public/.
  • [ ] Выдать права на запись в storage/.
  • [ ] Пройти установщик, сохранить сгенерированный пароль администратора.
  • [ ] Настроить cron schedule:run.
  • [ ] Проверить /health.json.
  • [ ] Импортировать жильцов и сверить несколько начислений руками.
  • [ ] Сделать первый бэкап и проверить восстановление на копии.

Кому доверить эксплуатацию

Техническая часть несложная, но регулярная: обновления, бэкапы, cron, разбор логов. Это не «поставил и забыл».

Минимальный набор обязанностей на стороне дома: кто-то, кто умеет зайти по SSH, посмотреть health.json, поднять упавший сервис и восстановить базу из бэкапа. Если такого человека нет, лучше брать облачный сервис с поддержкой, а не ставить своё.

Второй вопрос — доступ. Администратор системы видит персональные данные жильцов и историю платежей. Значит, нужны отдельные учётки, а не один пароль на правление, и правило «ушёл из правления — потерял доступ».

Третий — регламент. Кто вносит начисления, кто подтверждает оплату, что делать при спорной сумме. Система фиксирует факты, но не придумывает правила; правила — это решение собственников.

И четвёртый, самый недооценённый: обучение. Человек, который впервые видит панель, склонен искать «кнопку как в Excel». Полчаса объяснения экономят месяц переписки. Заодно стоит договориться о словаре: «начисление», «перерасчёт», «платёж» — разные вещи, и пока их называют одним словом, споры не заканчиваются.

Как выглядит нормальный запуск

Порядок, который экономит нервы.

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

Потом — сверка. Экспорт из системы против того, что было в таблице. Расхождения — это не ошибка системы, это вопросы к данным: дубликаты, разные написания адресов, пропущенные квартиры.

Затем — перенос целиком и первые настоящие начисления с ручной проверкой. Только после этого — рассылка жильцам.

Завершает запуск бэкап и восстановление на копии. Если восстановление не проверялось, бэкапа нет — это правило работает и здесь. И последнее: запишите, кто что делал на каждом шаге. Через месяц это будет единственным объяснением, почему в базе оказались именно такие цифры.

FAQ

Нужен ли облачный сервис?

Нет. Приложение размещается на своём сервере и работает с собственной базой.

Какую базу выбрать?

Для боевой работы MySQL или PostgreSQL; SQLite удобен для проверки и небольших дворов.

Почему установщик отвечает 500 на PHP 8.5?

Из-за устаревшей опции session.sid_length: предупреждение превращается в исключение. На 8.2–8.4 этого нет.

Обязательно ли расширение zip?

Для работы — нет, для бэкапов и обновлений — да. Проверяется через doctor.

Можно ли связать с реальной панелью домофона?

Да, через REST API и настройки DEVICE_*. Без панели система ведёт только учёт.

Где хранятся секреты?

В локальном конфиге и .env, вне git; пароли устройства и токены можно шифровать через secret:set.

Что было в заметках к релизу и что добавилось здесь

Заметки 2.0.2 — короткие и по делу: одна исправленная ошибка, требования к окружению, контрольные суммы. Для обзора этого мало, поэтому основное содержание собрано из README, кода и прогона.

Было в заметках Добавлено в статье
исправление проверки zip разбор, почему это важно при обновлении и бэкапе
таблица расширений порядок проверки окружения и типичные отказы
«217 тестов зелёные на PHP 8.5» фактический прогон на 8.5.4: установщик отдаёт 500
требования к БД выбор между SQLite, MySQL и PostgreSQL по задаче

Главное — расхождение про PHP 8.5. В заметках сказано, что тесты на этой версии зелёные; на живом сервере первая же страница не открывается из-за устаревшей опции сессии. Возможно, тесты ставят свой обработчик ошибок и не проходят через установщик, — но для читателя важен итог: на 8.5 приложение сейчас не разворачивается, на 8.2–8.4 разворачивается.

Итог

BAS-IP 2.0.2 — аккуратное приложение для задачи, которую обычно решают таблицей и перепиской: учёт жильцов, начисления с перерасчётом, гостевые пропуска и журнал открытий, всё на своём сервере и без обязательного облака. Прогон подтвердил качество кода (232 файла, ноль ошибок синтаксиса) и честность релиза (контрольная сумма совпала). И он же показал границу: на PHP 8.5 установщик падает из-за устаревшей опции сессии, хотя заметки к релизу обещают зелёные тесты на этой версии. Ставить стоит на 8.2–8.4 и проверять doctor до первого входа.

Цитата: Учёт во дворе ломается не от железа, а от того, что никто не помнит, кто и когда платил.

Связанные материалы

LLM Summary

  • Тема: BAS-IP 2.0.2 «Kronos» — саморазмещаемое PHP-приложение для управления шлагбаумом в жилом комплексе.
  • Состав: жильцы и помещения с импортом из CSV/JSON/Excel, начисления с перерасчётом, расщепление до копейки, FIFO оплат, гостевые QR-пропуска, журнал открытий, REST API для панели домофона, /health.json.
  • Требования: PHP 8.2+ (рекомендуется 8.5), расширения pdo, mbstring, curl, json, openssl, плюс zip для бэкапов и обновлений и sodium для шифрования секретов; MySQL 8 / MariaDB 10.6+ / PostgreSQL 13+ / SQLite 3.
  • Проверено 13.11.2026: архив bas-ip-2.0.2.zip — 1 113 546 байт, SHA-256 e6d248f0…22c9f9d совпал с .sha256; 289 файлов, из них 232 PHP, 12 .woff2, 8 .js, 5 .css; php -l по всем 232 файлам — 0 ошибок; tests/ и tools/ в дистрибутив отсутствуют; версия в коде App::VERSION = '2.0.2'.
  • Прогон на PHP 8.5.4: GET / → 302 на /install, /install → 500, /health.json → 500; в логе error-2026-11-13.log — ini_set(): session.sid_length INI setting is deprecated (src/BasIp/Core/Session.php:76), предупреждение превращается в ErrorException.
  • Расхождение с релизом: заметки обещают 217 тестов на PHP 8.5 и /health.json → 200; на живом 8.5.4 установщик недоступен — вывод: ставить на 8.2–8.4 либо ждать исправления.
  • Настройка: локальный конфиг → .env → config/config.php; секреты шифруются через secret:set; cron php bin/bas-ip schedule:run --quiet раз в минуту; docroot только public/.
  • Не проверялось: работа с реальной панелью домофона, денежные расчёты на своих данных, восстановление бэкапа, обновление с 2.0.1.
  • Ссылки: https://github.com/paulmann/BAS-IP, https://github.com/paulmann/BAS-IP/releases/tag/v2.0.2

Промт для агента (установка и настройка)

Готовый промт: скопируйте блок целиком. Источник шагов — README.md репозитория (файла AGENTS.md нет — проверено 13.11.2026) и php bin/bas-ip doctor; сверено с прогоном на PHP 8.5.4.

Задача: развернуть BAS-IP 2.0.2 на сервере и проверить, что учёт жильцов, начисления и health-эндпоинт работают.

Материалы:
- репозиторий: https://github.com/paulmann/BAS-IP
- README: https://github.com/paulmann/BAS-IP/blob/main/README.md
- релиз и архив: https://github.com/paulmann/BAS-IP/releases/tag/v2.0.2

Шаг 1. Скачать bas-ip-2.0.2.zip и сверить SHA-256 с bas-ip-2.0.2.zip.sha256.
Шаг 2. Проверить PHP: версия 8.2–8.4 (на 8.5 установщик отдаёт 500 из-за session.sid_length), расширения pdo, mbstring, curl, json, openssl, zip.
Шаг 3. Распаковать в /srv/bas-ip, направить docroot на public/.
Шаг 4. Выдать права на запись каталогу storage/.
Шаг 5. Создать базу и пользователя, выполнить php bin/bas-ip doctor — добиться зелёного результата.
Шаг 6. Открыть установщик, пройти мастер, сохранить пароль администратора.
Шаг 7. Настроить cron: * * * * * cd /srv/bas-ip && php bin/bas-ip schedule:run --quiet
Шаг 8. Проверить /health.json — ожидается status ok и список загруженных расширений.
Шаг 9. Импортировать жильцов, сверить два-три начисления вручную.
Шаг 10. Сделать бэкап БД и проверить восстановление на копии.

Запрещено:
- открывать docroot на корень проекта: config/ и storage/ уедут наружу;
- хранить секреты в config/config.php: файл под git и перезаписывается обновлением;
- отключать проверку zip: без него нет ни бэкапа, ни обновления;
- считать демо-данные доказательством правильности денежных расчётов;
- разворачивать на PHP 8.5 без проверки установщика;
- запускать обновление без снимка версии.

Что считать успехом: doctor без ошибок, установщик пройден, health.json отдаёт ok, cron работает, начисления сверены вручную, бэкап восстановлен на копии.