Documentation
¶
Overview ¶
Package moduleroleparity — сверка ОБЪЯВЛЕННЫХ манифестом системных ролей модуля с тем, что лежит в живой базе (задача продукта #1891).
Предмет: манифест обязан ОБЪЯВЛЯТЬ то, что у модуля есть ¶
Раздел `resources` каждого манифеста выводится из канона `fga_model.fga` — единственного документа, — и проверяется побайтовой сверкой. У раздела `roles` такого документа нет: действующее состояние ролей есть результат наложения применённых миграций, из которых ранние отменяются поздними. Поэтому объявление роли манифестом нельзя ни вывести, ни проверить чтением: угаданный раздел не остался бы бумажным — применитель (#1090) пишет им живые выдачи.
Отсюда способ доказательства: ПРОГОН против живой базы. Миграции исполняются по-настоящему, строки читаются оттуда, где они лежат, и объявление сверяется с НИМИ. Разбор SQL здесь не участвует ни одной строкой — он распознаватель, и молча пропустил бы форму записи, которой не знает.
Операнд «манифеста» производит ПРИМЕНИТЕЛЬ, а не копия его правил ¶
Второй перевод «манифест → строка роли» разошёлся бы с первым молча: оба отвечают одинаково на законном входе. Поэтому сторона манифеста собирается вызовом настоящего применителя (`moduleroles.Applier`) с писателем, который вместо записи ЗАПОМИНАЕТ — см. пробу. Здесь, в чистом ядре, живёт только сравнение двух уже готовых наборов.
Почему сравнение — отдельная чистая функция ¶
Способность гейта упасть доказывается инъекцией, а инъекция, требующая поднятой базы, стоила бы контейнера на каждое утверждение. Ядро чисто: `parity_injection_test.go` подаёт ему синтетические наборы и утверждает обе стороны по каждой оси.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Diff ¶
func Diff(states []ModuleState, ledger []Postponement) []string
Diff — находки сверки. Порядок устойчив: находка читается человеком, и её перестановка между прогонами читалась бы как изменение.
Осей четыре, и каждая своя:
- модуль не объявил живых ролей и не стоит в ведомости;
- объявленная роль не найдена в базе — объявление шире действительности;
- живая роль не объявлена модулем, который ОБЪЯВИЛ хотя бы одну, — раздел неполон, и его неполнота молчит: применитель напишет объявленное и не тронет остальное;
- роль есть на обеих сторонах, а её содержание расходится.
Плюс две оси самоистечения ведомости.
func RulesLiteral ¶
RulesLiteral — правила одной строкой, ДОСЛОВНО и без сортировки.
Приведение к канону здесь запрещено: применённая миграция несёт у ярусов чтения ровно `["read","list","get"]`, и сортировка либо разрешение снятого имени дали бы ДРУГУЮ строку — то есть сверка объявляла бы согласие там, где применитель записал бы иное.
Types ¶
type Census ¶
type Census struct {
// Manifests — манифестов модулей прочитано.
Manifests int
// Declared — ролей объявлено манифестами суммарно.
Declared int
// Live — системных ролей прочитано из базы суммарно.
Live int
// Ownerless — живых ролей, чей первый сегмент НЕ член закрытого набора
// модулей (`admin`, `edit`, `view`, `owner`, `kacho-system.*`). Манифестом
// они невыразимы by construction и находкой быть не могут: сверять их не с
// чем, и число названо именно поэтому.
Ownerless int
// Postponed — модулей, стоящих в ведомости #1891.
Postponed int
}
Census — объём осмотренного. Печатается ВСЕГДА и до всякого вердикта: без него «ноль находок» неотличимо от «ноль прочитанного».
type ModuleState ¶
type ModuleState struct {
// Module — имя модуля так, как его называет манифест.
Module string
// ManifestFile — координата манифеста: находка обязана называть, что править.
ManifestFile string
// Declared — роли, объявленные манифестом, в порядке объявления.
Declared []Role
// Live — роли этого модуля, прочитанные из живой базы.
Live []Role
}
ModuleState — что известно об одном модуле закрытого набора.
type Postponement ¶
type Postponement struct {
// Module — модуль, чьё объявление отложено.
Module string
// Why — чем отложенное держится: причина и предикат снятия.
Why string
}
Postponement — запись ведомости #1891: модуль, чьи роли ещё не объявлены.
Ведомость ИСТЕКАЕТ САМА, и это её несущее свойство: запись, чей модуль уже объявил свои роли, — находка, а не «уже не нужна»; запись модуля, у которого живых ролей нет вовсе, — тоже находка: откладывать нечего.
type Role ¶
Role — системная роль в форме, общей для обеих сторон сверки.
Полей ровно четыре, и каждое ОБЪЯВЛЕНО манифестом либо ВЫВЕДЕНО из объявленного применителем:
- `ID` выводится функцией имени (`domain.SystemRoleID`) — сверяется потому, что именно на него ссылаются выдачи: разошедшийся идентификатор означал бы новую строку рядом со старой, а не приведение старой;
- `Name` — `roles[].id` манифеста дословно;
- `Description` — назначение роли;
- `Rules` — право роли.
Разрешения (`permissions`) здесь НЕ сверяются: они сворачиваются из правил одной функцией (`domain.CompileRules`), и сверка свёртки с её же результатом была бы утверждением о постоянстве функции, а не о согласии манифеста с базой. Их согласие — предмет собственного гейта, и он есть: расхождение свёртки с хранимой формой ловит сверка проекций посева.