- Первый администратор создаётся через
/setup. - Пароли хранятся как Argon2 hash.
- Android получает 15-минутный JWT access token и управляемый refresh-token через
/api/v1/auth/login. - Refresh-token хранится на сервере только как hash, ротируется при каждом использовании и отзывается при выходе или смене пароля.
- Android хранит server URL и tokens в
EncryptedSharedPreferences. - Plaintext fallback Android удалён: ошибка Android Keystore не переключает приложение на обычные
SharedPreferences. - Mobile pairing token действует 10 минут, используется один раз и хранится в PostgreSQL только как hash.
- Попытки pairing ограничиваются по hash источника и token; исходные pairing/access/refresh tokens не записываются в аудит.
- OpenWrt agent использует отдельный device token.
- Device token хранится на сервере только как hash.
- Web UI
/devicesтребует вход через/login. - Production cookies имеют
HttpOnly,SecureиSameSite=Lax. - Все Web UI POST-формы защищены CSRF-токеном; детали описаны в security-web-ui.md.
- API-документация
/docs,/redoc,/openapi.jsonпо умолчанию выключена. - Команды управления выполняются только через allowlist.
- Произвольные shell-команды на роутере не поддерживаются.
- Доступ к серверным устройствам сейчас жёстко ограничен моделью
single-owner.
Сервер не стартует, если:
WRTMONITOR_JWT_SECRETпустой;WRTMONITOR_JWT_SECRETкороче 32 символов;WRTMONITOR_JWT_SECRETравен дефолтномуchange-me-*;- пароль PostgreSQL в
WRTMONITOR_DATABASE_URLпустой; - пароль PostgreSQL начинается с
change-me; - используется не PostgreSQL URL.
Исключение для тестов и CI возможно только при явном:
WRTMONITOR_ALLOW_INSECURE_DEV_DEFAULTS=trueНа реальном сервере этот параметр должен быть:
WRTMONITOR_ALLOW_INSECURE_DEV_DEFAULTS=falseProduction server_url должен быть HTTPS. Локальный HTTP разрешается только для временного теста:
WRTMONITOR_ALLOW_INSECURE_LOCAL=trueДаже при включённом параметре HTTP принимается только для loopback, link-local и private LAN адресов. Внешний домен с HTTP отклоняется. QR использует канонический WRTMONITOR_PUBLIC_SERVER_URL, а не заголовок Host от reverse proxy.
При false Web UI использует cookie Secure и должен открываться по внешнему
HTTPS-адресу. Вход через прямой http://IP:порт в этом режиме намеренно
блокируется. Android использует bearer/refresh-токены и от browser cookie не
зависит.
- произвольное выполнение shell-команд на роутере;
- входящий порт из интернета на OpenWrt;
- хранение device token в открытом виде на сервере;
- SQLite-режим для production.