Documentation
¶
Overview ¶
acceptance_edit_after_verdict.go — правка ОДОБРЕННОЙ приёмки после вердикта объявляется в самом документе.
Порт с монорепо (`internal/repohygiene/acceptanceeditafterverdict.go`, снят вынесением службы — `kacho#2597`). Изменилось: путь дома приёмок (был `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` (в монорепо — `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/`.
Предмет ¶
Число обращений к базе внутри одной функции. Допуск однократности обязан делать РОВНО ОДНО: «не предъявлялось ли уже» и «погасить» неделимы, и неделимыми их делает первичный ключ таблицы, а не аккуратность вызывающего. Пара «посмотреть — записать» проходит ВСЕ последовательные пробы: окна между чтением и записью при последовательном прогоне не существует.
Почему владелец соединения берётся из ОБЪЯВЛЕНИЯ ТИПА, а не из списка имён ¶
Разбор читает объявления структур файла и берёт в носители соединения те поля, ЧЕЙ ТИП называет драйвер базы. Переименование поля исход не меняет, чужое одноимённое поле находкой не становится.
assertion_verifier_single.go — разбор «сверка утверждения ключа доступа в дереве ОДНА» (приёмка Ф13 `docs/engineering/acceptance/passwordless-login-with-access-key.md`, Р13, §7 инв. 2, сценарий Ф13-31; задача PRO-Robotech/kaname#613).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Утверждение ключа сверяют две полосы — проверка утверждения из сессии (Ф7) и вход без пароля (Ф13). Обе обязаны звать ОДНОГО проверяющего (`internal/webauthnverify`): вторая сверка — «упрощённая для входа» либо копия — разошлась бы с первой молча ровно там, где расхождение опасно, и ни проба одной полосы, ни проба другой этого не показали бы.
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ ВЫЗОВ ПРИМИТИВА ПОДПИСИ, А НЕ ИМЯ ФУНКЦИИ
Копия проверяющего под другим именем узнаётся по тому, что она ДЕЛАЕТ: зовёт примитив сверки подписи стандартной библиотеки (`ecdsa.Verify`, `ecdsa.VerifyASN1`, `ed25519.Verify`, `rsa.VerifyPKCS1v15`, `rsa.VerifyPSS`). Такой вызов в прод-коде законен только в доме проверяющего; функция дома, его содержащая, — «объявление сверки», и оно ОДНО. Обёртка, зовущая `webauthnverify.VerifyAssertion`, — вызывающий, а не вторая сверка: она молчит и считается в переписи вызывающих.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ НАЗВАНЫ
примитив, взятый значением (`f := ecdsa.VerifyASN1`), — узел селектора без вызова; разбор считает и его (сторона ложного красного, не молчания); импорт примитива под псевдонимом распознаётся по пути импорта; сверка чужой библиотекой (не стандартной) этим разбором не видна — в дереве её нет, и перепись импортов это показала бы ростом числа файлов.
assurance_level_sole_writer.go — разбор «кто производит уровень уверенности и где он лежит как состояние» (приёмка Ф11, Р1, §7 инв. 4; гейт §8 «правило одно»).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Уровень сессии производит ОДНО правило — `assurance.LevelOf` — и как состояние он лежит только в записи сессии. Второй писатель (константа оси, употреблённая как значение; строка, преобразованная в уровень мимо правила) даёт уровень, которого правило не выводило, и делает его молча: оба пути компилируются, оба типизированы осью. Второе место хранения (поле уровня в строке способа входа) было бы неверно для каждого утверждения ключа без проверки пользователя и без срока жило бы вечно.
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ ТИП ОСИ, А НЕ ИМЯ ПОЛЯ
Разбор ищет обращения к типу `assurance.Level` и его константам через импорт дома правила — под любым псевдонимом импорта — и классифицирует каждое ПО РОДИТЕЛЬСКОМУ УЗЛУ:
l == assurance.Level2 · l != … · case assurance.Level3: ЧТЕНИЕ — молчит
assurance.LevelOf(…) · assurance.PresentableLevels(…) ВЫЗОВ ПРАВИЛА — молчит
x = assurance.Level2 · T{Level: assurance.Level1} ·
return assurance.Level3 · f(assurance.Level2) ПРОИЗВОДСТВО — находка
assurance.Level(s) ПРЕОБРАЗОВАНИЕ — находка
type T struct { … assurance.Level … } ДЕРЖАТЕЛЬ — судит ведомость
Поле уровня в структуре — не находка само по себе: запись сессии и четыре её чтения (ответ краю, ответ церемонии, запись журнала, токен) законны и названы поимённо ведомостью в пробе. Разбор лишь ДОКЛАДЫВАЕТ держателя с координатой.
───────────────────────────────────────────────────────────────────────────── ПОЛОВИНА ПО МИГРАЦИЯМ
Объявление оси уровня в схеме — перечень значений ровно «1», «2», «3» (`IN (…)` либо `= ANY (ARRAY[…])`) — читается вместе с именем столбца и таблицей, при которой он объявлен. Нужна потому, что колонку с умолчанием пишет база, и писателя в коде у неё нет: половина по коду её не видит. Законных мест два вида: таблица сессии (дом состояния) и названная ведомостью СНИМКОВ таблица, где уровень лежит неподвижной копией события (JudgeAssuranceAxisColumns).
───────────────────────────────────────────────────────────────────────────── ГРАНИЦА НАЗВАНА
Разбор по узлам, без вывода типов: уровень, пронесённый через переменную типа оси (`l := assurance.Level2; rec.level = l`), находится на первом шаге (константа как значение), а не на втором. Уровень, собранный строкой без типа оси, невидим — это довод держать значение типом. Голый текстовый столбец без объявления оси половина по миграциям не видит.
assurance_method_vocabulary.go — разбор «где ещё объявлен перечень имён способов предъявления» (приёмка Ф11, Р8; гейт §8 «словарь один»).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Словарь способов — password · totp · lookup_secret · webauthn · recovery_code — объявлен ОДИН раз, в `internal/assurance`, вместе с правилом вывода уровня. Всякий, кому нужен перечень, читает `assurance.Methods()`. Второе объявление перечня в прод-коде службы расходится с первым молча: способ, заведённый в одном и не заведённый в другом, доезжает до сессии безуровневым либо отвергается хранилищем, которое правило о нём не спрашивало.
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ ОБЪЯВЛЕНИЕ ПЕРЕЧНЯ, А НЕ СЛОВО
Строковый литерал, совпадающий с именем способа, находкой НЕ является: он бывает именем поля запроса, областью токена (`"webauthn"` в области удостоверения и в условии модели прав), меткой в перечне секретов. Перечнем считается УЗЕЛ разбора, несущий два и более РАЗЛИЧНЫХ имени словаря строковыми литералами (ast.BasicLit вида token.STRING). Комментарии в счёт не идут by construction: разбор ходит по узлам, а не по тексту.
───────────────────────────────────────────────────────────────────────────── ФОРМЫ ЗАПИСИ ПЕРЕЧНЯ — ПЕРЕЧИСЛЕНЫ
[]string{"password", "totp"} составной литерал (среза, карты,
структур — литералы собираются
по всему поддереву литерала)
const ( a = "password"; b = "totp" ) группа const/var, включая
var ( p = kind{"password"}; t = kind{"totp"} ) локальную в теле функции и
форму дома — структуры со
строкой внутри
case "password", "recovery_code": перечень ветви case
Форма, о которой разбор не знает, даёт не красное и не зелёное, а молчание; поэтому каждая из названных доказана инъекцией (assurance_method_vocabulary_injection_test.go).
───────────────────────────────────────────────────────────────────────────── ПОЛОВИНА ПО СХЕМЕ
Ограничение схемы, перечисляющее значения столбца (`IN (…)` либо `= ANY (ARRAY[…])`), среди которых есть имя словаря, обязано быть его ПОДМНОЖЕСТВОМ. Перечень без единого имени словаря — не предмет: состояния, алгоритмы, виды удостоверений у него свои. Чего разбор не видит — те же три границы, что у соседа по пакету (`key_algorithm_dictionary.go`): ограничение функцией или триггером, словарь из справочной таблицы, значение выражением.
ast_receiver.go — разбор получателя метода, общий для гейтов пакета.
Жил в гейте проводной стражи дороги к внешнему поставщику; гейт снят вместе с дорогой (kaname#363), а разбором пользуются гейты полосы входа и писателей адреса человека. Вторая копия одного разбора разошлась бы с первой молча, поэтому он вынесен сюда, а не скопирован.
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 — булева ОБЁРТКА вопроса о правах не вызывается там, где у неё есть парная форма с исходом (задача kacho#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:`, и из них выбрасываются строки оболочечных комментариев. Гейт по подстроке краснел бы на собственном объяснении и зеленел бы на шаге, откуда вызов сняли, а комментарий оставили.
binding_insert_writes_ledger.go — разбор «каждая вставка привязки доступа пишет ведомость выпущенных кортежей той же функцией» (kaname#670, класс kaname#665).
Предмет ¶
Снятие выдачи — штатное (`AccessBinding.Delete`) и дренажом области при удалении проекта или аккаунта (`shared.RevokeBindingsInScope`) — снимает РОВНО записанное в ведомости выдачи (`access_binding_emitted_tuples`). Выдача, вставленная без ведомости, уходит строкой, а кортежи, которые она выпустила, остаются фактами модели прав на объект, которого больше нет. Дважды этот класс жил молча (самовыдача заведения — #665, выдача приглашения — #670), потому что пустая ведомость неотличима от «выпускать было нечего».
Что судится ¶
Узел вызова `<…>.AccessBindingsW().Insert(…)` — вставка строки выдачи — и узел вызова `<…>.InsertEmittedTuples(…)` в ТОЙ ЖЕ самой внутренней функции (объявление либо литерал функции: вставка приглашения стоит в замыкании транзакции). Вставка без записи ведомости в своей функции — находка с координатой. Слово в комментарии или строке находкой не становится: судится узел вызова, а не текст.
Граница названа ¶
Разбор не следит за вызовами между функциями: ведомость, записанная вспомогательной функцией, которую зовёт вставляющая, гейтом не видна и даст находку. Это осознанно — запись ведомости и вставка обязаны стоять рядом, в одной транзакции и в одном месте чтения.
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_copy_parity.go — сверка двух копий каталога прав: своей и копии края.
───────────────────────────────────────────────────────────────────────────── ЧТО ЗДЕСЬ ИЗМЕНИЛОСЬ И ПОЧЕМУ (kaname#79)
Прежняя сверка была `cmp` двух файлов с ОДНОНАПРАВЛЕННОЙ посылкой: «источник истины один — копия края», и единственный совет находки — позвать `sync-permission-catalog`, то есть ПЕРЕПИСАТЬ свою копию копией края.
Посылка держалась, пока оба дерева линковали ОДИН фундамент. Она перестала держаться, когда фундамент переименовал свой контракт: полное имя метода у контракта, живущего в библиотеке, задаёт ВЕРСИЯ БИБЛИОТЕКИ, которую линкует дерево, а версии у деревьев разные. Тогда расхождение означает не «наша копия отстала», а «отстала копия края», и прежний совет в этом направлении ВРЕДЕН:
перепись 2026-09-14 (`corelib@v1.7.0` переименовал форму подписки; платформа на своём стволе пинила `corelib@v1.5.0`): записей у каждой стороны 338 расходится 1 — только сегмент пакета в `fqn` остальные поля записи совпадают дословно
Этот случай ЗАКРЫТ 2026-09-15: платформа подняла пин, копии снова совпадают побайтово, и запись ведомости, объяснявшая расхождение, снята — разбор у самой ведомости ниже. Довод о направлении оставлен, потому что он о КЛАССЕ: следующее переименование в фундаменте даст ту же картину.
ЧЕМ ВРЕДЕН СОВЕТ — сказано ровно настолько, насколько измерено.
Наша копия индексируется ПО `fqn` (`internal/apps/kaname/seed/permissions.go`, `byFQN`), и по нему же её спрашивают о ПОЛНОМ ИМЕНИ МЕТОДА, с которым вызов пришёл на СВОЙ слушатель (`internal/authzguard/acr_floor.go`, `requiredACRMin` → `strings.TrimPrefix(fullMethod, "/")`; `public_caller_policy.go`). Служба линкует `corelib@v1.7.0`, поэтому вызов приходит как `/corelib.subscription.…/Subscribe`. Записав сюда имя отставшего края, мы положили бы в посев имя метода, которого этот двоичный файл НЕ СЛУЖИТ, — мёртвая запись, а у служимого глагола записи бы не стало.
ГРАНИЦА ЭТОГО ДОВОДА НАЗВАНА, ЧТОБЫ ЕГО НЕ ПЕРЕСКАЗАЛИ ШИРЕ. У пола ACR промах поиска даёт исход «требования нет» (правило 3 в `allow`), но ДО него стоит правило 1: глагол обязан быть во фронтируемом краем наборе (`authzguard.GatewayFrontedInternalRPCs`). Перепись 2026-09-14: глагола подписки в этом наборе НЕТ, значит сегодня промах на нём ИНЕРТЕН. Довод латентный, а не наступивший, и записан он так намеренно: наступит он тогда, когда глагол во фронтируемый набор внесут, — и заметить это будет нечем.
───────────────────────────────────────────────────────────────────────────── ЧТО СВЕРКА УТВЕРЖДАЕТ ТЕПЕРЬ
Норма прежняя и НЕ ослаблена: копии — ОДИН порождённый артефакт. Изменилось то, что у равенства появились ЧЕТЫРЕ закрытых перечня объявленных окон — переименования фундамента, записи службы, ждущие края (kaname#181), глаголы, снятые службой, которые край ещё называет (kaname#564), и записи, у которых служба сменила значение одного поля (kaname#720), — и каждая запись обязана держать себя САМА в обе стороны. Остаток после их применения — находка с прежним текстом.
Сравнение остаётся ПОБАЙТОВЫМ, а не «по смыслу»: файл режется на блоки записей по своей же форме, сборка блоков обязана дословно воспроизвести исходный файл (иначе форма файла сменилась — тоже находка), переименование применяется к блоку края, блоки пересортировываются по `fqn` (переименование двигает запись в перечне) и сравниваются дословно.
───────────────────────────────────────────────────────────────────────────── ЧЕГО ЭТА СВЕРКА НЕ ЗАКРЫВАЕТ — сказано прямо
- Она НЕ знает пина фундамента у края: в конвейере копия края приезжает ВЫБОРКОЙ одного каталога, `go.mod` платформы в ней нет. Поэтому направление расхождения не ВЫЧИСЛЯЕТСЯ, а ОБЪЯВЛЯЕТСЯ ведомостью ниже, и держится ведомость самоистечением, а не доверием.
- Она НЕ судит, верно ли переименование по существу. Она судит, что оно объявлено, что обе его стороны в деревьях ЕСТЬ и что кроме него не разошлось ничего.
- Провязка сверки к конвейеру — предмет `catalog_check_wiring.go`, не этот.
catalog_covers_contract.go — своя копия каталога прав покрывает СВОЙ контракт.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ (kaname#184)
Копия каталога прав в этом дереве — порождённый артефакт: её строки край порождает из контрактов всех доменов, и строки ЭТОЙ службы — из её же контракта по пину модуля. Сверка копий (`catalog_copy_parity.go`) судит равенство ДВУХ копий, и только его; о том, покрывает ли наша копия наш собственный контракт, она не утверждает ничего — пока край пинит ревизию без нового глагола, обе копии его не несут, и сверка зелена.
Ровно так строка `InternalHumanSessionService/Resolve` осталась без предмета: контракт объявил глагол (kaname#179), обе копии молчали, обе сверки были зелены, и красное ждало подъёма пина платформой — то есть наступило бы в ЧУЖОМ дереве, чужим прогоном, на всяком следующем PR этой службы.
───────────────────────────────────────────────────────────────────────────── ЧТО УТВЕРЖДАЕТСЯ — В ОБЕ СТОРОНЫ, И ТОЛЬКО О СВОЁМ
- У каждого RPC, объявленного файлами контракта службы, есть строка в копии, и строка совпадает с аннотациями метода по каждой оси, которую каталог несёт. Строка без источника — находка: она пережила свой RPC.
- Строки ЧУЖИХ доменов не судятся вовсе: их источник живёт в чужом дереве, и «строка без RPC» для них означает лишь, что стабы чужого домена в этот двоичный файл не слинкованы. Судить их отсюда было бы утверждением о дереве, которого здесь нет.
Перечень своих пакетов ВЫВОДИТСЯ из обхода (пакет каждого файла контракта), а не выписывается: выписанный был бы вторым объявлением того же предмета.
Обход, не нашедший НИ ОДНОГО метода, — не «ноль находок», а ТРЕТИЙ ИСХОД: стабы не слинкованы либо приставка пути названа неверно, и гейт в таком состоянии не утверждает ничего. То же — пустая копия.
───────────────────────────────────────────────────────────────────────────── ЧТО ДЕЛАТЬ НА НАХОДКЕ — И ПОЧЕМУ НЕ РУКАМИ
Строка ПОРОЖДАЕТСЯ генератором края над контрактом службы (в дереве платформы `gateway/scripts/gen-permission-catalog.sh` с модулем службы, разрешённым на нужную ревизию), кладётся в копию и, пока край её не несёт, объявляется записью ведомости ожидающих края (`CatalogPendingEntries`, `catalog_copy_parity.go`). Правка JSON руками исходом не является: копия — порождаемый артефакт, и рукописная строка разошлась бы с тем, что край породит по пину, ровно на первой сверке после подъёма.
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` каталога с одним именем пакета собираются в один бинарь и делят помощников. Проба, сеющая через помощника из соседнего файла, сеет через производителя ровно так же.
Разбор идёт по СТРОКОВЫМ ЛИТЕРАЛАМ, а не по тексту файла ¶
Текстовый поиск нашёл бы обе примеет и в комментарии, объясняющем эту же дисциплину (в том числе в шапке самой пробы полноты).
ceremony_surface.go — гейт ЕДИНСТВЕННОСТИ ПОВЕРХНОСТИ церемонии (kaname#320; приёмка LINE-A-1, сценарий LINE-A-1-23: «эндпоинты монтируются на внешней поверхности выдачи и НИГДЕ больше»).
Что судится ¶
Два свойства, и «НИГДЕ больше» держат только оба вместе.
- ПУТЬ: для каждой координаты — на скольких ПОВЕРХНОСТЯХ процесса она резолвится. Не сколько раз её упомянули и не сколько вызовов Handle её назвали: обработчик, отданный двум поверхностям, регистрируется один раз и резолвится дважды; делегирование поддерева («/iam/v1/» → чужой мультиплексор) не называет координату вовсе и резолвит её.
- ОБРАБОТЧИК: конечная точка, до которой координата доходит на своей поверхности, не достижима ни на одной другой поверхности ни под каким путём. Эндпоинт выдачи, смонтированный на внутренней поверхности под путём «/internal/client-token», путём координаты там не резолвится — и всё же смонтирован. Тождество конечной точки — место рождения её значения, без копий по местам вызова: второй экземпляр того же конструктора на чужой поверхности — тот же эндпоинт. Обработчик координаты, не прослеженный до значения, — находка, а не молчание.
Как выводится, а не выписывается ¶
- ПОВЕРХНОСТЬ — объявление servicecontract.Surface в модуле службы: имя, досягаемость, обработчик. Перечня слушателей в гейте нет.
- ОБРАБОТЧИК поверхности прослеживается до мест рождения мультиплексоров сквозь переприсваивания, возвраты фабрик, поля, обёртки (ceremony_surface_flow.go).
- РЕГИСТРАЦИЯ — вызов Handle/HandleFunc на мультиплексоре net/http, Handle/HandlePath на мультиплексоре шлюза и http.Handle на общем мультиплексоре процесса, где бы в бинаре он ни стоял; путь сводится к значению обратным разбором (ceremony_surface_resolve.go). Опознаётся ВЫЗЫВАЕМЫЙ метод, а не синтаксис вызова: прямой выбор, значение метода, выражение метода, метод интерфейса и параметра типа, метод, продвинутый из встроенного поля, — один и тот же метод мультиплексора.
- «РЕЗОЛВИТСЯ» решает НАСТОЯЩИЙ мультиплексор: для каждого места рождения собирается http.ServeMux (или ServeMux шлюза) из выведенных образцов, и запрос координаты проходит его так же, как прошёл бы в процессе: метод и хост в образце, подстановки, хвостовой слэш, перенаправление. Своим разбором образца вердикт не выносится: образец расщепляется лишь затем, чтобы перечислить хосты, на которые идёт запрос, и формы переписи.
Чем гейт не судит (границы, названные прямо) ¶
- Правила HTTP контракта (.proto) читаются через порождённую привязку шлюза; её сверку с контрактом держит задание конвейера generate-diff.
- Путь, который задаёт оператор (поле, заполняемое декодером настройки), значения не имеет: он — лист ведомости с причиной, не пропуск.
- Маршрут, решаемый по пути запроса в теле обработчика (сравнение, switch, выбор из карты, функция сопоставления над путём и над значениями, в которые он течёт; куда выведение доходит и где кончается, названо в ceremony_surface_manual.go), и мультиплексор, отданный чужому коду, гейт не моделирует — и потому краснеет на них, а не молчит.
- Значения, прошедшие через пустой интерфейс, не прослеживаются. Вызов метода регистрации через интерфейс, который реализует мультиплексор, когда хоть у одного значения получателя реализация не найдена, — находка «не прослежен», даже если другие получатели разрешились; мультиплексор, переданный аргументом методу интерфейса с таким получателем, — находка «передан методу интерфейса». Ни то ни другое не молчание.
- Регистрация, которую разбор видит, стоит в переписи: на мультиплексоре своего вида, в непрослеженных или в недостижимом коде. Вызов через интерфейс, разрешившийся лишь у части получателей, стоит в двух графах: на мультиплексорах разрешившихся и в непрослеженных.
- Маршруты, которые заводят варианты конструктора мультиплексора шлюза (runtime.With…), не наблюдаются: вариант — чужой код без переданного ему мультиплексора. Сегодня варианты корня маршрутов не заводят.
- Обработчик судится по ЗНАЧЕНИЮ, а не по поведению: та же церемония, реализованная заново другим типом или другим конструктором, — другое значение, и её второй монтаж гейт не видит: это копия кода, а не второй монтаж того же эндпоинта.
- Монтаж обработчика на чужой поверхности судится по ВСЕМ её маршрутам, без учёта пути: эндпоинт за мультиплексором, до образцов которого запрос с этой поверхности не дойдёт, тоже считается смонтированным. Это перебор, а не недобор: гейт краснеет, а не молчит.
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» распознавателю не видны. Расширение на голый текст не замерялось и потому не вводится — оно находило бы имена модулей в любом предложении, где они соседствуют законно.
- ПОРЯДОК не судится — только состав.
comment_coordinate_layout.go — разбор комментария на ОДИН факт: называет ли он координату приставкой ЧУЖОЙ раскладки, когда та же координата лежит здесь.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Служба жила каталогом `services/iam/` внутри дерева платформы и переехала в свой репозиторий. Код переезд пережил — координаты в комментариях нет: шестьдесят с лишним мест продолжали называть файл приставкой, которой в этом дереве не существует.
Читателя это отправляет в никуда, а замер делает недействительным: предикат, списанный из комментария, печатает пусто — и пусто читается как «находок нет», а не как «искали не там».
───────────────────────────────────────────────────────────────────────────── ЧТО СЧИТАЕТСЯ НАХОДКОЙ — И ПОЧЕМУ НЕ ВСЯКОЕ УПОМИНАНИЕ ПРИСТАВКИ
Находка — координата `<приставка>/<хвост>`, У КОТОРОЙ ХВОСТ РЕЗОЛВИТСЯ В ЭТОМ ДЕРЕВЕ. Это и есть «тот же файл, названный чужим адресом».
Не находка, и всё это законно:
приставка БЕЗ хвоста — `git grep … -- services/iam`, `приставки services/iam/
в самостоятельном клоне нет`: проза О ПЕРЕЕЗДЕ и
указатель области в ЧУЖОМ дереве;
хвост с многоточием — `services/iam/internal/…`, `services/iam/.../x.txt`:
это не координата, а форма записи КЛАССА путей; обе
записи многоточия, знак и три точки, распознаватель
знает сам и отдаёт вызывающему помеченными;
хвост, не резолвящийся — назван файл, которого здесь нет: он либо чужой, либо
снят, и это ДРУГОЙ предмет (у него нет «того же файла
рядом», ради которого гейт и заведён).
Сужение до резолвящегося хвоста не осторожность, а точность: без него гейт краснел бы на каждом объяснении собственного предмета — проверка, судящая по слову, находит его в комментарии, который этот же предмет объясняет, и остаётся зелёной при снятой защите. Первая редакция этого файла так и покраснела: на строке выше, где форма с многоточием объявлена законной, — распознаватель формы не знал, а знал её только резолвер, до которого многоточие не доезжало.
───────────────────────────────────────────────────────────────────────────── РАЗБОР СУДИТ УЗЕЛ КОММЕНТАРИЯ, А НЕ СТРОКУ ФАЙЛА
Строковый литерал с приставкой — ЗАКОННАЯ и действующая форма: `treeposture` резолвит координату платформы в обеих посадках by construction, и именно ею пользуются пробы объёма, отпечатки и обходчики. Гейт, судивший бы строки, потребовал бы снять работающий механизм.
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-функции, и этот гейт её не судит.
doc_header_names_its_declaration.go — разбор шапок объявлений на ОДИН факт: то ли объявление названо шапкой, над которым она стоит.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Шапка этого дерева пишется формой «Имя — что это»: имя стоит первым словом, и по нему читатель находит объявление, не разбирая тело. Форма даёт и обратное: шапка, отвязавшаяся от своего объявления, продолжает выглядеть исправной.
Отвязывается она одним движением — между шапкой и её объявлением вставляют новое объявление со СВОЕЙ шапкой, а пустая строка между двумя блоками теряется. Go склеивает соседние строки комментария в ОДНУ группу, и вся она достаётся объявлению снизу. Тогда `go doc` печатает чужую шапку у одного имени и НИ ОДНОЙ у другого — при том что текст обеих на месте и дословно верен.
Второй путь тот же по исходу: объявление переименовали, шапку не тронули.
Почему это не косметика. Читатель, которому шапка уже ОТВЕТИЛА, что перед ним, дальше не проверяет — ровно как с комментарием о защите (`guard_named_in_comment.go`). Наблюдалось на посадочной настройке: шапка `APIServerConfig` с разбором двух форм адреса слушателя стояла над `SubscriptionConfig`, а у самой `APIServerConfig` шапки не было вовсе (kaname#118). Перепись по прод-дереву нашла тот же класс ещё в 22 местах.
───────────────────────────────────────────────────────────────────────────── ЧТО СЧИТАЕТСЯ ШАПКОЙ — ФОРМА НАЗВАНА, А НЕ ПОДРАЗУМЕВАЕТСЯ
Шапкой считается первая строка группы комментария вида
Имя — текст (тире, длинное) Имя – текст (тире, среднее) Имя - текст (дефис)
где «Имя» — идентификатор Go. Разделитель обязателен: без него первое слово прозы («Package», «Returns») стало бы находкой на ровном месте.
───────────────────────────────────────────────────────────────────────────── ФОРМЫ ОБЪЯВЛЕНИЯ ПЕРЕЧИСЛЕНЫ ПОИМЁННО
Форма, о которой распознаватель не знает, даёт не красное и не зелёное, а МОЛЧАНИЕ: объявление уезжает вне наблюдения. Читаются ВСЕ формы, у которых шапка вообще бывает:
func F(…) — FuncDecl func (r T) M(…) — FuncDecl с получателем; имя — метода type T … — GenDecl с одним TypeSpec, шапка на GenDecl type ( A …; B … ) — блок; шапка на КАЖДОМ TypeSpec отдельно const C = … / var V = … — GenDecl с одним ValueSpec, шапка на GenDecl const ( A = …; B = … ) — блок; шапка на КАЖДОМ ValueSpec отдельно
───────────────────────────────────────────────────────────────────────────── ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО, А НЕ СПРЯТАНО
- **шапка без разделителя** — каноническая форма Go «// F returns …». В этом дереве её почти нет (перепись печатает обе величины: шапок формы с разделителем и объявлений с шапкой вообще), а распознать её нельзя, не принимая за имя первое слово всякой прозы;
- **объявление с НЕСКОЛЬКИМИ именами в одной спецификации** (`var a, b = …`): шапка вправе называть любое из них, поэтому находкой считается лишь то, чьё имя не совпало НИ С ОДНИМ;
- **правдивость самого текста** шапки. Гейт судит, к тому ли объявлению она прикреплена, а не то, верно ли она его описывает.
documented_setting_key_exists.go — ОПИСЬ НАСТРОЕК В ПРОЗЕ НЕ ПЕРЕЖИВАЕТ СВОЙ ПРЕДМЕТ: всякий ключ, названный описью инженерной документации, существует в дереве настроек службы.
ПРЕДМЕТ ¶
Опись — таблица «переменная · ключ настройки · умолчание · описание» — живёт в прозе и НЕ исполняется. Настройка тем временем переезжает: группа `extapi.*` ушла целиком (`internal/apps/kaname/config/mode.go` объявляет её группой, «которой в настройке НЕТ ни одной ручки»), ручки поставщика личности переехали под `authn.*`. Опись осталась прежней — и читается как действительность.
Цена не гипотетическая, и одна из строк дороже прочих: опись называла YAML- ключ ДЛЯ ПРЕДЪЯВИТЕЛЯ (`extapi.hydra.admin-token`). Ключа нет, а оператор, прочитавший опись, пишет предъявитель в YAML — то есть в файл посадки, где секрету не место. Ложная опись здесь не просто устарела: она ПРИГЛАШАЕТ сделать то, что справочник посадки прямо запрещает.
РАСПОЗНАВАТЕЛЬ — ОБЪЯВЛЕННАЯ КОЛОНКА, А НЕ ФОРМА ТОКЕНА ¶
Судится не «всё, что похоже на ключ»: в этом корпусе точкой разделены имена Go (`authz.go`, `logger.Warn`), поля JSON (`invite.mailRateLimit`), маски (`authn.*`) и пары `ключ: значение`. Измерено на этом дереве: токенов вида `<секция>.<что-то>` в прозе 107, из них НЕ ключей настройки 36 — то есть треть, и почти вся она законна.
Поэтому судится то, что объявило СЕБЯ описью: колонка таблицы, чей заголовок называет ключ настройки. Автор описи утверждает «вот ключ» — это утверждение и проверяется.
Промах словаря заголовков не даёт молчания: всякий заголовок, несущий слово `yaml` и НЕ опознанный, печатается переписью с координатой. Новое написание колонки видно числом, а не отсутствием вопроса.
АВТОРИТЕТ КЛЮЧЕЙ — ПРОИЗВОДИТЕЛЬ, А НЕ ПЕРЕЧЕНЬ ¶
Множество ключей приходит ПАРАМЕТРОМ и берётся у структуры настроек по её разметке `mapstructure` (проба строит его отражением от `config.Config`). Выписанный здесь перечень разошёлся бы с настройкой молча — на той строке, которую забыли поправить, то есть ровно на классе, который гейт и ловит.
ГРАНИЦЫ — НАЗВАНЫ, ЧТОБЫ ГЕЙТ НЕ ЧИТАЛИ ШИРЕ ¶
- Ключ, названный в прозе ВНЕ объявленной колонки, не судится. Это не упущение, а цена отказа от формы токена (см. выше); число неосмотренных токенов названо там же.
- ИСТИННОСТЬ умолчания и описания не судится: здесь держится СУЩЕСТВОВАНИЕ ключа, то есть возможность его перемерить.
- Ячейка без токена ключевой формы (`—`, «нет», проза) — не находка: автор ключа не назвал. Такие строки печатаются отдельной величиной, а не растворяются в зелёном.
envelope_composition_root.go — страж корня композиции: в не-тестовом дереве службы огибающую по потолку строит ОДНО место — композиционный корень, — и мера прогона в нём — мера настенных часов (приёмка Ф3, Р17 «Мера прогона», Ф3-53 строка стража; заказ kaname#295).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Мера прогона — вход огибающей (`passwordverify.CostMeter`). В боевом корне её мерят настенные часы вокруг самого прогона (`WallClockCostMeter`); стоимость, назначенная числом, живёт только в пробах выбора потолка. Назначенная мера в не-тестовом файле довела бы число пробы туда, где платит вход, и исход входа снова стал бы отличим по времени; второе построение — вторая огибающая со своим потолком, которого полоса входа не читает. Оба пути компилируются, и ни одна проба огибающей их не видит: у проб своя огибающая.
───────────────────────────────────────────────────────────────────────────── ЕДИНИЦА СЧЁТА — МЕСТО ПОСТРОЕНИЯ, УЗНАННОЕ РАЗБОРОМ
Местом построения считается КАЖДАЯ форма, в которой огибающая появляется:
вызов конструктора `pv.NewEnvelope` (…) под любым именем импорта
дома, при импорте с точкой и без квалификатора в
самом доме; в скобках — то же;
конструктор значением `f := pv.NewEnvelope` — мера у места не видна;
значение мимо конструктора `pv.Envelope{…}`, `&pv.Envelope{…}`,
`new(pv.Envelope)`, `var e pv.Envelope`, поле и
элемент значения, приведение — огибающая без меры
либо с мерой, которой страж не видит; в доме — всякое
такое место вне тела конструктора (литерал функции
в нём — вне тела: исполняется после построения).
Тип огибающей за указателем (`*pv.Envelope`), в доводах и результатах функций, в именованном поле и в получателе метода — не построение: значения он не заводит. Встраивание огибающей — не построение, а подставной тип (ниже).
Дом узнаётся по ПУТИ ИМПОРТА в каждом файле, а не по имени: пакет того же имени из другого пути — чужой, его конструктор построением не считается, а его мера на месте меры дома — иная мера.
Мера судится у места вызова: довод конструктора, чья позиция ВЫВЕДЕНА из объявления (единственный параметр типа меры), обязан быть мерой настенных часов дома — селектором, в скобках либо приведением к типу меры. Всё иное — литерал функции, метод меры пробы, переменная, довод обёртки — иная мера. Обёртка, принимающая меру доводом и строящая огибающую внутри, краснеет консервативно: у места построения мера — идентификатор, и что в него положили, страж не прослеживает.
───────────────────────────────────────────────────────────────────────────── ЗАПИСЬ ПОЛЯ МЕРЫ — ТОЛЬКО ДОВОДОМ КОНСТРУКТОРА
Мера у места построения — мера огибающей, лишь пока в поле меры ложится довод меры конструктора и ничто иное. Поле ВЫВЕДЕНО из объявления огибающей (единственное поле типа меры). Законная запись одна: довод меры — тем же именем, без переписывания — в теле самого конструктора, не в литерале функции. Всякая иная запись поля в доме — присваивание (и кортежем), взятие адреса, поле или позиция в составном литерале, цикл по диапазону — красное с координатой и выражением: сеттер, позванный корнем после построения, меняет меру мимо довода, который страж судит. Переписанный или затенённый в теле конструктора довод меры — тоже красное; конструктор, не кладущий довода в поле, — красное с координатой конструктора.
Носитель меры в доме один — поле меры, и вход в него один — довод конструктора. Всякое иное обращение к типу меры в доме — переменная пакета, которую корень пишет после построения, довод сеттера, исход геттера, поле иной структуры, приведение — и всякий функциональный тип подписи меры, записанный без её имени, кроме объявления функции и литерала, — красное с координатой: второй носитель доводит до прогона меру мимо судимого довода. Геттер краснеет консервативно.
───────────────────────────────────────────────────────────────────────────── ПОДСТАВНОЙ ТИП НА МЕСТЕ ПОРТА
Полоса входа принимает огибающую портом; методы порта ВЫВЕДЕНЫ из его объявления (`PortDir`, `PortInterface`). Не-тестовый метод с именем и арностью метода порта на типе помимо огибающей дома — реализация порта вне дома: целиком (исход допуска под псевдонимом ли, из третьего пакета ли — тип исхода не читается) или частью, подменой одного метода поверх встроенного порта либо встроенной огибающей. Встраивание огибающей дома в структуру — по значению и по указателю, вне дома и в нём — красное само: встроивший исполняет порт методами огибающей и подменяет любой из них.
───────────────────────────────────────────────────────────────────────────── ОБХОД СИСТЕМЫ ТИПОВ
Неэкспортированное поле меры пишется мимо дома только мимо системы типов: импорт `unsafe` в файле, обращающемся к дому, и директива `//go:linkname`, называющая символ дома, в любом не-тестовом файле — красное с координатой.
───────────────────────────────────────────────────────────────────────────── ПОСЫЛКА — ОТКАЗ, А НЕ МОЛЧАНИЕ
Конструктор объявлен в доме ровно раз и несёт ровно один довод типа меры, и у довода есть имя; мера настенных часов, тип огибающей и тип меры объявлены в доме, тип меры — функциональный; у огибающей ровно одно поле типа меры, оно неэкспортировано, и его имя в доме несёт одно поле — тогда запись вне дома не компилируется, а в доме узнаётся по имени однозначно; порт объявлен ровно раз, методы перечислены без встраивания, и каждый объявлен у огибающей дома с той же арностью; `go.mod` корня дерева называет модуль; корень композиции несёт не-тестовые файлы. Не держится — ErrEnvelopeRootPremise с тем, что не нашлось. Пустой обход — ErrEmptyTraversal. «Построений 0» — находка о дереве, а не отказ посылки.
Положительный контроль того же прогона: законная запись поля меры и методы порта у огибающей дома узнаются теми же распознавателями, что ищут нарушение; перепись печатает их координаты.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
- Граница — РОД ФАЙЛА, суффикс `_test.go` (`ProductionGoFile`). Тег сборки не читается: не-тестовый файл под `//go:build ignore` судится, помощник пробы в не-тестовом файле краснеет по замыслу — Р17 проводит границу по роду файла, а не по имени меры.
- Единица — синтаксическое место. Второе построение во время работы через то же место (цикл, двойной вызов сборщика корня) статически не видно.
- Судится ИМЯ меры, путь довода в поле меры и носители меры в доме; что прогон делает с мерой поля дальше, — нет. Тело меры корня держит проба TestWallClockCostMeter_MeasuresTheWholeRunItCalls; то, что стоимость класса берётся мерой поля, — TestEnvelope_ADearerClassRaisesTheFloorACheaperOneDoesNot (назначенная пробой стоимость доходит до потолка).
- Тип довода и исхода не выводится: подставной метод узнаётся по имени и арности метода порта, и метод с тем же именем и арностью, порта не исполняющий, краснеет консервативно. Порт — объявленный спекой: иной порт над огибающей стражу неизвестен. Подпись меры сличается текстом типов: носитель под псевдонимом типа довода не узнаётся. Копия значения огибающей (`c := *e`) новой меры не заводит и не судится.
- Область обхода — `OutsideTraversal`: не-тестовые файлы под её сегментами не судятся, и перепись печатает их числом.
- Состав — индекс git: файл, не внесённый в индекс, стражу невидим.
failure_reset_sole_writer.go — разбор «кто обнуляет счёт неверных предъявлений по адресу» (приёмка Ф12 Р7 редакция 11, `docs/engineering/acceptance/second-factor-totp-and-recovery-codes.md`; Ф3 Р10 редакция 11, `docs/engineering/acceptance/login-lane-issues-our-session-and-logout-ends-it-server-side.md`; задача PRO-Robotech/kaname#287).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Счёт по адресу обнуляет вход, ЗАВЕРШЁННЫЙ до уровня всех заведённых у личности факторов. Условие это — свойство того, какие СТРОКИ СПОСОБОВ ВХОДА заведены, и того, что ПРЕДЪЯВЛЕНО в сессии; свойством полосы, из которой обнуление зовётся, оно не является. Поэтому решать его обязано ОДНО место, и всякая полоса обязана проходить через него.
Полоса, зовущая обнуление напрямую, решает это условие СВОИМ путём — либо не решает вовсе, и тогда успех одного первого фактора открывает свежее окно подбора второго. Класс не ловится ни сборкой, ни типом: прямой вызов компилируется и выглядит ровно так же, как правильный.
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ ОБРАЩЕНИЕ, А НЕ ИМЯ ФАЙЛА
Разбор ищет обращения к имени порта и классифицирует КАЖДОЕ по узлу:
w.ResetFailures(ctx, …) ВЫЗОВ — судится домом f := w.ResetFailures ЗНАЧЕНИЕ-МЕТОД — судится домом (вызовут позже) ResetFailures(ctx, …) в интерфейсе ОБЪЯВЛЕНИЕ — порт, молчит func (w *…) ResetFailures(…) РЕАЛИЗАЦИЯ — адаптер, молчит
Значение-метод названо отдельной формой намеренно: распознаватель, знающий только прямой вызов, пропустил бы обнуление, вынесенное в переменную, — и пропустил бы МОЛЧА, не дав ни красного, ни зелёного (`.claude/rules/testing.md` §«Гейт на класс», п. 7).
───────────────────────────────────────────────────────────────────────────── ГРАНИЦА НАЗВАНА
Гейт ловит БОЛЬШЕ обещанного и слеп там, где обещает видеть: по имени он находит и формы сверх четырёх перечисленных (отложенный вызов, выражение метода), а стережёт он «имя не упомянуто селектором вне дома» — не то же, что «счёт не обнуляется без вопроса об уровне». Первое влечёт второе, пока обнулить счёт можно только селектором этого имени, а это свойство того, как дерево написано сегодня, а не следствие разбора.
Эта посылка судится ОТДЕЛЬНО, по дереву, а не утверждается (`JudgeFailureRowRemovals` ниже), и по признаку, а не по началу оператора: текст, называющий таблицу счёта и несущий изменяющее слово в любом месте, законен ровно в двух местах — удалением по ключу в реализации порта и по возрасту в уборщике `SweepAgedFailures`; всякий иной — находка, как и текст с таблицей, который разбор не классифицирует. Пока посылка верна, молчание гейта значит то, что обещает, — в пределах её границы, названной ниже.
Границы остаются, обе названы:
разбор судит ИМЯ, а не тип приёмника — одноимённый метод чужого типа был бы сочтён обращением к порту, и гейт покраснел бы на невиновном; обёртка ВНУТРИ дома гейту невидима: он судит координату файла, поэтому второй безусловный путь, заведённый в самом доме, он не увидит — это держит таблица решений `completed_login_test.go`, а не он.
У посылки своя граница: она судит ЗНАЧЕНИЕ строкового выражения, которое сворачивается при разборе дерева, — литерала, склейки, имени константы либо связанного имени пакета этого модуля. Ей не видны оператор, собранный во время исполнения, — вызовом (`fmt.Sprintf`, `strings.Join`), в переменной функции, присваиванием переменной пакета, из константы чужого модуля (судятся тогда лишь его звенья-литералы, и имя таблицы с изменяющим словом в РАЗНЫХ звеньях не видно), — и оператор вне Go (триггер, правило либо функция миграции).
family_revocation_reason_writers.go — разбор «у каждого слова словаря причин отзыва семейства есть писатель» (задача PRO-Robotech/kaname#339, п.1 предиката снятия; приёмка `docs/engineering/acceptance/client-revocation-has-its-own-family-revocation-reason.md`, KN-FRV-17, решение Р12).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Словарь причин отзыва семейства ЗАКРЫТ: он перечисляет исчерпывающе, и ограничение схемы принимает ровно его. Слово, которого никто не пишет, превращает перечень в обещание — оно читается как работающее и не наступает ни при каком входе. Два таких слова жили в словаре со дня его заведения, и заметить это было нечем: имя без писателя компилируется, проходит пробы схемы и молчит.
───────────────────────────────────────────────────────────────────────────── ЧТО СЧИТАЕТСЯ ПИСАТЕЛЕМ — ДВЕ ВЕТВИ
- на константу домена этого слова ссылается УЗЕЛ разбора — селектор пакета домена (`domain.<имя>`) — в не-тестовом `.go` вне самого домена;
- причина фундамента того же написания сопрягается адаптером порта отзыва с этим словом (`ceremonyport.FamilyReasonOf`): такое слово пишется по значению и константы не называет.
Без второй ветви гейт назвал бы беспризорным слово, у которого писатель есть. Сопряжение вызывающий подаёт функцией: разбор о нём ничего не знает и фундамента не импортирует.
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ УЗЕЛ, А НЕ ТЕКСТ
Упоминание константы в комментарии или в строке писателем не является: комментарий в дерево узлов не входит, строка — узел литерала, а не селектора. Селектор судится по ПУТИ ИМПОРТА, а не по имени пакета: псевдоним импорта домена — та же ссылка, одноимённый селектор чужого пакета — не она. Имена констант и их значения берутся из объявлений домена, а не выписываются здесь: своя копия была бы вторым объявлением словаря.
───────────────────────────────────────────────────────────────────────────── ПУСТОЙ ОБХОД — ОТДЕЛЬНЫЙ ИСХОД
Ноль разобранных файлов, ноль файлов, импортирующих домен, либо пустой перечень — это «ноль прочитанного», а не «ноль находок», и такой исход обязан быть КРАСНЫМ.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦА НАЗВАНА
Импорт домена точкой, затенение имени импорта локальной переменной и слово, собранное из частей строки, разбор не видит. В дереве таких путей к словарю нет; первое и третье — довод держать ссылку селектором, каким она и написана.
family_verdict_single_reader.go — «отозвано ли семейство выпуска» решает ОДИН читатель, и каждая поверхность предъявления спрашивает его через ОДНО правило (задача PRO-Robotech/kaname#319, решение К10 вариант А).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ И ПОЧЕМУ ОН ГЕЙТ, А НЕ ВНИМАНИЕ
Решение о доступе по семейству принимают три поверхности: `IsRevoked` службы отзыва, авторитет отзыва на внутреннем слушателе и читатель предъявленного на публичном. Одно решение держится одним читателем только тогда, когда второго написания нет нигде:
- оператор, читающий запись выпуска, — ОДИН литерал в дереве. Второй литерал (свой запрос у одной из поверхностей) разошёлся бы с первым молча — например, забыв, что снятое семейство оставляет у записи ПУСТУЮ живость, — и обе копии были бы зелены на своих пробах;
- порт чтения семейства зовёт ТОЛЬКО правило (`internal/tokenrevocation`). Поверхность, позвавшая порт мимо правила, завела бы свою политику на пустой идентификатор и на неответ хранилища;
- каждая поверхность ЗАКРЫТОГО перечня зовёт правило. Поверхность, правила не зовущая, семейства не спрашивает вовсе;
- у решения нет ВТОРОГО ХРАНИЛИЩА. Правило читает утверждения токена, и каждое прочитанное утверждение решено поимённо: ключ отсечки субъекта или клиента либо идентификатор выпуска — единственный вход к записи выпуска. Утверждение, несущее семейство, превратило бы отсечку по ключу во второе хранилище решения о семействе со своим писателем и своей уборкой (К10, вариант А: семейство судит только запись выпуска). Перечень сверяется в обе стороны: решённое утверждение, которого правило больше не читает, — тоже находка (правило без `jti` о семействе не спрашивает);
- у решения нет ПУСТОГО хранилища. Отсутствие записи правило читает как «семейству не принадлежит», поэтому выпуск церемонии, не пишущий запись, выпускает токен, который отзыв семейства не снимает. Реализация порта выпуска фундамента (`IssueAccessToken` либо `StoreAccessToken` из `corelib/oauthceremony`, порты есть с тега v1.10.0-rc.1) при нуле вызовов писателя записи в дереве — находка. Сколько реализаций в дереве, печатает перепись («реализаций порта выпуска N»), а не этот заголовок: число меняется с деревом. Ноль реализаций законен — выпускать нечему, и ось о нём молчит. Предпосылка оси — объявление писателя в дереве: без него ось ослепла бы молча.
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ УЗЕЛ РАЗОБРАННОГО ДЕРЕВА, А НЕ ТЕКСТ ФАЙЛА
Литерал — узел `BasicLit`, вызов — узел `CallExpr`. Упоминание в комментарии (в том числе в этом) находкой не является.
Читающим считается литерал, который ОТКРЫВАЕТСЯ словом `SELECT` либо `WITH` и называет таблицу выпусков. Вставка и уборка открываются иначе и читателями не считаются: у них другой предмет.
Утверждение считается прочитанным правилом, когда в файле каталога правила индексируется параметр типа `jwt.MapClaims`: литералом, константой пакета либо переменной цикла по перечню-литералу пакета.
───────────────────────────────────────────────────────────────────────────── ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО
- оператор, собранный из кусков во время исполнения: разбор читает литерал, а не результат конкатенации. Довод держать оператор ОДНОЙ константой, каким он и написан;
- чтение таблицы выпусков ПОДЗАПРОСОМ внутри вставки, правки или удаления: такой литерал открывается не словом чтения. В дереве таких нет;
- вызов порта через переменную функционального типа (`f := r.FamilyRevoked` без вызова на месте): узел вызова здесь другой. В дереве таких нет;
- утверждение, прочитанное правилом не индексом параметра `jwt.MapClaims`: методом (`GetIssuedAt` — момент выпуска, ключом не служит), через переменную иного объявленного типа или через копию состава. Индекс, имя которого разбор не разрешил, — находка, а не молчание;
- второе хранилище семейства ВНЕ правила — поверхность, сама читающая утверждение семейства и спрашивающая хранилище мимо правила. Его ловит только ось «поверхность зовёт правило» и пробы поверхностей, а не эта;
- что писатель позван ИМЕННО на пути выдачи и ДО ответа, и что этот путь собран: ось судит, что вызов в дереве есть. Порядок на уровне адаптера держит `TestIssue_RecordsTheIssuanceInItsFamilyBeforeTheTokenLeaves` (`internal/ceremonyport`), сборку — гейт перечня источников отзыва службы (`TestContractListsFamilyAsProducedTodayOnlyWhenIssuanceIsRecorded`), путь запроса — сборка церемонии (kaname#407);
- порт выпуска под другим именем метода: имена взяты из фундамента (`corelib/oauthceremony`, порты есть с тега v1.10.0-rc.1), и переименование там ослепило бы ось.
Перечень границ, названный не полностью, хуже отсутствующего: он создаёт уверенность.
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).
guard_named_in_comment.go — разбор одного файла на ДВА РАЗНЫХ факта о защите: названа ли она КОММЕНТАРИЕМ и вызвана ли ВЫРАЖЕНИЕМ.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Комментарий, противоречащий коду, — не косметика. В обычном случае следующий читатель «чинит» код под неверный комментарий. Здесь хуже: комментарий уже ОТВЕТИЛ на вопрос «закрыт ли этот сегмент защитой», поэтому читатель не идёт проверять, и пробел остаётся незамеченным ИМЕННО ПОТОМУ, что о нём написано.
Класс наблюдался дважды и в двух разных видах. В монорепо: файл в пакете ролей утверждал, что сегмент глагола закрывается словарём домена, тогда как во всём пакете это имя встречалось РОВНО ОДИН раз — в самом этом комментарии. При выносе службы (kacho#2597): прод-код и приёмки службы продолжили называть держателями гейты монорепо, снятые вместе с каталогом, — то есть комментарий называл защиту, которой не существует ни в одном репозитории.
───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ УЗЕЛ РАЗБОРА, А НЕ ПОДСТРОКА
Поиск по подстроке нашёл бы имя в комментарии, который эту же защиту ОБЪЯСНЯЕТ, и счёл бы её присутствующей — то есть гейт зеленел бы на собственном объяснении. Поэтому два факта читаются РАЗНЫМИ средствами:
упоминание — ТОЛЬКО из узла комментария (ast.CommentGroup);
наличие — ТОЛЬКО из узла-идентификатора выражения (ast.Ident) и ТОЛЬКО
из прод-кода: вызов защиты внутри пробы её в прод-коде не создаёт.
Строковый литерал, несущий то же имя, наличием НЕ является: он узел ast.BasicLit, а не ast.Ident, и разбор его не засчитывает by construction.
───────────────────────────────────────────────────────────────────────────── ФОРМЫ ЗАПИСИ — ПЕРЕЧИСЛЕНЫ, А НЕ ПОДРАЗУМЕВАЮТСЯ
Форма, о которой распознаватель не знает, даёт не красное и не зелёное, а МОЛЧАНИЕ. Поэтому обе стороны перечислены поимённо, и по каждой стоит утверждение инъекции.
Формы показаны на ВЫМЫШЛЕННОМ имени GuardedCall, а не на записи действующего реестра, и это не стиль: godoc — тоже комментарий, и пример на живом имени сделал бы ЭТОТ ФАЙЛ находкой собственного гейта. Класс поймал себя сам при первом же прогоне после индексации (kacho#2597).
Упоминание в комментарии — четыре формы:
bare GuardedCall — имя прозой qualified domain.GuardedCall — имя с квалификатором пакета call GuardedCall() — имя со скобками backtick `GuardedCall` — имя в обратных кавычках
Наличие в выражении — четыре формы, и все четыре суть узел ast.Ident:
GuardedCall(v, t) прямой вызов domain.GuardedCall(v, t) вызов с квалификатором (Sel — тот же ast.Ident) f := GuardedCall значение функции f := domain.GuardedCall значение с квалификатором
───────────────────────────────────────────────────────────────────────────── ГРАНИЦА ИМЕНИ — НЕСУЩАЯ
Совпадение считается по ГРАНИЦЕ идентификатора, а не по вхождению подстроки: иначе `GuardedCallStrict` засчитывался бы упоминанием `GuardedCall`, и находка приходила бы на имя, которого комментарий не называл.
identity_growth_reader.go — разбор: у величины роста числа личностей есть ЧИТАТЕЛЬ, и он назван.
Предмет ¶
Величина, которую никто не смотрит, наблюдаемостью не является: она печатается на витрине, ничего не утверждает и создаёт уверенность, которой нет. Задача, заведшая семейство, просила именно наблюдаемость — «число личностей и скорость их появления видны, превышение порога порождает оповещение», — и ряд без правила закрывал бы её формой, а не существом.
Что считается читателем ¶
ТОЛЬКО выражение правила оповещения (`expr:`). Упоминание имени ряда в пояснении к тревоге или в таблице метрик читателем НЕ является: пояснение не срабатывает. Различие несущее — оба текста лежат в одном файле, и разбор, ищущий имя по всему документу, зеленел бы на ряде, о котором лишь написано.
Граница названа ¶
Судится ОДНО семейство, и его состав выводится из файла коллектора, а не из выписанного перечня. На прочие ряды службы разбор не распространяется, и это не оплошность: у части из них правил сегодня нет, и заведение им читателей — отдельная работа с отдельным предметом. Расширение на всё семейство метрик обязано прийти ВМЕСТЕ с этими правилами, иначе оно потребует перечня исключений — то есть заведёт ровно ту форму, в которой послабление переживает свой предмет.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/identitygrowthreader_test.go` (семейство снято вынесением службы, `kacho#2597`; предмет жив здесь — задача #17). Изменилось: координаты обоих операндов (приставки `services/iam/` в самостоятельном клоне нет), разбор вынесен из пробы в пакет `check`, приставка рядов берётся у того же имени, которым пакет уже называет свой словарь. Осталось дословно: имя гейта (`TestIdentityGrowthMetricsHaveANamedReader`), разбор выражений и граница «исполняемое против объяснения».
Близнец в платформе снят вместе с предметом — там этих рядов больше нет, поэтому пары файлов этот порт НЕ заводит.
injection_named_exists.go — разбор: доказательство способности упасть, НАЗВАННОЕ пробой, обязано существовать (kacho#2479).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Проба, чья шапка говорит «способность упасть доказана инъекцией — такой-то файл», делает утверждение о ДЕРЕВЕ. Утверждение это не компилируется и никем не сверяется: файл переименовали, унесли вместе с рефакторингом либо не написали вовсе — а шапка продолжает обещать доказательство. Гейт, потерявший способность краснеть, на чистом дереве выглядит РОВНО ТАК ЖЕ, как исправный, поэтому обещание доказательства читается как само доказательство.
Замер, из которого разбор выведен: на ревизии заведения упоминаний в комментариях было 122, не резолвилось ОДНО — шапка гейта осей адреса называла файл, которого в дереве не было с первого её дня.
───────────────────────────────────────────────────────────────────────────── У ЭТОГО РАЗБОРА ЕСТЬ БЛИЗНЕЦ В ПЛАТФОРМЕ — И ЭТО НАЗВАНО, А НЕ УМОЛЧАНО
Тот же разбор, поднятый до корня МОНОРЕПО, живёт в `tools/injectionproofgate` (задача kacho#2519): этот обходит корень своего модуля и о платформе не высказывается — в самостоятельном клоне службы монорепо нет вовсе. Обещания соседних модулей платформы этому модулю не принадлежат.
Свести обе реализации в одну сегодня НЕЛЬЗЯ: модуль службы пинит платформу псевдоверсией, поэтому импортировать пакет, которого в пинованной ревизии ещё нет, он не может. Предикат сведения: пин указывает на ревизию, где тот пакет существует; до этого две реализации об одном предмете живут рядом осознанно.
───────────────────────────────────────────────────────────────────────────── СУДЯТСЯ КОММЕНТАРИИ, И ЭТО РЕШЕНИЕ, А НЕ УПРОЩЕНИЕ
Координата доказательства пишется ПРОЗОЙ — это её законное место, и разбор читает разобранные группы комментариев, а не сырой текст файла. Строковые литералы намеренно НЕ судятся: в них живут синтетические имена, которые инъекции кладут во временные каталоги, и дерева они не называют вовсе. Судить их значило бы краснеть на чужой фикстуре — то есть на собственном доказательстве.
Величина «в строках» всё равно печатается переписью: молчание о целом виде вхождений неотличимо от их отсутствия.
───────────────────────────────────────────────────────────────────────────── ЗАКОННЫХ ФОРМ КООРДИНАТЫ ТРИ, И РАСПОЗНАВАТЕЛЬ ЗНАЕТ ВСЕ ТРИ
Форма, о которой он не знает, даёт не красное и не зелёное, а МОЛЧАНИЕ. Измерено на этом дереве: наивный резолвер («имя рядом с называющим») дал 4 непопадания из 138, и все четыре оказались ЗАКОННЫМИ формами, а не находками.
СОСЕД `<имя>_injection_test.go` — файл в каталоге называющего;
ПО МОДУЛЮ то же имя, но доказательство лежит в ДРУГОМ пакете модуля
(проба одного пакета ссылается на инъекцию соседнего);
КООРДИНАТОЙ `internal/<пакет>/<имя>_injection_test.go` — путь от корня
МОДУЛЯ службы, а не от корня монорепо: в самостоятельном клоне
приставки `services/iam/` нет, и счёт от неё указывал бы наружу
дерева.
Имя в примерах — ОБРАЗЕЦ с угловыми скобками, а не координата, и это не подгонка текста под инструмент: координата, названная в прозе, есть утверждение о дереве, и выдуманная — ложное. Разбор судит объявленные координаты, поэтому пример обязан не выглядеть ею.
issue_ref_prefix.go — ссылка на задачу ДРУГОГО репозитория несёт его имя (задача kaname#387).
Предмет ¶
Служба вынесена из монорепо вместе с историей, и в её дереве остались ссылки вида `#<N>` на задачи монорепо. На GitHub такая ссылка разрешается ВНУТРИ этого репозитория: номер вне диапазона задач службы даёт 404, номер из диапазона — чужую задачу службы, и оба исхода молчаливы. Ссылка без префикса здесь значит задачу службы; задача монорепо пишется `kacho#<N>`, воркспейса — `kacho-workspace#<N>`, прежнего трекера `kacho-iam` (история до монорепо) — `kacho-iam#<N>`.
Что гейт умеет утверждать и чего — нет ¶
Номер ВЫШЕ потолка задач службы задачей службы быть не может — такая ссылка без префикса есть находка без чтения намерения. Номер В ДИАПАЗОНЕ гейт не судит: `#337` равно законно значит задачу службы и неверно — задачу монорепо с тем же номером, и различить их можно только по референту (сверка по истории строки и заголовку задачи — работа kaname#387, не машинное правило). Это граница утверждения, а не дыра: она названа и в шапке пробы, и в её выводе («ссылок без префикса N, из них выше потолка M»).
Форма ссылки — та же, что у предиката задачи ¶
git grep -hIoE '(^|[^A-Za-z0-9/_#-])#[0-9]{3,5}\b'
с одним сужением: `&` перед `#` — числовая сущность разметки (`{`), а не ссылка. Цифр три–пять: короче — пункты и заголовки, длиннее — не номер задачи. Знак после номера — не буква, не цифра и не `_`: `#15161d` — цвет, не ссылка.
Предикат задачи вычитает ещё `docs/changes`; гейт этого исключения НЕ несёт: на дне заведения голых ссылок выше потолка там ноль, а исключение, которому нечего прощать, — слепая зона без срока.
job_knob_has_a_reader.go — разбор: у КАЖДОЙ величины секции фоновых заданий есть читатель вне пакета настроек (задача kacho#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 — разбор инструкций установки на предмет процедуры, которой оператор сохраняет строки таблицы ПЕРЕД её сносом (задача продукта kacho#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 — разбор: пакет, чей дублёр области видимости объявляет её НЕОГРАНИЧЕННОЙ, обязан называть живого держателя настоящего отбора.
Предмет, и почему требуется именно это ¶
Снисходительность здесь НАМЕРЕННА, и её цена названа в самих пробах: строк выдачи у их фикстуры нет вовсе, поэтому назвать кандидатов она не может, а сузив набор до пустого — вернула бы пустую страницу везде и стёрла бы предмет своих же проб (вердикт: каким отношением судится строка страницы). Требовать «почините дублёров» значило бы сломать работающее.
Опасно другое. Отбор кандидатов держит РОВНО ОДИН пакет, и держит он его на настоящей базе. Выпадет он из набора — по недосмотру, из-за недоступных контейнеров, при переименовании — и свойство перестанет проверяться НИГДЕ, а ссылки на него останутся и будут читаться как покрытие. Форма остаётся, содержание исчезает молча.
Поэтому разбор требует не сужения у дублёров, а РЕЗОЛВИМОСТИ ссылки: снятие держателя роняет прогон с ЕГО ИМЕНЕМ, а не тишиной.
Почему разбор синтаксиса для одной части и комментарии для другой ¶
Снисходительность — свойство ИСПОЛНЯЕМОГО кода (значение поля в литерале области), и ищется разбором: поиск подстроки нашёл бы слово в комментарии, объясняющем эту же проверку. Ссылка на держателя — наоборот, живёт ИМЕННО в комментарии, потому что адресована читателю; её и ищем в комментариях, разобранных парсером, а не в сыром тексте файла.
ДВА написания координаты — обе законны, и разбор обязан знать обе ¶
Здесь порт расходится с монорепошным оригиналом, и расходится ЗАМЕРОМ. Там координата была одна — `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).
login_verifier_containment.go — ЯДРО гейта: проверочный материал способа входа выходит из своего типа ТОЛЬКО в названном файле и не уходит из него мимо объявленного потребителя, а таблицу секрета называет ТОЛЬКО её адаптер (фаза Ф2, `kacho#1268`).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Материал пароля живёт в типе `domain.LoginVerifier`, который не печатается, не пишется в журнал и не сериализуется: каждый общий путь вывода отдаёт заглушку либо отказ (`internal/domain/login_method_test.go`). Выход у материала ОДИН — метод `Reveal`, — и он нужен ровно тем, кто кладёт материал в базу и сверяет с ним предъявленное.
Правил три:
- ВЫХОД вне разрешённого ФАЙЛА — находка: материал достан строкой и дальше ничем не защищён.
- ВТОРОЙ ЧИТАТЕЛЬ КОЛОНКИ — выражение вне файла-владельца, называющее таблицу секрета, — находка: он читает материал строкой, минуя тип.
- ВЫНОС — материал из разрешённого файла, имя таблицы из файла-владельца уходят туда, куда гейт дальше не смотрит, — находка. Разбор потока — `login_verifier_flow.go`, один на оба предмета.
Разрешение даётся ФАЙЛУ, а не пакету: пакет адаптера — 70 не-тестовых файлов, и разрешение каталогу пропускало выход в любом из них.
───────────────────────────────────────────────────────────────────────────── ПЕРЕПИСЬ НАПИСАНИЙ — ЧТО РАСПОЗНАВАТЕЛЬ ЗНАЕТ, ВЫВЕДЕНО ИЗ ГРАММАТИКИ
Судится РАЗБОРОМ, а не текстом: комментарий Go, объясняющий выход, и строка с его именем законны и обязаны остаться — гейт, краснеющий на собственном объяснении, снимают первым.
Правило 1 — выход записывается ОДНОЙ формой, селектором с его именем: вызов, значение метода, выражение метода, метод через интерфейс и через встроенное поле.
Правило 2 — имя таблицы. Строковое значение Go (литерал в двойных и в обратных кавычках, с экранированием Go внутри) судится ГРАММАТИКОЙ SQL — `sql_relation_name.go`: имя без кавычек в любом регистре, в кавычках побайтово, `U&"…"` с UESCAPE, со схемой и без, внутри строки SQL (`'…'::regclass`, `EXECUTE '…'`, E-, U&-, N-, долларовая строка, продолжение, склейка `||`). Каким выражением Go это значение записано:
литерал "…" и `…`
склейка `+` литералов, констант, приведений `string(…)`
и к строковому типу корпуса; судится свёрнутое
значение и отдельно каждое звено
связанное имя константа либо переменная уровня пакета, чьё
значение называет таблицу, — в том числе
повторённая неявно в группе `const (…)`; сама
константа владельца — такое имя
локальная константа `const` внутри функции участвует в склейке
селектор другого пакета `пакет.Имя` — с именем пакета, псевдонимом импорта и
через импорт с точкой
Правило 3 — вынос: возврат, именованный результат, переменная пакета (своего и чужого, её поле, элемент, ключ карты), память параметра и получателя, канал, аргумент функции чужого файла, непрозрачный вызов без объявления потребителя, встроенный вывод. Результат ПРЕОБРАЗУЮЩЕГО потребителя несёт предмет и ведётся дальше (kaname#139). Полный перечень и то, что несёт предмет, — шапка `login_verifier_flow.go`. Переменная пакета в разрешённом файле, чьё значение обращается к выходу, — вынос материала сама по себе.
Объявление предмета (имя выхода, файл и тип, где он объявлен, имя таблицы, разрешённые файлы, потребители) приходит ПАРАМЕТРОМ из файла пробы: литерал имени таблицы в этом файле сделал бы гейт своей же первой находкой, а файл пробы в корпус не входит by construction.
───────────────────────────────────────────────────────────────────────────── ПРЕМИСЫ — ОТКАЗ, А НЕ МОЛЧАНИЕ
- выход объявлен РОВНО ОДИН раз, в названном файле, на названном типе. Иначе селектор с тем же именем означает не этот выход, и перепись мерит чужой метод;
- файл-владелец таблицы называет её хоть раз: иначе второе правило ослепло;
- каждый разрешённый файл выход ИСПОЛЬЗУЕТ, каждый объявленный потребитель получает предмет: разрешение без предмета — место, куда вызов вносят незамеченным (послабление обязано истекать само);
- каждый потребитель объявлен с ВИДОМ и причиной, чистая позиция преобразующего — с причиной и не отрицательна: иначе отказ прогона, а не «находок ноль». Чистая позиция за последней позицией результата — находка (ей нечего разрешать), где число позиций синтаксис называет.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
- ФАЙЛЫ ПРОБ НЕ СУДЯТСЯ: пробе законно достать материал, чтобы сверить его побайтово, а фикстуре инъекции — написать форму дефекта. Файл пробы — `*_test.go` и оснастка проб `internal/testsupport/` (отбор `ShippedGoFile`): общая фикстура многих пакетов лежит в обычном файле, потому что `*_test.go` чужого пакета не импортируется (kaname#816). Что прод-сборка оснастку не импортирует, держит `ProbeToolingImports`.
- ИМЯ, СОБРАННОЕ ВО ВРЕМЯ ИСПОЛНЕНИЯ, НЕ УЗНАЁТСЯ: `fmt.Sprintf`, `strings.Join`, `+=` к переменной, срез байтов — это поток данных, а не синтаксис. В дереве такой формы нет; появится — гейт промолчит.
- ГРАНИЦЫ РАЗБОРА ПОТОКА — срез либо карта, скопированные присваиванием, материал, прочитанный владельцем из базы до обёртки в тип, отражение — названы в шапке `login_verifier_flow.go`.
- ГРАНИЦЫ РАСПОЗНАВАТЕЛЯ SQL — имя, собранное во время исполнения, аргумент `format('%I', …)` — названы в шапке `sql_relation_name.go`.
- ПУТЬ ВНЕ GO НЕ СУДИТСЯ: базу судит соседний гейт схемы `internal/repo/kaname/pg` `TestLoginVerifierStaysInsideTheSchema`, тем же распознавателем имени.
login_verifier_flow.go — РАЗБОР ПОТОКА предмета внутри файлов, которым он разрешён: материала способа входа — внутри разрешённых файлов, имени таблицы секрета — внутри файла-владельца. Предметов два, разбор один: вынос у них записывается одними и теми же формами, и вторая копия разбора разошлась бы с первой молча — ровно на той форме, которую знает одна из копий.
───────────────────────────────────────────────────────────────────────────── ЧТО ЗДЕСЬ «ВЫНОС» — ВСЕ СТОКИ ГРАММАТИКИ GO
Значение несёт предмет, если оно им является (источник), либо собрано из несущего: склейка `+`, приведение к предобъявленному типу (строке, числу — приведение к числу не очищает: `uint8(часть[0])` — байт материала), срезу байтов либо типу корпуса, взятие адреса, разыменование, индекс, срез, утверждение типа, составной литерал с несущим элементом (у карты — и с несущим ключом), встроенные `append`/`min`/`max`, замыкание, возвращающее несущее, и его вызов на месте, РЕЗУЛЬТАТ ПРЕОБРАЗУЮЩЕГО ПОТРЕБИТЕЛЯ (ниже) и результат функции своего файла, чей возврат нёс предмет. Хранилище, куда несущее положено, несёт его дальше; обход `range` по несущему делает несущими ключ и значение. Многозначный вызов судится по ПОЗИЦИЯМ во всех пяти местах, где грамматика Go его допускает: присваивание (`a, b, ok := f()`), объявление (`var a, b = f()`), возврат функции и возврат замыкания (`return f()`), единственный аргумент (`g(f())` — позиция i результата f есть аргумент i функции g). Где число позиций синтаксис не называет (оба вызова — непрозрачные), вызов несёт предмет, если несёт ЛЮБАЯ его позиция, — строже.
Вынос — любое место, откуда предмет уходит из файла мимо гейта:
возврат функции значение возврата несёт предмет
именованный результат присваивание ему — в том числе составное и
из отложенного замыкания: оно уходит вызывающему
переменная пакета присваивание ей, её полю, её элементу; предмет
ключом её карты; переменная ДРУГОГО пакета
память параметра, получателя присваивание через них: поле, элемент,
разыменование, `copy` в них
канал отправка
вызов функции корпуса аргумент либо получатель функции или метода,
объявленных в файле, которому предмет не
разрешён (соседний файл того же пакета, другой
пакет корпуса)
непрозрачный вызов вызов, внутрь которого гейт не видит
(библиотека, метод значения, чей тип синтаксис
не называет, функция-значение), — находка, если
он не объявлен ПОТРЕБИТЕЛЕМ с причиной
встроенный вывод `panic`, `print`, `println`
память без владельца присваивание в поле результата вызова
Вызов функции СВОЕГО разрешённого файла выносом не является: предмет остаётся в файле, и разбор продолжается в её теле с отмеченными параметрами — до неподвижной точки. Обратная половина — ВОЗВРАТ СВОЕМУ ФАЙЛУ: возврат предмета из функции, которую зовёт ТОЛЬКО её файл (без получателя, неэкспортируемая, упомянута лишь вызовом и лишь в своём файле — `lvInternal`), выносом не является, и результат её вызова у вызывающего несёт предмет по позициям. Возврат из любой другой функции — вынос.
Отдать материал КОНСТРУКТОРУ ЕГО ТИПА (функция файла объявления выхода без получателя, чей результат называет тип) — не вынос, а возврат под защиту типа; перепись считает такие вызовы отдельно. Любая другая функция того же файла судится как функция корпуса.
ПОТРЕБИТЕЛЬ — непрозрачный вызов, которому предмет отдан по существу. Объявляется в `LoginVerifierSpec.OpaqueConsumers` ключом «функция → вызов» с ВИДОМ и причиной (kaname#139); объявление без вызова — находка (послабление обязано истекать само), объявление без вида — отказ прогона. Видов два:
поглощающий оператор базы, сравнение, односторонняя функция: результат
— признак исхода либо величина, из которой предмет не
восстановить; ни одна позиция результата предмета не несёт
преобразующий строковая операция, декодирование, разборщик, снятие
обёртки: результат собран ИЗ предмета и несёт его в каждой
позиции, кроме объявленных чистыми с причиной (признак
«найдено», ошибка, не несущая входа). Результат ведётся
дальше, как выход `Reveal`: часть, возвращённая из файла, —
находка, часть, отданная необъявленному вызову, — находка.
Перепись называет порознь объявленных потребителей и прослеженные результаты: «потребителей N» не говорит, сколько результатов разбор вёл.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
- ПСЕВДОНИМ ЗНАЧЕНИЕМ: указатель, взятый адресом (`p := &out; p.m = x`), и его копии прослеживаются до цели; срез либо карта, скопированные присваиванием (`ys := xs; ys[0] = x; return xs`), — нет: без типов синтаксис не отличает такую копию от копии значения.
- ИСТОЧНИК ПОТОКА МАТЕРИАЛА — ВЫХОД `Reveal`. Материал, прочитанный владельцем из базы до обёртки в тип, — строка, и её путь внутри файла гейт не видит; держит ревью единственного разрешённого файла.
- ОТРАЖЕНИЕ и `unsafe` синтаксического следа не оставляют.
- ВИД ПОТРЕБИТЕЛЯ ГЕЙТ НЕ ПРОВЕРЯЕТ: внутрь вызова библиотеки он не видит, и «поглощающий», объявленный вызову, чей результат на деле несёт предмет, замолчит о его выносе. Вид держится причиной в ведомости, сверенной с кодом вызова, и ревью ведомости. Оператор базы, ЧИТАЮЩИЙ материал, объявлен поглощающим по границе 2: строка, прочитанная владельцем, до обёртки в тип не ведётся.
- СТРОЖЕ, ЧЕМ НУЖНО, — названо, чтобы не чинилось ослаблением: сводка возврата функции своего файла одна на все места вызова (контекст не различается); структура, в поле которой лёг предмет, несёт его вся — число в соседнем поле тоже; признак `ok` у `v, ok := m[k]` и подобных некомпонентных форм несёт предмет вместе со значением; многозначный вызов, чьё число позиций синтаксис не называет (непрозрачный вызов аргументом непрозрачного либо вариадического), несёт предмет, если несёт любая позиция, и отдаёт его всем параметрам получателя.
mail_kind_sender_parity.go — перепись ВИДОВ ПИСЬМА против их ОТПРАВИТЕЛЕЙ (приёмка `docs/engineering/acceptance/recovery-of-access.md`, Р3, сценарии Ф5-10 и Ф5-11; задача PRO-Robotech/kacho#1271).
Две стороны одного словаря ¶
Вид письма объявлен ДВАЖДЫ, и оба объявления обязательны:
- СХЕМОЙ — ограничением на колонку вида события очереди писем: строку другого вида база не принимает. Это закрытый словарь того, что вообще может лечь в очередь;
- ПРИМЕНИТЕЛЕМ — функцией формы `drainer.Applier` (`func(ctx, eventType string, payload T) error`), которая ветвится на своём параметре вида и сдаёт письмо узлу. Вид, на который применитель не ветвится, у него — «неизвестный», и строка отравляется, а не отправляется.
Расходятся они молча: миграция и функция правятся разными коммитами, и каждая по отдельности зелена. Гейт кладёт их рядом.
Что распознаётся — все законные формы записи, по каждой инъекция ¶
Схема: `CONSTRAINT … CHECK ((event_type = ANY (ARRAY['…'::text, …])))` в теле `CREATE TABLE`, и то же выражение в `ALTER TABLE … ADD CONSTRAINT`. Ограничение, снятое `DROP CONSTRAINT` и не объявленное заново, из словаря уходит. Читается ТОЛЬКО секция `+goose Up`: секция отката несёт то же имя с обратным смыслом. Последнее живое объявление побеждает — в порядке версий миграций, а он же и лексикографический порядок имён.
Применитель: сравнения `eventType ==`/`!=` с константой либо литералом и `switch eventType { case …: }`. Константа разрешается через словарь строковых констант прод-корпуса (общий помощник семейства дренажа); неразрешимое имя считается отдельно в переписи, а не молчит.
Обе стороны судят по УЗЛУ, а не по подстроке: проза этого же файла несёт каждое из искомых слов.
Чем ограничено — сказано вслух ¶
Пространство видов письма — `mail.`. Словарь очереди, ни один вид которого не в этом пространстве, к письмам не относится и переписью не учитывается. Применитель, ветвящийся на вид через промежуточную переменную (`k := eventType; if k == …`), распознавателю невидим; в дереве такой формы нет, и её появление обязано прийти сюда новой инъекцией, а не молчанием.
mail_send_paths.go — MAIL-47 приёмки ID-MAIL-1: путей отправки письма у нас РОВНО ОДИН, и отправляет он ТОЛЬКО наши виды письма.
Предмет ¶
Видов письма в продукте пять (подтверждение адреса, восстановление доступа, приглашение, код смены адреса и уведомление о смене адреса), и все пять отправляем МЫ. Приглашение — наше по решению Р23 приёмки ID-MAIL-1: его предмет — строка в НАШЕЙ базе. Восстановление доступа — наше с фазы Ф5 (одобренная `docs/engineering/acceptance/recovery-of-access.md`, Р3 и Д5): код чеканим мы, поток поставщика истёк вместе с поставщиком. Подтверждение адреса — наше по одобренной `docs/engineering/acceptance/access-beyond-login-needs-a-verified-address.md` (kaname#456, Р8): приёмка назвала переезд, код подтверждения чеканим мы, и без него человеку не открывается ничего дальше экрана подтверждения. Код смены адреса и уведомление о смене — наши по одобренной `docs/engineering/acceptance/email-change-is-confirmed-from-the-new-address.md` (kaname#635, Р7): глагол смены — наш с первого дня.
Перечень НАШИХ видов — `OurMailKinds` — закрыт и объявлен один раз; вид входит в него ТОЛЬКО одобренной приёмкой, назвавшей переезд, а не правкой гейта под покрасневший прогон.
Отсюда два признака нарушения, и каждый сам по себе достаточен:
- ВТОРОЙ путь отправки того же вида нарушает Р1 («два способа доставить одно и то же письмо, и какой сработает, решает порядок»);
- НАШ путь отправки вида вне перечня означает, что вид уехал к нам без приёмки, назвавшей переезд: у письма стало два производителя, и какой доедет, решает порядок, а не решение.
Что здесь считается путём отправки — ДВЕ оси ¶
ТРАНСПОРТ. Не-тестовый файл Go, импортирующий пакет, который говорит с почтовым узлом. Список объявлен закрытым (`mailTransportTokens`), его предпосылка проверяется: якорный пакет `net/smtp` обязан найтись в дереве хотя бы раз, иначе ось судит пустоту и молчит по этой причине, а не по существу.
Закрытый список знает ровно то, что в нём названо, — поэтому импорт, говорящий о почте словом в пути и не объявленный ни транспортом, ни не-транспортом (`mailNotTransport`), ни пакетом своего модуля, есть ОТКАЗ «форма разбору неизвестна», а не тишина. Второй отправитель на библиотеке вне списка иначе уезжал бы из-под наблюдения: якорная предпосылка на нём молчит (`net/smtp` в дереве остаётся), ось словаря молчит, если вид взят константой хранилища, а не литералом. Отказ снимается тем, кто форму знает: библиотека вносится в один из двух списков этим же изменением.
СЛОВАРЬ ВИДОВ. Строковый литерал вида `mail.<вид>.send` — имя события очереди писем, чей словарь закрыт CHECK'ом миграции. Вид, отличный от приглашения, есть находка ГДЕ УГОДНО в не-тестовом дереве, даже без транспорта рядом: расширить словарь молча нельзя, а расширенный словарь означает второй вид письма, уехавший от нас.
Вид письма, который отправляет путь, БЕРЁТСЯ ИЗ ЕГО ЖЕ ФАЙЛА — литералом оси 2. Путь, не назвавший вида, — находка: перепись обязана печатать ДВЕ величины, и вторая из воздуха не берётся.
Чего разбор НЕ видит — названо прямо ¶
Отправитель, написанный на голом сокете и говорящий по протоколу почты руками, осью 1 не опознаётся: он не импортирует ничего почтового. Границу закрывает ось 2 — такой отправитель всё равно обязан взять своё событие из очереди, а словарь очереди закрыт миграцией. Библиотека транспорта, чей путь импорта о почте не говорит ни словом (`sendgrid`, `ses` названы в списке именно поэтому), под отказ формы не подпадает — её место в списке, а не в предикате.
Путь — ОБЪЯВЛЕНИЕ, ОТКРЫВАЮЩЕЕ РАЗГОВОР, а не файл (kaname#175). Внутри файла, импортирующего транспорт, путём считается каждое объявление верхнего уровня, зовущее открывающую функцию транспорта (`mailTransportOpeners`: `Dial`, `NewClient`, `SendMail`, …) через имя его импорта; второе такое объявление в том же файле — второй путь, и находка называет оба. Объявление, упоминающее транспорт без открытия разговора (`smtp.PlainAuth`, тип `smtp.Auth`), путём не является. Файл, импортирующий транспорт и не открывающий разговора ни одним объявлением, остаётся одним путём на строке импорта: вид и производитель у него судятся по-прежнему, молчать о нём нельзя.
Об отправителе, живущем в ЧУЖОМ процессе, гейт не утверждает НИЧЕГО (круг 6, В3): его в нашем дереве нет и быть не может, а проверка, требующая утверждения о непрочитанном, есть «ноль находок» без прочтения. Что письма действительно уходят, утверждают сквозные пробы на поднятом стенде, наблюдая письмо у приёмника. Здесь утверждается, что у каждого нашего вида ровно один путь отправки, а вида вне перечня наш код не отправляет.
manifest_verb_class_rule.go — два распознавателя для свойств ДЕРЕВА, которых проба пакета утверждать не может.
правило «класс действия из его ИМЕНИ» объявлено в дереве РОВНО ОДИН РАЗ. Проба пакета о числе объявлений не утверждает ничего: она зелена при любом. Единственность объявления делает второе место НЕПРЕДСТАВИМЫМ, и это сильнее тождества импорта: появится генератор — импортировать ему будет нечего, кроме одной функции, by construction;
правило вывода «тип объекта из имени ресурса» СНЯТО и не возвращено тихо. Приёмка сняла его замером, и без держателя его можно вернуть молча: ключ перестал бы быть обязательным, а восстанавливающее правило поселилось бы в ДВУХ местах — в генераторе (когда опускать) и в загрузчике (как восстановить).
Как распознаётся правило «класс из имени» — и почему НЕ по набору литералов ¶
Наивный распознаватель («объявление, чей набор строковых литералов равен пяти каноническим») даёт ЛОЖНУЮ находку: рядом живёт ПОРЯДОК ПОКАЗА глаголов, набор у которого тот же, а референт другой. Гейт, краснеющий на верном коде, отключают первым.
Поэтому распознаётся ПАРА: функция, отвечающая «класс и получилось ли» (результаты `(string, bool)`), и набор ровно пяти канонических токенов, до которого она дотягивается — своим телом либо объявлением того же файла. Порядок показа под это не подпадает: его читает функция с ОДНИМ результатом.
Порт с монорепо — пара файлов названа, а не умолчана ¶
Перенесено с `PRO-Robotech/kacho:internal/repohygiene/manifestverbclassrule_test.go` (семейство снято вынесением службы, `kacho#2597`; предмет жив здесь — задача #17). Изменилось: каталог загрузчика (приставки `services/iam/` в самостоятельном клоне нет), пакет, и вход распознавателей — исходник вместо уже разобранного узла: разбор живёт теперь в одном месте, а проба и инъекция подают ему текст. Осталось дословно: имена обоих гейтов, пара признаков и тексты находок.
membership_removal_expires_invite.go — MAIL-46 приёмки ID-MAIL-1: глагол, снимающий участие, ОБЕСЦЕНИВАЕТ невыкупленное приглашение.
Предмет ¶
Строка приглашения ГЛОБАЛЬНА, членства — по аккаунту. Сняв членство и оставив строку ждущей выкупа, продукт оставляет приглашение действующим: первый вход человека переводит строку в состояние участника и со-коммитит указатель на ТОТ САМЫЙ аккаунт, из которого его исключили. Заметить это неоткуда — отказа нет, красного нет, человек просто оказывается там, где ему быть не положено.
Предикат судит ИСХОД, а не ИМЯ ¶
Требование приёмки сформулировано по исходу — «человек перестал быть участником», — поэтому и гейт ищет исход: оператор, СНИМАЮЩИЙ СТРОКУ ЧЛЕНСТВА, в каком бы глаголе он ни стоял. Новый глагол того же смысла попадает под гейт по построению, а переименование прежнего его не снимает — тогда как перечень имён разошёлся бы с деревом молча на первом же заведённом глаголе.
Что считается обесцениванием ¶
Запись СРОКА на строку приглашения (`invite_expires_at`) — то самое плечо, которое делает её невыкупаемой. Оно обязано стоять в ТОЙ ЖЕ функции: между двумя операторами, разнесёнными по функциям, появляется окно, в котором первый вход видит членств ноль и срок живым.
Чего гейт НЕ видит — названо прямо ¶
Снятие членства каскадом чужого ограничения либо триггером базы этим разбором не опознаётся: он читает код Go, а не схему. Граница закрыта с другой стороны — интеграционной пробой (`internal/repo/kaname/pg/invite_revoked_on_removal_integration_test.go`), которая судит ИСХОД на живой базе, чем бы членство ни снималось.
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).
migration_section_split.go — ЯДРО гейта: директива секции мигратора объявлена в дереве ОДИН раз, а не выписана заново каждым, кому понадобился прямой ход миграции.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ: популяция шире предмета, и расходится она молча
Прямой ход миграции и обратный — РАЗНЫЕ утверждения. Накат обязан быть применим к живым строкам; откат восстанавливает снятое, и ни в одном развёрнутом дереве его строк нет. Разбор, читающий файл целиком, меряет величину, которой не существует.
Разрез поэтому нужен многим, и каждый, кому он понадобился, писал свой. Замер на дереве 2026-09-14 дал ОДИННАДЦАТЬ реализаций одного разреза, и они давали ПЯТЬ разных ответов на один вопрос — «что делать с файлом без маркера прямого хода»: отдать тело целиком ВМЕСТЕ С ОТКАТОМ · отдать пустую строку · отдать всё от начала · отказать · не спрашивать вовсе. Сегодня оба маркера стоят у всех семнадцати миграций, поэтому расхождение молчит: премиса держится СОВПАДЕНИЕМ, а не устройством. Ровно так же держалась премиса гейта пика аккаунтов до `kacho#2363` — до первого оператора вставки в откате.
───────────────────────────────────────────────────────────────────────────── ЧТО СУДИТСЯ И ПОЧЕМУ ИМЕННО ЭТО
Находка — СТРОКОВЫЙ ЛИТЕРАЛ с директивой секции в не-тестовом файле Go вне файла-владельца разбора. Не «вызов, который режет»: разрез бывает записан десятком форм (`Index`, `Cut`, `Split`, срез по двум индексам), и распознаватель форм вызова знал бы их не все — то есть молчал бы на незнакомой, а молчание от чистоты не отличить. Литерал же в не-тестовом коде законного предмета не имеет вовсе: директива объявлена константой, и взять её неоткуда, кроме владельца.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
- ФАЙЛЫ ПРОБ НЕ СУДЯТСЯ. Фикстура синтетической миграции обязана нести директиву дословно — это её содержимое, а не копия разбора. Гейт их не читает by construction, и восемь таких копий разреза в пробах дерева остаются его слепой зоной. Названо числом, а не умолчанием.
- СКЛЕЙКА НЕ УЗНАЁТСЯ. Директива, собранная сложением частей, под предикат не подпадает. Форма в дереве не встречалась ни разу; появится — гейт промолчит, и это его граница, а не чистота.
- КОММЕНТАРИЙ — НЕ ЛИТЕРАЛ. Проза о директиве законна и обязана остаться: гейт, краснеющий на собственном объяснении, снимают первым.
Собственного литерала у этого файла нет: он спрашивает написание у владельца (`migrations.SectionMarkerStem`). Иначе гейт был бы своей же первой находкой, и его пришлось бы прощать — то есть заводить послабление там, где его можно не заводить вовсе.
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, задача продукта kacho#2098).
Порт с монорепо (`internal/repohygiene/moduleidentityseededonlybythebaseline_test.go`, снят вынесением службы — `kacho#2597`). В монорепо предикат жил ЦЕЛИКОМ внутри `_test.go` (пакет-«внешний тест», без отдельного `.go`); здесь он вынесен в не-тестовый файл, потому что кроме гейта его читает пересчёт.
ПРЕДМЕТ (дословно из монорепо) ¶
Личности модулей посеяны БАЗОВОЙ миграцией, то есть приезжают и в установку, где платформы нет вовсе. Строка, которую арендатор, развернувший службу доступа отдельно, нести не обязан, — это данные окружения, и в миграцию они не идут ни при каких условиях (§«Данные СТЕНДА заводятся посевом»).
СОСТОЯНИЕ НА ДЕНЬ ПЕРЕНОСА — ДРУГОЕ, чем в монорепо, и это названо числом ¶
В монорепо (на день заведения гейта) долг был НЕПОДВИЖЕН: применителя у раздела `seed` манифеста не было, применённую миграцию не поправить (ban #5), а свежая установка без платформы несла пять личностей чужого продукта.
В kaname этот долг ЗАКРЫТ отдельной задачей — kacho#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` сегодня находит ноль нарушений. Это НЕ делает гейт вакуумным: он и дальше судит регресс — появление НОВОЙ миграции, сеющей модульную личность НЕ через применитель (ровно тот класс, который kacho#2452 только что убрал). Обновлять эту прозу нормой `kacho#2098` больше не нужно: предмет её первой половины («свежая установка без платформы несёт ноль модульных СА, кроме остатка api-gateway») закрывает kacho#2452, а не этот гейт; гейт стережёт РОСТ.
РОДСТВО, КОТОРОЕ НАДО НАЗВАТЬ — И РАЗЛИЧИЕ (дословно из монорепо) ¶
У ролей модуля такой судья есть отдельным семейством (Г2, `migrationnotawriterofmodulerole`, НЕ входит в этот батч) — запрещает миграции писать роль модуля, у которого есть манифест, ПОЛНОСТЬЮ (у ролей применитель есть). У личностей применитель тоже теперь есть — но не для ВСЕХ (api-gateway — остаток), поэтому запрет здесь остаётся УЗКИМ: не «личность модуля не сеет никакая миграция», а «личность модуля не сеет НИКАКАЯ МИГРАЦИЯ КРОМЕ БАЗОВОЙ» — тот же периметр, что был в монорепо.
ЧЕГО ГЕЙТ НЕ ЛОВИТ (названо, чтобы на него не сослались шире предмета) ¶
Он про ПОСЕВ, а не про живую базу: строку, заведённую не миграцией, он не читает by construction. И он ничего не утверждает о ПОЛНОТЕ посева.
named_verb_form_expiry.go — разбор ПАРЫ: отвергается ли поимённая форма права роли прод-кодом манифеста и есть ли в дереве пробы шести сценариев её полноты. Находка — ровно одно их сочетание: форма принята, полнота не проверяется.
Порт с монорепо (`internal/repohygiene/namedverbformexpiry.go`, снят вынесением службы — `kacho#2597`). Изменилось: пакет (`repohygiene` → `check`), путь домена (`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/` не объявлен и не возвращается (задача kacho#1844 сняла его вместе с формой, которую он отвергал — `f5bb097046` в истории монорепо). Все шесть проб MOD-RL (04, 04a, 18, 18a, 19, 19a) в дереве ЕСТЬ (`internal/manifest/rolenamedverbs_test.go`, `internal/manifest/roleexport/namedverbs_test.go`). Гейт сегодня молчит по ВТОРОЙ законной причине — форма вернулась вместе со своей проверкой, ровно как того требует приёмка kacho#1844, — а не по первой. Это и есть содержание переноса: без держателя регресс (снятие одной из шести проб при живом возврате перечня имён) не был бы замечен НИЧЕМ.
Чего разбор НЕ видит — названо, а не спрятано (дословно из монорепо) ¶
Возврат сентинела, собранный в рантайме (через переменную, через таблицу видов). Такой формы в этом пакете нет, и появись она — гейт увидит ноль возвратов и покраснеет, то есть ошибётся В СТОРОНУ находки, а не молчания.
paired_write.go — ПАРНАЯ ЗАПИСЬ: функция, делающая одно из двух действий, обязана делать и второе (задача kaname#313).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
В службе есть пары действий, которые поодиночке снимают доступ НАПОЛОВИНУ и выглядят исполненными целиком: две записи отсечки; снятие сессии и отзыв выданного в ней. Половина исполняется, глагол отвечает успехом, и отличить это от работающего контроля наблюдением нельзя.
───────────────────────────────────────────────────────────────────────────── СКЛЕЙКА ПО ВЫЗОВУ — УЗКАЯ, И ЭТО РЕШЕНИЕ
Второе действие часто делается ВЫЗОВОМ помощника, а не своим оператором, — разбор, не идущий по вызовам, дал бы ложную находку на всякой такой двери (измерено). Но склейка ШИРОКАЯ здесь хуже узкой, и вот почему: у соседнего прибора щедрость теряет находку о МЁРТВОМ коде, а здесь потеряла бы находку о ЖИВОМ половинном снятии доступа — у прибора, который объявлен единственным держателем пары.
Поэтому склейка ограничена тремя условиями сразу:
- ОДИН ПАКЕТ. Имя, объявленное в чужом пакете, вызовом отсюда не разрешается; разные пакеты с одноимёнными функциями не склеиваются;
- ОДНОЗНАЧНОЕ ИМЯ. Имя, объявленное в пакете больше одного раза, склейку НЕ даёт: какой из одноимённых вызван, разбор без типов не знает, и засчитывать любой значило бы засчитывать наугад;
- ДОСТИЖИМЫЙ ВЫЗОВ. Вызов внутри заведомо мёртвой ветви (`if false`) не считается: дефект, спрятанный за такой ветвью, обязан ловиться. Ровно этим широкая склейка и была пробита.
───────────────────────────────────────────────────────────────────────────── ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО, А НЕ СПРЯТАНО
- приёмник вызова не разрешается: `a.Foo()` и `b.Foo()` при единственном в пакете `Foo` склеиваются одинаково. Сузить это до типа можно только разбором типов, и цена такого разбора решается отдельно;
- мёртвая ветвь опознаётся по литералу `false`; ветвь, мёртвая по значению переменной, здесь живая;
- действие, сделанное в схеме (триггер), не Go и здесь не судится.
password_hash_format_registry.go — гейт: перечень форматов проверочного значения сверен с ПРОВЕРЯЮЩИМИ, которые есть в дереве (приёмка ID-PW-1 §5 PWV-13 и строка 07.4).
Предмет ¶
Перечень форматов — закрытый словарь того, что продукт умеет ЧИТАТЬ. Он расходится с деревом двумя способами, и оба тихие:
- запись без проверяющего: формат объявлен, читателя нет. Значение такого формата доезжает до входа и получает исход «формат вне перечня» — то есть человек с верным паролем не входит, а перепись переноса его пропустила, потому что признак в перечне ЕСТЬ;
- проверяющий без записи: читатель есть, потолка у него нет. Тогда параметры стоимости берутся из самого значения без всякой границы, и чужой источник назначает цену каждой попытки.
Оба расхождения гейт называет находкой. Снятие записи ВМЕСТЕ с проверяющим он пропускает — дерево согласовано, — и это НЕ разрешение снимать: хранилищ установок гейт не читает, разрешение даёт перепись каждой из них (Р8, PWV-17). Сказано прямо, чтобы зелёный этого гейта не прочитали шире.
Что судится, и почему признаком СВОЙСТВА, а не именем ¶
«Проверяющий формата есть в дереве» опознаётся не по имени функции — имя переименуют, и гейт замолчит, — а по ВЕТВИ КЛАССИФИКАТОРА: в функции выбора стоит ветвь, которая по признаку формата уходит в свою функцию. Признак берётся из строковой константы, на которую ветвь ссылается, то есть из того же места, откуда его берёт исполняемый код.
Отсюда же строка 07.4: ни функция выбора, ни функции её ветвей не упоминают типа настройки «что писать». Выбор проверяющего производен от хранимого значения; прочти он настройку — смена настройки молча сделала бы нечитаемой уже лежащую популяцию.
Границы, названные вслух ¶
- ЗАПИСИ ПЕРЕЧНЯ приходят ДОВОДОМ, а не разбором: их объявляет домен, и он же их проверяет. Гейт судит поданное — тем же, чем судил бы прочитанное, но без второго разбора одного предмета.
- ВТОРОЕ ОБЪЯВЛЕНИЕ перечня ищется по составному литералу записи вне файла перечня. Литерал в пробе сюда не попадает: корпус не-тестовый.
- ЭТАЛОН ПОЛА приходит доводом и правится вместе с нормой, на которой стоит. Читать его из текста приёмки гейт не вправе: он сверялся бы с прозой, а не с нормой (§8 приёмки).
password_rule_sole_declaration.go — ГЕЙТ КЛАССА: правило пароля объявлено в дереве ОДИН раз, и всякая полоса, меняющая материал, зовёт его, а не несёт своего (приёмка Ф3, сценарий Ф3-32; Ф1-38; задача kacho#1269).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Три полосы меняют материал пароля: смена пароля (Ф3), регистрация (Ф4), восстановление (Ф5). Правило — минимальная длина, сходство с почтой, база утечек — у них ОДНО. Второе объявление правила разошлось бы с первым молча, и человек, чей пароль принят на регистрации, получил бы отказ на смене — либо наоборот, и второе хуже: правило, которое строже на входе и мягче на смене, есть правило только на бумаге.
───────────────────────────────────────────────────────────────────────────── ЕДИНИЦА СЧЁТА — ОБЪЯВЛЕНИЕ ПРАВИЛА, УЗНАННОЕ РАЗБОРОМ, А НЕ ПОДСТРОКОЙ
Объявлением правила считается КАЖДАЯ из трёх форм, и распознаватель знает их все, потому что дубликат приходит не копией имени, а копией существа:
- конструктор `NewPasswordRule` и тип `PasswordRule` — форма по имени;
- метод `Judge` с параметром, названным `password` — форма по глаголу: второе правило в другом пакете завело бы свой тип со своим именем, но судить пароль оно стало бы тем же словом;
- сравнение ДЛИНЫ В РУНАХ параметра `password` — форма по существу: `len([]rune(password)) < n` и `utf8.RuneCountInString(password) < n`. Байтовая длина (`len(password)`) правилом НЕ считается намеренно: она судит МАТЕРИАЛ, а не пароль (у bcrypt потолок 72 байта, PWV-19), и живёт у проверяющего законно.
Вызывающим считается вызов метода `Judge` с тремя доводами — контекст, почта, пароль — вне дома правила. Перепись печатает «объявлений 1 · вызывающих M», и M сегодня равно 1: регистрация и восстановление — Ф4 и Ф5, их вызовы появятся вместе с ними, и рост M — перепись, а не находка.
───────────────────────────────────────────────────────────────────────────── ЧТО ГЕЙТ НЕ УТВЕРЖДАЕТ
Он не судит, ВСЕ ЛИ полосы, меняющие материал, зовут правило: полоса, которая пишет материал и правила не спрашивает, тремя формами выше не узнаётся. Эту половину держит запрет на замещение материала мимо `Writer` (гейт локализации проверяющего) и приёмки самих полос.
people_address_lawful_writers.go — ПЕРЕЧЕНЬ законных писателей адреса человека в существующую строку в непроверочном Go (задача PRO-Robotech/kaname#635; приёмка `docs/engineering/acceptance/email-change-is-confirmed-from-the-new-address.md`, Р9, сценарий EC-24).
Предмет ¶
Гейт `TestPeopleAddressHasNoWriterInServiceCode` держал число таких мест равным нулю, пока у продукта не было глагола смены адреса, и текст его находки (`addressWriterFinding`) называл условия, без которых глагол не вносится. Приёмка смены адреса разобрала каждое условие (Р9) и разрешила ОДНОГО законного писателя — оператор исхода смены. Перечень называет его координатой: файл и функция, в которой стоит оператор, и довод.
Чем перечень держится ¶
- запись поглощает РОВНО ОДНО место записи адреса в своём файле и своей функции: второй оператор той же функции, пишущий адрес, — находка, как и любое место вне перечня;
- запись без предмета — находка: перечень истекает вместе со своим писателем и не переживает его, оставаясь на вид рабочим;
- запись о файле, которого в корпусе нет, считается отдельно (как у ведомости применённых миграций) — инъекция судит синтетику, — а проба дерева требует, чтобы таких было ноль.
Пополняется перечень только одобренной приёмкой, назвавшей писателя, — не правкой гейта под покрасневший прогон.
people_address_writers.go — разбор «кто пишет адрес человека в существующую строку» (`kaname.users.email`): часть (б) условия 7 чек-листа поверхности подтверждения адреса (приёмка PRO-Robotech/kacho-workspace `docs/specs/sub-phase-F6b-console-and-edge-confirmed-address-gate-acceptance.md`, край и служба; приёмка службы `docs/engineering/acceptance/access-beyond-login-needs-a-verified-address.md`; задача PRO-Robotech/kaname#464). Половина, судящая миграции, — адрес И отметка его подтверждения, формы определения схемы и строки триггера, ведомость применённых миграций — в `people_address_writers_migrations.go` (задача PRO-Robotech/kaname#471).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Отметку подтверждения снимает база на смене адреса (триггер `users_email_change_drops_verification`, миграция `20260915111233_login_methods_live_in_their_own_rows.sql`). Снятие само по себе не закрывает того, что уже открыто: перепрос открытых соединений края отметку не спрашивает, кеш решений края снятием не сбрасывается. Поэтому глагол смены адреса вносится только вместе со своими условиями, и держит это гейт: мест, где непроверочный код службы пишет адрес в СУЩЕСТВУЮЩУЮ строку человека, — ровно столько, сколько называет перечень законных писателей (`people_address_lawful_writers.go`): одно, оператор исхода смены адреса, внесённый одобренной приёмкой, разобравшей условия (kaname#635, Р9). Появление любого другого места — находка, и её текст называет, с чем вместе глагол вносится (`addressWriterFinding`).
Заведение строки (`INSERT INTO users (…, email, …)`) адреса не меняет — у новой строки прежнего адреса нет — и находкой не является; оно считается в переписи операторов записи в строки людей.
Корпус — ДВА вида входа, и оба судит один разбор текста SQL: строковые выражения непроверочного Go и тексты миграций. Предмет у них разный: в Go — адрес (у отметки подтверждения в Go есть законный писатель — глагол подтверждения), в миграции — адрес и отметка (у миграции законного писателя отметки нет).
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ СПИСОК SET ОПЕРАТОРА, А НЕ ПОДСТРОКА
Текст — значение строкового выражения Go, свёрнутое тем же проходом, что у гейтов значений строк (`newLVIndex`: литерал, склейка, константа, связанное имя пакета), и разобранный общим лексером SQL (`sqlTokens`). Склейка, которая целиком не свернулась, судится звеньями, и звенья, сворачивающиеся подряд за значением времени исполнения (`tbl + " SET " + column + " = $1"`), — одним текстом. Колонка читается в голове элемента списка SET; адрес в условии, в цели конфликта (`ON CONFLICT (lower(email))`) и в списке колонок вставки записью не является. Законные формы записи, каждая доказана инъекцией:
UPDATE [ONLY] [kaname.]users [[AS] u] SET … email = … ветвь UPDATE UPDATE users SET (…, email, …) = (…) та же ветвь IF … THEN UPDATE users SET … · правило DO UPDATE users SET … та же ветвь INSERT INTO users … ON CONFLICT … DO UPDATE SET … email = … ветвь ON CONFLICT MERGE INTO users … WHEN MATCHED THEN UPDATE SET … email = … ветвь MERGE любая из них внутри CTE, в склейке, в формате fmt.Sprintf, в строке SQL
и формы вне списка SET — определение схемы, переписывающее значения строк, и присваивание строке триггера (`people_address_writers_migrations.go`).
Имя без кавычек сравнивается без регистра ASCII, в кавычках — побайтово (так разрешает база; лексер общий).
───────────────────────────────────────────────────────────────────────────── ФОРМА, КОТОРУЮ РАЗБОР НЕ РЕШАЕТ, — НАХОДКА, А НЕ МОЛЧАНИЕ
«Не решается разбором» — каждая из форм ниже, и каждая доказана инъекцией:
- список SET над строками людей пуст, несёт пустой элемент, в голове элемента — подстановку формата (`%s`) либо не имя;
- UPDATE строк людей без списка SET в тексте;
- оператор с подстановкой вместо таблицы (либо вне текста), пишущий адрес либо колонку из подстановки;
- список SET без оператора в том же тексте, называющий адрес.
СПИСОК, ПОЛНЫЙ В ЛИТЕРАЛЕ И ПРОДОЛЖЕННЫЙ ВО ВРЕМЯ ИСПОЛНЕНИЯ. Гейт не прослеживает значение до исполнителя запроса, поэтому список SET над строками людей (либо над таблицей, которую текст не называет, — подстановка вместо таблицы либо оператор вне текста), чьи элементы решены и адреса не пишут, судится ещё раз:
- не закрыт в тексте — кончается концом текста, а не WHERE, FROM, RETURNING, `;` либо скобкой: хвост, приставленный склейкой с переменной, `+=`, `strings.Join` либо построителем, дописал бы колонку;
- несёт подстановку формата в значении элемента (`labels = %s`): подставленный текст дописал бы колонку.
Закрытый в своём тексте список продолжение колонкой не пополнит — хвост и подстановка после закрывающего слова молчат. Полная запись без хвоста тоже обязана закрыть список (`RETURNING`, `WHERE` либо `;`): отличить её от продолженной гейт не берётся. Пустой список над таблицей, которую текст не называет, колонок не несёт — его колонки приставляются звеньями и судятся звеньями.
ЗВЕНО-ПРИСВАИВАНИЕ. Текст, начатый списком присваиваний без оператора и без SET (`email = $2`, продолжение `, email = $3` либо `%s, email = $3`, кортеж `(display_name, email) = (…)`), приставляют к списку SET во время исполнения; голова элемента, называющая адрес, — «не решается». Звено условия отбора `email = $N` от звена списка SET неотличимо и пишется со своим словом (WHERE, AND, OR) либо выражением над колонкой — так пишет дерево (`lower(email) = lower($%d)`). Значение константы и имени уровня пакета звеном судится в месте обращения, не вошедшем в свёрнутое выражение (`q += set`, элемент `[]string{…}`): свёртка подставляет его туда.
Иначе колонку, собранную во время исполнения, гейт пропустил бы молча.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
- Корпус — непроверочный Go дерева и миграции службы (`PeopleAddressInput`). Места в ПРИМЕНЁННЫХ миграциях, которые правке не подлежат (ban #5), названы ведомостью поимённо — точной координатой (`people_address_writers_migrations.go`); у Go ведомости нет.
- Текст, собранный во время исполнения, судится по звеньям, которые сворачиваются (литерал, склейка, константа). Колонка адреса, дошедшая до списка SET не словом свёрнутого текста — из данных либо значением, подставленным в формат (`fmt.Sprintf("%s = $1", column)`), — видна только там, где ей негде встать молча: пустой список, пустой элемент, подстановка в голове либо в значении, список, не закрытый в тексте. Приставленная к списку, чья таблица в тексте не названа (`"UPDATE " + tbl + " SET "`), либо вставленная в закрытый текст заменой (`strings.Replace`), она не видна: адреса нет ни в одном слове, которое разбор читает. Звено с подстановкой в голове (`%s = $%d`) звеном-присваиванием адреса не считается — так же пишется условие любого построителя отбора.
- Ветвь MERGE в дереве сегодня пуста: её держит инъекция, а не перепись.
people_address_writers_migrations.go — половина гейта писателей адреса людей, судящая МИГРАЦИИ службы, и формы записи вне списка SET, которые знает общий разбор (задача PRO-Robotech/kaname#471; предмет и разбор списка SET — в шапке `people_address_writers.go`, #464).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ В МИГРАЦИИ
Миграция не пишет в строки людей, которых сама не заводит, ни адреса (`kaname.users.email`), ни отметки его подтверждения (`kaname.users.email_verified_at`). У адреса глагол смены вносится только со своими условиями; у отметки писателей два — предъявление кода подтверждения ставит её, база на смене адреса снимает, — и миграция третьим не становится. Текст миграции судится ТЕМ ЖЕ разбором, что строковые выражения Go: файл — один текст SQL, тела `DO $$ … $$`, подпрограмм и динамический SQL — вложенные строки, судимые ещё раз. Разделы `-- +goose Up` и `-- +goose Down` судятся оба: откат исполняется так же, как накат.
───────────────────────────────────────────────────────────────────────────── ФОРМЫ ЗАПИСИ ВНЕ СПИСКА SET — каждая доказана инъекцией
Определение схемы, пишущее значение колонки в строки, которых оператор не заводит (ALTER TABLE над строками людей):
ADD [COLUMN] [IF NOT EXISTS] колонка … DEFAULT выражение | GENERATED … ALTER [COLUMN] колонка SET DEFAULT выражение (не NULL: заводимые строки) ALTER [COLUMN] колонка [SET DATA] TYPE … USING выражение ALTER [COLUMN] колонка SET EXPRESSION AS (…) RENAME [COLUMN] другая TO колонка ALTER TABLE [kaname.]другая RENAME TO users (её строки становятся людьми)
Колонка либо таблица такого определения — подстановка формата (динамический SQL, `format('… %I …')`) — «не решается».
Запись строки триггера в теле подпрограммы на PL/pgSQL. База пишет ту строку, которую подпрограмма триггера ВЕРНУЛА, поэтому судятся две вещи.
- Цель присваивания, называющая строку триггера. Строку называют NEW, OLD, их псевдонимы (`имя ALIAS FOR new`, псевдоним псевдонима) и любое из них под меткой блока (`метка.new.колонка`; внешний блок помечен именем подпрограммы). Цели — все, какие есть в грамматике PL/pgSQL: начало оператора (`цель := …`, `цель = …`, с индексом `[…]`), `INTO [STRICT] цель[, …]`, `GET [CURRENT|STACKED] DIAGNOSTICS цель = …`, `FOR цель[, …] IN` (и под меткой цикла `<<метка>>`), `FOREACH цель … IN ARRAY`, аргумент `CALL` целиком (позиционный либо `имя =>`: выходной параметр процедуры пишет в него). Колонка названа — присваивание колонке; нет — строке целиком.
- RETURN в подпрограмме, объявленной `RETURNS trigger`: законно вернуть саму строку триггера (NEW, OLD, псевдоним, под меткой, в скобках), NULL, ничего и CASE, каждая ветвь которого законна. Прочее (`RETURN r` после `r := NEW; r.колонка := …`, `RETURN jsonb_populate_record(NEW, …)`) — строка, которая не строка триггера: база пишет её целиком.
Тело подпрограммы триггера на языке, отличном от PL/pgSQL, разбор не читает — оно пишет строку целиком. Какую таблицу пишет подпрограмма, решает ПРИВЯЗКА: объявление `CREATE TRIGGER … ON таблица … EXECUTE FUNCTION|PROCEDURE имя()` где угодно в корпусе (функция и триггер бывают в разных миграциях). Привязана к строкам людей — писатель, если колонка названа, и «не решается», если строка пишется целиком (событие не различается: заведённая строка, которую пишет триггер, — тоже строка, которой сам триггер не заводил); только к чужим таблицам — молчание; к таблице из подстановки либо ни к какой — «не решается». Триггер над строками людей либо над таблицей из подстановки, чья подпрограмма тела в корпусе не имеет (подпрограмма расширения пишет колонку, названную аргументом триггера), — «не решается» с координатой объявления триггера.
───────────────────────────────────────────────────────────────────────────── ВЕДОМОСТЬ ПРИМЕНЁННЫХ МИГРАЦИЙ — И ПОЧЕМУ ВЕДОМОСТЬ, А НЕ «ТОЛЬКО ДОБАВЛЕННОЕ»
В применённых миграциях места предмета ЕСТЬ (перепись — в пробе гейта), и применённая миграция не правится (ban #5). Соседние гейты миграций судят только добавленное относительно ствола; здесь это отвергнуто по трём доводам: (1) вердикт — свойство коммита без ствола: судится ВСЁ дерево на каждом прогоне, и клон без выборки ствола не уходит в пропуск; (2) места неподвижны — применённая миграция не меняется, поэтому ведомость точным числом не краснеет на движении к собственной цели; (3) писатель, ДОПИСАННЫЙ в применённую миграцию, — находка (обход добавленных файлов его не видит).
Запись ведомости — точная координата (файл, строка, колонка писателя либо форма «не решается») и довод. Запись с предметом молчит; запись, чьего места на своей строке разбор больше не находит, — находка (ведомость истекает вместе с предметом); запись о файле, которого нет в корпусе, считается отдельно (`LedgerOutOfCorpus`), и гейт дерева требует её нуля; что каждая запись называет ПРИМЕНЁННУЮ и нетронутую миграцию, держит проба гейта дерева по стволу.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
- Привязка триггера — по ИМЕНИ подпрограммы, без схемы: база привязывает по идентификатору, и `ALTER FUNCTION … RENAME` привязки не меняет — разбор этого не прослеживает; триггер, снятый позже (`DROP TRIGGER`), привязку не отзывает — лишняя находка, не пропуск.
- Подпрограмма, которую миграция ЗОВЁТ, судится там, где объявлено её тело; тело, объявленное вне корпуса, не видно (у подпрограммы триггера над строками людей это не молчание, а «не решается» — выше). Момент и уровень триггера не различаются: присваивание в подпрограмме триггера AFTER либо FOR EACH STATEMENT (возвращённая строка не пишется) и присваивание OLD в подпрограмме, возвращающей NEW, — лишняя находка, не пропуск.
- Запись через представление, правило над представлением и подмена подпрограммы-снимателя отметки (`CREATE OR REPLACE` без присваивания, снятие её триггера) — не формы записи колонки и этим разбором не судятся: снятие отметки на смене адреса и неподтверждённость новой строки держит интеграционная проба схемы на накатанной цепочке (`TestIntegration_AddressVerificationIsBoundToTheValue`, `internal/migrations/login_method_schema_integration_test.go`).
- Заведение строки с отметкой (`INSERT INTO users (…, email_verified_at)`) — заведение, а не запись в строку, которой оператор не заводил.
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». Цена шага не измерена здесь и решается своим изменением: у разрежённой выборки другой состав и другой вес.
probe_tooling.go — ОСНАСТКА ПРОБ: не-тестовые файлы Go под `internal/testsupport/`, которые импортируют только пробы (задача PRO-Robotech/kaname#816).
ПРЕДМЕТ ¶
Гейты прод-кода не судят файлы проб: пробе законно назвать таблицу секрета и поставить отметку, которую продукт ставит лишь миграцией, — фикстура заводит то, что заводит продукт. Файлом пробы до сих пор считался только `*_test.go`. Но `*_test.go` из другого пакета не импортируется, и общая фикстура многих пакетов обязана лежать в обычном файле — в оснастке проб. Без второй формы такой файл судился бы как прод-код, а у фикстуры, вынесенной из двадцати четырёх копий в одну, гейты прод-кода находили бы «третьего писателя», которого прод-сборка не содержит.
ПРЕДПОСЫЛКА — ПРОВЕРЯЕТСЯ, А НЕ ОБЪЯВЛЯЕТСЯ ¶
Снять оснастку с суда честно ровно тогда, когда прод-сборка её не видит. `ProbeToolingImports` судит это по разбору импортов каждого не-тестового файла вне оснастки: импорт пакета оснастки любой формы (обычный, псевдоним, с точкой, пустое имя, под любым тегом сборки) — находка с координатой. Иначе оснастка стала бы местом, куда прод-код прячет то, что гейт обязан видеть.
Оснастки в обходе нет — тоже находка: исключение, которому нечего исключать, истекает само.
ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ ¶
- Судится импорт ИЗ ЭТОГО МОДУЛЯ: другой модуль `internal/` этого модуля импортировать не может — это держит компилятор.
- Связь в обход импорта (`go:linkname`, отражение) не судится: в дереве такой формы нет.
proto_comment_names_a_real_message.go — разбор комментариев контракта на ОДИН факт: существует ли сообщение, которое комментарий называет координатой.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Комментарий контракта читает КЛИЕНТ, и он не всегда может открыть дерево. Названная в обратных кавычках координата `Message.field` есть обещание поля: клиент идёт за ним в стабы, не находит и решает, что отстала его версия.
Обещание переживает свой предмет МОЛЧА. Ни `buf lint`, ни `buf breaking`, ни генерация комментариев не читают: они судят объявления. Наблюдалось на привязке — комментарий обещал `Tuple.condition` при том, что сообщения `Tuple` в контрактах не было ни одного, а условия на кортеже своей формы на проводе не имеют вовсе (kaname#132).
───────────────────────────────────────────────────────────────────────────── ЧТО СЧИТАЕТСЯ ССЫЛКОЙ — ФОРМА НАЗВАНА, А НЕ ПОДРАЗУМЕВАЕТСЯ
Ссылкой считается токен В ОБРАТНЫХ КАВЫЧКАХ, несущий точку, у которого есть сегмент с заглавной первой буквой, а следом — сегмент со строчной:
`AccessBinding.scope_type` — короткая форма `kaname.cloud.iam.v1.AccessBinding.scope_type` — полная форма `AuthorizeService.CheckRequest.context` — через службу
Тип — ПОСЛЕДНИЙ сегмент с заглавной буквы: у полной формы перед ним стоит имя пакета, у формы через службу — имя службы, и оба сообщением не являются.
───────────────────────────────────────────────────────────────────────────── ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО, А НЕ СПРЯТАНО
- **ссылка без обратных кавычек**. Проза контракта называет типы и по-русски, и мимоходом; принимать за координату всякое слово с заглавной значило бы краснеть на собственном объяснении;
- **существование ПОЛЯ** внутри названного сообщения. Гейт судит тип: поле требует разбора тела сообщения вместе с вложенными и наследуемыми, а цена этого не окупается — `Tuple` не существовал целиком, и это тот случай, который встречается;
- **чужие контракты вне дерева**. Набор известных типов строится по ВСЕМ `*.proto` дерева, включая копии фундамента, — координата в контракт, которого рядом нет, будет находкой, и это верно: клиент этого дерева его тоже не откроет.
published_key_rule_home.go — разбор обращений к правилу критичных параметров заголовка платформы (`tokenpolicy.CriticalHeadersUnderstood`), держатель `TestPublishedKeyRuleHasOneHome` (задача PRO-Robotech/kaname#396).
Предмет ¶
Токен службы проверяют три читателя: читатель предъявленного на публичном слушателе, интроспекция для соседей и опознание токена доступа церемонии. Ключ проверки каждый из них выбирает из публикуемого набора ОДНИМ правилом — форма `kid` → ключ по `kid` → алгоритм, закреплённый за ключом, → критичные параметры заголовка → открытая половина ключа. До сведения правило было написано трижды; копии уже разошлись в мелочи (одна читала испорченный свой ключ как негодный токен), и следующая расходилась бы так же молча: все три отвечают «подпись сошлась». Дом правила — `internal/publishedkey`.
Что здесь считается КОПИЕЙ ¶
Обращение к `tokenpolicy.CriticalHeadersUnderstood` — вызов либо значение функции. Иных потребителей правила критичных параметров у продукта нет: проверка утверждения клиента (`clientassertion`) судит свой перечень понятых параметров над ключом реестра клиентов, и платформенного правила не зовёт.
Распознаватель знает ВСЕ формы обращения by construction ¶
Он связывает имя с ПУТЁМ импорта из разобранного дерева, а не с текстом: обычный импорт, псевдоним и точечный импорт опознаются одинаково; пустой импорт обращения дать не может и только считается переписью. Метод чужого типа с тем же именем обращением не является, и упоминание имени в комментарии или строке — тоже: разбор судит узел, а не подстроку.
Чего разбор НЕ видит — названо, а не спрятано ¶
- **копия, не судящая критичных параметров вовсе** — выбор ключа без этой ветви обращения не несёт. Это другой класс (снятая проверка), и держат его пробы ветвей в доме правила, а не этот гейт;
- **имя импорта, перекрытое локальным** — переменная `tokenpolicy` внутри функции. Такой код не собрался бы рядом с настоящим обращением.
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.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ — ОТСУТСТВИЕ, А НЕ ПРИСУТСТВИЕ, И ПОТОМУ ГЕЙТ НУЖЕН ОСОБЕННО
Проверка, ищущая ОТСУТСТВИЕ формы, на исчезнувшем предмете замолкает: её образец не совпадёт больше никогда, обход и перепись целы, вердикт зелёный. Отличить это от исправной работы можно только переписью ОБЪЁМА: «находок ноль» и «прочитано ноль» обязаны быть разными вердиктами, и оба напечатаны.
Предмет разбора — ВОЗВРАТ: авторитет величин, заведённый заново в службе, чей продукт отвечает «кому что разрешено», а не «сколько чего можно завести».
───────────────────────────────────────────────────────────────────────────── ЧТО СНЯТО ВМЕСТЕ С АВТОРИТЕТОМ, КРОМЕ ЕГО КОДА (kaname#108)
Здесь же называется судьба СОСЕДНЕГО гейта, чтобы его исчезновение не пришлось восстанавливать по истории: `quota_reader_grant_test.go` требовал, чтобы владелец считаемого вида состоял в группе читателей пределов. Он судил миграции ВСЕХ модулей платформы (`<корень>/services/**/*.sql`) и опирался на группу `module.quota_readers`.
Ни того, ни другого в этом репозитории нет: каталога соседних модулей — by construction, группы читателей — потому, что хранилище авторитета ушло из схемы вместе с ним. Гейт при этом не краснел и не зеленел: он спрашивал координату дерева платформы и пропускал себя в любой посадке, то есть не исполнялся НИ РАЗУ с момента выноса службы.
───────────────────────────────────────────────────────────────────────────── РАЗБОР СУДИТ УЗЕЛ-ИДЕНТИФИКАТОР, А НЕ ТЕКСТ — И ЭТО НЕСУЩЕЕ
Гейт по подстроке краснел бы на СОБСТВЕННОМ объяснении: перечень снятых имён стоит в этом же файле, а надгробие снятого метода — в `authzguard`. Проверка, судящая ТЕКСТ, не отличает исполняемую часть от комментария, который эту же часть объясняет, — и снимают её первой, как непонятную.
Поэтому ось прод-кода разбирает файл `go/parser`-ом и судит ТОЛЬКО узлы `*ast.Ident`. Комментарий, строковый литерал и запись о снятом предмете под неё не подпадают by construction — и это намеренно: снятое называется в отрицательной форме, надгробием, а не стирается молча. Читатель, пришедший за методом, которого больше нет, обязан узнать, что его СНЯЛИ, а не решить, что он ищет не там.
Ось контракта разбирает СТРОКУ ОБЪЯВЛЕНИЯ (`service` / `message` / `enum` / `rpc` в начале строки).
Ось СКВОЗНОГО НАБОРА разбирает порождённую коллекцию как JSON и судит АДРЕС шага. Она заведена позже трёх остальных (`kaname#124`) и ровно потому, что те её предмет не покрывали: они читают `.go`, `.proto` и `.fga`, а набор живёт в `.py` и `.json`. Замер на день заведения: авторитет был снят из всех трёх осей, а набор нёс 47 шагов к его поверхности в двух коллекциях — одиннадцать кейсов целой коллекции и три в соседней. Ни одна ось этого не видела, и утверждения о снятом предмете не краснели и не зеленели: они невыполнимы.
Отступ в образцах записан `[ \t]`, а НЕ `[[:space:]]`, и это не придирка: второй класс включает перевод строки, поэтому совпадение начиналось на строку РАНЬШЕ объявления и находка называла чужую координату. Поймала это инъекция, а не чтение: сам факт находки был верен, неверно было место — то есть гейт послал бы читателя искать не туда. `.proto` не разбирается тем же парсером, но объявление от комментария отличимо: комментарий начинается с `//`, а объявление — с ключевого слова. Граница названа честно: объявление, записанное внутри многострочного комментария `/* */`, разбору невидимо.
───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ ПРЕДИКАТ ПО СЛОВУ `limit` ОТВЕРГНУТ — ЭТО ИЗМЕРЕНО, А НЕ ВЫБРАНО
Прежняя редакция условия снятия kacho#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).
recipe_call_coordinate.go — гейт: КАТАЛОГ, названный строкой ВЫЗОВА в комментарии рецепта сборки, существует в этом дереве (задача PRO-Robotech/kacho#2613, предикат снятия п. 4).
Предмет ¶
Комментарий рецепта говорит читателю, ЧЕМ позвать цель: «Вызов: `make -C <кат> <цель>`». Строка вызова есть обещание исполнимости ЗДЕСЬ — она не описывает историю и не называет чужого держателя, она предписывает команду.
Каталог, которого в дереве нет, делает это обещание неисполнимым, и отказ приходит не там, где ошибка: `make -C <нет каталога>` печатает «нет такого файла или каталога» и выходит кодом 2, то есть читатель получает отказ ИНСТРУМЕНТА вместо отказа цели и идёт разбираться не туда. До задачи kacho#2613 таких строк в этом рецепте было ТРИ, и все три называли `services/iam` — каталог монорепо, от которого модуль отделён: отслеживаемых путей под `services/` в этом дереве НОЛЬ.
Класс тот же, что у соседей `acceptance_path_coordinate.go` (путь предиката) и `acceptance_probe_coordinate.go` (имя пробы): утверждение, пережившее свой предмет. Дерево у него другое — не приёмка, а рецепт сборки, — и потому у него свой держатель.
РАЗБОР ПО ПОЗИЦИЯМ АРГУМЕНТОВ, А НЕ ПОИСК ПОДСТРОКИ ¶
Подстрока `services/iam` встречается в этом файле, в прозе рецепта и в объяснениях прошлых дефектов — и там она ЗАКОННА: она свидетельствует о том, как было. Гейт по подстроке краснел бы на собственном объяснении (ровно тот класс, который корпус ловит).
Поэтому каталог опознаётся ПОЗИЦИЕЙ: строка вызова разбирается на поля, и каталогом признаётся аргумент ключа `-C` — приклеенный (`-C<кат>`) либо следующим полем (`-C <кат>`). Ни одно другое поле каталогом не считается: путь, названный прозой, этот гейт не судит вовсе, и это сказано ниже отдельной строкой, а не умолчано.
ГРАНИЦЫ НАЗВАНЫ, А НЕ УМОЛЧАНЫ ¶
- ПУТЬ, НАЗВАННЫЙ ПРОЗОЙ, не судится. `CLA.md` в объясняющем абзаце — координата, а не вызов; её предмет тот же, но её разбор требует отличать координату от формы имени, и это своя работа со своим замером. Число таких строк здесь не печатается: гейт их не ищет, и напечатанный ноль читался бы как «искали и не нашли».
- КАТАЛОГ СУДИТСЯ НА СУЩЕСТВОВАНИЕ, а не на исполнимость `make` в нём. Каталог, отслеживаемый деревом, но не несущий своего `Makefile`, здесь не находка: рецепт цитирует такую команду, чтобы объяснить, что она НЕИСПОЛНИМА, и отличить цитату от предписания машинно значило бы судить прозу. Ось соседняя и названа здесь, а не умолчана; предмет её — свой.
- ЦЕЛЬ вызова не проверяется. Объявлена ли она рецептом — предмет соседнего гейта провязки (`judge_target_wiring.go`), и второе место об одном предмете разошлось бы с ним молча.
- СТРОКА, НАЗВАВШАЯ ЧУЖОЙ РЕПОЗИТОРИЙ, освобождается: её координаты принадлежат чужому дереву, и требовать их отсюда значило бы завести находку на правдивой записи. Освобождение ВИДИМОЕ — перепись печатает его число, иначе оно стало бы слепой зоной ровно того размера, которого никто не видит.
registration_lanes.go — разбор ОБЪЯВЛЕНИЯ полос регистрации (приёмка Ф4 `docs/engineering/acceptance/registration-and-its-three-consequences.md`, Р4, Ф4-06…Ф4-10; задача PRO-Robotech/kacho#1270).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Полоса регистрации — сущность НАШЕГО кода, перечисленная одним местом: `registration.Lanes` в `internal/apps/kaname/api/registration/lanes.go`. Каждая полоса объявляет свои следствия, и гейт судит ЭТО объявление: полоса, у которой среди следствий нет выдачи сессии, — красное с её именем (Ф4-07); объявление, из которого не разобрано ни одной полосы, — не зелёное и не красное, а «вердикта нет» (Ф4-09).
Предмет переехал сюда из дома платформы: там свойство «каждая полоса выдаёт сессию» держал гейт, читавший объявление ЧУЖОЙ конфигурации по отступам (форма Ф-е). После Ф4 полоса — значение Go, и читается оно разбором.
───────────────────────────────────────────────────────────────────────────── ЧТО РАЗБИРАЕТСЯ — И В КАКИХ ФОРМАХ
Объявление — `var Lanes = []Lane{ … }` в файле объявления. Элемент перечня — составной литерал полосы; читаются два поля:
Name — строковый литерал либо идентификатор константы ТОГО ЖЕ файла;
Consequences — составной литерал среза, чьи элементы — идентификаторы
констант того же файла либо строковые литералы.
Формы записи элемента — ключевая (`{Name: …, Consequences: …}`) и позиционная (`{…, …}`), обе доказаны инъекцией. Выдача сессии узнаётся по ЗНАЧЕНИЮ следствия, а не по имени идентификатора: значение приносит вызывающий от производителя (`registration.ConsequenceSession`), и переименование константы гейт не ослепит.
───────────────────────────────────────────────────────────────────────────── ОБЪЯВЛЕНИЕ — ОДНО
Второе место, перечисляющее полосы, разошлось бы с первым молча, и гейт судил бы перечисленное, а исполнялось бы другое (Ф4-06). Поэтому вторая половина разбора обходит ВЕСЬ прод-код и считает составные литералы типа `Lane` (`registration.Lane` из чужого пакета): литерал вне файла объявления — находка с координатой. Комментарии и строки в счёт не идут by construction — разбор ходит по узлам.
relation_fact_sole_writer.go — разбор «кто пишет в таблицу прямого факта».
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Таблица `kaname.relation_fact` — то, из чего реляционная форма собирает безусловное основание вердикта. Наполняет её ТРИГГЕР на журнале намерений (`kaname.fga_outbox`, `relation_fact_follows_journal`), и это выбор схемы, а не привычка: производителей кортежа много и они разной природы (use-case, реконсайлер, посев старта, сырой SQL миграции), поэтому писатель, добавленный в код, не покрывает SQL вовсе, а перечень «кто ещё обязан писать факт» расходится с деревом при первой же новой миграции — молча.
Пока производитель ОДИН, появление нового происходит by construction: он кладёт строку журнала, и проекция подхватывает её, не зная о нём. Стоит завести второго писателя из кода — и инвариант ломается ровно в ту сторону, которую не видно: факт ЕСТЬ, и вердикт по нему выносится, а журнала за ним нет — то есть нет ни порядка применения, ни снятия, ни разбора оснований.
───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ УЗЕЛ РАЗБОРА, А НЕ ПОДСТРОКА ПО ТЕЛУ ФАЙЛА
Перенесённая из монорепо форма читала ТЕЛО файла целиком и сверяла подстроку. В этом дереве так нельзя: имя таблицы стоит в КОММЕНТАРИЯХ десятка прод-файлов (`module_seed_writer.go`, `fga_outbox/emitter.go`, `authzmodel.go` и другие) — ровно там, где объясняют, что пишет её триггер, а не код. Подстрочный разбор дал бы находку на объяснении инварианта, то есть гейт краснел бы на собственном предмете.
Поэтому запись ищется ТОЛЬКО в строковых литералах (узел ast.BasicLit вида token.STRING), а комментарии считаются ОТДЕЛЬНО и печатаются переписью: их ненулевое число — свидетельство, что разбор дошёл до мест, где о таблице говорят, и промолчал по существу, а не по слепоте.
───────────────────────────────────────────────────────────────────────────── ФОРМЫ ЗАПИСИ — ПЕРЕЧИСЛЕНЫ
SQL в этом дереве пишется многострочными литералами с отступами, поэтому глагол и имя таблицы разделены произвольным пробелом, включая перевод строки. Совпадение ищется по образцу, терпимому к пробелу и регистру:
INSERT INTO kaname.relation_fact одной строкой insert into kaname.relation_fact нижним регистром INSERT INTO\n\t\tkaname.relation_fact переносом и отступом DELETE FROM kaname.relation_fact снятие UPDATE kaname.relation_fact правка
Чтение (`SELECT`) законно и в перечень глаголов НЕ входит: форма его и делает.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦА НАЗВАНА, А НЕ УМОЛЧАНА
Разбор НЕ видит: SQL миграций (там запись законна — миграция и есть схема), проб (им положено готовить состояние) и ДИНАМИЧЕСКИ СОБРАННОГО имени таблицы (склейка из кусков, fmt.Sprintf, константа из другого пакета). Последнее — настоящая слепая зона: имя, собранное из частей, не ловится образцом ничем, и молчание гейта на нём не является доказательством.
request_field_has_a_reader.go — разбор: у КАЖДОГО поля сообщения запроса есть читатель в прод-коде своей службы (задача kacho#1351).
Предмет ¶
Поле запроса, которое принимают и не читают, тише отказа: вызывающий получает УСПЕХ и уверен, что его параметр применён. Продукт обещает возможность, которой нет. Обнаруживается это не отладкой, а последствиями — в чужой.
Норма контракта, которую гейт исполняет: у поля публичного запроса ОБЯЗАН быть читатель в прод-коде своей службы; отсутствие — находка, а не стиль. Законных исходов у непрочитанного поля три, четвёртого нет: реализовать · отвергать явно, называя поле, синхронно · снять с контракта, зарезервировав И номер, И имя. «Молча принять и выбросить» исходом не является.
Почему разбор УЗЛОВ, а не поиск имени геттера по дереву ¶
Имя геттера НЕ уникально. Замер на `lane/wb-s4-remnant`, единицы названы:
# сообщений, объявляющих ОДИН И ТОТ ЖЕ геттер, — 57
grep -c 'func (x \*[A-Za-z]*) GetAccountId()' pkg/api/kaname/cloud/iam/v1/*.pb.go
# различных ИМЁН геттеров, встречающихся в прод-коде, — 150
git grep -ohE '\.Get[A-Za-z0-9_]+\(' -- '*.go' ':!*_test.go' ':!pkg/api' | sort -u | wc -l
Полей в сообщениях запроса при этом 295 (перепись гейта, печатается каждым прогоном). То есть предикат по ИМЕНИ различает 150 значений там, где предмет имеет 295, а одно имя `GetAccountId` покрывает 57 разных полей: мёртвое поле выглядело бы живым оттого, что где-то рядом живёт его тёзка.
Поэтому читатель опознаётся парой «получатель × селектор»: идентификатор, чей ОБЪЯВЛЕННЫЙ тип есть `*<пакет>.<Сообщение>`, и обращение к полю через него. Число 295 в этой шапке — снимок; живое печатает перепись.
Что читателем НЕ является, и это решение, а не упущение ¶
- СБОРКА запроса (`&iamv1.XRequest{AccountId: …}`) — это сторона ПРОИЗВОДИТЕЛЯ. Засчитав её, гейт разрешил бы полю жить оттого, что его кто-то заполняет, — ровно то состояние, которое он заведён ловить;
- проба. Прод-код судится прод-кодом: поле, которое читает только проба, арендатору не служит;
- сгенерированный код (`pkg/api/**`). Он объявляет геттер у КАЖДОГО поля by construction, поэтому засчитанный читателем делает гейт тождественно зелёным.
Граница названа: запрос, ушедший в вызов ЦЕЛИКОМ ¶
Запрос, переданный дальше целиком (`h.uc.Execute(ctx, req)`), прослеживается ровно до того вызываемого, чей параметр объявлен тем же типом: дальше цепочка обрывается на интерфейсе или на своей структуре входа. Такие передачи НЕ прощаются молча — они печатаются переписью отдельной величиной, потому что «поле прочитано» и «запрос уехал целиком, а поле, может, и не прочитано» — разные вердикты, и второй обязан быть видим.
retired_issuer_claim.go — ГЕЙТ КЛАССА: утверждение, что прежний внешний OAuth-сервер ОСТАЁТСЯ подписантом либо издателем (или что служба сама не чеканит), законно только в форме надгробия (эпик kacho#2564, линия B).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Своя чеканка токенов действует на каждой предлагаемой цепочке установки (`deploy/values.prod.yaml`, `authn.tokenSigning.enabled: true`), и пять путей выдачи из шести чеканим мы. Но прозу об этом писали в разное время, и в дереве живут ДВЕ редакции одного утверждения:
«data-plane fetches verification keys from iam (Hydra stays the signer).» «Здесь стояло „Hydra stays the issuer/signer“ — утверждение, пережившее…»
Первая — утверждение, пережившее свой предмет (в дереве оно стояло без кавычек; здесь процитировано, потому что этот файл гейт читает тоже). Вторая — надгробие: та же фраза, но названная ПРЕЖНЕЙ и опровергнутая. Читатель, открывший первую, принимает её за действующее ограничение и строит на ней решение: «раз подписант чужой — ключницу здесь не ротировать, издателя здесь не сверять».
Цена этого класса в этом же дереве уже платилась: одно и то же утверждение «Hydra remains the signer/issuer» жило в ПЯТИ файлах двух репозиториев, и в день, когда его опровергли в одном, четыре других продолжали читаться как норма — их нашла эта перепись, а не обзор диффа.
───────────────────────────────────────────────────────────────────────────── ЧТО СУДИТСЯ — УТВЕРЖДЕНИЕ О ДЕЙСТВУЮЩЕМ, А НЕ СЛОВО
Слово «Hydra» в дереве законно во множестве мест: имена ручек посадки, колонка зеркала в применённой миграции, порт клиента к его админ-API, разбор самого переезда. Гейт по слову краснел бы на исправном дереве и был бы снят первым же обходом. Судится РОД утверждения — что прежний издатель остаётся (stays / remains / является) подписантом или издателем, что ключи проверки «его», что служба ничего не чеканит. Формы перечислены в `RetiredIssuerClaimForms` поимённо, и инъекция гоняет КАЖДУЮ.
───────────────────────────────────────────────────────────────────────────── ЗАКОННЫЙ БЛИЗНЕЦ — НАДГРОБИЕ, И РАСПОЗНАЁТСЯ ОН ДВУМЯ ПРИЗНАКАМИ
- утверждение стоит В КАВЫЧКАХ на той же строке («…», "…", “…”): корпус цитирует снятое именно так — «Здесь стояло „…“»;
- на той же строке стоит маркер прошедшего: «стояло», «It said», «пережившее», «no longer», «больше не».
Любого одного достаточно. Надгробие, разнесённое на две строки так, что ни маркер, ни кавычка не попали на строку с утверждением, гейт назовёт находкой — и это верно: такое надгробие читается как утверждение с той же вероятностью, с какой его не узнал распознаватель.
───────────────────────────────────────────────────────────────────────────── ЧЕГО ГЕЙТ НЕ ВИДИТ — НАЗВАНО ВСЛУХ
Описание полосы, названной по прежнему издателю («Hydra-issued token», «via Hydra»), под ось НЕ подпадает: это описание происхождения, а не утверждение о том, кто подписывает сегодня. Часть таких описаний тоже пережила предмет, и правится она обзором — предикат «назван прежний издатель» от «утверждается, что он действует» машинно не отличает. Пробы и e2e-наборы из обхода исключены: там прежний издатель законно стоит фикстурой.
retired_monorepo_gate_ledger.go — разбор «какие имена проб объявлены этим деревом».
Служебная половина ведомости гейтов, снятых из монорепо выносом службы (kacho#2597): ведомость обязана уметь спросить дерево, резолвится ли названный ею держатель, — и спросить УЗЛОМ ОБЪЯВЛЕНИЯ, а не подстрокой.
Разница несущая. Имя пробы встречается в этом дереве трижды помимо своего объявления: в прозе приёмок, в комментариях, объясняющих чем держится свойство, и в самой ведомости ниже. Подстрочный разбор объявил бы держателя живым по упоминанию о нём — то есть ведомость доказывала бы сама себя.
retired_vendor_bindings.go — ГЕЙТ КЛАССА: привязок к снимаемому провайдеру личности в дереве службы не становится больше, а их убыль записывается тем же изменением, которым она сделана (задача #323, эпик kacho#2564).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Прежний провайдер личности (выдача токена и сессия) снимается из службы. Снятие идёт многими изменениями, и каждое из них обязано уменьшать число привязок, а не менять одни на другие. Замер задачи: поле адреса прежнего издателя в конфигурации обогащения токена стояло в 74 строках 30 файлов на cbbac984 и в 79 строках 31 файла на 8f95be6c6 — две новые пробы полос хуков привязались к нему, и ни одна проверка этого дерева не покраснела.
Судья этого класса у платформы (задачи kacho#2730 и kacho#2864, файл `internal/repohygiene/retiredidentityvendorceiling.go` её дерева) читает дерево службы ПО ПИНУ `go.mod` платформы, то есть видит рост только тогда, когда платформа сдвигает пин, — после того как выросшее изменение уже влито здесь. Этот гейт судит то же дерево в момент изменения.
───────────────────────────────────────────────────────────────────────────── ФОРМА — ВЕДОМОСТЬ ПО ФАЙЛАМ, А НЕ ОДНО ЧИСЛО
Ведомость (`RetiredVendorLedger`, файл `RetiredVendorLedgerRel`) хранит ТОЧНОЕ число привязок каждого файла. Исходов у файла три, и два из них — находки:
привязок больше записи (или записи нет) рост — снимите привязку
привязок меньше записи убыль не записана — снизьте запись
до факта тем же изменением
привязок ноль, запись есть запись без предмета — снимите её
Почему по файлам: сумма по дереву ПРОЩАЕТ перенос. Изменение, снявшее десять строк в одном файле и добавившее одну в новом, по сумме убывает — а новая привязка при этом появилась. Ровно так выглядел рост этой задачи: по всему классу в единице этого гейта дерево между cbbac984 и 8f95be6c6 убыло с 1068 до 873, а две пробы привязались заново. Ведомость по файлам называет такую координату, сумма — нет.
Почему точное число, а не потолок: потолок, не сниженный вслед за убылью, прощает возврат снятого до прежней высоты. Точная запись делает возврат ростом.
ЗАПИСЬ ЗАНИМАЕТ ДВЕ СТРОКИ — путь и число, — и это решение о слиянии, а не вкус. git сливает правки СОСЕДНИХ строк конфликтом (проверено на git 2.53: правки строк 2 и 3 в двух ветках дают конфликт, правки строк 2 и 4 при нетронутой строке 3 — чистое слияние). Две ветки волны, снявшие привязки в разных файлах, правят числа разных записей; строка пути между числами остаётся нетронутой, и сведение волны не конфликтует в ведомости.
───────────────────────────────────────────────────────────────────────────── ЕДИНИЦА СЧЁТА И ОСИ
Класс один: текст несёт имя снимаемого провайдера (`RetiredVendorMarks`), подстрокой без учёта регистра. Мест прочтения три, по оси на каждое:
RetiredVendorAxisPath путь файла несёт имя 1 единица за файл RetiredVendorAxisLine строка текста несёт имя 1 единица за строку RetiredVendorAxisBinary байты двоичного несут имя 1 единица за файл
Граница слова НЕ ставится: слитное написание строчными — настоящая привязка, и правило границы отбросило бы её молча. Измерено на 8f95be6c6: слов, где имя продолжено строчной буквой, в дереве службы два (`hydraadminurl`, `hydraadmintokenenv`), и оба — привязки. Чужое слово, втекающее в имя, придёт находкой роста со своим текстом — видно, а не молча.
───────────────────────────────────────────────────────────────────────────── ЗАКОННЫЕ ФОРМЫ — КАК СНЯТИЕ ЗАПИСЫВАЕТСЯ, НЕ ПОДНИМАЯ ВЕДОМОСТИ
Подъём записи ответом не бывает (граница 4 ниже). Формы, которыми снятие обходится без него:
- ИСТОРИЯ СХЕМЫ СНЯТОГО. Строка каталога истории схемы (миграции и их пробы), каждое имя провайдера в которой — часть идентификатора, снятого самой историей, не привязка: миграция, снимающая столбец, обязана его назвать. Правило, условия и границы — `retired_vendor_schema_history.go`; перепись печатает число таких строк отдельно.
- ИМЯ ИЗ СЛОВАРЯ. Проба стража этого класса берёт имя провайдера из его словаря (`RetiredVendorMarks`, `RetiredIssuerName`), а не выписывает заново: привязка — строка словаря, и считается она один раз. То же для имени настройки: проба собирает его из того же словаря, а не выписывает литералом.
- ПЕРЕНОС. Запись нового файла заводится, запись прежнего снижается, обе правки — в одном диффе (шапка ведомости).
───────────────────────────────────────────────────────────────────────────── ЧЕГО ГЕЙТ НЕ ВИДИТ — НАЗВАНО, А НЕ ПОДРАЗУМЕВАЕТСЯ
- ПРОЗА. Файлы `.md`/`.mdx` и строки, НАЧИНАЮЩИЕСЯ маркером комментария, не судятся: упоминание провайдера в тексте дерево к нему не привязывает, а утверждение о нём как о действующем судит `retired_issuer_claim.go`. Перепись печатает число таких строк отдельно.
- ВЕДОМОСТЬ. Файл `RetiredVendorLedgerRel` — запись этого гейта, а не привязка; он исключён по точному пути, и его отсутствие в дереве — отказ (исключение, которому нечего исключать, истекает само).
- ПУТЬ API ПРОВАЙДЕРА БЕЗ ЕГО ИМЕНИ, ИМЯ, СКЛЕЕННОЕ ИЗ ЛИТЕРАЛОВ, И СОДЕРЖИМОЕ АРХИВОВ. Эти оси держит судья платформы по пину: словарь поверхностей живёт у него в единственном экземпляре, копия его сюда запрещена правилом о копиях между репозиториями. Архивов в дереве службы нет; двоичные судятся байтами, и их число печатается переписью.
- ПОДЪЁМ ЗАПИСИ. Ведомость — файл дерева, и изменение может поднять число записи вместе с ростом. Гейт этого не различает: без дерева базы перенос привязки из файла в файл и чистый рост дают одну и ту же правку. Подъём виден диффом одного файла, а чистый рост против базы ловит судья платформы на сдвиге пина. Так зелёное уже добывалось: сборка #483 подняла пять записей на 42 (коммит 49c38e18c) — строки снятия столбца, проба стража с именем литералом, проба с именем настройки литералом и перенос методов, записанный не в том диффе, где снижен прежний файл. Каждому из этих случаев отвечает законная форма выше.
- ИМЯ ИЗ СЛОВАРЯ В НЕ-ПРОБЕ. Форма «имя из словаря» законна для проб стража; не-тестовый код, собирающий имя провайдера из словаря, привязку прячет, и гейт её не видит — как и всякую склейку (граница 3).
retired_vendor_bindings_ledger.go — ВЕДОМОСТЬ привязок к снимаемому провайдеру личности, по файлу. Судит её `retired_vendor_bindings.go`; единица счёта — `RetiredVendorCountingUnit`.
Число записи — ТОЧНОЕ число привязок файла, а не потолок:
- изменение сняло привязки — число записи снижается тем же изменением до того, что печатает находка «убыль не записана»;
- в файле привязок не осталось либо файл снят — запись снимается;
- привязка перенесена в другой файл — запись того файла заводится, а прежнего снижается, и обе правки стоят в одном диффе рядом.
Запись ЗАНИМАЕТ ДВЕ СТРОКИ — путь и число: две ветки, снявшие привязки в соседних по порядку файлах, правят несоседние строки и сливаются без конфликта (обоснование — шапка `retired_vendor_bindings.go`). Пути строго по возрастанию: форма проверяется судьёй, и место новой записи однозначно.
Точка отсчёта — дерево 8f95be6c6 (голова линии #367 на момент заведения), из которого тем же изменением сняты шесть строк роста, найденного задачей #323: две пробы полос хуков задавали адрес прежнего издателя, которого не судят. На сведённом дереве сборки волны 4 (#483) записи приведены вниз к факту: полосы волны снимали привязки, ещё не зная этой ведомости. Рост, который они принесли в пяти файлах, НЕ записан: три файла сняли привязки по существу, а строки миграции, снявшей столбец зеркала, и её пробы — история схемы снятого идентификатора (`retired_vendor_schema_history.go`); то же снятие снизило запись свода, который столбец завёл. Ни одна запись не поднималась выше точки отсчёта и ни одна не заведена сверх неё. Каждая запись уходит вниз вместе с изменением, снимающим её привязки.
retired_vendor_schema_history.go — ЗАКОННАЯ ФОРМА СНЯТИЯ для гейта `retired_vendor_bindings.go`: строка истории схемы, называющая идентификатор, который сама история сняла, — не привязка (задача #323, сборка #483).
───────────────────────────────────────────────────────────────────────────── ПОЧЕМУ ФОРМА НУЖНА
Столбец, названный по снимаемому провайдеру, снимается миграцией, и миграция обязана назвать его: `DROP COLUMN` без имени не пишется, предохранитель наката спрашивает строки по нему же, откат восстанавливает его под тем же именем, проба миграции засевает прежнее состояние и спрашивает столбец после отката. Судья, считающий каждую такую строку привязкой, объявлял снятие РОСТОМ: миграция снятия столбца зеркала прежнего издателя (#362) дала ему 29 строк в двух новых файлах, и зелёное на сборке #483 было получено подъёмом ведомости — ровно той правкой, которую гейт различить не может (граница 4 его шапки). Эта форма делает подъём ненужным: снятие столбца снижает ведомость, в том числе у свода, который столбец завёл.
───────────────────────────────────────────────────────────────────────────── ПРАВИЛО
Идентификатор СНЯТ ИСТОРИЕЙ, когда выполнены все четыре условия:
- накат (секция до `-- +goose Down`) какой-либо миграции каталога его снимает оператором `DROP COLUMN | CONSTRAINT | INDEX | TABLE` — в исполняемом тексте: снятие в комментарии или в строковом литерале снятием не является;
- после последнего такого снятия тот же накат его не называет;
- ни одна миграция с бóльшей версией его не называет — ни накатом, ни откатом;
- снятий не меньше, чем заведений во всех накатах: имя, заведённое в двух таблицах и снятое в одной, живо.
Строка ФАЙЛА КАТАЛОГА ИСТОРИИ (миграция либо файл Go рядом с ней — проба миграции) не привязка, когда КАЖДОЕ имя провайдера в ней — часть снятого историей идентификатора. Такие строки считаются переписью отдельно и печатаются числом, как проза и комментарии.
Идентификатор — наибольший отрезок `[a-z0-9_]` вокруг вхождения метки, в нижнем регистре, без схемы и кавычек: `kaname.t.<метка>_id` даёт `<метка>_id`, а `t_<метка>_id_check` — самостоятельное имя со своими снятием и заведением.
───────────────────────────────────────────────────────────────────────────── ЧТО ФОРМА НЕ ПРОЩАЕТ — И ЧЕМ ЭТО ДОКАЗАНО
Строка вне каталога истории (репозиторий, край, чарт) — привязка, даже если называет снятый столбец: код, читающий снятый столбец, — дефект, а не история. Вложенный каталог — не история. Путь файла — своя ось, и история её не прощает. Метка пути образа идентификатором SQL не бывает и не прощается никогда. Каждое из этого и каждое из четырёх условий выше гоняется инъекцией: `retired_vendor_schema_history_injection_test.go`.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
Все они падают в сторону ПОДСЧЁТА — незнакомая форма даёт привязку, видимую ростом, а не молчание:
- снятие столбца без слова `COLUMN` (`ALTER TABLE t DROP x`) не узнаётся;
- `DROP TABLE a, b` узнаёт только первое имя;
- заведение считается формами `CREATE [UNIQUE] INDEX`, `CONSTRAINT x` (кроме `DROP CONSTRAINT`), `ADD [COLUMN]`, `CREATE TABLE`, `RENAME … TO` и определением столбца в начале строки; лишнее совпадение (строка условия, начатая именем столбца) досчитывает заведения и падает в сторону подсчёта.
ЕДИНСТВЕННАЯ граница, падающая в сторону ПРОЩЕНИЯ: заведение формой, которой распознаватель не знает (`CREATE TABLE … AS`, `LIKE`, наследование), недосчитывает заведения. После снятия — в том же накате или в поздней миграции — её держат условия 2 и 3: такая форма имя называет. ДО снятия — то же имя во второй таблице, заведённое незнакомой формой, пережило бы снятие в первой, и строки истории о нём прощались бы. Код, читающий такой столбец, лежит вне каталога истории и судится как всякая привязка; прощаются только строки самой истории.
revocation_writer_has_a_caller.go — ПУТЬ СНЯТИЯ ДОСТУПА, НЕ ДОСТИГАЮЩИЙ НОСИТЕЛЯ, КОТОРЫМ СУДИТ ЧИТАТЕЛЬ (задача kaname#313).
───────────────────────────────────────────────────────────────────────────── ФОРМА ДЕФЕКТА, А НЕ ЕГО ЭКЗЕМПЛЯР
Записей отсечки в службе больше одной. У каждой свой ключ, свой круг читателей и своя величина сравнения, и взаимозаменяемыми они не являются. Отсюда форма: запись ОБЪЯВЛЕНА, писатель для неё НАПИСАН, а позвать его некому — и тогда контроль существует в виде кода, не исполняясь ни при каком входе. Отличить это от работающего контроля чтением нельзя: «не отозван» и «отзыв не доехал» дают один и тот же наблюдаемый ответ.
Гейт судит ДЕРЕВО, а не ведомость записей: ведомость ослепла бы ровно тогда, когда опустеет, а множество таблиц отсечки ВЫВОДИТСЯ обходом — по имени, оканчивающемуся на суффикс отсечки, — и печатается переписью.
───────────────────────────────────────────────────────────────────────────── НАПРАВЛЕНИЕ ОШИБКИ ВЫБРАНО, А НЕ ПОЛУЧИЛОСЬ
Вызов опознаётся ПО ИМЕНИ функции или метода где угодно в не-тестовом дереве. Это заведомо ЩЕДРО к писателю: вызов через интерфейс с тем же именем метода засчитывается, хотя разбор не доказывает, что реализация именно эта. Выбрано так намеренно: ложная находка у гейта, судящего безопасность, заставляет снимать сам гейт, а пропуск оставляет предмет видимым другим приборам.
───────────────────────────────────────────────────────────────────────────── ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО, А НЕ СПРЯТАНО
писатель, чей единственный вызывающий — тоже мёртвый код: цепочку достижимости от композиционного корня разбор не строит;
писатель на SQL, собранном из кусков во время исполнения: разбор читает строковый ЛИТЕРАЛ, а не результат конкатенации;
писатель в схеме (триггер, функция) — он не Go и здесь не судится; именно такие писатели и создают вид работающего контроля;
ПИСАТЕЛЬ ОДНОЙ ЗАПИСИ ОТСЕЧКИ ИЗ ДВУХ — у него исполнитель ЕСТЬ, и этот гейт о нём молчит законно. Свойство независимое, и судят его отдельные гейты пары в `paired_write.go`, со СВОЕЙ, узкой склейкой по вызову.
Перечень границ, названный не полностью, хуже отсутствующего: он создаёт уверенность. Эта граница названа здесь потому, что именно её отсутствие позволило дефекту уцелеть — гейт был зелён, а четыре писателя полосы входа клали одну запись из двух.
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 — САМОИСТЕКАЮЩИЙ гейт решения «меточную ось сужать НЕ НАДО» (задача продукта kacho#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` этого агента — предмета оно судит компоненты дерева, отдельная от «когда посеяно» ось). Держать разбор внутри теста значило бы, что следующий перенос его продублирует, не заметив: инструкция переноса прямо требует проверить, не появился ли общий помощник, и переиспользовать его — вместо копии.
sentinel_translator_parity.go — разбор ПЕРЕВОДЧИКОВ отказа: какие полосы каждый из них различает.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Переводчик отказа — то место, где признак хранилища становится кодом gRPC. У домена он свой: текст терминального INTERNAL называет предмет («internal SA key error»), и сводить их в один нельзя — текст есть часть контракта.
Своим обязан быть ТЕКСТ, а не НАБОР РАЗЛИЧАЕМЫХ ПОЛОС. Полоса, которой переводчик не знает, уезжает в терминальный INTERNAL — то есть отказ, ПОВТОРЯЕМЫЙ по своей природе, приходит клиенту как поломка платформы, и клиент не повторит. Обратное так же плохо: отказ в правах, поданный как INTERNAL, прячет от вызывающего, что ему нечего чинить повтором.
Класс уже закрывался ОДНАЖДЫ и вернулся. Годок канонического переводчика говорит дословно: «Полное покрытие 8 sentinel'ов (включая ErrPermissionDenied / ErrUnauthenticated, которых не было в per-resource копиях — leak'ало codes.Internal клиенту до этой консолидации)». Копии завелись заново и снова разошлись набором ветвей (kaname#114): `ErrAborted` достижим — 40001/40P01 приходит из `pgmaperr`, — и на путях ключей и токенов уходил в INTERNAL.
───────────────────────────────────────────────────────────────────────────── ЧТО СЧИТАЕТСЯ ПЕРЕВОДЧИКОМ — ПРИЗНАК СЕМАНТИЧЕСКИЙ, А НЕ ПО ИМЕНИ
Предикат по имени (`mapPGErr`, `mapErr`) мерил бы соглашение об именовании: переводчик, названный иначе, прошёл бы мимо — ровно тот отказ, который гейт и заводится закрыть. Переводчиком считается функция, у которой ОБА признака:
- она различает ДВА И БОЛЕЕ разных sentinel'а `iamerr.Err*` в условии (ветвь `case` бестегового `switch` либо условие `if`);
- её ПОСЛЕДНИЙ оператор — терминальный `status.Error(codes.Internal, "…")` с литералом.
Второй признак и есть «переводчик», а не «проверка на месте вызова»: функция, разбирающая одну полосу и отдающая остальное канону (`shared.MapRepoErr`), терминального INTERNAL не несёт и под разбор не подпадает. Без этого признака находкой стал бы каждый вызывающий, спрашивающий `ErrNotFound`.
───────────────────────────────────────────────────────────────────────────── ФОРМЫ ЗАПИСИ ПЕРЕЧИСЛЕНЫ ПОИМЁННО
Форма, о которой распознаватель не знает, даёт МОЛЧАНИЕ. Читаются:
case errors.Is(err, iamerr.ErrX): — ветвь бестегового switch
case stderrors.Is(err, iamerr.ErrX): — он же под псевдонимом пакета
if errors.Is(err, iamerr.ErrX) { … } — условие if
errors.Is(a, iamerr.ErrX) || errors.Is(…) — дизъюнкция внутри условия
Псевдоним пакета `errors` разбор НЕ читает намеренно: он опознаёт sentinel по АРГУМЕНТУ (`iamerr.ErrX`), а не по имени вызываемого пакета. Поэтому `stderrors`, `goerrors` и любое другое написание опознаются одинаково.
ПОЛОСА КОНЦА КОНТЕКСТА (kaname#383) — не sentinel `iamerr`, а ошибки пакета `context`: `context.Canceled` и `context.DeadlineExceeded`, в тех же формах записи. Пакет опознаётся по ПУТИ ИМПОРТА файла, поэтому псевдоним импорта (`stdctx "context"`) читается так же, как голое имя; файл без импорта пакета читается по голому имени `context`. Поле `Canceled` чужого значения полосой не читается. В признак переводчика (п. 1 выше) эти полосы НЕ входят: счёт — по sentinel'ам `iamerr`, иначе переводчиком стала бы функция, судящая только срок.
───────────────────────────────────────────────────────────────────────────── ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО, А НЕ СПРЯТАНО
- **порядок ветвей**. Он несущий (у канона вложенные полосы спрашиваются до общего switch'а), но это другой предмет и другой гейт;
- **правильность КОДА** у ветви. Гейт судит, различает ли переводчик полосу, а не в какой код он её переводит;
- **переводчик БЕЗ терминального INTERNAL** — он под признак не подпадает и остаётся вне наблюдения. Это осознанная граница: без неё находкой стала бы всякая проверка на месте вызова.
sql_relation_name.go — ОБЩИЙ распознаватель имени отношения в тексте SQL. По нему судят оба гейта материала способа входа: гейт дерева Go — значения строковых литералов и их склеек (`login_verifier_containment.go`), гейт схемы — тексты подпрограмм базы (`internal/repo/kaname/pg` `TestLoginVerifierStaysInsideTheSchema`). Его же лексемы судят посылку гейта единственного писателя счёта (`failure_reset_sole_writer.go`). Разбор ОДИН: вторая копия разошлась бы с первой молча, и расхождение пришлось бы ровно на то написание, которое знает только одна из копий.
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ — ГРАММАТИКА, А НЕ ПОДСТРОКА
Прежде оба гейта искали имя таблицы образцом «целое слово, регистр как есть». Базе регистр имени без кавычек безразличен: `KANAME.USER_LOGIN_METHODS` она разрешает в ту же таблицу, и триггер соседней таблицы, читавший материал так, проходил мимо гейта схемы с «называющих таблицу 0». Ошибался образец и в обратную сторону: `user_login_methods$x` и `user_login_methodsé` для базы — другие имена, а образец считал их упоминанием.
Перечень написаний выведен из лексической структуры Postgres 16 (раздел 4.1 документации: идентификаторы, строковые константы, комментарии), а не из памяти:
ИМЯ
без кавычек [A-Za-z_\x80-\xff][A-Za-z0-9_$\x80-\xff]*; регистр
приводится к нижнему ТОЛЬКО у ASCII — база в UTF8
прочих букв не приводит
в кавычках "…", `""` внутри — кавычка; сравнение побайтовое
Юникодное U&"…" и u&"…": \XXXX, \+XXXXXX, `\\`, суррогатная
пара — один знак; UESCAPE 'c' после имени меняет знак
экранирования
длиннее 63 байт база усекает до 63 (NAMEDATALEN-1) по границе знака —
усекается и здесь
со схемой и без неё `схема.имя` и имя через путь поиска; `ONLY имя`,
`имя AS m`, `имя m`, `имя%ROWTYPE` — судится само имя
ИМЯ ВНУТРИ СТРОКИ — содержимое строки судится как текст SQL ещё раз: так
живут динамический SQL (`EXECUTE '…'`), разбор имени (`'…'::regclass`,
`to_regclass('…')`) и аргумент `format`
'…' и N'…' `''` — кавычка; содержимое судится и как есть, и с
раскрытой обратной косой (на случай посадки с
standard_conforming_strings = off)
E'…' \b \f \n \r \t, \o…\ooo, \xh…\xhh, \uXXXX,
\UXXXXXXXX, `\c` — сам знак c
U&'…' как U&"…", с UESCAPE
$метка$…$метка$ содержимое как есть
продолжение строки, разделённые пробелами с переводом строки
(и строчными комментариями после него), — одна строка
склейка || цепочка строковых констант через `||` судится и
целиком, и по звеньям — как склейка у гейта Go
B'…', X'…' битовые строки: имени не несут и не судятся
КОММЕНТАРИИ — не судятся: `--` до конца строки и `/* */` с вложением.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦЫ, НАЗВАННЫЕ ВСЛУХ
- ИМЯ, СОБРАННОЕ ВО ВРЕМЯ ИСПОЛНЕНИЯ, НЕ УЗНАЁТСЯ: склейка с переменной, `lower('USER_…')`, имя из каталога по oid — это поток данных, а не лексика.
- АРГУМЕНТ `format('%I', …)` СУДИТСЯ КАК ТЕКСТ SQL. `%I` берёт имя в кавычки, и `format('%I', 'USER_LOGIN_METHODS')` называет ДРУГОЕ отношение, — распознаватель найдёт в нём таблицу. Ошибка в сторону лишней находки, не пропуска.
- СТРОКИ, ВЛОЖЕННЫЕ ГЛУБЖЕ sqlMaxNesting, судятся без грамматики: имя ищется без учёта регистра и кавычек — лишняя находка возможна, пропуск нет.
- ОСКОЛОК ТЕКСТА (литерал Go, который склеивают во время исполнения): незакрытые строка и имя в кавычках судятся как текст SQL до конца осколка — они могли открыться в соседнем осколке. Комментарий, открытый в осколке, судится как комментарий.
- ТЕКСТ НЕ НА SQL — подпрограмма на языке, чью грамматику распознаватель не знает: `SQLRoutineNamesRelation` судит его без грамматики, как в границе 3.
- ЭКРАНИРОВАНИЕ НА КРАЮ ДИАПАЗОНА судится как у базы (сверено с postgres:16, проба `sql_relation_name_escape_test.go`): \ooo выше \377 — младший байт (\563 → 's'); \u, \U и U& с нулём либо выше U+10FFFF база отвергает — здесь остаются как написано, и коса граничит имя (лишняя находка, не пропуск). Суррогаты — так же, как у базы, в E-строке и в U&: пара склеивается в один знак (и через смешение \u/\U, \XXXX/\+XXXXXX); одиночный старший, одиночный младший и \u/\U с неполными цифрами база отвергает — здесь они остаются как написано (kaname#174). НЕ судится: годность байтов в кодировке.
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`, задача продукта kacho#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 — разбор для двух гейтов приёмки kacho#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`; задача продукта kacho#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_retired_provider.go — ГЕЙТ КЛАССА: имя утверждения в составе выданного токена не называет прежнего поставщика (kaname#375).
Предмет ¶
Состав утверждений нашего подписанта нёс утверждение, названное по поставщику, на КАЖДОЙ полосе выдачи, в том числе на посадке без поставщика. Имя утверждения — часть контракта токена: читатель, увидевший его, строит на нём решение о том, кто выдал токен. Экземпляр снят; этот гейт держит класс — всякое место сборки состава в дереве, чей ключ называет поставщика, находка.
Что судится ¶
Места сборки находит тот же разбор, что держит единственность состава (`ScanClaimAssemblies`): составной литерал `map[string]…` с ключами префикса утверждений. Судится КЛЮЧ, а не значение и не проза: значение выводится из настройки во время исполнения и дереву не видно — его держат пробы полос (`TestNoIssuanceLaneNamesTheRetiredProvider`). Имя поставщика берётся из одного источника с гейтом прозы (`RetiredIssuerName`).
Чего гейт НЕ видит — названо, а не спрятано ¶
Те же слепые зоны, что у разбора сборок: ключ, присвоенный по одному (`claims["…"] = v`), ключ, собранный из частей или взятый переменной, ключ без префикса утверждений.
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`.
Чего разбор НЕ видит — названо, а не спрятано ¶
- состав, собранный присваиваниями по одному ключу за раз;
- имя ключа, собранное из частей или взятое переменной;
- состав, объявленный в чужом языке.
token_family_sole_writer.go — разбор «кто заводит семейство выданного» (задача PRO-Robotech/kaname#313).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ И ПОЧЕМУ ОН ГЕЙТ, А НЕ ВНИМАНИЕ
Семейство нельзя заводить в сессию, которой больше нет. Держится это НЕ ключом: истечение сессии ключом невыразимо в принципе — производная колонка от `now()` движком отвергается, а обёрнутая замерзает на вставке и говорит «жива» об истёкшей строке. Поэтому условие живости стоит В САМОМ ОПЕРАТОРЕ вставки, вместе с записью.
Цена такой границы названа честно: непредставимость держится ЭТИМ писателем, а не построением. Второй писатель — любая другая вставка в `kaname.token_families` — обойдёт условие молча: он скомпилируется, он пройдёт все пробы церемонии, и он заведёт живое семейство в снятой сессии.
Границе, которая держится писателем, нужен ПРЕДИКАТ, а не внимание. Вот он.
───────────────────────────────────────────────────────────────────────────── СУДИТСЯ СТРОКОВЫЙ ЛИТЕРАЛ В РАЗОБРАННОМ ДЕРЕВЕ, А НЕ ТЕКСТ ФАЙЛА
Разбор идёт по узлам: каждый непроверочный `.go` разбирается, и осматриваются только строковые литералы. Поиск по тексту файла считал бы находкой упоминание в комментарии — в том числе в этом.
Классификация литерала, несущего вставку в таблицу семейств:
несёт условие живости сессии (`ended_at IS NULL` и `expires_at >`) — ОХРАНЯЕМЫЙ не несёт — НАХОДКА
───────────────────────────────────────────────────────────────────────────── ПУСТОЙ ОБХОД — ОТДЕЛЬНЫЙ ИСХОД
Ноль охраняемых писателей означает не «чисто», а «гейт потерял предмет»: константу переименовали, оператор собрали из кусков, таблицу переназвали. Такой обход обязан быть КРАСНЫМ, иначе гейт зеленеет ровно тогда, когда перестаёт смотреть.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦА НАЗВАНА
Оператор, собранный конкатенацией или `fmt.Sprintf` из частей, разбор по литералу не видит — это довод держать оператор ОДНОЙ константой, каким он и написан. Вставка, пришедшая из внешнего файла или сгенерированная, тоже невидима; в дереве таких путей к этой таблице нет.
withdrawal_producer_arrives_with_the_applier.go — разбор прод-дерева на СОГЛАСИЕ двух фактов: применитель ролей модуля приводится в действие, и производитель отзыва роли существует (порт с монорепо `internal/repohygiene/withdrawalproducerarriveswiththeapplier.go`, снят вынесением службы доступа — `kacho#2597`; задача продукта kacho#1913).
Предмет ¶
Сверка `moduleroles.Reconcile` объявляет вид расхождения `LiveNotDeclared` — «строка живёт, объявления у неё больше нет». Пока применитель НЕ приводится в действие в проде, отсутствие производителя снятия — остаток, а не дефект. Как только применитель начинают звать (`cmd/kaname/serve.go`, `moduleroles.NewApplier`, задача kacho#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 AcceptedMigrationForm() *regexp.Regexp
- func AdjudicateCarriedLedger(ledgerPath string, rows []CarriedLedgerRow, ...) []string
- func AdjudicateSeedCensus(decl SeedCensusDeclaration, rep SeedCensusReport) []string
- func AlertExpressionsIn(doc string) []string
- func AllowanceKey(a IssueRefAllowance) string
- func ApplierPortVerbDeletesTheRoleRow(name string) (bool, string)
- func AuditAcceptanceEditsAfterVerdict(root, dir string) ([]AcceptanceEditFinding, AcceptanceEditCensus, error)
- func AuditBareIssueRefs(root string, rels []string, ceiling int) ([]BareIssueRef, IssueRefCensus, 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 CollectCalledNames(path string, src []byte, into map[string]struct{}) error
- func CollectDeclaredNames(path string, src []byte, into map[string]int) error
- func CollectPredicateConcats(files []ReadPathFile, read func(abs string) ([]byte, error)) ([]ConcatFinding, ConcatCensus, error)
- func CompareCatalogCopies(edgeRaw, ownRaw string) ([]CatalogParityFinding, CatalogParityCensus, 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 DoorFormFindings(src string, declared map[string]DoorRow) (inspected map[DoorRow]int, findings []string, err error)
- func ExecutableRunBodies(raw string) ([]string, int, error)
- func FamilyReasonConstants(domainFiles map[string]string, typeName string) (map[string]string, error)
- func FamilyReasonWriterFindings(c FamilyReasonWritersCensus) []string
- func FamilyVerdictFindings(c FamilyVerdictCensus, surfaces []string) []string
- func FoldSeededServiceAccounts(ordered []string, bodies map[string]string) (alive map[string]SeededServiceAccount, unknownForms []string, stmtsTouched int)
- func GeneratedGettersIn(src string) []string
- func GoCamelCase(field string) string
- 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 IsMigrationFile(rel string) bool
- func IsModuleSetSurfaceFile(rel string) bool
- func IsSubjectChangeProducerFile(rel string) bool
- func IsVerbClassRuleSource(rel string) bool
- func IssuanceLaneFindings(files map[string]string, lanes []IssuanceLane) (inspected int, findings []string, err error)
- func JoinGrants(g []RelationGrant) string
- func JoinRelationSet(m map[string]bool) string
- func JoinRevoked(m map[string]string) string
- func JudgeAssuranceAxisColumns(columns []AxisColumnSite, home string, copies map[string]string) []string
- func JudgeAuthorityResidue(corpus, excused map[string]string) (AuthorityResidueCensus, []AuthorityResidueFinding)
- func JudgeCensusFixtures(byDir map[string][]CensusFileFacts) []string
- func JudgeClaimNamesNamingRetiredIssuer(assemblies []ClaimAssembly) ([]ClaimNamingRetiredIssuer, ClaimNamingRetiredIssuerCensus, error)
- func JudgeDocumentedSettingKeys(corpus TreeCorpus, keys map[string]bool) ([]SettingKeyFinding, SettingKeyCensus, error)
- func JudgeRetiredIssuerClaims(corpus map[string]string) ([]RetiredIssuerClaim, RetiredIssuerClaimCensus, error)
- func JudgeTargetWiringFaults(w JudgeTargetWiring) []string
- func LinePublishers() []string
- func MailImportFormIsUnknown(path, ownModule string) bool
- func MailImportIsTransport(path string) bool
- func MailKindOfLiteral(lit string) (string, bool)
- func MailKindsOfSchema(migrations TreeCorpus) (kinds []string, site string, read, decls int, err error)
- func MakefileDeclaresTarget(makefile, target string) bool
- func MarkWriterCalls(files map[string]string) (calls []string, parsed int, err error)
- 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 PeopleAddressInput(rel string) bool
- func PeopleAppliedMigrationRels() []string
- func PeopleRowWrites(sql string) (writes []string, upLines int)
- func ProbeCoordinateResolves(name string, declared []string) bool
- func ProbeDeclaredInHome(dir, ref, name string) bool
- func ProbeToolingGoFile(rel string) bool
- func ProdGoFiles(root string) (map[string]string, error)
- func ProdGoRoots(root string, tracked []string) ([]string, error)
- func ProductionGoFile(rel string) bool
- func ProtoTypeDecls(src []byte) []string
- 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 RetiredIssuerProseFile(rel string) bool
- func ReviewBaseBranches() []string
- func RevocationWriterPremise(parsed, floor int, c RevocationWriterCensus) error
- func RevokedRelationsFromMigrations(root string) (map[string]string, int, error)
- func SQLCreateTableBody(upSection, table string) string
- func SQLNamesRelation(src, relation string) bool
- func SQLRelationNamings(src, relation string) []string
- func SQLRoutineNamesRelation(language, src, relation string) (names, grammar bool)
- func ScanAddressInRefusalText(root string, files []string) (AddressCensus, []AddressFinding, error)
- func ScanApplierDeletes(path string, src []byte) (sites []ApplierDeleteSite, census ApplierDeleteCensus, err error)
- func ScanAssuranceLevelUses(path string, src []byte, homeImport string) ([]LevelUse, LevelUseCensus, error)
- func ScanAuditPayloads(root string) (findings []AuditPayloadFinding, census AuditPayloadCensus, err error)
- func ScanBindingInsertLedger(path string, src []byte) ([]BindingInsertSite, BindingInsertCensus, 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 ScanCommentCoordinates(path string, src []byte) (out []CommentCoordinate, census CommentCoordinateCensus, err error)
- func ScanCriticalHeaderRule(path string, src []byte) (sites []CriticalHeaderRuleSite, census CriticalHeaderRuleCensus, err error)
- func ScanDerivedIDDeclarations(path string, src []byte) (sites []DerivedIDImportSite, census DerivedIDCensus, err error)
- func ScanDocHeaders(path string, src []byte) (sites []DocHeaderSite, census DocHeaderCensus, err error)
- func ScanFactWrites(path string, src []byte, table string, verbs []string) ([]FactWriteSite, FactScanCensus, error)
- func ScanFailureResetUses(path string, src []byte) ([]FailureResetUse, FailureResetCensus, 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 ScanKeyProjections(path string, src []byte) ([]KeyProjection, KeyTypeCensus, error)
- func ScanMailSendFile(rel string, src []byte, ownModule string) (paths []MailSendPath, kinds []MailKindSite, census MailSendCensus, err error)
- func ScanMailSendPaths(root string) (paths []MailSendPath, kinds []MailKindSite, census MailSendCensus, err error)
- func ScanMembershipRemovalFile(rel string, src []byte) (sites []MembershipRemovalSite, census MembershipRemovalCensus, err error)
- func ScanMembershipRemovals(root string) (sites []MembershipRemovalSite, census MembershipRemovalCensus, err error)
- func ScanMethodVocabularyLists(path string, src []byte, vocabulary []string) ([]VocabularyListSite, VocabularyScanCensus, error)
- 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 ScanPairedStatements(path string, src []byte, first, second *regexp.Regexp, into map[string][2]bool) error
- func ScanPairedWrites(path string, src []byte, first, second *regexp.Regexp, ...) ([]PairedWriteFunc, PairedWriteCensus, error)
- func ScanProtoCommentRefs(path string, src []byte) (refs []ProtoCommentRef, census ProtoCommentCensus)
- func ScanRawOperationsRepo(root string) ([]RawOperationsRepoSite, TerminalRefusalCensus, error)
- func ScanRegistrationLanes(path string, src []byte, sessionValue string) ([]RegistrationLane, RegistrationLanesCensus, error)
- func ScanRevocationStatements(path string, src []byte, into map[string]string) error
- func ScanRevocationWriters(path string, src []byte, statements map[string]string) ([]RevocationWriter, RevocationWriterCensus, 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 ScanSentinelTranslators(path string, src []byte) (out []SentinelTranslator, census SentinelTranslatorCensus, err 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 ShippedGoFile(rel string) bool
- func SortedFuncNames(byFunc map[string]FunctionDatabaseCalls) []string
- func SortedTables(c RevocationWriterCensus) []string
- func SplitAlgorithmValues(values []string) (algorithms []string, hasEmpty bool)
- func SubjectChangeRosterTotal(declared map[string]int) int
- func TrackedDirsOf(tracked []string) map[string]bool
- func TrackedPathsOfTree(root string) ([]string, error)
- func TreeModulePath(root string) (string, error)
- type AcceptanceEditCensus
- type AcceptanceEditFinding
- type AddressCensus
- type AddressFinding
- type AlgorithmConstraint
- type AlgorithmDictionaryCensus
- type ApplierDeleteCensus
- type ApplierDeleteSite
- type AssertionVerifierCensus
- type AuditPayloadCensus
- type AuditPayloadFinding
- type AuditPayloadKey
- type AuditPayloadSite
- type AuditPersonalKey
- type AuthorityResidueCensus
- type AuthorityResidueFinding
- type AxisColumnSite
- type BareIssueRef
- type BindingInsertCensus
- type BindingInsertSite
- type BoolWrapperCall
- type CarriedLedgerCensus
- type CarriedLedgerRow
- type CarriedLedgerSection
- type CatalogCoverageCensus
- type CatalogFoundationRename
- type CatalogParityCensus
- type CatalogParityFinding
- type CatalogPendingEntry
- type CatalogRetiredEntry
- type CatalogRevisedEntry
- type CatalogSource
- type CatalogWriteCensus
- type CatalogWriteFinding
- type CensusFileFacts
- type CeremonyCoordinate
- type CeremonySurfaceCensus
- type CeremonySurfaceReport
- type CeremonySurfaceSpec
- type ClaimAssembly
- type ClaimAssemblyCensus
- type ClaimBuilderCall
- type ClaimNamingRetiredIssuer
- type ClaimNamingRetiredIssuerCensus
- type CommentCoordinate
- type CommentCoordinateCensus
- type ConcatCensus
- type ConcatFinding
- type ContractMethod
- type CoordinateVerdict
- type CriticalHeaderRuleCensus
- type CriticalHeaderRuleSite
- type DatabaseCallCensus
- type DatabaseCallSite
- type DeadPathCoordinate
- type DeadProbeCoordinate
- type DeclaredFuncCensus
- type DeleteRevokeCensus
- type DerivedIDCensus
- type DerivedIDImportSite
- type DocHeaderCensus
- type DocHeaderSite
- type DoorRow
- type DrainForm
- type DrainSite
- type EnvelopeEmbedding
- type EnvelopeMeterCarrier
- type EnvelopeMeterWrite
- type EnvelopePortImpl
- type EnvelopeRootCensus
- type EnvelopeRootSpec
- type EnvelopeRootVerdict
- type EnvelopeSite
- type EnvelopeSiteForm
- type EnvelopeTypeBypass
- type ExclusionFormCensus
- type ExclusionFormFinding
- type ExclusionFormInput
- type ExportProcedureCensus
- type FactScanCensus
- type FactWriteSite
- type FailureResetCensus
- type FailureResetLedgerEntry
- type FailureResetUse
- type FailureResetUseKind
- type FailureResetVerdictCensus
- type FailureRowRemoval
- type FailureRowRemovalCensus
- type FailureRowRemovalKind
- type FamilyReasonWord
- type FamilyReasonWritersCensus
- type FamilyVerdictCensus
- type FamilyVerdictSite
- type FunctionDatabaseCalls
- type GoSQLLiteral
- type GuardFileCensus
- type GuardFileScan
- type GuardMention
- type GuardMentionForm
- type HistoryCensus
- type HistoryQuestion
- type HomeVerdict
- type IdentityGrowthReaderCensus
- type ImagePublishedCensus
- type InjectionCensus
- type InjectionFinding
- type IssuanceLane
- type IssueRefAllowance
- type IssueRefCensus
- type IssueRefExclusion
- type JobFieldRead
- type JobKnobCensus
- type JobSection
- type JudgeTargetWiring
- type KeyField
- type KeyProjection
- type KeyTypeCensus
- type LenientScopeCensus
- type LevelUse
- type LevelUseCensus
- type LevelUseKind
- type LoginVerifierCensus
- type LoginVerifierConsumer
- type LoginVerifierConsumerKind
- type LoginVerifierFlowCensus
- type LoginVerifierSpec
- type MachineryCensus
- type MachineryClaim
- type MachineryFacts
- type MachineryKind
- type MailKindInventory
- type MailKindSite
- type MailSendCensus
- type MailSendFinding
- type MailSendPath
- type MailSenderCensus
- type MailSenderSite
- type MailWriterCensus
- type MembershipRemovalCensus
- type MembershipRemovalSite
- type MigrationRoleCensus
- type MigrationRoleSite
- type MigrationSectionSplitCensus
- type MigrationVersion
- type MigrationVersionAudit
- type MigrationVersionCensus
- type MigrationVersionOutcome
- type MirrorConditionOutcome
- type MirrorWiringScan
- type MirrorWrite
- type ModuleManifestSite
- type ModuleSetDecl
- type ModuleSetFinding
- type ModuleSetScan
- type NonASCIIIdent
- type OAuthFamilyCensus
- type OAuthFamilyWriter
- type OAuthFamilyWriterKind
- type PairedWriteCensus
- type PairedWriteFunc
- type PasswordHashRecordView
- type PasswordHashRegistryCensus
- type PasswordHashRegistrySpec
- type PasswordRuleCensus
- type PasswordRuleForm
- type PasswordRuleSite
- type PathCoordinate
- type PathCoordinateCensus
- type PathScanBorders
- type PeopleAddressCensus
- type PeopleAddressHalf
- type PeopleAppliedSite
- type PeopleLawfulGoWriter
- type ProbeCoordinate
- type ProbeCoordinateCensus
- type ProbeToolingCensus
- type ProtoCommentCensus
- type ProtoCommentRef
- type ProtoField
- type ProtoMessage
- type ProtoSurface
- type QueueInventory
- type RawOperationsRepoSite
- type ReadPathFile
- type RecipeCall
- type RecipeCallCensus
- type RecoveryPathMarkCensus
- type RecoveryPathMarkDecl
- type RefusalTextCensus
- type RefusalTextDecl
- type RefusalTextFinding
- type RegistrationLane
- type RegistrationLaneLiteralSite
- type RegistrationLanesCensus
- type RelationGrant
- type RequestFieldCensus
- type RequestFieldRead
- type RequestUse
- type RetiredIssuerClaim
- type RetiredIssuerClaimCensus
- type RetiredVendorBinding
- type RetiredVendorCensus
- type RetiredVendorFinding
- type RetiredVendorLedgerEntry
- type RetiredVendorVerdict
- type ReviewTriggerCensus
- type RevocationWriter
- type RevocationWriterCensus
- 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 SchemaQueues
- type SchemaValueListSite
- type SeedCensusCell
- type SeedCensusDeclaration
- type SeedCensusReport
- type SeededServiceAccount
- type SentinelTranslator
- type SentinelTranslatorCensus
- type SettingKeyCensus
- type SettingKeyFinding
- type SubjectChangeProducer
- type SubjectChangeRosterDiff
- type SurfaceHit
- type SurfaceRoutes
- type TerminalRefusalCensus
- type TokenClaimCensus
- type TokenClaimForm
- type TokenClaimUse
- type TreeCorpus
- func CorpusFrom(tree *treecorpus.Tree, want func(rel string) bool) (TreeCorpus, error)
- func DrainSiteCorpus(tree *treecorpus.Tree) (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 UnresolvedPathEntry
- type VerbFormSentinelCensus
- type Vertex
- type VocabularyListSite
- type VocabularyScanCensus
- type WrapperPair
- type WrapperScanReport
Constants ¶
const ( FormAddressIdent = "имя-переменной" FormAddressField = "поле-или-геттер" )
Формы записи адреса. Имена уезжают в перепись.
const ( // AssuranceHomeImport — путь пакета, где словарь и правило объявлены. AssuranceHomeImport = "github.com/PRO-Robotech/kaname/internal/assurance" // AssuranceHomeRel — его каталог от корня модуля. AssuranceHomeRel = "internal/assurance" )
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 ( // CatalogFindingLedger — находка в ведомости послаблений. CatalogFindingLedger = "ведомость" // CatalogFindingCopies — находка в самих копиях. CatalogFindingCopies = "копии" )
Виды находок. Разделены потому, что у них РАЗНЫЙ адресат: ведомость правят здесь, а расхождение копий ведёт либо к синхронизации, либо к платформе. Общий заголовок «копии разошлись» на находке ведомости лгал бы: при наступившем предикате снятия копии как раз СОВПАДАЮТ.
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 — каталог пакета-производителя, ОТ КОРНЯ своего модуля // (было `internal/repo/kaname/pg/resource_mirror`). EdgeProducerDir = "internal/repo/kaname/pg/resource_mirror" // EdgeProducerImport — хвост пути импорта. В самостоятельном модуле // службы совпадает с каталогом (расхождение, из-за которого монорепо // нёс ДВЕ константы, было следствием сегмента `services/iam`, которого // у своего модуля нет). EdgeProducerImport = EdgeProducerDir )
const ( // FailureResetPort — имя порта, обнуляющего счёт по адресу. FailureResetPort = "ResetFailures" // FailureResetHomeRel — дом единственного писателя от корня модуля: здесь // решается «завершён ли вход до уровня всех заведённых факторов». FailureResetHomeRel = "internal/apps/kaname/api/humansession/completed_login.go" )
const ( // FailureRowsTable — таблица следов неверных предъявлений: её строки и // есть счёт по адресу и по источнику. FailureRowsTable = "login_failures" // FailureRowsSweep — уборщик следов старше самого длинного окна счёта. FailureRowsSweep = "SweepAgedFailures" )
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 — где живут правила оповещений службы. // // Это ПРОИЗВОДИТЕЛЬ, а не его пересказ, и различие здесь несущее. Прежде // координата называла инженерный документ — то есть КОПИЮ, оставшуюся от // переноса правил на опубликованную страницу. Гейт был зелен, а свойство не // выполнялось: `kaname_identities_total` читало правило, которое жило // только в копии и не поставлялось никому (`kacho#2545`). Читатель, которого // нет у того, кто поставил продукт, читателем не является. // // Наведя гейт сюда, мы получили ЧЕСТНЫЙ красный — «ряд объявлен, но его не // читает ни одно правило», — и он снялся заведением правила в поставку, а не // правкой текста. IdentityGrowthReadersFile = "deploy/templates/prometheusrule.yaml" )
const ( // MailKindInvite — приглашение (ID-MAIL-1 Р23). MailKindInvite = "invite" // MailKindRecovery — восстановление доступа (Ф5 Р3, Д5 — переезд из полосы // поставщика; `kacho#1271`). MailKindRecovery = "recovery" // MailKindVerification — подтверждение адреса (kaname#456, Р8 — переезд // назван одобренной приёмкой). MailKindVerification = "verification" // MailKindEmailChange — код смены адреса на новый адрес (kaname#635, Р7 — // вид назван одобренной приёмкой // `email-change-is-confirmed-from-the-new-address.md`). MailKindEmailChange = "email-change" // MailKindEmailChanged — уведомление о смене адреса на прежний адрес // (kaname#635, Р7 — та же приёмка). MailKindEmailChanged = "email-changed" )
Виды письма, чей производитель — наш код.
const ( // ResourceMirrorTable — зеркало каталога ресурсов. ResourceMirrorTable = "kaname.resource_mirror" // MirrorReferenceLane — каталог ЭТАЛОННОЙ полосы: путь, по которому // регистрация от владельца ресурса доходит до строки зеркала. // // Переедет каталог — гейт объявит ОТКАЗ, а не промолчит: сверять «тем же // условием» станет не с чем. Правь эту константу тем же изменением, каким // двигаешь пакет. MirrorReferenceLane = "internal/repo/kaname/pg/resource_mirror/" )
const ( // PeopleRowsTable — таблица строк людей. PeopleRowsTable = "users" // PeopleAddressColumn — колонка адреса человека. PeopleAddressColumn = "email" // PeopleMarkColumn — колонка отметки подтверждения адреса человека. PeopleMarkColumn = "email_verified_at" )
const ( SetListUpdate = "UPDATE … SET" SetListConflict = "ON CONFLICT … DO UPDATE SET" SetListMerge = "MERGE … THEN UPDATE SET" )
Ветви списка SET — ключи переписи.
const ( PeopleStmtUpdate = "UPDATE" PeopleStmtInsert = "INSERT" PeopleStmtDelete = "DELETE" PeopleStmtMerge = "MERGE" )
Виды операторов записи в строки людей — ключи переписи.
const ( AxisContract = "контракт" AxisGoCode = "прод-код" AxisCatalogue = "каталог видов" AxisModel = "модель прав" AxisSuite = "сквозная проба" )
Названия осей. Вынесены константами, потому что их называет и инъекция: ось, переименованная в одном месте из двух, дала бы пробу, утверждающую о другой.
const ( // RegistrationHomeRel — каталог полосы регистрации от корня модуля. RegistrationHomeRel = "internal/apps/kaname/api/registration" // RegistrationLanesFileRel — файл ЕДИНСТВЕННОГО объявления полос. RegistrationLanesFileRel = RegistrationHomeRel + "/lanes.go" // RegistrationLanesVar — имя переменной объявления. RegistrationLanesVar = "Lanes" // RegistrationLaneType — имя типа полосы. RegistrationLaneType = "Lane" )
const ( RetiredVendorAxisPath = "имя провайдера в пути" RetiredVendorAxisLine = "имя провайдера в строке" RetiredVendorAxisBinary = "имя провайдера в байтах двоичного" )
Оси — константами, чтобы проба утверждала ось, а не подстроку текста.
const ( RetiredVendorGrown = "рост" RetiredVendorShrunk = "убыль не записана" RetiredVendorOrphan = "запись без предмета" )
Виды находки — закрытый словарь.
const ( SQLFormBare = "без кавычек" SQLFormQuoted = "в кавычках" SQLFormUnicode = "U&\"…\"" SQLFormInString = "внутри строки" SQLFormNoGrammar = "без грамматики" )
Формы записи имени — ключи переписи у вызывающих.
const ( TokenClaimOwnNamespace = "kaname" TokenClaimForeignNamespace = "kacho" )
TokenClaimOwnNamespace / TokenClaimForeignNamespace — свой и чужой словарь.
const AcceptanceHistoryFloor = 2
AcceptanceHistoryFloor — глубина истории дома приёмок, ниже которой признак «правлено после вердикта» НЕВЫРАЗИМ.
Два коммита — минимум, при котором отметка строки состояния и отметка файла МОГУТ разойтись. При одном они равны у каждого документа, поэтому ветвь сравнения не исполняется ни разу, и её молчание не означает ничего.
const AcceptedMigrationFormLayout = "YYYYMMDDHHMMSS_<что_делает>.sql"
AcceptedMigrationFormLayout — форма имени словами. Одна строка на всё дерево: вторая редакция того же расходится молча.
const AssertionVerifierHomeRel = "internal/webauthnverify/"
AssertionVerifierHomeRel — дом проверяющего от корня модуля.
const AssertionVerifierImport = "github.com/PRO-Robotech/kaname/internal/webauthnverify"
AssertionVerifierImport — путь импорта дома проверяющего.
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 CeremonyResolveDepthLimit = 16
CeremonyResolveDepthLimit — предел глубины прохождения запроса.
const CeremonySolveRoundLimit = 200
CeremonySolveRoundLimit — предел раундов неподвижной точки разбора.
Страж, а не условие сходимости: прослеживание монотонно на конечной решётке (места рождения, копии по местам вызова без повторов, поля, результаты), и неподвижная точка наступает всегда. Предел ловит рост сверх разумного, и его достижение — «гейт не исполнился» с числом раундов, а не вердикт по недособранному разбору. Сколько раундов ушло на самом деле, печатает перепись (SolveRounds, «раундов разбора N из предела»): число здесь не выписано, чтобы не пережить свой предмет.
const CriticalHeaderRuleFunc = "CriticalHeadersUnderstood"
CriticalHeaderRuleFunc — имя правила.
const CriticalHeaderRulePackage = "github.com/PRO-Robotech/corelib/tokenpolicy"
CriticalHeaderRulePackage — путь импорта дома правила критичных параметров.
const DeliveryMarkerColumn = "sent_at"
DeliveryMarkerColumn — колонка, которой в этом дереве помечают доставленную строку.
Словарь у признака ОДИН, и это замер, а не допущение: по всем миграциям службы колонок-признаков доставки ровно одна форма записи (`grep -ohE '\b(sent_at|delivered_at|processed_at|dispatched_at)\b' internal/migrations/*.sql | sort -u` → `sent_at`). Появится вторая — очередь, названная ею, выпадет из признака КОЛОНКИ, но останется в признаке ИМЕНИ, и расхождение двух чисел переписи это покажет.
const DerivedIDPackage = "crypto/md5"
DerivedIDPackage — путь импорта, вычисляющий дайджест.
const DrainRosterName = "commutativeDrainExempt"
DrainRosterName — имя росписи освобождений, на которое обязано сослаться обоснование в точке решения.
Константой, а не литералом в теле проверки: переименуют роспись — поправят здесь же, и два места об одном имени не заведутся.
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 FactTable = "kaname.relation_fact"
FactTable — таблица прямого факта.
const FailureResetHomeCall = "resetFailuresOnCompletedLogin"
FailureResetHomeCall — имя, которым полоса зовёт дом.
const FamilyVerdictRulePackage = "internal/tokenrevocation"
FamilyVerdictRulePackage — каталог правила отзыва, единственного вправе звать порт чтения семейства.
const FingerprintSourceRel = "services/iam/internal/repo/kaname/pg/scalegrid/fingerprint.go"
FingerprintSourceRel — объявление предмета замера, из которого ВЫВОДИТСЯ объём этого разбора.
Координата дана ОТ КОРНЯ ДЕРЕВА ПЛАТФОРМЫ, как и всё, что резолвится `treeposture`: приставка снимается самим резолвом, когда модуль стоит самостоятельным клоном. Своя, «модульная» форма здесь была бы вторым написанием одной координаты — а сам предмет замера объявляет каталоги именно в этой форме, и разбор обязан читать ту же.
const GeneratedStubsPrefix = "pkg/api/"
GeneratedStubsPrefix — каталог сгенерированных стабов: правило, найденное там, принадлежало бы генератору, а не дереву.
const ImageProducerJob = "image"
ImageProducerJob — задание, производящее и публикующее образ.
const ImagePublishCondition = "steps.gate.outputs.push == 'true'"
ImagePublishCondition — условие публикации. Его же несёт флаг отправки шага сборки (это проверяется как предпосылка), и им же обязана быть условлена сверка.
const ImagePublishedRevisionScript = ".github/scripts/image-published-revision.sh"
ImagePublishedRevisionScript — сверка опубликованного образа. ОДНО объявление координаты: вторая копия разошлась бы с первой молча.
const InstallGuideSuffix = "INSTALL.md"
InstallGuideSuffix — по чему инструкции обновления опознаются в составе дерева.
const JobsConfigTypeName = "JobsConfig"
JobsConfigTypeName — структура, чьи поля суть секции фоновых заданий.
const JobsSelectorName = "Jobs"
JobsSelectorName — поле, через которое корень добирается до секций.
const KanameNumberCeiling = 704
KanameNumberCeiling — наибольший номер задачи либо запроса службы на день замера. Номера у задач и запросов общие, поэтому потолок взят по обоим:
gh api 'repos/PRO-Robotech/kaname/issues?state=all&per_page=1&sort=created' --jq '.[0].number' → 704 @ 2026-10-11
Потолок отстаёт от трекера by construction. Ссылку на задачу службы новее потолка пишите `kaname#<N>` — префикс законен для любой задачи и потолка не требует; поднимать потолок вправе только новый замер той же командой.
const LineBranchPattern = "[0-9]+"
LineBranchPattern — форма имени ветки ЛИНИИ (волны, эпика): одна или больше цифр, и ничего больше.
Синтаксис фильтра провайдера: класс `[0-9]` — одна цифра, `+` — «один или больше предыдущего знака», и образец сопоставляется со ВСЕМ именем ветки. `'[0-9]*'` НЕ равносилен ему: `*` берёт любой хвост без косой черты, и ветка `2564-line-b` стала бы линией.
const MailEventKindColumn = "event_type"
MailEventKindColumn — колонка очереди, несущая вид события.
const MailKindNamespace = "mail."
MailKindNamespace — приставка всякого вида письма. Единственное объявление предмета обеих осей.
const ManifestLoaderDir = "internal/manifest"
ManifestLoaderDir — прод-файлы загрузчика манифеста. Гейт читает их как ТЕКСТ дерева: импортировать пакет отсюда нельзя (правило видимости `internal` тут ни при чём — импорт завёл бы зависимость гейта от предмета, который он судит).
const MigrationSectionOwnerRel = "internal/migrations/sql_text.go"
MigrationSectionOwnerRel — ЕДИНСТВЕННЫЙ файл дерева, которому положено выписывать директиву секции: он её и объявляет.
const MirrorDivergenceFunc = "Divergence"
MirrorDivergenceFunc — имя читателя, чей вызывающий здесь стережётся.
const MirrorDivergencePkgSuffix = "/repo/kaname/pg/resource_mirror"
MirrorDivergencePkgSuffix — хвост пути пакета-читателя разности.
const ModuleSetPkgRel = "internal/authzmap"
ModuleSetPkgRel — каталог пакета, объявляющего закрытую таблицу типов.
const ModuleSetVarName = "objectTypes"
ModuleSetVarName — имя переменной, чей составной литерал разбирается.
const PasswordRuleHomeRel = "internal/apps/kaname/api/humansession/password_rule.go"
PasswordRuleHomeRel — дом правила: единственный файл, где объявления законны.
const PlatformLayoutPrefix = "services/iam"
PlatformLayoutPrefix — приставка чужой раскладки, которую переезд оставил.
const ProbeToolingDir = "internal/testsupport/"
ProbeToolingDir — каталог оснастки проб относительно корня модуля.
const QueueTableSuffix = "_outbox"
QueueTableSuffix — приставка имени очереди в схеме службы.
Признак ИМЕНИ, а не единственный: рядом работает признак КОЛОНКИ (`DeliveryMarkerColumn`), и перепись печатает оба числа. Два признака об одном предмете заведены нарочно — расхождение между ними означает, что один из них разъехался с деревом, и это видно, а не молчит.
const RetiredIssuerName = "hydra"
RetiredIssuerName — имя снимаемого компонента, как его пишут в дереве.
const RetiredVendorCountingUnit = "строка текста, несущая имя провайдера, — одна единица, " +
"сколько бы вхождений в ней ни было; путь, несущий имя, — одна единица за файл сверх " +
"его строк; двоичный файл с именем в байтах — одна единица"
RetiredVendorCountingUnit — единица счёта одним текстом; печатается переписью.
const RetiredVendorLedgerRel = "internal/check/retired_vendor_bindings_ledger.go"
RetiredVendorLedgerRel — путь ведомости от корня дерева. Единственный путь, исключённый из обхода поимённо.
const RetiredVendorSchemaHistoryDir = "internal/migrations/"
RetiredVendorSchemaHistoryDir — каталог истории схемы службы: её миграции и их пробы. Судятся только прямые его файлы.
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 SentinelIAMPackage = "iamerr"
SentinelIAMPackage — пакет sentinel'ов, по которому они опознаются.
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 VendorRecordPath = "tests/newman/vendor-provenance.json"
VendorRecordPath — запись вендоренного слоя newman-набора.
const WithdrawalApplierImportPath = "github.com/PRO-Robotech/kaname/internal/apps/kaname/moduleroles"
WithdrawalApplierImportPath — пакет применителя ролей модуля.
const WorkflowsDirRel = ".github/workflows"
WorkflowsDirRel — дом заданий конвейера, единственный род носителей провязки в этом дереве.
Variables ¶
var ( // ErrRetiredVendorLedgerAbsent — файла ведомости нет в обходе. ErrRetiredVendorLedgerAbsent = errors.New("файла ведомости нет в обойдённом дереве") // ErrRetiredVendorLedgerForm — ведомость записана не по форме. ErrRetiredVendorLedgerForm = errors.New("ведомость записана не по форме") )
Отказы: там, где судить не по чему. Третья категория, а не «находок ноль».
var AcceptancePathCoordinateExemptions []DeadPathCoordinate
AcceptancePathCoordinateExemptions — ВЕДОМОСТЬ ПУСТА, и это её цель, а не её поломка. Заводя запись — назови номер задачи и предикат снятия рядом.
var AcceptanceProbeCoordinateExemptions = []DeadProbeCoordinate{ { Name: "TestAccessKeyPresentationHasNoSessionLevelConsumer", Docs: []string{"docs/engineering/acceptance/assurance-level-is-declared-by-our-session.md"}, Issue: 613, Note: "проба снята вместе с предметом: ось «заведено» читает ключи (kaname#613)", }, { Name: "TestNoStaleConditionExceptions", Docs: []string{"docs/engineering/acceptance/assurance-level-is-declared-by-our-session.md"}, Issue: 133, Note: "проба снята вместе с ведомостью исключений: условные записи модели получили производителя (kaname#133)", }, }
AcceptanceProbeCoordinateExemptions — ведомость послаблений; пустая — её цель, а не поломка. Заводя запись — назови номер задачи и предикат снятия в комментарии рядом.
var AuthorityResidueLedger = map[string]string{}
var ErrEmptyTraversal = errors.New("обход пуст: прочитано ноль файлов")
ErrEmptyTraversal — обход не принёс НИ ОДНОГО файла.
Отдельная ошибка, а не просто текст: вызывающий вправе отличить «прочитано ноль» от «читать не удалось», и эти два исхода требуют разных действий — первый чинят предметом гейта, второй условиями прогона.
var ErrEnvelopeRootPremise = errors.New("посылка стража корня композиции не держится")
ErrEnvelopeRootPremise — посылка стража корня не держится: объявления, по которым он узнаёт построение и меру, не найдены либо неоднозначны.
var ExclusionCoPresenceTerms = []string{"presented", "forwarded"}
ExclusionCoPresenceTerms — слова, которыми сообщение отказа называет СОЧЕТАНИЕ двух форм.
Требуются ВСЕ: отказ, назвавший одну форму, — про неё одну. Сообщения отказа читателя английские, поэтому и слова английские.
var ExclusionWrapFuncs = []string{"UnaryOver", "StreamOver"}
ExclusionWrapFuncs — имена, которыми читатель НАКРЫВАЕТ пару звеньев переданной личности. Обе полосы вызова: одиночная и потоковая.
var FactMutationVerbs = []string{"INSERT INTO", "UPDATE", "DELETE FROM"}
FactMutationVerbs — глаголы записи. SELECT сюда не входит намеренно.
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 — шесть сценариев, чья проверка полноты и есть содержание отсрочки. Перечень ЗАКРЫТ и выписан: он приезжает из приёмки `kacho#1090`, а не из дерева, и выводить его неоткуда — проб этих сценариев в дереве ноль by construction, то есть вывод из дерева дал бы пустой перечень и гейт, которому нечего требовать.
var OurMailKinds = []string{MailKindInvite, MailKindRecovery, MailKindVerification, MailKindEmailChange, MailKindEmailChanged}
OurMailKinds — ЗАКРЫТЫЙ перечень видов, которые отправляет наш код. Каждый обязан иметь путь отправки (иначе вид без производителя), и ни один чужой вид пути иметь не вправе.
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 RetiredIssuerClaimForms = []struct { Name string Re *regexp.Regexp }{ {"остаётся (stays/remains)", regexp.MustCompile(`(?i)\bhydra\s+(stays|remains)\b`)}, {"является издателем/подписантом", regexp.MustCompile( `(?i)\bhydra\s+is\s+(still\s+)?the\s+(token\s+)?(issuer|signer)\b|\b(issuer|signer)\s+is\s+hydra\b`)}, {"ключи проверки — его", regexp.MustCompile(`(?i)\b(keys?|kids?)\s+(are|is)\s+hydra's`)}, {"служба не чеканит", regexp.MustCompile( `(?i)\b(iam|kaname|shim|service|it)\s+(mints\s+nothing|does\s+not\s+mint|doesn't\s+mint)\b|\(hydra\s+does\)|\b(iam|kaname|служба|шим)\s+(ничего\s+не\s+чеканит|не\s+чеканит\s+ничего)`)}, {"остаётся (по-русски)", regexp.MustCompile( `(?i)\bhydra\s+оста[её]тся\b|(издател|подписант)[а-яё]*\s*[—–-]+\s*hydra\b|\bhydra\s*[—–-]+\s*(единственн[а-яё]+\s+)?(издател|подписант)`)}, }
RetiredIssuerClaimForms — формы утверждения «прежний издатель действует», каждая — отдельный распознаватель. Перечень закрыт и гоняется инъекцией поимённо: форма, о которой распознаватель не знает, даёт не красное и не зелёное, а молчание.
var RetiredVendorLedger = []RetiredVendorLedgerEntry{
{File: "docs/specs/reviews/access-keys-are-ours/79a82b12e95fe969b29b960ad98c02685dc97363cddd1f565ed778f5baaa531c.yaml",
Bindings: 1},
{File: "docs/specs/reviews/assurance-level-is-declared-by-our-session/87d47598d5b7fc860492709b7d2fdbca4fb851e0795cd07fce2c336aeb860a66.yaml",
Bindings: 1},
{File: "docs/specs/reviews/assurance-level-is-declared-by-our-session/c67a550612873247126eff7baf4ee68200fe136c200c3c0c039af18f17f17d6f.yaml",
Bindings: 1},
{File: "docs/specs/reviews/login-lane-issues-our-session-and-logout-ends-it-server-side/1a7f6846d102068bd7023eab4527010b573a22f43a1c988416a4c5f63e1a1170.yaml",
Bindings: 1},
{File: "docs/specs/reviews/login-lane-issues-our-session-and-logout-ends-it-server-side/f0c5850724d1372fb4be5d305c7bbcd22e45bbf613315912ed88bd3ab06e7fed.yaml",
Bindings: 2},
{File: "docs/specs/reviews/login-session-and-credentials-are-our-contract/664d261d56f3b8c845f0fe3e958d7a968b78b207c0073010835cca715cf3ac7e.yaml",
Bindings: 3},
{File: "docs/specs/reviews/login-session-and-credentials-are-our-contract/8893e52c686f57076c3f556803264dab5a0dea309e4c578f51a69f1dfdb4b24c.yaml",
Bindings: 6},
{File: "docs/specs/reviews/login-session-and-credentials-are-our-contract/8cdb75fcc0139c48bd0d78fd36ecbc398328428c24d386865eb02e2dc14d32e5.yaml",
Bindings: 2},
{File: "docs/specs/reviews/login-session-and-credentials-are-our-contract/d65209d603f2b9fb455571af072f3fd00ad82b7229bd5e6a453866ad2225b12d.yaml",
Bindings: 3},
{File: "docs/specs/reviews/login-session-and-credentials-are-our-contract/f8ea0dd42091d04138cd055a43e0ff3a4ffa6de82ef37d8b7d36768e3a16f9b8.yaml",
Bindings: 1},
{File: "docs/specs/reviews/password-verifier-follows-the-stored-value/2554fb6f46fa7f5768f746b5d620843fc045e53d7778919d9829f1b9467070cb.yaml",
Bindings: 1},
{File: "docs/specs/reviews/password-verifier-follows-the-stored-value/52bb1359370197d81ef5b9a42d75b83ff47dec17e787573a2495c8ff3f3cb852.yaml",
Bindings: 1},
{File: "docs/specs/reviews/password-verifier-follows-the-stored-value/b191a212653e8ac0caa9d58a663e884b31bd23995c5525c50fe2202fc763bbef.yaml",
Bindings: 1},
{File: "docs/specs/reviews/passwordless-login-with-access-key/305f0777c4864536746b45977419b55fa6e8c0b12985148b7a0ab34a21ced05f.yaml",
Bindings: 1},
{File: "docs/specs/reviews/passwordless-login-with-access-key/449a08dda5a3c693a81eb8acbee91767355ba57a227128ed9b73c07237c8bbdf.yaml",
Bindings: 1},
{File: "docs/specs/reviews/recovery-of-access/e889257fcf903394913affa761dc3d55ab54c8616c34175adce5cce63abcdc39.yaml",
Bindings: 1},
{File: "docs/specs/reviews/registration-and-its-three-consequences/397640b0fb41191a55aa6838c5a726e78151511d77203aa3192d70cf7f990be0.yaml",
Bindings: 1},
{File: "docs/specs/reviews/second-factor-totp-and-recovery-codes/08b6e9f7adfc32cd859c1aff6f5c211c708ca84e0e857f915173d346b9b490d3.yaml",
Bindings: 2},
{File: "internal/apps/kaname/config/lane_gates_injection_test.go",
Bindings: 3},
{File: "internal/apps/kaname/config/lane_gates_test.go",
Bindings: 1},
{File: "internal/bootstraptokenwire/provider_absent_injection_test.go",
Bindings: 1},
{File: "internal/check/carried_coordinate_ledger_test.go",
Bindings: 1},
{File: "internal/check/retired_issuer_claim.go",
Bindings: 6},
{File: "internal/check/retired_issuer_claim_injection_test.go",
Bindings: 12},
{File: "internal/check/retired_vendor_bindings.go",
Bindings: 1},
{File: "internal/errors/client_vocabulary_test.go",
Bindings: 1},
{File: "internal/migrations/0001_initial.sql",
Bindings: 1},
{File: "internal/migrations/20260917015400_recovery_code_is_our_record.sql",
Bindings: 1},
{File: "pkg/api/kaname/cloud/iam/v1/service_account_oauth_client.pb.go",
Bindings: 1},
{File: "pkg/api/kaname/cloud/iam/v1/user_oauth_client.pb.go",
Bindings: 1},
{File: "proto/kaname/cloud/iam/v1/service_account_oauth_client.proto",
Bindings: 1},
{File: "proto/kaname/cloud/iam/v1/user_oauth_client.proto",
Bindings: 1},
{File: "scripts/provider-revocation-equivalence-probe.sh",
Bindings: 2},
{File: "tests/newman/scripts/selftest_token_facade_forms.py",
Bindings: 1},
}
RetiredVendorLedger — точное число привязок по файлу, по возрастанию пути.
var RetiredVendorMarks = []string{"hydra", "kratos", "oryd/"}
RetiredVendorMarks — имя снимаемого провайдера личности, по которому узнаётся класс: служба выдачи, служба сессии и пространство их образов. Голое имя издателя библиотек сюда НЕ входит: под ним же живёт библиотека собственной чеканки токенов, ради которой снятие и делается.
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 AcceptedMigrationForm ¶ added in v0.5.0
AcceptedMigrationForm — ПРИНИМАЮЩАЯ форма имени новой миграции.
Отличается от [migrationVersionAny] ПРЕДМЕТОМ, а не строгостью: тот читает номер любой ширины (чтобы видеть унаследованное), эта говорит, что принимается у добавленного.
Объявление формы для ЧЕЛОВЕКА живёт в одном месте — `docs/engineering/architecture/migration-version-namespace.md`; здесь стоит её машинное представление, и документ на него ссылается, а не повторяет.
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 AllowanceKey ¶ added in v0.5.0
func AllowanceKey(a IssueRefAllowance) string
AllowanceKey — ключ позволения в переписи.
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 AuditBareIssueRefs ¶ added in v0.5.0
func AuditBareIssueRefs(root string, rels []string, ceiling int) ([]BareIssueRef, IssueRefCensus, error)
AuditBareIssueRefs судит файлы rels под root: голая ссылка с номером выше ceiling вне исключений и позволений — находка.
Пустой перечень — ошибка, а не «чисто»: ноль поданного означал бы ноль прочитанного при любом состоянии дерева.
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 CollectCalledNames ¶ added in v0.5.0
CollectCalledNames собирает имена, вызванные в ОДНОМ файле, — и функции, и методы (по последнему сегменту селектора).
func CollectDeclaredNames ¶ added in v0.5.0
CollectDeclaredNames собирает имена ОБЪЯВЛЕННЫХ функций и методов файла.
Нужны они затем, чтобы отличить «писателя не зовут» от «по имени не разобрать»: имя, объявленное в дереве не один раз, вызовом по имени не прослеживается, и молчание гейта на нём означало бы «я не смотрел».
func CollectPredicateConcats ¶ added in v0.3.0
func CollectPredicateConcats(files []ReadPathFile, read func(abs string) ([]byte, error)) ( []ConcatFinding, ConcatCensus, error, )
CollectPredicateConcats — находки и объём по перечню файлов.
read подаётся вызывающим: инъекция кормит разбор синтетикой, не трогая диск.
func CompareCatalogCopies ¶ added in v0.5.0
func CompareCatalogCopies(edgeRaw, ownRaw string) ([]CatalogParityFinding, CatalogParityCensus, error)
CompareCatalogCopies — сверка против ДЕЙСТВУЮЩЕЙ ведомости дерева. Возвращает перечень находок (пустой = зелёное) и перепись. Ошибка — это ТРЕТИЙ ИСХОД: разобрать не удалось, вердикта о совпадении копий НЕТ (не путать с находкой).
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 DoorFormFindings ¶ added in v0.5.0
func DoorFormFindings(src string, declared map[string]DoorRow) (inspected map[DoorRow]int, findings []string, err error)
DoorFormFindings — перепись экспортированных методов двери (`*Client` в src) против объявления: форма без строки, строка без формы, форма «под предикатом», не зовущая предиката. Печатаемое число — осмотрено форм.
func ExecutableRunBodies ¶ added in v0.2.0
ExecutableRunBodies — тела `run:` без строк оболочечных комментариев.
func FamilyReasonConstants ¶ added in v0.5.0
func FamilyReasonConstants(domainFiles map[string]string, typeName string) (map[string]string, error)
FamilyReasonConstants разбирает файлы домена и возвращает константы названного типа: имя → значение. Объявление без явного типа в счёт не идёт — у словаря тип указан у каждой константы.
func FamilyReasonWriterFindings ¶ added in v0.5.0
func FamilyReasonWriterFindings(c FamilyReasonWritersCensus) []string
FamilyReasonWriterFindings — вердикт по переписи. Пустой обход — находка сам по себе: «ноль прочитанного» не выдаётся за «ноль находок».
func FamilyVerdictFindings ¶ added in v0.5.0
func FamilyVerdictFindings(c FamilyVerdictCensus, surfaces []string) []string
FamilyVerdictFindings судит перепись против ЗАКРЫТОГО перечня поверхностей. Пусто — норма.
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 GeneratedGettersIn ¶ added in v0.5.0
GeneratedGettersIn возвращает пары «сообщение|геттер», объявленные сгенерированным файлом, — в форме `<Сообщение>|<Геттер>`.
Читается ОБЪЯВЛЕНИЕ метода узлом разбора, а не строка с `func (x *`: имя сообщения встречается в этом файле и комментарием, и строковым литералом дескриптора, и поиск по тексту засчитал бы их.
func GoCamelCase ¶ added in v0.5.0
GoCamelCase переводит имя поля контракта в имя геттера так же, как это делает генератор: разделитель снимается, следующая за ним буква поднимается в верхний регистр, цифры остаются как есть.
Начальные заглавные НЕ схлопываются в инициализмы: генератор даёт `AccountId`, а не `AccountID`, и гейт обязан спрашивать то имя, которое в дереве есть.
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 IsMigrationFile ¶ added in v0.5.0
IsMigrationFile — путь принадлежит дому миграций службы и несёт текст миграции.
Файл в том же каталоге, миграцией не являющийся (README, Go, ведомость дропов), предметом гейта НЕ является и находкой стать не может — но он ВХОДИТ В ЗНАМЕНАТЕЛЬ обхода: «рассмотрено 32 из 96» говорит, что обход видел каталог целиком, а не наткнулся на один файл.
func IsModuleSetSurfaceFile ¶ added in v0.4.0
IsModuleSetSurfaceFile — лежит ли файл на КЛИЕНТСКОЙ ПОВЕРХНОСТИ, перечни которой сверяются с набором.
func IsSubjectChangeProducerFile ¶ added in v0.3.0
IsSubjectChangeProducerFile — лежит ли координата в слое use-case и не проба ли это.
func IsVerbClassRuleSource ¶ added in v0.4.0
IsVerbClassRuleSource — файл, в котором правило «класс глагола» вправе быть объявлено. Тестовый корпус вычитается намеренно: фикстура инъекции обязана уметь написать форму дефекта, иначе гейт нельзя проверить.
func IssuanceLaneFindings ¶ added in v0.5.0
func IssuanceLaneFindings(files map[string]string, lanes []IssuanceLane) (inspected int, findings []string, err error)
IssuanceLaneFindings — каждая объявленная полоса существует и спрашивает правило выдачи; пустой перечень — находка.
func JoinGrants ¶ added in v0.3.0
func JoinGrants(g []RelationGrant) string
JoinGrants — различные пары «тип#отношение», по порядку.
func JoinRelationSet ¶ added in v0.3.0
JoinRelationSet — отношения одного типа, по порядку.
func JoinRevoked ¶ added in v0.5.0
JoinRevoked — отозванные отношения, по порядку. Для переписи: «отзывов N» без перечня не отличает точный отзыв от бланкетного.
func JudgeAssuranceAxisColumns ¶ added in v0.5.0
func JudgeAssuranceAxisColumns(columns []AxisColumnSite, home string, copies map[string]string) []string
JudgeAssuranceAxisColumns судит объявления оси уровня в схеме.
Объявление при таблице сессии (home) — дом состояния уровня. Объявление при таблице ведомости копий (copies: таблица → основание) — СНИМОК уровня, сделанный чтением записи сессии и дальше неподвижный: у гранта церемонии это уровень на выдаче кода, который обмен и оборот не пересчитывают (приёмка LINE-A-1 Р5/Р6, `oauthceremony.SessionRecord`). Объявление при любой иной таблице — находка: второе место хранения. Ведомость самоистекает: таблица копий без объявления оси в схеме — находка, как и дом без объявления.
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 JudgeClaimNamesNamingRetiredIssuer ¶ added in v0.5.0
func JudgeClaimNamesNamingRetiredIssuer(assemblies []ClaimAssembly) ( []ClaimNamingRetiredIssuer, ClaimNamingRetiredIssuerCensus, error, )
JudgeClaimNamesNamingRetiredIssuer — тело гейта над найденными сборками. Вынесено, чтобы инъекция звала ТО ЖЕ, что исполняется на дереве.
Пустой перечень сборок — отказ, а не «находок нет»: разбор, не нашедший ни одной сборки, ничего не осмотрел.
func JudgeDocumentedSettingKeys ¶ added in v0.5.0
func JudgeDocumentedSettingKeys(corpus TreeCorpus, keys map[string]bool) ([]SettingKeyFinding, SettingKeyCensus, error)
JudgeDocumentedSettingKeys — тело гейта над прочитанным. Инъекция зовёт ЕГО же, поэтому и корпус, и множество ключей приходят параметрами.
ТРИ ИСХОДА: вердикт · отказ предпосылки (ключей ноль — судить не по чему) · пустая ведомость (описей ноль) — и последняя ЗЕЛЁНАЯ: это цель, а не провал.
func JudgeRetiredIssuerClaims ¶ added in v0.5.0
func JudgeRetiredIssuerClaims(corpus map[string]string) ([]RetiredIssuerClaim, RetiredIssuerClaimCensus, error)
JudgeRetiredIssuerClaims — тело гейта над телами файлов. Вынесено, чтобы инъекция звала ТО ЖЕ, что исполняется на дереве.
Пустой корпус — отказ, а не «находок нет».
func JudgeTargetWiringFaults ¶ added in v0.3.0
func JudgeTargetWiringFaults(w JudgeTargetWiring) []string
JudgeTargetWiringFaults — находки по ОБЕИМ сторонам провязки.
Сверка идёт в обе стороны намеренно. Односторонняя («объявлена — обязана быть звана») пропускала бы обратный случай: носитель зовёт цель, которой рецепт не объявляет, — шаг молча зеленеет на несуществующей цели, потому что `make` такого имени не знает и... отказывает; а под `|| true` или в подстановке не отказывает вовсе. Это провязка в пустоту, и она хуже отсутствующей: выглядит исполненной.
func LinePublishers ¶ added in v0.5.0
func LinePublishers() []string
LinePublishers — имена объявлений процессов публикации, по порядку.
func MailImportFormIsUnknown ¶ added in v0.5.0
MailImportFormIsUnknown — предикат ОТКАЗА: путь импорта говорит о почте, а ни известным транспортом, ни известным не-транспортом, ни пакетом своего модуля не является. Исключений ровно три, и каждое — закрытый список либо го-модуль: предикат, отвергающий всё с «mail» в пути, назвал бы неизвестной формой собственное хранилище очереди.
func MailImportIsTransport ¶ added in v0.5.0
MailImportIsTransport — предикат оси 1: говорит ли этот импорт с почтовым узлом. Судит СЕГМЕНТЫ пути, а не подстроку.
func MailKindOfLiteral ¶ added in v0.5.0
MailKindOfLiteral — вид письма, названный литералом. Второе значение — был ли литерал именем события очереди вообще.
func MailKindsOfSchema ¶ added in v0.5.0
func MailKindsOfSchema(migrations TreeCorpus) (kinds []string, site string, read, decls int, err error)
MailKindsOfSchema — виды письма по корпусу миграций: последнее живое объявление словаря на колонке вида, чей перечень лежит в пространстве `mail.`.
Возвращает отсортированные виды, файл живого объявления, число прочитанных миграций и число осмотренных объявлений словаря на колонке вида (включая не-почтовые — они считаются, но в словарь не идут).
func MakefileDeclaresTarget ¶ added in v0.2.0
MakefileDeclaresTarget — объявлена ли цель в тексте Makefile.
func MarkWriterCalls ¶ added in v0.5.0
MarkWriterCalls — координаты ВЫЗОВОВ писателя отметки подтверждения (`MarkEmailVerified`) в непроверочном коде и число разобранных файлов. Объявления метода вызовами не считаются.
func MissingGrantedRelations ¶ added in v0.3.0
func MissingGrantedRelations(grants []RelationGrant, model map[string]map[string]bool, revoked map[string]string) []string
MissingGrantedRelations — выдачи, у которых в модели нет типа либо отношения.
revoked — отношения, чью выдачу снимает позднейшая миграция (`RevokedRelationsFromMigrations`). Передаётся ПАРАМЕТРОМ, а не берётся внутри: инъекция подаёт сюда синтетику, и судья, ходящий за ведомостью сам, на ней бы не работал.
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 PeopleAddressInput ¶ added in v0.5.0
PeopleAddressInput — отбор корпуса гейта: непроверочный Go и миграции службы. Объявлен один раз: гейт дерева и его перепись судят один отбор.
func PeopleAppliedMigrationRels ¶ added in v0.5.0
func PeopleAppliedMigrationRels() []string
PeopleAppliedMigrationRels — файлы, которые называет ведомость, без повторов: по ним проба гейта дерева сверяет, что каждый ПРИМЕНЁН и не тронут.
func PeopleRowWrites ¶ added in v0.5.0
PeopleRowWrites — операторы записи в строки людей в секции НАКАТА миграции; строки комментария не считаются. Второе число — осмотрено строк наката.
func ProbeCoordinateResolves ¶ added in v0.2.0
ProbeCoordinateResolves — объявленное имя начинается с координаты. declared обязан быть отсортирован: имя с префиксом P сортируется не раньше P, поэтому кандидат ровно один и находится двоичным поиском.
func ProbeDeclaredInHome ¶ added in v0.3.0
ProbeDeclaredInHome — объявлена ли проба в названном доме на названной ссылке.
func ProbeToolingGoFile ¶ added in v0.5.0
ProbeToolingGoFile — не-тестовый файл Go оснастки проб.
func ProdGoFiles ¶ added in v0.5.0
ProdGoFiles — непроверочные исходники каталогов `internal` и `cmd` модуля с корнем root: путь относительно корня в косой записи → текст. Состав берётся из индекса git, а не с диска.
Это тот состав, который `FamilyVerdict` судит на дереве. Гейт, опирающийся на ту же перепись (например, на число вызовов писателя записи выпуска), берёт состав отсюда: два состава одного факта разошлись бы молча.
func ProdGoRoots ¶ added in v0.2.0
ProdGoRoots — верхнеуровневые каталоги дерева, несущие отслеживаемый не-тестовый Go-код. Выведены обходом, а не выписаны.
func ProductionGoFile ¶ added in v0.4.0
ProductionGoFile — не-тестовый файл Go внутри области обхода.
Отбор, который в этом дереве повторяется чаще прочих. Объявлен один раз по той же причине, что и `OutsideTraversal`: три копии «`.go`, не `_test.go`, не служебный каталог» разошлись бы на первом же новом исключении.
func ProtoTypeDecls ¶ added in v0.5.0
ProtoTypeDecls — имена message и enum, объявленные одним файлом контракта.
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 RetiredIssuerProseFile ¶ added in v0.5.0
RetiredIssuerProseFile — файл, чью прозу гейт судит: всё отслеживаемое, кроме проб, e2e-наборов, порождённых стабов, замков зависимостей и двоичного.
Документация ВХОДИТ намеренно: страница оператора — то место, где утверждение переживает предмет дольше всего, потому что её никто не компилирует.
func ReviewBaseBranches ¶ added in v0.5.0
func ReviewBaseBranches() []string
ReviewBaseBranches — базы запроса, на которых процесс ОБЯЗАН идти, и только они. Одно объявление в дереве Go: процессы несут его копиями (иначе фильтр провайдеру не объявить), и разойтись копиям не даёт этот разбор.
func RevocationWriterPremise ¶ added in v0.5.0
func RevocationWriterPremise(parsed, floor int, c RevocationWriterCensus) error
RevocationWriterPremise — предпосылка вердикта.
func RevokedRelationsFromMigrations ¶ added in v0.5.0
RevokedRelationsFromMigrations — отношения, чью ВЫДАЧУ снимает накатная половина какой-либо миграции корпуса: имя отношения → координата миграции.
Второе возвращаемое — сколько файлов прочитано. Без него «отзывов ноль» неотличимо от «каталог не прочитан», и ось молча перестала бы работать.
func SQLCreateTableBody ¶ added in v0.2.0
SQLCreateTableBody — тело объявления таблицы, разобранное из НАКАТА (Up-секции без комментариев) миграции. sqlText — полный текст ФАЙЛА миграции (порт зовёт `migrations.MigrationUpSection` сам, чтобы не тянуть зависимость на пакет `migrations` из пакета `check` без нужды — вызывающий подаёт уже подготовленный текст наката).
func SQLNamesRelation ¶ added in v0.5.0
SQLNamesRelation — называет ли текст SQL отношение relation хоть раз. relation — имя, каким его хранит каталог базы.
func SQLRelationNamings ¶ added in v0.5.0
SQLRelationNamings — формы, которыми текст называет отношение: по записи на упоминание. Упоминание внутри строки записывается формой SQLFormInString, как бы оно ни было написано внутри неё.
func SQLRoutineNamesRelation ¶ added in v0.5.0
SQLRoutineNamesRelation — называет ли текст подпрограммы отношение и судился ли он грамматикой SQL. Язык решает, какой: `sql` и `plpgsql` — лексикой SQL (PL/pgSQL передаёт свои операторы разбору SQL как есть); текст на прочих языках — без грамматики (граница 5).
func ScanAddressInRefusalText ¶ added in v0.5.0
func ScanAddressInRefusalText(root string, files []string) (AddressCensus, []AddressFinding, error)
ScanAddressInRefusalText разбирает названные файлы и называет приёмники отказа и журнала, получившие адрес почты. Пустоту обхода судит вызывающий.
func ScanApplierDeletes ¶ added in v0.2.0
func ScanApplierDeletes(path string, src []byte) (sites []ApplierDeleteSite, census ApplierDeleteCensus, err error)
ScanApplierDeletes разбирает один файл пакета применителя.
func ScanAssuranceLevelUses ¶ added in v0.5.0
func ScanAssuranceLevelUses(path string, src []byte, homeImport string) ([]LevelUse, LevelUseCensus, error)
ScanAssuranceLevelUses разбирает один Go-файл и классифицирует обращения к оси уровня по родительскому узлу. homeImport — путь пакета дома правила.
func ScanAuditPayloads ¶ added in v0.3.0
func ScanAuditPayloads(root string) (findings []AuditPayloadFinding, census AuditPayloadCensus, err error)
ScanAuditPayloads обходит ОТСЛЕЖИВАЕМОЕ дерево модуля и находит личные ключи в нагрузках журнала аудита.
Состав берётся из индекса git, а не выписывается: каталог, заведённый завтра, попадает под гейт в день появления.
func ScanBindingInsertLedger ¶ added in v0.5.0
func ScanBindingInsertLedger(path string, src []byte) ([]BindingInsertSite, BindingInsertCensus, error)
ScanBindingInsertLedger разбирает один Go-файл и возвращает каждую вставку привязки доступа с признаком записи ведомости в той же самой внутренней функции.
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
ScanClassRuleDeclarations — объявления правила «класс из имени» в одном исходнике, с координатой каждого.
Неразбираемый исходник отдаёт признак, а не пустой перечень: «объявлений ноль» иначе означало бы и «их нет», и «разбор не состоялся».
func ScanCommentCoordinates ¶ added in v0.5.0
func ScanCommentCoordinates(path string, src []byte) (out []CommentCoordinate, census CommentCoordinateCensus, err error)
ScanCommentCoordinates разбирает один файл и возвращает координаты приставки, названные В КОММЕНТАРИЯХ, вместе с объёмом осмотренного. Отбор находок здесь НЕ делается: резолюция хвоста — свойство дерева, и её знает вызывающий.
func ScanCriticalHeaderRule ¶ added in v0.5.0
func ScanCriticalHeaderRule(path string, src []byte) (sites []CriticalHeaderRuleSite, census CriticalHeaderRuleCensus, err error)
ScanCriticalHeaderRule разбирает один файл и возвращает обращения к правилу критичных параметров вместе с объёмом осмотренного.
func ScanDerivedIDDeclarations ¶ added in v0.2.0
func ScanDerivedIDDeclarations(path string, src []byte) (sites []DerivedIDImportSite, census DerivedIDCensus, err error)
ScanDerivedIDDeclarations разбирает один файл и возвращает импорты `crypto/md5` вместе с объёмом осмотренного.
func ScanDocHeaders ¶ added in v0.5.0
func ScanDocHeaders(path string, src []byte) (sites []DocHeaderSite, census DocHeaderCensus, err error)
ScanDocHeaders разбирает один файл и возвращает ВСЕ прочитанные шапки формы «Имя — текст» вместе с объёмом осмотренного. Находки не отбираются здесь намеренно: отбор делает вызывающий, и тот же предикат зовёт инъекция.
func ScanFactWrites ¶ added in v0.5.0
func ScanFactWrites(path string, src []byte, table string, verbs []string) ([]FactWriteSite, FactScanCensus, error)
ScanFactWrites разбирает один файл и возвращает записи в таблицу прямого факта, найденные В СТРОКОВЫХ ЛИТЕРАЛАХ, вместе с объёмом осмотренного.
func ScanFailureResetUses ¶ added in v0.5.0
func ScanFailureResetUses(path string, src []byte) ([]FailureResetUse, FailureResetCensus, error)
ScanFailureResetUses разбирает один Go-файл и классифицирует обращения к порту обнуления счёта по узлу.
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 ScanKeyProjections ¶ added in v0.5.0
func ScanKeyProjections(path string, src []byte) ([]KeyProjection, KeyTypeCensus, error)
ScanKeyProjections разбирает один файл и возвращает найденные пары форм ключа вместе с объёмом осмотренного.
Перепись возвращается ВСЕГДА, включая случай «пар не найдено»: без неё «ноль находок» неотличимо от «ноль прочитанного».
func ScanMailSendFile ¶ added in v0.5.0
func ScanMailSendFile(rel string, src []byte, ownModule string) (paths []MailSendPath, kinds []MailKindSite, census MailSendCensus, err error)
ScanMailSendFile разбирает ОДИН файл: импорты транспорта и объявления вида.
ownModule — путь своего модуля из go.mod: пакеты своего модуля с «почтой» в пути импорта (хранилище очереди) — наш код, и разбор судит их содержимое там, где они лежат, а не имя импорта.
func ScanMailSendPaths ¶ added in v0.5.0
func ScanMailSendPaths(root string) (paths []MailSendPath, kinds []MailKindSite, census MailSendCensus, err error)
ScanMailSendPaths обходит не-тестовое дерево Go модуля.
func ScanMembershipRemovalFile ¶ added in v0.5.0
func ScanMembershipRemovalFile(rel string, src []byte) (sites []MembershipRemovalSite, census MembershipRemovalCensus, err error)
ScanMembershipRemovalFile разбирает ОДИН файл.
func ScanMembershipRemovals ¶ added in v0.5.0
func ScanMembershipRemovals(root string) (sites []MembershipRemovalSite, census MembershipRemovalCensus, err error)
ScanMembershipRemovals обходит не-тестовое дерево Go модуля.
func ScanMethodVocabularyLists ¶ added in v0.5.0
func ScanMethodVocabularyLists(path string, src []byte, vocabulary []string) ([]VocabularyListSite, VocabularyScanCensus, error)
ScanMethodVocabularyLists разбирает один Go-файл и возвращает узлы, несущие два и более различных имени словаря строковыми литералами.
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 ScanPairedStatements ¶ added in v0.5.0
func ScanPairedStatements(path string, src []byte, first, second *regexp.Regexp, into map[string][2]bool, ) error
ScanPairedStatements собирает ОБЪЯВЛЕНИЯ операторов, вынесенные из тела: имя константы либо переменной → какое из двух действий она делает.
ФОРМА ЭТА — НОРМА ЭТОГО ДЕРЕВА: оператор выносят ровно затем, чтобы исполнителей у него стало двое. Разбор, знающий только литерал В ТЕЛЕ, не видел бы именно тех, кого делят две полосы, — и первая редакция гейта действительно видела ОДИН снимающий оператор из двух (измерено).
func ScanPairedWrites ¶ added in v0.5.0
func ScanPairedWrites(path string, src []byte, first, second *regexp.Regexp, statements map[string][2]bool, ) ( []PairedWriteFunc, PairedWriteCensus, error, )
ScanPairedWrites разбирает ОДИН файл на пару действий, заданных образцами.
statements — объявления операторов, собранные первым проходом: функция, назвавшая такое объявление, делает действие ровно так же, как назвавшая литерал.
func ScanProtoCommentRefs ¶ added in v0.5.0
func ScanProtoCommentRefs(path string, src []byte) (refs []ProtoCommentRef, census ProtoCommentCensus)
ScanProtoCommentRefs разбирает один файл контракта и возвращает ссылки комментариев вместе с объёмом осмотренного. Находки не отбираются здесь: отбор делает вызывающий, и тот же предикат зовёт инъекция.
func ScanRawOperationsRepo ¶ added in v0.3.0
func ScanRawOperationsRepo(root string) ([]RawOperationsRepoSite, TerminalRefusalCensus, error)
ScanRawOperationsRepo обходит отслеживаемое дерево и находит вызовы сырого конструктора репозитория операций, отмечая обёрнутые.
func ScanRegistrationLanes ¶ added in v0.5.0
func ScanRegistrationLanes(path string, src []byte, sessionValue string) ([]RegistrationLane, RegistrationLanesCensus, error)
ScanRegistrationLanes разбирает файл объявления: находит `var Lanes = []Lane{…}` и читает каждую полосу. sessionValue — значение следствия «сессия выдана» от производителя.
func ScanRevocationStatements ¶ added in v0.5.0
ScanRevocationStatements собирает ОБЪЯВЛЕНИЯ операторов записи, вынесенные из тела, — имя константы либо переменной → таблица.
ФОРМА ЭТА НЕ РЕДКОСТЬ, А НОРМА ЭТОГО ДЕРЕВА: оператор выносят ровно затем, чтобы исполнителей у него стало двое (пул и транзакция), и не иметь двух копий. Разбор, знающий только литерал В ТЕЛЕ, не видел бы именно тех писателей, которых делят между собой две полосы, — и «находок ноль» у него означало бы «эту форму я не читаю».
Объявление живёт в любом файле ПАКЕТА, поэтому обход идёт в два прохода: сперва объявления по всему дереву, затем писатели.
func ScanRevocationWriters ¶ added in v0.5.0
func ScanRevocationWriters(path string, src []byte, statements map[string]string) ( []RevocationWriter, RevocationWriterCensus, error, )
ScanRevocationWriters разбирает ОДИН файл.
statements — объявления операторов, собранные первым проходом: функция, назвавшая такое объявление, есть писатель ровно так же, как назвавшая литерал.
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 ScanSentinelTranslators ¶ added in v0.5.0
func ScanSentinelTranslators(path string, src []byte) (out []SentinelTranslator, census SentinelTranslatorCensus, err error)
ScanSentinelTranslators разбирает один файл и возвращает переводчиков вместе с объёмом осмотренного.
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 ShippedGoFile ¶ added in v0.5.0
ShippedGoFile — не-тестовый файл Go прод-сборки: вне оснастки проб. Отбор гейтов прод-кода, которым оснастка проб не предмет; предпосылку держит `ProbeToolingImports`.
func SortedFuncNames ¶ added in v0.2.0
func SortedFuncNames(byFunc map[string]FunctionDatabaseCalls) []string
SortedFuncNames — имена разобранных функций для текста отказа.
func SortedTables ¶ added in v0.5.0
func SortedTables(c RevocationWriterCensus) []string
SortedTables — таблицы отсечки переписью, отсортированные.
func SplitAlgorithmValues ¶ added in v0.3.0
SplitAlgorithmValues делит значения словаря на алгоритмы и пустое.
Пустое выносится отдельно намеренно: оно означает «ключа нет», а не «любой алгоритм», и складывать его с алгоритмами значило бы объявить отсутствие ключа одним из них.
func SubjectChangeRosterTotal ¶ added in v0.3.0
SubjectChangeRosterTotal — сколько обращений объявляет перечень.
func TrackedDirsOf ¶ added in v0.5.0
TrackedDirsOf — каталоги, отслеживаемые деревом, из перечня его путей.
Выводятся из ПУТЕЙ, а не обходом диска: обход прочитал бы игнорируемые каталоги (рабочие копии, распаковки, отчёты прогонов), и вердикт стал бы свойством рабочего каталога, а не коммита.
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 AddressCensus ¶ added in v0.5.0
type AddressCensus struct {
Files int // не-тестовых файлов Go разобрано
Sinks map[string]int // приёмников по виду (отказ / журнал / подсказка)
Constants int // пакетных констант проиндексировано
ByForm map[string]int // находок по форме адреса
Opaque []string // непрозрачные вызовы, принявшие адрес: «файл:строка вызов»
}
AddressCensus — перепись одного обхода. Печатается ВСЕГДА.
func (AddressCensus) String ¶ added in v0.5.0
func (c AddressCensus) String() string
type AddressFinding ¶ added in v0.5.0
type AddressFinding struct {
File string // путь относительно корня
Line int
Sink string // имя приёмника, как оно записано
Kind string // отказ / журнал / подсказка
Form string // форма адреса
Expr string // выражение-носитель
}
AddressFinding — один приёмник, получивший адрес.
func (AddressFinding) String ¶ added in v0.5.0
func (f AddressFinding) 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 AssertionVerifierCensus ¶ added in v0.5.0
type AssertionVerifierCensus struct {
// Files — прод-файлов Go разобрано.
Files int
// Declarations — функции дома, зовущие примитив сверки подписи.
Declarations []string
// Callers — функции вне дома, зовущие `webauthnverify.VerifyAssertion`.
Callers []string
}
AssertionVerifierCensus — объём осмотренного.
func JudgeAssertionVerifiers ¶ added in v0.5.0
func JudgeAssertionVerifiers(corpus TreeCorpus) ([]string, AssertionVerifierCensus, error)
JudgeAssertionVerifiers — находки и перепись по корпусу прод-файлов Go.
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
// Suites — коллекций сквозного набора прочитано.
Suites int
// SuiteSteps — шагов коллекций осмотрено. Ноль здесь означает, что разбор не
// дошёл до набора, и его вердикт недействителен.
SuiteSteps 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 AxisColumnSite ¶ added in v0.5.0
AxisColumnSite — столбец схемы, чей перечень значений — ровно ось уровня.
func ScanAssuranceAxisColumns ¶ added in v0.5.0
func ScanAssuranceAxisColumns(path, upSection string) []AxisColumnSite
ScanAssuranceAxisColumns — объявления оси уровня в накате миграции.
Осью считается перечень значений ровно {'1','2','3'}; перечень уже или шире — не ось. Таблица — ближайшее слева `CREATE TABLE` либо `ALTER TABLE`.
func (AxisColumnSite) String ¶ added in v0.5.0
func (s AxisColumnSite) String() string
type BareIssueRef ¶ added in v0.5.0
type BareIssueRef struct {
Path string // путь от корня модуля, через `/`
Line int // с единицы
Number int
Text string // строка целиком, без хвостовых пробелов
}
BareIssueRef — ссылка `#<N>` без префикса репозитория.
func BareIssueRefs ¶ added in v0.5.0
func BareIssueRefs(rel string, src []byte) []BareIssueRef
BareIssueRefs — все ссылки `#<N>` без префикса в src, с любым номером. Отсев по потолку делает вызывающий: перепись обязана знать и те, что ниже.
func (BareIssueRef) String ¶ added in v0.5.0
func (r BareIssueRef) String() string
type BindingInsertCensus ¶ added in v0.5.0
BindingInsertCensus — объём осмотренного.
func (*BindingInsertCensus) Add ¶ added in v0.5.0
func (c *BindingInsertCensus) Add(o BindingInsertCensus)
Add — сложение переписей по файлам.
type BindingInsertSite ¶ added in v0.5.0
type BindingInsertSite struct {
File string
Line int
// Func — имя объемлющей функции (для литерала — «литерал в <имя>»).
Func string
// WritesLedger — в той же функции есть вызов InsertEmittedTuples.
WritesLedger bool
}
BindingInsertSite — одна вставка привязки доступа с координатой.
func (BindingInsertSite) String ¶ added in v0.5.0
func (s BindingInsertSite) 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 CatalogCoverageCensus ¶ added in v0.5.0
type CatalogCoverageCensus struct {
// Methods — RPC контракта, осмотренных обходом.
Methods int
// Packages — своих proto-пакетов, выведенных из обхода.
Packages int
// Rows — строк в копии всего.
Rows int
// OwnRows — из них строк своих пакетов (только они и судятся).
OwnRows int
}
CatalogCoverageCensus — объём осмотренного. Печатается независимо от исхода.
func CompareCatalogWithContract ¶ added in v0.5.0
func CompareCatalogWithContract(rows []catalogderive.Entry, methods []ContractMethod) ([]string, CatalogCoverageCensus, error)
CompareCatalogWithContract — сверка копии с контрактом. Возвращает находки (пустой перечень = зелёное) и перепись. Ошибка — ТРЕТИЙ ИСХОД: сверять было нечего, вердикта о покрытии НЕТ.
func (CatalogCoverageCensus) String ¶ added in v0.5.0
func (c CatalogCoverageCensus) String() string
String — перепись одной строкой.
type CatalogFoundationRename ¶ added in v0.5.0
type CatalogFoundationRename struct {
// EdgeFQN — полное имя метода в копии края.
EdgeFQN string
// OwnFQN — полное имя того же метода в нашей копии.
OwnFQN string
// Why — почему расхождение не дефект.
Why string
// Removal — ПРЕДИКАТ СНЯТИЯ записи, внешний по отношению к этому дереву.
Removal string
// Refs — где предмет ведётся.
Refs string
}
CatalogFoundationRename — объявленное расхождение копий, произведённое переименованием контракта, чей владелец — ФУНДАМЕНТ, а не одно из двух деревьев. Пока деревья пинят разные версии фундамента, обе копии верны каждая для своей, и совпасть они не могут by construction.
func CatalogFoundationRenames ¶ added in v0.5.0
func CatalogFoundationRenames() []CatalogFoundationRename
CatalogFoundationRenames — объявленный перечень (копия, чтобы вызывающий не правил ведомость через возвращённый срез).
type CatalogParityCensus ¶ added in v0.5.0
type CatalogParityCensus struct {
// EdgeEntries, OwnEntries — записей у каждой стороны.
EdgeEntries int
OwnEntries int
// RenamesDeclared — записей в ведомости.
RenamesDeclared int
// RenamesApplied — сколько из них ДЕЙСТВИТЕЛЬНО применились к копии края.
RenamesApplied int
// PendingDeclared — записей, ждущих края, в ведомости.
PendingDeclared int
// PendingApplied — сколько из них ДЕЙСТВИТЕЛЬНО вынесены из сравнения:
// глагол есть у нас и его ещё нет у края.
PendingApplied int
// RetiredDeclared — записей о снятых службой глаголах в ведомости.
RetiredDeclared int
// RetiredApplied — сколько из них ДЕЙСТВИТЕЛЬНО вынесены из сравнения:
// глагол есть у края и его уже нет у нас.
RetiredApplied int
// RevisedDeclared — записей о смене значения поля в ведомости.
RevisedDeclared int
// RevisedApplied — сколько из них ДЕЙСТВИТЕЛЬНО применены к копии края:
// у края прежнее значение, у нас новое.
RevisedApplied int
// BytesEqual — совпали ли копии побайтово ДО применения ведомости.
BytesEqual bool
}
CatalogParityCensus — объём осмотренного. «Ноль находок» обязано быть отличимо от «ноль прочитанного», а «ноль расхождений» — от «распознаватель ослеп».
func (CatalogParityCensus) String ¶ added in v0.5.0
func (c CatalogParityCensus) String() string
String — перепись одной строкой, пригодной для журнала конвейера.
type CatalogParityFinding ¶ added in v0.5.0
CatalogParityFinding — одна находка: вид и текст.
type CatalogPendingEntry ¶ added in v0.5.0
type CatalogPendingEntry struct {
// OwnFQN — полное имя метода в нашей копии.
OwnFQN string
// Why — почему отсутствие у края не дефект.
Why string
// Removal — ПРЕДИКАТ СНЯТИЯ, внешний по отношению к этому дереву.
Removal string
// Refs — где предмет ведётся.
Refs string
}
CatalogPendingEntry — запись нашей копии, у которой в копии края ещё нет предмета, потому что край порождает её из нашего контракта по пину.
func CatalogPendingEntries ¶ added in v0.5.0
func CatalogPendingEntries() []CatalogPendingEntry
CatalogPendingEntries — объявленный перечень (копия, см. CatalogFoundationRenames).
type CatalogRetiredEntry ¶ added in v0.5.0
type CatalogRetiredEntry struct {
// EdgeFQN — полное имя снятого метода в копии края.
EdgeFQN string
// Why — почему присутствие у края не дефект.
Why string
// Removal — ПРЕДИКАТ СНЯТИЯ, внешний по отношению к этому дереву.
Removal string
// Refs — где предмет ведётся.
Refs string
}
CatalogRetiredEntry — запись копии края, чей глагол служба уже сняла, а край ещё называет, потому что порождает её из нашего контракта по пину.
func CatalogRetiredEntries ¶ added in v0.5.0
func CatalogRetiredEntries() []CatalogRetiredEntry
CatalogRetiredEntries — объявленный перечень (копия, см. CatalogFoundationRenames).
type CatalogRevisedEntry ¶ added in v0.5.0
type CatalogRevisedEntry struct {
// FQN — полное имя метода; у обеих копий одно.
FQN string
// Field — имя поля записи в форме генератора.
Field string
// EdgeValue — значение поля в копии края (прежнее).
EdgeValue string
// OwnValue — значение поля в нашей копии (новое, порождённое из контракта).
OwnValue string
// Why — почему расхождение не дефект.
Why string
// Removal — ПРЕДИКАТ СНЯТИЯ, внешний по отношению к этому дереву.
Removal string
// Refs — где предмет ведётся.
Refs string
}
CatalogRevisedEntry — объявленная смена значения одного поля записи, которую край ещё не породил.
func CatalogRevisedEntries ¶ added in v0.5.0
func CatalogRevisedEntries() []CatalogRevisedEntry
CatalogRevisedEntries — объявленный перечень (копия, см. CatalogFoundationRenames).
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 CeremonyCoordinate ¶ added in v0.5.0
type CeremonyCoordinate struct {
// Name — координата словом: её называет находка.
Name string
// Path — путь, который судится.
Path string
// Written — путь ВЫПИСАН литералом, потому что производителя в дереве нет.
// Граница истекает сама: появится постоянная с этим значением — находка.
Written bool
// Anchor — координата-якорь: её поверхность и есть поверхность выдачи.
Anchor bool
}
CeremonyCoordinate — одна координата, которую судит гейт.
type CeremonySurfaceCensus ¶ added in v0.5.0
type CeremonySurfaceCensus struct {
SolveRounds int
ResolveSteps int
Packages int
Files int
RootFiles int
SurfaceDecls int
RaisedSurfaces int
SurfaceBuilders int
HTTPMuxes int
GatewayMuxes int
HTTPRegistrations int
GatewayRegistrations int
DefaultRegistrations int
UnreachableRegistrations int
UntracedRegistrations int
PathForms map[string]int
Unresolved []string
Escapes []string
ManualRouting []string
URLPathReads int
PathCarriers int
Sinks int
UnmountedMuxes int
WithoutProducer int
PositiveControls int
// CoordinateEndpoints — конечных точек, до которых доходят координаты на
// своих поверхностях (по месту рождения значения).
CoordinateEndpoints int
// SurfaceEndpoints — конечных точек, до которых доходят поверхности по
// любому пути: с ними сверяется обработчик каждой координаты.
SurfaceEndpoints int
}
CeremonySurfaceCensus — объём осмотренного.
func (CeremonySurfaceCensus) Summary ¶ added in v0.5.0
func (c CeremonySurfaceCensus) Summary() string
Summary — перепись одной строкой.
type CeremonySurfaceReport ¶ added in v0.5.0
type CeremonySurfaceReport struct {
Census CeremonySurfaceCensus
Coordinates []CoordinateVerdict
Surfaces []SurfaceRoutes
Findings []string
}
CeremonySurfaceReport — исход гейта.
func JudgeCeremonySurfaces ¶ added in v0.5.0
func JudgeCeremonySurfaces(ctx context.Context, spec CeremonySurfaceSpec, coords []CeremonyCoordinate) (CeremonySurfaceReport, error)
JudgeCeremonySurfaces судит, на скольких поверхностях резолвится каждая координата. Ошибка — гейт НЕ ИСПОЛНИЛСЯ (радиус не собран, файл не разобрался, разбор не дошёл до неподвижной точки, обратный разбор путей исчерпал бюджет шагов): это не зелёное и не находка. ctx ограничивает сбор радиуса (`go list`) вместе с его сроком.
type CeremonySurfaceSpec ¶ added in v0.5.0
type CeremonySurfaceSpec struct {
// ModuleRoot — корень модуля службы.
ModuleRoot string
// RootPackage — путь импорта композиционного корня.
RootPackage string
// Overlay — путь импорта → каталог, чьи не-тестовые .go заменяют пакет
// (или заводят новый).
Overlay map[string]string
// Unresolved — ведомость листов пути, не сводимых к значению. Точная по
// листу И месту: лист на неназванном месте — находка, запись без листа на
// своём месте — находка.
Unresolved []UnresolvedPathEntry
}
CeremonySurfaceSpec — что судить.
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 ClaimNamingRetiredIssuer ¶ added in v0.5.0
ClaimNamingRetiredIssuer — ключ сборки состава, называющий прежнего поставщика.
func (ClaimNamingRetiredIssuer) String ¶ added in v0.5.0
func (f ClaimNamingRetiredIssuer) String() string
type ClaimNamingRetiredIssuerCensus ¶ added in v0.5.0
ClaimNamingRetiredIssuerCensus — объём осмотренного. Печатается всегда: «ноль находок» обязано быть отличимо от «ноль прочитанного».
func (ClaimNamingRetiredIssuerCensus) String ¶ added in v0.5.0
func (c ClaimNamingRetiredIssuerCensus) String() string
type CommentCoordinate ¶ added in v0.5.0
type CommentCoordinate struct {
File string
Line int
// Text — координата целиком, как она записана.
Text string
// Tail — остаток после приставки, как он записан (многоточие сохранено).
Tail string
// ClassForm — хвост несёт многоточие (`…` либо `...`) сегментом или
// окончанием: это форма записи КЛАССА путей, а не координата одного файла.
// Резолвить такой хвост нечего, и вызывающий его в находки не берёт.
ClassForm bool
}
CommentCoordinate — координата, названная комментарием.
type CommentCoordinateCensus ¶ added in v0.5.0
type CommentCoordinateCensus struct {
// Comments — групп комментария прочитано.
Comments int
// Mentions — упоминаний приставки в них.
Mentions int
// WithTail — из них с непустым хвостом.
WithTail int
// ClassForms — из них в форме класса путей (с многоточием). Печатается
// отдельно: молчание на такой форме обязано быть отличимо от слепоты к ней.
ClassForms int
}
CommentCoordinateCensus — объём осмотренного одним файлом.
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 ContractMethod ¶ added in v0.5.0
type ContractMethod struct {
FullMethod string
Package string
Annotations catalogderive.Annotations
}
ContractMethod — один RPC контракта: полное имя в форме каталога (`<пакет>.<Служба>/<Метод>`, без ведущей косой черты) и его аннотации.
func OwnContractMethods ¶ added in v0.5.0
func OwnContractMethods(pathPrefix string) (methods []ContractMethod, files int)
OwnContractMethods — RPC всех файлов контракта, зарегистрированных в этом двоичном файле под названной приставкой пути (`kaname/` — корень контрактов службы в её дереве `proto/`). Возвращает методы, отсортированные по имени, и число осмотренных файлов — отдельно, чтобы «ноль методов» было отличимо от «ноль файлов».
type CoordinateVerdict ¶ added in v0.5.0
type CoordinateVerdict struct {
Name string
Path string
Surfaces []SurfaceHit
Producers []string
// Endpoints — конечные точки, до которых координата доходит на своих
// поверхностях: место рождения значения обработчика.
Endpoints []string
}
CoordinateVerdict — исход по одной координате.
func (CoordinateVerdict) Summary ¶ added in v0.5.0
func (c CoordinateVerdict) Summary() string
Summary — исход координаты одной строкой.
type CriticalHeaderRuleCensus ¶ added in v0.5.0
type CriticalHeaderRuleCensus struct {
// Selectors — выражений выбора (`x.Y`) прочитано.
Selectors int
// PolicyImports — импортов дома правила прочитано, в любой форме.
PolicyImports int
}
CriticalHeaderRuleCensus — объём осмотренного одним файлом.
type CriticalHeaderRuleSite ¶ added in v0.5.0
type CriticalHeaderRuleSite struct {
File string
Line int
// Form — форма обращения: `plain` · `alias` · `dot`. Печатается переписью,
// чтобы «ноль находок» было отличимо от «форму не узнали».
Form string
}
CriticalHeaderRuleSite — координата обращения к правилу.
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 DeclaredFuncCensus ¶ added in v0.5.0
type DeclaredFuncCensus struct {
// Decls — объявлений функций прочитано.
Decls int
// Tests — из них объявлений проб (имя начинается с Test).
Tests int
}
DeclaredFuncCensus — объём осмотренного одним файлом.
func ScanDeclaredFuncNames ¶ added in v0.5.0
ScanDeclaredFuncNames возвращает имена функций, ОБЪЯВЛЕННЫХ в файле.
Объявление, а не упоминание: узел ast.FuncDecl, а не совпадение текста. Метод (функция с приёмником) объявлением пробы не является и в набор не идёт — иначе метод с именем вида TestX выдал бы себя за держателя.
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 DocHeaderCensus ¶ added in v0.5.0
type DocHeaderCensus struct {
// Decls — объявлений прочитано (всех форм перечня выше).
Decls int
// Documented — из них с группой комментария над ними.
Documented int
// Headers — из них формы «Имя <разделитель> текст».
Headers int
}
DocHeaderCensus — объём осмотренного одним файлом.
type DocHeaderSite ¶ added in v0.5.0
type DocHeaderSite struct {
File string
Line int
// Named — имя, которое шапка называет первым словом.
Named string
// Declared — имена, объявленные узлом, которому шапка досталась. Их больше
// одного только у `var a, b = …`.
Declared []string
// Form — форма объявления: `func` · `method` · `type` · `const` · `var`.
// Печатается переписью: «ноль находок» обязано быть отличимо от «форму не
// узнали».
Form string
}
DocHeaderSite — одна прочитанная шапка вместе с объявлением, которому она досталась.
func (DocHeaderSite) Matches ¶ added in v0.5.0
func (s DocHeaderSite) Matches() bool
Matches — называет ли шапка то объявление, над которым стоит.
type DoorRow ¶ added in v0.5.0
type DoorRow string
DoorRow — строка переписи формы двери решения.
const ( // DoorUnderPredicate — отвечает вердиктом либо держателями: зовёт // предикат допуска. DoorUnderPredicate DoorRow = "под предикатом" // DoorRecords — отвечает записями для разбора и текста отказа. DoorRecords DoorRow = "отвечает записями" // DoorLiveness — о живости формы. DoorLiveness DoorRow = "живость" )
type DrainForm ¶ added in v0.5.0
type DrainForm string
DrainForm — форма, которой объявлен дренаж очереди.
type DrainSite ¶ added in v0.5.0
type DrainSite struct {
// Table — очередь, схема и имя.
Table string
// Form — форма объявления дренажа.
Form DrainForm
// Where — координаты мест, объявивших дренаж.
Where []string
// OrderKey — ключ порядка выборки; пустой означает «порядка нет».
OrderKey string
// RosterNamed — обоснование в точке решения СОСЛАЛОСЬ на роспись ЭТОГО
// дерева.
RosterNamed bool
// ForeignRoster — координаты обоснований, назвавших роспись ЧУЖОГО
// репозитория (`<пакет>.commutativeDrainExempt`). Отдельно от RosterNamed,
// потому что это не «сослался», а «сослался в никуда»: роспись монорепо
// после выноса службы записей её очередей не несёт, и читатель в точке
// решения попадает туда, где про его очередь не написано ничего.
ForeignRoster []string
}
DrainSite — одна дренируемая очередь: чем движется и по какому ключу выбирается.
type EnvelopeEmbedding ¶ added in v0.5.0
EnvelopeEmbedding — структура, встроившая огибающую дома.
type EnvelopeMeterCarrier ¶ added in v0.5.0
type EnvelopeMeterCarrier struct {
Rel string
Line int
// Context — объявление, в котором стоит обращение; Shape — подпись меры,
// записанная без имени типа меры (пусто — обращение к типу по имени).
Context, Shape string
}
EnvelopeMeterCarrier — обращение к типу меры в доме помимо поля меры огибающей и довода меры конструктора.
type EnvelopeMeterWrite ¶ added in v0.5.0
type EnvelopeMeterWrite struct {
Rel string
Line int
// Param — переписан довод меры конструктора, а не поле меры.
Param bool
// Where — где запись и почему она не законная; Form и Expr — вид и
// выражение записи.
Where, Form, Expr string
}
EnvelopeMeterWrite — запись поля меры либо довода меры конструктора, кроме законной.
type EnvelopePortImpl ¶ added in v0.5.0
EnvelopePortImpl — метод порта огибающей на типе помимо огибающей дома.
type EnvelopeRootCensus ¶ added in v0.5.0
type EnvelopeRootCensus struct {
// TreeFiles — файлов в составе дерева; ProductionGo — не-тестовых `.go` по
// суффиксу; OutsideTraversal — из них вне области обхода; Examined — разобрано.
TreeFiles, ProductionGo, OutsideTraversal, Examined int
// ReferringHome — файлов дома и файлов, импортирующих дом.
ReferringHome int
// HomeImport — путь импорта дома, выведенный из go.mod корня дерева.
HomeImport string
// MeterParam, MeterParamName — позиция довода меры у конструктора, с
// единицы, и его имя.
MeterParam int
MeterParamName string
// ConstructorAt, WallClockAt — координаты объявлений в доме.
ConstructorAt, WallClockAt string
// MeterField, MeterFieldAt — поле меры огибающей, выведенное из её объявления.
MeterField, MeterFieldAt string
// Port, PortAt — порт полосы входа; PortMethods — его методов.
Port, PortAt string
PortMethods int
// LawfulMeterWrites — законные записи поля меры; PortMethodsAtHome — методы
// порта, узнанные у огибающей дома тем же распознавателем, что ищет
// подставной тип. Положительный контроль того же прогона.
LawfulMeterWrites []string
PortMethodsAtHome int
}
EnvelopeRootCensus — объём осмотренного и посылка, на которой стоит вердикт.
func (EnvelopeRootCensus) String ¶ added in v0.5.0
func (c EnvelopeRootCensus) String() string
type EnvelopeRootSpec ¶ added in v0.5.0
type EnvelopeRootSpec struct {
// HomeDir — каталог дома огибающей от корня модуля; RootDir — каталог
// композиционного корня службы.
HomeDir, RootDir string
// Constructor, EnvelopeType, MeterType, WallClock — конструктор, тип
// огибающей, тип меры и мера настенных часов, объявленные домом.
Constructor, EnvelopeType, MeterType, WallClock string
// PortDir, PortInterface — каталог и имя порта, которым полоса входа
// принимает огибающую; его методы выводятся из объявления.
PortDir, PortInterface string
}
EnvelopeRootSpec — объявление предмета стража: где дом огибающей, где корень композиции и какими именами дом объявляет узнаваемое.
func EnvelopeCompositionRootSpec ¶ added in v0.5.0
func EnvelopeCompositionRootSpec() EnvelopeRootSpec
EnvelopeCompositionRootSpec — предмет стража в этом дереве.
type EnvelopeRootVerdict ¶ added in v0.5.0
type EnvelopeRootVerdict struct {
Census EnvelopeRootCensus
Sites []EnvelopeSite
PortImpls []EnvelopePortImpl
Embeddings []EnvelopeEmbedding
MeterWrites []EnvelopeMeterWrite
MeterCarriers []EnvelopeMeterCarrier
Bypasses []EnvelopeTypeBypass
Findings []string
}
EnvelopeRootVerdict — исход стража: перепись, найденное и находки.
func JudgeEnvelopeCompositionRoot ¶ added in v0.5.0
func JudgeEnvelopeCompositionRoot(tree *treecorpus.Tree, spec EnvelopeRootSpec) (EnvelopeRootVerdict, error)
JudgeEnvelopeCompositionRoot — вердикт стража по дереву.
func (EnvelopeRootVerdict) Summary ¶ added in v0.5.0
func (v EnvelopeRootVerdict) Summary() string
Summary — перепись и найденное одной строкой вывода.
type EnvelopeSite ¶ added in v0.5.0
type EnvelopeSite struct {
Rel string
Line int
Form EnvelopeSiteForm
// Expr — выражение места; Meter — довод меры (только у вызова).
Expr, Meter string
// MeterFrom — путь импорта пакета, которым квалифицирован довод меры
// (пусто — довод не селектор импортированного пакета).
MeterFrom string
// WallClock — довод меры вызова есть мера настенных часов дома.
WallClock bool
}
EnvelopeSite — место построения огибающей с координатой.
func (EnvelopeSite) String ¶ added in v0.5.0
func (s EnvelopeSite) String() string
type EnvelopeSiteForm ¶ added in v0.5.0
type EnvelopeSiteForm string
EnvelopeSiteForm — форма места построения огибающей.
const ( // EnvelopeSiteCall — вызов конструктора: мера судится доводом. EnvelopeSiteCall EnvelopeSiteForm = "вызов конструктора" // EnvelopeSiteConstructorValue — конструктор взят значением: мера у места не видна. EnvelopeSiteConstructorValue EnvelopeSiteForm = "конструктор взят значением" // EnvelopeSiteDetour — значение типа огибающей мимо конструктора. Имя без // подстроки `pass`: на неё в имени константы срабатывает G101 гейта gosec. EnvelopeSiteDetour EnvelopeSiteForm = "значение огибающей мимо конструктора" )
type EnvelopeTypeBypass ¶ added in v0.5.0
type EnvelopeTypeBypass struct {
Rel string
Line int
// Directive — текст директивы связывания; пусто — импорт unsafe.
Directive string
}
EnvelopeTypeBypass — обход системы типов рядом с домом огибающей.
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 FactScanCensus ¶ added in v0.5.0
type FactScanCensus struct {
// Strings — строковых литералов прочитано.
Strings int
// Comments — узлов-комментариев прочитано.
Comments int
// TableInStrings — литералов, называющих таблицу.
TableInStrings int
// TableInComments — комментариев, называющих таблицу. Печатается переписью:
// ненулевое число доказывает, что разбор дошёл до мест, где о таблице
// говорят, и промолчал ПО СУЩЕСТВУ, а не по слепоте.
TableInComments int
}
FactScanCensus — объём осмотренного одним файлом.
type FactWriteSite ¶ added in v0.5.0
FactWriteSite — координата записи в таблицу прямого факта.
type FailureResetCensus ¶ added in v0.5.0
type FailureResetCensus struct {
Files int
FilesNamingPort int
Calls int
MethodValues int
Declarations int
Implementations int
}
FailureResetCensus — объём осмотренного.
func (*FailureResetCensus) Add ¶ added in v0.5.0
func (c *FailureResetCensus) Add(o FailureResetCensus)
Add — сложение переписей по файлам.
type FailureResetLedgerEntry ¶ added in v0.5.0
type FailureResetLedgerEntry struct {
// Resets — сколько прямых обращений к порту в этом файле законно.
Resets int
// Subject — почему полоса решает счёт не через дом.
Subject string
// Refs — предмет трекера в форме «владелец/репозиторий#номер»; обязателен,
// если Resets > 0.
Refs string
// Removal — предикат снятия записи, исполнимый командой.
Removal string
}
FailureResetLedgerEntry — запись ведомости: сколько ПРЯМЫХ обращений к порту у этой полосы законно, почему и когда запись снимается.
Число несущее. Ключ-файл без числа прощает файл ЦЕЛИКОМ: второй прямой вызов, внесённый в тот же файл, гейт не покраснит, а самоистечение сработает только на нуле. Послабление записывается ПО ФАКТУ, а не потолком.
Запись, прощающая хотя бы одно прямое обращение, — ПОСЛАБЛЕНИЕ: условие обнуления решается там мимо дома. Такая запись обязана называть предмет трекера (`Refs`); без него она неотличима от забытой. Предикат снятия (`Removal`) обязателен у всякой записи.
type FailureResetUse ¶ added in v0.5.0
type FailureResetUse struct {
File string
Line int
Kind FailureResetUseKind
// Func — функция, внутри которой стоит обращение; пусто вне функции.
Func string
}
FailureResetUse — одно обращение к порту с координатой.
func ScanSessionLevelWrites ¶ added in v0.5.0
func ScanSessionLevelWrites(path string, src []byte) (writes []FailureResetUse, homeCalls int, err error)
ScanSessionLevelWrites — вызовы, которыми файл пишет уровень сессии, и вызовы дома. Оба судятся по УЗЛУ вызова, а не по слову в тексте: имя дома стоит и в прозе, объясняющей его, и гейт по подстроке краснел бы на собственном объяснении.
func (FailureResetUse) String ¶ added in v0.5.0
func (u FailureResetUse) String() string
type FailureResetUseKind ¶ added in v0.5.0
type FailureResetUseKind string
FailureResetUseKind — род обращения к порту обнуления.
const ( // FailureResetCall — прямой вызов обнуления. FailureResetCall FailureResetUseKind = "вызов" // FailureResetMethodValue — метод, взятый значением: вызовут позже. FailureResetMethodValue FailureResetUseKind = "значение-метод" // FailureResetDeclaration — объявление метода в интерфейсе порта. FailureResetDeclaration FailureResetUseKind = "объявление порта" // FailureResetImplementation — реализация порта адаптером. FailureResetImplementation FailureResetUseKind = "реализация порта" // FailureResetLevelWrite — запись уровня сессии: выводит популяцию гейта. FailureResetLevelWrite FailureResetUseKind = "запись уровня сессии" )
type FailureResetVerdictCensus ¶ added in v0.5.0
type FailureResetVerdictCensus struct {
FailureResetCensus
// LevelWritingFiles — файлы прод-кода, пишущие уровень сессии.
LevelWritingFiles int
// LevelWritingCalls — вызовы записи уровня в них.
LevelWritingCalls int
// ThroughHome — из них зовут дом единственного писателя.
ThroughHome int
// InLedger — из них названы ведомостью.
InLedger int
// HomeCalls — обращения к порту в самом доме: премиса гейта.
HomeCalls int
}
FailureResetVerdictCensus — ДВЕ величины, а не одна: полосы, ПИШУЩИЕ уровень сессии, и то, как каждая решает счёт. Одно число (по порту) скрывало бы ровно тот случай, ради которого гейт заведён, — полосу, завершающую вход и не решающую счёт ВОВСЕ: она порт не зовёт, поэтому в перепись по порту не попадает и остаётся невидимой.
func JudgeFailureReset ¶ added in v0.5.0
func JudgeFailureReset( corpus TreeCorpus, home string, ledger map[string]FailureResetLedgerEntry, ) ([]string, FailureResetVerdictCensus, error)
JudgeFailureReset — ВЕРДИКТ гейта над корпусом: находки и обе переписи.
Корпус — ПАРАМЕТР, поэтому инъекция подаёт синтетическое дерево и проверяет весь путь вердикта: обход, ведомость, сравнение с координатой дома, обе переписи. Прежняя редакция судила дерево прямо в теле пробы, и на КРАСНОМ дереве эта сборка не исполнялась ни разу — инъекция судила один классификатор.
type FailureRowRemoval ¶ added in v0.5.0
type FailureRowRemoval struct {
File string
Line int
Kind FailureRowRemovalKind
// Func — функция, в теле которой стоит текст; пусто — объявление пакета.
Func string
// Method — функция объявлена методом: реализация порта и уборщик — методы.
Method bool
// What — начало текста для находки.
What string
}
FailureRowRemoval — один текст над строками счёта с координатой.
type FailureRowRemovalCensus ¶ added in v0.5.0
type FailureRowRemovalCensus struct {
// Files — прочитанные файлы.
Files int
// StringValues — свёрнутые строковые значения: литерал, склейка, имя
// константы — по одному на наибольшее свёрнутое выражение.
StringValues int
// NamingTable — из них называют таблицу счёта.
NamingTable int
// Removals — из них тексты с изменяющим словом.
Removals int
// ByKeyInPort — из них удаления по ключу в реализации порта.
ByKeyInPort int
// ByAgeInSweep — из них удаления по возрасту в уборщике.
ByAgeInSweep int
}
FailureRowRemovalCensus — объём осмотренного посылкой.
func JudgeFailureRowRemovals ¶ added in v0.5.0
func JudgeFailureRowRemovals(corpus TreeCorpus) ([]string, FailureRowRemovalCensus, error)
JudgeFailureRowRemovals — ВЕРДИКТ посылки над корпусом: находки и перепись. Положительные половины (удаление по ключу в порту, по возрасту в уборщике) перепись называет отдельно: их ноль — «не исполнялось», а не «годно».
type FailureRowRemovalKind ¶ added in v0.5.0
type FailureRowRemovalKind string
FailureRowRemovalKind — как текст обходится со строками счёта.
const ( // FailureRowsByKey — удаление по ключу: это и есть обнуление счёта. FailureRowsByKey FailureRowRemovalKind = "по ключу" // FailureRowsByAge — удаление по возрасту: уборка истёкших следов. FailureRowsByAge FailureRowRemovalKind = "по возрасту" // FailureRowsOther — текст с изменяющим словом, который посылка не знает. FailureRowsOther FailureRowRemovalKind = "неизвестным посылке способом" // FailureRowsUnclassified — текст называет таблицу без изменяющего слова, и // разбор не узнаёт в нём ни чтения, ни вставки, ни имени таблицы. FailureRowsUnclassified FailureRowRemovalKind = "в форме, которую посылка не классифицирует" )
type FamilyReasonWord ¶ added in v0.5.0
type FamilyReasonWord struct {
// Word — написание слова, как его объявляет перечень домена.
Word string
// Constants — имена констант домена с этим значением.
Constants []string
// ConstantRefs — сколько узлов-селекторов домена ссылаются на эти
// константы в осмотренных файлах.
ConstantRefs int
// Conjugated — сопрягается ли причина фундамента того же написания с этим
// словом.
Conjugated bool
}
FamilyReasonWord — одно слово словаря и перепись его писателей.
func (FamilyReasonWord) HasWriter ¶ added in v0.5.0
func (w FamilyReasonWord) HasWriter() bool
HasWriter — есть ли у слова писатель хотя бы по одной ветви.
type FamilyReasonWritersCensus ¶ added in v0.5.0
type FamilyReasonWritersCensus struct {
// FilesRead — сколько файлов подано на осмотр.
FilesRead int
// FilesParsed — сколько из них импортируют домен и разобраны по узлам.
FilesParsed int
// Words — слова в порядке перечня домена.
Words []FamilyReasonWord
}
FamilyReasonWritersCensus — перепись обхода. Объём осмотренного печатается, потому что «находок ноль» без него неотличимо от «не смотрели».
func FamilyReasonWriters ¶ added in v0.5.0
func FamilyReasonWriters(files map[string]string, domainImport string, constants map[string]string, vocabulary []string, conjugated func(word string) bool) (FamilyReasonWritersCensus, error)
FamilyReasonWriters переписывает писателей каждого слова перечня.
files — не-тестовые файлы вне домена (путь → текст); отбор делает вызывающий. domainImport — путь импорта пакета домена. constants — имя константы → значение (см. FamilyReasonConstants). vocabulary — перечень домена. conjugated — ветвь сопряжения по значению; nil означает, что ветви нет.
func (FamilyReasonWritersCensus) Orphans ¶ added in v0.5.0
func (c FamilyReasonWritersCensus) Orphans() []string
Orphans — слова без писателя, в порядке перечня.
func (FamilyReasonWritersCensus) String ¶ added in v0.5.0
func (c FamilyReasonWritersCensus) String() string
String — перепись одной строкой: объём и исход по каждому слову.
type FamilyVerdictCensus ¶ added in v0.5.0
type FamilyVerdictCensus struct {
FilesParsed int
LiteralsSeen int
CallsSeen int
// Readers — литералы, читающие таблицу выпусков.
Readers []FamilyVerdictSite
// Bypasses — вызовы порта чтения семейства вне правила.
Bypasses []FamilyVerdictSite
// RuleCallers — каталоги, чьи файлы зовут правило.
RuleCallers map[string]bool
// ClaimsRead — утверждения, которые правило читает: имя → первая координата.
ClaimsRead map[string]FamilyVerdictSite
// UnresolvedClaims — индексы состава в правиле, имени которых разбор не
// разрешил.
UnresolvedClaims []FamilyVerdictSite
// IssuancePorts — не-тестовые реализации порта выпуска.
IssuancePorts []FamilyVerdictSite
// WriterDecls — объявления писателя записи выпуска.
WriterDecls []FamilyVerdictSite
// WriterCalls — вызовы писателя записи выпуска.
WriterCalls []FamilyVerdictSite
}
FamilyVerdictCensus — перепись обхода. Объём осмотренного печатается: «находок ноль» без него неотличимо от «не смотрели».
func FamilyVerdict ¶ added in v0.5.0
func FamilyVerdict(files map[string]string) (FamilyVerdictCensus, error)
FamilyVerdict разбирает названные непроверочные файлы (путь относительно корня модуля → исходник) и переписывает читателей семейства.
type FamilyVerdictSite ¶ added in v0.5.0
FamilyVerdictSite — координата находки или узла переписи.
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 GuardFileCensus ¶ added in v0.5.0
type GuardFileCensus struct {
// Comments — узлов-комментариев прочитано.
Comments int
// Idents — узлов-идентификаторов прочитано.
Idents int
}
GuardFileCensus — объём осмотренного одним файлом.
type GuardFileScan ¶ added in v0.5.0
type GuardFileScan struct {
// Mentions — упоминания из комментариев.
Mentions []GuardMention
// Uses — имена, вызванные выражением прод-кода.
Uses map[string]bool
// Census — объём осмотренного.
Census GuardFileCensus
}
GuardFileScan — исход разбора одного файла.
func ScanGuardNaming ¶ added in v0.5.0
ScanGuardNaming разбирает один файл и возвращает упоминания защит в комментариях и их наличие в выражениях прод-кода.
isTest несущий: наличие засчитывается ТОЛЬКО из прод-кода, потому что вызов защиты внутри пробы не делает её действующей в прод-пути. Упоминание при этом читается и из пробы — комментарий пробы, называющий защиту действующей, вводит читателя в то же заблуждение.
type GuardMention ¶ added in v0.5.0
type GuardMention struct {
Name string
File string
Line int
Form GuardMentionForm
}
GuardMention — координата упоминания защиты в комментарии.
type GuardMentionForm ¶ added in v0.5.0
type GuardMentionForm string
GuardMentionForm — форма, в которой комментарий назвал защиту.
const ( GuardMentionBare GuardMentionForm = "bare" GuardMentionQualified GuardMentionForm = "qualified" GuardMentionCall GuardMentionForm = "call" GuardMentionBacktick GuardMentionForm = "backtick" )
Формы упоминания. Печатаются переписью, чтобы «ноль находок» было отличимо от «форму не узнали».
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 ImagePublishedCensus ¶ added in v0.5.0
type ImagePublishedCensus struct {
// Steps — шагов в задании образа; Build — номер шага сборки (с нуля).
Steps int
Build int
// Checks, SelfTests — шагов, зовущих сверку и её самопроверку.
Checks int
SelfTests int
// EnvCompared — величин, сверенных с шагом сборки (по всем шагам сверки).
EnvCompared int
}
ImagePublishedCensus — объём осмотренного: «ноль находок» обязано быть отличимо от «ноль прочитанного».
func AuditImagePublishedRevision ¶ added in v0.5.0
func AuditImagePublishedRevision(raw string) ([]string, ImagePublishedCensus, error)
AuditImagePublishedRevision — вердикт о провязке сверки опубликованного.
Вынесено ЧИСТОЙ функцией от текста объявления затем, чтобы способность гейта упасть доказывалась подачей входа, а не чтением. Ошибка — предпосылка ложна (вердикт беспредметен); находки — провязка нарушена.
func (ImagePublishedCensus) String ¶ added in v0.5.0
func (c ImagePublishedCensus) String() string
String — перепись одной строкой.
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 IssuanceLane ¶ added in v0.5.0
IssuanceLane — полоса выдачи удостоверения человеку и функция, в которой она спрашивает правило выдачи.
type IssueRefAllowance ¶ added in v0.5.0
IssueRefAllowance — номер в названном файле, где голая форма есть ВХОД, а не ссылка: фикстура разборщика, цитата чужого сообщения либо значение данных, уже записанное применённой миграцией. Префикс там исказил бы предмет.
func IssueRefAllowances ¶ added in v0.5.0
func IssueRefAllowances() []IssueRefAllowance
IssueRefAllowances — объявленные позволения; копия, проба её не двигает.
type IssueRefCensus ¶ added in v0.5.0
type IssueRefCensus struct {
Listed int // путей подано
Read int // текстовых файлов прочитано
Binary int // пропущено как двоичные
Bare int // голых ссылок в судимых файлах, любой номер
AboveCeiling int // из них выше потолка (до позволений)
Excluded map[string]int // голых ссылок выше потолка под каждым исключением
Allowed map[string]int // под каждым позволением, ключ — "путь#номер"
}
IssueRefCensus — объём осмотренного: «находок ноль» обязано быть отличимо от «ноль прочитанного».
func (IssueRefCensus) String ¶ added in v0.5.0
func (c IssueRefCensus) String() string
type IssueRefExclusion ¶ added in v0.5.0
type IssueRefExclusion struct {
Name string
Why string
Match func(rel string) bool
MatchLine func(line string) bool
}
IssueRefExclusion — область дерева, которую гейт НЕ судит, с причиной.
Исключение без находок под собой — тоже находка (гейт сверяет это сам): послабление, которому нечего прощать, не истечёт больше никогда.
MatchLine сужает исключение до строк файла: когда он задан, вне суждения только строки, на которых он истинен, а остальные строки того же файла судятся.
func IssueRefExclusions ¶ added in v0.5.0
func IssueRefExclusions() []IssueRefExclusion
IssueRefExclusions — объявленные исключения; копия, проба её не двигает.
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 KeyField ¶ added in v0.5.0
type KeyField struct {
Name string // имя поля; пустое у встроенного
Type string // текст типа, как он написан
Line int
}
KeyField — одно поле разбираемого типа.
type KeyProjection ¶ added in v0.5.0
type KeyProjection struct {
File string
Line int
Method string
StoredType string
PublishedType string
StoredPrivate []KeyField // почему приёмник опознан хранимой формой
PrivateInPublished []KeyField // НАХОДКА: приватное в публикуемой форме
SameType bool // НАХОДКА: публикуемая форма не отделена от хранимой
FieldsInspected int
}
KeyProjection — найденная пара форм ключа.
StoredType — та, что несёт приватную половину (положительный близнец); PublishedType — та, в которую она проецируется. PrivateInPublished непусто ровно тогда, когда публикуемая форма приватный материал всё-таки несёт, — это и есть находка.
type KeyTypeCensus ¶ added in v0.5.0
KeyTypeCensus — объём осмотренного одним файлом.
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 LevelUse ¶ added in v0.5.0
type LevelUse struct {
File string
Line int
Kind LevelUseKind
// Holder — имя структуры (для LevelUseStructField).
Holder string
// Text — что именно стояло в узле (для читателя находки).
Text string
}
LevelUse — одно обращение к оси уровня с координатой.
type LevelUseCensus ¶ added in v0.5.0
type LevelUseCensus struct {
Files int
ImportingHome int
AxisReferences int
Comparisons int
RuleCalls int
Productions int
Conversions int
StructFields int
}
LevelUseCensus — объём осмотренного.
func (*LevelUseCensus) Add ¶ added in v0.5.0
func (c *LevelUseCensus) Add(o LevelUseCensus)
Add — сложение переписей по файлам.
type LevelUseKind ¶ added in v0.5.0
type LevelUseKind string
LevelUseKind — род обращения к оси уровня.
const ( // LevelUseComparison — сравнение с константой оси либо перечень case: чтение. LevelUseComparison LevelUseKind = "сравнение" // LevelUseRuleCall — вызов правила: единственное законное производство. LevelUseRuleCall LevelUseKind = "вызов правила" // LevelUseProduction — константа оси, употреблённая как значение: второй писатель. LevelUseProduction LevelUseKind = "производство мимо правила" // LevelUseConversion — преобразование в тип оси мимо правила. LevelUseConversion LevelUseKind = "преобразование в уровень" // LevelUseStructField — поле типа оси в объявлении структуры: держатель состояния. LevelUseStructField LevelUseKind = "поле уровня в структуре" )
type LoginVerifierCensus ¶ added in v0.5.0
type LoginVerifierCensus struct {
FilesRead, FilesParsed int
AccessorDecls int
AccessorUses int
AllowedUses map[string]int
// TableNamings — упоминания таблицы по формам записи; OwnerTableNamings —
// из них у владельца.
TableNamings map[string]int
OwnerTableNamings int
// Bindings — связанные имена, несущие имя таблицы: «каталог.имя».
Bindings []string
// Material, Name — разбор потока материала и имени таблицы.
Material, Name LoginVerifierFlowCensus
// ConsumerUses — объявленный потребитель → вызовов с предметом.
ConsumerUses map[string]int
// ConsumersAbsorbing, ConsumersTransforming — объявлений по виду;
// CleanPositions — чистых позиций, объявленных преобразующим.
ConsumersAbsorbing, ConsumersTransforming, CleanPositions int
}
LoginVerifierCensus — объём осмотренного по каждой оси.
func AuditLoginVerifierContainment ¶ added in v0.5.0
func AuditLoginVerifierContainment(corpus TreeCorpus, spec LoginVerifierSpec) ([]string, LoginVerifierCensus, error)
AuditLoginVerifierContainment — находки и перепись по корпусу не-тестовых файлов. Корпус и объявление приходят ПАРАМЕТРАМИ: инъекция обязана подать разбору синтетику, а не это дерево.
func (LoginVerifierCensus) String ¶ added in v0.5.0
func (c LoginVerifierCensus) String() string
type LoginVerifierConsumer ¶ added in v0.5.0
type LoginVerifierConsumer struct {
Kind LoginVerifierConsumerKind
// Clean — позиции результата ПРЕОБРАЗУЮЩЕГО (с нуля), которые предмета не
// несут, → причина, сверенная с кодом вызова. У поглощающего пусто: у него
// чисты все позиции, и вторая запись того же утверждения разошлась бы с первой.
Clean map[int]string
// Reason — почему предмет отдан этому вызову по существу.
Reason string
}
LoginVerifierConsumer — объявление потребителя.
type LoginVerifierConsumerKind ¶ added in v0.5.0
type LoginVerifierConsumerKind int
LoginVerifierConsumerKind — что потребитель делает с полученным предметом. Нулевое значение — «вид не объявлен», и гейт на нём отказывает: молчаливое умолчание любого из двух видов было бы решением, которого никто не принимал.
const ( // ConsumerAbsorbing — ПОГЛОЩАЮЩИЙ: предмет уходит в него и не возвращается; // результат — признак исхода (оператор базы: строка исхода, число строк, // ошибка драйвера) либо величина односторонней функции. Ни одна позиция // результата предмета не несёт. ConsumerAbsorbing LoginVerifierConsumerKind // ConsumerTransforming — ПРЕОБРАЗУЮЩИЙ: результат собран ИЗ предмета // (строковая операция, декодирование, разборщик, чья ошибка несёт вход). // Каждая позиция результата несёт предмет, кроме объявленных чистыми, и // разбор ведёт её дальше так же, как выход `Reveal`. ConsumerTransforming )
func (LoginVerifierConsumerKind) String ¶ added in v0.5.0
func (k LoginVerifierConsumerKind) String() string
type LoginVerifierFlowCensus ¶ added in v0.5.0
type LoginVerifierFlowCensus struct {
Functions int // тел функций разобрано (с уровнем пакета)
Holders int // хранилищ, несущих предмет
// Calls — вызовы, получившие предмет, по исходу: в свой файл, в чужие файлы
// корпуса, объявленным потребителям, необъявленным непрозрачным.
InFile, ToCorpus, ToConsumer, Undeclared int
// Absorbed, Transformed — из ToConsumer: вызовы поглощающих и
// преобразующих; результат вторых прослежен дальше (kaname#139).
// «Потребителей N» и «результатов прослежено M» — разные утверждения.
Absorbed, Transformed int
// ReturnsInFile — возвратов предмета из помощника, которого зовёт только
// свой файл: результат прослежен у вызывающего, а не объявлен выносом.
ReturnsInFile int
// IntoType — вызовов конструктора типа материала с предметом (возврат в тип).
IntoType int
}
LoginVerifierFlowCensus — перепись разбора потока одного предмета.
func (LoginVerifierFlowCensus) String ¶ added in v0.5.0
func (c LoginVerifierFlowCensus) String() string
type LoginVerifierSpec ¶ added in v0.5.0
type LoginVerifierSpec struct {
// Accessor — имя единственного выхода материала.
Accessor string
// DeclRel — файл, где выход объявлен; DeclType — тип-получатель.
DeclRel, DeclType string
// Table — таблица секрета; TableOwnerRel — единственный файл, который её называет.
Table, TableOwnerRel string
// AllowedFiles — файл → причина, по которой материал ему нужен. Причина
// уезжает в перепись: разрешение без названной причины снимается следующим.
AllowedFiles map[string]string
// OpaqueConsumers — вызов, которому материал либо имя таблицы отданы по
// существу, → его вид и причина. Ключ — «функция → вызов», как его печатает
// находка: `Тип.Метод → r.pool.QueryRow`. Объявление без вызова — находка;
// объявление без вида — отказ прогона (kaname#139).
OpaqueConsumers map[string]LoginVerifierConsumer
}
LoginVerifierSpec — объявление предмета гейта.
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 MailKindInventory ¶ added in v0.5.0
type MailKindInventory struct {
// Kinds — виды письма живой схемы, отсортированы.
Kinds []string
// KindSite — файл миграции, чьё объявление словаря живое (последнее).
KindSite string
// Senders — вид → применители, принимающие его (по функции, без повторов).
Senders map[string][]MailSenderSite
// Appliers — функций формы применителя найдено (всего, не только почтовых).
Appliers int
MigrationsRead int
VocabularyDeclarations int
GoFilesRead int
ComparisonSites int
// UnresolvedComparisons — сравнения параметра вида с именем, чьё значение
// словарь констант не знает. Слепая зона названа числом, а не спрятана.
UnresolvedComparisons int
}
MailKindInventory — перепись обеих сторон и объём осмотренного.
func MailKindInventoryOf ¶ added in v0.5.0
func MailKindInventoryOf(migrations, corpus TreeCorpus) (MailKindInventory, error)
MailKindInventoryOf — перепись по двум корпусам: миграции и прод-файлы Go.
ТРИ ИСХОДА: перепись собрана; читать не удалось (ошибка с координатой); прочитано ноль по любой из сторон — ErrEmptyTraversal, и это не «находок нет».
func (MailKindInventory) Findings ¶ added in v0.5.0
func (inv MailKindInventory) Findings() []string
Findings — расхождения двух сторон, по три оси, детерминированно.
func (MailKindInventory) KindsWithSender ¶ added in v0.5.0
func (inv MailKindInventory) KindsWithSender() int
KindsWithSender — вторая величина переписи: сколько видов схемы приняты хотя бы одним применителем.
type MailKindSite ¶ added in v0.5.0
MailKindSite — координата объявления вида письма.
type MailSendCensus ¶ added in v0.5.0
type MailSendCensus struct {
// Tracked — отслеживаемых файлов дерева всего.
Tracked int
// Read — не-тестовых файлов Go прочитано.
Read int
// Imports — импортов осмотрено.
Imports int
// Literals — строковых литералов осмотрено.
Literals int
// TransportAnchorHits — вхождений якорного пакета. Ноль означает, что
// предпосылка оси 1 не выполняется.
TransportAnchorHits int
// Paths — путей отправки найдено (первая несущая величина).
Paths int
// Kinds — виды письма, которые эти пути отправляют (вторая несущая).
Kinds []string
}
MailSendCensus — объём осмотренного. Две несущие величины MAIL-47 — `Paths` и `Kinds`; остальные доказывают, что обход непуст.
func (MailSendCensus) String ¶ added in v0.5.0
func (c MailSendCensus) String() string
String — перепись одной строкой, в форме, которую требует MAIL-47.
type MailSendFinding ¶ added in v0.5.0
type MailSendFinding struct {
// Where — координата `файл:строка`; пусто у находки об ОТСУТСТВИИ пути.
Where string
// Axis — `transport` либо `vocabulary`.
Axis string
// What — что именно найдено.
What string
// Why — почему это дефект, дословно для текста находки.
Why string
}
MailSendFinding — находка одной из двух осей.
func AdjudicateMailSendPaths ¶ added in v0.5.0
func AdjudicateMailSendPaths(paths []MailSendPath, kinds []MailKindSite) []MailSendFinding
AdjudicateMailSendPaths — ВЕРДИКТ по обеим осям. Отделён от обхода намеренно: инъекция подаёт ему синтетику напрямую и не поднимает дерева.
type MailSendPath ¶ added in v0.5.0
type MailSendPath struct {
// File — путь от корня модуля, через косую черту.
File string
// Line — строка импорта транспорта.
Line int
// Import — сам импорт, дословно.
Import string
// Kinds — виды письма, названные литералами ЭТОГО файла.
Kinds []string
// FormUnknown — импорт говорит о почте, а транспорт ли это, разбор не
// знает: это НЕ путь (в перепись путей не входит, вида не несёт), а отказ
// формы, и вердикт называет его находкой с координатой.
FormUnknown bool
}
MailSendPath — координата пути отправки.
type MailSenderCensus ¶ added in v0.5.0
MailSenderCensus — объём осмотренного на стороне Go.
func MailSendersOf ¶ added in v0.5.0
func MailSendersOf(corpus TreeCorpus) (map[string][]MailSenderSite, MailSenderCensus, error)
MailSendersOf — применители, принимающие виды письма, по прод-корпусу Go.
Применитель опознаётся ФОРМОЙ подписи (`drainer.Applier`), а не именем: имя — соглашение, форма — то, что дренаж исполняет. Сравнение параметра вида с константой либо литералом, значение которого лежит в пространстве `mail.`, делает функцию отправителем этого вида.
type MailSenderSite ¶ added in v0.5.0
MailSenderSite — ОДИН применитель, принимающий вид: файл, строка и имя функции. Строка указывает на место сравнения, имя — на функцию, которая и есть отправитель.
type MailWriterCensus ¶ added in v0.5.0
type MailWriterCensus struct {
FilesParsed int
// Writers — функции, ставящие письмо в очередь (`invite_mail_outbox.Emit*Tx`).
Writers []string
// ChargedHere — списывают окно сами, раньше постановки.
ChargedHere int
// ChargedByCaller — поставлены вызывающим, списавшим предел раньше.
ChargedByCaller int
}
MailWriterCensus — перепись писателей очереди писем.
func MailWriterFindings ¶ added in v0.5.0
func MailWriterFindings(files map[string]string) (MailWriterCensus, []string, error)
MailWriterFindings — каждый писатель очереди наших писем списывает окно раньше постановки: сам (`chargeInviteMailWindowTx`) либо каждый его вызывающий (`mailPacedByCaller`). Пустая перепись — находка.
type MembershipRemovalCensus ¶ added in v0.5.0
type MembershipRemovalCensus struct {
// Read — не-тестовых файлов Go прочитано.
Read int
// Funcs — функций осмотрено.
Funcs int
// Literals — строковых литералов осмотрено.
Literals int
// Removing — функций, снимающих строку участия.
Removing int
// Devaluing — из них обесценивающих невыкупленное приглашение.
Devaluing int
}
MembershipRemovalCensus — объём осмотренного.
func (MembershipRemovalCensus) String ¶ added in v0.5.0
func (c MembershipRemovalCensus) String() string
String — перепись одной строкой. Величин ДВЕ по существу — «снимающих найдено · из них обесценивающих», — и одна не заменяет другую: без первой «ноль находок» неотличимо от «ноль прочитанного».
type MembershipRemovalSite ¶ added in v0.5.0
type MembershipRemovalSite struct {
// File — путь от корня модуля, через косую черту.
File string
// Line — строка объявления функции.
Line int
// Func — имя функции.
Func string
// Devalues — обесценивает ли она невыкупленное приглашение.
Devalues bool
}
MembershipRemovalSite — координата функции, снимающей участие.
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 MigrationSectionSplitCensus ¶ added in v0.5.0
type MigrationSectionSplitCensus struct {
FilesRead int // не-тестовых файлов Go прочитано
FilesParsed int // из них разобрано
Literals int // строковых литералов с директивой секции встречено
OwnerLiterals int // из них в файле-владельце разбора
}
MigrationSectionSplitCensus — объём осмотренного.
Две величины на каждой оси, потому что «ноль находок» обязано быть отличимо от «ноль прочитанного»: пустой обход и чистое дерево печатают один и тот же ноль находок, а означают противоположное.
func AuditMigrationSectionSplit ¶ added in v0.5.0
func AuditMigrationSectionSplit(corpus TreeCorpus) ([]string, MigrationSectionSplitCensus, error)
AuditMigrationSectionSplit — находки и перепись по корпусу не-тестовых файлов.
Корпус приходит ПАРАМЕТРОМ: инъекция обязана подать разбору синтетическое дерево, а не это.
type MigrationVersion ¶ added in v0.5.0
type MigrationVersion struct {
// Value — числовое значение номера. Порядок применения — числовой,
// мигратор берёт его так же.
Value int64
// Width — сколько знаков занимает номер. Несущее различие: 14 — метка
// времени заведения, меньше — унаследованный номер прежней эры.
Width int
}
MigrationVersion — номер миграции и ширина его записи.
func MigrationVersionOf ¶ added in v0.5.0
func MigrationVersionOf(name string) (MigrationVersion, bool)
MigrationVersionOf — номер из имени файла.
Второй результат — «имя упорядочиваемо». Файл, у которого номера нет, не «нулевой версии»: о его месте в цепочке не известно НИЧЕГО, и подставить сюда ноль значило бы выдать незнание за знание.
type MigrationVersionAudit ¶ added in v0.5.0
type MigrationVersionAudit struct {
Outcome MigrationVersionOutcome
Census MigrationVersionCensus
Findings []string
}
MigrationVersionAudit — вердикт вместе с исходом и знаменателем.
Находки отдельно от исхода намеренно: «находок ноль» без исхода неотличимо от «обход ничего не принёс», и читатель прогона не обязан догадываться.
func AuditMigrationVersions ¶ added in v0.5.0
func AuditMigrationVersions(dirFiles, added []string) MigrationVersionAudit
AuditMigrationVersions — предмет гейта, взятый ЧИСТОЙ функцией.
`dirFiles` — ВСЕ пути каталога миграций (знаменатель обхода), `added` — пути, добавленные относительно ствола. Применённым считается всё, что в каталоге есть и добавленным не является: сравнивать новое с самим собой нечего.
Чистой она вынесена, чтобы инъекция судила ТОТ ЖЕ предикат на синтетическом входе, не трогая живое дерево и не заводя своей копии правила.
type MigrationVersionCensus ¶ added in v0.5.0
type MigrationVersionCensus struct {
// DirFiles — файлов каталога рассмотрено ВСЕГО (знаменатель).
DirFiles int
// SQL — из них признано миграциями.
SQL int
// Versioned — из миграций те, чьё имя упорядочиваемо.
Versioned int
// Widths — ПЕРЕПИСЬ ФОРМ, выведенная обходом: ширина номера → сколько
// файлов. Перечень форм в коде не выписан: он читается отсюда.
Widths map[int]int
// Unordered — миграции, номер которых не разобран. Не молчание и не
// находка сама по себе: их место в цепочке неизвестно.
Unordered []string
// Applied — миграции, уже лежащие в стволе (всё, кроме добавленного).
Applied int
// Added — миграции, добавленные относительно ствола.
Added int
// Compared — из добавленного то, что БЫЛО сопоставлено со старшей
// применённой. Отличается от Added ровно на случай «сравнивать не с чем».
Compared int
// HighestApplied, HighestValue — старшая применённая каталога.
HighestApplied string
HighestValue int64
}
MigrationVersionCensus — ЗНАМЕНАТЕЛЬ ОБХОДА и его состав.
Величин несколько, и это обязательно: одно число «добавлено N» скрывает ровно тот случай, ради которого гейт заведён, — добавленное есть, а сравнивать его не с чем.
func (MigrationVersionCensus) Forms ¶ added in v0.5.0
func (c MigrationVersionCensus) Forms() []string
Forms — перечень форм, ВЫВЕДЕННЫЙ обходом, в устойчивом порядке.
func (MigrationVersionCensus) String ¶ added in v0.5.0
func (c MigrationVersionCensus) String() string
String — перепись одной строкой.
type MigrationVersionOutcome ¶ added in v0.5.0
type MigrationVersionOutcome string
MigrationVersionOutcome — ЧТО СЛУЧИЛОСЬ с обходом. Печатается всегда.
const ( // MigrationVersionNoCorpus — обход не дал НИ ОДНОЙ миграции. Это не // «нарушений нет»: судить было нечего. MigrationVersionNoCorpus MigrationVersionOutcome = "НЕТ ПРЕДМЕТА: обход не дал ни одного файла миграции" // MigrationVersionNothingAdded — миграции есть, добавленных относительно // ствола нет. Класс говорит о НОВОЙ миграции, и новой здесь не появилось. MigrationVersionNothingAdded MigrationVersionOutcome = "НЕТ ПРЕДМЕТА: относительно ствола не добавлено ни одной миграции" // MigrationVersionNoPeer — добавленное есть, а сравнивать его не с чем: // применённых миграций в каталоге нет. Законное состояние нового домена — и // ровно тот случай, ради которого одно число «добавлено N» не годится. MigrationVersionNoPeer MigrationVersionOutcome = "" /* 156-byte string literal not displayed */ // MigrationVersionJudged — вердикт вынесен: хотя бы одно добавленное имя // сопоставлено с каноном формы или со старшей применённой. MigrationVersionJudged MigrationVersionOutcome = "ВЕРДИКТ ВЫНЕСЕН" )
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 OAuthFamilyCensus ¶ added in v0.5.0
type OAuthFamilyCensus struct {
FilesParsed int
LiteralsSeen int
Writers []OAuthFamilyWriter
GuardedCount int
BareCount int
}
OAuthFamilyCensus — перепись обхода. Объём осмотренного печатается, потому что «находок ноль» без него неотличимо от «не смотрели».
func OAuthFamilyWriters ¶ added in v0.5.0
func OAuthFamilyWriters(files map[string]string) (OAuthFamilyCensus, error)
OAuthFamilyWriters разбирает названные файлы и переписывает писателей.
Файлы подаются вызывающим уже отфильтрованными от проверочных: проба — законный писатель этой таблицы, и судить её этим гейтом значило бы запретить пробам строить сцену.
type OAuthFamilyWriter ¶ added in v0.5.0
type OAuthFamilyWriter struct {
Kind OAuthFamilyWriterKind
File string
Line int
}
OAuthFamilyWriter — найденный писатель с координатой.
type OAuthFamilyWriterKind ¶ added in v0.5.0
type OAuthFamilyWriterKind string
OAuthFamilyWriterKind — род найденного писателя.
Слова `Token` в именах рода нет намеренно: правило G101 сканера gosec судит константу по ИМЕНИ, и род писателя читался бы как зашитые учётные данные. Семейство — строка `kaname.token_families` церемонии OAuth, та же, чью причину отзыва несёт `domain.FamilyRevocationReason`.
const ( // OAuthFamilyWriterGuarded — вставка несёт условие живости сессии. OAuthFamilyWriterGuarded OAuthFamilyWriterKind = "охраняемый" // OAuthFamilyWriterBare — вставка без условия живости: второй писатель. OAuthFamilyWriterBare OAuthFamilyWriterKind = "без условия живости" )
type PairedWriteCensus ¶ added in v0.5.0
type PairedWriteCensus struct {
Funcs int
DoFirst int
DoSecond int
// Ambiguous — имён, объявленных в пакете не единожды: склейку они не дают.
Ambiguous int
// DeadCalls — вызовов, отброшенных как стоящие в мёртвой ветви.
DeadCalls int
}
PairedWriteCensus — объём осмотренного.
type PairedWriteFunc ¶ added in v0.5.0
type PairedWriteFunc struct {
File string
Line int
Pkg string
Name string
// First, Second — делает ли ПРЯМО (своим оператором).
First, Second bool
// Calls — однозначно разрешимые имена, вызванные из ДОСТИЖИМОГО кода.
Calls []string
}
PairedWriteFunc — функция и то, какие из двух действий она делает.
func PairedWriteFindings ¶ added in v0.5.0
func PairedWriteFindings(funcs []PairedWriteFunc) []PairedWriteFunc
PairedWriteFindings — функции, делающие ПЕРВОЕ и не делающие второго.
func ResolvePairedWrites ¶ added in v0.5.0
func ResolvePairedWrites(funcs []PairedWriteFunc, census *PairedWriteCensus) []PairedWriteFunc
ResolvePairedWrites достраивает второе действие ЧЕРЕЗ ВЫЗОВ — узко.
Склейка идёт только по имени, объявленному в ТОМ ЖЕ пакете РОВНО ОДИН раз. Имя, объявленное не единожды, отбрасывается и считается переписью: молчание о неразличимости — та же слепота, что и молчание о находке.
type PasswordHashRecordView ¶ added in v0.5.0
type PasswordHashRecordView struct {
Format string
Writable bool
// Params — параметры стоимости формата, в объявленном порядке.
Params []string
// Ceiling, Floor — потолок и пол по параметрам.
Ceiling, Floor map[string]uint32
// Range — область допустимости: параметр → [нижняя, верхняя] включительно.
Range map[string][2]uint32
}
PasswordHashRecordView — запись перечня в том виде, в каком её судит гейт.
type PasswordHashRegistryCensus ¶ added in v0.5.0
type PasswordHashRegistryCensus struct {
FilesRead int
Records int
Writable int
Branches int
PairsChecked int
SettingLookups int
}
PasswordHashRegistryCensus — перепись гейта. Печатается ВСЕГДА: «ноль расхождений» обязано быть отличимо от «ничего не прочитано».
func AuditPasswordHashFormatRegistry ¶ added in v0.5.0
func AuditPasswordHashFormatRegistry(corpus TreeCorpus, records []PasswordHashRecordView, spec PasswordHashRegistrySpec) ( []string, PasswordHashRegistryCensus, error, )
AuditPasswordHashFormatRegistry — сверка перечня с деревом.
func (PasswordHashRegistryCensus) String ¶ added in v0.5.0
func (c PasswordHashRegistryCensus) String() string
type PasswordHashRegistrySpec ¶ added in v0.5.0
type PasswordHashRegistrySpec struct {
// RegistryRel — файл, где объявлен перечень.
RegistryRel string
// VerifierRel — файл проверяющего: тот, где стоит классификатор.
VerifierRel string
// SelectorFunc — имя функции выбора проверяющего.
SelectorFunc string
// SettingType — имя типа настройки «что писать»: его не должно быть ни в
// функции выбора, ни в функциях её ветвей.
SettingType string
// RecordType — имя типа записи перечня: по его составному литералу ищется
// второе объявление перечня.
RecordType string
// FloorReference — эталон пола: формат → параметр → величина. Норма, на
// которой он стоит, названа в пробе.
FloorReference map[string]map[string]uint32
}
PasswordHashRegistrySpec — объявление предмета. Живёт в файле пробы.
type PasswordRuleCensus ¶ added in v0.5.0
type PasswordRuleCensus struct {
Files int
Declarations []PasswordRuleSite
Callers []PasswordRuleSite
}
PasswordRuleCensus — объём осмотренного и найденное.
func ScanPasswordRule ¶ added in v0.5.0
func ScanPasswordRule(rel string, src []byte) (PasswordRuleCensus, error)
ScanPasswordRule — объявления и вызовы правила пароля в одном файле.
func (*PasswordRuleCensus) Add ¶ added in v0.5.0
func (c *PasswordRuleCensus) Add(o PasswordRuleCensus)
Add — сложение переписей.
func (PasswordRuleCensus) Foreign ¶ added in v0.5.0
func (c PasswordRuleCensus) Foreign(homeRel string) []PasswordRuleSite
Foreign — объявления вне дома правила: находки.
func (PasswordRuleCensus) HomeFiles ¶ added in v0.5.0
func (c PasswordRuleCensus) HomeFiles() []string
HomeFiles — сколько разных файлов несут объявления: «одно объявление» значит ровно один файл, и он — дом.
type PasswordRuleForm ¶ added in v0.5.0
type PasswordRuleForm string
PasswordRuleForm — форма, в которой найдено объявление.
const ( // PasswordRuleFormName — конструктор либо тип по имени. PasswordRuleFormName PasswordRuleForm = "объявление по имени" // PasswordRuleFormVerb — метод `Judge` над паролем. PasswordRuleFormVerb PasswordRuleForm = "метод Judge над паролем" // PasswordRuleFormLength — сравнение длины пароля в рунах. PasswordRuleFormLength PasswordRuleForm = "сравнение длины пароля в рунах" )
#nosec G101 -- ИМЕНА ФОРМ ОБЪЯВЛЕНИЯ для текста находки гейта: слово «пароль» здесь — предмет проверки, а не значение удостоверения.
type PasswordRuleSite ¶ added in v0.5.0
type PasswordRuleSite struct {
Rel string
Line int
Form PasswordRuleForm
What string
}
PasswordRuleSite — найденное объявление либо вызов.
func (PasswordRuleSite) String ¶ added in v0.5.0
func (s PasswordRuleSite) String() string
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 PeopleAddressCensus ¶ added in v0.5.0
type PeopleAddressCensus struct {
// Go и Migrations — исходники Go и миграции службы.
Go, Migrations PeopleAddressHalf
// Writers — координаты записи адреса (в миграции — и отметки) мимо глагола.
Writers []string
// Undecided — координаты операторов, которые разбор не решает.
Undecided []string
// Applied — места применённых миграций, названные ведомостью: разобраны на
// этом прогоне, находкой не являются.
Applied []string
// LedgerEntries — записей ведомости; LedgerStale — из них без предмета
// (находка); LedgerOutOfCorpus — о файлах, которых в корпусе нет.
LedgerEntries, LedgerStale, LedgerOutOfCorpus int
// Lawful — законные писатели адреса в непроверочном Go, названные перечнем
// (`peopleLawfulGoWriters`): разобраны на этом прогоне, находкой не являются.
Lawful []string
// LawfulEntries — записей перечня; LawfulStale — из них без предмета
// (находка); LawfulOutOfCorpus — о файлах, которых в корпусе нет.
LawfulEntries, LawfulStale, LawfulOutOfCorpus int
}
PeopleAddressCensus — объём осмотренного по обоим видам входа.
func JudgePeopleAddressWriters ¶ added in v0.5.0
func JudgePeopleAddressWriters(corpus TreeCorpus) ([]string, PeopleAddressCensus, error)
JudgePeopleAddressWriters — ВЕРДИКТ над корпусом непроверочного Go и миграций службы: находки (места записи адреса, в миграции — и отметки; формы, которые разбор не решает; записи ведомости применённых миграций без предмета; пустой обход любого из двух видов входа) и перепись. Корпус приходит параметром: инъекция подаёт синтетику в тот же вердикт, что судит дерево. Файл вне обоих видов входа — ошибка, а не молчание.
func JudgePeopleAddressWritersWith ¶ added in v0.5.0
func JudgePeopleAddressWritersWith(corpus TreeCorpus, lawful []PeopleLawfulGoWriter) ([]string, PeopleAddressCensus, error)
JudgePeopleAddressWritersWith — тот же вердикт с перечнем законных писателей Go, поданным параметром: инъекция судит дерево без записи перечня и с ней.
func (PeopleAddressCensus) String ¶ added in v0.5.0
func (c PeopleAddressCensus) String() string
String — строка переписи для вывода проб.
type PeopleAddressHalf ¶ added in v0.5.0
type PeopleAddressHalf struct {
// Files — разобранные файлы.
Files int
// Texts — судимые тексты: у Go — свёрнутые строковые значения (по одному на
// наибольшее свёрнутое выражение), у миграций — файлы.
Texts int
// Statements — операторы записи в строки людей по виду.
Statements map[string]int
// SetLists — прочитанные списки SET над строками людей по ветви.
SetLists map[string]int
// SetListsClosed — из них закрытые в своём тексте (WHERE, FROM, RETURNING,
// `;`, скобка): продолжение во время исполнения колонки в них не допишет.
SetListsClosed int
// AssignmentPieces — звенья: тексты, начатые списком присваиваний без
// оператора и без SET.
AssignmentPieces int
// Columns — колонки строк людей, которые пишут прочитанные списки SET.
Columns map[string]int
// TableAlters — операторы ALTER TABLE над строками людей.
TableAlters int
// Routines — прочитанные тела подпрограмм (`CREATE FUNCTION … AS строка`).
Routines int
// Triggers — прочитанные объявления триггеров; TriggersOverPeople — из них
// над строками людей.
Triggers, TriggersOverPeople int
// RowAssignments — присваивания строке триггера (NEW, OLD, их псевдонимы и
// то же под меткой блока) в телах подпрограмм на PL/pgSQL, любой колонки, во
// всех целях присваивания его грамматики: начало оператора, INTO, GET
// DIAGNOSTICS, FOR, FOREACH, аргумент CALL.
RowAssignments int
// TriggerReturns — операторы RETURN в телах подпрограмм триггера на
// PL/pgSQL: база пишет ту строку, которую подпрограмма вернула.
TriggerReturns int
}
PeopleAddressHalf — объём осмотренного одного вида входа.
func (PeopleAddressHalf) StatementsTotal ¶ added in v0.5.0
func (h PeopleAddressHalf) StatementsTotal() int
StatementsTotal — всего операторов записи в строки людей.
func (PeopleAddressHalf) String ¶ added in v0.5.0
func (h PeopleAddressHalf) String() string
String — перепись вида входа словами.
type PeopleAppliedSite ¶ added in v0.5.0
type PeopleAppliedSite struct {
// Rel и Line — файл миграции и строка места.
Rel string
Line int
// Column — колонка писателя; пусто — место формы «не решается».
Column string
// Why — почему место законно и почему правке не подлежит.
Why string
}
PeopleAppliedSite — место предмета в ПРИМЕНЁННОЙ миграции, названное ведомостью: точная координата и довод.
type PeopleLawfulGoWriter ¶ added in v0.5.0
type PeopleLawfulGoWriter struct {
// Rel — файл; Func — функция, как её называет координата находки
// (`тип.метод` либо `функция`).
Rel, Func string
// Why — почему писатель законен: приёмка и чем выполнены условия гейта.
Why string
}
PeopleLawfulGoWriter — законный писатель адреса в непроверочном Go.
func PeopleLawfulGoWriters ¶ added in v0.5.0
func PeopleLawfulGoWriters() []PeopleLawfulGoWriter
PeopleLawfulGoWriters — перечень копией.
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 ProbeToolingCensus ¶ added in v0.5.0
type ProbeToolingCensus struct {
// FilesParsed — разобрано не-тестовых файлов Go.
FilesParsed int
// ProbeToolingFiles — из них оснастки проб; ShippedFiles — прод-сборки.
ProbeToolingFiles, ShippedFiles int
// Findings — импорт оснастки из прод-сборки с координатой; отсутствие
// оснастки в обходе.
Findings []string
}
ProbeToolingCensus — перепись проверки и её находки.
func ProbeToolingImports ¶ added in v0.5.0
func ProbeToolingImports(corpus TreeCorpus, module string) (ProbeToolingCensus, error)
ProbeToolingImports судит корпус не-тестовых файлов Go модуля с путём module: ни один файл прод-сборки не импортирует пакет оснастки проб.
type ProtoCommentCensus ¶ added in v0.5.0
type ProtoCommentCensus struct {
// Lines — строк прочитано.
Lines int
// Comments — из них строк комментария.
Comments int
// Refs — из них ссылок формы `Message.field`.
Refs int
// Decls — объявлений message/enum прочитано.
Decls int
}
ProtoCommentCensus — объём осмотренного одним файлом.
type ProtoCommentRef ¶ added in v0.5.0
type ProtoCommentRef struct {
File string
Line int
// Type — сообщение, которое ссылка называет.
Type string
// Text — токен целиком, как он записан.
Text string
}
ProtoCommentRef — координата ссылки, названной комментарием контракта.
type ProtoField ¶ added in v0.5.0
type ProtoField struct {
// Name — имя поля в контракте (`account_id`).
Name string
// Getter — имя геттера, которое по этому имени порождает генератор
// (`GetAccountId`). Вычисляется, а не угадывается; сходимость с
// генератором проверяет предпосылка гейта.
Getter string
// Line — строка объявления в файле контракта.
Line int
// Deprecated — поле помечено `[deprecated = true]`.
//
// Пометка И ЕСТЬ объявление «не применяется»: генератор проносит её в
// клиентские стабы, поэтому вызывающий предупреждён — а именно
// непредупреждённость и есть предмет запрета. Такое поле выводится из
// популяции и печатается переписью отдельно; снимут пометку — гейт
// начнёт судить его снова, то есть послабление истекает само.
Deprecated bool
}
ProtoField — поле сообщения контракта.
type ProtoMessage ¶ added in v0.5.0
type ProtoMessage struct {
Name string
File string
Fields []ProtoField
}
ProtoMessage — сообщение контракта и его поля верхнего уровня.
type ProtoSurface ¶ added in v0.5.0
type ProtoSurface struct {
Requests []RequestUse
Messages []ProtoMessage
}
ProtoSurface — то, что разбор вынул из одного файла контракта.
func ProtoSurfaceIn ¶ added in v0.5.0
func ProtoSurfaceIn(file, src string) (ProtoSurface, error)
ProtoSurfaceIn разбирает один файл контракта.
Разбор идёт по ГЛУБИНЕ СКОБОК, а не по первой закрывающей на своей строке: пустое сообщение записывают одной строкой (`message X {}`), и построчный разбор проглатывал бы его тело вместе со следующим сообщением, приписывая запросу поля ответа. Это наблюдалось: первая редакция замера дала две находки, обе ложные и обе этой формы.
type QueueInventory ¶ added in v0.5.0
type QueueInventory struct {
// Drained — дренируемые очереди по имени таблицы.
Drained map[string]*DrainSite
// Roles — сколько мест каждой роли машинерии очередей осмотрено
// («дренаж», «сканер», «возврат», «уборка»). Перепись форм: расширение
// распознавателя обязано менять её, иначе оно холостое.
Roles map[string]int
// Unclassified — литерал настроек из пространства машинерии очередей, чья
// роль не объявлена. Неизвестный вход — ЯВНЫЙ ОТКАЗ, а не молчание.
Unclassified []string
// Ambiguous — имя константы, которым два прод-файла назвали РАЗНЫЕ таблицы:
// резолв неоднозначен, и угадывать нельзя.
Ambiguous []string
// FilesRead — прочитано файлов Go.
FilesRead int
// LiteralsRead — осмотрено строковых литералов (объём обхода формы
// «собственный оператор»).
LiteralsRead int
// CommentsSeen — осмотрено комментариев внутри областей объявления дренажа.
// Ноль означал бы, что разбор идёт БЕЗ комментариев и любое молчание проверки
// делегирования ничего не доказывает.
CommentsSeen int
// contains filtered or unexported fields
}
QueueInventory — перепись очередей дерева.
func DrainInventoryOf ¶ added in v0.5.0
func DrainInventoryOf(corpus TreeCorpus, queues []string) (QueueInventory, error)
DrainInventoryOf — перепись дренажа по корпусу прод-файлов Go.
`queues` — очереди схемы: форма «собственный оператор» опознаётся ТОЛЬКО на них. Сужение не удобство: без него распознаватель считал бы очередью всякое имя, попавшее в строку с признаком доставки, — включая образцы в собственном исходнике проверок.
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 RecipeCall ¶ added in v0.5.0
type RecipeCall struct {
// Line — номер строки рецепта, чтобы читатель шёл по координате.
Line int
// Raw — тело комментария целиком: текст находки называет его дословно.
Raw string
// Dir — каталог, названный ключом `-C`. Пусто — вызов каталога не называет.
Dir string
// Foreign — строка объявила свои координаты координатами чужого репозитория.
Foreign bool
}
RecipeCall — строка ВЫЗОВА в комментарии рецепта: та, что предписывает команду.
func RecipeCallsOf ¶ added in v0.5.0
func RecipeCallsOf(body, ownHome string) (calls []RecipeCall, lines, comments int)
RecipeCallsOf — строки вызова в комментариях рецепта.
Возвращает вызовы И объём прочитанного: без второй величины «вызовов ноль» было бы неотличимо от «рецепт не прочитан».
type RecipeCallCensus ¶ added in v0.5.0
type RecipeCallCensus struct {
// Lines — строк рецепта прочитано.
Lines int
// Comments — из них строк-комментариев.
Comments int
// Calls — строк вызова среди них.
Calls int
// Dirs — вызовов, назвавших каталог ключом `-C`.
Dirs int
// Exempt — из них освобождённых упоминанием чужого репозитория.
Exempt int
// Resolved — каталогов, которые в дереве ЕСТЬ.
Resolved int
// Findings — находки, каждая с координатой.
Findings []string
}
RecipeCallCensus — объём осмотренного и находки.
Величины ПО КАЖДОЙ ОСИ отдельно: одно число скрыло бы случай, ради которого гейт заведён, — рецепт, в котором строк вызова не нашлось вовсе.
func JudgeRecipeCalls ¶ added in v0.5.0
func JudgeRecipeCalls(calls []RecipeCall, trackedDirs map[string]bool) RecipeCallCensus
JudgeRecipeCalls — суждение о разобранных вызовах.
Чистая функция от уже прочитанного: её же зовёт инъекция, подавая синтетику. Гейт, чью способность падать доказывают правкой живого рецепта, доказательства не имеет.
trackedDirs — каталоги, отслеживаемые деревом, выведенные из индекса git.
type RecoveryPathMarkCensus ¶ added in v0.5.0
type RecoveryPathMarkCensus struct {
GoFiles int
SQLFiles int
GoMentions int
Clearers []string
SQLMentioners []string
Findings []string
}
RecoveryPathMarkCensus — объём осмотренного и найденное.
func RecoveryPathMarkWriters ¶ added in v0.5.0
func RecoveryPathMarkWriters(goFiles map[string]string, sqlFS fs.FS, decl RecoveryPathMarkDecl) (RecoveryPathMarkCensus, error)
RecoveryPathMarkWriters судит дерево: goFiles — непроверочный код Go (путь → текст), sqlFS — миграции.
type RecoveryPathMarkDecl ¶ added in v0.5.0
RecoveryPathMarkDecl — объявление предмета: имя колонки, где живёт единственный снимающий оператор и какой файл миграции отметку ставит. Приходит ПАРАМЕТРОМ из файла пробы: литерал имени колонки в этом файле сделал бы гейт своей же первой находкой, а файл пробы в корпус не входит.
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 RegistrationLane ¶ added in v0.5.0
type RegistrationLane struct {
Name string
Line int
// Consequences — значения следствий, как они разрешились (литерал либо
// константа файла). Неразрешённый идентификатор остаётся именем с
// приставкой `?` — он виден в переписи, а не теряется.
Consequences []string
// IssuesSession — среди следствий есть значение выдачи сессии.
IssuesSession bool
}
RegistrationLane — одна полоса, как её прочитал разбор.
type RegistrationLaneLiteralSite ¶ added in v0.5.0
RegistrationLaneLiteralSite — составной литерал типа полосы в прод-коде.
func ScanRegistrationLaneLiterals ¶ added in v0.5.0
func ScanRegistrationLaneLiterals(path string, src []byte) ([]RegistrationLaneLiteralSite, error)
ScanRegistrationLaneLiterals — составные литералы типа `Lane` (в своём пакете) либо `<пакет>.Lane` (из чужого) в одном Go-файле. Читатель судит, лежат ли они в файле объявления.
func (RegistrationLaneLiteralSite) String ¶ added in v0.5.0
func (s RegistrationLaneLiteralSite) String() string
type RegistrationLanesCensus ¶ added in v0.5.0
type RegistrationLanesCensus struct {
// Declarations — переменных с именем объявления найдено (обязано быть 1).
Declarations int
// Lanes — полос разобрано.
Lanes int
// IssuingSession — из них с выдачей сессии.
IssuingSession int
}
RegistrationLanesCensus — объём осмотренного объявлением.
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 RequestFieldCensus ¶ added in v0.5.0
type RequestFieldCensus struct {
ProtoFiles int
GoFiles int
Services int
RequestUses int
Messages int
Fields int
PublicFields int
InternalFields int
// WholePassed — сообщений, ушедших в вызов целиком: их поля судить нечем,
// и они выведены из вердикта ЯВНО, а не прощены молча.
WholePassed int
EscapedFields int
// ScopeReadFields — полей, чей читатель — край (`scope_extractor`).
ScopeReadFields int
// DeprecatedFields — полей, помеченных `deprecated`.
DeprecatedFields int
Findings []string
}
RequestFieldCensus — перепись обхода и находки.
func JudgeRequestFieldReaders ¶ added in v0.5.0
func JudgeRequestFieldReaders( surfaces []ProtoSurface, reads []RequestFieldRead, whole []string, protoFiles, goFiles int, ) RequestFieldCensus
JudgeRequestFieldReaders сводит популяцию контракта с прочтениями прод-кода.
Судится ПОЛЕ, а не сообщение: сообщение, у которого прочитана половина полей, проходило бы, и непрочитанная половина осталась бы невидимой.
func (RequestFieldCensus) Summary ¶ added in v0.5.0
func (c RequestFieldCensus) Summary() string
Summary — перепись строкой: «ноль находок» обязано быть отличимо от «ноль прочитанного», поэтому объём осмотренного печатается всегда.
type RequestFieldRead ¶ added in v0.5.0
type RequestFieldRead struct {
Message string
// Selector — имя, через которое обратились: `GetAccountId` либо `AccountId`.
Selector string
File string
Line int
}
RequestFieldRead — прочтение поля запроса в прод-коде.
func RequestFieldReadsIn ¶ added in v0.5.0
func RequestFieldReadsIn(file, src string, messages map[string]bool) ([]RequestFieldRead, []string, error)
RequestFieldReadsIn разбирает один прод-файл Go и возвращает прочтения полей запроса вместе с перечнем запросов, ушедших в вызов целиком.
Идентификатор считается запросом, когда его ОБЪЯВЛЕННЫЙ тип есть указатель на известное сообщение: параметр функции, результат, объявление переменной либо присваивание от составного литерала. Псевдоним, связанный присваиванием от такого идентификатора, наследует связь — ровно та форма, которой пользуются обработчики.
type RequestUse ¶ added in v0.5.0
type RequestUse struct {
File string
Service string
RPC string
Message string
// Internal — глагол объявлен службой с приставкой `Internal`, то есть на
// внешний маршрутизатор не попадает (ban #6).
Internal bool
// ScopeFields — поля, названные `scope_extractor.from_request_field`.
// У них читатель есть, и он объявлен ЗДЕСЬ ЖЕ: край берёт по этому имени
// объект, про который спрашивает модель прав. Прод-кода службы такое поле
// может не касаться вовсе — и это не «принято-и-проигнорировано», а
// разделение обязанностей между краем и службой.
ScopeFields []string
}
RequestUse — употребление сообщения как запроса глагола.
type RetiredIssuerClaim ¶ added in v0.5.0
RetiredIssuerClaim — одно утверждение, пережившее предмет.
func (RetiredIssuerClaim) String ¶ added in v0.5.0
func (c RetiredIssuerClaim) String() string
type RetiredIssuerClaimCensus ¶ added in v0.5.0
type RetiredIssuerClaimCensus struct {
// Files — файлов корпуса прочитано.
Files int
// Mentions — строк, называющих прежний издатель хоть как-нибудь.
Mentions int
// Claims — из них утверждений о действующем (до вычета надгробий).
Claims int
// Tombstones — утверждений в форме надгробия (законный близнец).
Tombstones int
// Findings — утверждений, переживших предмет.
Findings int
}
RetiredIssuerClaimCensus — объём осмотренного. Печатается всегда: «ноль находок» обязано быть отличимо от «ноль прочитанного».
func (RetiredIssuerClaimCensus) String ¶ added in v0.5.0
func (c RetiredIssuerClaimCensus) String() string
type RetiredVendorBinding ¶ added in v0.5.0
type RetiredVendorBinding struct {
File string
// Line — номер строки; 0 там, где судится файл целиком (путь, байты).
Line int
Axis string
Text string
}
RetiredVendorBinding — одна привязка.
func (RetiredVendorBinding) Coord ¶ added in v0.5.0
func (b RetiredVendorBinding) Coord() string
Coord — координата привязки: `файл:строка · ось · текст`.
type RetiredVendorCensus ¶ added in v0.5.0
type RetiredVendorCensus struct {
// Разбиение обхода: Text + Binary + Prose + Ledger == Walked.
Walked int
Text int
Binary int
Prose int
Ledger int
// Lines — строк прочитано в судимых построчно.
Lines int
// CommentSkipped — строк, несущих имя, но начинающихся маркером
// комментария: цена границы, названная числом.
CommentSkipped int
// История схемы (`retired_vendor_schema_history.go`): миграций прочитано,
// идентификаторов, снятых историей, и строк истории снятого — законная
// форма снятия, названная числом, а не умолчанием.
HistoryMigrations int
HistoryRemoved int
HistoryLines int
Bindings int
ByPath int
ByLine int
ByBinary int
// Files — файлов, несущих хоть одну привязку.
Files int
// Entries, Recorded — записей ведомости и их сумма.
Entries int
Recorded int
Findings int
}
RetiredVendorCensus — объём осмотренного. Печатается всегда: «находок ноль» обязано быть отличимо от «прочитано ноль».
func (RetiredVendorCensus) String ¶ added in v0.5.0
func (c RetiredVendorCensus) String() string
type RetiredVendorFinding ¶ added in v0.5.0
type RetiredVendorFinding struct {
Kind string
File string
Recorded int
Actual int
// Bindings — все привязки файла; у роста это и есть координата.
Bindings []RetiredVendorBinding
}
RetiredVendorFinding — расхождение файла с его записью.
func (RetiredVendorFinding) String ¶ added in v0.5.0
func (f RetiredVendorFinding) String() string
type RetiredVendorLedgerEntry ¶ added in v0.5.0
RetiredVendorLedgerEntry — одна запись ведомости: файл и точное число его привязок в единице `RetiredVendorCountingUnit`.
type RetiredVendorVerdict ¶ added in v0.5.0
type RetiredVendorVerdict struct {
Findings []RetiredVendorFinding
Census RetiredVendorCensus
// PerFile — привязки дерева по файлу.
PerFile map[string][]RetiredVendorBinding
// RemovedBySchemaHistory — идентификаторы, снятые историей схемы, по
// возрастанию.
RemovedBySchemaHistory []string
}
RetiredVendorVerdict — исход суда над деревом.
func JudgeRetiredVendorBindings ¶ added in v0.5.0
func JudgeRetiredVendorBindings(corpus TreeCorpus, ledger []RetiredVendorLedgerEntry) (RetiredVendorVerdict, error)
JudgeRetiredVendorBindings — тело гейта над телами файлов дерева и ведомостью. Вынесено, чтобы инъекция звала ТО ЖЕ, что исполняется на дереве. Корпус — ВСЕ отслеживаемые файлы: проза и ведомость отсеиваются здесь, а не у читателя, иначе правило отбора жило бы вне пробы.
func (RetiredVendorVerdict) Roster ¶ added in v0.5.0
func (v RetiredVendorVerdict) Roster() string
Roster — перечень файлов с привязками: `число · путь`, по пути. Форма совпадает с тем, что ведомость обязана записать.
type ReviewTriggerCensus ¶ added in v0.5.0
type ReviewTriggerCensus struct {
// Files — объявлений прочитано; OnReview — из них идущих на запросе
// любым из двух событий; OnReviewTarget — из идущих на запросе тех, что
// идут на `pull_request_target`; ReviewAtLine — из идущих на запросе тех,
// у кого фильтр баз `pull_request` РАВЕН объявленному.
Files int
OnReview int
OnReviewTarget int
ReviewAtLine int
// OnBranchPush — идущих по `push` в ветки (не только в метки).
OnBranchPush int
// PublishersDeclared — записей в перечне публикующих; PublishersRead — из
// них объявлений, прочитанных в корпусе; PublishAtLine — из прочитанных
// тех, у кого `on.push.branches` РАВЕН ReviewBaseBranches.
PublishersDeclared int
PublishersRead int
PublishAtLine int
// Conditions — условий `if:` осмотрено (заданий и шагов вместе);
// ConditionLinks — звеньев в них прочитано. Условия есть, а звеньев ноль —
// разбор лексем ослеп, и молчание оси 4 сказано ни о чём.
Conditions int
ConditionLinks int
// Aliases — псевдонимов YAML разрешено до суждения (шапка, «YAML:
// ПСЕВДОНИМ РАЗРЕШАЕТСЯ ДО СУЖДЕНИЯ»).
Aliases int
}
ReviewTriggerCensus — объём осмотренного.
func AuditReviewTriggers ¶ added in v0.5.0
func AuditReviewTriggers(corpus map[string]string) ([]string, ReviewTriggerCensus, error)
AuditReviewTriggers — вердикт о триггерах КОРПУСА процессов.
Вход — имя объявления → его текст. Чистая функция от корпуса затем, чтобы способность упасть доказывалась подачей входа, а не правкой дерева.
func (ReviewTriggerCensus) String ¶ added in v0.5.0
func (c ReviewTriggerCensus) String() string
String — перепись одной строкой. «Ноль находок» обязано быть отличимо от «ноль прочитанного», поэтому печатаются все величины.
type RevocationWriter ¶ added in v0.5.0
type RevocationWriter struct {
File string
Line int
Name string
Table string
// Why — почему писатель стал находкой. Находка обязана называть ПРИЧИНУ, а
// не только координату: «его не зовут» и «по имени не разобрать, зовут ли»
// требуют разного, и слитые в одно они читаются одинаково.
Why string
}
RevocationWriter — функция либо метод, пишущий в запись отсечки.
func RevocationWritersWithoutACaller ¶ added in v0.5.0
func RevocationWritersWithoutACaller( writers []RevocationWriter, called map[string]struct{}, declared map[string]int, ) []RevocationWriter
RevocationWritersWithoutACaller — писатели, про которых НЕЛЬЗЯ СКАЗАТЬ, что их зовут.
Исходов находки ДВА, и они не сливаются:
- имени писателя нет среди вызванных — его не зовёт никто;
- имя писателя объявлено в дереве НЕ ОДИН раз — по имени не разобрать, зовут ли именно его. Это тоже находка, и вот почему: ровно так дефект и прятался. Писатель записи, по которой судит читатель предъявления, назывался общим словом, это слово звали пятеро посторонних, и прибор молчал с той же уверенностью, с какой молчит на работающем контроле.
Второй исход снимается ИМЕНЕМ: писатель отсечки обязан называться так, чтобы его можно было проследить. Это требование к форме, и оно дешевле любого разбора достижимости — а главное, оно не может замолчать.
type RevocationWriterCensus ¶ added in v0.5.0
type RevocationWriterCensus struct {
// Funcs — функций с телом осмотрено.
Funcs int
// Writers — писателей найдено.
Writers int
// Tables — таблицы отсечки, выведенные обходом.
Tables map[string]struct{}
// Statements — объявлений операторов записи, вынесенных из тела, осмотрено.
// Печатается отдельно: «форм записи известно две» обязано быть видно, иначе
// сужение разбора до одной формы прошло бы молча.
Statements int
}
RevocationWriterCensus — объём осмотренного.
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 SchemaQueues ¶ added in v0.5.0
type SchemaQueues struct {
// ByName — очереди, опознанные по приставке имени.
ByName []string
// ByMarker — очереди, опознанные по колонке-признаку доставки.
ByMarker []string
// Dropped — таблицы, снятые более поздней миграцией.
Dropped []string
// FilesRead — прочитано файлов миграций.
FilesRead int
// TablesRead — осмотрено объявлений таблиц.
TablesRead int
}
SchemaQueues — очереди ЖИВОЙ схемы: заведённые миграциями и не снятые ими.
func QueuesOfSchema ¶ added in v0.5.0
func QueuesOfSchema(migrations TreeCorpus) (SchemaQueues, error)
QueuesOfSchema — очереди схемы по корпусу миграций.
Признака ДВА и оба печатаются: приставка имени и колонка доставки. Один признак скрыл бы ровно тот случай, ради которого перепись и ведётся, — очередь, названную иначе либо помечающую доставку иной колонкой.
Снятые таблицы вычитаются: текстовый предикат по миграциям иначе считает живой ту, чей предмет убрала более поздняя миграция, а ложная находка выключает проверку быстрее, чем её чинят.
func (SchemaQueues) Live ¶ added in v0.5.0
func (q SchemaQueues) Live() []string
Live — очереди живой схемы: объединение обоих признаков, без снятых.
type SchemaValueListSite ¶ added in v0.5.0
type SchemaValueListSite struct {
File string
Line int
// Constraint — имя ограничения, если объявлено.
Constraint string
// Values — значения перечня как записаны.
Values []string
}
SchemaValueListSite — ограничение схемы, перечисляющее значения столбца, среди которых есть имя словаря.
func ScanSchemaValueLists ¶ added in v0.5.0
func ScanSchemaValueLists(path, upSection string, vocabulary []string) []SchemaValueListSite
ScanSchemaValueLists — перечни значений в накате миграции (`IN (…)`, `= ANY (ARRAY[…])`), пересекающиеся со словарём.
Разбор читает накат с ЗАБЕЛЁННЫМИ комментариями — забеливает вызывающий тем же средством, что у соседей по пакету (`migrations.MigrationUpSection`).
func (SchemaValueListSite) String ¶ added in v0.5.0
func (s SchemaValueListSite) String() string
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
// Edge — величина ГРАНИЦЫ: вхождения в тексте приёмки (оба его дома).
//
// Ведром она не является намеренно (задача #158): величина самоссылочна и
// растёт от документной работы, к предмету приёмки отношения не имеющей,
// поэтому её объявление в §0 облагало бы каждую приёмочную полосу правкой
// ЧУЖИХ чисел. Но из наблюдения она не изъята: предикат её печатает, а
// разбор читает — иначе изъятие стало бы маской.
Edge SeedCensusCell
// EdgeNamed — печатал ли предикат строку изъятого ВООБЩЕ.
//
// Отдельное поле, а не ноль в Edge: ноль вхождений в тексте приёмки —
// состояние достижимое (документ без единого литерала), а молчание
// предиката о границе — поломка. Слив их в одно значение, разбор объявил бы
// исправным прибор, переставший печатать.
EdgeNamed bool
}
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 SentinelTranslator ¶ added in v0.5.0
type SentinelTranslator struct {
File string
Line int
Func string
// Sentinels — полосы, которые переводчик различает, отсортированы: имена
// `iamerr.Err*` и полосы конца контекста (`context.Canceled`,
// `context.DeadlineExceeded`).
Sentinels []string
}
SentinelTranslator — один найденный переводчик отказа.
func (SentinelTranslator) Has ¶ added in v0.5.0
func (t SentinelTranslator) Has(sentinel string) bool
Has — различает ли переводчик эту полосу.
type SentinelTranslatorCensus ¶ added in v0.5.0
type SentinelTranslatorCensus struct {
// Funcs — функций прочитано.
Funcs int
// WithSentinels — из них различающих хотя бы один `iamerr.Err*`.
WithSentinels int
// Translators — из них переводчиков (оба признака).
Translators int
}
SentinelTranslatorCensus — объём осмотренного одним файлом.
type SettingKeyCensus ¶ added in v0.5.0
type SettingKeyCensus struct {
// Files — документов прочитано.
Files int
// Tables — таблиц с объявленной колонкой ключа найдено.
Tables int
// Rows — строк таблиц осмотрено.
Rows int
// RowsWithoutKey — строк, где ключ не назван (`—`, проза): граница, не находка.
RowsWithoutKey int
// Matched — ключей, найденных в настройке.
Matched int
// Keys — величина множества ключей, полученного от производителя.
Keys int
// UnnamedYAMLHeaders — заголовки со словом `yaml`, словарём НЕ опознанные,
// с координатой. Промах словаря обязан быть виден числом.
UnnamedYAMLHeaders []string
}
SettingKeyCensus — объём осмотренного. «Находок ноль» читается только рядом с ним: ноль описей и ноль прочитанных документов — разные вердикты.
func (SettingKeyCensus) String ¶ added in v0.5.0
func (c SettingKeyCensus) String() string
type SettingKeyFinding ¶ added in v0.5.0
type SettingKeyFinding struct {
// File — путь документа от корня дерева.
File string
// Line — номер строки описи, 1-based.
Line int
// Key — ключ, как его назвала опись.
Key string
// Nearest — ближайший существующий ключ по общему началу; пусто, если
// общего начала нет. Находка называет, ЧЕМ чинить, а не только что сломано.
Nearest string
}
SettingKeyFinding — ключ, названный описью и отсутствующий в настройке.
func (SettingKeyFinding) String ¶ added in v0.5.0
func (f SettingKeyFinding) String() string
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 SurfaceHit ¶ added in v0.5.0
SurfaceHit — поверхность, на которой резолвится координата, и путь до регистрации.
type SurfaceRoutes ¶ added in v0.5.0
SurfaceRoutes — выведенная таблица маршрутов одной поверхности.
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 DrainSiteCorpus ¶ added in v0.5.0
func DrainSiteCorpus(tree *treecorpus.Tree) (TreeCorpus, error)
DrainSiteCorpus — прод-файлы Go дерева: и проводка, и собственный оператор живут только в них.
Отдельным семейством, а не вызовом отбора в теле гейта: обход обязан приходить параметром, чтобы инъекция подала ему пустое дерево и премиса «прочитано ноль» была доказана исполнением, а не чтением (задача #17).
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)
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 UnresolvedPathEntry ¶ added in v0.5.0
type UnresolvedPathEntry struct {
// Leaf — ключ листа в том виде, в каком его печатает перепись.
Leaf string
// Where — полное имя объявленной функции, в которой стоит регистрация с
// этим листом. Ведомость точна по МЕСТУ: тот же лист на месте, которого
// запись не называет, — находка.
Where string
// Why — причина и предикат снятия.
Why string
}
UnresolvedPathEntry — объявленный лист пути, который разбор не сводит к значению.
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 VocabularyListSite ¶ added in v0.5.0
type VocabularyListSite struct {
File string
Line int
// Form — форма объявления (составной литерал · группа const/var · case).
Form string
// Names — имена словаря, найденные в узле, без повторов.
Names []string
}
VocabularyListSite — объявление перечня имён способов в Go-коде.
func (VocabularyListSite) String ¶ added in v0.5.0
func (s VocabularyListSite) String() string
type VocabularyScanCensus ¶ added in v0.5.0
type VocabularyScanCensus struct {
// Files — файлов прочитано (заполняет вызывающий).
Files int
// Strings — строковых литералов прочитано.
Strings int
// VocabularyStrings — литералов, совпавших с именем словаря (в любом узле).
VocabularyStrings int
// Lists — объявлений перечня найдено.
Lists int
}
VocabularyScanCensus — объём осмотренного.
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
- address_admission_gates.go
- address_in_refusal_text.go
- applier_never_deletes.go
- ascii_identifiers.go
- assertion_admission_calls.go
- assertion_verifier_single.go
- assurance_level_sole_writer.go
- assurance_method_vocabulary.go
- ast_receiver.go
- audit_payload_pii.go
- authz_wrapper_outcome_lanes.go
- basic_credential_proof_run.go
- binding_insert_writes_ledger.go
- build_stamp_word.go
- carried_coordinate_ledger.go
- catalog_check_wiring.go
- catalog_copy_parity.go
- catalog_covers_contract.go
- catalog_seed_parity.go
- catalog_writer_lock.go
- census_fixture_producer.go
- ceremony_surface.go
- ceremony_surface_flow.go
- ceremony_surface_load.go
- ceremony_surface_manual.go
- ceremony_surface_norace.go
- ceremony_surface_resolve.go
- client_expiry_immutable.go
- client_truth_exclusion_form.go
- client_truth_module_set.go
- comment_coordinate_layout.go
- contract_names_live_machinery.go
- deferred_work.go
- delete_revoke_producer.go
- derived_id_single_source.go
- doc_header_names_its_declaration.go
- documented_setting_key_exists.go
- drain_order_declared.go
- envelope_composition_root.go
- failure_reset_sole_writer.go
- family_revocation_reason_writers.go
- family_verdict_single_reader.go
- family_verdict_tree.go
- granted_relation_in_model.go
- guard_named_in_comment.go
- history_question_vertex.go
- identity_growth_reader.go
- image_published_revision.go
- injection_named_exists.go
- issue_ref_prefix.go
- job_knob_has_a_reader.go
- judge_target_wiring.go
- key_algorithm_dictionary.go
- limit_export_procedure.go
- list_scope_double.go
- login_verifier_containment.go
- login_verifier_flow.go
- mail_kind_sender_parity.go
- mail_send_paths.go
- manifest_verb_class_rule.go
- membership_removal_expires_invite.go
- migration_not_a_writer_of_module_role.go
- migration_section_split.go
- migration_version_monotonic.go
- mirror_catalog_condition.go
- mirror_divergence_wiring.go
- module_identity_seeded_only_by_baseline.go
- named_verb_form_expiry.go
- paired_write.go
- password_hash_format_registry.go
- password_rule_sole_declaration.go
- people_address_lawful_writers.go
- people_address_writers.go
- people_address_writers_migrations.go
- probe_home.go
- probe_tooling.go
- proto_comment_names_a_real_message.go
- published_key_private_half.go
- published_key_rule_home.go
- quota_authority_retired.go
- read_path_concat.go
- recipe_call_coordinate.go
- recovery_path_mark_writers.go
- refusal_text_is_fixed.go
- registration_lanes.go
- relation_fact_sole_writer.go
- request_field_has_a_reader.go
- retired_issuer_claim.go
- retired_monorepo_gate_ledger.go
- retired_vendor_bindings.go
- retired_vendor_bindings_ledger.go
- retired_vendor_schema_history.go
- review_trigger_scope.go
- revocation_writer_has_a_caller.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
- sentinel_translator_parity.go
- sql_relation_name.go
- subject_change_flush_parity.go
- system_role_row_is_never_deleted.go
- terminal_refusal_wrapping.go
- token_claim_foreign_brand.go
- token_claim_retired_provider.go
- token_claim_single_source.go
- token_family_sole_writer.go
- tree_corpus.go
- trunk_verdict_holder.go
- trunk_verdict_register.go
- withdrawal_producer_arrives_with_the_applier.go