Административная политика существует в двух видах: как решение и как факт на машине. Решение принимается в консоли и выглядит завершённым, факт наступает тогда, когда приложение на конкретном ноутбуке прочитало правило и стало ему следовать. Между этими состояниями лежит доставка, и занимаются ею средства управления устройствами, реестр с групповыми политиками, профили конфигурации и файл политики. Пока доставка не описана, любая политика остаётся намерением.
Наивный способ выглядит разумно: написать инструкцию, разослать её и попросить каждого выставить нужные настройки у себя. На десяти машинах это работает, потому что все десять человек сидят рядом, ставят одну и ту же версию в один день и помнят, зачем всё это делалось. Способ дешёвый и не требует ни инфраструктуры, ни согласований, и именно поэтому его тянут дальше, чем следует.
Ломается он тихо и в четырёх местах сразу. Пользовательская настройка правится пользователем, и обратная правка не оставляет следа. Новая машина приходит чистой, а инструкция к тому времени уже устарела. Версии расползаются, потому что обновляется каждый тогда, когда ему удобно. И главное - состояние парка перестаёт быть известным: на вопрос, у скольких машин закрыт вход под личной учётной записью, честного ответа нет, а есть предположение.
Профессиональный механизм разводит две вещи: доставку приложения и доставку правил. Оба потока идут через средство управления устройствами - Jamf, Intune, Kandji, - которое и ставит сборку, и применяет политику на весь парк. Транспортов у политики три, а набор ключей один: на Windows правила приходят реестром через групповые политики, и шаблоны административных политик кладутся рядом с системными; на macOS - профилем конфигурации; на Linux - файлом политики в домашнем каталоге пользователя, который приложение читает начиная с версии 2.0. Разница только в способе положить значение, смысл ключей во всех трёх случаях один и тот же.
Сам набор невелик и бьёт по существенному: разрешённые расширения, разрешённые идентификаторы команд для входа, адрес каталога расширений, отключение HTTP/2, режим обновлений и признак доверия к рабочей области. Ключ с разрешёнными командами - самый важный из них. Он превращает корпоративную сборку в корпоративную: под личной учётной записью в неё войти нельзя, и данные компании не уезжают в чужой договор через тот же самый редактор.
Политику стоит отличать от файла разрешений, хотя лежат они рядом. Разрешения задаются файлом на уровне пользователя и таким же файлом в репозитории, и описывают они другое: список команд оболочки, выполняемых без подтверждения, список инструментов протокола подключения инструментов с масками вида server:tool и server:*, и текстовые указания для классификатора автоматического ревью. Политика отвечает на вопрос, что можно установить и куда войти. Разрешения отвечают на вопрос, что агент делает без спроса. Слои разные: политику задаёт администратор парка, а файл разрешений ведут команда и репозиторий - но и его раскатывают тем же средством управления устройствами, причём настройки административной консоли замещают значения файла.
Отдельная ось - версии, и границ на ней две. Минимальная поддерживаемая версия даёт предупреждение, которое можно закрыть и работать дальше. Минимальная разрешённая версия закрытию не подлежит: обновление становится обязательным. Обе границы отсчитываются от общего выхода версии и идут с разницей примерно в месяц, около двух месяцев до первой и около трёх до второй. Смысл этой конструкции в том, что окно на обновление известно заранее, и поэтому обновление планируется как регулярная работа, а не как реакция на день, когда редактор перестал пускать.
Самое неприятное место - обновления и права администратора. На macOS обновление требует административных прав, а у разработчика в жёстко управляемом парке их обычно нет: запрос всплывает, ничем не заканчивается и повторяется. Выход - развести роли. Новую сборку доставляет средство управления устройствами, а запрос внутри приложения гасится политикой режима обновлений, выставленной в отключённое значение. Версия при этом едет централизованно и предсказуемо, а разработчик не выбирает момент и не ищет, у кого попросить пароль. На Windows та же задача решается флагами тихой установки, а первичная раскатка и обновление собираются в один набор команд. Ниже такой набор:
Проверяют результат не на машине администратора, а на образе обычного разработчика без повышенных прав, и проверяют поведением, а не наличием файла. Попробовать войти под учётной записью чужой команды и убедиться, что вход отклонён. Поставить расширение вне разрешённого списка и увидеть отказ. Дождаться обновления и убедиться, что оно приехало без единого диалога. Отдельно проверяется сеть: закрытый прокси должен пропускать адреса серверов продукта, загрузок и обновлений, каталога расширений, а также адреса сторонних поставщиков моделей, иначе исправно развёрнутая сборка окажется нерабочей по причине, не связанной с политикой.
Типичные провалы предсказуемы. Проверять политику на машине администратора, где всё разрешено и без неё. Считать, что политика заменяет файл разрешений, и оставить агенту свободу выполнять команды. Оставить режим обновлений по умолчанию там, где у людей нет административных прав, и получить вечный запрос без результата. Раскатать сборку, не открыв нужные адреса на прокси. Узнать о минимальной разрешённой версии в тот день, когда работать уже нельзя. И записать в файл политики ключ, которого приложение не знает, приняв отсутствие ошибки за применённое правило.
# Установка интерфейса командной строки; редактор доставляется средством управления устройствами
curl https://cursor.com/install -fsS | bash
# Windows: тихая установка без диалогов, без перезагрузки, с журналом
CursorSetup-x64-2.0.exe /SILENT /VERYSILENT /SUPPRESSMSGBOXES ^
/NORESTART /CLOSEAPPLICATIONS /LOG=install.log
# Windows: обновление уже установленного редактора требует признака /update
CursorSetup-x64-2.0.exe /VERYSILENT /update="%TEMP%\cursor-update.flag" ^
/CLOSEAPPLICATIONS /LOG=update.log
# Windows: шаблон политик кладётся к системным, языковой файл - в подкаталог локали
copy cursor.admx C:\Windows\PolicyDefinitions
copy cursor.adml C:\Windows\PolicyDefinitions\en-US
# macOS: те же ключи приезжают профилем конфигурации через средство управления устройствами
# Linux: файл политики, приложение читает его начиная с версии 2.0
cat > ~/.cursor/policy.json <<'JSON'
{
"AllowedTeamId": "1,3,7",
"UpdateMode": "none",
"WorkspaceTrustEnabled": true
}
JSON