fix(role-edit): пустой узел после отброшенного запрета и разворот массива в PS

Два дефекта, найденных вычиткой перед ревью.

deny-rights создавал узел объекта и, если фильтр умолчаний отбрасывал
все запреты, оставлял его пустым — в файл он попадал, когда сохранение
инициировала соседняя операция. Платформа пустых узлов не производит
(0 на 223k узлов корпуса). Теперь созданный впустую узел убирается.

Правило удаления узла было «не осталось разрешающих прав» — наследие
решения «false это шум». Замеры показали обратное: узел с одними
запретами осмыслен, так закрывают реквизит. Узел удаляется, только если
в нём не осталось прав вообще.

Там же закрыт разворот массива: `return @(...)` из функции отдаёт
единственный элемент скаляром, у которого .Count равен $null, поэтому
узел с ОДНИМ правом считался пустым и удалялся целиком. Поймал гард
минимального дифа: снятие одного права давало -11 строк вместо -4.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FGkXwoXTuafcu1SXMsauFq
This commit is contained in:
Nick Shirokov
2026-09-13 21:05:57 +03:00
co-authored by Claude Opus 5
parent e8c92362d5
commit 5ec732e12b
17 changed files with 963 additions and 16 deletions
@@ -0,0 +1,23 @@
{
"name": "Отброшенный запрет не оставляет пустой узел, когда файл меняет соседняя операция",
"setup": "fixture:role-base",
"params": {
"rolePath": "Roles/Менеджер"
},
"input": [
{
"operation": "deny-rights",
"value": "InformationRegister.Цены: Read"
},
{
"operation": "add-rights",
"value": "Catalog.Товары: Insert"
}
],
"expect": {
"fileNotContains": {
"file": "Roles/Менеджер/Ext/Rights.xml",
"text": "InformationRegister.Цены"
}
}
}