Documentation
¶
Overview ¶
acceptance_edit_after_verdict.go — правка ОДОБРЕННОЙ приёмки после вердикта объявляется в самом документе.
Порт с монорепо (`internal/repohygiene/acceptanceeditafterverdict.go`, снят вынесением службы — `kacho#2597`). Изменилось: путь дома приёмок (был `services/iam/docs/engineering/acceptance`, здесь — `docs/engineering/acceptance` от корня СВОЕГО модуля) и обход git через `platformtree`/`gitenv` вместо внутреннего `repoRoot(t)` монорепо. Осталось дословно: имя функции гейта (`TestAcceptanceEditedAfterItsVerdictSaysSo`), сам разбор и текст находки.
Предмет ¶
Вердикт есть утверждение о РЕВИЗИИ, которую прочитал проверяющий: правка её не переносит и не отзывает задним числом. Документ, чья строка состояния правлена раньше, чем сам файл, и не назвавший эту правку прямо, объявляет вердикт о ревизии, которую никто не читал.
Почему пара величин, а не одна ¶
Признак — сравнение двух отметок: когда последний раз правилась СТРОКА СОСТОЯНИЯ и когда сам документ. Обе берутся в ЭПОХЕ: строковое сравнение дат в двух часовых поясах даёт неверный порядок.
acceptance_path_coordinate.go — гейт: ПУТЬ, названный приёмкой как ПРЕДИКАТ, резолвится в дереве службы либо называет свой ДОМ.
Сосед по классу — `acceptance_probe_coordinate.go`: там координата есть ИМЯ ПРОБЫ, здесь — ПУТЬ. Предмет один (утверждение, пережившее свой предмет), граница разбора — разная, и разница ниже названа целиком, потому что дважды она ИНВЕРТИРОВАНА и списать её на небрежность легко.
Предмет ¶
Приёмка доказывает свои утверждения ПРЕДИКАТОМ — командой, которую читатель обязан прогнать сам: `git grep … -- <путь>`. Предикат, чей путь в дереве не существует, даёт пустоту НЕ ПОТОМУ, что находок нет, а потому, что читать было нечего. «Ноль находок» становится неотличимо от «ноль прочитанного», и читатель делает вывод О ДЕРЕВЕ по замеру, который ничего не измерял.
Это тот же класс, что у соседа, но он ТИШЕ. Мёртвое имя пробы обнаруживается первым же прогоном (`go test -run` отвечает «no tests to run»). Мёртвый путь не отвечает ничем: команда завершается успехом и печатает пустоту — ровно то, чего от неё и ждали, когда утверждение было «здесь чисто».
Замер, из которого гейт заведён (`kaname#71`, дерево на `bbd196ea`): путей, названных предикатом, — 52, из них не резолвилось **66 вхождений в 16 документах** по наивному предикату задачи и **192 в 24** по разбору, знающему путь-спецификацию в кавычках. Разница — не придирка: она и есть слепая зона наивного предиката, а слепая зона проверки не краснеет и не зеленеет.
ГРАНИЦА РАЗБОРА — названа явно, потому что путь стоит в тексте ТРОЯКО ¶
Один и тот же путь встречается в приёмке в трёх видах, и лишь один из них — координата, за которой читатель идёт с командой:
`git grep -n 'X' -- internal/manifest` — ПРЕДИКАТ: путь после `--`, СУДИТСЯ `internal/manifest/roles.go:135` — проза: описание места, НЕ судится `git ls-files 'proto/kacho/cloud/iam/**'` — путь-спец БЕЗ `--`, НЕ судится
ПРОЗА ВНЕ СУЖДЕНИЯ, и это решение, а не недосмотр. Путь в прозе — описание, а не адрес для прогона; в корпусе приёмок службы таких вхождений ОДНОГО только монорепного корня 992 в 33 документах, и почти все они — исторические утверждения о дереве, каким оно было ДО выноса (`kacho#2598`). Судить их значило бы требовать переписать свидетельство о прошлом. Число прозаических вхождений тем не менее ПЕЧАТАЕТСЯ переписью: слепая зона, которую видно, остаток, а не дыра.
ПУТЬ-СПЕЦИФИКАЦИЯ БЕЗ `--` ВНЕ СУЖДЕНИЯ ПО ДРУГОЙ ПРИЧИНЕ, и она несущая: в форме `git ls-files <спец>` путь сплошь и рядом есть САМ ПРЕДМЕТ УТВЕРЖДЕНИЯ ОБ ОТСУТСТВИИ — «такого корня в дереве нет, → 0». Там нерезолвящийся путь не дефект, а ровно то, что доказывают, и находка на нём была бы ложной. Отличить «путь мёртв» от «путь назван мёртвым намеренно» можно лишь прочитав НАМЕРЕНИЕ соседней прозы, а этого гейт не умеет и обещать не вправе. Замер: в дереве таких вхождений 33, из них утверждением об отсутствии — 27. Число печатается.
ОГОРОЖЕННЫЙ БЛОК КОДА СУДИТСЯ — ИНВЕРСИЯ ОТНОСИТЕЛЬНО СОСЕДА ¶
Сосед пропускает огороженные блоки целиком: имя пробы внутри команды — не координата, а часть предиката, и судить его значило бы краснеть на собственном объяснении документа.
Здесь наоборот: блок кода — ГЛАВНОЕ место жительства предиката. Приёмка выносит команду в блок именно тогда, когда хочет, чтобы её прогнали. Пропусти гейт огороженные блоки — и он потерял бы 48 вхождений из 192 (четверть), не сказав об этом ничем. Поэтому блок судится, а различение делает не забор, а ПОЗИЦИЯ ТОКЕНА: после `--` в строке, несущей `git grep` либо `git ls-files`.
ПОДСТАНОВОЧНЫЙ ЗНАК: судится ГЛУБОЧАЙШИЙ ПРЕДОК БЕЗ МЕТАСИМВОЛА ¶
`internal/migrations/*.sql` резолвится, если есть КАТАЛОГ `internal/migrations`, а не если шаблону что-то соответствует. Различие несущее в обе стороны:
- шаблон, которому сегодня не соответствует ничто, — ЗАКОННЫЙ вердикт («миграций с такой датой нет»), а не мёртвая координата;
- каталог, которого нет, — мёртвая координата, даже когда шаблон выглядит правдоподобно.
Отсюда правило отсечения: берём часть до первого метасимвола и поднимаемся до ближайшего `/`. Наивное «часть до звёздочки» ошибается на шаблоне, чей метасимвол стоит ВНУТРИ имени файла (`internal/migrations/20260902*`): оно объявило бы мёртвым живой каталог. Класс пойман на себе при заведении гейта.
НАЗВАННЫЙ ДОМ: чужой репозиторий — вне суждения, но НЕ прощён ¶
Форма ВЗЯТА у соседа (`владелец/репозиторий:путь`, необязательно `@<ревизия>`), а он взял её у `scripts/docs-gate/check-03-holding-claim-resolves.py` воркспейса. Отличие от соседа одно: там дом стоит у ИМЕНИ, здесь — у ПУТИ, потому что координата этого гейта и есть путь. Двоеточие не спутать с git-формой `<ревизия>:<путь>`: слева от него требуется слэш, которого у ревизии не бывает.
Чужой дом ВНЕ суждения по построению: чужого дерева рядом может не быть, а сеть в прогоне гейта запрещена. «Вне суждения» отличается от «прощено» тремя свойствами, и все три обязательны:
- чужая координата СЧИТАЕТСЯ, а её дома ПЕЧАТАЮТСЯ: дом, стоящий в корпусе один раз, тем самым виден — опечатка в имени репозитория не уходит молча;
- приставка, домом НЕ являющаяся (`kacho:internal/x`, `MOD-MF-21:internal/x`), — НАХОДКА. Иначе любой неразобранный префикс снимал бы путь с суждения, и приставка стала бы способом спрятать адрес, а не назвать дом;
- СТОРОЖА живут в гейте, а не здесь: ядро судит поданные значения, и для него всякий непустой дом чужой. Свой дом, названный чужим, ловит гейт.
ЧЕГО ЭТОТ ГЕЙТ НЕ ДЕЛАЕТ — сказано прямо ¶
Он судит СУЩЕСТВОВАНИЕ пути, а НЕ истинность числа, стоящего рядом с предикатом. Путь, приведённый к дереву, делает предикат исполнимым; сойдётся ли его вывод с числом, которое приёмка назвала, — вопрос К ЧИСЛУ, и он закрывается кругом ревью, а не этой проверкой. Граница честная и она же неприятная: живой адрес с ложным содержимым хуже мёртвого, потому что не краснеет. Держателя у второй половины сегодня НЕТ, и завести его дороже: потребовался бы прогон каждого предиката приёмки на каждом прогоне гейта.
acceptance_probe_coordinate.go — гейт: имя пробы, названное приёмкой КООРДИНАТОЙ, резолвится функцией в дереве.
Порт с монорепо (`internal/repohygiene/acceptanceprobecoordinate.go`, снят вынесением службы — `kacho#2597`). До этой правки держатель (`TestAcceptanceProbeCoordinateResolves`) не существовал ни в одном файле, а восемь живых приёмок службы (`roles-come-as-data-not-migrations.md`, `model-block-prose-has-a-home.md`, `model-generated-from-manifest.md`, `classes-form-of-role-right.md`, `retire-tenant-condition-surface.md`, `system-role-segments-resolve.md`, `module-manifest-resources-roles-deprecated.md`, `module-manifest-roles-and-seed-grants.md`) продолжали называть его своим.
Предмет ¶
Приёмка ссылается на пробу, чтобы читатель мог её открыть и прогнать. Проба переживает не всякую правку: её переименовывают, сводят с соседней, снимают вместе с предметом — и делают это в СВОЁМ изменении, которое чужой приёмки не касается. Тогда координата остаётся стоять, а функции за ней нет.
Класс — утверждение, пережившее свой предмет, и он опаснее обычной устаревшей строки: следующий идёт по названному адресу, не находит ничего и делает вывод О ДЕРЕВЕ, а не о документе.
Почему координатой считается ТОЛЬКО целый пролёт кода ¶
Имя пробы встречается в приёмке в трёх видах, и лишь один из них — координата:
`TestFoo` — КООРДИНАТА: пролёт целиком есть имя `go test -run '^TestFoo$' -count=1` — предикат: имя стоит внутри команды «проба TestFoo снята вместе с предметом» — проза разбора
Проверка по подстроке краснела бы на втором и третьем, то есть на СОБСТВЕННОМ объяснении документа. Поэтому документ читается РАЗОБРАННЫМ: огороженные блоки кода пропускаются целиком, а из строки берутся только пролёты `…`, чьё содержимое ЦЕЛИКОМ есть имя пробы.
Почему резолв по ПРЕФИКСУ, а не по равенству ¶
Корпус называет пробу двумя законными формами: полным именем и ИДЕНТИФИКАТОРОМ СЦЕНАРИЯ (`TestIAMCT112`), которым отбирают семейство — `-run '^TestIAMCT112'`. Отсюда правило: координата резолвится, если ОБЪЯВЛЕННОЕ имя начинается с неё. Направление существенно: `TestFoo‹хвост›` → `TestFoo` этим правилом не прощается — объявленное короче координаты и её префиксом не является.
НАЗВАННЫЙ ДОМ: чужой репозиторий — вне суждения, но НЕ прощён ¶
Служба вынесена из монорепо (`kacho#2598`), и приёмки уехали вместе с ней, а гейты дерева остались там, где судят своё дерево. Отсюда третья форма записи координаты:
`TestFoo` — координата ЭТОГО дерева, судится; `PRO-Robotech/kacho:TestFoo` — координата ЧУЖОГО дома; `PRO-Robotech/kacho@d941344bd9:TestFoo` — чужой дом, связанный ревизией.
Форма ВЗЯТА, а не придумана здесь: `owner/name:` у координаты ввёл `PRO-Robotech/kacho-workspace` `scripts/docs-gate/check-03-holding-claim-resolves.py` по тому же поводу — вынос службы оставил его координаты нерезолвящимися в стволе продукта. Оттуда же довод в пользу двоеточия: спутать `owner/name:путь` с git-формой `<ревизия>:<путь>` нельзя, потому что слева требуется слэш, которого у ревизии не бывает. Отличие одно и вынужденное: там дом стоит у ПУТИ, здесь — у ИМЕНИ, потому что координата ЭТОГО гейта и есть имя.
Чужой дом ВНЕ суждения по построению: ни подтвердить, ни опровергнуть объявление функции в чужом репозитории этот гейт не может — дерева рядом нет, а сеть в прогоне гейта запрещена. Доктрина в дереве уже есть и здесь не заводится второй раз: `carried_coordinate_ledger.go` §«Кросс-репо координата — вне суждения ОБОИХ сторон».
РЕЗОЛВ В НАЗВАННОМ ДОМЕ ТЕПЕРЬ ДЕЛАЕТСЯ — `probe_home.go` плюс `JudgeHomes` у вызывающего. Ядро по-прежнему судит ЗНАЧЕНИЯ и чужих деревьев не читает: оно собирает координаты чужих домов в `ForeignCoordinates`, а резолвит их тот, у кого есть корень. Ниже — прежний разбор, объясняющий, почему ветвь нельзя было завести БЕЗ производителя входа; он остаётся верным и описывает, чем производитель стал.
ПРЕЖНИЙ ОСТАТОК (закрыт `kaname#44`): резолв в названном доме здесь НЕ делался, и это остаток с предметом, а не граница по незнанию: воркспейс его умеет (опознаёт дерево идентичностью `origin`, отвечает третьей категорией, когда дерева рядом нет), но в конвейере службы чужого дерева нет НИКОГДА — ветвь была бы вечно-пустой, то есть мёртвым стражем ровно того вида, который запрещает ban #16. Заводится вместе с резолвером дома и инъекцией на двух синтетических деревьях — `kaname#44`.
«Вне суждения» отличается от «прощено» ТРЕМЯ свойствами, и все три обязательны:
- чужая координата СЧИТАЕТСЯ, а её дома ПЕЧАТАЮТСЯ переписью. Дом, стоящий в корпусе один раз, тем самым виден — опечатка в имени репозитория не уходит молча. Связанные РЕВИЗИЕЙ считаются отдельно: они не проверяемы даже там, где дерево дома есть;
- приставка, домом НЕ являющаяся (`kacho:TestFoo`, `IAM-MV-04:TestFoo`), — НАХОДКА. Без этого любой не-разобранный префикс снимал бы координату с суждения, и приставка стала бы способом спрятать адрес, а не назвать дом;
- ДВА СТОРОЖА, и живут они в гейте (`acceptance_probe_coordinate_test.go`), а не здесь, потому что им нужен дом ЭТОГО дерева — ядро судит значения, и для него всякий непустой дом чужой. Первый отвергает корпус, где ВСЕ координаты объявлены чужими: судить нечего, и «находок ноль» означало бы «ноль прочитанного». Второй ловит СВОЙ дом, названный чужим (`PRO-Robotech/kaname:TestFoo`), — иначе всякая мёртвая координата закрывается припиской своего же имени репозитория. Дом дерева выводится из `go.mod` (`OwnHomeOfTree`), а не складывается литералом.
Замер перед введением формы: пролётов вида `<что-то>:<имя-пробы>` в корпусе приёмок — НОЛЬ в обе стороны (и разобранных домом, и не разобранных), то есть правило 2 не краснеет ни на одной существующей строке.
applier_never_deletes.go — разбор пакета применителя ролей на предмет удаления строки роли (приёмка `docs/engineering/acceptance/roles-come-as-data-not-migrations.md` §3.1, держатель Г3; сценарий MOD-RD-15).
Порт с монорепо (`internal/repohygiene/applierneverdeletes.go`, снят вынесением службы — `kacho#2597`). Осталось дословно: имя функции гейта (`TestMODRD15ApplierNeverDeletesARoleRow`), сам разбор (обе оси, оба образца) и текст находки. Изменилось: пакет-цель — `internal/apps/kaname/moduleroles` (в монорепо — `services/iam/internal/apps/kaname/moduleroles`), путь-константа без префикса `services/iam/`.
Предмет ¶
Роль с выдачами удалить нельзя (`ON DELETE RESTRICT`) — применитель встал бы на первой же роли, которой кто-то пользуется. Форма отзыва роли выбрана решением: строка ПОМЕЧАЕТСЯ снятой, а не удаляется (`docs/engineering/architecture/role-withdrawal-is-a-mark.md`).
Что здесь считается находкой — ДВЕ оси, и первая сильнее ¶
- порт применителя объявляет ОДНОЗНАЧНО удаляющий глагол НАД СТРОКОЙ РОЛИ (судит имена методов интерфейса: глагол + предмет глагола);
- в пакете стоит оператор `DELETE` над таблицей ролей строковым литералом узла разбора, а не подстрокой текста.
Чего разбор НЕ видит — названо, а не спрятано ¶
Запрос, собранный из кусков в рантайме, и запрос, приехавший параметром — первое не встречается в дереве, второе ловит первая ось: чтобы позвать чужое удаление, порт обязан его объявить.
ascii_identifiers.go — шов гейта имён этого дерева к общему разбору фундамента.
Предмет ¶
Ban #17 состоит из двух половин, и в этом дереве держалась ровно одна. Объявления конвейера судит `TestDeliveryCarriesItsOwnPipeline` (`internal/supplyhygiene`). Идентификаторы Go не судил НИКТО: держателем был гейт монорепо (`PRO-Robotech/kacho:TestIdentifiersAreASCII`), а после вынесения службы (`kacho#2597`, `kacho#2598`) он судит ЧУЖОЕ дерево — его зелёный о `PRO-Robotech/kaname` не говорит ничего. Шесть вхождений в приёмках службы продолжали называть его своим держателем. Предмет закрыт задачей #41.
Разбор переехал в фундамент — копии здесь больше нет ¶
Почему имя обязано быть латинским, чем омоглиф опасен и почему это РАЗБОР, а не поиск по образцу, — сказано в github.com/PRO-Robotech/corelib/treehygiene, там же и сам разбор. Здесь это не пересказывается: два места об одном предмете расходятся молча, и цена копии измерена — разбор имён совпадал с близнецом платформы на 17 строках кода из 34 (#51, ban #20).
Что осталось СВОИМ ¶
Обход и его КОРЕНЬ: фундамент разбирает ОДИН исходник и о деревьях не высказывается — судить чужое дерево значило бы краснеть на чужом. Обход по корню модуля службы, перепись и порог беспредметности живут у гейта, `ascii_identifiers_test.go`.
Своих правил у этого файла нет, и потому он — ШОВ, а не вторая реализация: гейт и его инъекция зовут одно имя, и связь с фундаментом объявлена в одном месте. Появится у службы своя часть разбора имён — её место здесь, и менять придётся один файл, а не три.
assertion_admission_calls.go — разбор обращений к базе, разложенных по функциям (приёмка F2, сценарий F2-28).
Порт с монорепо (`internal/repohygiene/assertionadmissioncalls.go`, снят вынесением службы — `kacho#2597`). Держатель этого гейта уже цитируется ПРОД-КОММЕНТАРИЕМ в дереве службы: `internal/repo/kaname/pg/client_assertion_replay_repo.go` — «Гейт TestAssertionAdmissionIsASingleDatabaseCall стережёт это число». Осталось дословно: имя функции гейта, сам разбор и текст находки. Изменилось: путь без префикса `services/iam/`.
Предмет ¶
Число обращений к базе внутри одной функции. Допуск однократности обязан делать РОВНО ОДНО: «не предъявлялось ли уже» и «погасить» неделимы, и неделимыми их делает первичный ключ таблицы, а не аккуратность вызывающего. Пара «посмотреть — записать» проходит ВСЕ последовательные пробы: окна между чтением и записью при последовательном прогоне не существует.
Почему владелец соединения берётся из ОБЪЯВЛЕНИЯ ТИПА, а не из списка имён ¶
Разбор читает объявления структур файла и берёт в носители соединения те поля, ЧЕЙ ТИП называет драйвер базы. Переименование поля исход не меняет, чужое одноимённое поле находкой не становится.
audit_payload_pii.go — ГЕЙТ КЛАССА: нагрузка записи журнала аудита не несёт личных данных (задача `kacho#2483`).
Норма платформы названа здесь ФАКТОМ, а не ссылкой на документ: личные данные конечного пользователя — почта, телефон, предъявляемый секрет — не пишутся в след ни на успехе, ни на отказе, а корреляция ведётся по неизменяемому идентификатору.
Предмет ¶
Приёмник журнала аудита — собственный поток записей службы, и он кладёт ВСЕ поля нагрузки как есть: шага сокрытия нет ни одного. Значит всякий личный ключ, положенный в нагрузку, уезжает в поток, а срок хранения потока становится сроком хранения личных данных. Корреляция при этом личных полей НЕ требует: идентификатор субъекта (`user_id` / `resource_id`) в нагрузке уже есть, он неизменяем и остаётся правдой через год, тогда как почта и отображаемое имя изменяемы и правдой не остаются.
Почему ГЕЙТ, а не правка двух мест ¶
Правка закрывает экземпляр; класс приходит не по одному. Мест построения нагрузки в дереве три с лишним десятка, они лежат в разных пакетах, и ни одно из них не видит остальных. Автор следующего, скопировав соседнее, внесёт личный ключ незамеченным: отказа нет, красного нет, наблюдаемо это только у получателя потока.
Перечень личных ключей объявлен ЗАКРЫТЫМ СПИСКОМ, и он не выдуман ¶
Он взят у самого дерева: проба `set_blocked_test.go` уже утверждает отсутствие `email` / `display_name` / `displayName` / `external_id` в нагрузке пользовательского события — то есть решение о составе личных ключей дерево приняло раньше этого гейта, а гейт распространяет его с одного события на все. Сверх того перечень несёт ключи-секреты: та же нагрузка объявляет о себе «No secrets in payload», и это утверждение до сих пор держалось комментарием.
`external_id` попадает в перечень СОЗНАТЕЛЬНО, и это расходится с нормой платформы, называющей его не-личным идентификатором корреляции для журнала процесса. Расхождение разрешается ЕДИНИЦЕЙ НОСИТЕЛЯ: та норма — о СТРОКЕ ЖУРНАЛА процесса, которую читает оператор и которая живёт до ротации; здесь — о ЗАПИСИ ПОТОКА АУДИТА, которая живёт срок хранения потока и уезжает к внешнему получателю. Для второго носителя дерево выбрало строже, и выбрало до нас.
Чего перечень НЕ содержит и почему ¶
Ключа `name` в нём нет, хотя проба пользовательского события требует его отсутствия. Причина — предмет: в нагрузке роли, группы и реестра `name` есть имя РЕСУРСА, а не человека, и оно там законно (пять мест дерева). Запрет по имени ключа, верный для одного вида события и неверный для пяти, гейтом дерева быть не может; держит его проба СВОЕГО события, где известно, чьё это имя.
Формы построения нагрузки — перечислены ВСЕ, и каждая доказана ¶
Распознаватель, не знающий одной из форм, не даёт ни красного, ни зелёного — он МОЛЧИТ, и записанное в этой форме оказывается вне наблюдения, оставаясь на вид покрытым. Формы поэтому измерены по дереву, а не придуманы:
FormFieldLiteral `Payload: map[string]any{…}` — литерал прямо в поле;
FormHelperDecl `func …Payload(…) map[string]any { … }` — построитель,
чьи ключи живут у ОБЪЯВЛЕНИЯ, а не у вызова;
FormIndexAssign `p["ключ"] = …` — ключ, добавленный ПОСЛЕ литерала;
литеральный разбор без него теряет условные ключи;
FormFieldIdent `Payload: p`, где `p` собран выше в той же функции.
Поле `EventPayload` формой НЕ является и в счёт не идёт: это уже сериализованные байты у писателя, а не место построения. Разбор, судящий по подстроке `Payload:`, принял бы его за пятую форму — и судил бы место, где ключей нет вовсе.
Значение поля `Payload`, не сводящееся ни к одной форме, разбор объявляет НЕПРОЗРАЧНЫМ и печатает числом. Ноль непрозрачных — вердикт обхода, а не свойство записи: пока их ноль, «личных ключей нет» сказано обо всех местах.
Чем держится способность упасть ¶
`audit_payload_pii_injection_test.go` — инъекция в обе стороны по КАЖДОЙ форме и по КАЖДОМУ объявленному ключу: дефект находится с координатой, законный близнец (тот же ключ в НЕ-нагрузочном литерале, идентификатор вместо личного поля) молчит.
authz_wrapper_outcome_lanes.go — булева ОБЁРТКА вопроса о правах не вызывается там, где у неё есть парная форма с исходом (задача #1045).
Порт с монорепо (`internal/repohygiene/authzwrapperoutcomelanes_test.go`, снят вынесением службы — `kacho#2597`). В кaname живёт как минимум одна такая пара: `authzguard.SubjectIsClusterAdmin` (bool) рядом с `SubjectIsClusterAdminE`/`SubjectIsClusterAdminPlainE` (bool, error) — то есть предмет ЖИВ, и гейт переносится. Изменилось: перечень «прод-корней» и путь модуля читаются из СВОЕГО дерева, а не из монорепо; имя гейта сохранено дословно.
Что ищется — СВОЙСТВО, и оно ВЫВОДИТСЯ ИЗ ДЕРЕВА ¶
Перечня имён у этого гейта нет и быть не может: пары выводятся —
F — экспортированная функция пакета, возвращающая РОВНО `bool`;
FE — функция ТОГО ЖЕ пакета с именем `F`+`E` либо `F`+`PlainE`,
возвращающая `(bool, error)`.
Есть пара ⇒ автор пакета УЖЕ объявил, что у этого вопроса три исхода, а не два. Значит вызов булевой половины из ЧУЖОГО пакета — выбор, а не необходимость, и выбран он в пользу формы, из которой «хранилище не ответило» достать нельзя.
Граница названа честно ¶
Вызовы ВНУТРИ пакета, объявившего пару, под гейт не подпадают: там булева половина и есть тело обёртки. Узнавание идёт по ИМЕНИ ИМПОРТА файла, а не по типам.
basic_credential_proof_run.go — доказательство формы базового удостоверения обязано ПРОИЗВОДИТЬСЯ ПРОГОНОМ, а не просто лежать в дереве (`PRO-Robotech/kacho#1253`).
Порт с монорепо (`internal/repohygiene/basiccredentialproofrun_test.go`, снят вынесением службы — `kacho#2597`). Осталось дословно: имя функции гейта, сам разбор `run:`-тел workflow и текст находки. Изменилось: пути без префикса `services/iam/`, конвейер — `.github/workflows/` СВОЕГО репозитория.
Предмет ¶
Во всём сквозном прогоне не было НИ ОДНОГО зелёного утверждения, читающего секрет базового удостоверения из УСПЕШНОГО ответа. Проверка, которую никто не зовёт, ничего не производит: её зелёное существует только в чужой голове.
Читается ИСПОЛНЯЕМАЯ часть, а не текст ¶
YAML разбирается, берутся тела `run:`, и из них выбрасываются строки оболочечных комментариев. Гейт по подстроке краснел бы на собственном объяснении и зеленел бы на шаге, откуда вызов сняли, а комментарий оставили.
build_stamp_word.go — разбор объявления строковой константы синтаксическим деревом, а не текстом.
Предмет ¶
Слово «сборка штамп не проставила» стоит в прозе (шапках, документации) не реже, чем в объявлении. Поиск по подстроке нашёл бы собственное объяснение и остался бы зелёным при разошедшихся объявлениях — узел объявления константы судится вместо строки файла ровно по этой причине.
carried_coordinate_ledger.go — разбор ведомости координат, переносимых до снятия внешнего провайдера аутентификации клиента (приёмка F2, сценарий F2-46, §9.4).
Порт с монорепо (`internal/repohygiene/carriedcoordinateledger.go`, снят вынесением службы — `kacho#2597`). Осталось дословно: имя функции гейта (`TestCarriedCoordinateLedgerExpiresOnItsOwn`), сам разбор и словарь исходов. Изменилось: путь ведомости без префикса `services/iam/` (`docs/engineering/architecture/client-assertion-carried-over-coordinates.md`) и область зеркальной колонки — раньше сужалась до `services/iam/` внутри монорепо, теперь это ВЕСЬ репозиторий службы (у неё нет больше соседей по дереву). Ведомость службы, будучи скопирована целиком, несла координаты со старым префиксом `services/iam/` — они не резолвились НИ ОДНА (кросс-репо staleness, а не намеренное послабление); исправлено тем же изменением, которым перенесён гейт.
Предмет ¶
Фаза F2 завела принимающую сторону и ничего не сносит. У каждой координаты, дожившей до снятия внешнего провайдера, обязан быть назван исход из закрытого словаря; четвёртого — «осталось как есть, потому что не заметили» — не существует. У исхода «оставлено» обязан быть ПРЕДИКАТ СНЯТИЯ.
Гейт двусторонний ¶
- ПОЛНОТА: координата, живущая в дереве и не названная ведомостью, — находка;
- САМОИСТЕЧЕНИЕ: запись, чьей координаты в дереве больше нет, — находка.
Кросс-репо координата — вне суждения ОБОИХ сторон ¶
Ведомость несёт координаты не только своего репозитория (напр. `services/registry/...` — сервис реестра остался в монорепо продукта, а не уехал со службой доступа). Такую координату этот гейт не проверяет НИ ПОЛНОТОЙ, ни САМОИСТЕЧЕНИЕМ: он не может ни подтвердить, ни опровергнуть существование файла в ЧУЖОМ репозитории. «В скоупе» решает первый сегмент пути — совпадает с одним из ФАКТИЧЕСКИ отслеживаемых верхних каталогов своего дерева.
catalog_check_wiring.go — сверка каталога прав с копией края обязана быть ЗВАНОЙ конвейером, а не просто существующей целью Makefile.
ПРЕДМЕТ У ГЕЙТА ФОРМА-ПРОВЕРКА, А НЕ ФОРМА-СИНХРОНИЗАЦИЯ (kaname#15) ¶
Портированная редакция требовала вызова `sync-permission-catalog` — и была НЕИСПОЛНИМА by construction: эта цель ПИШЕТ файл. Задание, правящее дерево, вердикта о дереве не даёт: «копии совпали» после собственного `cp` истинно всегда, а рабочая копия ранера уезжает от коммита. Поэтому решение записано в самом рецепте, а гейт судит его: конвейер зовёт `check-permission-catalog` (ничего не пишет, годна обеим посадкам) и НЕ зовёт пишущую форму, которая объявлена ручной операцией выпуска.
Отсюда и переименование пробы: портированное имя было `TestCatalogSyncTargetIsCalledByThePipeline`, и после смены предмета оно утверждало бы неверное — цель синхронизации конвейером не звана НАМЕРЕННО.
Вторая половина того же решения — ОТКУДА БЕРЁТСЯ КОПИЯ КРАЯ. Замер, которого у портированной редакции не было: копия края приезжает в самостоятельный клон МОДУЛЕМ-ПИНОМ платформы (`go.mod`), поэтому сверка исполнима и здесь, а не только в полном чекауте монорепо. Предикат и его граница — в рецепте, у самой цели.
Порт с монорепо (`internal/repohygiene/catalogcheckwiring_test.go`, снят вынесением службы — `kacho#2597` с заявлением «предмет уехал вместе со службой»). Заявление НЕВЕРНО для kaname: своя половина цепочки уехала СЮДА — цель `sync-permission-catalog` объявлена в корневом Makefile службы (`GATEWAY_CATALOG`/`IAM_CATALOG_EMBED`), и её собственный комментарий говорит: «Копия каталога у iam ОБЯЗАНА побайтово совпадать с копией шлюза». Предмет, которым монорепошный гейт стерёг ПРОВЯЗКУ, здесь тот же самый, только половина цепочки живёт по обе стороны границы репозитория.
Здесь СУЖЕННАЯ форма монорепошного гейта: он спрашивал достижимость через ОБЩИЙ анализатор рецептов Makefile (`gatetargetwiring.go`, там же судят гейты `services/*`), которого в этом репозитории нет и заводить его ради двух целей с нулём зависимых — избыточно (ни у `check-permission-catalog`, ни у `sync-permission-catalog` сегодня НЕТ ни одной цели-потребителя внутри Makefile: обе стоят сами по себе, реаситься до них нечему). Поэтому проверяется прямая достижимость: зовёт ли ХОТЬ ОДИН шаг конвейера имя цели напрямую (`make check-permission-catalog` либо `make -C … <цель>`). Появится цель-потребитель — предикат обязан расшириться до реситься-графа, как в монорепо; это отдельное изменение, а не молчаливое сужение.
Чем этот гейт НЕ является ¶
Он не сверяет копии побайтово — это отдельный предмет, и живёт он внутри рецепта `check-permission-catalog`. Предмет ЭТОГО гейта — ПРОВЯЗКА: существует ли у сверки вызывающий среди того, что исполняется САМО, и не зовёт ли конвейер пишущую форму вместо неё.
catalog_writer_lock.go — всякий прод-писатель строк `kaname.catalog_*` берёт глобальный транзакционный замок каталога (приёмка `docs/engineering/acceptance/plan-confirms-what-apply-withdraws.md` §7, объём О11, держатель Г1; kacho#1034).
Порт с монорепо (`internal/repohygiene/catalogwriterlock.go`, снят вынесением службы — `kacho#2597` с заявлением «обход служб жив, но исполняемых операторов записи в этот каталог ноль». Заявление было верно ТОЛЬКО для монорепо (там дерево служб доступа исчезло) — приёмка сама называет отсутствие держателя пунктом Н5 и требует его. Механизм в дереве службы ЖИВ дословно: `internal/repo/kaname/pg/catalog_writer.go` несёт `CatalogLockKey`/`LockCatalog` (`pg_advisory_xact_lock`) и три `UpsertModule`/`UpsertResource`/`UpsertVerb` на том же получателе (`catalogWriter`) — единица суждения по-прежнему сходится. Осталось дословно: весь алгоритм (регулярки, разбор, единица суждения, тексты находок). Изменилось: путь-константа без префикса `services/iam/`, обход — от корня СВОЕГО репозитория целиком (предмет запрета — «ВСЯКИЙ прод-писатель», не только сегодняшний).
Предмет ¶
Подтверждение применения (отпечаток состояния модуля) есть CAS ТОЛЬКО потому, что между чтением отпечатка и записью строк не может встать второй писатель. Обеспечивает это не сравнение, а `pg_advisory_xact_lock`, взятый В ТЕЛЕ КАКОГО-ЛИБО МЕТОДА писателя (гейт не проверяет порядок — это держит интеграционная проба, не разбор).
Единица суждения — ТИП (получатель метода), а не файл и не пакет-вызывающий ¶
Замок и запись могут лежать в РАЗНЫХ методах ОДНОГО получателя в ОДНОМ пакете (как здесь: `LockCatalog` и `UpsertModule` — оба методы `catalogWriter` в `internal/repo/kaname/pg`) — тогда они СХОДЯТСЯ в одну единицу суждения и гейт молчит. Замок, взятый ЧУЖИМ пакетом (например, вызывающим use-case, держащим порт `CatalogWriter`), этот гейт НЕ видит — он не о том, кто ЗОВЁТ замок, а о том, что писатель СПОСОБЕН его взять (несёт метод, который это делает).
census_fixture_producer.go — проба, которая пересчитывает ВСЕ строки таблицы, не вправе наполнять её сама в обход производителя.
Порт с монорепо (`internal/repohygiene/censusfixtureproducer_test.go`, снят вынесением службы — `kacho#2597`). Гейт уже цитируется ШЕСТЬЮ местами в дереве службы (прод-код `internal/repo/kaname/pg/scalegrid/{census,seed}.go` и пробы `relverdict`/`parentedge`) как «гейт дерева `TestCensusFixturesSeedThroughTheProducer`» — предмет жив, и цитаты уже ждут держателя. Осталось дословно: имя функции гейта, разбор и текст находки. Изменилось: пакет-производитель узнаётся ОДНОЙ величиной (каталог = хвост импорта: у самостоятельного модуля службы расхождения, из-за которого монорепо держало ДВЕ константы, больше нет), обход — от корня СВОЕГО модуля, без сегмента `services/iam`.
Предмет ¶
Утверждение вида «у каждой строки зеркала есть цепь предков» — квантор по всему множеству. Если множество наполнила сама проба прямой записью в таблицу, утверждается свойство ФИКСТУРЫ: она положила ровно то, что потом пересчитала. Такая проба остаётся зелёной, даже если производитель перестал писать цепь ЦЕЛИКОМ.
Единица суждения — ПАКЕТ, а не файл ¶
В Go все `_test.go` каталога с одним именем пакета собираются в один бинарь и делят помощников. Проба, сеющая через помощника из соседнего файла, сеет через производителя ровно так же.
Разбор идёт по СТРОКОВЫМ ЛИТЕРАЛАМ, а не по тексту файла ¶
Текстовый поиск нашёл бы обе примеет и в комментарии, объясняющем эту же дисциплину (в том числе в шапке самой пробы полноты).
client_expiry_immutable.go — разбор операторов правки, разложенных по столбцам (приёмка F2, §9.4, решение §2.10).
Порт с монорепо (`internal/repohygiene/clientexpiryimmutable.go`, снят вынесением службы — `kacho#2597` с заявлением «снято вместе с предметом: таблицы user_oauth_clients в применённых миграциях дерева нет». Заявление было верно ТОЛЬКО для монорепо (там дерево служб доступа исчезло целиком) — в дереве службы обе таблицы объявлены (сегодня — в консолидированной `internal/migrations/0001_initial.sql`), с колонкой `expires_at`. Осталось дословно: имя функции гейта, сам разбор и текст находки. Изменилось: пути без префикса `services/iam/`.
Предмет ¶
Срок клиента неизменяем после создания. На этой предпосылке стоит структурная гарантия: срок выданного токена не превышает остатка срока клиента, и проверять это на пути запроса не нужно ровно потому, что срок не двигается. Сдвинь его — и гарантия держится ничем.
Что здесь считается ПРАВКОЙ СТОЛБЦА ¶
UPDATE t SET expires_at = $2 WHERE id = $1 ← правка: столбец назван в SET INSERT INTO t (…, expires_at) VALUES (…) ← СОЗДАНИЕ: срок назначается SELECT expires_at FROM t WHERE id = $1 ← чтение
Чего разбор НЕ видит — названо, а не спрятано ¶
- оператор, собранный из частей во время выполнения;
- правка через функцию базы или триггер, а не оператором `UPDATE`;
- `UPDATE` без имени таблицы в том же литерале.
client_truth_exclusion_form.go — извлечение для гейта «форма взаимоисключения, НАЗВАННАЯ оператору, есть та, которой оно держится» (задача #17, порт-ПОЛОВИНА семейства `clienttruth_kaname_exclusion_form` с монорепо `internal/repohygiene/clienttruth_kaname_exclusion_form.go`, снятого выносом службы — `kacho#2597`).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Назваться на публичном слушателе Kaname можно двумя способами: предъявить удостоверение самому либо получить личность от нашего края. Способы взаимоисключающи, и держится это ПОСТРОЕНИЕМ, а не проверкой.
Держалось оно не всегда так. Прежняя редакция требовала ОТВЕРГАТЬ запрос, несущий обе формы, — и эта проверка отвергала бы каждый запрос, проксированный нашим же краем, потому что сочетание производил он сам. Ветвь отказа снята вместе со своим предметом; страница оператора об этом узнать не могла — она не собирается и ничего не импортирует.
───────────────────────────────────────────────────────────────────────────── ДВА УТВЕРЖДЕНИЯ, И ВТОРОЕ ПОЛОЖИТЕЛЬНОЕ
A. отказ, ОБЕЩАННЫЙ страницей, обязан иметь производителя в не-тестовом коде читателя. Обещание без производителя — утверждение, пережившее свой предмет: оператор ждёт отказа, которого служба не делает; B. пока построение живо, страница обязана НАЗЫВАТЬ его.
Второе — положительное, и это не стилистика. Отрицание («страница не говорит такого-то слова») ЗАМОЛКАЕТ при первой же переформулировке: вход, на котором оно находит нарушение, перестаёт быть представимым, а ветвь остаётся в коде и вердикт остаётся зелёным — а отличить это от исправной работы нельзя ничем, потому что обе стороны печатают ноль находок. Утверждение B умолкнуть не может: оно краснеет ровно тогда, когда объяснение исчезает.
───────────────────────────────────────────────────────────────────────────── ЧТО РАЗРЕЗ СДЕЛАЛ С УТВЕРЖДЕНИЕМ B — И ПОЧЕМУ ЭТО НЕ ОСЛАБЛЕНИЕ
Взаимоисключение держат ДВА построения, по одному на сторону провода, и разрез развёл их по репозиториям:
СНЯТИЕ у края — край снимает арендаторское удостоверение перед пересылкой
за себя. Замер этого дерева: `git ls-files gateway | wc -l`
→ 0; `git grep -l StripPresentedCredential` → 0. Живёт в
`PRO-Robotech/kacho`.
ОБЁРТКА у нас — читатель предъявленного удостоверения НАКРЫВАЕТ пару
звеньев переданной личности и решает по её вердикту, а не
становится с ней в цепочку. Живёт ЗДЕСЬ.
Предок брал премисой первое, потому что оба лежали в одном дереве. Здесь премисой берётся ВТОРОЕ — наша половина построения, и она судится тем же разбором, что и всё остальное.
Это НЕ ослабление предмета, а смена ОПЕРАНДА ПРЕМИСЫ: утверждение B осталось прежним («построение живо ⇒ страница его называет»), сменилось то, чем доказывается «живо». Судить снятие у края отсюда было бы можно только чтением чужого репозитория с диска — тогда вердикт стал бы свойством того, что случайно лежит в кеше машины прогона, а не свойством коммита ни одного из двух деревьев.
───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ ОБЁРТКА — ИМЕННО ПОСТРОЕНИЕ, А НЕ ПРОВЯЗКА
Носитель личности платформы устроен так, что снятие имеет приоритет над любым последующим назначением. Читатель, поставленный ПОСЛЕ пары, назначил бы вызывающего, и назначение молча не доехало бы до обработчика. Поэтому читатель прогоняет пару САМ и решает по её вердикту — решение о том, КТО звонит, принимается в одном месте, и сочетания двух форм не возникает by construction.
Разомкни обёртку — и взаимоисключение перестаёт держаться построением на нашей стороне, то есть страница начинает объяснять механизм, которого нет. Ровно это утверждение B и стережёт.
───────────────────────────────────────────────────────────────────────────── РАСПОЗНАВАТЕЛИ — ЧЕМ СУДЯТ, И ПОЧЕМУ НЕ ПОДСТРОКОЙ ПО ФАЙЛУ
Сторона ДЕРЕВА судится РАЗБОРОМ, а не текстом, и это несущее: файл читателя несёт НАДГРОБИЕ снятой ветви — связный абзац по-русски о том самом сочетании форм, — и проверка по подстроке объявила бы живым ровно то, что снято: предикат, судящий СЛОВО вместо УЗЛА, находит собственное объяснение. Поэтому считаются УЗЛЫ-ВЫЗОВЫ и литеральные аргументы, а комментарии не читаются вовсе.
Сообщение отказа собирают конкатенацией (`refuse("… " + err.Error())`), поэтому разбор аргументов идёт по дереву выражения: читатель одиночного литерала такое сообщение НЕ УВИДЕЛ БЫ — то есть дал бы молчание вместо вердикта.
Сторона СТРАНИЦЫ судится по абзацу — прозы иначе не судить, и это сказано прямо, а не спрятано. Смягчает три вещи:
- корень предмета один и это ИМЯ предмета (`взаимоисключ`), а не оборот речи: переформулировать объяснение, не назвав предмета, значит перестать его объяснять, и это ловит утверждение B;
- регистр снимается. Страница пишет `ОБЕ` прописными, и предикат, читающий написанное, промолчал бы на живом производителе;
- вердикт выносится ПОАБЗАЦНО. Соседний абзац той же страницы законно говорит об отказе — о единообразии его текста, — и файл целиком читать нельзя: отказ соседа зачёлся бы обещанием предмета.
client_truth_module_set.go — извлечение для гейта «перечень модулей платформы, названный клиентской поверхностью, ПОЛОН» (задача #17, порт семейства `clienttruth_iam_moduleset` с монорепо `internal/repohygiene/clienttruth_iam_moduleset.go`, снятого выносом службы — `kacho#2597`).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ — и почему цена неполноты в БЕЗОПАСНОСТИ, а не в удобстве
Набор модулей закрыт, и его единственный источник — приставки ключей закрытой таблицы типов объекта (`objectTypes` пакета `internal/authzmap`). Модуль — то, чем клиент выражает грант (`Rule.module`).
Перечень, назвавший МЕНЬШЕ, чем принимает сервер, читается клиентом как «тонко выдать доступ к недостающему домену НЕЛЬЗЯ», а единственный документированный выход при таком чтении — системная роль на весь уровень, то есть заведомое расширение доступа. Клиент платит доступом за нашу опечатку в прозе.
Замер, на котором семейство заведено (kacho#1627): сервер принимал ШЕСТЬ модулей, а называли ЧЕТЫРЕ и справочная страница ролей, и комментарий поля контракта; шапка функции членства рядом называла ПЯТЬ. Разошлись не документ с кодом, а ТРИ места об одном предмете, из которых верно было ни одно.
───────────────────────────────────────────────────────────────────────────── ЧТО ИЗМЕНИЛ ПЕРЕЕЗД, А ЧТО НЕТ
Предмет НЕ изменился. Изменились координаты: приставка `services/iam/` ушла вместе с монорепо, поверхности стали `docs/content` и `proto/kaname/cloud/iam` (копия контракта приехала сюда с `kaname#49`), объявление набора — `internal/authzmap`. ОБА операнда лежат в этом дереве, поэтому семейство судится здесь целиком, а не половиной.
Прежняя посылка задачи #17 называла семейство кросс-репозиторным. Она опровергнута замером операндов: пакет объявления — 61 файл, поверхности — 68.
───────────────────────────────────────────────────────────────────────────── НАБОР ВЫВОДИТСЯ РАЗБОРОМ, А НЕ ЧТЕНИЕМ ТЕКСТА
Считаются узлы-ключи составного литерала. Имена модулей стоят и в комментариях рядом с объявлением — и в том самом абзаце, который объясняет выбор написания ключа, — поэтому предикат по подстроке краснел бы на собственном объяснении таблицы: судящий СЛОВО вместо УЗЛА находит сам себя.
Объявление разрешается по ПАКЕТУ, а не по файлу. В монорепо оно переезжало между файлами дважды (`fga_types.go` → `tables_gen.go`), и оба раза привязка к имени файла давала не находку, а «анализатор не отработал» — третью категорию, поданную как красное. Пакет и есть единица области видимости Go: package-level имя в нём ровно одно by construction, и перенос между файлами о нём ничего не меняет.
Приставка берётся до ПЕРВОЙ точки — то же разбиение, каким его делает `authzmap.SplitObjectType`. Ключ без точки модуля НЕ ДАЁТ и себя целиком не отдаёт: он не «модуль без ресурса», а ключ неверной формы, и записать его в набор значило бы объявить модулем то, чем таблица его не называет.
───────────────────────────────────────────────────────────────────────────── ЧТО СЧИТАЕТСЯ ПЕРЕЧНЕМ — И ЧЕГО ГЕЙТ НЕ СУДИТ, НАЗВАНО ЧИСЛОМ
Перечень — имена модулей в КОД-ФОРМАТИРОВАНИИ (`имя` либо <code>имя</code>), соединённые косой чертой, ТРИ и более подряд. Каждый такой перечень обязан назвать набор целиком.
- СПАН ИЗ ДВУХ ИМЁН перечнем не считается — это законная пара («`vpc`/`compute` остаются label-selectable»). Порог в три оставлен потому, что гейт, у которого находки ложные, отключают первым. Сколько таких пар встречено — печатает перепись, а не утверждает эта шапка: прежняя редакция абзаца в монорепо называла четыре, и гейт опроверг её на первом же прогоне. Способность молчать на паре доказана инъекцией.
- ПРОЗА без код-форматирования не судится: «модули iam, vpc и compute» распознавателю не видны. Расширение на голый текст не замерялось и потому не вводится — оно находило бы имена модулей в любом предложении, где они соседствуют законно.
- ПОРЯДОК не судится — только состав.
contract_names_live_machinery.go — МАШИНЕРИЯ, НАЗВАННАЯ КОММЕНТАРИЕМ КОНТРАКТА, ОБЯЗАНА СУЩЕСТВОВАТЬ В ДЕРЕВЕ.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Комментарий публичного контракта читает ИНТЕГРАТОР — у него нет ни нашей истории, ни возможности перемерить. Обещание механизма, снятого миграцией, для него неотличимо от действующего.
Класс тот же, что у поля запроса, которое принимают и не читают: возможность ОБЪЯВЛЕНА, и за неё никто не отвечает. Исходов у него три — реализовать · отвергать явно · снять с контракта; «оставить как есть» исходом не является, потому что вызывающий узнаёт о несделанном только по последствиям и только в своей отладке.
Наблюдалось (kacho#2486): `rpc ForceLogout` обещал строку в очереди федеративного уведомления и рассылку по каналу, обновляющую кэш отзыва на крае. Очередь снята миграцией, канал снят вместе со своим триггером, а рядом стояла ссылка на файл контракта, которого в модуле нет. Три утверждения пережили свой предмет и продолжали читаться как действующие.
───────────────────────────────────────────────────────────────────────────── СУЖЕНИЕ ИДЁТ ПО МАРКЕРУ, КОТОРЫЙ СТАВИТ САМ КОММЕНТАРИЙ
Голый предикат «слово в обратных кавычках обязано резолвиться» негоден, и это ИЗМЕРЕНО, а не предположено: на дереве службы он даёт 239 токенов, из которых 159 не резолвятся ни в таблицу, ни в канал, ни в колонку — 66 % ложных находок. Предикат с такой долей не читают, а гейт, который не читают, не держит ничего.
Поэтому заявлением считается не токен, а токен ВМЕСТЕ С МАРКЕРОМ, который комментарий ставит сам:
`<имя>_outbox` суффикс очереди — заявлена ТАБЛИЦА `<имя>` table слово сразу после — заявлена ТАБЛИЦА `<имя>` channel слово сразу после — заявлен КАНАЛ NOTIFY … on `<имя>` оборот перед — заявлен КАНАЛ
Замер того же дерева этим предикатом ДО правки: заявлений 9, резолвятся 6 (`audit_outbox`, `fga_outbox`, `session_revocations`), не резолвятся 3 — ровно те три, ради которых гейт заведён. Ложных находок ноль.
ПОСЛЕ правки заявлений о ТАБЛИЦЕ десять и все резолвятся, а заявлений о КАНАЛЕ НОЛЬ: оба, что были, называли снятый канал и сняты вместе с ним. Ноль здесь не прячется — перепись печатает виды РАЗДЕЛЬНО, поэтому «про каналы никто не писал» отличимо от «про каналы не спрашивали». Предмет у этой ветви производим в любой момент: она оживёт от первой же строки, назвавшей канал.
───────────────────────────────────────────────────────────────────────────── ЧТО СЧИТАЕТСЯ ИСТИНОЙ
Схему называет ПРИМЕНЁННОЕ дерево миграций, а не намерение: таблицы — `CREATE TABLE`, каналы — `pg_notify`. Обе половины читаются из одного источника, поэтому снятие механизма миграцией немедленно делает заявление о нём находкой, и держать запись ради зелёного негде.
───────────────────────────────────────────────────────────────────────────── ВТОРАЯ ОСЬ: ССЫЛКА НА СОСЕДНИЙ КОНТРАКТ
Комментарий, называющий `<имя>.proto` БЕЗ каталога, называет контракт ЭТОГО модуля — так в дереве и пишут (`internal_iam_service.proto`, `user.proto`). Такое имя обязано резолвиться.
Ссылка С КАТАЛОГОМ (`kacho/cloud/validation.proto`) под ось НЕ подпадает, и это решение, а не пропуск: у платформы свой репозиторий, её файла в этом модуле нет by construction, и утверждение о чужом дереве предикатом ЭТОГО дерева не судится. Замер: таких ссылок 2, обе законны; включив их, гейт начал бы с двух ложных находок и потребовал бы ведомости прощений — то есть исключения, выданного вперёд.
deferred_work.go — СВОЯ часть гейта отложенной работы: корень обхода и виды вычитания. Разбор общий и живёт в фундаменте.
Предмет ¶
Запреты «никакого тех-долга» и «всегда production-grade, НИКОГДА MVP» стоят в корпусе правил с самого начала. В ЭТОМ дереве их не держало ничего: держателем был гейт монорепо (`PRO-Robotech/kacho:TestNoDeferredWorkInTheTree`), а после вынесения службы (`kacho#2597`, `kacho#2598`) он судит ЧУЖОЕ дерево — его зелёный о `PRO-Robotech/kaname` не говорит ничего. Четыре приёмки службы продолжали называть его своим держателем. Предмет закрыт задачей #40.
Разбор переехал в фундамент — копии здесь больше нет ¶
Словарь форм, образец, отсев по затравке, граница употребления и упоминания, обход и перепись живут в github.com/PRO-Robotech/corelib/treehygiene и приезжают сюда ПИНОМ версии. Здесь они не пересказываются — пересказ и есть то второе место об одном предмете, ради снятия которого переезд и сделан.
Цена копии была измерена, а не предположена (#51): разбор отложенной работы совпадал с близнецом платформы на 99 строках кода из 186, разбор имён — на 17 из 34, а словарь форм совпадал по составу ТОЧНО. Совпадение содержимого нарушением не смягчалось, а доказывало его: держателя у одинаковости не было ни одного, и расхождение наступило бы молча — заведут в одном дереве тринадцатую форму, в другом её не будет, и написанное в ней окажется не находкой и не чистотой, а НЕВИДИМОСТЬЮ. Ban #20 корпуса правил говорит это прямо: файл, чей владелец — другой репозиторий, в этом дереве не лежит; нужен предмет — берут пином, не нужен — файла нет.
Что осталось СВОИМ — и почему именно это ¶
Ровно две вещи, и обе суть утверждения об ЭТОМ дереве, а не об общем разборе:
- КОРЕНЬ ОБХОДА. Его даёт гейт, и это корень МОДУЛЯ службы: судить дерево платформы отсюда значило бы краснеть на чужом, а в самостоятельном клоне его нет вовсе;
- ВИДЫ ВЫЧИТАНИЯ (treehygiene.DeferralSkip). Перечень вычитаемого есть утверждение о составе конкретного дерева, и предмет каждого вида измерен ЗДЕСЬ. Готовых видов фундамент не раздаёт намеренно: раздавая их, он утверждал бы о чужом дереве то, чего не измерял, и предикат «вид без предмета» обессмыслился бы.
Что СНЯТО вместе с переездом — и чем свойство держится теперь ¶
Прежняя редакция несла отдельный вычет имени функции стандартной библиотеки: вызова через точку, синтаксически похожего на обращение к читателю кода. Ветвь НЕ перенесена, потому что она недостижима — класс границы в самом образце фундамента уже отличает вызов через точку от обращения, и инъекция фундамента это измерила: с отключённым вычетом вердикт суиты не изменился ни на одной пробе.
Свойство при этом не потеряно и держится с ОБЕИХ сторон шва: TestDeferralGateStaysSilentOnStdlibContextTODO — здесь, на кроне этого дерева; TestDottedCallIsNotADeferral — в фундаменте, на самом образце. Ослабят класс границы — покраснеют обе.
derived_id_single_source.go — разбор объявлений деривации детерминированного идентификатора (приёмка `docs/engineering/acceptance/roles-come-as-data-not-migrations.md` §3.3; приёмка `seed-identity-names-its-own-service.md` §6, держатель `TestDeterministicIDDerivationIsDeclaredOnce`).
Предмет ¶
Идентификатор системной роли, служебной учётки модуля и связки OAuth есть функция ИМЕНИ: применённые миграции адресуют строки выражением `'<префикс>' || substr(md5('<имя>'), 1, 17)`, и на эти идентификаторы ссылаются выданные права. Вторая копия формулы разойдётся с первой МОЛЧА — и разойдётся ровно там, где обе отвечают «идентификатор вычислен»: полученное значение остаётся синтаксически верным и перестаёт находить строку. Наблюдаемо это только по отказу в доступе у арендатора, у которого право не отзывали.
Порт с монорепо (`internal/repohygiene/derivedidsinglesource.go`, снят вынесением службы — `kacho#2597`): формула не переехала с кодом целиком, а была написана заново рядом с единственным домом — `internal/domain/derived_id.go`, чей собственный комментарий уже называет этот гейт держателем и ожидает его присутствия. До этой правки объявление не охранялось ничем: единственность была фактом дня, а не удержанным свойством.
Что здесь считается ОБЪЯВЛЕНИЕМ ¶
Файл прод-дерева, импортирующий `crypto/md5`. Иных потребителей MD5 в этом продукте нет и быть не должно: как примитив защиты MD5 запрещён (сам импорт в доме несёт отметку `#nosec G501`), а как контрольная сумма он здесь не применяется — значит всякое его вычисление есть деривация идентификатора.
Распознаватель знает ВСЕ формы импорта by construction ¶
Он читает ПУТЬ импорта из разобранного дерева, а не имя пакета в тексте, поэтому псевдоним (`md5b "crypto/md5"`), точечный (`. "crypto/md5"`) и пустой (`_ "crypto/md5"`) импорты опознаются одинаково. Упоминание пути в комментарии или в строковом литерале импортом НЕ является — разбор судит узел, а не подстроку.
Чего разбор НЕ видит — названо, а не спрятано ¶
- **своя реализация MD5 руками** — развёрнутый алгоритм без импорта. Это другой класс, и ловит его обзор, а не этот гейт;
- **вычисление на стороне базы** — `md5()` в тексте миграции. Это ВТОРАЯ сторона равенства, а не вторая копия Go-функции, и этот гейт её не судит.
granted_relation_in_model.go — разбор: отношение, которое ВЫДАЁТ миграция, обязано СУЩЕСТВОВАТЬ в модели, которую применяет решение о доступе.
Предмет ¶
Выдача права живёт в двух артефактах, и они доезжают до решения РАЗНЫМИ путями: отношение объявляет модель прав, а саму выдачу пишет миграция — строкой в очередь. Если миграция называет отношение, которого в применяемой модели нет, запись отвергается со значением «такого отношения нет», дренаж верно считает такой отказ ПОСТОЯННЫМ, и строка травится: счётчик попыток выставляется в потолок, и больше её не возьмут никогда.
Что это стоит ¶
У этой очереди НЕТ переезда отравленных строк обратно в работу: разбор партиций идёт по идентификатору ресурса, которого у неё нет by construction (она партиционирована по ключу кортежа). Следствие названо честно: отравленная строка не «подождёт», а ЛЕЖИТ ДО ВМЕШАТЕЛЬСТВА ОПЕРАТОРА. Право, которое она несла, не выдаётся.
Почему разбор дерева, а не внимание ¶
Расхождение не видно НИ ОДНОЙ из двух сторон. Миграция — обычный SQL: она применяется без ошибки, потому что про модель ничего не знает. Модель — обычный DSL: он проходит проверку, потому что про миграции ничего не знает. Сборка цела, пробы обеих сторон зелёные, а право не выдано. Единственное место, где два факта встречаются, — дерево.
Чего этот разбор НЕ ловит (названо, чтобы на него не сослались шире предмета) ¶
Он про СОСТАВ, а не про ПОРЯДОК. Если отношение в модели есть, но новая её редакция ещё не применена, а дренаж уже взял строку, — пара сойдётся, разбор промолчит, а строка отравится ровно так же. Порядок двух путей доставки деревом не проверяется.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/grantedrelationinmodel_test.go` (снято вынесением службы — `kacho#2598`; предмет жив здесь, задача #17). Изменилось: координаты обоих операндов (приставки `services/iam/` в самостоятельном клоне нет), разбор вынесен из пробы в пакет `check`. Осталось дословно: имя гейта, ОБЕ формы записи кортежа и то, что применяемая модель читается ВСТРОЕННАЯ, а не каноническая.
Близнеца в платформе нет: семейство снято там вместе со службой (ban #20).
identity_growth_reader.go — разбор: у величины роста числа личностей есть ЧИТАТЕЛЬ, и он назван.
Предмет ¶
Величина, которую никто не смотрит, наблюдаемостью не является: она печатается на витрине, ничего не утверждает и создаёт уверенность, которой нет. Задача, заведшая семейство, просила именно наблюдаемость — «число личностей и скорость их появления видны, превышение порога порождает оповещение», — и ряд без правила закрывал бы её формой, а не существом.
Что считается читателем ¶
ТОЛЬКО выражение правила оповещения (`expr:`). Упоминание имени ряда в пояснении к тревоге или в таблице метрик читателем НЕ является: пояснение не срабатывает. Различие несущее — оба текста лежат в одном файле, и разбор, ищущий имя по всему документу, зеленел бы на ряде, о котором лишь написано.
Граница названа ¶
Судится ОДНО семейство, и его состав выводится из файла коллектора, а не из выписанного перечня. На прочие ряды службы разбор не распространяется, и это не оплошность: у части из них правил сегодня нет, и заведение им читателей — отдельная работа с отдельным предметом. Расширение на всё семейство метрик обязано прийти ВМЕСТЕ с этими правилами, иначе оно потребует перечня исключений — то есть заведёт ровно ту форму, в которой послабление переживает свой предмет.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/identitygrowthreader_test.go` (семейство снято вынесением службы, `kacho#2597`; предмет жив здесь — задача #17). Изменилось: координаты обоих операндов (приставки `services/iam/` в самостоятельном клоне нет), разбор вынесен из пробы в пакет `check`, приставка рядов берётся у того же имени, которым пакет уже называет свой словарь. Осталось дословно: имя гейта (`TestIdentityGrowthMetricsHaveANamedReader`), разбор выражений и граница «исполняемое против объяснения».
Близнец в платформе снят вместе с предметом — там этих рядов больше нет, поэтому пары файлов этот порт НЕ заводит.
injection_named_exists.go — разбор: доказательство способности упасть, НАЗВАННОЕ пробой, обязано существовать (#2479).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Проба, чья шапка говорит «способность упасть доказана инъекцией — такой-то файл», делает утверждение о ДЕРЕВЕ. Утверждение это не компилируется и никем не сверяется: файл переименовали, унесли вместе с рефакторингом либо не написали вовсе — а шапка продолжает обещать доказательство. Гейт, потерявший способность краснеть, на чистом дереве выглядит РОВНО ТАК ЖЕ, как исправный, поэтому обещание доказательства читается как само доказательство.
Замер, из которого разбор выведен: на ревизии заведения упоминаний в комментариях было 122, не резолвилось ОДНО — шапка гейта осей адреса называла файл, которого в дереве не было с первого её дня.
───────────────────────────────────────────────────────────────────────────── У ЭТОГО РАЗБОРА ЕСТЬ БЛИЗНЕЦ В ПЛАТФОРМЕ — И ЭТО НАЗВАНО, А НЕ УМОЛЧАНО
Тот же разбор, поднятый до корня МОНОРЕПО, живёт в `tools/injectionproofgate` (задача #2519): этот обходит корень своего модуля и о платформе не высказывается — в самостоятельном клоне службы монорепо нет вовсе. Обещания соседних модулей платформы этому модулю не принадлежат.
Свести обе реализации в одну сегодня НЕЛЬЗЯ: модуль службы пинит платформу псевдоверсией, поэтому импортировать пакет, которого в пинованной ревизии ещё нет, он не может. Предикат сведения: пин указывает на ревизию, где тот пакет существует; до этого две реализации об одном предмете живут рядом осознанно.
───────────────────────────────────────────────────────────────────────────── СУДЯТСЯ КОММЕНТАРИИ, И ЭТО РЕШЕНИЕ, А НЕ УПРОЩЕНИЕ
Координата доказательства пишется ПРОЗОЙ — это её законное место, и разбор читает разобранные группы комментариев, а не сырой текст файла. Строковые литералы намеренно НЕ судятся: в них живут синтетические имена, которые инъекции кладут во временные каталоги, и дерева они не называют вовсе. Судить их значило бы краснеть на чужой фикстуре — то есть на собственном доказательстве.
Величина «в строках» всё равно печатается переписью: молчание о целом виде вхождений неотличимо от их отсутствия.
───────────────────────────────────────────────────────────────────────────── ЗАКОННЫХ ФОРМ КООРДИНАТЫ ТРИ, И РАСПОЗНАВАТЕЛЬ ЗНАЕТ ВСЕ ТРИ
Форма, о которой он не знает, даёт не красное и не зелёное, а МОЛЧАНИЕ. Измерено на этом дереве: наивный резолвер («имя рядом с называющим») дал 4 непопадания из 138, и все четыре оказались ЗАКОННЫМИ формами, а не находками.
СОСЕД `<имя>_injection_test.go` — файл в каталоге называющего;
ПО МОДУЛЮ то же имя, но доказательство лежит в ДРУГОМ пакете модуля
(проба одного пакета ссылается на инъекцию соседнего);
КООРДИНАТОЙ `internal/<пакет>/<имя>_injection_test.go` — путь от корня
МОДУЛЯ службы, а не от корня монорепо: в самостоятельном клоне
приставки `services/iam/` нет, и счёт от неё указывал бы наружу
дерева.
Имя в примерах — ОБРАЗЕЦ с угловыми скобками, а не координата, и это не подгонка текста под инструмент: координата, названная в прозе, есть утверждение о дереве, и выдуманная — ложное. Разбор судит объявленные координаты, поэтому пример обязан не выглядеть ею.
job_knob_has_a_reader.go — разбор: у КАЖДОЙ величины секции фоновых заданий есть читатель вне пакета настроек (задача #2647).
Предмет ¶
Ручка настроек, которую принимают, валидируют и не читают, — это «принято-и-проигнорировано» на уровне НАСТРОЙКИ, и там оно тише, чем в поле запроса. Оператор, выставивший величину, получает УСПЕХ: значение принято, провалидировано, отказа нет. Он уверен, что изменил поведение. Поведение осталось прежним.
Три обстоятельства делают это неотличимым от исправной работы, и все три наблюдались вместе на `jobs.catalog-snapshot.refresh-interval`:
- величина объявлена ДВАЖДЫ — секцией настроек и ручкой окружения в композиционном корне, — а петлю ведёт одна;
- умолчания РАСХОДЯТСЯ (минута против пятнадцати секунд), то есть даже незаданная ручка описывает поведение неверно вчетверо;
- страж старта у поля ЕСТЬ и отвергает непозитивное — и тем создаёт вид живого механизма: «ручка работает».
Наблюдаемого отличия нет ни одного: снимок обновляется, просто не с тем периодом. Заметить можно только замером окна отставания.
Что считается ЧИТАТЕЛЕМ, и почему собственная валидация им не является ¶
Читателем считается обращение к полю в композиционном корне — там, где величина попадает в механизм. Метод `Validate` самой секции читателем НЕ является by construction: он живёт в пакете настроек, и его вызов доказывает ровно то, что величину проверили, — а не то, что ею кто-то пользуется. Именно поэтому предикат задачи звучал «читатель ВНЕ собственной валидации»: у поля без механизма читателей было два, и оба — его собственная проверка.
Почему разбор УЗЛОВ, а не поиск имени ¶
Имя поля (`Interval`, `Enabled`, `Grace`) — из самых частых в дереве, и поиск по нему засчитал бы читателем одноимённое поле ЧУЖОЙ структуры, комментарий и строку журнала. Поэтому читатель опознаётся цепочкой узлов: обращение к полю через `…Jobs.<секция>` либо через ПСЕВДОНИМ, связанный с этой цепочкой (`c := cfg.Jobs.ExpiredCredentialReclaim`, дальше `c.Interval`) — ровно та форма, которой пользуется корень.
Граница названа: секция, переданная ЦЕЛИКОМ ¶
Секция, ушедшая в вызов целиком (`f(cfg.Jobs.X)`), пофайлово не разбирается: о её полях этот гейт не утверждает ничего. Такие секции НЕ прощаются молча — они печатаются переписью отдельной величиной, потому что «поле прочитано» и «секция уехала целиком, а поле, может, и не прочитано» — разные вердикты, и второй обязан быть видим.
judge_target_wiring.go — разбор: у ЕДИНСТВЕННОГО судьи оси обязан быть вызывающий среди того, что исполняется само.
Предмет ¶
Часть осей этого дерева судит ровно один исполнитель, поднимаемый целью рецепта: форму манифеста модуля — загрузчик `internal/manifest` (цель `module-manifest-check`), сходимость блоков модели доступов с манифестами — `tools/model-canon-check.sh` (цель `model-canon-check`). Единственность судьи назначена намеренно, и второго заводить нельзя: две копии одного суждения расходятся молча и расходятся там, где обе зелены.
У единственности есть цена. Если у такого судьи нет ВЫЗЫВАЮЩЕГО, то ось, которую судит только он, не встречает НИ ОДНОЙ автоматической проверки — и молчание неотличимо от исправной работы. Это вторая половина класса «проверка с формой, но без содержания»: страж, который ничего не проверяет, и страж, которого никто не зовёт. Здесь — вторая.
Чем этот разбор НЕ является ¶
Он не судит форму манифеста и не сверяет блоки модели: второй судья тех же осей запрещён. Его предмет — ПРОВЯЗКА.
Почему разобранный YAML, а не текст ¶
Имя цели встречается в носителях чаще, чем её вызов: в заголовке шага, в условии, в комментарии, который эту же провязку объясняет. Поиск подстрокой зеленел бы на собственном объяснении и оставался бы зелёным при СНЯТОЙ провязке. Поэтому вызов ищется в теле `run:` разобранного задания, а комментарии из тела снимаются (`ExecutableRunBodies`), и форма вызова требуется исполняемая (`CallsMakeTarget`).
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/gatetargetwiring.go` вместе с двумя его семействами (`modulemanifestcheckwiring`, `modelcanoncheckwiring`; сняты вынесением службы — `kacho#2598`, предмет жив здесь, задача #17). Изменилось: операндов у обхода не «Makefile каждого сервиса», а ОДИН корневой рецепт — у самостоятельного модуля сервисных подкаталогов нет by construction; носителей провязки тоже один род (задания конвейера), потому что локального прогонщика `scripts/ci-local.sh` в этом дереве не существует. Примитивы разбора не копируются: они уже живут в пакете (`MakefileDeclaresTarget`, `ExecutableRunBodies`, `CallsMakeTarget`) и приехали сюда портом гейта сверки каталога прав.
Близнеца в платформе у этого разбора нет: оба семейства сняты там вместе со службой, поэтому пары файлов порт НЕ заводит (ban #20).
key_algorithm_dictionary.go — разбор словаря зарегистрированного алгоритма в СХЕМЕ.
Предмет ¶
Словарь алгоритмов ключа объявлен дважды: ограничением схемы и закрытым перечнем кода. Совпадение двух объявлений держится ГЕЙТОМ, а не совпадением формулировок: разойдясь, они дают либо строку, которую схема примет, а проверяющий не признает, либо алгоритм, который проверяющий считает допустимым, а вставить его нельзя.
Пустое значение — ЗАКОННЫЙ вход, и означает оно «ключа нет» ¶
Ограничение допускает пустую строку, и это не расхождение с кодом: пустое значение означает «ключа нет», а не «любой алгоритм». Клиент с пустым зарегистрированным алгоритмом аутентифицироваться утверждением не может — и это свойство держится проверкой на непустоту, а не словарём. Разбор поэтому выносит пустое значение отдельно, а не считает его алгоритмом.
Что здесь считается ДЕЙСТВУЮЩИМ объявлением ¶
Миграции применяются по порядку и не правятся (ban #5), поэтому действует ПОСЛЕДНЕЕ объявление ограничения с этим именем, а снятое `DROP CONSTRAINT` не действует вовсе. Разбор читает файлы в том же порядке, в котором их применяет накат.
Какие формы записи словаря разбор ЗНАЕТ ¶
Их две, и обе законны в этом дереве (предмет [dictionaryListOpensAt]):
key_algorithm IN ('', 'ES256', 'RS256', 'EdDSA') -- рука
key_algorithm = ANY (ARRAY[''::text, 'ES256'::text, 'RS256'::text]) -- снимок
Вторую производит сведённый свод миграций: свод написан инструментом, и членство он записывает только так. Разбор, знавший одну форму, не краснел и не молчал, а ОСЛЕП: находил ноль объявлений и сообщал об этом словами «столбец не сужен ничем» — утверждение о СЕБЕ, сказанное о схеме.
Чего разбор НЕ видит — названо, а не спрятано ¶
- **ограничение, наложенное функцией или триггером**, а не перечнем значений. Форма другая, и предмет у неё другой.
- **словарь, собранный из значений другой таблицы** (внешний ключ на справочник): тогда объявления в тексте миграции нет вовсе, и сверять нечего — счётчик найденных ограничений это покажет.
- **значение, собранное выражением** — конкатенация, вызов функции. Приведение типа на литерале в этот пункт НЕ входит: имя типа стоит за кавычками, поэтому значением оно не становится.
- **перечень ЗАПРЕЩЁННОГО** — не по слепоте, а по решению: гейт сверяет словарь с перечнем ДОПУСТИМОГО кода, и засчитать дополнение множества значило бы сравнить его с самим множеством.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/keyalgorithmdictionary.go` (снято вынесением службы — `kacho#2598`; предмет жив здесь, задача #17). Изменилось: накат миграции подаёт ВЫЗЫВАЮЩИЙ (та же форма, что у соседа по пакету — `SQLCreateTableBody`), поэтому зависимости на пакет миграций у разбора нет; помощник чтения идентификатора переименован, чтобы не переобъявлять соседского. Осталось дословно: имя гейта, обе формы словаря и граница «пустое — не алгоритм».
Близнеца в платформе нет: семейство снято там вместе со службой (ban #20).
limit_export_procedure.go — разбор инструкций установки на предмет процедуры, которой оператор сохраняет строки таблицы ПЕРЕД её сносом (задача продукта #2134, приёмка KAN-QUOTA-1 §9 `ПР-3`, сценарий `KAN-Q4-07`).
Предмет ¶
Накат отказывает, увидев живые строки в таблице, которую снесёт ещё не применённая миграция, и называет оператору два шага: сохранить и разрешить снос. Первый — команда, и производит её РОВНО ОДНО место, `dropguard.PreserveCommand`.
Оператор читает эту команду дважды и в двух РАЗНЫХ местах: в отказе, когда накат уже встал, и в инструкции обновления, когда он к обновлению готовится. Два написания одной команды расходятся молча — и расходится то, которое НЕ исполняется, то есть документ. Поэтому документ обязан нести её ДОСЛОВНО, а не пересказом.
Оси находки — две, и они с разных сторон ¶
- **инструкция службы доступа обязана нести команду для таблицы величин.** Версия, снимающая домен величин, сносит `kaname.limits`; счёт её строк ненулевой у ЛЮБОЙ установки (цепочка сеет умолчания, администратор пишет сверх), значит отказ наступит у каждого, и процедура обязана быть записана ЗАРАНЕЕ. Ось привязана к координате намеренно: без неё «команды нет вовсе» давало бы ноль предметов, то есть зелёное на достигнутой потере;
- **всякая процедура выгрузки в любой инструкции обязана совпадать с производителем побайтово.** Ось ловит ВТОРОЕ написание — то, что заведут соседи, скопировав абзац и поправив под себя.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/limitexportprocedure.go` (семейство снято вынесением службы, `kacho#2597`; предмет жив здесь — задача #17: INSTALL.md службы несёт команду для `kaname.limits`). Изменилось: дом производителя (`PRO-Robotech/corelib:dropguard`, приезжает пином — своей копии порт НЕ заводит), пакет, координата инструкции (приставки `services/iam/` в самостоятельном клоне нет) и имена трёх внутренних помощников, разведённые с соседями по пакету. Осталось дословно: имя гейта, обе оси находки и разбор.
Чего разбор НЕ видит — названо, а не спрятано ¶
Команду, разорванную переносом строки: строка документа читается целиком, и перенос внутри неё разорвал бы и саму команду для того, кто её копирует. Отдельно: разбор судит ТЕКСТ инструкции, а не то, что psql её исполнит, — исполнимость против живой схемы утверждает интеграционная проба службы доступа, где база поднимается.
list_scope_double.go — разбор: пакет, чей дублёр области видимости объявляет её НЕОГРАНИЧЕННОЙ, обязан называть живого держателя настоящего отбора.
Предмет, и почему требуется именно это ¶
Снисходительность здесь НАМЕРЕННА, и её цена названа в самих пробах: строк выдачи у их фикстуры нет вовсе, поэтому назвать кандидатов она не может, а сузив набор до пустого — вернула бы пустую страницу везде и стёрла бы предмет своих же проб (вердикт: каким отношением судится строка страницы). Требовать «почините дублёров» значило бы сломать работающее.
Опасно другое. Отбор кандидатов держит РОВНО ОДИН пакет, и держит он его на настоящей базе. Выпадет он из набора — по недосмотру, из-за недоступных контейнеров, при переименовании — и свойство перестанет проверяться НИГДЕ, а ссылки на него останутся и будут читаться как покрытие. Форма остаётся, содержание исчезает молча.
Поэтому разбор требует не сужения у дублёров, а РЕЗОЛВИМОСТИ ссылки: снятие держателя роняет прогон с ЕГО ИМЕНЕМ, а не тишиной.
Почему разбор синтаксиса для одной части и комментарии для другой ¶
Снисходительность — свойство ИСПОЛНЯЕМОГО кода (значение поля в литерале области), и ищется разбором: поиск подстроки нашёл бы слово в комментарии, объясняющем эту же проверку. Ссылка на держателя — наоборот, живёт ИМЕННО в комментарии, потому что адресована читателю; её и ищем в комментариях, разобранных парсером, а не в сыром тексте файла.
ДВА написания координаты — обе законны, и разбор обязан знать обе ¶
Здесь порт расходится с монорепошным оригиналом, и расходится ЗАМЕРОМ. Там координата была одна — `services/iam/internal/apps/kaname/api/<пакет>`. Здесь в дереве живут ОБЕ формы, и обе законны: приставка `services/iam/` остаётся канонической для вызовов `platformtree` (`treeposture.PathOf` принимает координату ОТ КОРНЯ ДЕРЕВА ПЛАТФОРМЫ и снимает приставку сам, когда модуль стоит самостоятельным клоном), а без приставки пишут там, где адресуют каталог этого модуля напрямую.
Замер на дереве: строк-комментариев с приставкой — 53 в 31 файле, строк кода с ней же — 20, и КАЖДАЯ из двадцати законна by construction: это аргументы `platformtree`.
ЧТО ЭТА ОСЬ СЕГОДНЯ МЕНЯЕТ, НАЗВАНО ЧЕСТНО — вердикта она не меняет, и сказать это надо прямо, иначе следующий прочтёт её как закрытый дефект. Перемер образцом только с приставкой: пакетов 27, снисходительных 7, держателя называют те же 7, находок 0 — то есть ровно столько же. Голая форма слепой не бывает by construction (она совпадает и ВНУТРИ приставочной), а приставочная теряет сегодня лишь 4 ссылки переписи из 54.
Ось заведена не ради сегодняшнего числа, а ради ЗАВТРАШНЕГО: ссылка, написанная в голой форме в пакете, где другой ссылки нет, при однобразцовом распознавателе дала бы не красное и не зелёное, а невидимость. Перепись печатает обе величины порознь, поэтому смена соотношения будет видна числом, а не догадкой.
Граница, объявленная самим разбором ¶
Судятся только пакеты, которые снисходительного дублёра ЗАВОДЯТ. Пакет без него под разбор не подпадает — там нечему быть снисходительным. «Ноль находок» означает «у каждого снисходительного назван живой держатель», а не «снисходительных нет»: перепись печатает оба числа.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/listscopedoubleisnotlenient_test.go` (семейство снято вынесением службы — `kacho#2598`; предмет жив здесь, задача #17). Изменилось: корень обхода (приставки `services/iam/` в самостоятельном клоне нет), разбор вынесен из пробы в пакет `check`, распознаватель знает обе формы координаты. Осталось дословно: имя гейта (`TestLenientScopeDoubleNamesALiveHolder`), предмет, граница и то, что снисходительность ищется разбором, а ссылка — в комментариях.
Близнеца в платформе нет: семейство снято там вместе со службой (ban #20).
manifest_verb_class_rule.go — два распознавателя для свойств ДЕРЕВА, которых проба пакета утверждать не может.
правило «класс действия из его ИМЕНИ» объявлено в дереве РОВНО ОДИН РАЗ. Проба пакета о числе объявлений не утверждает ничего: она зелена при любом. Единственность объявления делает второе место НЕПРЕДСТАВИМЫМ, и это сильнее тождества импорта: появится генератор — импортировать ему будет нечего, кроме одной функции, by construction;
правило вывода «тип объекта из имени ресурса» СНЯТО и не возвращено тихо. Приёмка сняла его замером, и без держателя его можно вернуть молча: ключ перестал бы быть обязательным, а восстанавливающее правило поселилось бы в ДВУХ местах — в генераторе (когда опускать) и в загрузчике (как восстановить).
Как распознаётся правило «класс из имени» — и почему НЕ по набору литералов ¶
Наивный распознаватель («объявление, чей набор строковых литералов равен пяти каноническим») даёт ЛОЖНУЮ находку: рядом живёт ПОРЯДОК ПОКАЗА глаголов, набор у которого тот же, а референт другой. Гейт, краснеющий на верном коде, отключают первым.
Поэтому распознаётся ПАРА: функция, отвечающая «класс и получилось ли» (результаты `(string, bool)`), и набор ровно пяти канонических токенов, до которого она дотягивается — своим телом либо объявлением того же файла. Порядок показа под это не подпадает: его читает функция с ОДНИМ результатом.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/manifestverbclassrule_test.go` (семейство снято вынесением службы, `kacho#2597`; предмет жив здесь — задача #17). Изменилось: каталог загрузчика (приставки `services/iam/` в самостоятельном клоне нет), пакет, и вход распознавателей — исходник вместо уже разобранного узла: разбор живёт теперь в одном месте, а проба и инъекция подают ему текст. Осталось дословно: имена обоих гейтов, пара признаков и тексты находок.
migration_not_a_writer_of_module_role.go — разбор миграций и манифестов: роль модуля, у которого ЕСТЬ манифест, пишет применитель, а не миграция.
Предмет ¶
Миграция, вставившая такую роль, заводит ВТОРОГО писателя одного предмета: два места разойдутся молча — правка манифеста не доедет до строки, потому что строку держит миграция, а перепись применителя об этом ничего не скажет.
Перечень модулей с манифестом ВЫВОДИТСЯ, а ведомость НЕ заводится ¶
Ведомость «модули без манифеста» есть второе место об одном предмете, и расходится оно МОЛЧА — ровно в тот день, когда у модуля появляется или исчезает манифест. Производный перечень истекает BY CONSTRUCTION: запись исчезает вместе с появлением манифеста, и истекать вручную нечему.
Число манифестов здесь намеренно НЕ выписано вторым местом: оно растёт с каждым новым модулем и устарело бы молча. Узнаётся одной командой:
git ls-files '*manifest.yaml' | wc -l # сколько их в дереве СЕЙЧАС
Как узнаётся манифест — по СОДЕРЖИМОМУ, а не по пути ¶
Разбор, привязанный к пути, молчал бы вечно, окажись путь другим, — и его молчание было бы неотличимо от чистоты. Поэтому манифест опознаётся парой ключей верхнего уровня: объявлением версии контракта и именем модуля.
Форм записи имени роли ДВЕ, и обе законны ¶
Рукописная выводит идентификатор ИЗ имени, поэтому имя стоит аргументом деривации; снимочная подставляет уже вычисленный идентификатор и перечисляет колонки явно. Разбор, знавший одну, извлекал ноль имён при сорока восьми блоках — это не находка и не молчание, а невидимость: каждая вставленная роль оказалась вне наблюдения. Ловят это ДВЕ величины переписи: «имён извлечено» и «блоков с непрочитанным именем».
Чего разбор НЕ видит — названо ¶
- **фикстуры проб** — они объявляют чужой модуль и сделали бы его «модулем с манифестом», превратив каждую его миграцию в находку. Исключены по каталогу, и это единственное исключение;
- **манифест, приезжающий не файлом дерева** (карта настроек, том) — его в дереве нет by construction, и разбор о нём ничего не утверждает;
- **имя роли, записанное литералом идентификатора** — такие роли вне закрытого набора модулей, то есть находкой быть не могут ни при каком манифесте.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/migrationnotawriterofmodulerole.go` (снято вынесением службы — `kacho#2598`; предмет жив здесь, задача #17). Разбор перенесён БЕЗ правок логики: его операнды — текст манифеста и текст миграции, и ни один не несёт координаты дерева. Изменились только координаты в гейте рядом.
Близнеца в платформе нет: семейство снято там вместе со службой (ban #20).
mirror_catalog_condition.go — разбор: УСЛОВИЕ КАТАЛОГА НЕСЁТ КАЖДЫЙ ПИСАТЕЛЬ ЗЕРКАЛА.
Предмет ¶
Зеркало каталога ресурсов — проекция, которую владельцы присылают через проксируемую полосу регистрации. Требование «тип обязан иметь живую строку каталога» выражено ОПЕРАТОРОМ записи, а не внешним ключом: постоянное ограничение запретило бы платформе снять тип, пока у арендатора есть ресурс этого типа, то есть сделало бы решение платформы заложником данных арендатора.
Цена выбора: инвариант стал свойством ПОЛОСЫ, а не свойством ТАБЛИЦЫ. Инвариант, выраженный в одном операторе из нескольких, — это инвариант, которого нет: второй писатель обходит его молча, и обнаруживается это тогда, когда данные уже записаны. Этот разбор — второй рубеж под тем же утверждением.
Требование ВЫВОДИТСЯ из эталонной полосы, а не задаётся литералом ¶
Две копии одного условия разошлись бы молча — и разошлись бы именно там, где расхождение не видно: обе выглядели бы исправными. Поэтому условие берётся у полосы, через которую идёт регистрация от владельцев, и сверка идёт МЕЖДУ полосами. Переедет эталон — разбор объявит ОТКАЗ, а не промолчит.
Каталог берётся ИЗ ТОГО ЖЕ ЛИТЕРАЛА ¶
Обещание сверки, данное в комментарии рядом, условием не является — иначе писателю довольно было бы пообещать её словами.
Признак таблицы каталога — ПРЕФИКС, а не перечень ¶
Каталог растёт, и выписанный перечень отстал бы от него молча: новое условие оказалось бы вне наблюдения, не будучи нарушением.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/mirrorcatalogcondition_test.go` (снято вынесением службы — `kacho#2598`; предмет жив здесь, задача #17). Изменилось: координаты эталонной полосы и владельца таблицы (приставки `services/iam/` в самостоятельном клоне нет — модуль и есть владелец, поэтому проверка «писатель вне владельца» здесь выродилась бы в тождество и заменена проверкой, что писатель лежит В ДЕРЕВЕ МОДУЛЯ); разбор вынесен из пробы в пакет `check`. Осталось дословно: имя гейта, перечень глаголов записи с признаком «вводит строку», вывод условия из эталона и самоистечение ведомости.
Близнеца в платформе нет: семейство снято там вместе со службой (ban #20).
mirror_divergence_wiring.go — у ЧТЕНИЯ РАЗНОСТИ зеркала и каталога обязан быть ВЫЗЫВАЮЩИЙ в композиционном корне (kacho#1828).
Предмет ¶
Разность зеркала и живого каталога — величина, от которой зависит решение владельца об отзыве, а отзыв ОТНИМАЕТ доступ. Читатель этой разности в дереве есть и хорошо построен; до этого гейта его не спрашивал НИ ОДИН путь исполнения — только интеграционные пробы. Механизм без вызывающего от отсутствующего неотличим: на поднятом стенде величина не производится, и «разности нет» читается ровно так же, как «никто не мерил».
Почему гейт судит УЗЕЛ ВЫЗОВА, а не слово ¶
Имя читателя встречается в этом дереве и прозой — в объяснениях, включая объяснение самого гейта. Проверка по подстроке краснела бы на собственном комментарии, а зеленела бы на закомментированном вызове.
Какие формы записи вызова гейт знает ¶
Обе законные: `resource_mirror.Divergence(…)` и вызов через АЛИАС импорта (`mirror "…/resource_mirror"` → `mirror.Divergence(…)`). Локальное имя пакета берётся из блока импортов каждого файла, а не предполагается равным последнему сегменту пути. Форма, о которой распознаватель не знает, — не редкость, а слепая зона: всё, записанное в ней, оказывается вне наблюдения.
Чем этот гейт НЕ является ¶
Он не утверждает, что разность ПУСТА, и не вправе: непустая разность на стенде арендатора — предмет решения владельца, а не находка проверки. Предмет здесь один — ВЫЗЫВАЮЩИЙ существует.
module_identity_seeded_only_by_baseline.go — личность модуля заводит ТОЛЬКО применённая базовая миграция (ПР-5 приёмки WIRE-1, задача продукта #2098).
Порт с монорепо (`internal/repohygiene/moduleidentityseededonlybythebaseline_test.go`, снят вынесением службы — `kacho#2597`). В монорепо предикат жил ЦЕЛИКОМ внутри `_test.go` (пакет-«внешний тест», без отдельного `.go`); здесь он вынесен в не-тестовый файл, потому что кроме гейта его читает пересчёт.
ПРЕДМЕТ (дословно из монорепо) ¶
Личности модулей посеяны БАЗОВОЙ миграцией, то есть приезжают и в установку, где платформы нет вовсе. Строка, которую арендатор, развернувший службу доступа отдельно, нести не обязан, — это данные окружения, и в миграцию они не идут ни при каких условиях (§«Данные СТЕНДА заводятся посевом»).
СОСТОЯНИЕ НА ДЕНЬ ПЕРЕНОСА — ДРУГОЕ, чем в монорепо, и это названо числом ¶
В монорепо (на день заведения гейта) долг был НЕПОДВИЖЕН: применителя у раздела `seed` манифеста не было, применённую миграцию не поправить (ban #5), а свежая установка без платформы несла пять личностей чужого продукта.
В kaname этот долг ЗАКРЫТ отдельной задачей — #2452 (`20260909202745_module_identities_leave_the_baseline.sql`, применена ДО выноса службы из монорепо, то есть закрытие произошло в исходном дереве, а не в этом порту): пять личностей (`kacho-vpc`, `kacho-compute`, `kacho-nlb`, `kacho-registry`, `kacho-storage`) СНЯТЫ этой миграцией, а применитель заведён (`internal/apps/kaname/moduleseed`), позван из композиционного корня. Остаются ДВЕ: `bootstrap-admin` (личность самой службы, не модульная — `IsModule()` false) и `kacho-api-gateway` (модульная, остаток, названный вслух в шапке миграции — у края манифеста нет вовсе, применителя заводить некому, снимается вместе со своим производителем).
Обе остаются посеянными БАЗОВОЙ миграцией (`0001_initial.sql`, первой в порядке применения) — то есть `moduleIdentitiesSeededOutsideTheBaseline` сегодня находит ноль нарушений. Это НЕ делает гейт вакуумным: он и дальше судит регресс — появление НОВОЙ миграции, сеющей модульную личность НЕ через применитель (ровно тот класс, который #2452 только что убрал). Обновлять эту прозу нормой `#2098` больше не нужно: предмет её первой половины («свежая установка без платформы несёт ноль модульных СА, кроме остатка api-gateway») закрывает #2452, а не этот гейт; гейт стережёт РОСТ.
РОДСТВО, КОТОРОЕ НАДО НАЗВАТЬ — И РАЗЛИЧИЕ (дословно из монорепо) ¶
У ролей модуля такой судья есть отдельным семейством (Г2, `migrationnotawriterofmodulerole`, НЕ входит в этот батч) — запрещает миграции писать роль модуля, у которого есть манифест, ПОЛНОСТЬЮ (у ролей применитель есть). У личностей применитель тоже теперь есть — но не для ВСЕХ (api-gateway — остаток), поэтому запрет здесь остаётся УЗКИМ: не «личность модуля не сеет никакая миграция», а «личность модуля не сеет НИКАКАЯ МИГРАЦИЯ КРОМЕ БАЗОВОЙ» — тот же периметр, что был в монорепо.
ЧЕГО ГЕЙТ НЕ ЛОВИТ (названо, чтобы на него не сослались шире предмета) ¶
Он про ПОСЕВ, а не про живую базу: строку, заведённую не миграцией, он не читает by construction. И он ничего не утверждает о ПОЛНОТЕ посева.
named_verb_form_expiry.go — разбор ПАРЫ: отвергается ли поимённая форма права роли прод-кодом манифеста и есть ли в дереве пробы шести сценариев её полноты. Находка — ровно одно их сочетание: форма принята, полнота не проверяется.
Порт с монорепо (`internal/repohygiene/namedverbformexpiry.go`, снят вынесением службы — `kacho#2597`). Изменилось: пакет (`repohygiene` → `check`), путь домена (`services/iam/internal/manifest/` → `internal/manifest/`, префикс `services/iam/` снят — в kaname код службы лежит от корня репозитория). Осталось дословно: разбор узла (не подстроки), закрытый перечень шести сценариев, различение двух законных причин молчания.
Почему этот перенос ОБЯЗАТЕЛЕН, а не факультативен ¶
Прод-код `internal/manifest/roleexport/check.go` (написанный ДО выноса службы, когда `internal/repohygiene` был тем же репозиторием) буквально называет держателя: «ЧЕМ ДЕРЖИТСЯ ЗАПРЕТ ... гейтом дерева `internal/repohygiene` `TestNamedVerbFormReturnsOnlyWithItsCompletenessCheck`». До этого файла держателя в дереве kaname не было ни одного: цитата утверждала присутствие проверки, которой не существует.
Предмет — ПАРА, а не любая её половина (дословно из монорепо) ¶
Принять перечень ИМЁН, не умея проверить его полноту по классу, значит свести его к классу МОЛЧА и выдать право ШИРЕ просимого (замер приёмки: 55 вхождений из 92 в черновике vpc совпадают с именем класса). Молчание гейта законно ПО ДВУМ причинам, и различать их вызывающему не нужно: форма отвергается сентинелом (возвратов > 0) ЛИБО она вернулась вместе со своей проверкой (все шесть проб MOD-RL найдены).
Замер на дне переноса (kaname@issue-2597, kacho#2597) ¶
Сентинел `ErrRoleRuleVerbsRetired` в `internal/manifest/` не объявлен и не возвращается (задача #1844 сняла его вместе с формой, которую он отвергал — `f5bb097046` в истории монорепо). Все шесть проб MOD-RL (04, 04a, 18, 18a, 19, 19a) в дереве ЕСТЬ (`internal/manifest/rolenamedverbs_test.go`, `internal/manifest/roleexport/namedverbs_test.go`). Гейт сегодня молчит по ВТОРОЙ законной причине — форма вернулась вместе со своей проверкой, ровно как того требует приёмка #1844, — а не по первой. Это и есть содержание переноса: без держателя регресс (снятие одной из шести проб при живом возврате перечня имён) не был бы замечен НИЧЕМ.
Чего разбор НЕ видит — названо, а не спрятано (дословно из монорепо) ¶
Возврат сентинела, собранный в рантайме (через переменную, через таблицу видов). Такой формы в этом пакете нет, и появись она — гейт увидит ноль возвратов и покраснеет, то есть ошибётся В СТОРОНУ находки, а не молчания.
probe_home.go — РЕЗОЛВ НАЗВАННОГО ДОМА: координата чужого дерева проверяется В НЁМ, а не просто считается.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Приставка `<владелец>/<репозиторий>:` снимает координату с суждения соседнего гейта: подтвердить объявление функции в чужом репозитории он не мог. Пока это было так, у приставки была вторая, незаявленная роль — СПОСОБ СНЯТЬ КООРДИНАТУ С ПРОВЕРКИ. Имя, снятое в чужом дереве завтра, здесь не покраснело бы ни разу, и приёмка посылала бы читателя по адресу, которого нет.
ПОЧЕМУ ЭТО НЕ ЗАВОДИЛОСЬ РАНЬШЕ — И ПОЧЕМУ ДОВОД БЫЛ ВЕРЕН. Ветвь резолва без производителя входа есть мёртвый страж: объявлен и никогда не исполняется. Он заводится ВМЕСТЕ с производителем, и производитель здесь — две синтетические копии с РАЗНЫМИ идентичностями (`probe_home_injection_test.go`).
───────────────────────────────────────────────────────────────────────────── ПОРЯДОК КАНДИДАТОВ ЗАКРЫТ И ОБЪЯВЛЕН
- переменная `KACHO_HOME_<ИМЯ>` — оператор назвал копию явно;
- соседний клон: у каждого предка своего корня — `<предок>/<имя>` и `<предок>/project/<имя>`;
- ничего — ТРЕТЬЯ КАТЕГОРИЯ.
ДОМ ОПОЗНАЁТСЯ ИДЕНТИЧНОСТЬЮ `origin`, А НЕ ИМЕНЕМ КАТАЛОГА. Каталог зовут как угодно, и совпадение имени ничего не обещает: копия под именем `kacho` бывает клоном чего угодно. Поэтому кандидат, чей `origin` не тот, ОТВЕРГАЕТСЯ и называется в причине — «указатель, ведущий в чужой репозиторий, дома не даёт».
ПРИЧИНА ПЕРЕЧИСЛЯЕТ КАЖДОГО ОТВЕРГНУТОГО. Без перечня «дома нет» читается как «искали одно место», а починки у «переменная указывает мимо» и «клона нет» разные — и первая состоит в правке того, что уже объявлено.
───────────────────────────────────────────────────────────────────────────── ГДЕ СУДИТСЯ — В СТВОЛЕ ДОМА, А НЕ В ИНДЕКСЕ ЛЕЖАЩЕЙ РЯДОМ КОПИИ
Координата резолвится по `origin/main` дома. Копия ОБЩАЯ: её ревизию переключает соседняя сессия, не спрашивая отправляющего, и вердикт, прочитанный с индекса, есть функция чужого переключения. Класс наблюдался целиком (`PRO-Robotech/kacho-workspace#543`): копия стояла на линии, где каталог переименован, и проверка объявила несуществующими координаты, которые в стволе ЕСТЬ.
Координата, СВЯЗАННАЯ РЕВИЗИЕЙ (`owner/repo@<хеш>:Имя`), судится на ЭТОЙ ревизии, а не на стволе: она указывает в прошлое состояние чужого дерева намеренно, и сводить её к стволу значило бы судить не то, что написано.
Ствол не резолвится (клон без этой ссылки) — ТРЕТЬЯ КАТЕГОРИЯ, а не находка: судить не по чему, и молчаливый откат на индекс копии здесь запрещён той же причиной, что выше.
───────────────────────────────────────────────────────────────────────────── ЧТО ЭТОТ РЕЗОЛВ СЕГОДНЯ ДАЁТ В КОНВЕЙЕРЕ — СКАЗАНО ПРЯМО, А НЕ ПОДРАЗУМЕВАЕТСЯ
На машине разработчика, где копия дома лежит рядом, резолв ИСПОЛНЯЕТСЯ: замер на дереве службы — домов 2, координат проверено в доме 101, находок 0.
В конвейере службы копии дома рядом НЕТ: единственная выборка чужого дерева (`ci.yml`, задание сверки каталога прав) кладёт его в каталог с ДРУГИМ именем и берёт один подкаталог. Кандидатом она поэтому не становится, и резолв даёт ТРЕТЬЮ КАТЕГОРИЮ со своим числом — то есть безопасный исход, а не ложную находку: «дома нет» никогда не читается как «имени нет».
ОСТАТОК НАЗВАН С ПРЕДИКАТОМ, А НЕ ОБЕЩАНИЕМ. Чтобы резолв исполнялся и в конвейере, заданию, гоняющему этот гейт, нужна выборка дома и переменная `KACHO_HOME_KACHO`, указывающая на неё. Предикат снятия: прогон конвейера печатает «координат проверено в доме N > 0». Цена шага не измерена здесь и решается своим изменением: у разрежённой выборки другой состав и другой вес.
quota_authority_retired.go — АВТОРИТЕТ ВЕЛИЧИН УШЁЛ ИЗ СЛУЖБЫ ДОСТУПА ЦЕЛИКОМ.
Задача продукта `PRO-Robotech/kacho#2117`, приёмка `KAN-QUOTA-1`, стадия S4, сценарии `KAN-Q4-08`, `KAN-Q4-10`, `KAN-Q4-14`; условие готовности `DoD S4` пп. 1, 13.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ — ОТСУТСТВИЕ, А НЕ ПРИСУТСТВИЕ, И ПОТОМУ ГЕЙТ НУЖЕН ОСОБЕННО
Проверка, ищущая ОТСУТСТВИЕ формы, на исчезнувшем предмете замолкает: её образец не совпадёт больше никогда, обход и перепись целы, вердикт зелёный. Отличить это от исправной работы можно только переписью ОБЪЁМА: «находок ноль» и «прочитано ноль» обязаны быть разными вердиктами, и оба напечатаны.
Предмет разбора — ВОЗВРАТ: авторитет величин, заведённый заново в службе, чей продукт отвечает «кому что разрешено», а не «сколько чего можно завести».
───────────────────────────────────────────────────────────────────────────── РАЗБОР СУДИТ УЗЕЛ-ИДЕНТИФИКАТОР, А НЕ ТЕКСТ — И ЭТО НЕСУЩЕЕ
Гейт по подстроке краснел бы на СОБСТВЕННОМ объяснении: перечень снятых имён стоит в этом же файле, а надгробие снятого метода — в `authzguard`. Проверка, судящая ТЕКСТ, не отличает исполняемую часть от комментария, который эту же часть объясняет, — и снимают её первой, как непонятную.
Поэтому ось прод-кода разбирает файл `go/parser`-ом и судит ТОЛЬКО узлы `*ast.Ident`. Комментарий, строковый литерал и запись о снятом предмете под неё не подпадают by construction — и это намеренно: снятое называется в отрицательной форме, надгробием, а не стирается молча. Читатель, пришедший за методом, которого больше нет, обязан узнать, что его СНЯЛИ, а не решить, что он ищет не там.
Ось контракта разбирает СТРОКУ ОБЪЯВЛЕНИЯ (`service` / `message` / `enum` / `rpc` в начале строки).
Отступ в образцах записан `[ \t]`, а НЕ `[[:space:]]`, и это не придирка: второй класс включает перевод строки, поэтому совпадение начиналось на строку РАНЬШЕ объявления и находка называла чужую координату. Поймала это инъекция, а не чтение: сам факт находки был верен, неверно было место — то есть гейт послал бы читателя искать не туда. `.proto` не разбирается тем же парсером, но объявление от комментария отличимо: комментарий начинается с `//`, а объявление — с ключевого слова. Граница названа честно: объявление, записанное внутри многострочного комментария `/* */`, разбору невидимо.
───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ ПРЕДИКАТ ПО СЛОВУ `limit` ОТВЕРГНУТ — ЭТО ИЗМЕРЕНО, А НЕ ВЫБРАНО
Прежняя редакция условия снятия #2117 считала слово `limit` в контракте и была НЕДОСТИЖИМА by construction (`kacho#2457`): под неё попадали имя поля размера страницы (`int32 limit = 2`), предел веерного ответа и проза об учёте у владельцев. Чтобы предикат дал ноль, пришлось бы снять имя поля страницы — ломающее изменение, к величинам отношения не имеющее.
Здесь предмет назван ИМЕНЕМ АВТОРИТЕТА, а не словом: закрытый перечень снятых символов и объявления, чьё имя несёт `Limit`. Поле `limit` объявлением не является и разбору невидимо.
───────────────────────────────────────────────────────────────────────────── ЗАКОННЫЙ ОСТАТОК НАЗВАН ПОИМЁННО — ИНАЧЕ ГЕЙТ ПОТРЕБОВАЛ БЫ РАСШИРЕНИЯ ПОВЕРХНОСТИ
Из службы уходит АВТОРИТЕТ величин. НЕ уходят три вещи, и каждая обязана молчать под всеми осями:
`LimitKind` и словарь посадки три собственных потолка службы берут величину
из посадки (`П25`, `KAN-Q3-01`); снять их
значило бы оставить самостоятельную установку
без ограничения на число аккаунтов и
удостоверений — расширение поверхности, не
названное ни в одном артефакте;
`IdentityQuotaService`, арендаторское чтение СВОЕГО потолка; переехало
`Quota` в контракт службы решением `Д9` именно затем,
чтобы пережить уход модуля;
предел СКОРОСТИ приёма защита от злоупотребления, а не потолок
количества; слово «квота» в её отказе —
совпадение написания.
Ни одно из трёх в перечень снятых имён не входит, и каждое стоит законным близнецом в инъекции (`quota_authority_retired_injection_test.go`): без второй половины «находок нет» было бы неотличимо от «разбор не смотрит».
read_path_concat.go — разбор: НА ПУТИ ЧТЕНИЯ СРАВНИВАЮТСЯ КОЛОНКИ, А НЕ ИХ СКЛЕЙКА.
Предмет ¶
Склейка колонки внутри УСЛОВИЯ выводит колонку из-под индекса: сравнивать приходится вычисленное значение, а вычисленное значение отбирает строки только ПОСЛЕ того, как они прочитаны. Ответ от этого не меняется, стоимость растёт с числом строк в системе, и заметно это только под нагрузкой.
Класс измерен, а не предположен. Починка горячего пути перевела на пару колонок два места — вердикт и перечисление объектов. Перепись ПО СВОЙСТВУ («колонка склеивается там, где значение сравнивается») дала на том же дереве ЧЕТЫРЕ: два обратных вопроса и две точки прибора замера, гасившие индекс области. У одной из четырёх комментарий рядом обещал «колонками, а не склейкой» — то есть был ложен.
Поведенческой пробы для этого мало: она мерит ту точку входа, которую зовёт, и молчит об остальных — ровно это и позволило долгу прожить. Свойство — свойство ДЕРЕВА, и держать его обязан обход дерева.
Объём ВЫВОДИТСЯ, а не выписывается ¶
Каталоги берутся у объявления предмета замера (`scalegrid/fingerprint.go`) — того же источника, которым определяется предмет прибора. Выписанный перечень не двинулся бы от нового каталога и продолжал бы сторожить прежние.
Читается ИСПОЛНЯЕМАЯ часть ¶
Литералы разбираются по синтаксическому дереву Go (SQL в Go-комментарии кодом не является), внутри литерала снимаются SQL-комментарии, а содержимое строковых литералов SQL ЗАКРЫВАЕТСЯ с сохранением длины — иначе слово внутри литерала читается как ключевое, условие обрывается, и гейт молчит ровно на той форме, ради которой написан.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/readpathconcat_test.go` (снято вынесением службы — `kacho#2598`; предмет жив здесь, задача #17). Изменилось: координата объявления предмета замера (приставки `services/iam/` в самостоятельном клоне нет), разбор вынесен из пробы в пакет `check`, разбор литералов Go взят у соседнего семейства того же дерева и живёт здесь одной копией. Осталось дословно: имя гейта, перечни ключевых слов условия, границы цепочки склейки и счёт законного близнеца.
Близнеца в платформе нет: семейство снято там вместе со службой (ban #20).
role_operation_response_state.go — анализатор «ответ операции над ролью не несёт вычисленного состояния, и это ОБЕСПЕЧЕНО, а не совпало».
Порт с монорепо (`internal/repohygiene/roleoperationresponsestate.go`, снят вынесением службы — `kacho#2597`). Дословно: весь анализатор. Изменилось: пакет (`repohygiene` → `check`); `ServiceRoot` теперь пустая строка у вызывающего — в kaname дерево службы лежит от корня, а не под `services/iam`.
Предмет ¶
Контракт роли обещает арендатору буквально следующее: нулевое значение `health` и `lifecycle` означает «ЭТИМ ОТВЕТОМ НЕ ВЫЧИСЛЕНО» и никогда «роль здорова» либо «роль объявлена»; его несут ответы операций `Create`/`Update`, а `Get` и `List` заполняют состояние всегда.
Обещание держится ТОЛЬКО ТЕМ, что производителя вычисленного состояния никто не звал на пути мутации. Свойство «by construction» тем и плохо, что его снятие ТИХОЕ.
Что судится ¶
ПЕРЕВОДЧИК ответа операции над ролью — не-тестовая функция, у которой (а) результаты ровно `(*anypb.Any, error)`, (б) есть параметр типа `domain.Role` и (в) в теле стоит вызов перевода `dto.Transfer`. Каждый такой переводчик обязан звать проекцию (`domain.Role.WithoutComputedState`). Не зовёт — находка с координатой.
ЧЕГО ОН НЕ СУДИТ ¶
- ПОЛНОТУ набора производных полей — предмет пробы самой проекции;
- ЛИШНЮЮ РАБОТУ — расход без последствий для контракта;
- ЧТЕНИЯ (`Get`/`List`) — у них результат не `(*anypb.Any, error)`.
Падает на ПУСТОМ ОБХОДЕ ¶
Ноль прочитанных файлов, ноль разобранных функций либо ноль найденных переводчиков роли — «находок ноль» неотличимо от «прочитано ноль».
role_scope_chain_stays_empty.go — САМОИСТЕКАЮЩИЙ гейт решения «меточную ось сужать НЕ НАДО» (задача продукта #1913, приёмка `docs/engineering/acceptance/role-withdrawal-has-a-producer.md` §2.8, §10 шаг 8).
Порт с монорепо (`internal/repohygiene/rolescopechainstaysempty.go`, снят вынесением службы — `kacho#2597`). Дословно: весь предикат, распознаватели, закрытый перечень ярусных источников. Изменилось: пакет (`repohygiene` → `check`), путь-приставка обхода (`services/iam/` снята — в kaname код службы лежит от корня).
Что здесь стережётся — ФАКТ О ДЕРЕВЕ, на котором стоит решение ¶
Приёмка решила НЕ сужать меточную ось выдачи по живости роли, и решение стоит целиком на одном факте: у роли МОДУЛЯ цепь областей ПУСТА, поэтому меточная выдача не достаёт её ни живую, ни снятую. Факт измерен и верен сегодня — и НЕ ЗАЩИЩЁН НИЧЕМ:
- роль модуля всегда кластерного яруса, потому что `owner_module` и `cluster_id` пишет ОДИН оператор, а не ограничение схемы;
- у роли кластерного яруса цепь пуста, потому что ни одна ветвь производителя звеньев её не отбирает: ветви берут `account_id` и `project_id`, а у роли модуля они пусты оба.
Значит производителя звена для `iam_role` может завести любая соседняя работа. Появится он — решение §2.8 станет неверным, а доступ вернётся МОЛЧА. Этот гейт и есть то единственное, что об этом скажет.
ЧТО СЧИТАЕТСЯ НАХОДКОЙ — ИСТОЧНИК ветви, а не имя типа ¶
Ветвей, производящих звено для `iam_role`, две, и обе ЗАКОННЫ:
(5a) роль АККАУНТА → источник `account_id` (5b) роль ПРОЕКТА → источник `project_id`
Находка — ТРЕТЬЯ ветвь: та, что производит звено для `iam_role`, не спрашивая ни одного из двух ярусных столбцов.
ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО, А НЕ СПРЯТАНО ¶
- звено, приехавшее ЗЕРКАЛОМ ресурса (writer одинаков для всех типов);
- запрос, собранный из кусков в рантайме;
- производителя вне дерева kaname.
role_verb_projection_sole_writer.go — разбор операторов записи в проекции роли: «кто АВТОРУЕТ строку, кто её СНИМАЕТ, переселяет ли снимающий-не-автор снятое» (порт с монорепо `internal/repohygiene/roleverbsolewriter_test.go`, держатель `TestIAMRV112_RoleVerbProjectionHasASoleWriter`, снят вынесением службы доступа — `kacho#2597`).
Предмет ¶
Таблицы `kaname.role_verb` и `kaname.role_rule_ref` — проекции роли, то, из чего цепь вердикта собирает ответ «разрешено ли действие». Класс, ради которого гейт заведён: ДВЕ реализации знают, что такое законная строка, и расходятся МОЛЧА — обе компилируются, у обеих есть пробы, и различаются они только на входе, который ни одна проба не подаёт.
Единица — «авторует», а не «пишет» (решение kacho#1034, перенесено дословно) ¶
Что такое законная строка, объявляет ТОЛЬКО `INSERT`: он называет колонки и значения. `DELETE`/`UPDATE` строку не авторуют — они её снимают или правят. Значит класс живёт в АВТОРСТВЕ, а не в записи вообще, и единица гейта — функция, ВНОСЯЩАЯ строку. Снимающий не-автор обязан ПЕРЕСЕЛИТЬ снятое в `kaname.role_grant_orphan` ТЕМ ЖЕ оператором — иначе отобранное право неотличимо от никогда не выданного.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь-константа слоя (без префикса `services/iam/` — код лежит от корня модуля kaname), обход дерева (`gitenv`+`git ls-files` вручную → `github.com/PRO-Robotech/kacho/pkg/treecorpus` и `internal/testsupport/platformtree.RequireCorpus`, потому что предмет — внутри службы, дерева платформы модулю не нужно). Осталось дословно: имена таблиц-проекций, форма распознавателя (узел-литерал разобранного AST, а не текст файла), три оси проверки (авторство · переселение · слой) и имя держателя `TestIAMRV112_RoleVerbProjectionHasASoleWriter` — на нём стоят цитаты `docs/engineering/acceptance/role-verb-projection-sole-writer.md`, `rule-segments-have-a-referent.md` и `module-manifest-roles-and-seed-grants.md`, написанные ДО выноса, когда `internal/repohygiene` был тем же репозиторием.
Граница названа, а не умолчана ¶
Гейт читает СТРОКОВЫЕ ЛИТЕРАЛЫ непроверочного кода Go, разобранного в дерево, и приписывает находку объемлющей функции. Он НЕ видит: SQL миграций (там запись законна — миграция и есть схема), проб (им положено готовить состояние), имя таблицы, собранное из кусков (слепая зона, предикатом по подстроке не ловится ничем).
seed_identity_census.go — разбор ДВУХ текстов об одном предмете: вывода переписи посевной идентичности и чисел, объявленных приёмкой `docs/engineering/acceptance/seed-identity-names-its-own-service.md` §0.
ПРЕДМЕТ ¶
У приёмки есть исполняемый предикат, лежащий рядом с ней (`seed-identity-names-its-own-service.py`), и числа §0 — его вывод. Пока предиката никто не зовёт, эти два текста расходятся МОЛЧА: документ продолжает называть числа, верные для ревизии, которой в стволе уже нет, и отличить «перемерено» от «переписано по памяти» нечем.
ПРИЗНАК — ИЗМЕРЕН, А НЕ ПРЕДПОЛОЖЕН ¶
Расхождение наступило до заведения этого гейта и было найдено вручную: объявление называло по ведру ПРЕДМЕТА `130 · 54 ф.`, предикат на стволе давал `130 · 56 ф.`. Вхождений СТОЛЬКО ЖЕ — двигались файлы, — поэтому расхождение не видно ни по одному числу в отдельности и обнаруживается только сверкой обоих текстов целиком.
ЕДИНСТВЕННЫЙ ИСТОЧНИК ПЕРЕЧНЯ ВЁДЕР — САМ ПРЕДИКАТ ¶
Перечень вёдер здесь НЕ выписан. Он берётся из того, что предикат напечатал: выписанный был бы вторым местом об одном предмете и разошёлся бы с предикатом ровно тогда, когда тот заведёт новое ведро, — то есть остался бы зелёным на ведре, о котором никто не спросил.
ЧЕГО ЭТОТ РАЗБОР НЕ СУДИТ ¶
- ИСТИННОСТЬ вёдер. Правильно ли предикат раскладывает вхождение по вёдрам — вопрос его собственной адъюдикации, и машинного предиката у него нет;
- ПРОЗУ §0. Числа, названные прозой в тексте, здесь не ищутся: их формы столько же, сколько предложений, и разбор по образцу нашёл бы собственное объяснение. Судится ОБЪЯВЛЕНИЕ — блок, названный ревизией измерения.
seeded_service_accounts.go — разбор посева служебных учёток по цепочке миграций: вставка заводит строку, удаление её снимает.
Порт ОБЩЕГО вспомогательного разбора с монорепо (жил как package-private `seededSA`/`foldSeededServiceAccounts` в `internal/repohygiene/moduleserviceaccounthasacomponent_test.go`, снят вынесением службы — `kacho#2597`). Перенесён в НЕ-тестовый файл и экспортирован, потому что нужен как минимум ДВУМ гейтам монорепо: `moduleidentityseededonlybythebaseline` (перенесён этим же изменением, `module_identity_seeded_only_by_baseline.go`) и `moduleserviceaccounthasacomponent` (семейство, НЕ входящее в батч `kacho#2597` этого агента — предмета оно судит компоненты дерева, отдельная от «когда посеяно» ось). Держать разбор внутри теста значило бы, что следующий перенос его продублирует, не заметив: инструкция переноса прямо требует проверить, не появился ли общий помощник, и переиспользовать его — вместо копии.
subject_change_flush_parity.go — извлечение для гейта «полоса производителей очереди смены субъекта не пополняется МОЛЧА» (задача #17, порт-ПОЛОВИНА семейства `subjectchangeflushparity` с монорепо `internal/repohygiene/subjectchangeflushparity.go`, снятого выносом службы — `kacho#2597`).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ ПРЕДКА — ДВЕ ПОЛОСЫ ОДНОГО МЕХАНИЗМА, СВЕРЯЕМЫЕ МЕЖДУ СОБОЙ
Смена прав доезжает до кэша решений края ДВУМЯ независимыми полосами:
- НЕМЕДЛЕННО, на реплике, обслужившей мутацию, — самосбросом по полному имени метода (набор `subjectChangingFQNs` у края);
- С ЗАДЕРЖКОЙ, на соседних репликах, — через очередь смены субъекта (`kaname.subject_change_outbox`), которую край читает сам.
Полосы кормит ОДНО событие, но перечни у них РАЗНЫЕ и ведутся врозь. Заведя шестого производителя очереди, легко не вспомнить о самосбросе: соседние реплики сойдутся за интервал опроса, а та, что мутацию обслужила, продолжит отвечать по закешированному вердикту — то есть по ОТОЗВАННОМУ праву, и дольше всех именно там, где пользователь только что нажал «отозвать».
Заметить это по одной полосе нельзя: каждая исправна сама по себе. Предок поэтому спрашивал не «верен ли перечень» (это и есть спорный вопрос), а РЕШАЛ ЛИ КТО-НИБУДЬ, что полосы различаются.
───────────────────────────────────────────────────────────────────────────── ЧТО РАЗРЕЗ СДЕЛАЛ С ЭТИМ ГЕЙТОМ — СКАЗАНО ЧИСЛОМ, А НЕ ОГОВОРКОЙ
Полосы развело по РАЗНЫМ РЕПОЗИТОРИЯМ. Замер этого дерева (`61053691` плюс дифф этого изменения):
производители очереди internal/apps/kaname/api 5 ЗДЕСЬ набор самосброса gateway/internal/middleware/authz.go 0 у края платформы
Предикат второй строки: `git grep -l subjectChangingFQNs` → 0; каталога `gateway` в составе этого дерева нет вовсе (`git ls-files gateway | wc -l` → 0).
Сверить полосы МЕЖДУ СОБОЙ отсюда нельзя, и обходить это чтением чужого репозитория с диска — НЕЛЬЗЯ ТЕМ БОЛЕЕ: вердикт стал бы свойством того, что случайно лежит в модульном кеше машины прогона, а не свойством коммита ни одного из двух деревьев. Тот же довод, по которому соседнее семейство (`subject_change_gap_detection_test.go`) судит два звена из трёх.
───────────────────────────────────────────────────────────────────────────── ЧТО ЭТА ПОЛОВИНА ДЕРЖИТ — И ЧЕГО ОНА НЕ ДЕРЖИТ
ДЕРЖИТ: полоса производителей не пополняется молча. Перечень объявлен в дереве, и гейт сверяет его с разбором. Шестой производитель делает вердикт красным, а правку перечня — ВИДИМОЙ В ДИФФЕ, где обзор и спрашивает: «а краю сказали?». Без этого добавление производителя не оставляет в этом репозитории следа ВООБЩЕ, и расхождение полос наступает молча.
НЕ ДЕРЖИТ: что край свой набор пополнил. Это утверждение о ЧУЖОМ дереве, и сделать его отсюда нечем. Объявленный здесь перечень — ОПЕРАНД для той стороны: пинить его вправе гейт платформы, потому что перечень отслеживается git и меняется только изменением.
Сказано прямо, потому что половина, выдающая себя за целое, хуже отсутствия: зелёный вердикт читался бы как «полосы сошлись».
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ УЗЕЛ ОБРАЩЕНИЯ, А НЕ УЗЕЛ ВЫЗОВА — ЦЕНА ИЗМЕРЕНА ПРЕДКОМ
Обращений к методу в дереве ДВЕ формы, и обе законны:
w.AccessBindingsW().EmitSubjectChangeEvent(ctx, …) // вызов на месте fanout(ctx, …, w.AccessBindingsW().EmitSubjectChangeEvent, …) // передан значением
Вторая появляется, когда строка пишется НА КАЖДОГО субъекта привязки общим развёртывателем: сам вызов уезжает в него, а производителем остаётся use-case, который метод отдал. Распознаватель, знавший только первую, объявлял вторую отсутствующей — не нарушением, а НЕВИДИМОСТЬЮ: два живых производителя пропадали из переписи. Поэтому судится `*ast.SelectorExpr`: узел вызова его содержит, поэтому обе формы считаются по разу и ни одна дважды.
В этом дереве вторая форма ЖИВАЯ — её несут `access_binding/delete.go` и `access_binding/revoke.go`, то есть два производителя из пяти. Слепота стоила бы ровно их.
system_role_row_is_never_deleted.go — разбор прод-кода kaname на предмет удаления строки СИСТЕМНОЙ роли (порт с монорепо `internal/repohygiene/systemrolerowisneverdeleted.go`, снят вынесением службы доступа — `kacho#2597`; решение `docs/engineering/architecture/role-withdrawal-is-a-mark.md`, задача продукта #1913).
Предмет ¶
Роль, объявленная манифестом модуля, системная BY CONSTRUCTION: применитель ставит `IsSystem: true`, а `roles.is_system` вычисляется из `cluster_id`. Значит вопрос «как снять роль модуля» есть вопрос «что делает прод-код со строкой системной роли», и у него два взаимоисключающих ответа: удалить строку либо пометить её снятой. Линия выбрала ВТОРОЙ:
- **роль в работе не удалится вовсе.** Выдачи ссылаются на роль ключом `access_bindings_role_fk … ON DELETE RESTRICT`; удаление роли, за которой стоит хоть одна строка выдачи, отвергается `SQLSTATE 23503`;
- **если бы не отвергалось — три проекции уехали бы МОЛЧА**: селекторы правил, проекция глаголов и проекция объявленных сегментов;
- **отзыв перестал бы достигать ПРЕДЪЯВЛЕНИЯ наблюдаемо.** У снятой пометкой строки есть что читать на пути запроса; у удалённой читать нечего.
Что здесь считается находкой — ОДНА ось, и она про оператор ¶
Оператор `DELETE` над таблицей `roles`, не сужённый на ПОЛЬЗОВАТЕЛЬСКУЮ роль. Сужение опознаётся в ДВУХ законных написаниях: `is_system = false` (и `NOT is_system`) — прямо по вычисляемой колонке; `cluster_id IS NULL` — по кластерному якорю, из которого она и вычисляется.
Ось судит СТРОКОВЫЙ ЛИТЕРАЛ узла разбора, а не текст файла: слово `DELETE` стоит и в комментариях, объясняющих сам запрет. Оператор отличается от ПРОЗЫ, цитирующей оператор, по ПРОДОЛЖЕНИЮ за именем таблицы (`WHERE`, `RETURNING`, `USING`, `;`, конец литерала) — привязки к началу строки недостаточно.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь-константа (`iamGoPrefix = "services/iam/"` → обход всего дерева модуля без префикса, код лежит от корня). Осталось дословно: обе регулярки сужения и продолжения, форма распознавателя (`ScanRoleDeletes`), имя держателя `TestSystemRoleRowIsNeverDeleted`.
Чего разбор НЕ видит — названо, а не спрятано ¶
- **миграции.** Каждая снимала роль удалением до решения — это СТАТУС-КВО, который решение и заменяет, а не находка сегодняшнего дерева;
- **каскад по чужому ключу.** Строка роли уезжает вместе со своим ярусом (аккаунт, проект). Для СИСТЕМНОЙ роли ярус — кластер;
- **запрос, собранный из кусков в рантайме** либо приехавший параметром.
terminal_refusal_wrapping.go — разбор для двух гейтов приёмки #2439: репозиторий операций попадает в use-case только ОБЁРНУТЫМ, и тексты отказа объявлены в одном месте.
Приёмка: `docs/engineering/acceptance/refusal-text-names-the-lane-that-can-retry.md`, сценарии KN-RTX-06 и KN-RTX-08.
Что предикат устанавливает, а что НЕТ — сказано здесь, а не в заголовке ¶
Он устанавливает ОДНО: всякий сырой конструктор репозитория операций в прод-коде обёрнут надстройкой прямо на месте вызова. Всеобщности вида «всякий терминальный исход проходит надстройку» он НЕ устанавливает и не обязан: четвёртый писатель терминального исхода — реконсайлер осиротевших операций — идёт мимо контракта репозитория и вынесен исключением приёмки (§2.3).
Различие несущее. Две первые редакции приёмки были отвергнуты ровно за заголовок шире предиката: читатель пишет гейт по заголовку, а не по телу.
Почему разбор синтаксический, а не по подстроке ¶
Имя конструктора встречается в комментариях — в этом дереве четыре вхождения, из которых настоящий вызов ОДИН. Проверка по подстроке краснела бы на собственном объяснении соседнего файла; разбор судит узел ВЫЗОВА.
token_claim_foreign_brand.go — разбор ИМЁН КЛЕЙМ выпущенного токена: не называет ли клеймо, которое читает предъявитель токена БЕЗ нашего исходного кода, чужой платформенный бренд (порт, СУЖЕННЫЙ ДО ОСИ А, с монорепо `internal/repohygiene/tokenclaimforeignbrand.go`, снят вынесением службы доступа — `kacho#2597`; задача продукта #2127, семейство приёмки IAM-SEV-NAME-05).
Предмет ¶
Служба — самостоятельный продукт, ставящийся в чужом облаке. Норма разделения (решение владельца, kacho#2076): продукт наследует КОД, но не ИМЯ. Имя клейма читается оператором чужого облака без нашего исходного кода — достаточно раскодировать токен, — поэтому приставка имени клейма есть идентичность, а не код. Свой словарь — `kaname_`; чужой, платформенный — `kacho_`. `internal/domain/principal_claims.go` уже несёт три клейма формы `kaname_*` — предмет живой, не гипотетический.
Что здесь ПОРТИРОВАНО (ось А), а что НЕТ (ось Б) — сказано прямо ¶
Монорепошный предок судил ДВЕ оси: А — имя клейма принадлежит своему словарю; Б — у имени из своего словаря нет двойника в чужом словаре НИГДЕ в отслеживаемом дереве, включая не-Go текст (посевные наборы, профиль развёртывания, собранные коллекции проб, клиентская страница). Здесь перенесена ТОЛЬКО ось А — разбор Go-кода по четырём позициям чеканки и чтения. Ось Б требует единого свода дерева kaname И его нынешних потребителей (документация арендатора, коллекции проб), который на дату переноса не собран в одном месте; расширение до неё — отдельная работа, не сделанная здесь умышленно, а не забытая молча.
Позиции, которые СУДЯТСЯ (перенесены дословно) ¶
claims := map[string]any{"kacho_user_id": …} ← ключ состава
pt, _ := claims["kacho_principal_type"].(string) ← чтение по имени
case "kacho_mfa_at": ← разбор по имени
verifiedClaim(vt, "kacho_principal_type") ← имя передано вызовом
Чего разбор НЕ видит — названо, а не спрятано ¶
- имя клейма, собранное из частей либо взятое переменной;
- приставка, отданная предикату (`strings.HasPrefix(k, "kacho_")`) — ось Б предка ловила и её; здесь эта форма вне наблюдения;
- не-Go текст.
token_claim_single_source.go — разбор мест, СОБИРАЮЩИХ состав утверждений выданного токена (порт с монорепо `internal/repohygiene/tokenclaimsinglesource.go`, снят вынесением службы доступа — `kacho#2597`; приёмка F2, сценарий F2-42, §2.11).
Предмет ¶
Токен принципалу выдают ДВА пути: обратный вызов прежнего провайдера, пока он жив, и собственный эндпоинт (`internal/service/token_enrichment_own_lane.go`). Пока перечень утверждений и правила их вычисления живут у каждого свои, различие между ними НЕ ЯВЛЯЕТСЯ НИЧЬЕЙ НАХОДКОЙ: оно не выражено и потому не может покраснеть. Первая же правка одной стороны разойдётся с другой молча — у ПРИНЦИПАЛА, чей токен выдан не тем путём.
Что здесь считается СБОРКОЙ, а что ПОТРЕБЛЕНИЕМ ¶
claims := map[string]any{"kaname_user_id": …, "kaname_account_id": …} ← СБОРКА
return s.userTokenClaims(row, user, subject, hookCtx) ← потребление
Потребителей должно быть МНОГО — они и есть цель: второй способ дойти до той же сборки, а не второй состав. Находкой является ВТОРАЯ СБОРКА.
Почему судится ИМЯ КЛЮЧА, а не тип отображения ¶
Предмет — СЛОВАРЬ утверждений, поэтому место опознаётся по именам ключей, а тип значений в счёт не идёт.
Почему порог по числу ключей, а не «хоть один» ¶
Префикс утверждений встречается и вне состава — им же названы метрики и поля контекста. Место, назвавшее один ключ, состава не объявляет.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь-константа владельца (без префикса `services/iam/`). Осталось дословно: обе функции разбора, форма узла (составной литерал `map[string]…`, узел вызова), имя держателя `TestTokenClaimsAreAssembledInOnePlace`.
Чего разбор НЕ видит — названо, а не спрятано ¶
- состав, собранный присваиваниями по одному ключу за раз;
- имя ключа, собранное из частей или взятое переменной;
- состав, объявленный в чужом языке.
withdrawal_producer_arrives_with_the_applier.go — разбор прод-дерева на СОГЛАСИЕ двух фактов: применитель ролей модуля приводится в действие, и производитель отзыва роли существует (порт с монорепо `internal/repohygiene/withdrawalproducerarriveswiththeapplier.go`, снят вынесением службы доступа — `kacho#2597`; задача продукта #1913).
Предмет ¶
Сверка `moduleroles.Reconcile` объявляет вид расхождения `LiveNotDeclared` — «строка живёт, объявления у неё больше нет». Пока применитель НЕ приводится в действие в проде, отсутствие производителя снятия — остаток, а не дефект. Как только применитель начинают звать (`cmd/kaname/serve.go`, `moduleroles.NewApplier`, задача #1034/#2010 — В KANAME ЭТО УЖЕ ПРОИЗОШЛО), остаток становится дефектом, необратимым ДЛЯ АРЕНДАТОРА: роль, которую нельзя снять, живёт вечно, и право, выданное через неё, продолжает действовать после того, как модуль перестал её объявлять.
Что здесь считается находкой — ОДНО согласие, а не два запрета ¶
Находка — состояние «применитель приводится в действие, производителя отзыва нет». Ни одна половина по отдельности находкой не является:
приводится в действие · производитель есть → норма, работа сделана приводится в действие · производителя нет → НАХОДКА не приводится · производителя нет → остаток не приводится · производитель есть → норма, производитель приехал раньше
Обе половины судятся по УЗЛУ РАЗБОРА, а не по слову ¶
«Применитель приводится в действие» — это ВЫЗОВ через импортированный пакет, а не упоминание его имени. «Производитель отзыва» — это оператор ЗАПИСИ над `roles`, ставящий пометку снятия В СПИСКЕ ПРИСВОЕНИЙ.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь импорта применителя (без `services/iam/` — код лежит от корня модуля kaname: путь становится `github.com/PRO-Robotech/kaname/internal/apps/kaname/moduleroles`). Осталось дословно: обе регулярки, форма связывания импорта (по псевдониму, а не по последнему сегменту пути), различение узла разбора и узла-прозы, имя держателя `TestWithdrawalProducerArrivesWithTheApplier`.
Чего разбор НЕ видит — названо, а не спрятано ¶
- миграцию как производителя (запрещена отдельным гейтом её же смысла);
- производителя вне дерева модуля;
- запрос, собранный из кусков в рантайме.
Index ¶
- Constants
- Variables
- func AcceptanceDocsOfTree(root string) (map[string]string, error)
- func AdjudicateCarriedLedger(ledgerPath string, rows []CarriedLedgerRow, ...) []string
- func AdjudicateSeedCensus(decl SeedCensusDeclaration, rep SeedCensusReport) []string
- func AlertExpressionsIn(doc string) []string
- func ApplierPortVerbDeletesTheRoleRow(name string) (bool, string)
- func AuditAcceptanceEditsAfterVerdict(root, dir string) ([]AcceptanceEditFinding, AcceptanceEditCensus, error)
- func AuditDeferredWork(root string) (findings []treehygiene.DeferralFinding, census treehygiene.DeferralCensus, ...)
- func AuditExclusionForm(in ExclusionFormInput) ([]ExclusionFormFinding, ExclusionFormCensus, error)
- func AuditMachineryClaims(f MachineryFacts) ([]MachineryClaim, MachineryCensus)
- func AuditNamedInjections(root string) ([]InjectionFinding, InjectionCensus, error)
- func AuditPayloadForms() []struct{ ... }
- func AuditRoleOperationResponseState(opts RoleOperationResponseStateOptions, log io.Writer) ([]RoleOperationResponseStateFinding, RoleOperationResponseStateCensus, error)
- func AuthorVerbOf(table string) string
- func BaselineMigrationOf(ordered []string) string
- func CallsMakeTarget(body, target string) bool
- func CollectPredicateConcats(files []ReadPathFile, read func(abs string) ([]byte, error)) ([]ConcatFinding, ConcatCensus, error)
- func ConstStringValue(src []byte, name string) (string, bool, error)
- func CountRelations(m map[string]map[string]bool) int
- func DeclaredContexts(raw string, trunkProcesses []string) []string
- func DeclaredProbesOfTree(root string) ([]string, error)
- func DeclaresSelfFlushSet(rel, src string) (bool, error)
- func DeferralSkips() []treehygiene.DeferralSkip
- func ExecutableRunBodies(raw string) ([]string, int, error)
- func FoldSeededServiceAccounts(ordered []string, bodies map[string]string) (alive map[string]SeededServiceAccount, unknownForms []string, stmtsTouched int)
- func HasModuleSetSurfaceExt(rel string) bool
- func HomeEnvVar(identity string) string
- func HomeRef(dir, rev string) (string, string)
- func HomeTree(ownRoot, identity string) (string, string)
- func IdentityGrowthMetricNamesIn(src string) []string
- func InvocationsOf(script string, bodies []string) int
- func IsGeneratedFile(f *ast.File) bool
- func IsModuleSetSurfaceFile(rel string) bool
- func IsSubjectChangeProducerFile(rel string) bool
- func IsVerbClassRuleSource(rel string) bool
- func JoinGrants(g []RelationGrant) string
- func JoinRelationSet(m map[string]bool) string
- func JudgeAuthorityResidue(corpus, excused map[string]string) (AuthorityResidueCensus, []AuthorityResidueFinding)
- func JudgeCensusFixtures(byDir map[string][]CensusFileFacts) []string
- func JudgeTargetWiringFaults(w JudgeTargetWiring) []string
- func MakefileDeclaresTarget(makefile, target string) bool
- func MissingGrantedRelations(grants []RelationGrant, model map[string]map[string]bool) []string
- func MissingScenarioProbes(funcNames []string) []string
- func ModuleIdentitiesSeededOutsideTheBaseline(alive map[string]SeededServiceAccount, baseline string) []string
- func NamedVerbFormFinding(sentinelReturns int, probeNames []string) []string
- func OutsideTraversal(rel string) bool
- func OwnHomeOfTree(root string) (string, error)
- func ParseCarriedCoordinateLedger(body string) ([]CarriedLedgerRow, map[string]CarriedLedgerSection, CarriedLedgerCensus)
- func PathCoordinatesIn(doc, body string) ([]PathCoordinate, PathScanBorders)
- func PathSpecResolves(spec string, dirs map[string]bool) bool
- func ProbeCoordinateResolves(name string, declared []string) bool
- func ProbeDeclaredInHome(dir, ref, name string) bool
- func ProdGoRoots(root string, tracked []string) ([]string, error)
- func ProductionGoFile(rel string) bool
- func PushesToTrunk(raw string) (bool, string, error)
- func RelationsByType(text string) map[string]map[string]bool
- func RemovalVerbsOf(table string) []string
- func RepoIdentity(dir string) string
- func SQLCreateTableBody(upSection, table string) string
- func ScanApplierDeletes(path string, src []byte) (sites []ApplierDeleteSite, census ApplierDeleteCensus, err error)
- func ScanAuditPayloads(root string) (findings []AuditPayloadFinding, census AuditPayloadCensus, err error)
- func ScanCatalogWriteLocking(files []CatalogSource) ([]CatalogWriteFinding, CatalogWriteCensus, error)
- func ScanClaimAssemblies(path string, src []byte, prefix string, minKeys int) ([]ClaimAssembly, ClaimAssemblyCensus, error)
- func ScanClaimBuilderCalls(path string, src []byte, builders map[string]bool) ([]ClaimBuilderCall, ClaimAssemblyCensus, error)
- func ScanClassRuleDeclarations(rel string, src []byte) ([]string, error)
- func ScanDerivedIDDeclarations(path string, src []byte) (sites []DerivedIDImportSite, census DerivedIDCensus, err error)
- func ScanFixedRefusalTexts(root string, files []string) (RefusalTextCensus, []RefusalTextFinding, error)
- func ScanHistoryQuestions(corpus map[string][]byte, trunkRefs []string) ([]HistoryQuestion, HistoryCensus)
- func ScanKeyAlgorithmConstraints(path, upSection, column string) (found []AlgorithmConstraint, dropped []string, ...)
- func ScanMigrationRoleInserts(path string, src []byte) (sites []MigrationRoleSite, census MigrationRoleCensus)
- func ScanModuleSetEnumerations(rel, body string, modules []string) ([]ModuleSetFinding, ModuleSetScan)
- func ScanObjectTypeUses(rel string, src []byte) (reads int, writes []string, err error)
- func ScanRawOperationsRepo(root string) ([]RawOperationsRepoSite, TerminalRefusalCensus, error)
- func ScanRoleDeletes(path string, src []byte) (sites []RoleDeleteSite, census RoleDeleteCensus, err error)
- func ScanRoleScopeChain(path, src string) (found []RoleScopeChainSite, census RoleScopeChainCensus)
- func ScanRoleWithdrawalWiring(path string, src []byte) (drive, mark []RoleWithdrawalSite, census RoleWithdrawalCensus, err error)
- func ScanSQLUpdates(path string, src []byte, tables []string) ([]SQLUpdate, SQLUpdateCensus, error)
- func ScanTokenClaimForeignBrand(path string, src []byte) ([]TokenClaimUse, TokenClaimCensus, error)
- func ScenarioProbeName(scenario string) string
- func SeedScopeUnfit(ordered []string, alive map[string]SeededServiceAccount) string
- func SortedFuncNames(byFunc map[string]FunctionDatabaseCalls) []string
- func SplitAlgorithmValues(values []string) (algorithms []string, hasEmpty bool)
- func SubjectChangeRosterTotal(declared map[string]int) int
- func TrackedPathsOfTree(root string) ([]string, error)
- func TreeModulePath(root string) (string, error)
- type AcceptanceEditCensus
- type AcceptanceEditFinding
- type AlgorithmConstraint
- type AlgorithmDictionaryCensus
- type ApplierDeleteCensus
- type ApplierDeleteSite
- type AuditPayloadCensus
- type AuditPayloadFinding
- type AuditPayloadKey
- type AuditPayloadSite
- type AuditPersonalKey
- type AuthorityResidueCensus
- type AuthorityResidueFinding
- type BoolWrapperCall
- type CarriedLedgerCensus
- type CarriedLedgerRow
- type CarriedLedgerSection
- type CatalogSource
- type CatalogWriteCensus
- type CatalogWriteFinding
- type CensusFileFacts
- type ClaimAssembly
- type ClaimAssemblyCensus
- type ClaimBuilderCall
- type ConcatCensus
- type ConcatFinding
- type DatabaseCallCensus
- type DatabaseCallSite
- type DeadPathCoordinate
- type DeadProbeCoordinate
- type DeleteRevokeCensus
- type DerivedIDCensus
- type DerivedIDImportSite
- type ExclusionFormCensus
- type ExclusionFormFinding
- type ExclusionFormInput
- type ExportProcedureCensus
- type FunctionDatabaseCalls
- type GoSQLLiteral
- type HistoryCensus
- type HistoryQuestion
- type HomeVerdict
- type IdentityGrowthReaderCensus
- type InjectionCensus
- type InjectionFinding
- type JobFieldRead
- type JobKnobCensus
- type JobSection
- type JudgeTargetWiring
- type LenientScopeCensus
- type MachineryCensus
- type MachineryClaim
- type MachineryFacts
- type MachineryKind
- type MigrationRoleCensus
- type MigrationRoleSite
- type MirrorConditionOutcome
- type MirrorWiringScan
- type MirrorWrite
- type ModuleManifestSite
- type ModuleSetDecl
- type ModuleSetFinding
- type ModuleSetScan
- type NonASCIIIdent
- type PathCoordinate
- type PathCoordinateCensus
- type PathScanBorders
- type ProbeCoordinate
- type ProbeCoordinateCensus
- type RawOperationsRepoSite
- type ReadPathFile
- type RefusalTextCensus
- type RefusalTextDecl
- type RefusalTextFinding
- type RelationGrant
- type RoleDeleteCensus
- type RoleDeleteSite
- type RoleOperationResponseStateCensus
- type RoleOperationResponseStateFinding
- type RoleOperationResponseStateOptions
- type RoleProjectionOp
- type RoleScopeChainCensus
- type RoleScopeChainSite
- type RoleWithdrawalCensus
- type RoleWithdrawalSite
- type SQLUpdate
- type SQLUpdateCensus
- type SeedCensusCell
- type SeedCensusDeclaration
- type SeedCensusReport
- type SeededServiceAccount
- type SubjectChangeProducer
- type SubjectChangeRosterDiff
- type TerminalRefusalCensus
- type TokenClaimCensus
- type TokenClaimForm
- type TokenClaimUse
- type TreeCorpus
- func CorpusFrom(tree *treecorpus.Tree, want func(rel string) bool) (TreeCorpus, error)
- func ExclusionFormGoCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- func ExportProcedureGuides(tree *treecorpus.Tree) (TreeCorpus, error)
- func ManifestLoaderCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- func MigrationCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- func MirrorCandidateCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- func ModuleSetDeclCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- func ModuleSetSurfaceCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- func SubjectChangeProducerCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- func VerbClassRuleCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
- type TrunkHolderCensus
- type TrunkProcessCensus
- type TrunkRegisterCensus
- type VerbFormSentinelCensus
- type Vertex
- type WrapperPair
- type WrapperScanReport
Constants ¶
const ( // FormFieldLiteral — литерал прямо в поле `Payload`. FormFieldLiteral = "литерал-в-поле" // FormHelperDecl — объявление построителя `…Payload(…) map[string]any`. FormHelperDecl = "построитель" // FormIndexAssign — ключ, добавленный присваиванием по индексу. FormIndexAssign = "присваивание-по-индексу" // FormFieldIdent — `Payload: p`, где `p` собран выше в той же функции. FormFieldIdent = "имя-собранное-рядом" // FormHelperCall — ВЫЗОВ построителя в поле `Payload`. Ключей не несёт: // они судятся у объявления. Считается, чтобы вызов был виден переписи // учтённым, а не пропал между формами. FormHelperCall = "вызов-построителя" // FormOpaque — значение поля `Payload`, не сводящееся ни к одной форме. // Литеральным разбором НЕ судится; печатается числом. FormOpaque = "непрозрачное" )
Формы построения нагрузки. Имена уезжают в перепись: раскладка по формам показывает, какая из них перестала встречаться, — а перестать она может и оттого, что разбор её больше не видит.
const ( // CarriedOutcomeKept — оставлено как путь к прежнему контуру. ТОЛЬКО этот // исход требует предиката снятия. CarriedOutcomeKept = "оставлено" // CarriedOutcomeRemoved — снято. CarriedOutcomeRemoved = "снято" // CarriedOutcomeRewritten — переписано на наш идентификатор. CarriedOutcomeRewritten = "переписано" // CarriedOutcomeNotSubject — предметом не является. CarriedOutcomeNotSubject = "не предмет" )
Закрытый словарь исходов.
const ( // CensusMirrorTable / CensusEdgeTable — таблицы, чья совместная // упомянутость в ОДНОМ SQL-литерале и есть перепись покрытия: она // спрашивает про рёбра у строк зеркала, то есть квантифицирует по // множеству. CensusMirrorTable = "kaname.resource_mirror" CensusEdgeTable = "kaname.resource_parent_edge" // RawEdgeWriteMarker — прямая запись рёбер в обход производителя. RawEdgeWriteMarker = "INSERT INTO kaname.resource_parent_edge" // EdgeProducerCall — имя экспортированной функции-производителя. EdgeProducerCall = "UpsertTx" // EdgeProducerDir — каталог пакета-производителя, ОТ КОРНЯ своего модуля // (было `services/iam/internal/repo/kaname/pg/resource_mirror`). EdgeProducerDir = "internal/repo/kaname/pg/resource_mirror" // EdgeProducerImport — хвост пути импорта. В самостоятельном модуле // службы совпадает с каталогом (расхождение, из-за которого монорепо // нёс ДВЕ константы, было следствием сегмента `services/iam`, которого // у своего модуля нет). EdgeProducerImport = EdgeProducerDir )
const ( // MigrationsDirRel — дом миграций службы. MigrationsDirRel = "internal/migrations" // AppliedModelRelPath — модель, которую ПРИМЕНЯЕТ решение о доступе. // // Каноническая копия (`proto/kaname/cloud/iam/v1/fga_model.fga`) сюда // намеренно НЕ подставляется: две копии держит байт-идентичными своя цель, а // разбор обязан читать ту, которая ИСПОЛНЯЕТСЯ. AppliedModelRelPath = "internal/authzmodel/fga_model.fga" )
const ( // IdentityGrowthCollectorFile — где объявлено семейство величин. IdentityGrowthCollectorFile = "internal/observability/metrics/identity_growth_collector.go" // IdentityGrowthReadersFile — где живут правила оповещений службы. IdentityGrowthReadersFile = "docs/engineering/components/32-observability.md" )
const ( // ResourceMirrorTable — зеркало каталога ресурсов. ResourceMirrorTable = "kaname.resource_mirror" // MirrorReferenceLane — каталог ЭТАЛОННОЙ полосы: путь, по которому // регистрация от владельца ресурса доходит до строки зеркала. // // Переедет каталог — гейт объявит ОТКАЗ, а не промолчит: сверять «тем же // условием» станет не с чем. Правь эту константу тем же изменением, каким // двигаешь пакет. MirrorReferenceLane = "internal/repo/kaname/pg/resource_mirror/" )
const ( AxisContract = "контракт" AxisGoCode = "прод-код" AxisCatalogue = "каталог видов" AxisModel = "модель прав" )
Названия осей. Вынесены константами, потому что их называет и инъекция: ось, переименованная в одном месте из двух, дала бы пробу, утверждающую о другой.
const ( TokenClaimOwnNamespace = "kaname" TokenClaimForeignNamespace = "kacho" )
TokenClaimOwnNamespace / TokenClaimForeignNamespace — свой и чужой словарь.
const AcceptanceHistoryFloor = 2
AcceptanceHistoryFloor — глубина истории дома приёмок, ниже которой признак «правлено после вердикта» НЕВЫРАЗИМ.
Два коммита — минимум, при котором отметка строки состояния и отметка файла МОГУТ разойтись. При одном они равны у каждого документа, поэтому ветвь сравнения не исполняется ни разу, и её молчание не означает ничего.
const CatalogCheckTarget = "check-permission-catalog"
CatalogCheckTarget — имя цели Makefile, СВЕРЯЮЩЕЙ копии и ничего не пишущей. Ровно её обязан звать конвейер.
const CatalogLockKeyIdent = "CatalogLockKey"
CatalogLockKeyIdent — имя константы ключа.
const CatalogLockKeyValue = "kaname.module_catalog"
CatalogLockKeyValue — её значение (принимается и литералом).
const CatalogSyncTarget = "sync-permission-catalog"
CatalogSyncTarget — имя цели Makefile, ПЕРЕПИСЫВАЮЩЕЙ каталог прав из копии края. Ручная операция выпуска: конвейер её звать не вправе.
const DerivedIDPackage = "crypto/md5"
DerivedIDPackage — путь импорта, вычисляющий дайджест.
const EmitSubjectChangeSelector = "EmitSubjectChangeEvent"
EmitSubjectChangeSelector — имя метода порта, которым производится строка очереди смены субъекта.
const ExclusionEdgeStripHome = "PRO-Robotech/kacho:gateway/internal/principalmeta/credential_strip.go"
ExclusionEdgeStripHome — дерево и файл, где живёт ВТОРАЯ половина построения.
const ExclusionGuideRel = "INSTALL.md"
ExclusionGuideRel — страница установки: то, что читает оператор.
const ExclusionReaderDeclFileRel = "internal/presentedcred/reader.go"
ExclusionReaderDeclFileRel — файл, ОБЪЯВЛЯЮЩИЙ обёртку.
Его собственные определения вызовами не являются: объявление без вызывающего механизма не даёт — ровно тот класс, ради которого предок отделял объявление снятия от его вызовов.
const ExclusionReaderDirRel = "internal/presentedcred"
ExclusionReaderDirRel — не-тестовый код читателя предъявленного удостоверения.
const ExclusionRefuseFunc = "refuse"
ExclusionRefuseFunc — имя конструктора отказа читателя.
const FingerprintSourceRel = "services/iam/internal/repo/kaname/pg/scalegrid/fingerprint.go"
FingerprintSourceRel — объявление предмета замера, из которого ВЫВОДИТСЯ объём этого разбора.
Координата дана ОТ КОРНЯ ДЕРЕВА ПЛАТФОРМЫ, как и всё, что резолвится `treeposture`: приставка снимается самим резолвом, когда модуль стоит самостоятельным клоном. Своя, «модульная» форма здесь была бы вторым написанием одной координаты — а сам предмет замера объявляет каталоги именно в этой форме, и разбор обязан читать ту же.
const GeneratedStubsPrefix = "pkg/api/"
ScanClassRuleDeclarations — объявления правила «класс из имени» в одном исходнике, с координатой каждого.
Неразбираемый исходник отдаёт признак, а не пустой перечень: «объявлений ноль» иначе означало бы и «их нет», и «разбор не состоялся». GeneratedStubsPrefix — каталог сгенерированных стабов: правило, найденное там, принадлежало бы генератору, а не дереву.
const InstallGuideSuffix = "INSTALL.md"
exportCopyMarker — по чему строка документа опознаётся как процедура выгрузки. Это мета-команда оболочки psql, и в прозе она не встречается: у разбора нет риска принять за процедуру объяснение процедуры. InstallGuideSuffix — по чему инструкции обновления опознаются в составе дерева.
const JobsConfigTypeName = "JobsConfig"
JobsConfigTypeName — структура, чьи поля суть секции фоновых заданий.
const JobsSelectorName = "Jobs"
JobsSelectorName — поле, через которое корень добирается до секций.
const ManifestLoaderDir = "internal/manifest"
ManifestLoaderDir — прод-файлы загрузчика манифеста. Гейт читает их как ТЕКСТ дерева: импортировать пакет отсюда нельзя (правило видимости `internal` тут ни при чём — импорт завёл бы зависимость гейта от предмета, который он судит).
const MirrorDivergenceFunc = "Divergence"
MirrorDivergenceFunc — имя читателя, чей вызывающий здесь стережётся.
const MirrorDivergencePkgSuffix = "/repo/kaname/pg/resource_mirror"
MirrorDivergencePkgSuffix — хвост пути пакета-читателя разности.
const ModuleSetPkgRel = "internal/authzmap"
ModuleSetPkgRel — каталог пакета, объявляющего закрытую таблицу типов.
const ModuleSetVarName = "objectTypes"
ModuleSetVarName — имя переменной, чей составной литерал разбирается.
const RoleGrantOrphanTable = "kaname.role_grant_orphan"
RoleGrantOrphanTable — куда обязано переселяться снятое не-автором.
const RoleRuleRefTable = "kaname.role_rule_ref"
RoleRuleRefTable — вторая проекция того же объявления: каждый объявленный сегмент правила (kacho#1030). Предмет у таблиц разный, а требование к автору — одно.
const RoleRuleVerbsSentinel = "ErrRoleRuleVerbsRetired"
RoleRuleVerbsSentinel — имя сентинела, которым пред-разборная проверка отвергает снятый ключ. Объявлено ЗДЕСЬ, потому что гейт живёт в общем пакете, а сентинел — в `internal/manifest`, закрытом правилом видимости Go. Что имя не разошлось с продуктом, утверждает сам гейт: ноль возвратов на живом дереве — находка, а не молчание.
const RoleScopeChainTable = "resource_parent_edge"
RoleScopeChainTable — таблица звеньев цепи.
const RoleScopeChainType = "iam_role"
RoleScopeChainType — тип объекта модели прав, чью цепь областей стережёт гейт.
const RoleVerbTable = "kaname.role_verb"
RoleVerbTable — проекция «роль → тип объекта × глагол».
const RoleVerbWriterLayer = "/internal/repo/"
RoleVerbWriterLayer — слой, которому принадлежит SQL проекции. Писатель вне него — находка, даже если он один.
const SeedCensusFrozenBucket = "ПРЕДМЕТ: свод и миграции"
SeedCensusFrozenBucket — ведро, которому ноль НЕДОСТИЖИМ by construction: применённая миграция посеяла прежнее написание и правке не подлежит (ban #5), а переводящая обязана его назвать, чтобы найти строку.
Имя объявлено здесь ОДИН раз и сверяется с тем, что печатает предикат: ведро, переименованное у предиката и не переименованное здесь, дало бы «его нет», то есть отключило бы проверку ниже молча.
const SelfFlushSetHome = "PRO-Robotech/kacho:gateway/internal/middleware/authz.go"
SelfFlushSetHome — дерево и файл, где вторая полоса живёт.
const SelfFlushSetName = "subjectChangingFQNs"
SelfFlushSetName — имя набора самосброса У КРАЯ.
Объявлено здесь, хотя предмета в этом дереве нет: имя есть КООРДИНАТА второй полосы, и без неё текст находки не сказал бы читателю, куда идти. Пустой результат поиска по нему — не находка, а измеренное отсутствие второй стороны, и гейт называет его отдельной строкой переписи.
const SubjectChangeProducerRootRel = "internal/apps/kaname/api"
SubjectChangeProducerRootRel — каталог use-case владельца прав.
Каталог СЛОЯ, а не перечень файлов: слой — единица архитектуры службы, и он не стареет вместе с деревом. Переедет слой — обход опустеет, и гейт откажет, а не смолчит.
const TrunkBranch = "main"
TrunkBranch — ствол, чей вердикт остаётся без читателя.
const TrunkHolderJob = "trunkverdict"
TrunkHolderJob — идентификатор задания, которое его зовёт.
const TrunkHolderScript = ".github/scripts/trunk-verdict-holder.sh"
TrunkHolderScript — держатель вердикта ствола. ОДНО объявление координаты: вторая копия разошлась бы с первой молча.
const TrunkRegisterRel = ".github/TRUNK-VERDICT.md"
TrunkRegisterRel — дом перечня. ОДНО объявление координаты.
const UseCaseAPIRootRel = "internal/apps/kaname/api"
UseCaseAPIRootRel — дом пакетов use-case в дереве МОДУЛЯ.
const WithdrawalApplierImportPath = "github.com/PRO-Robotech/kaname/internal/apps/kaname/moduleroles"
WithdrawalApplierImportPath — пакет применителя ролей модуля.
const WorkflowsDirRel = ".github/workflows"
WorkflowsDirRel — дом заданий конвейера, единственный род носителей провязки в этом дереве.
Variables ¶
var AcceptancePathCoordinateExemptions []DeadPathCoordinate
AcceptancePathCoordinateExemptions — ВЕДОМОСТЬ ПУСТА, и это её цель, а не её поломка. Заводя запись — назови номер задачи и предикат снятия рядом.
var AcceptanceProbeCoordinateExemptions []DeadProbeCoordinate
AcceptanceProbeCoordinateExemptions — ВЕДОМОСТЬ ПУСТА, и это её цель, а не её поломка. Заводя запись — назови номер задачи и предикат снятия в комментарии рядом.
var AuthorityResidueLedger = map[string]string{
"quota_reader": "право читать действующие пределы; глаголы, его требовавшие, сняты " +
"стадией S4, но само право ВЫДАНО применённой миграцией 0001_initial.sql " +
"(4 строки + группа-получатель) и ТРЕБУЕТСЯ двумя записями каталога прав, " +
"чья копия принадлежит краю платформы. Отзыв — новая миграция плюс перекат " +
"служб на новый идентификатор модели; предмет заведён задачей kaname#59. " +
"ПРЕДИКАТ СНЯТИЯ: объявления нет ни в одной копии модели — запись становится " +
"находкой в тот же прогон",
}
var ErrEmptyTraversal = errors.New("обход пуст: прочитано ноль файлов")
ErrEmptyTraversal — обход не принёс НИ ОДНОГО файла.
Отдельная ошибка, а не просто текст: вызывающий вправе отличить «прочитано ноль» от «читать не удалось», и эти два исхода требуют разных действий — первый чинят предметом гейта, второй условиями прогона.
var ExclusionCoPresenceTerms = []string{"presented", "forwarded"}
ExclusionCoPresenceTerms — слова, которыми сообщение отказа называет СОЧЕТАНИЕ двух форм.
Требуются ВСЕ: отказ, назвавший одну форму, — про неё одну. Сообщения отказа читателя английские, поэтому и слова английские.
var ExclusionWrapFuncs = []string{"UnaryOver", "StreamOver"}
ExclusionWrapFuncs — имена, которыми читатель НАКРЫВАЕТ пару звеньев переданной личности. Обе полосы вызова: одиночная и потоковая.
var MirrorWriteVerbs = []struct { Verb string Introduces bool }{ {"INSERT INTO " + ResourceMirrorTable, true}, {"MERGE INTO " + ResourceMirrorTable, true}, {"UPDATE " + ResourceMirrorTable, false}, {"DELETE FROM " + ResourceMirrorTable, false}, }
MirrorWriteVerbs — глаголы записи. Чтение в перечень не входит намеренно: читателей у зеркала десятки, все законны, и они служат близнецом, на котором разбор обязан молчать.
Introduces — вводит ли оператор НОВУЮ строку. Предмет условия есть только у вводящих: правка существующей строки нового типа не заводит, а снятие тем более. Требовать сверки у них значило бы требовать её там, где сверять нечего.
var ModuleSetSurfaceExts = []string{".mdx", ".md", ".proto"}
ModuleSetSurfaceExts — расширения файлов поверхности.
var ModuleSetSurfaces = []string{"docs/content", "proto/kaname/cloud/iam"}
ModuleSetSurfaces — КЛИЕНТСКИЕ поверхности: то, что читает арендатор.
Инженерные записки (`docs/engineering`) сюда НЕ входят, и это решение, а не пропуск: их предмет — реализация, а не обещание клиенту. Шапка функции членства в монорепо чинилась руками ровно по этой границе.
var NamedVerbScenarios = []string{"04", "04a", "18", "18a", "19", "19a"}
NamedVerbScenarios — шесть сценариев, чья проверка полноты и есть содержание отсрочки. Перечень ЗАКРЫТ и выписан: он приезжает из приёмки `#1090`, а не из дерева, и выводить его неоткуда — проб этих сценариев в дереве ноль by construction, то есть вывод из дерева дал бы пустой перечень и гейт, которому нечего требовать.
var PathCoordinateHomeShape = regexp.MustCompile(
`^([A-Za-z0-9][A-Za-z0-9._-]*/[A-Za-z0-9][A-Za-z0-9._-]*)(?:@([0-9a-fA-F]{7,40}))?$`)
PathCoordinateHomeShape — форма НАЗВАННОГО ДОМА: `<владелец>/<репозиторий>` и, необязательно, `@<ревизия>`. Ревизия только шестнадцатеричная и не короче семи знаков: произвольная строка после `@` сделала бы домом любую опечатку.
var ProbeCoordinateHomeShape = regexp.MustCompile(
`^([A-Za-z0-9][A-Za-z0-9._-]*/[A-Za-z0-9][A-Za-z0-9._-]*)(?:@([0-9a-fA-F]{7,40}))?$`)
ProbeCoordinateHomeShape — форма НАЗВАННОГО ДОМА: `<владелец>/<репозиторий>` и, необязательно, `@<ревизия>`. Ревизия — только шестнадцатеричная и не короче семи знаков: короткая или произвольная строка после `@` сделала бы домом любую опечатку.
var ProbeCoordinateShape = regexp.MustCompile(`^(Test|Fuzz|Benchmark|Example)[A-Za-z0-9_]{2,}$`)
ProbeCoordinateShape — форма имени пробы Go. Три знака минимум после вида: голое `Test` резолвилось бы префиксом ко всему дереву.
var RoleProjectionTables = []string{RoleVerbTable, RoleRuleRefTable}
RoleProjectionTables — таблицы, у каждой из которых автор обязан быть один.
var RoleScopeChainTierSources = []string{"account_id", "project_id"}
RoleScopeChainTierSources — ярусные столбцы, из которых звено роли берётся ЗАКОННО. Перечень закрытый и короткий by construction.
Functions ¶
func AcceptanceDocsOfTree ¶ added in v0.2.0
AcceptanceDocsOfTree — приёмки, живущие в каталоге приёмок службы. Перечень ВЫВОДИТСЯ обходом, а не выписывается.
Порт сужен до posture этого дерева: монорепо держало приёмки НЕСКОЛЬКИХ служб под `services/*/docs/engineering/acceptance/`, а самостоятельный клон службы несёт СВОЙ единственный каталог прямо у корня — `docs/engineering/acceptance/`. Сужение измерено, а не предположено: в дереве продукта второго дома приёмок не было никогда (§«У приёмки домов ДВА» — второй дом был именно этот, iam-only).
func AdjudicateCarriedLedger ¶ added in v0.2.0
func AdjudicateCarriedLedger( ledgerPath string, rows []CarriedLedgerRow, sections map[string]CarriedLedgerSection, treeHas func(string) bool, inScope func(string) bool, mustBeNamed []string, ) []string
AdjudicateCarriedLedger — что не так с ведомостью относительно дерева.
treeHas — состав дерева; inScope — координата принадлежит СВОЕМУ репозиторию и подлежит суждению (кросс-репо путь пропускается обеими проверками — ни полнотой, ни самоистечением: этот гейт не может судить чужой репозиторий); mustBeNamed — координаты, которые ведомость обязана назвать.
func AdjudicateSeedCensus ¶ added in v0.3.0
func AdjudicateSeedCensus(decl SeedCensusDeclaration, rep SeedCensusReport) []string
AdjudicateSeedCensus сверяет объявленное с произведённым ПО КАЖДОМУ ведру предиката. Ведро, которое предикат напечатал, а объявление не называет, — находка: иначе новое ведро уехало бы из-под наблюдения молча.
ВТОРАЯ ПОЛОВИНА — АНТИМАСКА, И БЕЗ НЕЁ ПЕРВАЯ НИЧЕГО НЕ СТОИТ ¶
Предикат готовности перехода (§7-П2 приёмки) звучит «живое ведро даёт ноль». Ноль там наступает ДВУМЯ путями, и они неотличимы по самому числу: переход состоялся — либо обход ослеп (литерал переписан, популяция сузилась, ревизия не та). Поэтому здесь проверяется ВТОРАЯ величина: замёрзшее ведро обязано быть НЕПУСТЫМ. Оно доказывает, что обход всё ещё находит написание там, где ban #5 держит его вечно, — то есть что ноль живого есть вердикт, а не молчание прибора.
func AlertExpressionsIn ¶ added in v0.3.0
AlertExpressionsIn — тела выражений `expr:` правил оповещения.
Берётся ТОЛЬКО исполняемая часть: однострочное выражение целиком либо блок, введённый `|`, до первого поля того же или меньшего отступа. Комментарии снимаются — иначе имя ряда, УБРАННОГО из выражения и оставшегося в объяснении, продолжало бы считаться читателем.
func ApplierPortVerbDeletesTheRoleRow ¶ added in v0.2.0
ApplierPortVerbDeletesTheRoleRow — предикат оси 1: удаляет ли метод порта СТРОКУ РОЛИ. Второе значение — почему, дословно для текста находки.
func AuditAcceptanceEditsAfterVerdict ¶ added in v0.2.0
func AuditAcceptanceEditsAfterVerdict(root, dir string) ([]AcceptanceEditFinding, AcceptanceEditCensus, error)
AuditAcceptanceEditsAfterVerdict — вердикт о доме приёмок.
func AuditDeferredWork ¶ added in v0.3.0
func AuditDeferredWork(root string) ( findings []treehygiene.DeferralFinding, census treehygiene.DeferralCensus, err error)
AuditDeferredWork обходит дерево под root общим разбором фундамента, связав его с видами вычитания ЭТОГО дерева.
Связывание живёт здесь, в ОДНОМ месте, и это несущее: инъекция обязана гонять ту же функцию, что гейт. Раздай мы виды по вызывающим — каждая проба связывала бы их заново, и доказанной оказалась бы не та связка, которая судит дерево.
Возвращает находки и перепись осмотренного: «ноль находок» обязано быть отличимо и от «ноль прочитанного», и от «прочитал не там». Вердикт — падать ли и с каким текстом — выносит гейт: текст отказа обязан называть исходы, принятые в ЭТОМ дереве.
func AuditExclusionForm ¶ added in v0.3.0
func AuditExclusionForm(in ExclusionFormInput) ([]ExclusionFormFinding, ExclusionFormCensus, error)
func AuditMachineryClaims ¶ added in v0.3.0
func AuditMachineryClaims(f MachineryFacts) ([]MachineryClaim, MachineryCensus)
AuditMachineryClaims — заявления комментариев контрактов, которым в дереве нечего назвать. Пусто = норма.
Возвращает находки и перепись раздельно: перепись — самостоятельное утверждение, и пустой обход обязан быть отличим от чистого дерева.
func AuditNamedInjections ¶
func AuditNamedInjections(root string) ([]InjectionFinding, InjectionCensus, error)
AuditNamedInjections обходит дерево модуля от root и возвращает находки с переписью.
Обращения к пробе здесь нет намеренно: разбор, роняющий её изнутри, инъекции не поддаётся — синтетическому дереву некуда было бы подать вход.
func AuditPayloadForms ¶ added in v0.3.0
AuditPayloadForms — объявленные формы с примерами; гейт предъявляет каждую.
func AuditRoleOperationResponseState ¶ added in v0.2.0
func AuditRoleOperationResponseState( opts RoleOperationResponseStateOptions, log io.Writer, ) ([]RoleOperationResponseStateFinding, RoleOperationResponseStateCensus, error)
AuditRoleOperationResponseState выносит вердикт о дереве.
func AuthorVerbOf ¶ added in v0.2.0
AuthorVerbOf — оператор, которым строка ВНОСИТСЯ.
func BaselineMigrationOf ¶ added in v0.2.0
BaselineMigrationOf — применённая базовая миграция: первая в порядке применения. Порядок goose лексикографический, поэтому перечень уже отсортирован вызывающим.
func CallsMakeTarget ¶ added in v0.2.0
CallsMakeTarget — исполняемое тело шага (`run:` без строк оболочечных комментариев) зовёт названную цель формой `make <цель>` либо `make -C <каталог> <цель>` (в этом репозитории цель лежит в корневом Makefile, поэтому `-C` без аргумента либо `-C .` — тоже законная форма).
func CollectPredicateConcats ¶ added in v0.3.0
func CollectPredicateConcats(files []ReadPathFile, read func(abs string) ([]byte, error)) ( []ConcatFinding, ConcatCensus, error, )
CollectPredicateConcats — находки и объём по перечню файлов.
read подаётся вызывающим: инъекция кормит разбор синтетикой, не трогая диск.
func ConstStringValue ¶ added in v0.2.0
ConstStringValue — значение строковой константы, объявленной в исходнике.
Возвращает признак находки отдельно от значения: «объявления нет» и «объявлено пустым» — разные состояния, и схлопывать их нельзя.
func CountRelations ¶ added in v0.3.0
CountRelations — сколько отношений объявлено всего.
func DeclaredContexts ¶ added in v0.4.0
DeclaredContexts — обязательные контексты, ОБЪЯВЛЕННЫЕ перечнем (первая колонка таблицы контекстов).
Живут они не в дереве, а в настройках ветки, поэтому перечень их копирует — и копия обязана быть сверяема. Сверку делает вызывающий (это сеть), а не эта функция; здесь — только то, что объявлено.
func DeclaredProbesOfTree ¶ added in v0.2.0
DeclaredProbesOfTree — имена всех проб дерева, объявленных в отслеживаемых файлах проб.
func DeclaresSelfFlushSet ¶ added in v0.3.0
DeclaresSelfFlushSet — ОБЪЯВЛЯЕТ ли файл набор самосброса.
Судится УЗЕЛ ОБЪЯВЛЕНИЯ, а не вхождение имени, и это не педантизм — цена измерена на самом гейте. Первая редакция искала имя ПОДСТРОКОЙ по всем файлам Go и на первом же прогоне после посадки нашла… собственное объявление координаты второй полосы (`SelfFlushSetName = "subjectChangingFQNs"` строкой выше). То есть проверка покраснела на своём же объяснении и объявила, что вторая полоса приехала в это дерево, — ровно тот класс, что ловит проверку, судящую СЛОВО вместо УЗЛА.
Узел снимает это by construction: строковый литерал, имя типа, комментарий и сообщение об отказе объявлением не являются, а `var subjectChangingFQNs = …` является — и только оно.
func DeferralSkips ¶ added in v0.3.0
func DeferralSkips() []treehygiene.DeferralSkip
DeferralSkips — объявленные виды вычитания; гейт сверяет их предмет.
Отдаётся копия перечня: он есть предмет пробы, и проба не вправе его двигать.
func ExecutableRunBodies ¶ added in v0.2.0
ExecutableRunBodies — тела `run:` без строк оболочечных комментариев.
func FoldSeededServiceAccounts ¶ added in v0.2.0
func FoldSeededServiceAccounts(ordered []string, bodies map[string]string) ( alive map[string]SeededServiceAccount, unknownForms []string, stmtsTouched int, )
FoldSeededServiceAccounts складывает посев по цепочке: вставка заводит строку, удаление её снимает. Возвращает живые строки, находки формы и объём осмотренного.
Формы записи названы ЯВНО, и незнакомая — находка, а не молчание: форма, о которой разбор не знает, уводит предмет из-под наблюдения, ничего не нарушив (§«Гейт на класс» п. 7).
Разбор НЕ понимает PL/pgSQL-блоков `DO $$ ... $$` — наивное деление на `;` внутри такого блока даёт много фрагментов, большинство отбрасываются (не называют таблицу или несут не INSERT/UPDATE/DELETE), но статический `DELETE FROM kaname.service_accounts WHERE name IN (...)` внутри такого блока распознаётся корректно, потому что сам оператор синтаксически цел между соседними `;`. Динамическое снятие через переменную (`WHERE name = ANY(var)`) разбором НЕ узнаётся — это названо явно шапкой такой миграции продукта (`20260909202745_module_identities_leave_the_baseline.sql`): имена стоят литералами в статическом операторе именно для того, чтобы этот разбор их видел.
func HasModuleSetSurfaceExt ¶ added in v0.3.0
HasModuleSetSurfaceExt — файл поверхности ли это.
func HomeEnvVar ¶ added in v0.3.0
HomeEnvVar — имя переменной, которой оператор называет копию дома явно.
func HomeRef ¶ added in v0.3.0
HomeRef — ссылка, по которой судится дом. Ствол, если ревизия не названа.
func HomeTree ¶ added in v0.3.0
HomeTree — (путь, причина). Пустой путь означает: дома нет, и это ТРЕТЬЯ категория, а не вердикт о документе.
func IdentityGrowthMetricNamesIn ¶ added in v0.3.0
IdentityGrowthMetricNamesIn — имена рядов в исходнике коллектора.
Комментарии снимаются первыми: файл коллектора подробно объясняет, почему рядов два, и называет их имена в прозе. Разбор сырого текста засчитал бы объявлением упоминание в разборе.
func InvocationsOf ¶ added in v0.2.0
InvocationsOf — сколько тел `run:` действительно зовут названный скрипт.
func IsGeneratedFile ¶ added in v0.2.0
IsGeneratedFile — узел разбора несёт отметку `Code generated … DO NOT EDIT.`
func IsModuleSetSurfaceFile ¶ added in v0.4.0
IsModuleSetSurfaceFile — лежит ли файл на КЛИЕНТСКОЙ ПОВЕРХНОСТИ, перечни которой сверяются с набором.
func IsSubjectChangeProducerFile ¶ added in v0.3.0
func IsVerbClassRuleSource ¶ added in v0.4.0
IsVerbClassRuleSource — файл, в котором правило «класс глагола» вправе быть объявлено. Тестовый корпус вычитается намеренно: фикстура инъекции обязана уметь написать форму дефекта, иначе гейт нельзя проверить.
func JoinGrants ¶ added in v0.3.0
func JoinGrants(g []RelationGrant) string
JoinGrants — различные пары «тип#отношение», по порядку.
func JoinRelationSet ¶ added in v0.3.0
JoinRelationSet — отношения одного типа, по порядку.
func JudgeAuthorityResidue ¶ added in v0.3.0
func JudgeAuthorityResidue(corpus, excused map[string]string) (AuthorityResidueCensus, []AuthorityResidueFinding)
JudgeAuthorityResidue судит корпус: ключ — путь в дереве, значение — текст.
excused — ведомость отношений модели, чьё снятие объявлено чужим предметом (`AuthorityResidueLedger`). Передаётся ПАРАМЕТРОМ, а не берётся из пакета: инъекция подаёт сюда синтетику, и судья, ходящий за ведомостью сам, на ней бы не работал. Сверка идёт в ОБЕ стороны — отношение вне ведомости есть находка, запись ведомости без предмета есть находка тоже.
Вид оси выбирается по имени файла: `.go` (не `_test.go`) — прод-код, `.proto` — контракт, `.fga` — модель прав. Файл, не попавший ни под одну, не читается вовсе и в перепись не идёт: молчание о нём честнее, чем ноль.
Возвращает перепись и находки; находок ноль при непустой переписи — годно.
func JudgeCensusFixtures ¶ added in v0.2.0
func JudgeCensusFixtures(byDir map[string][]CensusFileFacts) []string
JudgeCensusFixtures выносит вердикт по КАТАЛОГАМ: ключ — каталог тестового пакета, значение — факты его файлов.
func JudgeTargetWiringFaults ¶ added in v0.3.0
func JudgeTargetWiringFaults(w JudgeTargetWiring) []string
JudgeTargetWiringFaults — находки по ОБЕИМ сторонам провязки.
Сверка идёт в обе стороны намеренно. Односторонняя («объявлена — обязана быть звана») пропускала бы обратный случай: носитель зовёт цель, которой рецепт не объявляет, — шаг молча зеленеет на несуществующей цели, потому что `make` такого имени не знает и... отказывает; а под `|| true` или в подстановке не отказывает вовсе. Это провязка в пустоту, и она хуже отсутствующей: выглядит исполненной.
func MakefileDeclaresTarget ¶ added in v0.2.0
MakefileDeclaresTarget — объявлена ли цель в тексте Makefile.
func MissingGrantedRelations ¶ added in v0.3.0
func MissingGrantedRelations(grants []RelationGrant, model map[string]map[string]bool) []string
MissingGrantedRelations — выдачи, у которых в модели нет типа либо отношения.
func MissingScenarioProbes ¶ added in v0.2.0
MissingScenarioProbes — сценарии из закрытого перечня, у которых в дереве нет ни одной пробы.
Принимается перечень ИМЁН функций, а не текст файлов: подстрока `TestMODRL04` стои́т и внутри `TestMODRL04a`, и гейт, судящий вхождение, зачёл бы одну пробу за две. Имя сравнивается с ПРЕФИКСОМ и следующим за ним символом.
func ModuleIdentitiesSeededOutsideTheBaseline ¶ added in v0.2.0
func ModuleIdentitiesSeededOutsideTheBaseline(alive map[string]SeededServiceAccount, baseline string) []string
ModuleIdentitiesSeededOutsideTheBaseline — судья, отделённый от дерева ради инъекции. Находка — живая МОДУЛЬНАЯ учётка, чью строку завела не базовая миграция.
func NamedVerbFormFinding ¶ added in v0.2.0
NamedVerbFormFinding — РЕШЕНИЕ гейта одной функцией: сценарии, оставшиеся без пробы, когда форма уже не отвергается.
Объявлено здесь, а не внутри гейта, ровно затем, чтобы инъекция гоняла ТОТ ЖЕ предикат, что и прогон дерева: второй, написанный в пробе «по образцу», разошёлся бы с первым молча — и разошёлся бы именно там, где расхождение не видно, потому что оба отвечают одинаково на сегодняшнем входе.
Пустой результат означает молчание, и у него ДВЕ законные причины: форма отвергается (`sentinelReturns > 0`) либо она вернулась вместе со своей проверкой (пробы найдены). Различать их вызывающему не нужно — обе законны.
func OutsideTraversal ¶ added in v0.4.0
OutsideTraversal — путь ВНЕ области обхода: система контроля версий, оснастка агента, документация, вендоренное и артефакты сборки.
Предикат один на дерево и объявлен здесь: прежде он жил в файле пробы соседнего семейства, и всякий следующий обход либо звал чужую пробу, либо заводил свою копию перечня. Копии перечня расходятся молча — и расходится та, которую не считали.
func OwnHomeOfTree ¶ added in v0.2.0
OwnHomeOfTree — дом ЭТОГО дерева в форме `владелец/репозиторий`, выведенный из пути модуля в `go.mod`.
Нужен НЕ ядру, а гейту: ядро судит поданные значения и про дома знает только то, что дом непустой — чужой. Свой дом, названный в приёмке чужим, ядру неотличим от настоящего чужого, и именно эту дыру закрывает сторожевая ось гейта — она сверяет перепись домов с этим значением.
Путь модуля берётся у `go.mod`, а не собирается литералом: литерал разошёлся бы с переименованием репозитория молча.
func ParseCarriedCoordinateLedger ¶ added in v0.2.0
func ParseCarriedCoordinateLedger(body string) ( []CarriedLedgerRow, map[string]CarriedLedgerSection, CarriedLedgerCensus, )
ParseCarriedCoordinateLedger разбирает ведомость.
func PathCoordinatesIn ¶ added in v0.4.0
func PathCoordinatesIn(doc, body string) ([]PathCoordinate, PathScanBorders)
PathCoordinatesIn разбирает документ: возвращает СУДИМЫЕ координаты и то, что разбор видел, но судить не стал.
func PathSpecResolves ¶ added in v0.4.0
PathSpecResolves — путь-спецификация резолвится, когда в дереве есть её ГЛУБОЧАЙШИЙ ПРЕДОК БЕЗ МЕТАСИМВОЛА.
Судится каталог, а не соответствие шаблону: шаблон, которому сегодня не соответствует ничто, есть законный вердикт, а не мёртвый адрес.
func ProbeCoordinateResolves ¶ added in v0.2.0
ProbeCoordinateResolves — объявленное имя начинается с координаты. declared обязан быть отсортирован: имя с префиксом P сортируется не раньше P, поэтому кандидат ровно один и находится двоичным поиском.
func ProbeDeclaredInHome ¶ added in v0.3.0
ProbeDeclaredInHome — объявлена ли проба в названном доме на названной ссылке.
func ProdGoRoots ¶ added in v0.2.0
ProdGoRoots — верхнеуровневые каталоги дерева, несущие отслеживаемый не-тестовый Go-код. Выведены обходом, а не выписаны.
func ProductionGoFile ¶ added in v0.4.0
ProductionGoFile — не-тестовый файл Go внутри области обхода.
Отбор, который в этом дереве повторяется чаще прочих. Объявлен один раз по той же причине, что и `OutsideTraversal`: три копии «`.go`, не `_test.go`, не служебный каталог» разошлись бы на первом же новом исключении.
func PushesToTrunk ¶ added in v0.4.0
PushesToTrunk — идёт ли процесс по `push` в ствол.
func RelationsByType ¶ added in v0.3.0
RelationsByType — разбор DSL модели: тип → множество объявленных отношений.
Предикаты построчные и СТРОГИЕ: объявление типа занимает строку целиком, а объявление отношения начинается с ключевого слова. Готовая форма модели в JSON под эти строки не подпадает ни одной строкой.
func RemovalVerbsOf ¶ added in v0.2.0
RemovalVerbsOf — операторы, которыми строка СНИМАЕТСЯ либо правится.
Чтение (`SELECT … FROM`, `JOIN`) в перечень не входит намеренно: читатели у проекции законны и служат близнецом, на котором гейт молчит.
func RepoIdentity ¶ added in v0.3.0
RepoIdentity — идентичность рабочей копии: `owner/name` из `origin`. Пустая строка означает, что идентичность непроверяема.
func SQLCreateTableBody ¶ added in v0.2.0
SQLCreateTableBody — тело объявления таблицы, разобранное из НАКАТА (Up-секции без комментариев) миграции. sqlText — полный текст ФАЙЛА миграции (порт зовёт `migrations.MigrationUpSection` сам, чтобы не тянуть зависимость на пакет `migrations` из пакета `check` без нужды — вызывающий подаёт уже подготовленный текст наката).
func ScanApplierDeletes ¶ added in v0.2.0
func ScanApplierDeletes(path string, src []byte) (sites []ApplierDeleteSite, census ApplierDeleteCensus, err error)
ScanApplierDeletes разбирает один файл пакета применителя.
func ScanAuditPayloads ¶ added in v0.3.0
func ScanAuditPayloads(root string) (findings []AuditPayloadFinding, census AuditPayloadCensus, err error)
ScanAuditPayloads обходит ОТСЛЕЖИВАЕМОЕ дерево модуля и находит личные ключи в нагрузках журнала аудита.
Состав берётся из индекса git, а не выписывается: каталог, заведённый завтра, попадает под гейт в день появления.
func ScanCatalogWriteLocking ¶ added in v0.2.0
func ScanCatalogWriteLocking(files []CatalogSource) ([]CatalogWriteFinding, CatalogWriteCensus, error)
ScanCatalogWriteLocking разбирает состав прод-файлов и отвечает, какие единицы пишут строки каталога, не запирая его. Файлы группируются ПО ПАКЕТУ (каталогу).
func ScanClaimAssemblies ¶ added in v0.2.0
func ScanClaimAssemblies(path string, src []byte, prefix string, minKeys int) ( []ClaimAssembly, ClaimAssemblyCensus, error, )
ScanClaimAssemblies разбирает один файл и собирает места сборки состава.
prefix — префикс имени ключа состава; minKeys — сколько РАЗНЫХ ключей делают место сборкой.
func ScanClaimBuilderCalls ¶ added in v0.2.0
func ScanClaimBuilderCalls(path string, src []byte, builders map[string]bool) ( []ClaimBuilderCall, ClaimAssemblyCensus, error, )
ScanClaimBuilderCalls разбирает один файл и собирает вызовы сборщиков состава.
func ScanClassRuleDeclarations ¶ added in v0.3.0
func ScanDerivedIDDeclarations ¶ added in v0.2.0
func ScanDerivedIDDeclarations(path string, src []byte) (sites []DerivedIDImportSite, census DerivedIDCensus, err error)
ScanDerivedIDDeclarations разбирает один файл и возвращает импорты `crypto/md5` вместе с объёмом осмотренного.
func ScanFixedRefusalTexts ¶
func ScanFixedRefusalTexts(root string, files []string) (RefusalTextCensus, []RefusalTextFinding, error)
ScanFixedRefusalTexts разбирает названные файлы и называет конструкции статуса на полосах чужой причины, чей текст не доказан фиксированным.
root служит только для печати координат. Пустой обход ошибкой ЗДЕСЬ не объявляется: пустоту судит вызывающий — у гейта дерева и у пробы инъекции законные пороги пустоты разные.
func ScanHistoryQuestions ¶ added in v0.3.0
func ScanHistoryQuestions(corpus map[string][]byte, trunkRefs []string) ([]HistoryQuestion, HistoryCensus)
ScanHistoryQuestions — все вопросы об истории в названном корпусе.
Корпус приходит ГОТОВЫМ (`rel -> содержимое`), а не читается отсюда: так инъекция подаёт разбору свой вход, не заводя второго читателя дерева.
trunkRefs — имена, которые в этом дереве ОБЪЯВЛЕНЫ стволом. Перечень — параметр, а не константа: иначе ось «ствол назван» нечем подать синтетике, и она осталась бы без доказательства падучести.
func ScanKeyAlgorithmConstraints ¶ added in v0.3.0
func ScanKeyAlgorithmConstraints(path, upSection, column string) ( found []AlgorithmConstraint, dropped []string, census AlgorithmDictionaryCensus, )
ScanKeyAlgorithmConstraints разбирает один файл миграции.
column — имя столбца, чей словарь стережётся.
func ScanMigrationRoleInserts ¶ added in v0.3.0
func ScanMigrationRoleInserts(path string, src []byte) (sites []MigrationRoleSite, census MigrationRoleCensus)
ScanMigrationRoleInserts извлекает имена ролей, вставляемых миграцией.
Блок — от `INSERT INTO kaname.roles` до первой строки, оканчивающейся `;`. Привязка к блоку обязательна: тот же образец идентификатора встречается во вставках в ЧУЖИЕ таблицы (селекторы, выдачи служебным учёткам), и предикат без привязки мерил бы упоминания идентификатора, а не строки роли.
Форм записи имени ДВЕ, и обе законны ¶
… VALUES ('rol' || substr(md5('iam.account.admin'),1,17), …, 'iam.account.admin', …)
INSERT INTO kaname.roles (id, account_id, name, …) VALUES ('rol6307…', NULL, 'iam.account.admin', …)
Первая — рукописная: идентификатор ВЫВОДИТСЯ из имени, поэтому имя стоит аргументом деривации и берётся оттуда. Вторая пришла со сводом миграций iam 2026-09-04: свод написан `pg_dump`, тот подставляет уже вычисленный идентификатор и перечисляет колонки явно — деривации в нём нет НИ ОДНОЙ, и разбор, знавший только её, извлекал ноль имён при 48 блоках. Это не находка и не молчание, а невидимость: каждая вставленная роль оказалась вне наблюдения.
Вторая форма читается по ПЕРЕЧНЮ КОЛОНОК, а не по позиции: позиция колонки `name` в дампе не гарантирована ничем, кроме самого перечня, и выписать её числом значило бы завести второе место об одном предмете.
Блок, из которого имя извлечь не удалось, считается ОТДЕЛЬНО (MigrationRoleCensus.Unreadable) и молча не пропускается: неизвестная форма обязана быть видна, иначе следующая сделает то же, что сделал дамп.
func ScanModuleSetEnumerations ¶ added in v0.3.0
func ScanModuleSetEnumerations(rel, body string, modules []string) ([]ModuleSetFinding, ModuleSetScan)
func ScanObjectTypeUses ¶ added in v0.3.0
ScanObjectTypeUses — сколько раз поле типа объекта ЧИТАЕТСЯ и где ему ПРИСВАИВАЮТ.
Обе величины вместе: «присваиваний ноль» при нуле чтений означает, что распознаватель не видит поля вовсе, и тогда вердикт о присваиваниях не значит ничего.
func ScanRawOperationsRepo ¶ added in v0.3.0
func ScanRawOperationsRepo(root string) ([]RawOperationsRepoSite, TerminalRefusalCensus, error)
ScanRawOperationsRepo обходит отслеживаемое дерево и находит вызовы сырого конструктора репозитория операций, отмечая обёрнутые.
func ScanRoleDeletes ¶ added in v0.2.0
func ScanRoleDeletes(path string, src []byte) (sites []RoleDeleteSite, census RoleDeleteCensus, err error)
ScanRoleDeletes разбирает один файл Go.
func ScanRoleScopeChain ¶ added in v0.2.0
func ScanRoleScopeChain(path, src string) (found []RoleScopeChainSite, census RoleScopeChainCensus)
ScanRoleScopeChain разбирает один файл — SQL миграции либо прод-исходник Go.
func ScanRoleWithdrawalWiring ¶ added in v0.2.0
func ScanRoleWithdrawalWiring(path string, src []byte) (drive, mark []RoleWithdrawalSite, census RoleWithdrawalCensus, err error)
ScanRoleWithdrawalWiring разбирает один файл Go.
Возвращает две половины раздельно — приведение применителя в действие и производителя отзыва, — потому что находка есть их НЕСОГЛАСИЕ, а не любая из них. Сводит половины вызывающий.
func ScanSQLUpdates ¶ added in v0.2.0
ScanSQLUpdates разбирает один файл и собирает операторы правки названных таблиц.
func ScanTokenClaimForeignBrand ¶ added in v0.2.0
func ScanTokenClaimForeignBrand(path string, src []byte) ([]TokenClaimUse, TokenClaimCensus, error)
ScanTokenClaimForeignBrand разбирает один файл Go и возвращает употребления имени клейма из ЧУЖОГО словаря (namespace == TokenClaimForeignNamespace) в одной из четырёх законных позиций чеканки/чтения.
func ScenarioProbeName ¶ added in v0.2.0
ScenarioProbeName — имя пробы сценария в написании этого дерева.
func SeedScopeUnfit ¶ added in v0.2.0
func SeedScopeUnfit(ordered []string, alive map[string]SeededServiceAccount) string
SeedScopeUnfit — ПРЕДМЕТА нет. Отдельной функцией, а не тремя ветвями внутри пробы: способность гейта отличить «ноль находок» от «ноль прочитанного» проверяется инъекцией, а инъекция не может спросить `require`/`t.Fatalf` напрямую.
func SortedFuncNames ¶ added in v0.2.0
func SortedFuncNames(byFunc map[string]FunctionDatabaseCalls) []string
SortedFuncNames — имена разобранных функций для текста отказа.
func SplitAlgorithmValues ¶ added in v0.3.0
SplitAlgorithmValues делит значения словаря на алгоритмы и пустое.
Пустое выносится отдельно намеренно: оно означает «ключа нет», а не «любой алгоритм», и складывать его с алгоритмами значило бы объявить отсутствие ключа одним из них.
func SubjectChangeRosterTotal ¶ added in v0.3.0
SubjectChangeRosterTotal — сколько обращений объявляет перечень.
func TrackedPathsOfTree ¶ added in v0.4.0
TrackedPathsOfTree — отслеживаемые пути дерева. Перечень ВЫВОДИТСЯ обходом индекса git, а не выписывается: рукописный список разошёлся бы с деревом молча.
func TreeModulePath ¶ added in v0.2.0
TreeModulePath — путь модуля, чтобы импорт файла сопоставлялся с каталогом дерева. Читается из go.mod, а не выписывается.
Types ¶
type AcceptanceEditCensus ¶ added in v0.2.0
type AcceptanceEditCensus struct {
DocsRead int
NoStateLine []string
NoHistory []string
EditedAfter int
CarryingNote int
// HistoryDepth — сколько коммитов трогали дом приёмок, со ЗНАЧЕНИЕМ,
// обрезанным сверху на AcceptanceHistoryFloor.
//
// Величина несущая, а не справочная: признак «правлено ПОСЛЕ вердикта»
// есть СРАВНЕНИЕ двух отметок git, и в дереве с одним коммитом обе отметки
// совпадают у каждого документа BY CONSTRUCTION. Там EditedAfter равен нулю
// не потому, что приёмки не правили, а потому, что сравнивать нечего, — и
// без этой величины два состояния неотличимы.
//
// Обрезается намеренно: вопрос к ней один — «есть ли чему сравниваться», а
// полный счёт стоил бы обхода всей истории дома приёмок на каждом прогоне.
HistoryDepth int
}
AcceptanceEditCensus — объём осмотренного.
Величин ТРИ, и печатаются все: «приёмок N · правлено после вердикта M · из них с записью K». Одно число здесь скрывало бы ровно тот случай, ради которого гейт заведён — документ, который никто не правил, и документ, чью правку никто не назвал, дают одинаковый ноль находок.
func (AcceptanceEditCensus) String ¶ added in v0.2.0
func (c AcceptanceEditCensus) String() string
type AcceptanceEditFinding ¶ added in v0.2.0
type AcceptanceEditFinding struct {
File string
StateLine int
StateChangedAt int64
FileChangedAt int64
}
AcceptanceEditFinding — приёмка, правленая ПОСЛЕ объявления своего состояния, и не объявившая этого.
func (AcceptanceEditFinding) String ¶ added in v0.2.0
func (f AcceptanceEditFinding) String() string
type AlgorithmConstraint ¶ added in v0.3.0
type AlgorithmConstraint struct {
File string
Line int
// Name — имя ограничения: им же оно снимается, и по нему разбор понимает,
// какое объявление какое переобъявляет.
Name string
// Values — значения словаря в том виде, в каком они записаны, включая
// пустое.
Values []string
}
AlgorithmConstraint — объявление словаря алгоритма ограничением схемы.
type AlgorithmDictionaryCensus ¶ added in v0.3.0
type AlgorithmDictionaryCensus struct {
// Files — файлов миграций прочитано.
Files int
// Statements — объявлений ограничения с этим столбцом найдено (включая
// переобъявленные позднее).
Statements int
// Drops — снятий ограничения найдено.
Drops int
}
AlgorithmDictionaryCensus — объём осмотренного.
type ApplierDeleteCensus ¶ added in v0.2.0
ApplierDeleteCensus — объём осмотренного одним файлом.
type ApplierDeleteSite ¶ added in v0.2.0
type ApplierDeleteSite struct {
File string
Line int
// Kind — ось: `port-verb` либо `sql-literal`.
Kind string
// What — что именно найдено: имя метода либо начало литерала.
What string
}
ApplierDeleteSite — координата находки.
type AuditPayloadCensus ¶ added in v0.3.0
type AuditPayloadCensus struct {
Tracked int // элементов в индексе дерева
Read int // прочитано файлов Go
Parsed int // из них разобрано без ошибки
Sites int // мест построения нагрузки
SitesByForm map[string]int // форма → сколько мест
Keys int // ключей осмотрено
Files []string // файлы, где найдено хоть одно место
}
AuditPayloadCensus — объём осмотренного. Печатается всегда: «личных ключей нет» обязано быть отличимо от «ничего не разобрано».
func (AuditPayloadCensus) String ¶ added in v0.3.0
func (c AuditPayloadCensus) String() string
String — перепись одной строкой.
type AuditPayloadFinding ¶ added in v0.3.0
type AuditPayloadFinding struct {
Where string // путь:строка
Form string // какой формой он записан
Key string
Why string
}
AuditPayloadFinding — один личный ключ с координатой.
func (AuditPayloadFinding) String ¶ added in v0.3.0
func (f AuditPayloadFinding) String() string
type AuditPayloadKey ¶ added in v0.3.0
AuditPayloadKey — один ключ нагрузки с его строкой.
type AuditPayloadSite ¶ added in v0.3.0
type AuditPayloadSite struct {
Form string
Line int
Keys []AuditPayloadKey
}
AuditPayloadSite — одно место построения нагрузки.
func ParseAuditPayloadSites ¶ added in v0.3.0
func ParseAuditPayloadSites(path string, src []byte) ([]AuditPayloadSite, error)
ParseAuditPayloadSites разбирает ОДИН файл и находит места построения нагрузки со всеми ключами, записанными любой из объявленных форм.
Вынесено отдельной функцией с экспортом затем, чтобы предикат можно было предъявить синтетическому входу: на чистом дереве находок ноль, и без такого предъявления «ноль находок» было бы неотличимо от разбора, который ничего не ищет.
type AuditPersonalKey ¶ added in v0.3.0
type AuditPersonalKey struct {
// Key — ключ ДОСЛОВНО, как он стоит в литерале. Сверка точная: `token_id`
// не есть `token`, и подстрочное сравнение сделало бы находкой законный
// идентификатор.
Key string
// Why — чем именно ключ личен либо секретен. Текст уезжает в находку:
// проверка, не называющая причины, снимается следующим как непонятная.
Why string
}
AuditPersonalKey — один ключ, которому в нагрузке журнала аудита не место.
func AuditPersonalKeys ¶ added in v0.3.0
func AuditPersonalKeys() []AuditPersonalKey
AuditPersonalKeys — объявленный перечень; гейт сверяет его с деревом.
type AuthorityResidueCensus ¶ added in v0.3.0
type AuthorityResidueCensus struct {
// GoFiles — прод-файлов Go разобрано.
GoFiles int
// GoIdents — узлов-идентификаторов осмотрено.
GoIdents int
// Contracts — файлов контракта прочитано.
Contracts int
// ContractDecls — объявлений контракта осмотрено.
ContractDecls int
// Models — объявлений модели прав прочитано.
Models int
// Kept — прочтений законного соседа. Ноль здесь означает, что разбор не
// дошёл до остатка, и его вердикт недействителен.
Kept int
// Excused — прочтений отношения, снятие которого объявлено чужим предметом.
// Печатается рядом с находками: послабление, о котором не сказано числом,
// неотличимо от его отсутствия.
Excused int
// Unparsed — файлов Go, которые парсер не принял. Третья категория: это не
// «находок нет», а «о файле не известно ничего».
Unparsed []string
}
AuthorityResidueCensus — объём осмотренного.
Печатается ВСЕГДА и целиком: у проверки на отсутствие это единственное, чем «находок ноль» отличается от «прочитано ноль».
func (AuthorityResidueCensus) String ¶ added in v0.3.0
func (c AuthorityResidueCensus) String() string
type AuthorityResidueFinding ¶ added in v0.3.0
AuthorityResidueFinding — одна находка: где, по какой оси и что именно.
func (AuthorityResidueFinding) String ¶ added in v0.3.0
func (f AuthorityResidueFinding) String() string
type BoolWrapperCall ¶ added in v0.2.0
type BoolWrapperCall struct {
File string
Line int
Pair WrapperPair
}
BoolWrapperCall — одно употребление булевой половины из чужого пакета.
type CarriedLedgerCensus ¶ added in v0.2.0
type CarriedLedgerCensus struct {
Lines int
Sections int
Tables int
Rows int
RowsWithoutCoordinate int
}
CarriedLedgerCensus — объём осмотренного.
type CarriedLedgerRow ¶ added in v0.2.0
type CarriedLedgerRow struct {
Section string
Line int
Coordinate string
Outcome string
OutcomeCell string
}
CarriedLedgerRow — строка ведомости.
type CarriedLedgerSection ¶ added in v0.2.0
CarriedLedgerSection — раздел документа.
type CatalogSource ¶ added in v0.2.0
CatalogSource — один прод-файл на вход разбора. Инъекция подаёт синтетический состав, не трогая рабочую копию.
type CatalogWriteCensus ¶ added in v0.2.0
type CatalogWriteCensus struct {
Files int
Parsed int
Funcs int
Executors int
StringLiterals int
Comments int
TextMatches int
TextFiles int
Executed int
ExecutingFiles int
WriteUnits int
LockedUnits int
LockSites int
}
CatalogWriteCensus — объём осмотренного.
type CatalogWriteFinding ¶ added in v0.2.0
CatalogWriteFinding — координата находки: писатель без замка.
type CensusFileFacts ¶ added in v0.2.0
CensusFileFacts — то, что гейт узнаёт об одном файле.
func CensusFactsOf ¶ added in v0.2.0
func CensusFactsOf(rel string, body []byte, producerPkg string) (CensusFileFacts, error)
CensusFactsOf разбирает один файл. Разбор, а не текст: комментарий, объясняющий эту же дисциплину, производителем не является.
type ClaimAssembly ¶ added in v0.2.0
ClaimAssembly — место, собирающее состав утверждений.
type ClaimAssemblyCensus ¶ added in v0.2.0
type ClaimAssemblyCensus struct {
MapLiterals int
EmptyMapLiterals int
KeyedLiterals int
Calls int
}
ClaimAssemblyCensus — объём осмотренного одним файлом.
type ClaimBuilderCall ¶ added in v0.2.0
ClaimBuilderCall — вызов сборщика состава: чем состав ПОТРЕБЛЯЕТСЯ.
type ConcatCensus ¶ added in v0.3.0
type ConcatCensus struct {
Dirs []string
Files int
Literals int
Segments int
ConcatsInPredicate int
// ConcatsElsewhere — законный близнец: склейка в ПРОЕКЦИИ. Без него «находок
// ноль» неотличимо от «разбор ничего не прочитал».
ConcatsElsewhere int
}
ConcatCensus — объём осмотренного.
type ConcatFinding ¶ added in v0.3.0
ConcatFinding — одно условие, сравнивающее склейку колонки.
type DatabaseCallCensus ¶ added in v0.2.0
DatabaseCallCensus — объём осмотренного одним файлом.
func ScanDatabaseCallsByFunction ¶ added in v0.2.0
func ScanDatabaseCallsByFunction(path string, src []byte) ( map[string]FunctionDatabaseCalls, DatabaseCallCensus, error, )
ScanDatabaseCallsByFunction разбирает один файл и раскладывает обращения к базе по функциям.
type DatabaseCallSite ¶ added in v0.2.0
DatabaseCallSite — координата обращения к базе.
type DeadPathCoordinate ¶ added in v0.4.0
DeadPathCoordinate — ПОСЛАБЛЕНИЕ: путь, о котором известно, что он не резолвится, и чей предмет принадлежит ДРУГОМУ кругу приёмки.
Запись заводится ПО ФАКТУ. Послабление ИСТЕКАЕТ САМО, и оба конца — находка: путь стал резолвиться → исключать нечего; путь больше не стоит ни в одном документе → исключать нечего.
type DeadProbeCoordinate ¶ added in v0.2.0
DeadProbeCoordinate — ПОСЛАБЛЕНИЕ: координата, о которой известно, что она не резолвится, и чей предмет принадлежит ДРУГОМУ кругу приёмки.
Запись заводится ПО ФАКТУ, а не с запасом. Послабление ИСТЕКАЕТ САМО, и оба конца — находка: имя стало резолвиться → исключать нечего; имя больше не стоит ни в одном документе → исключать нечего.
type DeleteRevokeCensus ¶
type DeleteRevokeCensus struct {
Dirs int // каталогов под api/ осмотрено
Files int // не-тестовых файлов Go разобрано
EmitCalls int // вызовов EmitReconcileEvent найдено
OwnTyped int // каталогов, у которых выведен СВОЙ тип
WithDeleteGo int // из них несущих delete.go
Population int // судимых каталогов (свой тип И delete.go)
Satisfying int // из них эмитирующих отзыв своего типа
}
DeleteRevokeCensus — перепись одного обхода. Печатается ВСЕГДА: «ноль находок» обязано быть отличимо от «ноль прочитанного».
func ScanDeleteRevokeProducers ¶
func ScanDeleteRevokeProducers(apiDir string) (DeleteRevokeCensus, []string, error)
ScanDeleteRevokeProducers обходит каталоги use-case под apiDir и называет те, у которых путь снятия собственного объекта остался без производителя отзыва.
Возвращает перепись, находки (по одной на каталог, в порядке имён — отказ на одном и том же дереве читается одинаково от прогона к прогону) и ошибку обхода. Пустой обход ошибкой ЗДЕСЬ не объявляется: пустоту судит вызывающий, потому что у гейта дерева и у пробы инъекции законные пороги пустоты разные.
func (DeleteRevokeCensus) String ¶
func (c DeleteRevokeCensus) String() string
type DerivedIDCensus ¶ added in v0.2.0
type DerivedIDCensus struct {
// Imports — объявлений импорта прочитано.
Imports int
}
DerivedIDCensus — объём осмотренного одним файлом.
type DerivedIDImportSite ¶ added in v0.2.0
type DerivedIDImportSite struct {
File string
Line int
// Form — форма импорта: `plain` · `alias` · `dot` · `blank`. Печатается
// переписью, чтобы «ноль находок» было отличимо от «форму не узнали».
Form string
}
DerivedIDImportSite — координата импорта, вычисляющего MD5.
type ExclusionFormCensus ¶ added in v0.3.0
type ExclusionFormCensus struct {
GuideParagraphs int
SubjectParagraphs int
ExplainByRefusal int
ExplainByBuild int
ReaderGoFiles int
RefuseCalls int
CoPresenceRefusals int
WrapGoFiles int
WrapCalls int
WrapSites []string
}
ExclusionFormCensus — объём осмотренного, по ОБЕИМ сторонам.
type ExclusionFormFinding ¶ added in v0.3.0
type ExclusionFormFinding struct {
// Kind — "refusal-without-producer" | "construction-unnamed".
Kind string
Rel string
// Line — первая строка абзаца предмета; 0, когда абзаца предмета нет вовсе.
Line int
Excerpt string
}
ExclusionFormFinding — одно расхождение страницы с деревом.
func (ExclusionFormFinding) String ¶ added in v0.3.0
func (f ExclusionFormFinding) String() string
type ExclusionFormInput ¶ added in v0.3.0
type ExclusionFormInput struct {
GuideRel string
GuideBody string
// ReaderFiles — не-тестовые файлы читателя: координата → исходник.
ReaderFiles map[string]string
// WrapFiles — не-тестовый код, в котором ищутся обращения-обёртки.
// Объявляющий файл читателя вызывающим не считается.
WrapFiles map[string]string
}
ExclusionFormInput — что судить.
Координаты и тела приходят параметрами, а не читаются внутри: инъекция подаёт синтетику тем же входом, что и гейт — настоящее дерево.
type ExportProcedureCensus ¶ added in v0.3.0
type ExportProcedureCensus struct {
// Guides — инструкций прочитано.
Guides int
// Lines — строк в них прочитано.
Lines int
// Procedures — строк, несущих процедуру выгрузки о КОНКРЕТНОЙ таблице.
Procedures int
// Templates — строк-образцов, где имя таблицы оставлено оператору. Считаются
// отдельно: образец не утверждает о таблице ничего и сверять его с
// производителем не с чем.
Templates int
// Tables — таблицы, чью выгрузку эти строки называют.
Tables []string
}
ExportProcedureCensus — объём осмотренного. Печатается всегда: «находок ноль» обязано быть отличимо от «прочитано ноль».
func JudgeExportProcedure ¶ added in v0.3.0
func JudgeExportProcedure(guides map[string]string, required map[string]string) (ExportProcedureCensus, []string)
JudgeExportProcedure судит корпус инструкций: ключ — путь, значение — текст.
required — таблицы, чья процедура выгрузки обязана быть записана, и в какой именно инструкции. Возвращает перепись и находки; находок ноль — годно.
func (ExportProcedureCensus) String ¶ added in v0.3.0
func (c ExportProcedureCensus) String() string
type FunctionDatabaseCalls ¶ added in v0.2.0
type FunctionDatabaseCalls struct {
Name string
Line int
Calls []DatabaseCallSite
}
FunctionDatabaseCalls — обращения одной функции.
type GoSQLLiteral ¶ added in v0.3.0
GoSQLLiteral — литерал SQL, найденный в исходнике Go.
func SQLLiteralsOfGo ¶ added in v0.3.0
func SQLLiteralsOfGo(name string, body []byte) []GoSQLLiteral
SQLLiteralsOfGo — литералы, разобранные ПО СИНТАКСИЧЕСКОМУ ДЕРЕВУ Go.
Не по тексту файла: SQL, стоящий в Go-комментарии, кодом не является, и читать его как код значило бы краснеть на объяснении запрета.
СКЛЕЙКА РАЗБИРАЕТСЯ ЦЕЛИКОМ. Кусок запроса, собранный конкатенацией, сам по себе не несёт ни параметров, ни предикатов — они в соседних слагаемых, — и судить его отдельно значило бы объявлять находкой каждый второй фрагмент. Слагаемые, не являющиеся литералами, подставляются как `$?`: их значение неизвестно, но известно, что там стоит ВЫЧИСЛЯЕМОЕ.
type HistoryCensus ¶ added in v0.3.0
type HistoryCensus struct {
// FilesRead — файлов прочитано; GoParsed — из них разобрано деревом.
FilesRead int
GoParsed int
// GoUnparsed — файлов Go, которые разобрать НЕ УДАЛОСЬ. Отдельная величина:
// неразобранный файл невидим, и его молчание неотличимо от чистоты.
GoUnparsed []string
// LinesStripped — строк комментария, снятых до разбора в не-Go файлах.
// Печатается затем, чтобы «проза о merge-base не сработала» было ЗАМЕРОМ,
// а не обещанием.
LinesStripped int
// VerbOutsideRunner — вызовов, чьи литералы несут глагол, но запускателем
// git вызов не является (`require.Contains(t, got, "merge-base")`).
//
// Величина печатается ОТДЕЛЬНО затем, чтобы сужение до запускателя было
// видно числом: ноль здесь означал бы, что сужение ничего не отсекает, а
// большое число — что оно отсекает предмет.
VerbOutsideRunner int
// Questions — вопросов об истории всего; по вершинам — три величины ниже.
Questions int
Head int
Trunk int
Unnamed int
// ByVerb — сколько вопросов задал каждый глагол. Глагол, давший ноль,
// означает, что этой формы в дереве нет, а не что разбор её не знает.
ByVerb map[string]int
}
HistoryCensus — ОБЪЁМ ОСМОТРЕННОГО. «Ноль находок» обязано быть отличимо от «ноль прочитанного», а «ноль вопросов» — от «разбор не дошёл до вызовов».
type HistoryQuestion ¶ added in v0.3.0
type HistoryQuestion struct {
File string
Line int
Verb string
Vertex Vertex
// Literals — литеральные аргументы вызова, как их прочитал разбор. Нужны
// читателю находки: без них он не отличит свой вызов от соседнего.
Literals []string
}
HistoryQuestion — один вызов git, задающий вопрос об истории.
func (HistoryQuestion) String ¶ added in v0.3.0
func (q HistoryQuestion) String() string
String — координата и вердикт одной строкой.
type HomeVerdict ¶ added in v0.3.0
type HomeVerdict struct {
// Findings — имя, которого в доме НЕТ. Вердикт, а не третья категория.
Findings []string
// Voids — ТРЕТЬЯ КАТЕГОРИЯ: дома рядом нет либо судить в нём не по чему.
// В проход НЕ засчитывается и находок не гасит.
Voids []string
// Resolved — координат, найденных в своём доме.
Resolved int
// HomesResolved — дома, копии которых нашлись; HomesAbsent — которых нет.
HomesResolved []string
HomesAbsent []string
}
HomeVerdict — исход резолва координаты в названном доме.
func JudgeHomes ¶ added in v0.3.0
func JudgeHomes(ownRoot string, coords []ProbeCoordinate) HomeVerdict
JudgeHomes — резолв координат чужих домов В НАЗВАННОМ ДОМЕ.
НАХОДКИ И ТРЕТЬЯ КАТЕГОРИЯ РАЗВЕДЕНЫ, и вызывающий обязан объявлять находки ПЕРВЫМИ: иначе «дома нет» становится маской — одной такой строки хватило бы, чтобы настоящая находка перестала блокировать отправку.
Дом резолвится ОДИН раз на имя: без этого перепись печатала бы его столько раз, сколько координат на него ссылается.
type IdentityGrowthReaderCensus ¶ added in v0.4.0
type IdentityGrowthReaderCensus struct {
// Metrics — ряды, объявленные коллектором.
Metrics []string
// Expressions — выражения правил оповещения, прочитанные у документа.
Expressions int
}
IdentityGrowthReaderCensus — ОБЪЁМ ОСМОТРЕННОГО обеих сторон сверки.
func JudgeIdentityGrowthReaders ¶ added in v0.4.0
func JudgeIdentityGrowthReaders(collector, doc string) (IdentityGrowthReaderCensus, []string, error)
JudgeIdentityGrowthReaders — у каждого объявленного ряда есть читатель.
ПРЕМИСЫ ЖИВУТ ЗДЕСЬ, а не в теле гейта (задача #17). Прежде обе стояли в пробе, входом им служили два файла, прочитанные от корня своего модуля, и подать им пустую сторону было НЕЧЕМ: ветви читались глазами и не исполнялись ни разу. Приняв обе стороны параметрами, они стали проверяемы синтетикой.
Ноль рядов и ноль выражений — РАЗНЫЕ отказы намеренно: первый означает, что ослеп разбор коллектора, второй — что ослеп разбор правил, и чинятся они в разных местах. Слив их в один текст, гейт посылал бы читателя не туда.
type InjectionCensus ¶
type InjectionCensus struct {
// GoFiles — исходников модуля разобрано.
GoFiles int
// NamingFiles / InComments — файлов, называющих доказательство, и самих
// упоминаний В КОММЕНТАРИЯХ (судимая полоса).
NamingFiles int
InComments int
// InStrings — упоминаний в строковых литералах (полоса НЕ судимая; названа,
// чтобы её отсутствие в вердикте не приняли за отсутствие вхождений).
InStrings int
// Resolved — из судимых упоминаний нашли свой файл.
Resolved int
}
InjectionCensus — объём осмотренного. Печатается ВСЕГДА: «ноль находок» обязано быть отличимо от «ноль прочитанного».
type InjectionFinding ¶
type InjectionFinding struct {
NamedBy string // координата называющего, от корня обхода
Coordinate string // что названо
}
InjectionFinding — упоминание, у которого нет предмета.
type JobFieldRead ¶ added in v0.4.0
JobFieldRead — прочтение величины в композиционном корне.
func JobFieldReadsIn ¶ added in v0.4.0
JobFieldReadsIn разбирает ОДИН файл корня: какие величины прочитаны и какие секции ушли в вызов целиком.
Имя секции подаётся набором, а не угадывается: гейт судит те секции, которые объявлены, и на одноимённом поле чужой структуры молчит.
type JobKnobCensus ¶ added in v0.4.0
type JobKnobCensus struct {
Sections int
Fields int
Read int
WholeSection []string
Files int
Findings []string
}
JobKnobCensus — объём осмотренного и вердикт.
Величин ПЯТЬ, и печатаются все: «секций N · величин M · прочитано K · секций целиком L · файлов корня F». Одно число скрывало бы ровно тот случай, ради которого гейт заведён: величина без читателя и величина, чья секция уехала целиком, дают одинаковый ноль находок.
func JudgeJobKnobReaders ¶ added in v0.4.0
func JudgeJobKnobReaders(sections []JobSection, reads []JobFieldRead, whole []string, files int) JobKnobCensus
JudgeJobKnobReaders — судящее ядро. Вход подаётся ЗНАЧЕНИЯМИ: инъекция обязана уметь дать ему свой вход, не трогая рабочую копию, из которой запущена.
func (JobKnobCensus) Summary ¶ added in v0.4.0
func (c JobKnobCensus) Summary() string
type JobSection ¶ added in v0.4.0
type JobSection struct {
// Name — имя поля в JobsConfig (оно же сегмент ключа настроек).
Name string
// Type — имя структуры секции.
Type string
// Fields — величины секции, объявленные тегом настроек.
Fields []string
}
JobSection — секция фоновых заданий и её величины.
func JobSectionsIn ¶ added in v0.4.0
func JobSectionsIn(src string) ([]JobSection, error)
JobSectionsIn разбирает объявление секций фоновых заданий.
Состав ВЫВОДИТСЯ из исходника, а не выписывается: выписанный перечень секций разошёлся бы с деревом на первой же новой петле — и разошёлся бы молча, потому что гейт судил бы ровно то, что ему назвали.
type JudgeTargetWiring ¶ added in v0.3.0
type JudgeTargetWiring struct {
// Target — имя цели, о которой всё нижеследующее.
Target string
// Declared — объявлена ли цель корневым рецептом.
Declared bool
// Callers — файлы заданий, чьё тело `run:` зовёт цель исполняемой формой.
Callers []string
// MakefilesRead — прочитано рецептов (в этом дереве обязан быть ровно один).
MakefilesRead int
// WorkflowsRead — найдено файлов заданий.
WorkflowsRead int
// WorkflowsParsed — из них разобрано как YAML.
WorkflowsParsed int
// RunStepsRead — шагов с непустым телом `run:`.
RunStepsRead int
// Unreadable — файлы, которые прочитать или разобрать не удалось; НЕ
// проверены, и молчать о них нельзя.
Unreadable []string
}
JudgeTargetWiring — что дерево говорит о ПРОВЯЗКЕ одной цели-судьи.
Перепись хранится рядом с вердиктом намеренно: «вызова нет» и «не прочитано ничего» выглядят одинаково, пока объём осмотренного не назван числом.
func ReadJudgeTargetWiring ¶ added in v0.3.0
func ReadJudgeTargetWiring(root, target string) (JudgeTargetWiring, error)
ReadJudgeTargetWiring — обход дерева: кто объявляет цель и кто её зовёт.
Ошибка возвращается там, где обход БЕСПРЕДМЕТЕН (нет рецепта, нет каталога заданий): «ноль находок» обязано быть отличимо от «ноль прочитанного», и различать их обязан сам разбор, а не читатель его вывода.
func (JudgeTargetWiring) Census ¶ added in v0.3.0
func (w JudgeTargetWiring) Census() string
Census — объём осмотренного. Печатается ВСЕГДА: без него «вызывающий есть» неотличимо от «читать было нечего».
type LenientScopeCensus ¶ added in v0.3.0
type LenientScopeCensus struct {
Packages int
Lenient int
Named int
Holders int
HolderTests int
// RefsPrefixed / RefsBare — сколько ссылок пришло в каждой из двух законных
// форм. Печатаются порознь намеренно: ноль в одной из них означает, что
// форма перестала встречаться, и это повод перемерить распознаватель, а не
// повод ему молчать.
RefsPrefixed int
RefsBare int
}
LenientScopeCensus — объём осмотренного. Печатается ВСЕГДА: «ноль находок» обязано быть отличимо от «ноль прочитанного».
func AuditLenientScopes ¶ added in v0.3.0
func AuditLenientScopes(apiRoot string) (LenientScopeCensus, []string, error)
AuditLenientScopes ВОЗВРАЩАЕТ находки, а не роняет прогон сам: инъекция обязана уметь их прочитать, чтобы утверждать, ЧТО именно нашлось, а не только «покраснело». Отказ предпосылки остаётся ошибкой — на слепом обходе говорить не о чем.
func (LenientScopeCensus) String ¶ added in v0.3.0
func (c LenientScopeCensus) String() string
type MachineryCensus ¶ added in v0.3.0
type MachineryCensus struct {
// Files — прочитано файлов контрактов.
Files int
// CommentBlocks — прочитано блоков комментария.
CommentBlocks int
// Claims — распознано заявлений всего.
Claims int
// ByKind — распознано заявлений по видам.
ByKind map[MachineryKind]int
// Resolved — из них резолвится (законные близнецы).
Resolved int
}
MachineryCensus — объём осмотренного. Печатается всегда: «ноль находок» обязано быть отличимо от «ноль прочитанного».
type MachineryClaim ¶ added in v0.3.0
type MachineryClaim struct {
// File — путь контракта относительно корня набора.
File string
// Line — строка, на которой стоит имя.
Line int
// Name — заявленное имя.
Name string
// Kind — чем комментарий его назвал.
Kind MachineryKind
}
MachineryClaim — одно заявление комментария о машинерии дерева.
type MachineryFacts ¶ added in v0.3.0
type MachineryFacts struct {
// Sources — путь контракта → его исходный текст.
Sources map[string]string
// Tables — таблицы ПРИМЕНЁННОЙ схемы.
Tables map[string]struct{}
// Channels — каналы уведомления, которые эта схема производит.
Channels map[string]struct{}
// Contracts — базовые имена контрактов, существующих в модуле.
Contracts map[string]struct{}
}
MachineryFacts — вход предиката. Собран так, чтобы предикат прогонялся инъекцией, не трогая дерево.
type MachineryKind ¶ added in v0.3.0
type MachineryKind string
MachineryKind — что именно заявил комментарий.
const ( // MachineryTable — заявлена таблица схемы. MachineryTable MachineryKind = "таблица" // MachineryChannel — заявлен канал уведомления. MachineryChannel MachineryKind = "канал" // MachineryContract — заявлен соседний файл контракта. MachineryContract MachineryKind = "контракт" )
type MigrationRoleCensus ¶ added in v0.3.0
type MigrationRoleCensus struct {
// Blocks — блоков `INSERT INTO kaname.roles` прочитано.
Blocks int
// Names — имён ролей извлечено.
Names int
// Unreadable — блоков, из которых имя роли извлечь НЕ УДАЛОСЬ.
//
// Величина отдельная и несущая: без неё «извлечено меньше, чем блоков»
// неотличимо от «блок вставляет роль без имени», а первое означает, что
// разбор встретил форму, которой не знает, — то есть невидимость, а не
// находку и не молчание.
Unreadable int
}
MigrationRoleCensus — объём осмотренного.
type MigrationRoleSite ¶ added in v0.3.0
type MigrationRoleSite struct {
File string
Name string
// Owner — первый сегмент имени: модуль-владелец либо пусто.
Owner string
}
MigrationRoleSite — роль, вставляемая миграцией.
type MirrorConditionOutcome ¶ added in v0.3.0
type MirrorConditionOutcome struct {
// Findings — писатели, обошедшие условие эталонной полосы.
Findings []string
// Stale — записи ведомости, которым больше нечего исключать.
Stale []string
// Required — условие, выведенное из эталонной полосы (таблицы каталога).
Required []string
// Lanes — вводящих писателей всего.
Lanes int
// LaneKeys — они же поимённо: число без перечня читатель проверить не может.
LaneKeys []string
// Carriers — из них несущих требуемое условие целиком.
Carriers int
// Exempt — из них погашенных ведомостью.
Exempt int
// ReferenceMissing — эталонной полосы в наборе нет; сверять не с чем.
ReferenceMissing bool
}
MirrorConditionOutcome — вердикт сверки полос вместе с переписью.
func MirrorConditionReport ¶ added in v0.3.0
func MirrorConditionReport(writes []MirrorWrite, ledger map[string]string) MirrorConditionOutcome
MirrorConditionReport — ЧИСТАЯ функция сверки: по набору записей и ведомости возвращает находки и перепись. Вынесена из обхода дерева намеренно — только так её способность краснеть и молчать доказывается инъекцией на синтетическом входе, не трогая настоящее дерево.
type MirrorWiringScan ¶ added in v0.3.0
type MirrorWiringScan struct {
// Files — не-тестовых файлов Go разобрано.
Files int
// Calls — узлов вызова читателя найдено.
Calls int
// CallSites — файлы с вызовом, по возрастанию.
CallSites []string
}
MirrorWiringScan — что увидел обход композиционного корня.
func ScanMirrorDivergenceWiring ¶ added in v0.3.0
func ScanMirrorDivergenceWiring(root string) (MirrorWiringScan, error)
ScanMirrorDivergenceWiring обходит названный каталог и считает вызовы читателя разности.
Вынесен отдельно от гейта затем, чтобы инъекция гоняла ТУ ЖЕ функцию на синтетическом дереве: проверка, доказанная на своей копии разбора, доказывает свойство копии.
type MirrorWrite ¶ added in v0.3.0
type MirrorWrite struct {
// File — путь от корня дерева; заполняет обходчик.
File string
// Func — объемлющая функция; пустое имя означает пакетный уровень.
Func string
// Verb — какой оператор записи найден.
Verb string
// Introduces — вводит ли оператор новую строку.
Introduces bool
// Catalog — таблицы каталога, названные В ТОМ ЖЕ операторе, по возрастанию.
Catalog []string
}
MirrorWrite — одна найденная запись в зеркало.
func MirrorWritesIn ¶ added in v0.3.0
func MirrorWritesIn(filename, src string) ([]MirrorWrite, int, error)
func (MirrorWrite) Key ¶ added in v0.3.0
func (w MirrorWrite) Key() string
Key — координата писателя в ведомости исключений.
type ModuleManifestSite ¶ added in v0.3.0
ModuleManifestSite — манифест, найденный в дереве.
func ScanModuleManifest ¶ added in v0.3.0
func ScanModuleManifest(path string, src []byte) (ModuleManifestSite, bool)
ScanModuleManifest опознаёт манифест модуля по содержимому.
type ModuleSetDecl ¶ added in v0.3.0
type ModuleSetDecl struct {
// PkgFiles — сколько не-тестовых файлов пакета осмотрено. Без этой величины
// «объявление найдено» неотличимо от «прочитан один файл, и повезло».
PkgFiles int
// DeclFile — где объявление нашлось. Печатается, потому что именно это место
// и переезжало: читатель обязан видеть, О ЧЁМ вынесен вердикт, не заглядывая
// в исходник гейта.
DeclFile string
// TypeKeys — сколько ключей прочитано. Приставок мало by construction, и одна
// их величина не отличила бы «таблица прочитана» от «прочитаны две строки».
TypeKeys int
}
ModuleSetDecl — перепись РАЗРЕШЕНИЯ объявления.
func ModuleSetFromDecl ¶ added in v0.3.0
ModuleSetFromDecl выводит закрытый набор модулей РАЗБОРОМ объявления.
`files` — содержимое не-тестовых файлов пакета: координата → исходник. Читатель отдаёт их сам, потому что гейт берёт их из индекса git, а инъекция — из синтетики, и разводить эти два источника внутри значило бы завести здесь вторую посадку.
type ModuleSetFinding ¶ added in v0.3.0
ModuleSetFinding — один неполный перечень.
func (ModuleSetFinding) String ¶ added in v0.3.0
func (f ModuleSetFinding) String() string
type ModuleSetScan ¶ added in v0.3.0
type ModuleSetScan struct {
// Enumerations — сколько перечней (три имени и более) рассужено.
Enumerations int
// PairSpans — сколько спанов РОВНО из двух имён встречено и НЕ рассужено.
// Объявленная слепая зона, а не находка.
PairSpans int
}
ModuleSetScan — перепись обхода поверхностей.
type NonASCIIIdent ¶ added in v0.3.0
type NonASCIIIdent = treehygiene.NonASCIIIdent
NonASCIIIdent — одно нелатинское имя с координатой; тип фундамента, названный здесь именем шва.
Псевдоним, а не своя запись: своя дала бы второе объявление об одном предмете, а перекладывание полей из чужой записи в свою — место, где поле теряется молча.
func ScanNonASCIIIdents ¶ added in v0.3.0
func ScanNonASCIIIdents(name string, src []byte) (seen int, findings []NonASCIIIdent, err error)
ScanNonASCIIIdents разбирает ОДИН исходник и возвращает: сколько имён осмотрено и какие из них нелатинские.
Перепись «имён осмотрено N» нужна гейту, чтобы «ноль находок» было отличимо от «разбор ничего не увидел»; неразбираемый файл отдаёт признак, а не пустой успех, — обе половины держит фундамент, и утверждают их его пробы.
type PathCoordinate ¶ added in v0.4.0
type PathCoordinate struct {
// Path — путь-спецификация без приставки дома.
Path string
// Home — названный дом `владелец/репозиторий`. Пусто — дом ЭТО дерево.
Home string
// Rev — ревизия названного дома, если названа.
Rev string
// Span — токен, как он стоит в документе: без него читатель не найдёт строку.
Span string
// HomeMalformed — приставка есть, а домом она не является.
HomeMalformed bool
Doc string
Line int
}
PathCoordinate — одно вхождение путевой координаты.
type PathCoordinateCensus ¶ added in v0.4.0
type PathCoordinateCensus struct {
Docs int
Tracked int
Coordinates int
Resolved int
Exempted int
// Foreign — координаты, назвавшие ЧУЖОЙ дом: вне суждения, но в переписи.
Foreign int
// RevisionBound — из них связанные РЕВИЗИЕЙ: не проверяемы даже там, где
// дерево дома есть.
RevisionBound int
// ForeignHomes — различные названные дома, по алфавиту.
ForeignHomes []string
// Borders — что разбор видел и не судил.
Borders PathScanBorders
Findings []string
}
PathCoordinateCensus — перепись обхода. «Ноль находок» обязано быть отличимо от «ноль прочитанного», поэтому объём осмотренного — отдельное утверждение.
func JudgePathCoordinates ¶ added in v0.4.0
func JudgePathCoordinates(docs map[string]string, tracked []string, exemptions []DeadPathCoordinate) PathCoordinateCensus
JudgePathCoordinates — судящее ядро. Вход подаётся ЗНАЧЕНИЯМИ, а не читается из дерева: инъекция обязана уметь дать ему свой вход, не трогая рабочую копию, из которой запущена.
type PathScanBorders ¶ added in v0.4.0
type PathScanBorders struct {
// BareSpec — путей-спецификаций в форме `git ls-files <спец>` без `--`.
BareSpec int
// Magic — магических путей-спецификаций (`:!*.md`, `:(glob)…`): не пути.
Magic int
// Elided — многоточий-эллипсисов (`…/*.yaml`): не пути, а сокращение прозы.
Elided int
}
PathScanBorders — то, что разбор ВИДЕЛ и НЕ СУДИЛ. Печатается переписью: слепая зона, которую видно, — остаток, а не дыра.
type ProbeCoordinate ¶ added in v0.2.0
type ProbeCoordinate struct {
Name string
// Home — названный дом `владелец/репозиторий`. Пусто — дом ЭТО дерево.
Home string
// Rev — ревизия названного дома, если названа.
Rev string
// Span — пролёт, как он стоит в документе. Нужен находке: без него читатель
// не найдёт строку, у которой имя пробы лишь хвост.
Span string
// HomeMalformed — приставка есть, а домом она не является.
HomeMalformed bool
Doc string
Line int
}
ProbeCoordinate — одно вхождение координаты: имя, дом и место, где оно стоит.
func ProbeCoordinatesIn ¶ added in v0.2.0
func ProbeCoordinatesIn(doc, body string) []ProbeCoordinate
ProbeCoordinatesIn разбирает документ и возвращает координаты — только их.
type ProbeCoordinateCensus ¶ added in v0.2.0
type ProbeCoordinateCensus struct {
Docs int
Declared int
Coordinates int
Resolved int
Exempted int
// Foreign — координаты, назвавшие ЧУЖОЙ дом: вне суждения, но в переписи.
Foreign int
// RevisionBound — из них связанные РЕВИЗИЕЙ чужого дома. Величина отдельная,
// потому что отвечает на другой вопрос: сколько координат указывает в ПРОШЛОЕ
// состояние чужого дерева, то есть не проверяемо даже там, где дерево есть.
RevisionBound int
// ForeignHomes — различные названные дома, по алфавиту. Печатаются, чтобы дом,
// стоящий в корпусе один раз, был виден: опечатка в имени репозитория иначе
// уходит молча.
ForeignHomes []string
// ForeignCoordinates — сами координаты чужих домов, чтобы их можно было
// РЕЗОЛВИТЬ в названном доме, а не только сосчитать. Ядро судит значения и
// чужих деревьев не читает: резолв делает вызывающий, у которого есть корень.
ForeignCoordinates []ProbeCoordinate
Findings []string
}
ProbeCoordinateCensus — перепись обхода. «Ноль находок» обязано быть отличимо от «ноль прочитанного», поэтому объём осмотренного — отдельное утверждение.
func JudgeProbeCoordinates ¶ added in v0.2.0
func JudgeProbeCoordinates(docs map[string]string, declared []string, exemptions []DeadProbeCoordinate) ProbeCoordinateCensus
JudgeProbeCoordinates — судящее ядро. Вход подаётся значениями, а не читается из дерева: инъекция обязана уметь дать ему свой вход, не трогая рабочую копию, из которой запущена.
type RawOperationsRepoSite ¶ added in v0.3.0
type RawOperationsRepoSite struct {
Where string // путь:строка
Wrapped bool // обёрнут ли надстройкой прямо здесь
}
RawOperationsRepoSite — один вызов сырого конструктора с координатой.
type ReadPathFile ¶ added in v0.3.0
type ReadPathFile struct {
// Rel — координата в том виде, в каком её объявляет предмет замера; ею
// называется находка.
Rel string
// Abs — путь, по которому файл читается.
Abs string
}
ReadPathFile — файл предмета замера: координата для находки и путь на диске.
func ReadPathGoFiles ¶ added in v0.3.0
func ReadPathGoFiles(root string) (files []ReadPathFile, dirs []string, err error)
ReadPathGoFiles — не-тестовые .go каталогов, составляющих предмет замера.
Координаты приводятся к посадке ДЕТЕКТОРОМ дерева (`treeposture.PathUnder`), а не складываются с корнем здесь: правило приведения живёт в одном месте дерева, и второй его копии не заводится. Первая редакция порта складывала путь сама — и её поймал гейт дерева `TestPlatformCoordinatesTouchingTheTreeAreAnchoredInTheModule` двумя находками: под чужим деревом такой путь указал бы на чужой файл, и вердикт был бы о нём.
Каталог, в котором таких файлов нет вовсе (каталог миграций), в объём просто не приносит ничего — исключать его СПИСКОМ не нужно, и списка здесь нет.
type RefusalTextCensus ¶
type RefusalTextCensus struct {
Files int // файлов Go (не-тестовых) разобрано
Constructions int // конструкций статуса найдено всего
Population int // из них на полосах чужой причины (код назван синтаксически)
Fixed int // из них с доказуемо фиксированным текстом
CodeNotLiteral int // конструкций с ВЫЧИСЛЯЕМЫМ кодом — вне популяции (слепая зона)
Constants int // пакетных строковых констант проиндексировано
}
RefusalTextCensus — перепись одного обхода. Печатается ВСЕГДА: «ноль находок» обязано быть отличимо от «ноль прочитанного».
func (RefusalTextCensus) String ¶
func (c RefusalTextCensus) String() string
type RefusalTextDecl ¶ added in v0.3.0
RefusalTextDecl — одно объявление текста отказа с координатой.
type RefusalTextFinding ¶
type RefusalTextFinding struct {
File string // путь относительно названного корня
Line int
Code string // Unavailable / Internal
Expr string // выражение текста, как оно записано
}
RefusalTextFinding — одна конструкция, чей текст не доказан фиксированным.
type RelationGrant ¶ added in v0.3.0
type RelationGrant struct {
ObjectType string
Relation string
Where string // путь относительно корня — координата находки
}
RelationGrant — одна выдача: какое отношение на каком типе объекта пишет миграция.
func GrantsFromMigrations ¶ added in v0.3.0
func GrantsFromMigrations(root string) (grants []RelationGrant, migrationsRead, blocksSeen int, err error)
GrantsFromMigrations — пары «тип объекта + отношение» из миграций, пишущих в очередь. Возвращает ещё и объём осмотренного: без него «ноль находок» неотличимо от «ноль прочитанного».
type RoleDeleteCensus ¶ added in v0.2.0
RoleDeleteCensus — объём осмотренного одним файлом.
type RoleDeleteSite ¶ added in v0.2.0
RoleDeleteSite — координата находки.
type RoleOperationResponseStateCensus ¶ added in v0.2.0
type RoleOperationResponseStateCensus struct {
Files int
Funcs int
AnypbFuncs int
RoleTranslators int
ProjectionCalled int
}
RoleOperationResponseStateCensus — объём осмотренного.
func (RoleOperationResponseStateCensus) String ¶ added in v0.2.0
func (c RoleOperationResponseStateCensus) String() string
type RoleOperationResponseStateFinding ¶ added in v0.2.0
RoleOperationResponseStateFinding — переводчик, не зовущий проекцию.
func (RoleOperationResponseStateFinding) String ¶ added in v0.2.0
func (f RoleOperationResponseStateFinding) String() string
type RoleOperationResponseStateOptions ¶ added in v0.2.0
type RoleOperationResponseStateOptions struct {
Root string
ServiceRoot string
DomainPkg string
RoleType string
TransferFunc string
ProjectionMethod string
}
RoleOperationResponseStateOptions — вход анализатора.
type RoleProjectionOp ¶ added in v0.2.0
type RoleProjectionOp struct {
// Func — объемлющая функция; пустое имя означает пакетный уровень.
Func string
// Verb — какой оператор найден.
Verb string
// Authors — оператор ВНОСИТ строку.
Authors bool
// Relocates — ТОТ ЖЕ литерал переселяет снятое в RoleGrantOrphanTable.
//
// Признак читается по литералу, а не по функции: переселение и снятие
// обязаны быть неделимы, а неделимы они ровно тогда, когда стоят в одном
// операторе.
Relocates bool
}
RoleProjectionOp — один найденный оператор над проекцией.
func RoleProjectionWritesIn ¶ added in v0.2.0
func RoleProjectionWritesIn(filename, src, table string) ([]RoleProjectionOp, int, error)
RoleProjectionWritesIn разбирает исходник Go и возвращает операторы над таблицей проекции, приписанные объемлющей функции, плюс число строковых литералов, называющих таблицу вообще (перепись предпосылки: читатели тоже считаются).
Признак судит УЗЕЛ-ЛИТЕРАЛ разобранного дерева, а не текст файла: имя таблицы встречается и в комментариях — в том числе в комментариях, объясняющих эту самую проверку, — и гейт по подстроке краснел бы на собственном объяснении.
func RoleVerbWritesIn ¶ added in v0.2.0
func RoleVerbWritesIn(filename, src string) ([]RoleProjectionOp, int, error)
RoleVerbWritesIn — совместимая обёртка для инъекции по первой проекции.
type RoleScopeChainCensus ¶ added in v0.2.0
RoleScopeChainCensus — объём осмотренного одним файлом.
type RoleScopeChainSite ¶ added in v0.2.0
RoleScopeChainSite — координата одной находки.
type RoleWithdrawalCensus ¶ added in v0.2.0
type RoleWithdrawalCensus struct {
AppliedImports int
Selectors int
StringLiterals int
Comments int
WritesOverRoles int
}
RoleWithdrawalCensus — объём осмотренного одним файлом.
type RoleWithdrawalSite ¶ added in v0.2.0
RoleWithdrawalSite — координата одной из двух половин.
type SQLUpdateCensus ¶ added in v0.2.0
type SQLUpdateCensus struct {
StringLiterals int
SQLLiterals int
Updates int
UpdatesWithoutColumns int
}
SQLUpdateCensus — объём осмотренного одним файлом.
type SeedCensusCell ¶ added in v0.3.0
SeedCensusCell — одна клетка переписи: вхождений и файлов.
func (SeedCensusCell) String ¶ added in v0.3.0
func (c SeedCensusCell) String() string
type SeedCensusDeclaration ¶ added in v0.3.0
type SeedCensusDeclaration struct {
// Revision — ревизия измерения, названная ОДНОЙ строкой документа.
Revision string
// Buckets — объявленные величины, по ведру.
Buckets map[string]SeedCensusCell
// BlockLines — сколько строк объявляющего блока прочитано (перепись:
// «ноль находок» обязано быть отличимо от «ноль прочитанного»).
BlockLines int
// LineOf — НОМЕР СТРОКИ документа (от нуля), на которой объявлено ведро.
//
// Нужен не разбору, а тому, кто правит объявление точечно — инъекции.
// Без него порча «первого вхождения величины в файле» промахивается мимо
// объявления, как только та же величина упомянута прозой выше: инъекция
// тогда красит текст, которого гейт не судит, и молча ничего не доказывает.
// Наблюдалось на этом самом файле.
LineOf map[string]int
}
SeedCensusDeclaration — то, что объявила приёмка.
func ParseSeedCensusDeclaration ¶ added in v0.3.0
func ParseSeedCensusDeclaration(doc string, buckets []string) SeedCensusDeclaration
ParseSeedCensusDeclaration читает объявление приёмки.
Блок ищется ПО РЕВИЗИИ, а не по порядку: в документе живёт и второй блок тех же вёдер — замер в монорепо, объявленный историческим свидетельством. Разбор «первый попавшийся блок» сверял бы величины ЧУЖОГО дерева и был бы при этом зелёным ровно до тех пор, пока кто-нибудь не тронет здешние числа.
Внутри строки берётся ПОСЛЕДНЯЯ клетка: столбцов у блока два — монорепо и это дерево, — и здешний стоит правым.
type SeedCensusReport ¶ added in v0.3.0
type SeedCensusReport struct {
Revision string
Indexed int
Read int
Binary int
Buckets map[string]SeedCensusCell
Order []string
}
SeedCensusReport — то, что напечатал предикат.
func ParseSeedCensusOutput ¶ added in v0.3.0
func ParseSeedCensusOutput(out string) (SeedCensusReport, error)
ParseSeedCensusOutput разбирает вывод предиката.
Отказ — не пустой отчёт: предикат, не напечатавший ни объёма осмотренного, ни одного ведра, о дереве не сказал ничего, и выдавать это за ноль находок нельзя.
type SeededServiceAccount ¶ added in v0.2.0
type SeededServiceAccount struct {
ID, Name, Description, Where string
}
SeededServiceAccount — посеянная служебная учётка.
func (SeededServiceAccount) IsModule ¶ added in v0.2.0
func (s SeededServiceAccount) IsModule() bool
IsModule — учётка объявляет себя модульной.
type SubjectChangeProducer ¶ added in v0.3.0
SubjectChangeProducer — одно обращение к производителю очереди.
func SubjectChangeProducersIn ¶ added in v0.3.0
func SubjectChangeProducersIn(rel, src string) ([]SubjectChangeProducer, error)
SubjectChangeProducersIn считает обращения к производителю в ОДНОМ файле.
Возвращает координаты обращений. Разбор — не поиск по подстроке: имя метода стоит и в комментариях, объясняющих сам механизм, и предикат по слову краснел бы на собственном объяснении.
func (SubjectChangeProducer) String ¶ added in v0.3.0
func (p SubjectChangeProducer) String() string
type SubjectChangeRosterDiff ¶ added in v0.3.0
type SubjectChangeRosterDiff struct {
// Undeclared — файл несёт больше обращений, чем объявлено (в том числе
// файл, которого в перечне нет вовсе).
Undeclared []string
// Stale — перечень называет то, чего в дереве больше нет либо стало меньше.
// Запись, которой нечего называть, — НАХОДКА: послабление обязано истекать
// само, иначе оно переживает свой предмет, оставаясь на вид рабочим.
Stale []string
}
SubjectChangeRosterDiff — расхождение перечня с деревом.
func CompareSubjectChangeRoster ¶ added in v0.3.0
func CompareSubjectChangeRoster( found []SubjectChangeProducer, declared map[string]int, ) SubjectChangeRosterDiff
CompareSubjectChangeRoster сверяет перечень с разбором — в ОБЕ стороны.
Сверяется пара «файл → сколько обращений», а не только число файлов: второе обращение, добавленное в уже объявленный файл, — такой же новый производитель, как и первый в новом файле, и полоса пополняется им ровно так же.
Число целиком (а не только состав) сверять обязательно и по другой причине: предок сравнивал ЧИСЛА полос, и величина, которую край пинит, — это число.
func (SubjectChangeRosterDiff) Empty ¶ added in v0.3.0
func (d SubjectChangeRosterDiff) Empty() bool
Empty — сошлись ли перечень и дерево.
type TerminalRefusalCensus ¶ added in v0.3.0
type TerminalRefusalCensus struct {
Tracked int // элементов в индексе дерева
Read int // прочитано файлов Go
Parsed int // из них разобрано
Ctors int // найдено вызовов сырого конструктора
Wrapped int // из них обёрнуто на месте
Mentions int // упоминаний имени вне вызова (комментарий, строка)
}
TerminalRefusalCensus — объём осмотренного.
func ScanRefusalTextLiterals ¶ added in v0.3.0
func ScanRefusalTextLiterals(root string, texts []string) ( map[string][]RefusalTextDecl, TerminalRefusalCensus, error, )
ScanRefusalTextLiterals ищет ЛИТЕРАЛЫ обоих текстов отказа в прод-дереве.
Предмет KN-RTX-08: у каждого текста ровно одно объявление. Литерал, написанный вторым местом, заводит копию, которая разойдётся с первой молча — на всяком входе, кроме сериализационного конфликта, обе стороны отвечают одинаково.
func (TerminalRefusalCensus) String ¶ added in v0.3.0
func (c TerminalRefusalCensus) String() string
String — перепись одной строкой.
type TokenClaimCensus ¶ added in v0.2.0
TokenClaimCensus — объём осмотренного одним файлом.
type TokenClaimForm ¶ added in v0.2.0
type TokenClaimForm string
TokenClaimForm — в какой позиции стоит имя.
const ( TokenClaimFormKey TokenClaimForm = "ключ состава" // #nosec G101 -- подпись позиции разбора, не удостоверение TokenClaimFormRead TokenClaimForm = "чтение по имени" // #nosec G101 -- подпись позиции разбора, не удостоверение TokenClaimFormCase TokenClaimForm = "разбор по имени" // #nosec G101 -- подпись позиции разбора, не удостоверение TokenClaimFormArg TokenClaimForm = "имя в вызове" // #nosec G101 -- подпись позиции разбора, не удостоверение TokenClaimFormConst TokenClaimForm = "объявление константы" // #nosec G101 -- подпись позиции разбора, не удостоверение )
Значения — ПРОЗА для человека, читающего находку, а не материал удостоверения. Сканер безопасности видит здесь форму «имя с `token`/`claim` получает строковый литерал» и по ней подозревает вшитое удостоверение (G101, уверенность LOW). Подозрение снимается предметом: перечисляется ПОЗИЦИЯ имени в разборе (ключ состава · чтение · разбор · аргумент · объявление), и ни одно значение не участвует ни в одной проверке подлинности — они попадают только в текст находки. Подавление стоит НА КАЖДОЙ СТРОКЕ объявления, а не на `const (`: оговорка на строке блока этим сканером к отдельным объявлениям не применяется — проверено прогоном пина (до правки level=error 5, после 0), а не прочтением. Ни на что за пределами этих пяти строк подавление не распространяется.
type TokenClaimUse ¶ added in v0.2.0
type TokenClaimUse struct {
File string
Line int
Func string
Namespace string
Name string
Form TokenClaimForm
}
TokenClaimUse — одно употребление имени клейма чужого словаря.
type TreeCorpus ¶ added in v0.4.0
TreeCorpus — тела отобранных файлов по относительному пути от корня дерева.
func CorpusFrom ¶ added in v0.4.0
func CorpusFrom(tree *treecorpus.Tree, want func(rel string) bool) (TreeCorpus, error)
CorpusFrom — тела файлов дерева, отобранные предикатом `want`.
Отбор ПАРАМЕТР, а корпус — значение: так гейт перестаёт строить свой обход в теле пробы, а инъекция получает возможность подать тот же отбор пустому дереву.
ТРИ ИСХОДА, И ТРЕТИЙ НАЗВАН ОТДЕЛЬНОЙ ОШИБКОЙ:
корпус непуст — вердикт выносится;
файл не прочитан — отказ с координатой: гейт не вправе судить
документ, которого он не читал;
не отобрано ни одного — ErrEmptyTraversal, и это НЕ «находок нет».
func ExclusionFormGoCorpus ¶ added in v0.4.0
func ExclusionFormGoCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
AuditExclusionForm сверяет форму взаимоисключения, названную оператору, с той, которой оно держится в этом дереве. ExclusionFormGoCorpus — непроверочные файлы Go дерева: и сторона отказа, и сторона обёртки берутся из одного обхода.
Дерево приходит параметром, отбор объявлен один раз, пустой обход — отказ, а не «находок ноль» (задача #17). Отбор сужен `ProductionGoFile`, то есть служебные каталоги (документация, оснастка, вендоренное) из него выпадают; на этом дереве сужение не меняет НИЧЕГО — файлов Go под ними ноль, — а по построению делает обход тем же, каким его видят соседние семейства.
func ExportProcedureGuides ¶ added in v0.4.0
func ExportProcedureGuides(tree *treecorpus.Tree) (TreeCorpus, error)
ExportProcedureGuides — корпус инструкций обновления из ДЕРЕВА.
Дерево приходит параметром, а отбор объявлен здесь и больше нигде: гейт и инъекция зовут ОДНУ функцию, поэтому синтетика проверяет тот же отбор, что исполняется на боевом прогоне, а не его копию. Пустой обход — отказ (`ErrEmptyTraversal`), а не «находок ноль».
func ManifestLoaderCorpus ¶ added in v0.4.0
func ManifestLoaderCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
ManifestLoaderCorpus — прод-файлы ЗАГРУЗЧИКА манифеста.
func MigrationCorpus ¶ added in v0.4.0
func MigrationCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
MigrationCorpus — файлы миграций из ДЕРЕВА.
Сборщик общий на два семейства (словарь алгоритма и писатель роли модуля): обе прежде строили обход сами, и премисы «миграций прочитано ноль» у обеих стояли в теле пробы, где подать им пустое дерево было нечем (#17).
func MirrorCandidateCorpus ¶ added in v0.4.0
func MirrorCandidateCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
MirrorWritesIn разбирает исходник Go и возвращает записи в зеркало, приписанные объемлющей функции, плюс число литералов, называющих таблицу вообще (перепись предпосылки: читатели тоже считаются). MirrorCandidateCorpus — непроверочные файлы Go дерева, среди которых ищутся писатели зеркала.
Дерево приходит параметром, отбор объявлен один раз (`ProductionGoFile`), и пустой обход даёт отказ, а не «находок ноль». Прежде обход строился в теле пробы от корня своего модуля, и его премиса не исполнялась ни разу (#17).
func ModuleSetDeclCorpus ¶ added in v0.4.0
func ModuleSetDeclCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
ScanModuleSetEnumerations судит перечни ОДНОГО файла поверхности.
Возвращает находки и перепись; вызывающий складывает перепись по файлам сам — ему же принадлежит решение, какие файлы читать. ModuleSetDeclCorpus — файлы ПАКЕТА, из разбора которого выводится набор.
Дерево параметром, отбор объявлен здесь, пустой обход — отказ (#17).
func ModuleSetSurfaceCorpus ¶ added in v0.4.0
func ModuleSetSurfaceCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
ModuleSetSurfaceCorpus — файлы клиентской поверхности из ДЕРЕВА.
func SubjectChangeProducerCorpus ¶ added in v0.4.0
func SubjectChangeProducerCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
IsSubjectChangeProducerFile — лежит ли координата в слое use-case и не проба ли это. SubjectChangeProducerCorpus — корпус производителей полосы самосброса из ДЕРЕВА.
Отбор объявлен `IsSubjectChangeProducerFile` и зовётся отсюда, а дерево приходит параметром: гейт и инъекция ходят ОДНОЙ дорогой, поэтому синтетика проверяет тот же отбор, что исполняется на боевом прогоне. Пустой обход — отказ (`ErrEmptyTraversal`), а не «находок ноль».
func VerbClassRuleCorpus ¶ added in v0.4.0
func VerbClassRuleCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
VerbClassRuleCorpus — корпус, в котором ищется объявление правила.
Дерево параметром, отбор объявлен здесь, пустой обход — отказ (#17): прежде обход строился в теле пробы от корня своего модуля, и его премиса «обход не прочитал ни одного файла» не исполнялась ни разу.
func (TreeCorpus) Rels ¶ added in v0.4.0
func (c TreeCorpus) Rels() []string
Rels — относительные пути корпуса в устойчивом порядке. Детерминизм входа — часть контракта проверки: обход, отдающий файлы в разном порядке, даёт находки в разном порядке, и два прогона становятся несравнимы.
type TrunkHolderCensus ¶ added in v0.3.0
type TrunkHolderCensus struct {
// Jobs — заданий в процессе; Needed — сколько из них перечислено держателем.
Jobs int
Needed int
// Steps — шагов у держателя; RunBodies — из них с непустым телом.
Steps int
RunBodies int
SelfTests int
Verdicts int
JobPerms int
FlowPerms int
HolderSeen bool
// CancelInProgress — вытесняет ли процесс собственный прогон. От этого
// зависит, чем условие держателя обязано быть.
CancelInProgress bool
}
TrunkHolderCensus — объём осмотренного.
func AuditTrunkHolderWiring ¶ added in v0.3.0
func AuditTrunkHolderWiring(raw string) ([]string, TrunkHolderCensus, error)
AuditTrunkHolderWiring — вердикт о провязке держателя.
Вынесено ЧИСТОЙ функцией от текста объявления затем, чтобы способность гейта упасть доказывалась подачей входа, а не чтением.
func (TrunkHolderCensus) String ¶ added in v0.3.0
func (c TrunkHolderCensus) String() string
String — перепись одной строкой.
type TrunkProcessCensus ¶ added in v0.4.0
type TrunkProcessCensus struct {
// Files — объявлений прочитано; OnTrunk — из них идущих по push в ствол;
// WithHolder — из тех, что несут держателя.
Files int
OnTrunk int
WithHolder int
}
TrunkProcessCensus — объём осмотренного по КОРПУСУ процессов.
func AuditTrunkProcesses ¶ added in v0.4.0
func AuditTrunkProcesses(corpus map[string]string) ([]string, TrunkProcessCensus, error)
AuditTrunkProcesses — вердикт о том, что у КАЖДОГО процесса ствола есть читатель, и что провязка каждого исправна.
Вход — имя объявления → его текст. Чистая функция от корпуса затем, чтобы инъекция подавалась входом, а не правкой дерева.
func (TrunkProcessCensus) String ¶ added in v0.4.0
func (c TrunkProcessCensus) String() string
String — перепись одной строкой. «Ноль находок» обязано быть отличимо от «ноль прочитанного», поэтому печатаются все три величины, а не последняя.
type TrunkRegisterCensus ¶ added in v0.4.0
type TrunkRegisterCensus struct {
// Rows — строк перечня «что не переносится»; Complete — из них с непустым
// производителем. Contexts — строк таблицы обязательных контекстов.
Rows, Complete, Contexts int
// JobsNamed — упомянутых заданий; JobsResolved — из них найденных в дереве.
JobsNamed, JobsResolved int
// ProcessesNamed — процессов ствола, названных перечнем, из ProcessesOnTrunk.
ProcessesNamed, ProcessesOnTrunk int
}
TrunkRegisterCensus — объём осмотренного.
func AuditTrunkRegister ¶ added in v0.4.0
func AuditTrunkRegister(raw string, jobs map[string]string, trunkProcesses []string) ([]string, TrunkRegisterCensus, error)
AuditTrunkRegister — вердикт о перечне.
jobs — задания, существующие в дереве (имя задания → процесс); trunkProcesses — отображаемые имена процессов ствола. Чистая функция от входа затем, чтобы инъекция подавалась входом, а не правкой дерева.
func (TrunkRegisterCensus) String ¶ added in v0.4.0
func (c TrunkRegisterCensus) String() string
String — перепись одной строкой: «ноль находок» обязано быть отличимо от «ноль прочитанного».
type VerbFormSentinelCensus ¶ added in v0.2.0
type VerbFormSentinelCensus struct {
// CompositeLits — составных литералов прочитано. Предпосылка оси: разбор
// ищет присваивание внутри литерала, и ноль литералов означает, что
// искать было негде.
CompositeLits int
// Idents — идентификаторов прочитано: объём разбора в самой мелкой единице.
Idents int
// SentinelReturns — возвратов сентинела найдено.
SentinelReturns int
}
VerbFormSentinelCensus — объём, осмотренный разбором ОДНОГО файла.
func ScanVerbFormSentinel ¶ added in v0.2.0
func ScanVerbFormSentinel(rel string, src []byte) (VerbFormSentinelCensus, error)
ScanVerbFormSentinel считает ВОЗВРАТЫ сентинела в одном файле Go.
Возвратом считается присваивание `kind: <Сентинел>` в составном литерале, стоящем внутри `return` — то есть исход функции, а не упоминание имени.
type Vertex ¶ added in v0.3.0
type Vertex int
Vertex — вершина, относительно которой задан вопрос об истории.
const ( // VertexUnnamed — вершина ЛИТЕРАЛОМ НЕ НАЗВАНА: она пришла переменной либо // оставлена умолчанию (`git log` без ревизии есть `git log HEAD`). // // Это НЕ «вершина неизвестна разбору» и не молчание: состояние объявлено, // считается и требует записанного довода — иначе «сказано, судит она ствол // или рабочую вершину» осталось бы необеспеченным ровно там, где вершину и // не видно. VertexUnnamed Vertex = iota // VertexHead — среди литералов стоит рабочая вершина. VertexHead // VertexTrunk — среди литералов стоит объявленный ствол. VertexTrunk )
type WrapperPair ¶ added in v0.2.0
WrapperPair — вопрос, у которого автор пакета объявил ОБЕ формы.
func (WrapperPair) OutcomeForms ¶ added in v0.2.0
func (p WrapperPair) OutcomeForms() string
OutcomeForms — половины с исходом, перечисленные для сообщения.
type WrapperScanReport ¶ added in v0.2.0
type WrapperScanReport struct {
Roots []string
Files int
Generated int
DotImports int
Pairs []WrapperPair
Found []BoolWrapperCall
}
WrapperScanReport — что именно осмотрено. Печатается ВСЕГДА.
func ScanBoolWrapperCalls ¶ added in v0.2.0
func ScanBoolWrapperCalls(root string, roots []string, under func(string) ([]string, error)) (WrapperScanReport, error)
ScanBoolWrapperCalls — два прохода по одному корпусу: сперва вывести пары, затем найти их употребления. under — обходчик поддерева (обычно `treecorpus.Under`), подаётся вызывающим, чтобы инъекция могла подставить синтетическое дерево без записи в рабочую копию.
Source Files
¶
- acceptance_edit_after_verdict.go
- acceptance_path_coordinate.go
- acceptance_probe_coordinate.go
- applier_never_deletes.go
- ascii_identifiers.go
- assertion_admission_calls.go
- audit_payload_pii.go
- authz_wrapper_outcome_lanes.go
- basic_credential_proof_run.go
- build_stamp_word.go
- carried_coordinate_ledger.go
- catalog_check_wiring.go
- catalog_seed_parity.go
- catalog_writer_lock.go
- census_fixture_producer.go
- client_expiry_immutable.go
- client_truth_exclusion_form.go
- client_truth_module_set.go
- contract_names_live_machinery.go
- deferred_work.go
- delete_revoke_producer.go
- derived_id_single_source.go
- granted_relation_in_model.go
- history_question_vertex.go
- identity_growth_reader.go
- injection_named_exists.go
- job_knob_has_a_reader.go
- judge_target_wiring.go
- key_algorithm_dictionary.go
- limit_export_procedure.go
- list_scope_double.go
- manifest_verb_class_rule.go
- migration_not_a_writer_of_module_role.go
- mirror_catalog_condition.go
- mirror_divergence_wiring.go
- module_identity_seeded_only_by_baseline.go
- named_verb_form_expiry.go
- probe_home.go
- quota_authority_retired.go
- read_path_concat.go
- refusal_text_is_fixed.go
- role_operation_response_state.go
- role_scope_chain_stays_empty.go
- role_verb_projection_sole_writer.go
- seed_identity_census.go
- seeded_service_accounts.go
- subject_change_flush_parity.go
- system_role_row_is_never_deleted.go
- terminal_refusal_wrapping.go
- token_claim_foreign_brand.go
- token_claim_single_source.go
- tree_corpus.go
- trunk_verdict_holder.go
- trunk_verdict_register.go
- withdrawal_producer_arrives_with_the_applier.go