From d27dfbf8e1fbcad38f7d5446d4d4f3e52c4cb60c Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Mon, 9 Feb 2026 21:22:14 +0300 Subject: [PATCH] Add role-guide.md and update README with role skills Co-Authored-By: Claude Opus 4.6 --- .claude/skills/role-compile/SKILL.md | 250 ++++++++-------- .claude/skills/role-info/SKILL.md | 12 +- .../skills/role-info/scripts/role-info.ps1 | 277 +++++++++--------- README.md | 11 +- docs/role-guide.md | 69 +++++ 5 files changed, 357 insertions(+), 262 deletions(-) create mode 100644 docs/role-guide.md diff --git a/.claude/skills/role-compile/SKILL.md b/.claude/skills/role-compile/SKILL.md index 41a069db..5df23c48 100644 --- a/.claude/skills/role-compile/SKILL.md +++ b/.claude/skills/role-compile/SKILL.md @@ -19,12 +19,22 @@ allowed-tools: /role-compile ``` -- **RoleName** — программное имя роли (например, `ВыполнениеРегламентныхЗаданий`) -- **RolesDir** — каталог `Roles/` в исходниках конфигурации или обработки +- **RoleName** — программное имя роли +- **RolesDir** — каталог `Roles/` в исходниках конфигурации -## Что создать +## Файловая структура и регистрация -### 1. Файл метаданных: `Roles/.xml` +``` +Roles/ + ИмяРоли.xml ← метаданные (uuid, имя, синоним) + ИмяРоли/ + Ext/ + Rights.xml ← определение прав +``` + +В `Configuration.xml` добавить `ИмяРоли` в секцию ``. + +## Шаблон метаданных: Roles/ИмяРоли.xml ```xml @@ -49,11 +59,9 @@ allowed-tools: ``` -**UUID:** Сгенерируй через PowerShell: `[guid]::NewGuid().ToString()` +**UUID:** `powershell.exe -Command "[guid]::NewGuid().ToString()"` -**Namespace:** Минимальный набор — достаточно `xmlns`, `v8`, `xr`, `xs`, `xsi`. Полный набор из спецификации тоже корректен. - -### 2. Файл прав: `Roles//Ext/Rights.xml` +## Шаблон прав: Roles/ИмяРоли/Ext/Rights.xml ```xml @@ -64,146 +72,136 @@ allowed-tools: false true false - + ``` -### 3. Регистрация в Configuration.xml - -Добавь `ИмяРоли` в секцию `` файла `Configuration.xml`. +NB: namespace `http://v8.1c.ru/8.2/roles` (исторически 8.2, не 8.3). ## Формат блока прав -Каждый объект — отдельный блок ``: - -```xml - - ТипОбъекта.ИмяОбъекта - - ИмяПрава - true - - -``` - -Несколько прав — несколько `` внутри одного ``. - -## Права по типам объектов (краткая справка) - -### Ссылочные объекты данных - -| Тип | Типичные права | -|-----|---------------| -| `Catalog` | Read, Insert, Update, Delete, View, Edit, InputByString, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractiveDelete | -| `Document` | (все Catalog) + Posting, UndoPosting, InteractivePosting, InteractivePostingRegular, InteractiveUndoPosting, InteractiveChangeOfPosted | -| `ChartOfAccounts` | (как Catalog) + предопределённые: InteractiveDeletePredefinedData и др. | -| `ChartOfCharacteristicTypes` | (как ChartOfAccounts) | -| `ChartOfCalculationTypes` | (как ChartOfAccounts) | -| `ExchangePlan` | (как Catalog) | -| `BusinessProcess` | (как Catalog) + Start, InteractiveStart, InteractiveActivate | -| `Task` | (как Catalog) + Execute, InteractiveExecute, InteractiveActivate | - -### Регистры - -| Тип | Права | -|-----|-------| -| `InformationRegister` | Read, Update, View, Edit, TotalsControl | -| `AccumulationRegister` | Read, Update, View, Edit, TotalsControl | -| `AccountingRegister` | Read, Update, View, Edit, TotalsControl | -| `CalculationRegister` | Read, View | - -### Простые типы - -| Тип | Права | -|-----|-------| -| `DataProcessor` | Use, View | -| `Report` | Use, View | -| `Constant` | Read, Update, View, Edit | -| `CommonForm` | View | -| `CommonCommand` | View | -| `Subsystem` | View | -| `DocumentJournal` | Read, View | -| `Sequence` | Read, Update | -| `SessionParameter` | Get, Set | -| `CommonAttribute` | View, Edit | -| `WebService` / `HTTPService` / `IntegrationService` | Use | - -### Вложенные объекты - -| Вложенный тип | Права | Пример | -|--------------|-------|--------| -| `*.StandardAttribute.*` | View, Edit | `Document.Реализация.StandardAttribute.Posted` | -| `*.Attribute.*` | View, Edit | `Catalog.Контрагенты.Attribute.ИНН` | -| `*.TabularSection.*` | View, Edit | `Document.Реализация.TabularSection.Товары` | -| `*Register.*.Dimension.*` | View, Edit | `InformationRegister.Цены.Dimension.Номенклатура` | -| `*Register.*.Resource.*` | View, Edit | `InformationRegister.Цены.Resource.Цена` | -| `*.Command.*` | View | `Catalog.Контрагенты.Command.Открыть` | - -### Configuration - -Права на конфигурацию в целом: `Configuration.ИмяКонфигурации` - -Ключевые: Administration, DataAdministration, ThinClient, WebClient, ThickClient, ExternalConnection, Output, SaveUserData, InteractiveOpenExtDataProcessors, InteractiveOpenExtReports - -## Типичные наборы прав - -### Чтение справочника - ```xml Catalog.Номенклатура Readtrue Viewtrue - InputByStringtrue ``` -### Полные права на документ +Имя объекта — dot-нотация: `ТипОбъекта.Имя[.ТипВложенного.ИмяВложенного]`. + +## Практические наборы прав + +### Catalog / ExchangePlan + +| Набор | Права | +|-------|-------| +| Чтение | Read, View, InputByString | +| Полные | Read, Insert, Update, Delete, View, Edit, InputByString, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark | + +### Document + +| Набор | Права | +|-------|-------| +| Чтение | Read, View, InputByString | +| Полные | Read, Insert, Update, Delete, View, Edit, InputByString, Posting, UndoPosting, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractivePosting, InteractivePostingRegular, InteractiveUndoPosting, InteractiveChangeOfPosted | + +### InformationRegister / AccumulationRegister / AccountingRegister + +| Набор | Права | +|-------|-------| +| Чтение | Read, View | +| Полные | Read, Update, View, Edit | + +TotalsControl — только для управления итогами, обычно не нужно. + +### Простые типы + +| Тип | Права | +|-----|-------| +| `DataProcessor` / `Report` | Use, View | +| `Constant` | Read, Update, View, Edit (чтение: Read, View) | +| `CommonForm` / `CommonCommand` / `Subsystem` / `FilterCriterion` | View | +| `DocumentJournal` | Read, View | +| `Sequence` | Read, Update | +| `SessionParameter` | Get (+ Set если пишет) | +| `CommonAttribute` | View (+ Edit если редактирует) | +| `WebService` / `HTTPService` / `IntegrationService` | Use | +| `CalculationRegister` | Read, View | + +### Редкие ссылочные типы + +| Тип | Особенности (относительно Catalog) | +|-----|-------| +| `ChartOfAccounts`, `ChartOfCharacteristicTypes`, `ChartOfCalculationTypes` | + Predefined-права (InteractiveDeletePredefinedData и др.) | +| `BusinessProcess` | + Start, InteractiveStart, InteractiveActivate | +| `Task` | + Execute, InteractiveExecute, InteractiveActivate | + +### Типы БЕЗ прав в ролях + +Enum, FunctionalOption, DefinedType, CommonModule, CommonPicture, CommonTemplate — не фигурируют в Rights.xml. + +### Вложенные объекты (права: View, Edit) + +``` +Catalog.Контрагенты.Attribute.ИНН +Document.Реализация.StandardAttribute.Posted +Document.Реализация.TabularSection.Товары +InformationRegister.Цены.Dimension.Номенклатура +InformationRegister.Цены.Resource.Цена +Catalog.Контрагенты.Command.ОткрытьКарточку ← только View +Task.Задача.AddressingAttribute.Исполнитель +``` + +Используются для точечного запрета: `false` на конкретный реквизит. + +### Configuration + +Объект: `Configuration.ИмяКонфигурации`. Ключевые права: Administration, DataAdministration, ThinClient, WebClient, ThickClient, MobileClient, ExternalConnection, Output, SaveUserData, InteractiveOpenExtDataProcessors, InteractiveOpenExtReports, MainWindowModeNormal, MainWindowModeWorkplace, MainWindowModeEmbeddedWorkplace, MainWindowModeFullscreenWorkplace, MainWindowModeKiosk, AnalyticsSystemClient. + +> DataHistory-права (ReadDataHistory, UpdateDataHistory и др.) существуют у Catalog, Document, Register, Constant — но используются крайне редко, в типовых ролях практически не встречаются. + +## RLS (ограничения на уровне записей) + +Внутрь ``, после ``. Применяется к Read, Update, Insert, Delete. + +```xml + + Read + true + + #ИмяШаблона("Параметр1", "Параметр2") + + +``` + +Шаблоны — в конце Rights.xml, после всех ``: + +```xml + + ИмяШаблона(Параметр1, Параметр2) + Текст шаблона + +``` + +`&` в условии → `&`. Типичные шаблоны: ДляОбъекта, ПоЗначениям, ДляРегистра. + +## Пример: роль для регламентного задания ```xml - Document.РеализацияТоваровУслуг + Catalog.Валюты Readtrue - Inserttrue - Updatetrue - Deletetrue - Postingtrue - UndoPostingtrue - Viewtrue - InteractiveInserttrue - Edittrue - InteractiveSetDeletionMarktrue - InteractiveClearDeletionMarktrue - InteractivePostingtrue - InteractivePostingRegulartrue - InteractiveUndoPostingtrue - InteractiveChangeOfPostedtrue - InputByStringtrue -``` - -### Использование обработки - -```xml - DataProcessor.ОбновлениеЦен - Usetrue - Viewtrue - -``` - -### Чтение/запись регистра - -```xml - - InformationRegister.ЦеныНоменклатуры + InformationRegister.КурсыВалют Readtrue Updatetrue - Viewtrue - Edittrue + + + Constant.ОсновнаяВалюта + Readtrue ``` -## Полная спецификация - -См. [1c-role-spec.md](../../docs/1c-role-spec.md) — полный каталог прав, RLS, шаблоны ограничений, версии формата. +Фоновые задания не требуют Interactive/View/Edit-прав и прав конфигурации (ThinClient, WebClient и др.) — только программные (Read, Insert, Update, Delete, Posting). diff --git a/.claude/skills/role-info/SKILL.md b/.claude/skills/role-info/SKILL.md index 9e3acfcd..98c38cc9 100644 --- a/.claude/skills/role-info/SKILL.md +++ b/.claude/skills/role-info/SKILL.md @@ -31,11 +31,17 @@ powershell.exe -File .claude\skills\role-info\scripts\role-info.ps1 -RightsPath |----------|:------------:|----------| | `-RightsPath` | да | Путь к Rights.xml | | `-ShowDenied` | нет | Показать запрещённые права (по умолчанию скрыты) | -| `-MaxPerGroup` | нет | Макс. объектов на группу (по умолчанию 20). `0` = без ограничений | +| `-Limit` | нет | Макс. строк вывода (по умолчанию `150`). `0` = без ограничений | +| `-Offset` | нет | Пропустить N строк — для пагинации (по умолчанию `0`) | | `-OutFile` | нет | Записать результат в файл (UTF-8 BOM). Без этого — вывод в консоль | **Важно:** Всегда используй `-OutFile` и читай результат через Read tool. Прямой вывод в консоль через bash ломает кириллицу. +Для большой роли при усечении вывода: +```powershell +... -Offset 150 # пагинация: пропустить первые 150 строк +``` + ## Формат вывода ``` @@ -65,8 +71,12 @@ Templates: ДляРегистра, ПоЗначениям --- Total: 138 allowed, 18 denied + +[TRUNCATED] Shown 150 of 220 lines. Use -Offset 150 to continue. ``` +Используйте `-Offset N` и `-Limit N` для постраничного просмотра. + ### Обозначения - `[RLS]` — право с ограничением на уровне записей (restrictionByCondition) diff --git a/.claude/skills/role-info/scripts/role-info.ps1 b/.claude/skills/role-info/scripts/role-info.ps1 index 86490178..4c93908c 100644 --- a/.claude/skills/role-info/scripts/role-info.ps1 +++ b/.claude/skills/role-info/scripts/role-info.ps1 @@ -1,27 +1,25 @@ param( - [Parameter(Mandatory=$true)][string]$RightsPath, - [switch]$ShowDenied, - [int]$MaxPerGroup = 20, - [string]$OutFile + [Parameter(Mandatory=$true)][string]$RightsPath, + [switch]$ShowDenied, + [int]$Limit = 150, + [int]$Offset = 0, + [string]$OutFile ) $ErrorActionPreference = 'Stop' -# --- Output helper --- +# --- Output helper (always collect, paginate at the end) --- $script:lines = @() -function Out([string]$text) { - if ($OutFile) { $script:lines += $text } - else { Write-Host $text } -} +function Out([string]$text) { $script:lines += $text } # --- Resolve paths --- if (-not [System.IO.Path]::IsPathRooted($RightsPath)) { - $RightsPath = Join-Path (Get-Location).Path $RightsPath + $RightsPath = Join-Path (Get-Location).Path $RightsPath } if (-not (Test-Path $RightsPath)) { - Out "[ERROR] File not found: $RightsPath" - exit 1 + Write-Host "[ERROR] File not found: $RightsPath" + exit 1 } # --- Try to find metadata file for role name/synonym --- @@ -34,18 +32,18 @@ $roleFolderName = Split-Path $roleDir -Leaf $metaPath = Join-Path $rolesDir "$roleFolderName.xml" if (Test-Path $metaPath) { - try { - [xml]$metaXml = Get-Content -Path $metaPath -Encoding UTF8 - $ns = New-Object System.Xml.XmlNamespaceManager($metaXml.NameTable) - $ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses") - $ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core") - $nameNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Name", $ns) - if ($nameNode) { $roleName = $nameNode.InnerText } - $synNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Synonym/v8:item[v8:lang='ru']/v8:content", $ns) - if ($synNode) { $roleSynonym = $synNode.InnerText } - } catch { - # Ignore metadata parsing errors - } + try { + [xml]$metaXml = Get-Content -Path $metaPath -Encoding UTF8 + $ns = New-Object System.Xml.XmlNamespaceManager($metaXml.NameTable) + $ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses") + $ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core") + $nameNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Name", $ns) + if ($nameNode) { $roleName = $nameNode.InnerText } + $synNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Synonym/v8:item[v8:lang='ru']/v8:content", $ns) + if ($synNode) { $roleSynonym = $synNode.InnerText } + } catch { + # Ignore metadata parsing errors + } } if (-not $roleName) { $roleName = $roleFolderName } @@ -70,78 +68,78 @@ $totalDenied = 0 $objects = $root.GetElementsByTagName("object", $rightsNs) foreach ($obj in $objects) { - $objName = "" - $rights = @() + $objName = "" + $rights = @() - foreach ($child in $obj.ChildNodes) { - if ($child.LocalName -eq "name" -and $child.NamespaceURI -eq $rightsNs) { - $objName = $child.InnerText - } - if ($child.LocalName -eq "right" -and $child.NamespaceURI -eq $rightsNs) { - $rName = "" - $rValue = "" - $hasRLS = $false - foreach ($rc in $child.ChildNodes) { - if ($rc.LocalName -eq "name") { $rName = $rc.InnerText } - if ($rc.LocalName -eq "value") { $rValue = $rc.InnerText } - if ($rc.LocalName -eq "restrictionByCondition") { $hasRLS = $true } - } - if ($rName -and $rValue) { - $rights += @{ name = $rName; value = $rValue; rls = $hasRLS } - } - } - } + foreach ($child in $obj.ChildNodes) { + if ($child.LocalName -eq "name" -and $child.NamespaceURI -eq $rightsNs) { + $objName = $child.InnerText + } + if ($child.LocalName -eq "right" -and $child.NamespaceURI -eq $rightsNs) { + $rName = "" + $rValue = "" + $hasRLS = $false + foreach ($rc in $child.ChildNodes) { + if ($rc.LocalName -eq "name") { $rName = $rc.InnerText } + if ($rc.LocalName -eq "value") { $rValue = $rc.InnerText } + if ($rc.LocalName -eq "restrictionByCondition") { $hasRLS = $true } + } + if ($rName -and $rValue) { + $rights += @{ name = $rName; value = $rValue; rls = $hasRLS } + } + } + } - if (-not $objName -or $rights.Count -eq 0) { continue } + if (-not $objName -or $rights.Count -eq 0) { continue } - # Split into type prefix and short name - $dotIdx = $objName.IndexOf(".") - if ($dotIdx -lt 0) { continue } - $typePrefix = $objName.Substring(0, $dotIdx) - $shortName = $objName.Substring($dotIdx + 1) + # Split into type prefix and short name + $dotIdx = $objName.IndexOf(".") + if ($dotIdx -lt 0) { continue } + $typePrefix = $objName.Substring(0, $dotIdx) + $shortName = $objName.Substring($dotIdx + 1) - foreach ($r in $rights) { - if ($r.value -eq "true") { - $totalAllowed++ - if (-not $allowed.Contains($typePrefix)) { - $allowed[$typePrefix] = [ordered]@{} - } - if (-not $allowed[$typePrefix].Contains($shortName)) { - $allowed[$typePrefix][$shortName] = @() - } - $suffix = $r.name - if ($r.rls) { - $suffix += " [RLS]" - $rlsObjects += "$typePrefix.$shortName ($($r.name))" - } - $allowed[$typePrefix][$shortName] += $suffix - } - else { - $totalDenied++ - if (-not $denied.Contains($typePrefix)) { - $denied[$typePrefix] = [ordered]@{} - } - if (-not $denied[$typePrefix].Contains($shortName)) { - $denied[$typePrefix][$shortName] = @() - } - $denied[$typePrefix][$shortName] += $r.name - } - } + foreach ($r in $rights) { + if ($r.value -eq "true") { + $totalAllowed++ + if (-not $allowed.Contains($typePrefix)) { + $allowed[$typePrefix] = [ordered]@{} + } + if (-not $allowed[$typePrefix].Contains($shortName)) { + $allowed[$typePrefix][$shortName] = @() + } + $suffix = $r.name + if ($r.rls) { + $suffix += " [RLS]" + $rlsObjects += "$typePrefix.$shortName ($($r.name))" + } + $allowed[$typePrefix][$shortName] += $suffix + } + else { + $totalDenied++ + if (-not $denied.Contains($typePrefix)) { + $denied[$typePrefix] = [ordered]@{} + } + if (-not $denied[$typePrefix].Contains($shortName)) { + $denied[$typePrefix][$shortName] = @() + } + $denied[$typePrefix][$shortName] += $r.name + } + } } # --- Restriction templates --- $templates = @() $tplNodes = $root.GetElementsByTagName("restrictionTemplate", $rightsNs) foreach ($tpl in $tplNodes) { - foreach ($child in $tpl.ChildNodes) { - if ($child.LocalName -eq "name") { - $tName = $child.InnerText - # Extract just the name part before parentheses - $parenIdx = $tName.IndexOf("(") - if ($parenIdx -gt 0) { $tName = $tName.Substring(0, $parenIdx) } - $templates += $tName - } - } + foreach ($child in $tpl.ChildNodes) { + if ($child.LocalName -eq "name") { + $tName = $child.InnerText + # Extract just the name part before parentheses + $parenIdx = $tName.IndexOf("(") + if ($parenIdx -gt 0) { $tName = $tName.Substring(0, $parenIdx) } + $templates += $tName + } + } } # --- Output --- @@ -154,78 +152,91 @@ Out "" Out "Properties: setForNewObjects=$setForNew, setForAttributesByDefault=$setForAttrs, independentRightsOfChildObjects=$independentChild" Out "" -# Helper: output group with truncation +# Helper: output group function OutGroup($objMap, [string]$prefix, [switch]$isDenied) { - $keys = @($objMap.Keys) - $shown = 0 - foreach ($shortName in $keys) { - if ($MaxPerGroup -gt 0 -and $shown -ge $MaxPerGroup) { - $remaining = $keys.Count - $shown - Out " ... ещё $remaining (используй -MaxPerGroup 0 для полного списка)" - break - } - if ($isDenied) { - $rightsList = ($objMap[$shortName] | ForEach-Object { "-$_" }) -join ", " - } else { - $rightsList = $objMap[$shortName] -join ", " - } - Out " ${shortName}: $rightsList" - $shown++ - } + foreach ($shortName in @($objMap.Keys)) { + if ($isDenied) { + $rightsList = ($objMap[$shortName] | ForEach-Object { "-$_" }) -join ", " + } else { + $rightsList = $objMap[$shortName] -join ", " + } + Out " ${shortName}: $rightsList" + } } # Allowed rights grouped by type if ($allowed.Count -gt 0) { - Out "Allowed rights:" - Out "" - foreach ($typePrefix in $allowed.Keys) { - $objMap = $allowed[$typePrefix] - Out " $typePrefix ($($objMap.Count)):" - OutGroup $objMap $typePrefix - Out "" - } + Out "Allowed rights:" + Out "" + foreach ($typePrefix in $allowed.Keys) { + $objMap = $allowed[$typePrefix] + Out " $typePrefix ($($objMap.Count)):" + OutGroup $objMap $typePrefix + Out "" + } } else { - Out "(no allowed rights)" - Out "" + Out "(no allowed rights)" + Out "" } # Denied rights if ($ShowDenied -and $denied.Count -gt 0) { - Out "Denied rights:" - Out "" - foreach ($typePrefix in $denied.Keys) { - $objMap = $denied[$typePrefix] - Out " $typePrefix ($($objMap.Count)):" - OutGroup $objMap $typePrefix -isDenied - Out "" - } + Out "Denied rights:" + Out "" + foreach ($typePrefix in $denied.Keys) { + $objMap = $denied[$typePrefix] + Out " $typePrefix ($($objMap.Count)):" + OutGroup $objMap $typePrefix -isDenied + Out "" + } } elseif ($totalDenied -gt 0) { - Out "Denied: $totalDenied rights (use -ShowDenied to list)" - Out "" + Out "Denied: $totalDenied rights (use -ShowDenied to list)" + Out "" } # RLS summary if ($rlsObjects.Count -gt 0) { - Out "RLS: $($rlsObjects.Count) restrictions" + Out "RLS: $($rlsObjects.Count) restrictions" } # Templates if ($templates.Count -gt 0) { - Out "Templates: $($templates -join ', ')" + Out "Templates: $($templates -join ', ')" } Out "" Out "---" Out "Total: $totalAllowed allowed, $totalDenied denied" -# --- Write to file if requested --- -if ($OutFile) { - if (-not [System.IO.Path]::IsPathRooted($OutFile)) { - $OutFile = Join-Path (Get-Location).Path $OutFile - } - $utf8 = New-Object System.Text.UTF8Encoding($true) - [System.IO.File]::WriteAllLines($OutFile, $script:lines, $utf8) - Write-Host "Output written to $OutFile" +# --- Pagination and output --- +$totalLines = $script:lines.Count +$lines = $script:lines + +if ($Offset -gt 0) { + if ($Offset -ge $totalLines) { + Write-Host "[INFO] Offset $Offset exceeds total lines ($totalLines). Nothing to show." + exit 0 + } + $lines = $lines[$Offset..($totalLines - 1)] +} + +if ($Limit -gt 0 -and $lines.Count -gt $Limit) { + $shown = $lines[0..($Limit - 1)] + $remaining = $totalLines - $Offset - $Limit + $shown += "" + $shown += "[TRUNCATED] Shown $Limit of $totalLines lines. Use -Offset $($Offset + $Limit) to continue." + $lines = $shown +} + +if ($OutFile) { + if (-not [System.IO.Path]::IsPathRooted($OutFile)) { + $OutFile = Join-Path (Get-Location).Path $OutFile + } + $utf8 = New-Object System.Text.UTF8Encoding($true) + [System.IO.File]::WriteAllLines($OutFile, $lines, $utf8) + Write-Host "Output written to $OutFile" +} else { + foreach ($l in $lines) { Write-Host $l } } diff --git a/README.md b/README.md index 2cb9d208..4a788d95 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ |--------|--------|----------|------| | Внешние обработки (EPF) | 10 навыков `/epf-*` | Создание, модификация, сборка обработок из XML-исходников | [Подробнее](docs/epf-guide.md) | | Табличный документ (MXL) | 4 навыка `/mxl-*` | Анализ, создание, компиляция макетов печатных форм | [Подробнее](docs/mxl-guide.md) | -| Управляемые формы (Form) | 4 навыка `/form-*` | Анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) | +| Управляемые формы (Form) | 5 навыков `/form-*` | Анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) | +| Роли (Role) | 2 навыка `/role-*` | Анализ прав роли, создание роли из описания | [Подробнее](docs/role-guide.md) | | Утилиты | `/img-grid` | Наложение сетки на изображение для определения пропорций колонок | — | ## Требования @@ -38,6 +39,7 @@ - [Табличный документ (MXL)](docs/1c-spreadsheet-spec.md) — XML-формат SpreadsheetDocument, совместимость версий - [MXL DSL](docs/mxl-dsl-spec.md) — JSON-формат описания макета для `/mxl-compile` и `/mxl-decompile` - [Form DSL](docs/form-dsl-spec.md) — JSON-формат описания формы для `/form-compile` +- [Роли (Rights.xml)](docs/1c-role-spec.md) — XML-формат прав роли, типы объектов, RLS ## Структура репозитория @@ -61,16 +63,21 @@ ├── form-compile/ # Компиляция формы из JSON ├── form-validate/ # Валидация формы ├── form-add/ # Добавление элементов в форму +├── form-patterns/ # Справочник паттернов компоновки форм +├── role-info/ # Анализ прав роли +├── role-compile/ # Создание роли из описания └── img-grid/ # Сетка для анализа изображений docs/ ├── epf-guide.md # Гайд: внешние обработки ├── mxl-guide.md # Гайд: табличный документ ├── form-guide.md # Гайд: управляемые формы +├── role-guide.md # Гайд: роли ├── 1c-xml-format-spec.md # Спецификация XML-формата ├── 1c-form-spec.md # Спецификация управляемых форм ├── 1c-help-spec.md # Спецификация встроенной справки ├── build-spec.md # Спецификация сборки/разборки ├── 1c-spreadsheet-spec.md # Спецификация табличного документа ├── mxl-dsl-spec.md # Спецификация MXL DSL -└── form-dsl-spec.md # Спецификация Form DSL +├── form-dsl-spec.md # Спецификация Form DSL +└── 1c-role-spec.md # Спецификация ролей (Rights.xml) ``` diff --git a/docs/role-guide.md b/docs/role-guide.md new file mode 100644 index 00000000..ff40e964 --- /dev/null +++ b/docs/role-guide.md @@ -0,0 +1,69 @@ +# Роли (Role) + +Навыки группы `/role-*` позволяют анализировать и создавать роли 1С — XML-файлы прав доступа (Rights.xml) и метаданных. + +## Навыки + +| Навык | Параметры | Описание | +|-------|-----------|----------| +| `/role-info` | `` | Компактная сводка прав: объекты по типам, только разрешённые, RLS, шаблоны | +| `/role-compile` | ` ` | Создание роли: метаданные + Rights.xml по описанию прав | + +## Сценарии использования + +### Анализ существующей роли + +``` +> Проанализируй права роли Roles/БазовыеПраваБП/Ext/Rights.xml +``` + +Claude вызовет `/role-info`, получит компактную сводку (тысячи строк XML → 50–300 строк текста) и опишет: +- какие объекты доступны и с какими правами +- где есть ограничения RLS +- какие шаблоны ограничений используются + +### Создание роли для регламентного задания + +``` +> Проанализируй модуль регламентного задания ОбновлениеКурсовВалют +> и создай роль с минимальными правами для его выполнения +``` + +Claude проанализирует код, определит используемые объекты метаданных, и вызовет `/role-compile` для создания роли с нужными правами (Read, Update, Posting и т.д.). + +### Создание роли по описанию + +``` +> Создай роль МенеджерПродаж с правами: +> - Документ РеализацияТоваровУслуг: полные права +> - Справочник Контрагенты: чтение +> - Справочник Номенклатура: чтение +> - Регистр ЦеныНоменклатуры: чтение +``` + +Рабочий цикл: +1. Claude генерирует `Roles/МенеджерПродаж.xml` (метаданные с UUID) +2. Claude генерирует `Roles/МенеджерПродаж/Ext/Rights.xml` (права) +3. Регистрирует роль в `Configuration.xml` (``) +4. Проверяет результат через `/role-info` + +## Структура файлов роли + +``` +Roles/ +├── ИмяРоли.xml # Метаданные (UUID, синоним) +└── ИмяРоли/ + └── Ext/ + └── Rights.xml # Права доступа +``` + +Регистрация в `Configuration.xml`: +```xml + + ИмяРоли + +``` + +## Спецификация + +Полная спецификация формата: [1c-role-spec.md](1c-role-spec.md) — типы объектов, права, RLS, шаблоны ограничений, версии формата.