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

Как это устроено внутри

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

Шифрование чувствительных данных

API-ключи платёжных провайдеров (Brocard и т.д.) шифруются в БД алгоритмом AES-256-GCM. Master-ключ хранится в env сервера, отдельно от базы — дамп БД сам по себе бесполезен без сервера. Пароли пользователей хранятся как bcrypt-хеш с солью; восстановить исходный пароль из БД невозможно.

Бэкапы

Hetzner Cloud Backups делают еженедельные снимки сервера на стороне провайдера, плюс ежедневный pg_dump базы внутри сервера с ретеншном 14 дней. Восстановление до любой точки за последние 7 дней — за минуты.

Защита логина

Сессии — JWT, секрет ротируется. Rate-limit на /login и /forgot-password: 5 попыток за 15 минут с одной пары email+IP, потом блок ещё на 15 минут. Soft-suspend для пользователей: данные сохраняются, но войти нельзя — обратимая операция, никаких потерь.

Доступ внутри команды (RBAC)

Пять ролей: OWNER, ADMIN, FINANCE, TEAM_LEAD, BUYER. Каждая операция (создать карту, выплатить зарплату, поменять план) проверяется на сервере — клиентскому фильтру не доверяем. TEAM_LEAD видит только свою команду; BUYER — только свои связки.

Изоляция между организациями

Каждый запрос к данным идёт с фильтром по organizationId, который выводится из сессии — не из URL и не из тела запроса. Подменить orgId в запросе нельзя: сервер использует только тот, что привязан к текущему пользователю.

Журнал админских действий

Append-only лог любогоадминского действия: смена тарифа, выдача триала, wipe данных, удаление организации, блокировка пользователя. Записи нельзя редактировать. Если возникает вопрос «кто и когда что-то сделал в моей организации» — у нас есть ответ.

Privacy в нашей админке

Мы как админы и support видим метаданные организаций (количество транзакций, активных юзеров, активацию по 6 точкам, статус интеграции с Brocard) — но не суммы. Конкретные транзакции, балансы кошельков и API-ключи нам недоступны через интерфейс. Это сознательная граница, а не недосмотр.

Сетевой периметр

TLS через Let's Encrypt с автообновлением. Caddy reverse-proxy спереди, приложение и Postgres в одной internal-сети Docker — Postgres не выставлен на публичный интерфейс. SSH только по ключу (без паролей), fail2ban против перебора.

Право на забвение

Полный экспорт всех данных организации в ZIP-архив CSV — одной кнопкой в /settings/export, без модерации и подтверждений. Удаление организации — owner-кнопка в /settings/profile с подтверждением через slug. После удаления стираются связанные пользователи без других организаций и временные демо-аккаунты.

Soft-block авто-синков на правки оператора

Если оператор вручную правит транзакцию, пришедшую через Brocard sync, она помечается как «отредактирована локально». Следующий синк уже не перетирает её — человеческое значение побеждает данные провайдера до явного сброса флага.

На случай если что-то покажется недостаточным

Я отвечаю в TG в течение часа — на любые вопросы по безопасности, на просьбу подробнее раскрыть какую-то секцию или показать конкретный код. Контакты на странице «О проекте».