feat(meta-edit,meta-compile,meta-remove): support-guard перед правкой объектов на поддержке

Пилот энфорсмента issue #23: перед записью навыки-мутаторы проверяют
состояние поддержки (Ext/ParentConfigurations.bin) и блокируют опасную
правочку. Триггер — наличие bin (конфиг на поддержке); реакция из
.v8-project.json editingAllowedCheck (deny|warn|off, по умолчанию deny).

Assert-EditAllowed (нативная копия в каждом навыке, оба порта):
walk-up резолвит uuid цели (объект / владелец / корень — по пути) и
корень конфигурации, затем G-vs-f1 и консервативная свёртка min(f1).
Два режима: require-editable (f1≥1, G≠1) для правок/добавлений;
require-removed (f1=2) для удаления.
- meta-edit (v1.7): editable на редактируемом объекте;
- meta-compile (v1.13): editable на корне (добавление нового объекта);
- meta-remove (v1.2): removed на удаляемом объекте.

Диагностика через [Console]::Error.WriteLine + exit 1 (не Write-Error:
под ErrorActionPreference=Stop тот бросает и был бы проглочен catch'ем).

Тесты: малая on-support фикстура с рукотворным bin (root/Locked f1=0,
Removed f1=2); guard-deny кейсы (expectError) — оба рантайма зелёные,
старые кейсы не сломаны (конфиги без bin → allow). Поле editingAllowedCheck
задокументировано в docs/v8-project-guide.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-20 14:57:14 +03:00
co-authored by Claude Opus 4.8
parent 489b8389aa
commit 2136245b69
22 changed files with 898 additions and 6 deletions
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Catalog uuid="22222222-2222-2222-2222-222222222222">
<Properties>
<Name>Locked</Name>
<Synonym/>
<CodeLength>9</CodeLength>
<DescriptionLength>25</DescriptionLength>
</Properties>
<ChildObjects/>
</Catalog>
</MetaDataObject>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Catalog uuid="33333333-3333-3333-3333-333333333333">
<Properties>
<Name>Removed</Name>
<Synonym/>
<CodeLength>9</CodeLength>
<DescriptionLength>25</DescriptionLength>
</Properties>
<ChildObjects/>
</Catalog>
</MetaDataObject>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Configuration uuid="11111111-1111-1111-1111-111111111111">
<Properties>
<Name>ТестКонфиг</Name>
<Vendor>ТестВендор</Vendor>
<Version>1.0</Version>
</Properties>
<ChildObjects>
<Catalog>Locked</Catalog>
<Catalog>Removed</Catalog>
</ChildObjects>
</Configuration>
</MetaDataObject>
@@ -0,0 +1 @@
{6,0,1,aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,0,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb,"1.0","ТестВендор","ТестКонфиг",3,0,0,11111111-1111-1111-1111-111111111111,0,0,22222222-2222-2222-2222-222222222222,22222222-2222-2222-2222-222222222222,2,0,33333333-3333-3333-3333-333333333333,33333333-3333-3333-3333-333333333333}
@@ -0,0 +1,6 @@
{
"name": "Guard: добавление объекта при закрытом корне (f1=0) запрещено",
"setup": "fixture:on-support",
"input": { "type": "Catalog", "name": "НовыйСправочник" },
"expectError": "support-guard"
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Catalog uuid="22222222-2222-2222-2222-222222222222">
<Properties>
<Name>Locked</Name>
<Synonym/>
<CodeLength>9</CodeLength>
<DescriptionLength>25</DescriptionLength>
</Properties>
<ChildObjects/>
</Catalog>
</MetaDataObject>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Catalog uuid="33333333-3333-3333-3333-333333333333">
<Properties>
<Name>Removed</Name>
<Synonym/>
<CodeLength>9</CodeLength>
<DescriptionLength>25</DescriptionLength>
</Properties>
<ChildObjects/>
</Catalog>
</MetaDataObject>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Configuration uuid="11111111-1111-1111-1111-111111111111">
<Properties>
<Name>ТестКонфиг</Name>
<Vendor>ТестВендор</Vendor>
<Version>1.0</Version>
</Properties>
<ChildObjects>
<Catalog>Locked</Catalog>
<Catalog>Removed</Catalog>
</ChildObjects>
</Configuration>
</MetaDataObject>
@@ -0,0 +1 @@
{6,0,1,aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,0,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb,"1.0","ТестВендор","ТестКонфиг",3,0,0,11111111-1111-1111-1111-111111111111,0,0,22222222-2222-2222-2222-222222222222,22222222-2222-2222-2222-222222222222,2,0,33333333-3333-3333-3333-333333333333,33333333-3333-3333-3333-333333333333}
@@ -0,0 +1,7 @@
{
"name": "Guard: правка объекта на замке (f1=0) запрещена",
"setup": "fixture:on-support",
"params": { "objectPath": "Catalogs/Locked.xml" },
"input": { "operations": [ { "op": "add-attribute", "name": "ТестРеквизит", "type": "String", "length": 10 } ] },
"expectError": "support-guard"
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Catalog uuid="22222222-2222-2222-2222-222222222222">
<Properties>
<Name>Locked</Name>
<Synonym/>
<CodeLength>9</CodeLength>
<DescriptionLength>25</DescriptionLength>
</Properties>
<ChildObjects/>
</Catalog>
</MetaDataObject>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Catalog uuid="33333333-3333-3333-3333-333333333333">
<Properties>
<Name>Removed</Name>
<Synonym/>
<CodeLength>9</CodeLength>
<DescriptionLength>25</DescriptionLength>
</Properties>
<ChildObjects/>
</Catalog>
</MetaDataObject>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17">
<Configuration uuid="11111111-1111-1111-1111-111111111111">
<Properties>
<Name>ТестКонфиг</Name>
<Vendor>ТестВендор</Vendor>
<Version>1.0</Version>
</Properties>
<ChildObjects>
<Catalog>Locked</Catalog>
<Catalog>Removed</Catalog>
</ChildObjects>
</Configuration>
</MetaDataObject>
@@ -0,0 +1 @@
{6,0,1,aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,0,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb,"1.0","ТестВендор","ТестКонфиг",3,0,0,11111111-1111-1111-1111-111111111111,0,0,22222222-2222-2222-2222-222222222222,22222222-2222-2222-2222-222222222222,2,0,33333333-3333-3333-3333-333333333333,33333333-3333-3333-3333-333333333333}
@@ -0,0 +1,6 @@
{
"name": "Guard: удаление объекта на замке (f1=0) запрещено",
"setup": "fixture:on-support",
"object": "Catalog.Locked",
"expectError": "support-guard"
}