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

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

Три читателя и три границы

Первая ошибка смешанной базы знаний: считать, что аудиторий две, «наши» и «чужие». На деле их как минимум три.

  • Гость: человек без учётной записи. Ему можно показать то, что вы готовы увидеть в публичном интернете: общие описания, справку по тарифам, правила обращения.
  • Клиент: человек, у которого есть вход и договор. Ему нужны инструкции по вашему продукту, регламенты подключения, истории изменений, но не ваши рабочие споры.
  • Сотрудник: видит всё предыдущее плюс внутренние заметки, разборы инцидентов, черновики и переписку об условиях.

Теперь материалы. Тоже три типа, и важно, что граница проходит не по темам, а по последствиям утечки:

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

Получается матрица, которую полезно нарисовать до первого создания полки:

Кто что должен видеть
МатериалГостьКлиентСотрудник
Общая справкачитаетчитаетчитает и правит
Клиентская инструкцияне видитчитаетчитает и правит
Внутреннее обсуждениене видитне видитчитает и правит

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

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

Как складываются права на конкретном контенте

В документации BookStack о ролях и разрешениях (Roles and Permissions) важны для нашей задачи два свойства. Первое: разрешения нескольких ролей суммируются, то есть если одна из ролей пользователя даёт действие, он его получает. Второе: права на отдельный контент могут переопределять базовые права ролей, а в модели есть ограничения вида Own, привязанные к авторству.

Из суммирования вытекает неочевидный практический вывод. Закрыть что-то одной ролью недостаточно, если у человека есть другая роль, которая это открывает. Типичная история: завели роль «Клиент» без доступа к внутреннему разделу, а потом сотруднику из партнёрской компании выдали ещё и роль «Редактор» для одной книги. В сумме он видит больше, чем вы задумывали, причём ни одна роль по отдельности ничего подозрительного не показывает.

Поэтому разумная схема строится так:

  1. Роль клиента делается минимальной по смыслу: чтение клиентского контента и ничего лишнего. Базовые права на просмотр держите узкими, а открывайте точечно.
  2. Одному человеку не выдаются роли «на всякий случай». Если сотруднику нужно видеть клиентскую часть глазами клиента, у него должна быть отдельная тестовая учётная запись только с ролью клиента, а не его рабочая запись с добавленными правами.
  3. Внутренняя часть закрывается переопределениями на уровне контента, а не надеждой на то, что роль клиента просто «не дотягивается».

Переопределения на конкретной книге или полке работают как противовес суммированию: вы явно говорите, какие роли здесь могут читать, и не зависите от общих настроек. Но у этого есть цена. Чем больше точечных исключений, тем сложнее помнить, почему страница видна. Хорошее правило: исключение должно соответствовать клетке матрицы. Если вы не можете показать клетку, которую оно реализует, исключение лишнее.

Пример: два сложения, один сюрприз

Допустим, у вас роли «Клиент» (читает книгу «Подключение»), «Сотрудник» (читает и правит всё) и «Автор документации» (правит книгу «Подключение»). Консультант-подрядчик получает «Клиент» и «Автор документации», потому что он помогает писать инструкции. В сумме он может править клиентские материалы, и это ожидаемо. Но если роль автора когда-то расширят на «просмотр всех книг», сумма молча откроет ему внутренние обсуждения. Проверять нужно не роли поодиночке, а итог для живого человека: зайти под его учётной записью или под тестовой копией с тем же набором ролей и пройти по матрице.

Четыре пути к одному материалу

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

Путь первый: поиск

Поиск неприятен тем, что результаты показывают фрагменты. Если система вдруг покажет заголовок или выдержку из закрытой страницы, утечка случится без единого открытия страницы. Поведение поиска зависит от версии и конфигурации, поэтому обещать изоляцию без проверки нельзя. Проверка простая и неприятно полезная:

  1. Выберите в закрытой странице редкое слово, которого нет больше нигде, например выдуманное кодовое имя проекта.
  2. Войдите под тестовой учётной записью клиента и введите это слово в поиск.
  3. Повторьте без входа, если у гостей есть доступ к поиску.
  4. Попробуйте несколько слов из заголовка, из тела и из подписи к картинке.

Ожидаемый результат: пусто. Если пусто только в одном из случаев, значит, остальные не проверены.

Путь второй: прямая ссылка на страницу

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

Путь третий: изображение

Здесь и спрятан сюжет из начала статьи. По документации по безопасности BookStack (Security) изображения по умолчанию размещаются с публичным доступом, а для усиления защиты есть отдельные варианты. Значит, права страницы и права картинки это два разных вопроса. Скриншот из закрытой инструкции может открываться по своему адресу тому, кто этот адрес знает.

Тут важна честность в формулировках. В той же документации сказано, что непредсказуемое имя файла делает URL сложнее для угадывания, но проверкой прав пользователя это не является. Непредсказуемый адрес это неудобство для угадывающего, но не авторизация. Адрес картинки может попасть в историю браузера, в пересылку, в журнал прокси, в письмо коллеге. Как только кто-то им поделился, замок исчез, потому что замка не было.

Практические последствия такие:

  • Если на закрытой странице есть изображения, их нужно считать потенциально доступными по адресу, пока вы не включили и не проверили защиту, описанную в документации для вашей версии.
  • Не вставляйте в скриншоты клиентские данные: токены, адреса, имена, суммы. Размытие на этапе съёмки надёжнее, чем настройка хранилища потом.
  • Для действительно чувствительных иллюстраций решите заранее, что они вообще не должны жить как изображения в странице, а должны быть вложением или отдельным закрытым файлом.

