Documentation
¶
Overview ¶
acceptance_edit_after_verdict.go — правка ОДОБРЕННОЙ приёмки после вердикта объявляется в самом документе.
Порт с монорепо (`internal/repohygiene/acceptanceeditafterverdict.go`, снят вынесением службы — `kacho#2597`). Изменилось: путь дома приёмок (был `services/iam/docs/engineering/acceptance`, здесь — `docs/engineering/acceptance` от корня СВОЕГО модуля) и обход git через `platformtree`/`gitenv` вместо внутреннего `repoRoot(t)` монорепо. Осталось дословно: имя функции гейта (`TestAcceptanceEditedAfterItsVerdictSaysSo`), сам разбор и текст находки.
Предмет ¶
Вердикт есть утверждение о РЕВИЗИИ, которую прочитал проверяющий: правка её не переносит и не отзывает задним числом. Документ, чья строка состояния правлена раньше, чем сам файл, и не назвавший эту правку прямо, объявляет вердикт о ревизии, которую никто не читал.
Почему пара величин, а не одна ¶
Признак — сравнение двух отметок: когда последний раз правилась СТРОКА СОСТОЯНИЯ и когда сам документ. Обе берутся в ЭПОХЕ: строковое сравнение дат в двух часовых поясах даёт неверный порядок.
acceptance_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` §«Кросс-репо координата — вне суждения ОБОИХ сторон».
РЕЗОЛВ в названном доме здесь НЕ делается, и это остаток с предметом, а не граница по незнанию: воркспейс его умеет (опознаёт дерево идентичностью `origin`, отвечает третьей категорией, когда дерева рядом нет), но в конвейере службы чужого дерева нет НИКОГДА — ветвь была бы вечно-пустой, то есть мёртвым стражем ровно того вида, который запрещает ban #16. Заводится вместе с резолвером дома и инъекцией на двух синтетических деревьях — `kaname#44`.
«Вне суждения» отличается от «прощено» ТРЕМЯ свойствами, и все три обязательны:
- чужая координата СЧИТАЕТСЯ, а её дома ПЕЧАТАЮТСЯ переписью. Дом, стоящий в корпусе один раз, тем самым виден — опечатка в имени репозитория не уходит молча. Связанные РЕВИЗИЕЙ считаются отдельно: они не проверяемы даже там, где дерево дома есть;
- приставка, домом НЕ являющаяся (`kacho:TestFoo`, `IAM-MV-04:TestFoo`), — НАХОДКА. Без этого любой не-разобранный префикс снимал бы координату с суждения, и приставка стала бы способом спрятать адрес, а не назвать дом;
- ДВА СТОРОЖА, и живут они в гейте (`acceptance_probe_coordinate_test.go`), а не здесь, потому что им нужен дом ЭТОГО дерева — ядро судит значения, и для него всякий непустой дом чужой. Первый отвергает корпус, где ВСЕ координаты объявлены чужими: судить нечего, и «находок ноль» означало бы «ноль прочитанного». Второй ловит СВОЙ дом, названный чужим (`PRO-Robotech/kaname:TestFoo`), — иначе всякая мёртвая координата закрывается припиской своего же имени репозитория. Дом дерева выводится из `go.mod` (`OwnHomeOfTree`), а не складывается литералом.
Замер перед введением формы: пролётов вида `<что-то>:<имя-пробы>` в корпусе приёмок — НОЛЬ в обе стороны (и разобранных домом, и не разобранных), то есть правило 2 не краснеет ни на одной существующей строке.
applier_never_deletes.go — разбор пакета применителя ролей на предмет удаления строки роли (приёмка `docs/engineering/acceptance/roles-come-as-data-not-migrations.md` §3.1, держатель Г3; сценарий MOD-RD-15).
Порт с монорепо (`internal/repohygiene/applierneverdeletes.go`, снят вынесением службы — `kacho#2597`). Осталось дословно: имя функции гейта (`TestMODRD15ApplierNeverDeletesARoleRow`), сам разбор (обе оси, оба образца) и текст находки. Изменилось: пакет-цель — `internal/apps/kaname/moduleroles` (в монорепо — `services/iam/internal/apps/kaname/moduleroles`), путь-константа без префикса `services/iam/`.
Предмет ¶
Роль с выдачами удалить нельзя (`ON DELETE RESTRICT`) — применитель встал бы на первой же роли, которой кто-то пользуется. Форма отзыва роли выбрана решением: строка ПОМЕЧАЕТСЯ снятой, а не удаляется (`docs/engineering/architecture/role-withdrawal-is-a-mark.md`).
Что здесь считается находкой — ДВЕ оси, и первая сильнее ¶
- порт применителя объявляет ОДНОЗНАЧНО удаляющий глагол НАД СТРОКОЙ РОЛИ (судит имена методов интерфейса: глагол + предмет глагола);
- в пакете стоит оператор `DELETE` над таблицей ролей строковым литералом узла разбора, а не подстрокой текста.
Чего разбор НЕ видит — названо, а не спрятано ¶
Запрос, собранный из кусков в рантайме, и запрос, приехавший параметром — первое не встречается в дереве, второе ловит первая ось: чтобы позвать чужое удаление, порт обязан его объявить.
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/`.
Предмет ¶
Число обращений к базе внутри одной функции. Допуск однократности обязан делать РОВНО ОДНО: «не предъявлялось ли уже» и «погасить» неделимы, и неделимыми их делает первичный ключ таблицы, а не аккуратность вызывающего. Пара «посмотреть — записать» проходит ВСЕ последовательные пробы: окна между чтением и записью при последовательном прогоне не существует.
Почему владелец соединения берётся из ОБЪЯВЛЕНИЯ ТИПА, а не из списка имён ¶
Разбор читает объявления структур файла и берёт в носители соединения те поля, ЧЕЙ ТИП называет драйвер базы. Переименование поля исход не меняет, чужое одноимённое поле находкой не становится.
authz_wrapper_outcome_lanes.go — булева ОБЁРТКА вопроса о правах не вызывается там, где у неё есть парная форма с исходом (задача #1045).
Порт с монорепо (`internal/repohygiene/authzwrapperoutcomelanes_test.go`, снят вынесением службы — `kacho#2597`). В кaname живёт как минимум одна такая пара: `authzguard.SubjectIsClusterAdmin` (bool) рядом с `SubjectIsClusterAdminE`/`SubjectIsClusterAdminPlainE` (bool, error) — то есть предмет ЖИВ, и гейт переносится. Изменилось: перечень «прод-корней» и путь модуля читаются из СВОЕГО дерева, а не из монорепо; имя гейта сохранено дословно.
Что ищется — СВОЙСТВО, и оно ВЫВОДИТСЯ ИЗ ДЕРЕВА ¶
Перечня имён у этого гейта нет и быть не может: пары выводятся —
F — экспортированная функция пакета, возвращающая РОВНО `bool`;
FE — функция ТОГО ЖЕ пакета с именем `F`+`E` либо `F`+`PlainE`,
возвращающая `(bool, error)`.
Есть пара ⇒ автор пакета УЖЕ объявил, что у этого вопроса три исхода, а не два. Значит вызов булевой половины из ЧУЖОГО пакета — выбор, а не необходимость, и выбран он в пользу формы, из которой «хранилище не ответило» достать нельзя.
Граница названа честно ¶
Вызовы ВНУТРИ пакета, объявившего пару, под гейт не подпадают: там булева половина и есть тело обёртки. Узнавание идёт по ИМЕНИ ИМПОРТА файла, а не по типам.
basic_credential_proof_run.go — доказательство формы базового удостоверения обязано ПРОИЗВОДИТЬСЯ ПРОГОНОМ, а не просто лежать в дереве (`PRO-Robotech/kacho#1253`).
Порт с монорепо (`internal/repohygiene/basiccredentialproofrun_test.go`, снят вынесением службы — `kacho#2597`). Осталось дословно: имя функции гейта, сам разбор `run:`-тел workflow и текст находки. Изменилось: пути без префикса `services/iam/`, конвейер — `.github/workflows/` СВОЕГО репозитория.
Предмет ¶
Во всём сквозном прогоне не было НИ ОДНОГО зелёного утверждения, читающего секрет базового удостоверения из УСПЕШНОГО ответа. Проверка, которую никто не зовёт, ничего не производит: её зелёное существует только в чужой голове.
Читается ИСПОЛНЯЕМАЯ часть, а не текст ¶
YAML разбирается, берутся тела `run:`, и из них выбрасываются строки оболочечных комментариев. Гейт по подстроке краснел бы на собственном объяснении и зеленел бы на шаге, откуда вызов сняли, а комментарий оставили.
build_stamp_word.go — разбор объявления строковой константы синтаксическим деревом, а не текстом.
Предмет ¶
Слово «сборка штамп не проставила» стоит в прозе (шапках, документации) не реже, чем в объявлении. Поиск по подстроке нашёл бы собственное объяснение и остался бы зелёным при разошедшихся объявлениях — узел объявления константы судится вместо строки файла ровно по этой причине.
carried_coordinate_ledger.go — разбор ведомости координат, переносимых до снятия внешнего провайдера аутентификации клиента (приёмка F2, сценарий F2-46, §9.4).
Порт с монорепо (`internal/repohygiene/carriedcoordinateledger.go`, снят вынесением службы — `kacho#2597`). Осталось дословно: имя функции гейта (`TestCarriedCoordinateLedgerExpiresOnItsOwn`), сам разбор и словарь исходов. Изменилось: путь ведомости без префикса `services/iam/` (`docs/engineering/architecture/client-assertion-carried-over-coordinates.md`) и область зеркальной колонки — раньше сужалась до `services/iam/` внутри монорепо, теперь это ВЕСЬ репозиторий службы (у неё нет больше соседей по дереву). Ведомость службы, будучи скопирована целиком, несла координаты со старым префиксом `services/iam/` — они не резолвились НИ ОДНА (кросс-репо staleness, а не намеренное послабление); исправлено тем же изменением, которым перенесён гейт.
Предмет ¶
Фаза F2 завела принимающую сторону и ничего не сносит. У каждой координаты, дожившей до снятия внешнего провайдера, обязан быть назван исход из закрытого словаря; четвёртого — «осталось как есть, потому что не заметили» — не существует. У исхода «оставлено» обязан быть ПРЕДИКАТ СНЯТИЯ.
Гейт двусторонний ¶
- ПОЛНОТА: координата, живущая в дереве и не названная ведомостью, — находка;
- САМОИСТЕЧЕНИЕ: запись, чьей координаты в дереве больше нет, — находка.
Кросс-репо координата — вне суждения ОБОИХ сторон ¶
Ведомость несёт координаты не только своего репозитория (напр. `services/registry/...` — сервис реестра остался в монорепо продукта, а не уехал со службой доступа). Такую координату этот гейт не проверяет НИ ПОЛНОТОЙ, ни САМОИСТЕЧЕНИЕМ: он не может ни подтвердить, ни опровергнуть существование файла в ЧУЖОМ репозитории. «В скоупе» решает первый сегмент пути — совпадает с одним из ФАКТИЧЕСКИ отслеживаемых верхних каталогов своего дерева.
catalog_check_wiring.go — сверка каталога прав с копией края обязана быть ЗВАНОЙ конвейером, а не просто существующей целью Makefile.
ПРЕДМЕТ У ГЕЙТА ФОРМА-ПРОВЕРКА, А НЕ ФОРМА-СИНХРОНИЗАЦИЯ (kaname#15) ¶
Портированная редакция требовала вызова `sync-permission-catalog` — и была НЕИСПОЛНИМА by construction: эта цель ПИШЕТ файл. Задание, правящее дерево, вердикта о дереве не даёт: «копии совпали» после собственного `cp` истинно всегда, а рабочая копия ранера уезжает от коммита. Поэтому решение записано в самом рецепте, а гейт судит его: конвейер зовёт `check-permission-catalog` (ничего не пишет, годна обеим посадкам) и НЕ зовёт пишущую форму, которая объявлена ручной операцией выпуска.
Отсюда и переименование пробы: портированное имя было `TestCatalogSyncTargetIsCalledByThePipeline`, и после смены предмета оно утверждало бы неверное — цель синхронизации конвейером не звана НАМЕРЕННО.
Вторая половина того же решения — ОТКУДА БЕРЁТСЯ КОПИЯ КРАЯ. Замер, которого у портированной редакции не было: копия края приезжает в самостоятельный клон МОДУЛЕМ-ПИНОМ платформы (`go.mod`), поэтому сверка исполнима и здесь, а не только в полном чекауте монорепо. Предикат и его граница — в рецепте, у самой цели.
Порт с монорепо (`internal/repohygiene/catalogcheckwiring_test.go`, снят вынесением службы — `kacho#2597` с заявлением «предмет уехал вместе со службой»). Заявление НЕВЕРНО для kaname: своя половина цепочки уехала СЮДА — цель `sync-permission-catalog` объявлена в корневом Makefile службы (`GATEWAY_CATALOG`/`IAM_CATALOG_EMBED`), и её собственный комментарий говорит: «Копия каталога у iam ОБЯЗАНА побайтово совпадать с копией шлюза». Предмет, которым монорепошный гейт стерёг ПРОВЯЗКУ, здесь тот же самый, только половина цепочки живёт по обе стороны границы репозитория.
Здесь СУЖЕННАЯ форма монорепошного гейта: он спрашивал достижимость через ОБЩИЙ анализатор рецептов Makefile (`gatetargetwiring.go`, там же судят гейты `services/*`), которого в этом репозитории нет и заводить его ради двух целей с нулём зависимых — избыточно (ни у `check-permission-catalog`, ни у `sync-permission-catalog` сегодня НЕТ ни одной цели-потребителя внутри Makefile: обе стоят сами по себе, реаситься до них нечему). Поэтому проверяется прямая достижимость: зовёт ли ХОТЬ ОДИН шаг конвейера имя цели напрямую (`make check-permission-catalog` либо `make -C … <цель>`). Появится цель-потребитель — предикат обязан расшириться до реситься-графа, как в монорепо; это отдельное изменение, а не молчаливое сужение.
Чем этот гейт НЕ является ¶
Он не сверяет копии побайтово — это отдельный предмет, и живёт он внутри рецепта `check-permission-catalog`. Предмет ЭТОГО гейта — ПРОВЯЗКА: существует ли у сверки вызывающий среди того, что исполняется САМО, и не зовёт ли конвейер пишущую форму вместо неё.
catalog_writer_lock.go — всякий прод-писатель строк `kaname.catalog_*` берёт глобальный транзакционный замок каталога (приёмка `docs/engineering/acceptance/plan-confirms-what-apply-withdraws.md` §7, объём О11, держатель Г1; kacho#1034).
Порт с монорепо (`internal/repohygiene/catalogwriterlock.go`, снят вынесением службы — `kacho#2597` с заявлением «обход служб жив, но исполняемых операторов записи в этот каталог ноль». Заявление было верно ТОЛЬКО для монорепо (там дерево служб доступа исчезло) — приёмка сама называет отсутствие держателя пунктом Н5 и требует его. Механизм в дереве службы ЖИВ дословно: `internal/repo/kaname/pg/catalog_writer.go` несёт `CatalogLockKey`/`LockCatalog` (`pg_advisory_xact_lock`) и три `UpsertModule`/`UpsertResource`/`UpsertVerb` на том же получателе (`catalogWriter`) — единица суждения по-прежнему сходится. Осталось дословно: весь алгоритм (регулярки, разбор, единица суждения, тексты находок). Изменилось: путь-константа без префикса `services/iam/`, обход — от корня СВОЕГО репозитория целиком (предмет запрета — «ВСЯКИЙ прод-писатель», не только сегодняшний).
Предмет ¶
Подтверждение применения (отпечаток состояния модуля) есть CAS ТОЛЬКО потому, что между чтением отпечатка и записью строк не может встать второй писатель. Обеспечивает это не сравнение, а `pg_advisory_xact_lock`, взятый В ТЕЛЕ КАКОГО-ЛИБО МЕТОДА писателя (гейт не проверяет порядок — это держит интеграционная проба, не разбор).
Единица суждения — ТИП (получатель метода), а не файл и не пакет-вызывающий ¶
Замок и запись могут лежать в РАЗНЫХ методах ОДНОГО получателя в ОДНОМ пакете (как здесь: `LockCatalog` и `UpsertModule` — оба методы `catalogWriter` в `internal/repo/kaname/pg`) — тогда они СХОДЯТСЯ в одну единицу суждения и гейт молчит. Замок, взятый ЧУЖИМ пакетом (например, вызывающим use-case, держащим порт `CatalogWriter`), этот гейт НЕ видит — он не о том, кто ЗОВЁТ замок, а о том, что писатель СПОСОБЕН его взять (несёт метод, который это делает).
census_fixture_producer.go — проба, которая пересчитывает ВСЕ строки таблицы, не вправе наполнять её сама в обход производителя.
Порт с монорепо (`internal/repohygiene/censusfixtureproducer_test.go`, снят вынесением службы — `kacho#2597`). Гейт уже цитируется ШЕСТЬЮ местами в дереве службы (прод-код `internal/repo/kaname/pg/scalegrid/{census,seed}.go` и пробы `relverdict`/`parentedge`) как «гейт дерева `TestCensusFixturesSeedThroughTheProducer`» — предмет жив, и цитаты уже ждут держателя. Осталось дословно: имя функции гейта, разбор и текст находки. Изменилось: пакет-производитель узнаётся ОДНОЙ величиной (каталог = хвост импорта: у самостоятельного модуля службы расхождения, из-за которого монорепо держало ДВЕ константы, больше нет), обход — от корня СВОЕГО модуля, без сегмента `services/iam`.
Предмет ¶
Утверждение вида «у каждой строки зеркала есть цепь предков» — квантор по всему множеству. Если множество наполнила сама проба прямой записью в таблицу, утверждается свойство ФИКСТУРЫ: она положила ровно то, что потом пересчитала. Такая проба остаётся зелёной, даже если производитель перестал писать цепь ЦЕЛИКОМ.
Единица суждения — ПАКЕТ, а не файл ¶
В Go все `_test.go` каталога с одним именем пакета собираются в один бинарь и делят помощников. Проба, сеющая через помощника из соседнего файла, сеет через производителя ровно так же.
Разбор идёт по СТРОКОВЫМ ЛИТЕРАЛАМ, а не по тексту файла ¶
Текстовый поиск нашёл бы обе примеет и в комментарии, объясняющем эту же дисциплину (в том числе в шапке самой пробы полноты).
client_expiry_immutable.go — разбор операторов правки, разложенных по столбцам (приёмка F2, §9.4, решение §2.10).
Порт с монорепо (`internal/repohygiene/clientexpiryimmutable.go`, снят вынесением службы — `kacho#2597` с заявлением «снято вместе с предметом: таблицы user_oauth_clients в применённых миграциях дерева нет». Заявление было верно ТОЛЬКО для монорепо (там дерево служб доступа исчезло целиком) — в дереве службы обе таблицы объявлены (сегодня — в консолидированной `internal/migrations/0001_initial.sql`), с колонкой `expires_at`. Осталось дословно: имя функции гейта, сам разбор и текст находки. Изменилось: пути без префикса `services/iam/`.
Предмет ¶
Срок клиента неизменяем после создания. На этой предпосылке стоит структурная гарантия: срок выданного токена не превышает остатка срока клиента, и проверять это на пути запроса не нужно ровно потому, что срок не двигается. Сдвинь его — и гарантия держится ничем.
Что здесь считается ПРАВКОЙ СТОЛБЦА ¶
UPDATE t SET expires_at = $2 WHERE id = $1 ← правка: столбец назван в SET INSERT INTO t (…, expires_at) VALUES (…) ← СОЗДАНИЕ: срок назначается SELECT expires_at FROM t WHERE id = $1 ← чтение
Чего разбор НЕ видит — названо, а не спрятано ¶
- оператор, собранный из частей во время выполнения;
- правка через функцию базы или триггер, а не оператором `UPDATE`;
- `UPDATE` без имени таблицы в том же литерале.
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-функции, и этот гейт её не судит.
injection_named_exists.go — разбор: доказательство способности упасть, НАЗВАННОЕ пробой, обязано существовать (#2479).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Проба, чья шапка говорит «способность упасть доказана инъекцией — такой-то файл», делает утверждение о ДЕРЕВЕ. Утверждение это не компилируется и никем не сверяется: файл переименовали, унесли вместе с рефакторингом либо не написали вовсе — а шапка продолжает обещать доказательство. Гейт, потерявший способность краснеть, на чистом дереве выглядит РОВНО ТАК ЖЕ, как исправный, поэтому обещание доказательства читается как само доказательство.
Замер, из которого разбор выведен: на ревизии заведения упоминаний в комментариях было 122, не резолвилось ОДНО — шапка гейта осей адреса называла файл, которого в дереве не было с первого её дня.
───────────────────────────────────────────────────────────────────────────── У ЭТОГО РАЗБОРА ЕСТЬ БЛИЗНЕЦ В ПЛАТФОРМЕ — И ЭТО НАЗВАНО, А НЕ УМОЛЧАНО
Тот же разбор, поднятый до корня МОНОРЕПО, живёт в `tools/injectionproofgate` (задача #2519): этот обходит корень своего модуля и о платформе не высказывается — в самостоятельном клоне службы монорепо нет вовсе. Обещания соседних модулей платформы этому модулю не принадлежат.
Свести обе реализации в одну сегодня НЕЛЬЗЯ: модуль службы пинит платформу псевдоверсией, поэтому импортировать пакет, которого в пинованной ревизии ещё нет, он не может. Предикат сведения: пин указывает на ревизию, где тот пакет существует; до этого две реализации об одном предмете живут рядом осознанно.
───────────────────────────────────────────────────────────────────────────── СУДЯТСЯ КОММЕНТАРИИ, И ЭТО РЕШЕНИЕ, А НЕ УПРОЩЕНИЕ
Координата доказательства пишется ПРОЗОЙ — это её законное место, и разбор читает разобранные группы комментариев, а не сырой текст файла. Строковые литералы намеренно НЕ судятся: в них живут синтетические имена, которые инъекции кладут во временные каталоги, и дерева они не называют вовсе. Судить их значило бы краснеть на чужой фикстуре — то есть на собственном доказательстве.
Величина «в строках» всё равно печатается переписью: молчание о целом виде вхождений неотличимо от их отсутствия.
───────────────────────────────────────────────────────────────────────────── ЗАКОННЫХ ФОРМ КООРДИНАТЫ ТРИ, И РАСПОЗНАВАТЕЛЬ ЗНАЕТ ВСЕ ТРИ
Форма, о которой он не знает, даёт не красное и не зелёное, а МОЛЧАНИЕ. Измерено на этом дереве: наивный резолвер («имя рядом с называющим») дал 4 непопадания из 138, и все четыре оказались ЗАКОННЫМИ формами, а не находками.
СОСЕД `<имя>_injection_test.go` — файл в каталоге называющего;
ПО МОДУЛЮ то же имя, но доказательство лежит в ДРУГОМ пакете модуля
(проба одного пакета ссылается на инъекцию соседнего);
КООРДИНАТОЙ `internal/<пакет>/<имя>_injection_test.go` — путь от корня
МОДУЛЯ службы, а не от корня монорепо: в самостоятельном клоне
приставки `services/iam/` нет, и счёт от неё указывал бы наружу
дерева.
Имя в примерах — ОБРАЗЕЦ с угловыми скобками, а не координата, и это не подгонка текста под инструмент: координата, названная в прозе, есть утверждение о дереве, и выдуманная — ложное. Разбор судит объявленные координаты, поэтому пример обязан не выглядеть ею.
module_identity_seeded_only_by_baseline.go — личность модуля заводит ТОЛЬКО применённая базовая миграция (ПР-5 приёмки WIRE-1, задача продукта #2098).
Порт с монорепо (`internal/repohygiene/moduleidentityseededonlybythebaseline_test.go`, снят вынесением службы — `kacho#2597`). В монорепо предикат жил ЦЕЛИКОМ внутри `_test.go` (пакет-«внешний тест», без отдельного `.go`); здесь он вынесен в не-тестовый файл, потому что кроме гейта его читает пересчёт.
ПРЕДМЕТ (дословно из монорепо) ¶
Личности модулей посеяны БАЗОВОЙ миграцией, то есть приезжают и в установку, где платформы нет вовсе. Строка, которую арендатор, развернувший службу доступа отдельно, нести не обязан, — это данные окружения, и в миграцию они не идут ни при каких условиях (`data-integrity.md` §«Данные СТЕНДА заводятся посевом»).
СОСТОЯНИЕ НА ДЕНЬ ПЕРЕНОСА — ДРУГОЕ, чем в монорепо, и это названо числом ¶
В монорепо (на день заведения гейта) долг был НЕПОДВИЖЕН: применителя у раздела `seed` манифеста не было, применённую миграцию не поправить (ban #5), а свежая установка без платформы несла пять личностей чужого продукта.
В kaname этот долг ЗАКРЫТ отдельной задачей — #2452 (`20260909202745_module_identities_leave_the_baseline.sql`, применена ДО выноса службы из монорепо, то есть закрытие произошло в исходном дереве, а не в этом порту): пять личностей (`kacho-vpc`, `kacho-compute`, `kacho-nlb`, `kacho-registry`, `kacho-storage`) СНЯТЫ этой миграцией, а применитель заведён (`internal/apps/kaname/moduleseed`), позван из композиционного корня. Остаются ДВЕ: `kacho-bootstrap-admin` (личность самой службы, не модульная — `IsModule()` false) и `kacho-api-gateway` (модульная, остаток, названный вслух в шапке миграции — у края манифеста нет вовсе, применителя заводить некому, снимается вместе со своим производителем).
Обе остаются посеянными БАЗОВОЙ миграцией (`0001_initial.sql`, первой в порядке применения) — то есть `moduleIdentitiesSeededOutsideTheBaseline` сегодня находит ноль нарушений. Это НЕ делает гейт вакуумным: он и дальше судит регресс — появление НОВОЙ миграции, сеющей модульную личность НЕ через применитель (ровно тот класс, который #2452 только что убрал). Обновлять эту прозу нормой `#2098` больше не нужно: предмет её первой половины («свежая установка без платформы несёт ноль модульных СА, кроме остатка api-gateway») закрывает #2452, а не этот гейт; гейт стережёт РОСТ.
РОДСТВО, КОТОРОЕ НАДО НАЗВАТЬ — И РАЗЛИЧИЕ (дословно из монорепо) ¶
У ролей модуля такой судья есть отдельным семейством (Г2, `migrationnotawriterofmodulerole`, НЕ входит в этот батч) — запрещает миграции писать роль модуля, у которого есть манифест, ПОЛНОСТЬЮ (у ролей применитель есть). У личностей применитель тоже теперь есть — но не для ВСЕХ (api-gateway — остаток), поэтому запрет здесь остаётся УЗКИМ: не «личность модуля не сеет никакая миграция», а «личность модуля не сеет НИКАКАЯ МИГРАЦИЯ КРОМЕ БАЗОВОЙ» — тот же периметр, что был в монорепо.
ЧЕГО ГЕЙТ НЕ ЛОВИТ (названо, чтобы на него не сослались шире предмета) ¶
Он про ПОСЕВ, а не про живую базу: строку, заведённую не миграцией, он не читает by construction. И он ничего не утверждает о ПОЛНОТЕ посева.
named_verb_form_expiry.go — разбор ПАРЫ: отвергается ли поимённая форма права роли прод-кодом манифеста и есть ли в дереве пробы шести сценариев её полноты. Находка — ровно одно их сочетание: форма принята, полнота не проверяется.
Порт с монорепо (`internal/repohygiene/namedverbformexpiry.go`, снят вынесением службы — `kacho#2597`). Изменилось: пакет (`repohygiene` → `check`), путь домена (`services/iam/internal/manifest/` → `internal/manifest/`, префикс `services/iam/` снят — в kaname код службы лежит от корня репозитория). Осталось дословно: разбор узла (не подстроки), закрытый перечень шести сценариев, различение двух законных причин молчания.
Почему этот перенос ОБЯЗАТЕЛЕН, а не факультативен ¶
Прод-код `internal/manifest/roleexport/check.go` (написанный ДО выноса службы, когда `internal/repohygiene` был тем же репозиторием) буквально называет держателя: «ЧЕМ ДЕРЖИТСЯ ЗАПРЕТ ... гейтом дерева `internal/repohygiene` `TestNamedVerbFormReturnsOnlyWithItsCompletenessCheck`». До этого файла держателя в дереве kaname не было ни одного: цитата утверждала присутствие проверки, которой не существует.
Предмет — ПАРА, а не любая её половина (дословно из монорепо) ¶
Принять перечень ИМЁН, не умея проверить его полноту по классу, значит свести его к классу МОЛЧА и выдать право ШИРЕ просимого (замер приёмки: 55 вхождений из 92 в черновике vpc совпадают с именем класса). Молчание гейта законно ПО ДВУМ причинам, и различать их вызывающему не нужно: форма отвергается сентинелом (возвратов > 0) ЛИБО она вернулась вместе со своей проверкой (все шесть проб MOD-RL найдены).
Замер на дне переноса (kaname@issue-2597, kacho#2597) ¶
Сентинел `ErrRoleRuleVerbsRetired` в `internal/manifest/` не объявлен и не возвращается (задача #1844 сняла его вместе с формой, которую он отвергал — `f5bb097046` в истории монорепо). Все шесть проб MOD-RL (04, 04a, 18, 18a, 19, 19a) в дереве ЕСТЬ (`internal/manifest/rolenamedverbs_test.go`, `internal/manifest/roleexport/namedverbs_test.go`). Гейт сегодня молчит по ВТОРОЙ законной причине — форма вернулась вместе со своей проверкой, ровно как того требует приёмка #1844, — а не по первой. Это и есть содержание переноса: без держателя регресс (снятие одной из шести проб при живом возврате перечня имён) не был бы замечен НИЧЕМ.
Чего разбор НЕ видит — названо, а не спрятано (дословно из монорепо) ¶
Возврат сентинела, собранный в рантайме (через переменную, через таблицу видов). Такой формы в этом пакете нет, и появись она — гейт увидит ноль возвратов и покраснеет, то есть ошибётся В СТОРОНУ находки, а не молчания.
role_operation_response_state.go — анализатор «ответ операции над ролью не несёт вычисленного состояния, и это ОБЕСПЕЧЕНО, а не совпало».
Порт с монорепо (`internal/repohygiene/roleoperationresponsestate.go`, снят вынесением службы — `kacho#2597`). Дословно: весь анализатор. Изменилось: пакет (`repohygiene` → `check`); `ServiceRoot` теперь пустая строка у вызывающего — в kaname дерево службы лежит от корня, а не под `services/iam`.
Предмет ¶
Контракт роли обещает арендатору буквально следующее: нулевое значение `health` и `lifecycle` означает «ЭТИМ ОТВЕТОМ НЕ ВЫЧИСЛЕНО» и никогда «роль здорова» либо «роль объявлена»; его несут ответы операций `Create`/`Update`, а `Get` и `List` заполняют состояние всегда.
Обещание держится ТОЛЬКО ТЕМ, что производителя вычисленного состояния никто не звал на пути мутации. Свойство «by construction» тем и плохо, что его снятие ТИХОЕ.
Что судится ¶
ПЕРЕВОДЧИК ответа операции над ролью — не-тестовая функция, у которой (а) результаты ровно `(*anypb.Any, error)`, (б) есть параметр типа `domain.Role` и (в) в теле стоит вызов перевода `dto.Transfer`. Каждый такой переводчик обязан звать проекцию (`domain.Role.WithoutComputedState`). Не зовёт — находка с координатой.
ЧЕГО ОН НЕ СУДИТ ¶
- ПОЛНОТУ набора производных полей — предмет пробы самой проекции;
- ЛИШНЮЮ РАБОТУ — расход без последствий для контракта;
- ЧТЕНИЯ (`Get`/`List`) — у них результат не `(*anypb.Any, error)`.
Падает на ПУСТОМ ОБХОДЕ ¶
Ноль прочитанных файлов, ноль разобранных функций либо ноль найденных переводчиков роли — «находок ноль» неотличимо от «прочитано ноль».
role_scope_chain_stays_empty.go — САМОИСТЕКАЮЩИЙ гейт решения «меточную ось сужать НЕ НАДО» (задача продукта #1913, приёмка `docs/engineering/acceptance/role-withdrawal-has-a-producer.md` §2.8, §10 шаг 8).
Порт с монорепо (`internal/repohygiene/rolescopechainstaysempty.go`, снят вынесением службы — `kacho#2597`). Дословно: весь предикат, распознаватели, закрытый перечень ярусных источников. Изменилось: пакет (`repohygiene` → `check`), путь-приставка обхода (`services/iam/` снята — в kaname код службы лежит от корня).
Что здесь стережётся — ФАКТ О ДЕРЕВЕ, на котором стоит решение ¶
Приёмка решила НЕ сужать меточную ось выдачи по живости роли, и решение стоит целиком на одном факте: у роли МОДУЛЯ цепь областей ПУСТА, поэтому меточная выдача не достаёт её ни живую, ни снятую. Факт измерен и верен сегодня — и НЕ ЗАЩИЩЁН НИЧЕМ:
- роль модуля всегда кластерного яруса, потому что `owner_module` и `cluster_id` пишет ОДИН оператор, а не ограничение схемы;
- у роли кластерного яруса цепь пуста, потому что ни одна ветвь производителя звеньев её не отбирает: ветви берут `account_id` и `project_id`, а у роли модуля они пусты оба.
Значит производителя звена для `iam_role` может завести любая соседняя работа. Появится он — решение §2.8 станет неверным, а доступ вернётся МОЛЧА. Этот гейт и есть то единственное, что об этом скажет.
ЧТО СЧИТАЕТСЯ НАХОДКОЙ — ИСТОЧНИК ветви, а не имя типа ¶
Ветвей, производящих звено для `iam_role`, две, и обе ЗАКОННЫ:
(5a) роль АККАУНТА → источник `account_id` (5b) роль ПРОЕКТА → источник `project_id`
Находка — ТРЕТЬЯ ветвь: та, что производит звено для `iam_role`, не спрашивая ни одного из двух ярусных столбцов.
ЧЕГО РАЗБОР НЕ ВИДИТ — НАЗВАНО, А НЕ СПРЯТАНО ¶
- звено, приехавшее ЗЕРКАЛОМ ресурса (writer одинаков для всех типов);
- запрос, собранный из кусков в рантайме;
- производителя вне дерева kaname.
role_verb_projection_sole_writer.go — разбор операторов записи в проекции роли: «кто АВТОРУЕТ строку, кто её СНИМАЕТ, переселяет ли снимающий-не-автор снятое» (порт с монорепо `internal/repohygiene/roleverbsolewriter_test.go`, держатель `TestIAMRV112_RoleVerbProjectionHasASoleWriter`, снят вынесением службы доступа — `kacho#2597`).
Предмет ¶
Таблицы `kaname.role_verb` и `kaname.role_rule_ref` — проекции роли, то, из чего цепь вердикта собирает ответ «разрешено ли действие». Класс, ради которого гейт заведён: ДВЕ реализации знают, что такое законная строка, и расходятся МОЛЧА — обе компилируются, у обеих есть пробы, и различаются они только на входе, который ни одна проба не подаёт.
Единица — «авторует», а не «пишет» (решение kacho#1034, перенесено дословно) ¶
Что такое законная строка, объявляет ТОЛЬКО `INSERT`: он называет колонки и значения. `DELETE`/`UPDATE` строку не авторуют — они её снимают или правят. Значит класс живёт в АВТОРСТВЕ, а не в записи вообще, и единица гейта — функция, ВНОСЯЩАЯ строку. Снимающий не-автор обязан ПЕРЕСЕЛИТЬ снятое в `kaname.role_grant_orphan` ТЕМ ЖЕ оператором — иначе отобранное право неотличимо от никогда не выданного.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь-константа слоя (без префикса `services/iam/` — код лежит от корня модуля kaname), обход дерева (`gitenv`+`git ls-files` вручную → `github.com/PRO-Robotech/kacho/pkg/treecorpus` и `internal/testsupport/platformtree.RequireCorpus`, потому что предмет — внутри службы, дерева платформы модулю не нужно). Осталось дословно: имена таблиц-проекций, форма распознавателя (узел-литерал разобранного AST, а не текст файла), три оси проверки (авторство · переселение · слой) и имя держателя `TestIAMRV112_RoleVerbProjectionHasASoleWriter` — на нём стоят цитаты `docs/engineering/acceptance/role-verb-projection-sole-writer.md`, `rule-segments-have-a-referent.md` и `module-manifest-roles-and-seed-grants.md`, написанные ДО выноса, когда `internal/repohygiene` был тем же репозиторием.
Граница названа, а не умолчана ¶
Гейт читает СТРОКОВЫЕ ЛИТЕРАЛЫ непроверочного кода Go, разобранного в дерево, и приписывает находку объемлющей функции. Он НЕ видит: SQL миграций (там запись законна — миграция и есть схема), проб (им положено готовить состояние), имя таблицы, собранное из кусков (слепая зона, предикатом по подстроке не ловится ничем).
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` этого агента — предмета оно судит компоненты дерева, отдельная от «когда посеяно» ось). Держать разбор внутри теста значило бы, что следующий перенос его продублирует, не заметив: инструкция переноса прямо требует проверить, не появился ли общий помощник, и переиспользовать его — вместо копии.
system_role_row_is_never_deleted.go — разбор прод-кода kaname на предмет удаления строки СИСТЕМНОЙ роли (порт с монорепо `internal/repohygiene/systemrolerowisneverdeleted.go`, снят вынесением службы доступа — `kacho#2597`; решение `docs/engineering/architecture/role-withdrawal-is-a-mark.md`, задача продукта #1913).
Предмет ¶
Роль, объявленная манифестом модуля, системная BY CONSTRUCTION: применитель ставит `IsSystem: true`, а `roles.is_system` вычисляется из `cluster_id`. Значит вопрос «как снять роль модуля» есть вопрос «что делает прод-код со строкой системной роли», и у него два взаимоисключающих ответа: удалить строку либо пометить её снятой. Линия выбрала ВТОРОЙ:
- **роль в работе не удалится вовсе.** Выдачи ссылаются на роль ключом `access_bindings_role_fk … ON DELETE RESTRICT`; удаление роли, за которой стоит хоть одна строка выдачи, отвергается `SQLSTATE 23503`;
- **если бы не отвергалось — три проекции уехали бы МОЛЧА**: селекторы правил, проекция глаголов и проекция объявленных сегментов;
- **отзыв перестал бы достигать ПРЕДЪЯВЛЕНИЯ наблюдаемо.** У снятой пометкой строки есть что читать на пути запроса; у удалённой читать нечего.
Что здесь считается находкой — ОДНА ось, и она про оператор ¶
Оператор `DELETE` над таблицей `roles`, не сужённый на ПОЛЬЗОВАТЕЛЬСКУЮ роль. Сужение опознаётся в ДВУХ законных написаниях: `is_system = false` (и `NOT is_system`) — прямо по вычисляемой колонке; `cluster_id IS NULL` — по кластерному якорю, из которого она и вычисляется.
Ось судит СТРОКОВЫЙ ЛИТЕРАЛ узла разбора, а не текст файла: слово `DELETE` стоит и в комментариях, объясняющих сам запрет. Оператор отличается от ПРОЗЫ, цитирующей оператор, по ПРОДОЛЖЕНИЮ за именем таблицы (`WHERE`, `RETURNING`, `USING`, `;`, конец литерала) — привязки к началу строки недостаточно.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь-константа (`iamGoPrefix = "services/iam/"` → обход всего дерева модуля без префикса, код лежит от корня). Осталось дословно: обе регулярки сужения и продолжения, форма распознавателя (`ScanRoleDeletes`), имя держателя `TestSystemRoleRowIsNeverDeleted`.
Чего разбор НЕ видит — названо, а не спрятано ¶
- **миграции.** Каждая снимала роль удалением до решения — это СТАТУС-КВО, который решение и заменяет, а не находка сегодняшнего дерева;
- **каскад по чужому ключу.** Строка роли уезжает вместе со своим ярусом (аккаунт, проект). Для СИСТЕМНОЙ роли ярус — кластер;
- **запрос, собранный из кусков в рантайме** либо приехавший параметром.
token_claim_foreign_brand.go — разбор ИМЁН КЛЕЙМ выпущенного токена: не называет ли клеймо, которое читает предъявитель токена БЕЗ нашего исходного кода, чужой платформенный бренд (порт, СУЖЕННЫЙ ДО ОСИ А, с монорепо `internal/repohygiene/tokenclaimforeignbrand.go`, снят вынесением службы доступа — `kacho#2597`; задача продукта #2127, семейство приёмки IAM-SEV-NAME-05).
Предмет ¶
Служба — самостоятельный продукт, ставящийся в чужом облаке. Норма разделения (решение владельца, kacho#2076): продукт наследует КОД, но не ИМЯ. Имя клейма читается оператором чужого облака без нашего исходного кода — достаточно раскодировать токен, — поэтому приставка имени клейма есть идентичность, а не код. Свой словарь — `kaname_`; чужой, платформенный — `kacho_`. `internal/domain/principal_claims.go` уже несёт три клейма формы `kaname_*` — предмет живой, не гипотетический.
Что здесь ПОРТИРОВАНО (ось А), а что НЕТ (ось Б) — сказано прямо ¶
Монорепошный предок судил ДВЕ оси: А — имя клейма принадлежит своему словарю; Б — у имени из своего словаря нет двойника в чужом словаре НИГДЕ в отслеживаемом дереве, включая не-Go текст (посевные наборы, профиль развёртывания, собранные коллекции проб, клиентская страница). Здесь перенесена ТОЛЬКО ось А — разбор Go-кода по четырём позициям чеканки и чтения. Ось Б требует единого свода дерева kaname И его нынешних потребителей (документация арендатора, коллекции проб), который на дату переноса не собран в одном месте; расширение до неё — отдельная работа, не сделанная здесь умышленно, а не забытая молча.
Позиции, которые СУДЯТСЯ (перенесены дословно) ¶
claims := map[string]any{"kacho_user_id": …} ← ключ состава
pt, _ := claims["kacho_principal_type"].(string) ← чтение по имени
case "kacho_mfa_at": ← разбор по имени
verifiedClaim(vt, "kacho_principal_type") ← имя передано вызовом
Чего разбор НЕ видит — названо, а не спрятано ¶
- имя клейма, собранное из частей либо взятое переменной;
- приставка, отданная предикату (`strings.HasPrefix(k, "kacho_")`) — ось Б предка ловила и её; здесь эта форма вне наблюдения;
- не-Go текст.
token_claim_single_source.go — разбор мест, СОБИРАЮЩИХ состав утверждений выданного токена (порт с монорепо `internal/repohygiene/tokenclaimsinglesource.go`, снят вынесением службы доступа — `kacho#2597`; приёмка F2, сценарий F2-42, §2.11).
Предмет ¶
Токен принципалу выдают ДВА пути: обратный вызов прежнего провайдера, пока он жив, и собственный эндпоинт (`internal/service/token_enrichment_own_lane.go`). Пока перечень утверждений и правила их вычисления живут у каждого свои, различие между ними НЕ ЯВЛЯЕТСЯ НИЧЬЕЙ НАХОДКОЙ: оно не выражено и потому не может покраснеть. Первая же правка одной стороны разойдётся с другой молча — у ПРИНЦИПАЛА, чей токен выдан не тем путём.
Что здесь считается СБОРКОЙ, а что ПОТРЕБЛЕНИЕМ ¶
claims := map[string]any{"kaname_user_id": …, "kaname_account_id": …} ← СБОРКА
return s.userTokenClaims(row, user, subject, hookCtx) ← потребление
Потребителей должно быть МНОГО — они и есть цель: второй способ дойти до той же сборки, а не второй состав. Находкой является ВТОРАЯ СБОРКА.
Почему судится ИМЯ КЛЮЧА, а не тип отображения ¶
Предмет — СЛОВАРЬ утверждений, поэтому место опознаётся по именам ключей, а тип значений в счёт не идёт.
Почему порог по числу ключей, а не «хоть один» ¶
Префикс утверждений встречается и вне состава — им же названы метрики и поля контекста. Место, назвавшее один ключ, состава не объявляет.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь-константа владельца (без префикса `services/iam/`). Осталось дословно: обе функции разбора, форма узла (составной литерал `map[string]…`, узел вызова), имя держателя `TestTokenClaimsAreAssembledInOnePlace`.
Чего разбор НЕ видит — названо, а не спрятано ¶
- состав, собранный присваиваниями по одному ключу за раз;
- имя ключа, собранное из частей или взятое переменной;
- состав, объявленный в чужом языке.
withdrawal_producer_arrives_with_the_applier.go — разбор прод-дерева на СОГЛАСИЕ двух фактов: применитель ролей модуля приводится в действие, и производитель отзыва роли существует (порт с монорепо `internal/repohygiene/withdrawalproducerarriveswiththeapplier.go`, снят вынесением службы доступа — `kacho#2597`; задача продукта #1913).
Предмет ¶
Сверка `moduleroles.Reconcile` объявляет вид расхождения `LiveNotDeclared` — «строка живёт, объявления у неё больше нет». Пока применитель НЕ приводится в действие в проде, отсутствие производителя снятия — остаток, а не дефект. Как только применитель начинают звать (`cmd/kaname/serve.go`, `moduleroles.NewApplier`, задача #1034/#2010 — В KANAME ЭТО УЖЕ ПРОИЗОШЛО), остаток становится дефектом, необратимым ДЛЯ АРЕНДАТОРА: роль, которую нельзя снять, живёт вечно, и право, выданное через неё, продолжает действовать после того, как модуль перестал её объявлять.
Что здесь считается находкой — ОДНО согласие, а не два запрета ¶
Находка — состояние «применитель приводится в действие, производителя отзыва нет». Ни одна половина по отдельности находкой не является:
приводится в действие · производитель есть → норма, работа сделана приводится в действие · производителя нет → НАХОДКА не приводится · производителя нет → остаток не приводится · производитель есть → норма, производитель приехал раньше
Обе половины судятся по УЗЛУ РАЗБОРА, а не по слову ¶
«Применитель приводится в действие» — это ВЫЗОВ через импортированный пакет, а не упоминание его имени. «Производитель отзыва» — это оператор ЗАПИСИ над `roles`, ставящий пометку снятия В СПИСКЕ ПРИСВОЕНИЙ.
Что изменилось при переносе, а что осталось дословно ¶
Изменилось: пакет (`repohygiene` → `check`), путь импорта применителя (без `services/iam/` — код лежит от корня модуля kaname: путь становится `github.com/PRO-Robotech/kaname/internal/apps/kaname/moduleroles`). Осталось дословно: обе регулярки, форма связывания импорта (по псевдониму, а не по последнему сегменту пути), различение узла разбора и узла-прозы, имя держателя `TestWithdrawalProducerArrivesWithTheApplier`.
Чего разбор НЕ видит — названо, а не спрятано ¶
- миграцию как производителя (запрещена отдельным гейтом её же смысла);
- производителя вне дерева модуля;
- запрос, собранный из кусков в рантайме.
Index ¶
- Constants
- Variables
- func AcceptanceDocsOfTree(root string) (map[string]string, error)
- func AdjudicateCarriedLedger(ledgerPath string, rows []CarriedLedgerRow, ...) []string
- func ApplierPortVerbDeletesTheRoleRow(name string) (bool, string)
- func AuditAcceptanceEditsAfterVerdict(root, dir string) ([]AcceptanceEditFinding, AcceptanceEditCensus, error)
- func AuditNamedInjections(root string) ([]InjectionFinding, InjectionCensus, error)
- 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 ConstStringValue(src []byte, name string) (string, bool, error)
- func DeclaredProbesOfTree(root string) ([]string, error)
- func ExecutableRunBodies(raw string) ([]string, int, error)
- func FoldSeededServiceAccounts(ordered []string, bodies map[string]string) (alive map[string]SeededServiceAccount, unknownForms []string, stmtsTouched int)
- func InvocationsOf(script string, bodies []string) int
- func IsGeneratedFile(f *ast.File) bool
- func JudgeCensusFixtures(byDir map[string][]CensusFileFacts) []string
- func MakefileDeclaresTarget(makefile, target string) bool
- func MissingScenarioProbes(funcNames []string) []string
- func ModuleIdentitiesSeededOutsideTheBaseline(alive map[string]SeededServiceAccount, baseline string) []string
- func NamedVerbFormFinding(sentinelReturns int, probeNames []string) []string
- func OwnHomeOfTree(root string) (string, error)
- func ParseCarriedCoordinateLedger(body string) ([]CarriedLedgerRow, map[string]CarriedLedgerSection, CarriedLedgerCensus)
- func ProbeCoordinateResolves(name string, declared []string) bool
- func ProdGoRoots(root string, tracked []string) ([]string, error)
- func RemovalVerbsOf(table string) []string
- func SQLCreateTableBody(upSection, table string) string
- func ScanApplierDeletes(path string, src []byte) (sites []ApplierDeleteSite, census ApplierDeleteCensus, err error)
- func ScanCatalogWriteLocking(files []CatalogSource) ([]CatalogWriteFinding, CatalogWriteCensus, error)
- func ScanClaimAssemblies(path string, src []byte, prefix string, minKeys int) ([]ClaimAssembly, ClaimAssemblyCensus, error)
- func ScanClaimBuilderCalls(path string, src []byte, builders map[string]bool) ([]ClaimBuilderCall, ClaimAssemblyCensus, error)
- func ScanDerivedIDDeclarations(path string, src []byte) (sites []DerivedIDImportSite, census DerivedIDCensus, err error)
- func ScanFixedRefusalTexts(root string, files []string) (RefusalTextCensus, []RefusalTextFinding, error)
- func ScanRoleDeletes(path string, src []byte) (sites []RoleDeleteSite, census RoleDeleteCensus, err error)
- func ScanRoleScopeChain(path, src string) (found []RoleScopeChainSite, census RoleScopeChainCensus)
- func ScanRoleWithdrawalWiring(path string, src []byte) (drive, mark []RoleWithdrawalSite, census RoleWithdrawalCensus, err error)
- func ScanSQLUpdates(path string, src []byte, tables []string) ([]SQLUpdate, SQLUpdateCensus, error)
- func ScanTokenClaimForeignBrand(path string, src []byte) ([]TokenClaimUse, TokenClaimCensus, error)
- func ScenarioProbeName(scenario string) string
- func SeedScopeUnfit(ordered []string, alive map[string]SeededServiceAccount) string
- func SortedFuncNames(byFunc map[string]FunctionDatabaseCalls) []string
- func TreeModulePath(root string) (string, error)
- type AcceptanceEditCensus
- type AcceptanceEditFinding
- type ApplierDeleteCensus
- type ApplierDeleteSite
- type BoolWrapperCall
- type CarriedLedgerCensus
- type CarriedLedgerRow
- type CarriedLedgerSection
- type CatalogSource
- type CatalogWriteCensus
- type CatalogWriteFinding
- type CensusFileFacts
- type ClaimAssembly
- type ClaimAssemblyCensus
- type ClaimBuilderCall
- type DatabaseCallCensus
- type DatabaseCallSite
- type DeadProbeCoordinate
- type DeleteRevokeCensus
- type DerivedIDCensus
- type DerivedIDImportSite
- type FunctionDatabaseCalls
- type InjectionCensus
- type InjectionFinding
- type ProbeCoordinate
- type ProbeCoordinateCensus
- type RefusalTextCensus
- type RefusalTextFinding
- 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 SeededServiceAccount
- type TokenClaimCensus
- type TokenClaimForm
- type TokenClaimUse
- type VerbFormSentinelCensus
- type WrapperPair
- type WrapperScanReport
Constants ¶
const ( // CarriedOutcomeKept — оставлено как путь к прежнему контуру. ТОЛЬКО этот // исход требует предиката снятия. CarriedOutcomeKept = "оставлено" // CarriedOutcomeRemoved — снято. CarriedOutcomeRemoved = "снято" // CarriedOutcomeRewritten — переписано на наш идентификатор. CarriedOutcomeRewritten = "переписано" // CarriedOutcomeNotSubject — предметом не является. CarriedOutcomeNotSubject = "не предмет" )
Закрытый словарь исходов.
const ( // CensusMirrorTable / CensusEdgeTable — таблицы, чья совместная // упомянутость в ОДНОМ SQL-литерале и есть перепись покрытия: она // спрашивает про рёбра у строк зеркала, то есть квантифицирует по // множеству. CensusMirrorTable = "kaname.resource_mirror" CensusEdgeTable = "kaname.resource_parent_edge" // RawEdgeWriteMarker — прямая запись рёбер в обход производителя. RawEdgeWriteMarker = "INSERT INTO kaname.resource_parent_edge" // EdgeProducerCall — имя экспортированной функции-производителя. EdgeProducerCall = "UpsertTx" // EdgeProducerDir — каталог пакета-производителя, ОТ КОРНЯ своего модуля // (было `services/iam/internal/repo/kaname/pg/resource_mirror`). EdgeProducerDir = "internal/repo/kaname/pg/resource_mirror" // EdgeProducerImport — хвост пути импорта. В самостоятельном модуле // службы совпадает с каталогом (расхождение, из-за которого монорепо // нёс ДВЕ константы, было следствием сегмента `services/iam`, которого // у своего модуля нет). EdgeProducerImport = EdgeProducerDir )
const ( TokenClaimOwnNamespace = "kaname" TokenClaimForeignNamespace = "kacho" )
TokenClaimOwnNamespace / TokenClaimForeignNamespace — свой и чужой словарь.
const CatalogCheckTarget = "check-permission-catalog"
CatalogCheckTarget — имя цели Makefile, СВЕРЯЮЩЕЙ копии и ничего не пишущей. Ровно её обязан звать конвейер.
const CatalogLockKeyIdent = "CatalogLockKey"
CatalogLockKeyIdent — имя константы ключа.
const CatalogLockKeyValue = "kaname.module_catalog"
CatalogLockKeyValue — её значение (принимается и литералом).
const CatalogSyncTarget = "sync-permission-catalog"
CatalogSyncTarget — имя цели Makefile, ПЕРЕПИСЫВАЮЩЕЙ каталог прав из копии края. Ручная операция выпуска: конвейер её звать не вправе.
const DerivedIDPackage = "crypto/md5"
DerivedIDPackage — путь импорта, вычисляющий дайджест.
const 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 WithdrawalApplierImportPath = "github.com/PRO-Robotech/kaname/internal/apps/kaname/moduleroles"
WithdrawalApplierImportPath — пакет применителя ролей модуля.
Variables ¶
var AcceptanceProbeCoordinateExemptions []DeadProbeCoordinate
AcceptanceProbeCoordinateExemptions — ВЕДОМОСТЬ ПУСТА, и это её цель, а не её поломка. Заводя запись — назови номер задачи и предикат снятия в комментарии рядом.
var NamedVerbScenarios = []string{"04", "04a", "18", "18a", "19", "19a"}
NamedVerbScenarios — шесть сценариев, чья проверка полноты и есть содержание отсрочки. Перечень ЗАКРЫТ и выписан: он приезжает из приёмки `#1090`, а не из дерева, и выводить его неоткуда — проб этих сценариев в дереве ноль by construction, то есть вывод из дерева дал бы пустой перечень и гейт, которому нечего требовать.
var ProbeCoordinateHomeShape = regexp.MustCompile(
`^([A-Za-z0-9][A-Za-z0-9._-]*/[A-Za-z0-9][A-Za-z0-9._-]*)(?:@([0-9a-fA-F]{7,40}))?$`)
ProbeCoordinateHomeShape — форма НАЗВАННОГО ДОМА: `<владелец>/<репозиторий>` и, необязательно, `@<ревизия>`. Ревизия — только шестнадцатеричная и не короче семи знаков: короткая или произвольная строка после `@` сделала бы домом любую опечатку.
var ProbeCoordinateShape = regexp.MustCompile(`^(Test|Fuzz|Benchmark|Example)[A-Za-z0-9_]{2,}$`)
ProbeCoordinateShape — форма имени пробы Go. Три знака минимум после вида: голое `Test` резолвилось бы префиксом ко всему дереву.
var RoleProjectionTables = []string{RoleVerbTable, RoleRuleRefTable}
RoleProjectionTables — таблицы, у каждой из которых автор обязан быть один.
var RoleScopeChainTierSources = []string{"account_id", "project_id"}
RoleScopeChainTierSources — ярусные столбцы, из которых звено роли берётся ЗАКОННО. Перечень закрытый и короткий by construction.
Functions ¶
func AcceptanceDocsOfTree ¶ added in v0.2.0
AcceptanceDocsOfTree — приёмки, живущие в каталоге приёмок службы. Перечень ВЫВОДИТСЯ обходом, а не выписывается.
Порт сужен до posture этого дерева: монорепо держало приёмки НЕСКОЛЬКИХ служб под `services/*/docs/engineering/acceptance/`, а самостоятельный клон службы несёт СВОЙ единственный каталог прямо у корня — `docs/engineering/acceptance/`. Сужение измерено, а не предположено: в дереве продукта второго дома приёмок не было никогда (`polyrepo.md` §«У приёмки домов ДВА» — второй дом был именно этот, iam-only).
func AdjudicateCarriedLedger ¶ added in v0.2.0
func AdjudicateCarriedLedger( ledgerPath string, rows []CarriedLedgerRow, sections map[string]CarriedLedgerSection, treeHas func(string) bool, inScope func(string) bool, mustBeNamed []string, ) []string
AdjudicateCarriedLedger — что не так с ведомостью относительно дерева.
treeHas — состав дерева; inScope — координата принадлежит СВОЕМУ репозиторию и подлежит суждению (кросс-репо путь пропускается обеими проверками — ни полнотой, ни самоистечением: этот гейт не может судить чужой репозиторий); mustBeNamed — координаты, которые ведомость обязана назвать.
func 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 AuditNamedInjections ¶
func AuditNamedInjections(root string) ([]InjectionFinding, InjectionCensus, error)
AuditNamedInjections обходит дерево модуля от root и возвращает находки с переписью.
Обращения к пробе здесь нет намеренно: разбор, роняющий её изнутри, инъекции не поддаётся — синтетическому дереву некуда было бы подать вход.
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 ConstStringValue ¶ added in v0.2.0
ConstStringValue — значение строковой константы, объявленной в исходнике.
Возвращает признак находки отдельно от значения: «объявления нет» и «объявлено пустым» — разные состояния, и схлопывать их нельзя.
func DeclaredProbesOfTree ¶ added in v0.2.0
DeclaredProbesOfTree — имена всех проб дерева, объявленных в отслеживаемых файлах проб.
func ExecutableRunBodies ¶ added in v0.2.0
ExecutableRunBodies — тела `run:` без строк оболочечных комментариев.
func FoldSeededServiceAccounts ¶ added in v0.2.0
func FoldSeededServiceAccounts(ordered []string, bodies map[string]string) ( alive map[string]SeededServiceAccount, unknownForms []string, stmtsTouched int, )
FoldSeededServiceAccounts складывает посев по цепочке: вставка заводит строку, удаление её снимает. Возвращает живые строки, находки формы и объём осмотренного.
Формы записи названы ЯВНО, и незнакомая — находка, а не молчание: форма, о которой разбор не знает, уводит предмет из-под наблюдения, ничего не нарушив (`testing.md` §«Гейт на класс» п. 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 InvocationsOf ¶ added in v0.2.0
InvocationsOf — сколько тел `run:` действительно зовут названный скрипт.
func IsGeneratedFile ¶ added in v0.2.0
IsGeneratedFile — узел разбора несёт отметку `Code generated … DO NOT EDIT.`
func JudgeCensusFixtures ¶ added in v0.2.0
func JudgeCensusFixtures(byDir map[string][]CensusFileFacts) []string
JudgeCensusFixtures выносит вердикт по КАТАЛОГАМ: ключ — каталог тестового пакета, значение — факты его файлов.
func MakefileDeclaresTarget ¶ added in v0.2.0
MakefileDeclaresTarget — объявлена ли цель в тексте Makefile.
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 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 ProbeCoordinateResolves ¶ added in v0.2.0
ProbeCoordinateResolves — объявленное имя начинается с координаты. declared обязан быть отсортирован: имя с префиксом P сортируется не раньше P, поэтому кандидат ровно один и находится двоичным поиском.
func ProdGoRoots ¶ added in v0.2.0
ProdGoRoots — верхнеуровневые каталоги дерева, несущие отслеживаемый не-тестовый Go-код. Выведены обходом, а не выписаны.
func RemovalVerbsOf ¶ added in v0.2.0
RemovalVerbsOf — операторы, которыми строка СНИМАЕТСЯ либо правится.
Чтение (`SELECT … FROM`, `JOIN`) в перечень не входит намеренно: читатели у проекции законны и служат близнецом, на котором гейт молчит.
func SQLCreateTableBody ¶ added in v0.2.0
SQLCreateTableBody — тело объявления таблицы, разобранное из НАКАТА (Up-секции без комментариев) миграции. sqlText — полный текст ФАЙЛА миграции (порт зовёт `migrations.MigrationUpSection` сам, чтобы не тянуть зависимость на пакет `migrations` из пакета `check` без нужды — вызывающий подаёт уже подготовленный текст наката).
func ScanApplierDeletes ¶ added in v0.2.0
func ScanApplierDeletes(path string, src []byte) (sites []ApplierDeleteSite, census ApplierDeleteCensus, err error)
ScanApplierDeletes разбирает один файл пакета применителя.
func 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 ScanDerivedIDDeclarations ¶ added in v0.2.0
func ScanDerivedIDDeclarations(path string, src []byte) (sites []DerivedIDImportSite, census DerivedIDCensus, err error)
ScanDerivedIDDeclarations разбирает один файл и возвращает импорты `crypto/md5` вместе с объёмом осмотренного.
func ScanFixedRefusalTexts ¶
func ScanFixedRefusalTexts(root string, files []string) (RefusalTextCensus, []RefusalTextFinding, error)
ScanFixedRefusalTexts разбирает названные файлы и называет конструкции статуса на полосах чужой причины, чей текст не доказан фиксированным.
root служит только для печати координат. Пустой обход ошибкой ЗДЕСЬ не объявляется: пустоту судит вызывающий — у гейта дерева и у пробы инъекции законные пороги пустоты разные.
func ScanRoleDeletes ¶ added in v0.2.0
func ScanRoleDeletes(path string, src []byte) (sites []RoleDeleteSite, census RoleDeleteCensus, err error)
ScanRoleDeletes разбирает один файл Go.
func ScanRoleScopeChain ¶ added in v0.2.0
func ScanRoleScopeChain(path, src string) (found []RoleScopeChainSite, census RoleScopeChainCensus)
ScanRoleScopeChain разбирает один файл — SQL миграции либо прод-исходник Go.
func ScanRoleWithdrawalWiring ¶ added in v0.2.0
func ScanRoleWithdrawalWiring(path string, src []byte) (drive, mark []RoleWithdrawalSite, census RoleWithdrawalCensus, err error)
ScanRoleWithdrawalWiring разбирает один файл Go.
Возвращает две половины раздельно — приведение применителя в действие и производителя отзыва, — потому что находка есть их НЕСОГЛАСИЕ, а не любая из них. Сводит половины вызывающий.
func ScanSQLUpdates ¶ added in v0.2.0
ScanSQLUpdates разбирает один файл и собирает операторы правки названных таблиц.
func ScanTokenClaimForeignBrand ¶ added in v0.2.0
func ScanTokenClaimForeignBrand(path string, src []byte) ([]TokenClaimUse, TokenClaimCensus, error)
ScanTokenClaimForeignBrand разбирает один файл Go и возвращает употребления имени клейма из ЧУЖОГО словаря (namespace == TokenClaimForeignNamespace) в одной из четырёх законных позиций чеканки/чтения.
func ScenarioProbeName ¶ added in v0.2.0
ScenarioProbeName — имя пробы сценария в написании этого дерева.
func SeedScopeUnfit ¶ added in v0.2.0
func SeedScopeUnfit(ordered []string, alive map[string]SeededServiceAccount) string
SeedScopeUnfit — ПРЕДМЕТА нет. Отдельной функцией, а не тремя ветвями внутри пробы: способность гейта отличить «ноль находок» от «ноль прочитанного» проверяется инъекцией, а инъекция не может спросить `require`/`t.Fatalf` напрямую.
func SortedFuncNames ¶ added in v0.2.0
func SortedFuncNames(byFunc map[string]FunctionDatabaseCalls) []string
SortedFuncNames — имена разобранных функций для текста отказа.
func 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
}
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 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 BoolWrapperCall ¶ added in v0.2.0
type BoolWrapperCall struct {
File string
Line int
Pair WrapperPair
}
BoolWrapperCall — одно употребление булевой половины из чужого пакета.
type CarriedLedgerCensus ¶ added in v0.2.0
type CarriedLedgerCensus struct {
Lines int
Sections int
Tables int
Rows int
RowsWithoutCoordinate int
}
CarriedLedgerCensus — объём осмотренного.
type CarriedLedgerRow ¶ added in v0.2.0
type CarriedLedgerRow struct {
Section string
Line int
Coordinate string
Outcome string
OutcomeCell string
}
CarriedLedgerRow — строка ведомости.
type CarriedLedgerSection ¶ added in v0.2.0
CarriedLedgerSection — раздел документа.
type CatalogSource ¶ added in v0.2.0
CatalogSource — один прод-файл на вход разбора. Инъекция подаёт синтетический состав, не трогая рабочую копию.
type CatalogWriteCensus ¶ added in v0.2.0
type CatalogWriteCensus struct {
Files int
Parsed int
Funcs int
Executors int
StringLiterals int
Comments int
TextMatches int
TextFiles int
Executed int
ExecutingFiles int
WriteUnits int
LockedUnits int
LockSites int
}
CatalogWriteCensus — объём осмотренного.
type CatalogWriteFinding ¶ added in v0.2.0
CatalogWriteFinding — координата находки: писатель без замка.
type CensusFileFacts ¶ added in v0.2.0
CensusFileFacts — то, что гейт узнаёт об одном файле.
func CensusFactsOf ¶ added in v0.2.0
func CensusFactsOf(rel string, body []byte, producerPkg string) (CensusFileFacts, error)
CensusFactsOf разбирает один файл. Разбор, а не текст: комментарий, объясняющий эту же дисциплину, производителем не является.
type ClaimAssembly ¶ added in v0.2.0
ClaimAssembly — место, собирающее состав утверждений.
type ClaimAssemblyCensus ¶ added in v0.2.0
type ClaimAssemblyCensus struct {
MapLiterals int
EmptyMapLiterals int
KeyedLiterals int
Calls int
}
ClaimAssemblyCensus — объём осмотренного одним файлом.
type ClaimBuilderCall ¶ added in v0.2.0
ClaimBuilderCall — вызов сборщика состава: чем состав ПОТРЕБЛЯЕТСЯ.
type 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 DeadProbeCoordinate ¶ added in v0.2.0
DeadProbeCoordinate — ПОСЛАБЛЕНИЕ: координата, о которой известно, что она не резолвится, и чей предмет принадлежит ДРУГОМУ кругу приёмки.
Запись заводится ПО ФАКТУ, а не с запасом. Послабление ИСТЕКАЕТ САМО, и оба конца — находка: имя стало резолвиться → исключать нечего; имя больше не стоит ни в одном документе → исключать нечего.
type DeleteRevokeCensus ¶
type DeleteRevokeCensus struct {
Dirs int // каталогов под api/ осмотрено
Files int // не-тестовых файлов Go разобрано
EmitCalls int // вызовов EmitReconcileEvent найдено
OwnTyped int // каталогов, у которых выведен СВОЙ тип
WithDeleteGo int // из них несущих delete.go
Population int // судимых каталогов (свой тип И delete.go)
Satisfying int // из них эмитирующих отзыв своего типа
}
DeleteRevokeCensus — перепись одного обхода. Печатается ВСЕГДА: «ноль находок» обязано быть отличимо от «ноль прочитанного».
func ScanDeleteRevokeProducers ¶
func ScanDeleteRevokeProducers(apiDir string) (DeleteRevokeCensus, []string, error)
ScanDeleteRevokeProducers обходит каталоги use-case под apiDir и называет те, у которых путь снятия собственного объекта остался без производителя отзыва.
Возвращает перепись, находки (по одной на каталог, в порядке имён — отказ на одном и том же дереве читается одинаково от прогона к прогону) и ошибку обхода. Пустой обход ошибкой ЗДЕСЬ не объявляется: пустоту судит вызывающий, потому что у гейта дерева и у пробы инъекции законные пороги пустоты разные.
func (DeleteRevokeCensus) String ¶
func (c DeleteRevokeCensus) String() string
type DerivedIDCensus ¶ added in v0.2.0
type DerivedIDCensus struct {
// Imports — объявлений импорта прочитано.
Imports int
}
DerivedIDCensus — объём осмотренного одним файлом.
type DerivedIDImportSite ¶ added in v0.2.0
type DerivedIDImportSite struct {
File string
Line int
// Form — форма импорта: `plain` · `alias` · `dot` · `blank`. Печатается
// переписью, чтобы «ноль находок» было отличимо от «форму не узнали».
Form string
}
DerivedIDImportSite — координата импорта, вычисляющего MD5.
type FunctionDatabaseCalls ¶ added in v0.2.0
type FunctionDatabaseCalls struct {
Name string
Line int
Calls []DatabaseCallSite
}
FunctionDatabaseCalls — обращения одной функции.
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 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
Findings []string
}
ProbeCoordinateCensus — перепись обхода. «Ноль находок» обязано быть отличимо от «ноль прочитанного», поэтому объём осмотренного — отдельное утверждение.
func JudgeProbeCoordinates ¶ added in v0.2.0
func JudgeProbeCoordinates(docs map[string]string, declared []string, exemptions []DeadProbeCoordinate) ProbeCoordinateCensus
JudgeProbeCoordinates — судящее ядро. Вход подаётся значениями, а не читается из дерева: инъекция обязана уметь дать ему свой вход, не трогая рабочую копию, из которой запущена.
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 RefusalTextFinding ¶
type RefusalTextFinding struct {
File string // путь относительно названного корня
Line int
Code string // Unavailable / Internal
Expr string // выражение текста, как оно записано
}
RefusalTextFinding — одна конструкция, чей текст не доказан фиксированным.
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 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 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 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 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_probe_coordinate.go
- applier_never_deletes.go
- assertion_admission_calls.go
- authz_wrapper_outcome_lanes.go
- basic_credential_proof_run.go
- build_stamp_word.go
- carried_coordinate_ledger.go
- catalog_check_wiring.go
- catalog_seed_parity.go
- catalog_writer_lock.go
- census_fixture_producer.go
- client_expiry_immutable.go
- delete_revoke_producer.go
- derived_id_single_source.go
- injection_named_exists.go
- module_identity_seeded_only_by_baseline.go
- named_verb_form_expiry.go
- refusal_text_is_fixed.go
- role_operation_response_state.go
- role_scope_chain_stays_empty.go
- role_verb_projection_sole_writer.go
- seeded_service_accounts.go
- system_role_row_is_never_deleted.go
- token_claim_foreign_brand.go
- token_claim_single_source.go
- withdrawal_producer_arrives_with_the_applier.go