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

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

Три слоя вместо одной свалки

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

  • Общие документы сети. Стандарты обслуживания, правила возврата, регламенты безопасности, фирменные требования к оформлению. Их читают все, правит узкий круг.
  • Локальные дополнения. Что меняется в конкретном филиале: приложение, поставщик, график работы, контакты ответственных. Их читает и правит команда филиала.
  • Материалы управления. Условия с партнёрами, внутренние разборы, расчёты роялти, переписка по спорным вопросам. Читать их должна только центральная команда.

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

Как выглядит одна инструкция в двух частях

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

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

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

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

Во вторник добавляется шаг с фотофиксацией. Здесь общая страница говорит о результате («состояние товара зафиксировано и приложено к заказу»), а способ остаётся за филиалом. Одиннадцать точек прикладывают фото так, как привыкли, а редактор двенадцатой дописывает в своём дополнении, какая кнопка в приложении за это отвечает. Если бы название кнопки жило в общей странице, пришлось бы либо писать условие для одного филиала, либо оставлять одиннадцать человек с инструкцией, которая к ним не относится.

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

У содержания должен быть хозяин

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

Для франшизы удобно закрепить трёх ответственных:

  1. Владелец каждой общей книги — человек из центральной команды. Он решает, что считается правилом сети.
  2. Редактор филиала — один-два человека на точку, которые ведут локальные дополнения.
  3. Хранитель структуры — тот, кто следит за названиями, порядком полок и тем, чтобы новые материалы не оседали в случайных местах.

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

Журнал изменений на такой странице полезнее, чем кажется. Одна строка вида «дата, что поменялось, кого касается» экономит десятки вопросов в чате. Филиал с собственным приложением увидит пометку «шаг с фотофиксацией» и сразу поймёт, что ему стоит заглянуть в свое дополнение.

Роли BookStack: как их собрать под франшизу

Теперь перейдём к настройкам. Главное, что нужно держать в голове: разрешения нескольких ролей суммируются, то есть если одна из ролей пользователя даёт действие, он его получит. Это описано в документации BookStack по ролям и правам. На практике это значит, что роль нельзя «запретить» другой ролью на том же уровне: запрет в одной не отменит разрешение в другой.

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

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

Набор ролей для сети

Пример набора ролей для сети филиалов (проект, не готовая настройка)
РольЧто должна уметьГде расширяются права
Читатель сетиПросматривать общие материалыОбщие полки
Сотрудник филиалаПросматривать общее и своёПолка своего филиала
Редактор филиалаСоздавать и править локальные страницыПолка своего филиала
Владелец общей книгиПравить общие инструкцииОбщие книги по зоне ответственности
УправлениеВидеть закрытые материалыПолка управления

Обратите внимание на одну тонкость. Если в каждом филиале свои сотрудники, соблазнительно создать по роли на филиал: «Сотрудник филиала А», «Сотрудник филиала Б». Это работает и даёт самое наглядное разделение, но при росте сети вы получите десятки ролей. Альтернатива — одна общая роль, а доступ к полке филиала задаётся переопределением на самой полке для конкретных ролей. Выбор зависит от размера: для пяти-семи точек отдельные роли проще понять, для сорока уже придётся думать о сопровождении.

Что происходит, если человек работает в двух местах

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

Чтобы не полагаться на память, переводу сотрудника удобно дать короткий порядок действий из трёх шагов: сначала назначается роль нового филиала, затем снимается роль старого, и только после этого учётная запись проверяется на практике. Последний шаг важен именно из-за суммирования: если одна из ролей даёт доступ к полке, пользователь его получит, даже когда вторая роль ничего не разрешает. Значит, по одному виду списка ролей на «чистоту» можно судить только после того, как вы убедились, что чужая полка больше не открывается.

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

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

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

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

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

Картинки и вложения живут по другим правилам

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

Как сказано в разделе BookStack о безопасности, изображения по умолчанию размещаются с публичным доступом, а для усиления защиты предусмотрены отдельные варианты. Это принципиально: закрытая страница не означает закрытую картинку. Если кто-то получит адрес изображения, он может открыть его, не имея прав на страницу.

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

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

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

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

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

Вложения: другое поведение, другой риск

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

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

  1. Войти пользователем из другого филиала и убедиться, что страница недоступна.
  2. Открыть адрес вложения в окне без авторизации и убедиться, что файл не отдаётся.
  3. Для изображений на той же странице повторить проверку по адресу картинки.

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

Выпуск новой редакции и судьба старой

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

Для мелкой правки, вроде исправленной опечатки или уточнения формулировки, хватит записи в «Что изменилось». Для существенной — такой, как новый срок обращения — разумно предупредить редакторов филиалов заранее, а в странице-журнале указать дату вступления правила в силу. Заметьте: именно дату, а не «с сегодняшнего дня». Филиалам нужно время поправить собственные дополнения.

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

Новый филиал: подключение без импровизации

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

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

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

Когда партнёр уходит

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

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

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

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

BookStack — довольно скромное по ресурсам веб-приложение, и для базы знаний сети небольшого размера обычно достаточно виртуального сервера начального уровня. Мы не беремся называть точные цифры без замеров на ваших данных: потребление зависит от числа одновременных читателей, объёма вложений и поиска. Ориентиры по тарифам удобно взять из публичной линейки VPS MAATRIX: от Ba с 1 vCPU, 2 ГБ RAM и 40 ГБ NVMe до более мощных Uab, Heka, Maat и Djed. Ресурсы тарифа не равны обещанию ёмкости, поэтому начинайте с малого и смотрите на реальную нагрузку.

Есть детали, которые для базы знаний франшизы важны именно на своём сервере. Root-доступ позволяет самостоятельно настроить способ хранения изображений и вложений и проверить результат, о чём шла речь выше. Для локации стоит выбирать ту, что ближе к основной массе сотрудников, из доступных в предложении: UK, US, RU и FR. Резервное копирование в описании тарифов как встроенная возможность не заявлено, поэтому копии базы и файлов нужно организовать самостоятельно. Для базы знаний, где живут регламенты всей сети, это не формальность, а часть ответственности владельца системы.

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

Как сотрудник филиала находит своё правило

Теперь соберём всё на одной ситуации. Администратор филиала с собственным приложением открывает базу и ищет «возврат товара». Поиск возвращает общую страницу сети и дополнение своего филиала — других результатов нет, потому что чужие дополнения для него закрыты правами, а архивные редакции убраны на полку управления.

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

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