Путь четвёртый: вложение

По той же документации локальные вложения по умолчанию находятся за слоем авторизации приложения, а для S3 доступ зависит от настроек хранилища. Различие принципиальное: PDF с инструкцией, прикреплённый к странице на локальном диске, обычно отдаётся только через приложение, то есть с проверкой прав. Но если вы вынесли файлы в S3-совместимое хранилище, то защита определяется политикой самого хранилища, и проверять нужно уже его, а не только права страниц.

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

Сводка: что проверять в каждой клетке

Четыре пути для клетки «клиент не видит внутреннее обсуждение»
ПутьЧто делаетеЧто должны увидеть
ПоискВводите редкое слово из закрытой страницы под клиентомНи заголовка, ни фрагмента
Прямая ссылкаОткрываете адрес страницы в чистом окне и под клиентомОтказ в доступе
ИзображениеОткрываете адрес картинки из страницы без входаНе должно открываться; если открывается, это решается настройкой хранения или отказом от картинки
ВложениеОткрываете адрес файла без входа, отдельно для локального диска и S3Запрос на вход или отказ

Таблица лишь напоминает порядок. Ценность в том, что вы прогоняете её для каждой клетки матрицы «не видит», а не один раз для красивой демонстрации.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.

АРЕНДОВАТЬ СЕРВЕР

Доступ через родительский раздел

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

Поэтому структуру стоит строить так, чтобы граница аудитории совпадала с границей контейнера:

  • Одна полка для общей справки.
  • Отдельная полка для клиентских инструкций.
  • Отдельная закрытая полка для внутреннего.

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

Это же объясняет, почему не стоит делать клиентский раздел «просто внутренним с исключениями». Модель «всё закрыто, кроме отдельных страниц» требует от вас постоянной дисциплины в обратную сторону: каждая новая страница по умолчанию закрыта, и открыть её нужно осознанно. Модель «всё открыто для клиентов, кроме отдельных страниц» ломается при первом же забытом исключении.

Приглашение нового клиента

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

  1. Создайте учётную запись с ролью клиента и ни с какой другой. Не копируйте роли с чужой записи «как у предыдущего».
  2. Прежде чем отправлять приглашение, проверьте тестовой записью с такой же ролью, что клиент видит ровно клиентскую полку, а поиск не показывает чужого.
  3. Если у вас несколько клиентов, подумайте, должны ли они видеть материалы друг друга. Общая клиентская полка подходит для универсальных инструкций. Материалы, где фигурирует конкретная компания, лучше держать отдельно, и тогда понадобятся роли на каждого клиента или иной способ разделить аудитории. Это уже архитектурное решение: добавляйте его осознанно, потому что число ролей растёт, а вместе с ним и сумма прав на человека.
  4. Только после проверки отправляйте доступ.

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

Когда клиент уходит

Прекращение сотрудничества — момент, когда система доступа проверяется на правду. Здесь нужна трезвая формулировка того, что вы можете и чего не можете.

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

Не можете: отозвать то, что клиент уже скачал или сохранил. PDF, который он открыл, остаётся у него. Скриншот страницы остаётся. Адрес картинки, который лежит у него в браузере, может продолжать открываться, если изображение размещено с публичным доступом и вы не меняли это. Поэтому обещание «после окончания договора вы больше не имеете доступа к материалам» должно говорить о доступе к системе, а не об уже полученных копиях. Если для вас важно, чтобы клиентские инструкции не ходили по рукам, это решается условиями договора и тем, какие материалы вы вообще кладёте в клиентскую зону, но не настройкой базы знаний.

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

Где всё это размещать

Смешанная база знаний требует сервера, на котором вы контролируете хранение файлов, настройки веб-сервера и доступ к конфигурации. Это тот случай, когда пригодится собственный VPS: вы решаете, лежат ли вложения на локальном диске или во внешнем хранилище, и именно это решение определяет, кто отвечает за защиту файлов, приложение или политика хранилища. На VPS MAATRIX вы получаете root-доступ, NVMe-диски и процессоры AMD EPYC; в публичном предложении указаны локации UK, US, RU и FR, а оплата доступна картой РФ и через СБП, при этом VPS создаётся автоматически через пару минут после оплаты. Тарифы по ресурсам: Ba (1 vCPU, 2 ГБ RAM, 40 ГБ NVMe), Uab (2 vCPU, 4 ГБ, 80 ГБ), Heka (4 vCPU, 8 ГБ, 160 ГБ), Maat (8 vCPU, 16 ГБ, 240 ГБ), Djed (16 vCPU, 32 ГБ, 320 ГБ). Это параметры машины, а не обещание, сколько клиентов выдержит ваша база: нагрузку нужно мерить на своих материалах. Для небольшой документации с локальными вложениями обычно достаточно скромных ресурсов, а диск стоит выбирать с учётом того, сколько скриншотов и PDF вы накопите. Подробности и актуальное наличие образов смотрите в каталоге VPS MAATRIX.

Если вы выбираете между разными системами и думаете о переезде из облачных заметок, пригодится материал о переносе базы знаний из Notion на свой сервер: там разбирается другой инструмент, но сама логика переезда и вопросов доступа во многом схожа.

Что видит клиент

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

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