Keel: как спроектировать систему, в которой нельзя подсмотреть
В большинстве CRM «скрыть поле» означает убрать его с экрана. Данные при этом лежат в той же таблице, приходят в браузер в ответе API и достаются любому, кто откроет инструменты разработчика. Для обычной задачи этого достаточно. Для Keel — нет, потому что вся суть продукта в том, что часть людей не должна знать некоторых вещей. Объясню, как такое проектируется.
Задача: цепочка клиент → менеджер → декларант
Keel — веб-CRM для процесса ВЭД (внешнеэкономической деятельности). В процессе три роли:
- Клиент — компания, которой нужно оформить груз.
- Менеджер — работает с клиентом и знает его.
- Таможенный декларант — оформляет документы и знает заявку.
Ключевое требование — обезличивание: менеджер никогда не знает, какой декларант ведёт заявку, а декларант никогда не знает, кто клиент. Это защищает коммерческую модель сервиса и персональные данные: нельзя «обойти» посредника, потому что нечего обходить.
Почему скрыть поле в интерфейсе — не решение
Если ограничение реализовано в интерфейсе, оно держится ровно до первого запроса к API. Типичные дыры:
- API возвращает объект целиком, а фронтенд просто не показывает часть полей.
- Сообщения об ошибках случайно раскрывают идентификаторы.
- Поиск, фильтры и сортировка позволяют вычислить скрытое значение косвенно.
- Экспорт и отчёты строятся запросом, который не знает про правила видимости.
Каждая такая дыра — реальный инцидент в продакшне. Поэтому в Keel ограничение лежит там, где обойти его нельзя.
Что сделано в архитектуре
Обезличивание обеспечивают сервер и физически раздельные базы данных:
| Уровень | Как работает |
|---|---|
| Хранение | Данные, которые разные роли не должны знать друг о друге, лежат в физически раздельных базах |
| Сервер | Каждый запрос выполняется в контексте роли. Сервер физически не обращается к тем данным, которые роли знать нельзя |
| API | Роль не получает лишних полей даже при ручном вызове. Отдаётся только то, что разрешено |
| Интерфейс | Просто отображает то, что разрешил сервер. На него безопасность не опирается |
Принцип такой: безопасность не должна зависеть от того, что разработчик не забыл добавить проверку. Если данных нет в ответе, их нельзя ни украсть, ни показать по ошибке.
Стек и почему он такой
- Rust (axum, sqlx) — строгая типизация позволяет выражать правила доступа на уровне типов, и часть ошибок такого рода ловится компилятором, а не в продакшне. Библиотека sqlx умеет сверять SQL-запросы со схемой базы на этапе сборки.
- Postgres — надёжная реляционная база с богатыми возможностями разграничения доступа.
- S3 — хранилище документов.
- Vue 3 + TypeScript — интерфейс с типизированным обращением к API.
- Self-hosted, single-tenant — у каждого заказчика своя установка и свои данные, без общей мультиарендной базы.
Что ещё умеет продукт
Ядро CRM: роли, карточки клиентов с контролируемым доступом к персональным данным, заявки со SLA. Поверх него — управление задачами с канбан-досками, планирование по диаграмме Ганта, учёт времени, блочный редактор документов с экспортом в DOCX и PDF, а также каналы связи с клиентами через Telegram, email и WhatsApp.
Чему этот проект учит
- Требования безопасности нужно выявлять до проектирования, а не после. «Менеджер не должен знать декларанта» — это не пункт чек-листа в конце, это исходное условие, которое определило структуру баз данных.
- Безопасность — свойство архитектуры. Её нельзя «прикрутить» перед релизом. Подробнее о подходе: Безопасная разработка ПО: как защита закладывается с первого дня.
- Строгие инструменты экономят время. Типы и проверки при сборке ловят ошибки задолго до продакшна, а это часть Качество кода: что оно значит для бизнеса и как его обеспечить.
- Юридическая грамотность помогает. Персональные данные, роли и ответственность сторон нужно понимать до написания кода.
Нужна система с жёсткими правилами доступа?
Если в вашем продукте есть данные, которые разные группы людей не должны видеть, начните с проектирования границ доступа. Опишите задачу мне в Telegram: @w1shmaster. Как мы пройдём путь от идеи до работающей системы, расскажет статья Разработка ПО с нуля под ключ: от идеи до релиза.