Documentation
¶
Overview ¶
Package moduleseedparity — сверка раздела `seed` манифеста модуля с ЖИВОЙ базой (задача kacho#1891, вторая половина её предиката).
Сверяются ВСЕ ЧЕТЫРЕ подраздела, и невыразимого вида строки не осталось ¶
Раздел несёт четыре подраздела — служебные записи, группы, выдачи и вступления, — и сверка судит каждый. Здесь стояло «наружу выведена только НЕВЫРАЗИМОСТЬ: у выдачи есть ключ `roleId` и нет ни одного ключа для ОТНОШЕНИЯ, поэтому выдача отношением необъявима ни при каком написании; группа необъявима по следствию» и называлась живой проба предпосылки `TestBindingFormStillCannotExpressARelationGrant`. Шапка пережила предмет: ключ `grantedRelation` заведён 2026-09-04 (kacho#1936), проба сработала как обещала и снята вместе со своим предметом, предикат `ExpressibleByForm` и перечень `Inexpressible` — тоже (надгробия ниже). Всякая живая строка модуля судится наравне с остальными.
Число границы считается ПО ВЛАДЕЛЬЦУ, и это не педантизм ¶
Строка без модуля-владельца (`kacho-api-gateway`, `bootstrap-admin`, `user:*`, владельческая привязка системного аккаунта) манифестом МОДУЛЯ невыразима by construction: объявлять её некому, и её отсутствие среди объявленного — верно, а не пробел. Перепись поэтому печатает по каждому подразделу четыре величины: объявлено · живых · без модуля-владельца · с владельцем. Одно число скрывало бы ровно тот случай, ради которого граница названа.
Владелец живой СЛУЖЕБНОЙ ЗАПИСИ выводится ИМЕНЕМ; владелец ГРУППЫ — ОБЪЯВЛЕНИЕМ ¶
Служебная запись модуля названа `kacho-<служба>`; служба переводится в модуль закрытого набора платформы. Запись, чьё имя этому не отвечает, манифестом модуля невыразима by construction — у неё нет модуля-владельца, — и считается отдельно. Иначе её отсутствие среди объявленных читалось бы как неполнота.
Группа так не именуется: обе живые группы платформы носят приставку `module-`, а объявляет их манифест САМОЙ службы (приёмка MRW-1, Р5). Поэтому группа относится к модулю по объявлению — GroupOwnership, ключ — пара (аккаунт, имя); выдача, чей субъект группа, — по объявлению этой группы. Ключ СРАВНЕНИЯ остаётся тройкой с назначением (`keysOfGroup`): относи строку той же тройкой — и дрейф назначения ушёл бы в разряд «без владельца», погасив обе стороны вердикта разом. Правило имени для групп отвергнуто, потому что не называет владельца: обе группы приставку несут, а объявляет их один манифест из шести.
Index ¶
Constants ¶
const ( SubjectTypeGroup = "group" SubjectTypeServiceAccount = "serviceAccount" )
SubjectTypeGroup / SubjectTypeServiceAccount — написание вида субъекта, принятое МАНИФЕСТОМ. Живая строка переводится в него ОДИН раз, на чтении: второе написание того же предмета разошлось бы с первым молча.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Binding ¶
type Binding struct {
SubjectType string
SubjectName string
// RoleID — выдача РОЛЬЮ: единственная форма, которую манифест умеет
// объявить.
RoleID string
// Relation — выдача ОТНОШЕНИЕМ. Ключа для неё у формы манифеста нет ни
// одного, поэтому строка с непустым Relation невыразима by construction
// (kacho#1936). Поле здесь ради того, чтобы это было ВИДНО, а не выпадало из
// чтения молча.
Relation string
ScopeType string
ScopeID string
}
Binding — выдача, которую делает установка модуля.
Вид субъекта пишется по-МАНИФЕСТНОМУ (`serviceAccount`, `group`): второе написание того же предмета разошлось бы с первым, поэтому перевод живой строки (`service_account`) делается ОДИН раз, на чтении, а не по месту сравнения.
Якорь области хранится в точечной форме (`iam.cluster`) — так его пишет манифест, и так же переводится живая пара `resource_type`/`resource_id`.
type Census ¶
type Census struct {
Manifests int
SA Subsection
Groups Subsection
Bindings Subsection
Joins Subsection
}
Census — объём осмотренного. Печатается ВСЕГДА и ДО вердикта: «находок ноль» обязано быть отличимо от «прочитано ноль».
type GroupOwnership ¶ added in v0.5.0
GroupOwnership — какой модуль ОБЪЯВИЛ группу: пара (аккаунт, имя) → модуль (приёмка MRW-1, Р5).
Ключ — пара, а не имя и не тройка. Не имя: то же имя в другом аккаунте — другая группа. Не тройка: назначение принадлежит ключу СРАВНЕНИЯ, и, попав в ключ атрибуции, оно отправило бы строку с разошедшимся назначением в разряд «без владельца», где обе стороны вердикта молчат.
Написания сравниваются СЫРЫМИ — окна двух написаний аккаунта здесь нет: оно существует ради непереведённых чужих манифестов и истекает с их переводом.
func (GroupOwnership) Declare ¶ added in v0.5.0
func (o GroupOwnership) Declare(module, account, name string)
Declare записывает объявление: манифест модуля `module` заводит группу `name` в аккаунте `account`.
type Join ¶
Join — вступление служебной записи в чужую группу. Обе стороны адресуются ПАРОЙ (аккаунт, имя): так они уникальны в продукте.
type ModuleState ¶
type ModuleState struct {
Module string
ManifestFile string
DeclaredSA []ServiceAccount
LiveSA []ServiceAccount
DeclaredGroup []Group
LiveGroup []Group
DeclaredBinding []Binding
LiveBinding []Binding
DeclaredJoin []Join
LiveJoin []Join
}
ModuleState — обе стороны сверки по одному модулю.
Живые строки приходят сюда УЖЕ отнесёнными к модулю-владельцу: строки без владельца сверке не подлежат и считаются переписью отдельно.
type Result ¶
type Result struct {
// Findings — расхождения объявленного с живым. Гейт на них падает.
Findings []string
}
Result — исход сверки.
Перечень ОДИН. Их было два, и различие было несущим: расхождение чинилось правкой манифеста, невыразимое — правкой ФОРМЫ, разными людьми в разных изменениях, и сложить их значило бы требовать от автора манифеста починить то, чего он написать не может.
Второй перечень снят вместе со своим предметом (kacho#1936): форма научилась выражать выдачу отношением, и строк, которых автор написать не может, не осталось. Держать пустой перечень значило бы держать исключение, которому нечего исключать, — оно не истекло бы уже никогда.
func Compare ¶
func Compare(states []ModuleState) Result
Compare сравнивает объявленное с живым по каждому модулю.
Расхождение называется В ОБЕ СТОРОНЫ: строка живая и не объявленная — манифест неполон; объявленная и не живая — манифест обещает то, чего установка не завела. Второе не мягче первого: применитель, когда он появится, заведёт по объявлению.
Обход ОДИН: перечни находок и невыразимого производятся вместе, поэтому вызывающий не может прочитать один и забыть про другой.
type ServiceAccount ¶
ServiceAccount — служебная запись: то, что сверяется, и ничего сверх. Идентификатор сюда НЕ входит: живой его производит выражение внутри миграции (`'sva' || substr(md5(name), 1, 17)`), то есть он есть частность записи, а не то, что объявляет манифест. Сверять по нему значило бы требовать от манифеста воспроизвести случайность.
func (ServiceAccount) String ¶
func (s ServiceAccount) String() string
type Subsection ¶
Subsection — перепись одного подраздела посева.
Величин ТРИ, и ни одну нельзя выбросить, не потеряв различия, ради которого перепись и печатается: `Live` отвечает, читалось ли вообще что-то; `Ownerless` отделяет невыразимое by construction (объявлять некому) от пробела; `Owned` называет предмет сверки. Одно число вместо трёх скрывало бы ровно тот случай, ради которого граница названа.
ЧЕТВЁРТАЯ величина здесь была — `Inexpressible`, «та часть предмета, которой форма не умеет», — и снята вместе со своим предметом (kacho#1936): форма научилась выражать выдачу отношением, невыразимого вида строки не осталось. Величина, тождественно равная нулю, перепись не уточняет, а разбавляет: читатель ищет у неё смысл и не находит.
func (Subsection) String ¶
func (s Subsection) String() string