# BAS-IP Gate Manager

**Система управления шлагбаумом BAS-IP для жилого комплекса** — жители, оплаты, гостевой доступ, журнал открываний, рассылки и REST API в одном application, которое поднимается за пять минут и работает на PHP 8.2+ без единого внешнего CDN.

[![PHP](https://img.shields.io/badge/PHP-8.2%2B%20%28рекомендуется%208.5%29-777bb3?logo=php&logoColor=white)](https://www.php.net/)
[![DB](https://img.shields.io/badge/MySQL%20%7C%20MariaDB%20%7C%20PostgreSQL%20%7C%20SQLite-336791?logo=postgresql&logoColor=white)](wiki/03-Configuration.md)
[![Tests](https://img.shields.io/badge/tests-200%20passed-brightgreen)](tests)
[![Version](https://img.shields.io/badge/version-2.0.2%20Kronos-orange)](CHANGELOG.md)
[![No CDN](https://img.shields.io/badge/CDN-none%2C%20всё%20локально-success)](wiki/04-Architecture.md)

> **v2 «Kronos»** — полный рефакторинг v1 (один файл `bas-ip.php` с токеном в репозитории)
> в product-grade приложение: роли и права, биллинг с перерасчётами, гостевые пропуски
> с QR-кодом, журнал каждого открывания, рассылки, бэкапы, автообновление, Tailwind CSS
> + shadcn/ui с тёмной темой и полностью автономный набор ассетов.
> Исходный код v1 навсегда сохранён в ветке [`main`](https://github.com/paulmann/BAS-IP/tree/main).

---

## Зачем это нужно

В жилом комплексе со шлагбаумом BAS-IP постоянно крутится одна и та же рутина:
кто-то платит за обслуживание, кто-то забывает; курьерам и гостям нужно открывать
ворота; председатель хочет знать, кто и когда заезжал. BAS-IP Gate Manager закрывает
весь цикл:

* **База жителей** — ФИО, несколько телефонов, e-mail, квартира, машины (госномер + марка),
  комментарии, чекбоксы «доступ» и «включен». Массовые действия и расчёты учитывают
  только активных жителей.
* **Оплаты** — вводите общую сумму обслуживания за месяц, система делит её между
  активными жителями (поровну, по площади, по числу жителей или по доле), выставляет счета
  и рассылает уведомления со ссылкой на оплату. При смене числа участников или суммы —
  перерасчёт с дополнительными счетами и сторно, без тронутых уже выставленных счетов.
* **Гостевой доступ** — житель сам создаёт пропуск на 12 часов (настраивается до 72):
  ссылка с QR-кодом, короткий код для клавиатуры панели, PIN. Каждое создание и каждое
  открывание пишется в журнал.
* **Журнал шлагбаума** — кто, когда, каким доступом (свой / гостевой / API / аварийный),
  результат, устройство, фото-снимок камеры.
* **Админка** — пользователи и сессии, настройки, аудит, бэкапы, импорт/экспорт базы
  (CSV/JSON/Excel), объявления, расписания и «тихие часы», диагностика, обновления.
* **REST API и интеграции** — токены с областями доступа, Prometheus-метрики, Telegram-бот,
  Home Assistant, вебхуки.

## Возможности

| Блок | Детали |
|---|---|
| Аутентификация | логин / e-mail / **номер телефона** в любом написании (bcrypt/argon2id), 2FA TOTP, «запомнить меня», сброс пароля по e-mail, блокировка после серии неудач, управление сессиями; учётки жителей создаются одной кнопкой: логин = телефон, пароль генерируется |
| Роли | `admin` (всё), `operator` (жители, касса, шлагбаум, рассылки), `resident` (свой кабинет) + 40+ точечных прав |
| Жители | карточка с историей: счета, оплаты, машины, контакты, гостевые пропуска, открывания, комментарии; мягкое удаление и восстановление |
| Биллинг | начисления (charges) → счета (invoices) → оплаты (payments) с FIFO-распределением, переплата на балансе, перерасчёт, должники, напоминания, пени-статусы «просрочен» |
| Шлагбаум | драйверы: панель BAS-IP Camdroid (`/api/v0`), произвольное HTTP-реле, эмулятор (dry-run); несколько устройств; **камера привязана к шлагбауму**: кадры через сервер, MJPEG-поток через прокси или прямой поток; SIP вкл/выкл; перезагрузка |
| Пульт жителя | полноэкранный `/remote`: гигантская кнопка «ОТКРЫТЬ» (~95% экрана) с полноэкранным откликом и вибрацией, живая камера выбранного шлагбаума, переключатель камер, Wake Lock — управление одной рукой из машины |
| Гостевой доступ | подписанные ссылки, QR, код из 6 символов без неоднозначных глифов, PIN для панели, лимиты на жителя и на дом, авто-истечение |
| Уведомления | каналы: log, SMTP/e-mail, Telegram (бот + рассылки), SMS, WhatsApp, webhook; очередь с ретраями; шаблоны с подстановками `{name}`, `{amount}`, `{pay_link}`… |
| Данные | импорт жителей из CSV/JSON/Excel с инспекцией и маппингом колонок, экспорт всего, бэкапы БД (mysqldump/pg_dump/sqlite) с восстановлением |
| Безопасность | CSP с nonce, CSRF, rate-limit на всё, security-заголовки, шифрование секретов (AES-256-GCM), аудит-лог, IP-allowlist, hardened-сессии |
| Эксплуатация | веб-установщик, `bin/bas-ip` (71 команда), cron-планировщик, режим обслуживания, `/health` + `/metrics`, автообновление из GitHub с бэкапом и откатом |
| UI | Tailwind CSS + shadcn/ui-токены, светлая/тёмная тема (переключатель, авт по системе, сохранение), mobile-first, PWA-манифест, командная палитра, всё локально — без CDN |

## Быстрый старт (5 минут)

Требования: **PHP 8.2+** (рекомендуется 8.5) с расширениями `pdo`, `mbstring`, `curl`,
`json`, `openssl`, `zip`; любая из **MySQL 8 / MariaDB 10.6+ / PostgreSQL 13+ / SQLite 3**.

```bash
git clone https://github.com/paulmann/BAS-IP.git
cd BAS-IP
php bin/bas-ip serve            # встроенный сервер → http://localhost:8080
```

Откройте `http://localhost:8080` — мастер установки проверит окружение,
протестирует соединение с БД и панелью, создаст `.bas-ip.config.local.php`
(он в `.gitignore`: секреты не попадут в репозиторий и не потеряются при
обновлении), применит миграции, создаст администратора (пароль генерируется
автоматически — можно заменить) и сразу войдёт в админку; по желанию
заполнит демо-данные.

Для production: веб-сервер должен смотреть в `public/`
([nginx](wiki/01-Installation.md#nginx), [Apache](wiki/01-Installation.md#apache) — готовые конфиги в wiki),
`storage/` — доступна на запись, плюс cron:

```cron
* * * * * cd /var/www/bas-ip && php bin/bas-ip schedule:run --quiet
```

## Конфигурация

Все настройки — в `config/config.php` (значения по умолчанию, под git) и
`.bas-ip.config.local.php` в корне (ваши значения и секреты, вне git).
Порядок загрузки: **локальный файл → `.env` → config по умолчанию**. Секреты
(пароль устройства, токены ботов) можно хранить шифрованными:
`php bin/bas-ip secret:set DEVICE_PASSWORD` и ссылка `${secret:DEVICE_PASSWORD}`
в конфиге. Полная справка по каждому ключу — [wiki/03-Configuration.md](wiki/03-Configuration.md).

## Тесты

```bash
php tests/run.php                      # SQLite (по умолчанию)
BASIP_TEST_DB=mysql php tests/run.php  # MySQL / MariaDB
BASIP_TEST_DB=pgsql php tests/run.php  # PostgreSQL
php tools/smoke.php                    # end-to-end: 68 проверок всех маршрутов
```

200 тестов / 850+ проверок: деньги (расщепление до копейки, FIFO оплат, перерасчёт),
аутентификация и права, гостевые пропуска, HTTP-слой (CSRF, заголовки, редиректы),
импорт/экспорт, 2FA/TOTP, обновления.

## Документация

* **[Wiki](wiki/Home.md)** — установка, конфигурация, архитектура, гайды администратора
  и жителя, биллинг, API, устройства, безопасность, бэкапы, обновления, CLI, миграция с v1.
* **Встроенная справка** — в приложении на `/help` (36 разделов, поиск, горячие клавиши).
* **API** — `/api/v1/docs` (интерактивный справочник) и [wiki/10-API.md](wiki/10-API.md).
* [CHANGELOG](CHANGELOG.md) · [SECURITY](SECURITY.md) · [CONTRIBUTING](CONTRIBUTING.md)

## Структура проекта

```
bin/bas-ip            консоль (71 команда: migrate, billing:*, gate:*, backup:*, update:*)
config/               config.php (дефолты) + routes.php (таблица маршрутов)
database/migrations/  схема БД (переносима между MySQL/PostgreSQL/SQLite)
public/               документ-рут: index.php, ассеты (css/js/шрифты/иконки — всё локальное)
resources/            css-исходники Tailwind, views (PHP-шаблоны), встроенная справка
src/BasIp/            ядро: Core (контейнер/роутер/сессии), Db, Auth, Http, Domain,
                      Services, Notify, Device, Update, Console, Support
storage/              логи, бэкапы, экспорт, очередь, кэш, сессии (вне git)
tests/                200 тестов + smoke; tools/ — сборка ассетов и smoke-тесты
wiki/                 полная документация (GitHub Wiki)
```

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

* Пароли — `password_hash` (bcrypt, при наличии sodium — argon2id), 2FA TOTP,
  ротация сессий при входе, absolute + idle timeout.
* CSP `default-src 'self'` c nonce для скриптов, `X-Frame-Options`, `nosniff`,
  `Referrer-Policy`, `Permissions-Policy`, HSTS (за HTTPS), `no-store` для HTML.
* CSRF-токены на все POST, rate-limit на логин/API/открытие ворот/гостевые ссылки.
* Секреты шифруются AES-256-GCM (ключ приложения), аудит всех значимых действий,
  журнал входов, API-токены с областями доступа и сроком действия.
* Сообщение об уязвимости: см. [SECURITY.md](SECURITY.md) — **не** создавайте публичный issue.

> ⚠️ **Наследие v1:** в истории ветки `main` лежит `.api_token` устройства.
> Если вы использовали v1 с реальной панелью — **отзовите/смените этот ключ**
> в настройках BAS-IP. v2 хранит токены устройств только в шифрованном виде.

## Обновление версии

Приложение умеет обновлять себя само: **Админка → Система → Обновления** или
`php bin/bas-ip update:run`. Перед установкой создаётся снимок файлов и бэкап БД,
локальный конфиг и `storage/` никогда не перезаписываются, доступен откат
(`update:rollback`). Подробности — [wiki/14-Updating.md](wiki/14-Updating.md).

## Лицензия

PolyForm Noncommercial 1.0.0 © Mikhail Deynekin — см. [LICENSE](LICENSE).
Иконки — [Lucide](https://lucide.dev) (ISC), шрифты — Inter и JetBrains Mono (OFL 1.1),
QR — qrcode-generator (MIT). Все зависимости вендорятся локально.
