From d1abf6722630f68fe21eef27524c646ca46070d7 Mon Sep 17 00:00:00 2001 From: Khasbulat Abdullin Date: Mon, 5 Oct 2026 23:41:12 +0300 Subject: [PATCH 1/5] docs(migration): explain default roots and historical archive hashes --- content/docs/migration/easyp-v0.mdx | 29 ++++++++++++++++++++++++-- content/docs/migration/easyp-v0.ru.mdx | 29 ++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/content/docs/migration/easyp-v0.mdx b/content/docs/migration/easyp-v0.mdx index b3073c4..1718a32 100644 --- a/content/docs/migration/easyp-v0.mdx +++ b/content/docs/migration/easyp-v0.mdx @@ -51,7 +51,28 @@ Modified legacy policy and manifest files receive byte-identical .v0.bakwith_imports, and supported managed settings. Relative paths remain relative to the configuration directory. -Legacy direct and indirect requirements are converted to native require directives. The tool checks that whole v1 source roots would select the same local protobuf files with the same import paths. It does not silently expand a sliced input into an entire module. +Legacy direct and indirect requirements are converted to native require directives. The tool proves that local generation keeps the same protobuf files and import paths, using whole roots or exact package selectors. + +## Keep default roots and source locations + +An omitted or empty legacy root means .. Native protobuf.mod has the same default when roots is omitted; there is no need to move proto files into a new directory. + +For example, an input selecting mcp under root . can become the following generation selection when all files in the package are selected: + +~~~yaml +version: v1 +generate: + packages: [mcp.options.v1] +plugins: + - name: go + out: . + opts: + paths: source_relative +~~~ + +Import roots stay unchanged and generated files keep their source-relative paths. The wizard first tries whole-root equality, then infers nonempty package selectors only if they select exactly the same physical files with the same import names. Selecting part of a package, crossing hidden/vendor/nested-module boundaries, or combining an inferred filter with whole-module Git generation inputs remains blocked. The selected sources and fixed selectors are checked again before apply. + +The preview warns that future files declaring a selected package also participate in generation, even outside the old input directory. This support requires an updated v1 nightly; the initial v1.0.0-nightly.20261005.1 rejects directory subsets that need package inference. Variable placeholders are not expanded into saved values. If a placeholder or selector prevents safe analysis, conversion fails rather than persisting credentials or guessing its meaning. @@ -59,11 +80,15 @@ Variable placeholders are not expanded into saved values. If a placeholder or se A full commit SHA is preserved, including a full SHA embedded in an old pseudo-version. For a legacy lock entry containing a tag but no SHA, conversion resolves that tag and verifies the historical installed-tree hash before accepting the revision. A moved tag or mismatched historical hash is an error. +Git's annotated-tag spelling, such as `v0.4.0^{}`, is accepted for a full SemVer tag in the historical lock. The tag, commit and original hash are still verified, and the old lock stays byte-identical. Peeled branches, abbreviated refs, repeated suffixes and pseudo-version-shaped peeled tags are rejected. + +Released v0 installers archived Git's *.proto pathspec and stripped legacy root prefixes before hashing. Migration reproduces that archive at the pinned revision; it also retains verification of the existing whole-tree hash format. Git archive attributes that omit or alter proto files require manual migration because a native checkout would change the contract. + The v1 content hash is then calculated independently over the tracked repository files. Old and new hashes cover different path layouts and cannot be copied or compared as interchangeable values. A missing historical dependency pin is not replaced with current HEAD. ## Explicit limitations -Unknown fields, invalid or multi-document YAML, ambiguous source selection, unsupported references, and conflicting native outputs are rejected. Custom Git-input roots/subdirectories, external or sliced local inputs whose exact selection cannot be preserved, unsafe managed selectors, and full lock conversion with local replacements may require manual migration. Buf configurations are not inputs to this v0 converter. +Invalid known fields, invalid or multi-document YAML, ambiguous source selection, unsupported references, and conflicting native outputs are rejected. Keys ignored by v0 are omitted with warnings and remain in the legacy backup. Custom Git-input roots/subdirectories, external or sliced local inputs whose exact selection cannot be preserved, unsafe managed selectors, and full lock conversion with local replacements may require manual migration. Buf configurations are not inputs to this v0 converter. The command stages all outputs and checks observed inputs again before applying. Ordinary application failures are rolled back. Several file replacements are not one process-crash-atomic transaction: after a machine or process failure, inspect the preserved backups and Git state before continuing. Uncooperative concurrent writers cannot be made safe by this command. diff --git a/content/docs/migration/easyp-v0.ru.mdx b/content/docs/migration/easyp-v0.ru.mdx index 7118b20..6bc2027 100644 --- a/content/docs/migration/easyp-v0.ru.mdx +++ b/content/docs/migration/easyp-v0.ru.mdx @@ -51,7 +51,28 @@ easyp migrate --dir . --module github.com/acme/contracts --resolve-lock --write Сохраняются фактически выбранные lint-правила, исключения, параметры правил и прежняя явная настройка подавления комментариями. Буквальные исключения и префиксные исключения отдельных правил преобразуются в соответствующие правила v1. В генерации сохраняются источники плагинов, argv, options, with_imports и поддерживаемые managed-настройки. Относительные пути остаются привязанными к каталогу конфигурации. -Legacy-требования direct и indirect преобразуются в require. Проверяется, что новые корни целиком выбирают те же локальные protobuf-файлы с теми же import-путями. Выбранная часть каталога не расширяется молча до всего модуля. +Legacy-требования direct и indirect преобразуются в require. Мигратор доказывает, что локальная генерация сохраняет те же protobuf-файлы и import-пути, используя целые корни или точные selectors пакетов. + +## Сохранение корней по умолчанию и расположения исходников + +Пустой или отсутствующий legacy root означает .. В native protobuf.mod действует тот же корень по умолчанию, если roots не указан. Перемещать proto-файлы в новый каталог не требуется. + +Например, input, выбирающий mcp внутри root ., может перейти к следующей выборке генерации, если выбран весь пакет: + +~~~yaml +version: v1 +generate: + packages: [mcp.options.v1] +plugins: + - name: go + out: . + opts: + paths: source_relative +~~~ + +Корни импортов сохраняются, а сгенерированные файлы остаются по прежним source-relative путям. Мастер сначала проверяет совпадение целых корней, затем выводит непустой список selectors пакетов, только если он выбирает точно те же физические файлы с теми же import-именами. Частичная выборка пакета, изменение границ скрытых/vendor/вложенных модулей и сочетание выведенного фильтра с Git-input целого модуля отклоняются. Перед применением проверяются и исходники, и зафиксированные selectors. + +Preview предупреждает: будущие файлы с выбранным protobuf-пакетом тоже участвуют в генерации, даже вне прежнего input-каталога. Эта поддержка требует обновлённого v1 nightly; первый v1.0.0-nightly.20261005.1 отклоняет выборки каталогов, для которых нужен вывод пакетов. Подстановки переменных не сохраняются в раскрытом виде. Если переменная или selector мешает безопасному анализу, перенос останавливается, а не записывает секреты и не угадывает смысл настройки. @@ -59,11 +80,15 @@ Legacy-требования direct и indirect пре Полный SHA коммита сохраняется, в том числе когда он встроен в старую псевдоверсию. Если запись содержит только тег, миграция разрешает его и проверяет исторический хеш установленного дерева перед принятием ревизии. Перенос тега или несовпадение прежнего хеша приводит к ошибке. +Запись аннотированного Git-тега вроде `v0.4.0^{}` допустима для полного SemVer-тега в историческом lock. Тег, commit и исходный хеш по-прежнему проверяются, а старый lock сохраняется побайтово. Peeled-ветки, сокращённые refs, повторные суффиксы и peeled-теги в форме псевдоверсии отклоняются. + +Выпущенные версии v0 архивировали Git-pathspec *.proto и убирали legacy-префиксы корней перед вычислением хеша. Мигратор воспроизводит этот архив в закреплённой ревизии; проверка существующего формата хеша полного дерева тоже сохраняется. Git-атрибуты архива, исключающие или изменяющие proto-файлы, требуют ручной миграции: native checkout изменил бы контракт. + После проверки новый хеш v1 рассчитывается независимо по отслеживаемым файлам репозитория. Старый и новый хеши относятся к разным раскладкам путей; их нельзя просто копировать или считать взаимозаменяемыми. Отсутствующий исторический pin не заменяется текущим HEAD. ## Явные ограничения -Неизвестные поля, некорректный YAML или несколько YAML-документов, неоднозначный набор исходников, неподдерживаемые refs и конфликтующие native-файлы отклоняются. Нестандартные root/sub_directory Git-input, внешние или частичные локальные inputs с непереносимой выборкой, неоднозначные managed selectors и полный перенос lock при локальных заменах могут потребовать ручной миграции. Buf-конфигурация не является входом этого v0-конвертера. +Некорректные значения известных полей, некорректный YAML или несколько YAML-документов, неоднозначный набор исходников, неподдерживаемые refs и конфликтующие native-файлы отклоняются. Ключи, игнорировавшиеся в v0, пропускаются с предупреждениями и сохраняются в legacy-копии. Нестандартные root/sub_directory Git-input, внешние или частичные локальные inputs с непереносимой выборкой, неоднозначные managed selectors и полный перенос lock при локальных заменах могут потребовать ручной миграции. Buf-конфигурация не является входом этого v0-конвертера. Все результаты сначала подготавливаются, затем состояние входов проверяется повторно. Обычные ошибки применения вызывают откат. Несколько замен файлов не образуют общую транзакцию, атомарную при падении процесса или компьютера: после такого сбоя нужно проверить резервные копии и Git-состояние. Команда не гарантирует безопасность при записи файлов посторонними несогласованными процессами. From e3cf0e1cc140f42c3aeb410c4e12a7388eac430e Mon Sep 17 00:00:00 2001 From: Khasbulat Abdullin Date: Tue, 6 Oct 2026 01:23:02 +0300 Subject: [PATCH 2/5] docs(migration): preserve source targets with literal paths --- content/docs/migration/easyp-v0.mdx | 12 +++++++----- content/docs/migration/easyp-v0.ru.mdx | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/content/docs/migration/easyp-v0.mdx b/content/docs/migration/easyp-v0.mdx index 1718a32..c2da1b5 100644 --- a/content/docs/migration/easyp-v0.mdx +++ b/content/docs/migration/easyp-v0.mdx @@ -51,18 +51,18 @@ Modified legacy policy and manifest files receive byte-identical .v0.bakwith_imports, and supported managed settings. Relative paths remain relative to the configuration directory. -Legacy direct and indirect requirements are converted to native require directives. The tool proves that local generation keeps the same protobuf files and import paths, using whole roots or exact package selectors. +Legacy direct and indirect requirements are converted to native require directives. The tool proves that local generation keeps the same protobuf files and import paths, using whole roots, literal generation paths or exact package selectors. ## Keep default roots and source locations An omitted or empty legacy root means .. Native protobuf.mod has the same default when roots is omitted; there is no need to move proto files into a new directory. -For example, an input selecting mcp under root . can become the following generation selection when all files in the package are selected: +For example, an input selecting mcp under root . can become the following generation selection without including copies elsewhere in the repository: ~~~yaml version: v1 generate: - packages: [mcp.options.v1] + paths: [mcp] plugins: - name: go out: . @@ -70,9 +70,11 @@ plugins: paths: source_relative ~~~ -Import roots stay unchanged and generated files keep their source-relative paths. The wizard first tries whole-root equality, then infers nonempty package selectors only if they select exactly the same physical files with the same import names. Selecting part of a package, crossing hidden/vendor/nested-module boundaries, or combining an inferred filter with whole-module Git generation inputs remains blocked. The selected sources and fixed selectors are checked again before apply. +Import roots stay unchanged and generated files keep their source-relative paths. The wizard first tries whole-root equality, then literal directory paths, then complete package selectors for mixed-root cases. Each choice must select exactly the same physical files with the same import names. Paths can preserve part of a package: ignored Gradle build copies outside `mcp` stay out of generation. Hidden/vendor/nested-module boundary changes and inferred local filters mixed with whole-module Git inputs remain blocked. Sources and fixed paths/packages are checked again before apply. -The preview warns that future files declaring a selected package also participate in generation, even outside the old input directory. This support requires an updated v1 nightly; the initial v1.0.0-nightly.20261005.1 rejects directory subsets that need package inference. +`generate.paths` matches literal import-relative files or directory subtrees, with `.` meaning all sources; `mcp` does not select `mcp-copy`. Paths intersect optional package selectors, and every selector must match a resulting source across the selected modules. Unknown selectors fail before plugins or descriptor writes, even without plugins or under `--all`. Required imports outside these paths remain available. These paths are separate from plugin `opts.paths`, which controls output layout. + +Path selection requires an updated v1 build; the initial v1.0.0-nightly.20261005.1 and commit 8be79c7 do not provide it. When migration uses the complete-package fallback, the preview still warns that future files in those packages become targets regardless of their directory. Variable placeholders are not expanded into saved values. If a placeholder or selector prevents safe analysis, conversion fails rather than persisting credentials or guessing its meaning. diff --git a/content/docs/migration/easyp-v0.ru.mdx b/content/docs/migration/easyp-v0.ru.mdx index 6bc2027..fab5078 100644 --- a/content/docs/migration/easyp-v0.ru.mdx +++ b/content/docs/migration/easyp-v0.ru.mdx @@ -51,18 +51,18 @@ easyp migrate --dir . --module github.com/acme/contracts --resolve-lock --write Сохраняются фактически выбранные lint-правила, исключения, параметры правил и прежняя явная настройка подавления комментариями. Буквальные исключения и префиксные исключения отдельных правил преобразуются в соответствующие правила v1. В генерации сохраняются источники плагинов, argv, options, with_imports и поддерживаемые managed-настройки. Относительные пути остаются привязанными к каталогу конфигурации. -Legacy-требования direct и indirect преобразуются в require. Мигратор доказывает, что локальная генерация сохраняет те же protobuf-файлы и import-пути, используя целые корни или точные selectors пакетов. +Legacy-требования direct и indirect преобразуются в require. Мигратор доказывает, что локальная генерация сохраняет те же protobuf-файлы и import-пути, используя целые корни, буквальные пути генерации или точные selectors пакетов. ## Сохранение корней по умолчанию и расположения исходников Пустой или отсутствующий legacy root означает .. В native protobuf.mod действует тот же корень по умолчанию, если roots не указан. Перемещать proto-файлы в новый каталог не требуется. -Например, input, выбирающий mcp внутри root ., может перейти к следующей выборке генерации, если выбран весь пакет: +Например, input, выбирающий mcp внутри root ., может перейти к следующей выборке генерации, не включая копии из других каталогов репозитория: ~~~yaml version: v1 generate: - packages: [mcp.options.v1] + paths: [mcp] plugins: - name: go out: . @@ -70,9 +70,11 @@ plugins: paths: source_relative ~~~ -Корни импортов сохраняются, а сгенерированные файлы остаются по прежним source-relative путям. Мастер сначала проверяет совпадение целых корней, затем выводит непустой список selectors пакетов, только если он выбирает точно те же физические файлы с теми же import-именами. Частичная выборка пакета, изменение границ скрытых/vendor/вложенных модулей и сочетание выведенного фильтра с Git-input целого модуля отклоняются. Перед применением проверяются и исходники, и зафиксированные selectors. +Корни импортов сохраняются, а сгенерированные файлы остаются по прежним source-relative путям. Мастер сначала проверяет совпадение целых корней, затем буквальные пути каталогов, затем selectors полных пакетов для смешанных корней. Каждый вариант должен выбирать точно те же физические файлы с теми же import-именами. Пути позволяют выбрать часть пакета: игнорируемые Gradle-копии вне `mcp` не становятся целями генерации. Изменение границ скрытых/vendor/вложенных модулей и сочетание выведенного локального фильтра с Git-input целого модуля отклоняются. Перед применением проверяются исходники и зафиксированные пути/пакеты. -Preview предупреждает: будущие файлы с выбранным protobuf-пакетом тоже участвуют в генерации, даже вне прежнего input-каталога. Эта поддержка требует обновлённого v1 nightly; первый v1.0.0-nightly.20261005.1 отклоняет выборки каталогов, для которых нужен вывод пакетов. +`generate.paths` выбирает буквальные import-relative пути файлов или поддеревьев каталогов; `.` означает все исходники, а `mcp` не совпадает с `mcp-copy`. Пути пересекаются с необязательными selectors пакетов. Каждый selector должен совпасть с итоговым исходником хотя бы в одном выбранном модуле. Неизвестные selectors отклоняются до запуска плагинов и записи descriptors, в том числе без плагинов или с `--all`. Необходимые импорты вне этих путей остаются доступными. Эти пути отличаются от plugin `opts.paths`, управляющего раскладкой результатов. + +Выборка по путям требует обновлённой сборки v1: первый v1.0.0-nightly.20261005.1 и коммит 8be79c7 её не поддерживают. Если мастер использует fallback по полным пакетам, preview по-прежнему предупреждает, что будущие файлы этих пакетов станут целями независимо от каталога. Подстановки переменных не сохраняются в раскрытом виде. Если переменная или selector мешает безопасному анализу, перенос останавливается, а не записывает секреты и не угадывает смысл настройки. From 3f21e81d1a9ee4c5a12be9b4f33c5b187eeff5b8 Mon Sep 17 00:00:00 2001 From: Khasbulat Abdullin Date: Tue, 6 Oct 2026 02:33:33 +0300 Subject: [PATCH 3/5] docs(migration): describe auxiliary Git link verification --- content/docs/migration/easyp-v0.mdx | 2 ++ content/docs/migration/easyp-v0.ru.mdx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/content/docs/migration/easyp-v0.mdx b/content/docs/migration/easyp-v0.mdx index c2da1b5..411cc35 100644 --- a/content/docs/migration/easyp-v0.mdx +++ b/content/docs/migration/easyp-v0.mdx @@ -88,6 +88,8 @@ Released v0 installers archived Git's *.proto pathspec and stripped The v1 content hash is then calculated independently over the tracked repository files. Old and new hashes cover different path layouts and cannot be copied or compared as interchangeable values. A missing historical dependency pin is not replaced with current HEAD. +Auxiliary Git symlinks, such as PGV's `example-workspace/.bazelrc`, are omitted without reading their targets. This also permits dangling links and links materialized as text by `core.symlinks=false`. Links affecting proto files, dependency metadata or configured source roots remain errors. When auxiliary links are omitted, historical verification requires the actual v0 proto archive hash; a whole-tree hash calculated after dropping links is not accepted as historical proof. The native hash covers regular tracked files and excludes the omitted links. + ## Explicit limitations Invalid known fields, invalid or multi-document YAML, ambiguous source selection, unsupported references, and conflicting native outputs are rejected. Keys ignored by v0 are omitted with warnings and remain in the legacy backup. Custom Git-input roots/subdirectories, external or sliced local inputs whose exact selection cannot be preserved, unsafe managed selectors, and full lock conversion with local replacements may require manual migration. Buf configurations are not inputs to this v0 converter. diff --git a/content/docs/migration/easyp-v0.ru.mdx b/content/docs/migration/easyp-v0.ru.mdx index fab5078..67db50c 100644 --- a/content/docs/migration/easyp-v0.ru.mdx +++ b/content/docs/migration/easyp-v0.ru.mdx @@ -88,6 +88,8 @@ plugins: После проверки новый хеш v1 рассчитывается независимо по отслеживаемым файлам репозитория. Старый и новый хеши относятся к разным раскладкам путей; их нельзя просто копировать или считать взаимозаменяемыми. Отсутствующий исторический pin не заменяется текущим HEAD. +Служебные Git-ссылки, например `example-workspace/.bazelrc` в PGV, пропускаются без чтения их целей. Это относится и к оборванным ссылкам, и к ссылкам, записанным Git как текст при `core.symlinks=false`. Ссылки, затрагивающие proto-файлы, метаданные зависимостей или заданные корни исходников, остаются ошибками. При пропуске служебных ссылок историческая проверка требует хеш настоящего proto-архива v0: хеш полного дерева после удаления ссылок не доказывает прежнее содержимое. Новый native-хеш охватывает обычные отслеживаемые файлы без пропущенных ссылок. + ## Явные ограничения Некорректные значения известных полей, некорректный YAML или несколько YAML-документов, неоднозначный набор исходников, неподдерживаемые refs и конфликтующие native-файлы отклоняются. Ключи, игнорировавшиеся в v0, пропускаются с предупреждениями и сохраняются в legacy-копии. Нестандартные root/sub_directory Git-input, внешние или частичные локальные inputs с непереносимой выборкой, неоднозначные managed selectors и полный перенос lock при локальных заменах могут потребовать ручной миграции. Buf-конфигурация не является входом этого v0-конвертера. From bdb3fd3813ba701b1435f1650674e95795c5fc95 Mon Sep 17 00:00:00 2001 From: Khasbulat Abdullin Date: Tue, 6 Oct 2026 16:57:43 +0300 Subject: [PATCH 4/5] docs(v1): describe bounded aliases and one materialized hash policy --- content/docs/migration/easyp-v0.mdx | 8 ++++++-- content/docs/migration/easyp-v0.ru.mdx | 8 ++++++-- content/docs/reference/protobuf-lock.mdx | 4 ++-- content/docs/reference/protobuf-lock.ru.mdx | 4 ++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/content/docs/migration/easyp-v0.mdx b/content/docs/migration/easyp-v0.mdx index 411cc35..105480b 100644 --- a/content/docs/migration/easyp-v0.mdx +++ b/content/docs/migration/easyp-v0.mdx @@ -86,9 +86,13 @@ Git's annotated-tag spelling, such as `v0.4.0^{}`, is accepted for a full SemVer Released v0 installers archived Git's *.proto pathspec and stripped legacy root prefixes before hashing. Migration reproduces that archive at the pinned revision; it also retains verification of the existing whole-tree hash format. Git archive attributes that omit or alter proto files require manual migration because a native checkout would change the contract. -The v1 content hash is then calculated independently over the tracked repository files. Old and new hashes cover different path layouts and cannot be copied or compared as interchangeable values. A missing historical dependency pin is not replaced with current HEAD. +The v1 content hash is then calculated independently over the materialized logical snapshot. Old and new hashes cover different path layouts and cannot be copied or compared as interchangeable values. A missing historical dependency pin is not replaced with current HEAD. -Auxiliary Git symlinks, such as PGV's `example-workspace/.bazelrc`, are omitted without reading their targets. This also permits dangling links and links materialized as text by `core.symlinks=false`. Links affecting proto files, dependency metadata or configured source roots remain errors. When auxiliary links are omitted, historical verification requires the actual v0 proto archive hash; a whole-tree hash calculated after dropping links is not accepted as historical proof. The native hash covers regular tracked files and excludes the omitted links. +Internal symlinks to files, directories, import roots and metadata are supported. Protobuf import names follow the logical path of the alias. Local targets must remain inside their owning source boundary; Git targets must be relative and resolve entirely from the pinned tree. Selected dangling links, cycles, submodule crossings and undeclared nested repositories fail. Invalid unused auxiliary links are omitted. Git snapshots contain regular resolved bytes, including safe non-proto aliases, regardless of `core.symlinks`. + +If the legacy configuration file itself is a symlink, migration replaces that logical file with regular v1 content and creates a regular backup of its original contents. The former target stays unchanged; rollback restores the original link. Inputs and link topology are checked again before applying. + +Historical v0 archive verification remains a separate migration step. A valid historical file alias must preserve both its installed import name and resolved contents. Its target must exist in the archived inputs; the verifier cannot use current files or unarchived Git blobs. The v1 hash is calculated independently from the materialized snapshot. ## Explicit limitations diff --git a/content/docs/migration/easyp-v0.ru.mdx b/content/docs/migration/easyp-v0.ru.mdx index 67db50c..d810988 100644 --- a/content/docs/migration/easyp-v0.ru.mdx +++ b/content/docs/migration/easyp-v0.ru.mdx @@ -86,9 +86,13 @@ plugins: Выпущенные версии v0 архивировали Git-pathspec *.proto и убирали legacy-префиксы корней перед вычислением хеша. Мигратор воспроизводит этот архив в закреплённой ревизии; проверка существующего формата хеша полного дерева тоже сохраняется. Git-атрибуты архива, исключающие или изменяющие proto-файлы, требуют ручной миграции: native checkout изменил бы контракт. -После проверки новый хеш v1 рассчитывается независимо по отслеживаемым файлам репозитория. Старый и новый хеши относятся к разным раскладкам путей; их нельзя просто копировать или считать взаимозаменяемыми. Отсутствующий исторический pin не заменяется текущим HEAD. +После проверки новый хеш v1 рассчитывается независимо по материализованному логическому снимку. Старый и новый хеши относятся к разным раскладкам путей; их нельзя просто копировать или считать взаимозаменяемыми. Отсутствующий исторический pin не заменяется текущим HEAD. -Служебные Git-ссылки, например `example-workspace/.bazelrc` в PGV, пропускаются без чтения их целей. Это относится и к оборванным ссылкам, и к ссылкам, записанным Git как текст при `core.symlinks=false`. Ссылки, затрагивающие proto-файлы, метаданные зависимостей или заданные корни исходников, остаются ошибками. При пропуске служебных ссылок историческая проверка требует хеш настоящего proto-архива v0: хеш полного дерева после удаления ссылок не доказывает прежнее содержимое. Новый native-хеш охватывает обычные отслеживаемые файлы без пропущенных ссылок. +Внутренние симлинки на файлы, каталоги, import roots и метаданные поддерживаются. Имя protobuf-импорта определяется логическим путём ссылки. Локальная цель должна оставаться внутри границы своего источника; Git-ссылка должна быть относительной и разрешаться целиком в закреплённом дереве. Оборванные ссылки, циклы, переходы в submodule и необъявленные вложенные репозитории среди выбранных входов вызывают ошибку. Некорректные неиспользуемые служебные ссылки пропускаются. Git-снимок содержит обычные файлы с разрешёнными байтами, включая безопасные служебные алиасы, независимо от `core.symlinks`. + +Если legacy-конфигурация сама является симлинком, миграция заменяет файл по этому логическому пути обычным v1-файлом и создаёт обычную резервную копию прежнего содержимого. Бывшая цель остаётся неизменной; откат восстанавливает исходную ссылку. Перед применением входные файлы и цепочка ссылок проверяются повторно. + +Проверка исторического архива v0 остаётся отдельным этапом миграции. Исторический файловый алиас должен сохранять имя установленного импорта и разрешённое содержимое. Его цель должна существовать среди файлов архива: проверка не использует текущие файлы или не попавшие в архив Git-объекты. Хеш v1 вычисляется независимо по материализованному снимку. ## Явные ограничения diff --git a/content/docs/reference/protobuf-lock.mdx b/content/docs/reference/protobuf-lock.mdx index f0e0681..b52bc0a 100644 --- a/content/docs/reference/protobuf-lock.mdx +++ b/content/docs/reference/protobuf-lock.mdx @@ -33,7 +33,7 @@ description: "Specification for protobuf.lock, the generated lockfile securing r type: "string" }, "modules[].hash": { - description: "Go dirhash.Hash1 digest (h1:...) of the Git-tracked regular files at the locked commit.", + description: "Go dirhash.Hash1 digest (h1:...) of the materialized logical snapshot at the locked commit.", type: "string" } }} @@ -68,7 +68,7 @@ During tidy, get, and update, every fetch mod download uses the locked commit even after a tag moves, provided that commit remains available. -The hash uses Go's dirhash.Hash1 over all regular files tracked by Git at the commit, with repository-relative paths. EasyP verifies it on download and when reusing an installed module; corrupt installations are rejected. +The hash uses Go's dirhash.Hash1 over the materialized logical snapshot at the commit, with repository-relative paths. Safe internal aliases contribute their resolved bytes under their logical names; Git objects are read directly, without checkout filters. Buf filters apply before hashing and installation. Invalid unused auxiliary links are omitted. Cache identity includes the source, commit and hash. EasyP verifies it on download and when reusing an installed module; corrupt installations are rejected. The v1 cache reuses an object store per Git remote. A known exact commit can be fetched without contacting the remote. A cold request first tries a depth-one fetch of the exact commit; if the server rejects that request, EasyP falls back to advertised reachable history. The original commit is still required: HEAD is never substituted. Tag lookups are refreshed separately so cache reuse cannot hide a retag. A commit absent from cache can still require access to its source. diff --git a/content/docs/reference/protobuf-lock.ru.mdx b/content/docs/reference/protobuf-lock.ru.mdx index 30cae53..97edc09 100644 --- a/content/docs/reference/protobuf-lock.ru.mdx +++ b/content/docs/reference/protobuf-lock.ru.mdx @@ -33,7 +33,7 @@ description: "Спецификация файла protobuf.lock, автомат type: "string" }, "modules[].hash": { - description: "Дайджест Go dirhash.Hash1 (h1:...) для обычных файлов, отслеживаемых Git в зафиксированном коммите.", + description: "Дайджест Go dirhash.Hash1 (h1:...) для материализованного логического снимка зафиксированного коммита.", type: "string" } }} @@ -68,7 +68,7 @@ modules: mod download использует коммит из lock даже после переноса тега, если этот коммит доступен. -hash вычисляется через Go dirhash.Hash1 по всем обычным файлам, отслеживаемым Git в коммите, с путями относительно репозитория. Хеш проверяется и при скачивании, и при повторном использовании установленного модуля; повреждённая установка отклоняется. +hash вычисляется через Go dirhash.Hash1 по материализованному логическому снимку коммита с путями относительно репозитория. Безопасные внутренние алиасы добавляют разрешённые байты под своими логическими именами; Git-объекты читаются напрямую, без checkout-фильтров. Buf-фильтры применяются до хеширования и установки. Некорректные неиспользуемые служебные ссылки пропускаются. Ключ кеша включает источник, commit и hash. Хеш проверяется и при скачивании, и при повторном использовании установленного модуля; повреждённая установка отклоняется. Для каждого Git remote кеш v1 повторно использует хранилище объектов. Известный точный коммит можно получить без обращения к remote. При холодном запросе сначала выполняется shallow-загрузка точного коммита с глубиной один; если сервер её отклоняет, используется доступная история объявленных ссылок. Всё равно требуется исходный коммит: HEAD вместо него не подставляется. Проверки тегов обновляются отдельно, поэтому кеш не скрывает перенос тега. Отсутствующий в кеше коммит всё ещё может потребовать доступа к источнику. From 20335b0f543c3bc65c61603f137207392cad83b7 Mon Sep 17 00:00:00 2001 From: Khasbulat Abdullin Date: Tue, 6 Oct 2026 21:57:12 +0300 Subject: [PATCH 5/5] docs(v1): explain module filters and optional migration settings --- content/docs/migration/easyp-v0.mdx | 8 ++- content/docs/migration/easyp-v0.ru.mdx | 6 ++- content/docs/reference/easyp-gen-yaml.mdx | 53 +++++++++++++++++++- content/docs/reference/easyp-gen-yaml.ru.mdx | 51 ++++++++++++++++++- 4 files changed, 113 insertions(+), 5 deletions(-) diff --git a/content/docs/migration/easyp-v0.mdx b/content/docs/migration/easyp-v0.mdx index 105480b..daee670 100644 --- a/content/docs/migration/easyp-v0.mdx +++ b/content/docs/migration/easyp-v0.mdx @@ -49,7 +49,7 @@ Modified legacy policy and manifest files receive byte-identical .v0.bakwith_imports, and supported managed settings. Relative paths remain relative to the configuration directory. +The converter preserves the effective selected lint rules, exceptions, rule settings, and explicit legacy comment-suppression setting. It converts literal ignores and rule-specific prefix ignores to the corresponding v1 exclusions. Generation preserves plugin sources, argv, options, with_imports, and supported managed settings. Plugin output paths remain relative to the configuration directory. Legacy direct and indirect requirements are converted to native require directives. The tool proves that local generation keeps the same protobuf files and import paths, using whole roots, literal generation paths or exact package selectors. @@ -72,12 +72,16 @@ plugins: Import roots stay unchanged and generated files keep their source-relative paths. The wizard first tries whole-root equality, then literal directory paths, then complete package selectors for mixed-root cases. Each choice must select exactly the same physical files with the same import names. Paths can preserve part of a package: ignored Gradle build copies outside `mcp` stay out of generation. Hidden/vendor/nested-module boundary changes and inferred local filters mixed with whole-module Git inputs remain blocked. Sources and fixed paths/packages are checked again before apply. -`generate.paths` matches literal import-relative files or directory subtrees, with `.` meaning all sources; `mcp` does not select `mcp-copy`. Paths intersect optional package selectors, and every selector must match a resulting source across the selected modules. Unknown selectors fail before plugins or descriptor writes, even without plugins or under `--all`. Required imports outside these paths remain available. These paths are separate from plugin `opts.paths`, which controls output layout. +`generate.paths` matches literal module-directory-relative files or directory subtrees, with `.` meaning all sources; `mcp` does not select `mcp-copy`. Paths intersect optional package selectors, and every selector must match a resulting source across the selected modules. Unknown selectors fail before plugins or descriptor writes, even without plugins or under `--all`. Required imports outside these paths remain available. These paths are separate from plugin `opts.paths`, which controls output layout. Path selection requires an updated v1 build; the initial v1.0.0-nightly.20261005.1 and commit 8be79c7 do not provide it. When migration uses the complete-package fallback, the preview still warns that future files in those packages become targets regardless of their directory. Variable placeholders are not expanded into saved values. If a placeholder or selector prevents safe analysis, conversion fails rather than persisting credentials or guessing its meaning. +For a sole local input, migration does not repeat its module in `generate.modules`: it is inferred from the generator location. With `root: api, path: easyp`, the output is `generate.paths: [api/easyp]` and protobuf import names stay unchanged. Global filters remain available without listing modules; each module object can also add its own `paths`/`packages`, intersected with global filters. + +Migration does not create an empty `options.go.package_prefix`. This field is optional: omission allows normal v1 inheritance, while an explicitly empty value blocks prefix inheritance. + ## Historical lock integrity A full commit SHA is preserved, including a full SHA embedded in an old pseudo-version. For a legacy lock entry containing a tag but no SHA, conversion resolves that tag and verifies the historical installed-tree hash before accepting the revision. A moved tag or mismatched historical hash is an error. diff --git a/content/docs/migration/easyp-v0.ru.mdx b/content/docs/migration/easyp-v0.ru.mdx index d810988..072d071 100644 --- a/content/docs/migration/easyp-v0.ru.mdx +++ b/content/docs/migration/easyp-v0.ru.mdx @@ -72,12 +72,16 @@ plugins: Корни импортов сохраняются, а сгенерированные файлы остаются по прежним source-relative путям. Мастер сначала проверяет совпадение целых корней, затем буквальные пути каталогов, затем selectors полных пакетов для смешанных корней. Каждый вариант должен выбирать точно те же физические файлы с теми же import-именами. Пути позволяют выбрать часть пакета: игнорируемые Gradle-копии вне `mcp` не становятся целями генерации. Изменение границ скрытых/vendor/вложенных модулей и сочетание выведенного локального фильтра с Git-input целого модуля отклоняются. Перед применением проверяются исходники и зафиксированные пути/пакеты. -`generate.paths` выбирает буквальные import-relative пути файлов или поддеревьев каталогов; `.` означает все исходники, а `mcp` не совпадает с `mcp-copy`. Пути пересекаются с необязательными selectors пакетов. Каждый selector должен совпасть с итоговым исходником хотя бы в одном выбранном модуле. Неизвестные selectors отклоняются до запуска плагинов и записи descriptors, в том числе без плагинов или с `--all`. Необходимые импорты вне этих путей остаются доступными. Эти пути отличаются от plugin `opts.paths`, управляющего раскладкой результатов. +`generate.paths` выбирает буквальные пути файлов от каталога модуля или поддеревьев каталогов; `.` означает все исходники, а `mcp` не совпадает с `mcp-copy`. Пути пересекаются с необязательными selectors пакетов. Каждый selector должен совпасть с итоговым исходником хотя бы в одном выбранном модуле. Неизвестные selectors отклоняются до запуска плагинов и записи descriptors, в том числе без плагинов или с `--all`. Необходимые импорты вне этих путей остаются доступными. Эти пути отличаются от plugin `opts.paths`, управляющего раскладкой результатов. Выборка по путям требует обновлённой сборки v1: первый v1.0.0-nightly.20261005.1 и коммит 8be79c7 её не поддерживают. Если мастер использует fallback по полным пакетам, preview по-прежнему предупреждает, что будущие файлы этих пакетов станут целями независимо от каталога. Подстановки переменных не сохраняются в раскрытом виде. Если переменная или selector мешает безопасному анализу, перенос останавливается, а не записывает секреты и не угадывает смысл настройки. +Для единственного локального источника мигратор не повторяет модуль в `generate.modules`: он определяется по расположению `easyp.gen.yaml`. При `root: api, path: easyp` записывается `generate.paths: [api/easyp]`, а имена protobuf-импортов остаются прежними. Общие фильтры можно использовать без списка модулей; собственные `paths`/`packages` также допустимы внутри элемента `modules` и пересекаются с общими. + +Мигратор не создаёт пустой `options.go.package_prefix`. Это необязательное поле: отсутствие допускает обычное наследование настроек v1, а явная пустая строка блокирует наследование префикса. + ## Целостность исторического lock-файла Полный SHA коммита сохраняется, в том числе когда он встроен в старую псевдоверсию. Если запись содержит только тег, миграция разрешает его и проверяет исторический хеш установленного дерева перед принятием ревизии. Перенос тега или несовпадение прежнего хеша приводит к ошибке. diff --git a/content/docs/reference/easyp-gen-yaml.mdx b/content/docs/reference/easyp-gen-yaml.mdx index 119a1f0..71bf44f 100644 --- a/content/docs/reference/easyp-gen-yaml.mdx +++ b/content/docs/reference/easyp-gen-yaml.mdx @@ -24,6 +24,22 @@ The easyp.gen.yaml file specifies **consumer-side code generation r }, "generate.modules": { description: "Module identities or workspace-relative local module paths. Dependencies use the nearest protobuf.mod beside or above this config within the workspace and its lock. If omitted, that module is selected; without a manifest, the project directory is used.", + type: "(string | object)[]" + }, + "generate.modules[].module": { + description: "Selected module identity or workspace-relative module directory. A plain string is shorthand without local filters.", + type: "string" + }, + "generate.modules[].paths": { + description: "Literal files or directory subtrees relative to this module directory, intersected with global filters.", + type: "string[]" + }, + "generate.modules[].packages": { + description: "Exact protobuf packages in this module, intersected with global filters.", + type: "string[]" + }, + "generate.paths": { + description: "Literal files or subtrees relative to each selected module directory. Available without listing modules; omitted or empty selects all paths.", type: "string[]" }, "generate.packages": { @@ -72,7 +88,7 @@ The easyp.gen.yaml file specifies **consumer-side code generation r type: "object" }, "options.go.package_prefix": { - description: "Computes go_package, changing Go options only. Full managed mode requires generate.managed.enabled: true.", + description: "Optional. Omitted permits inheritance; explicit empty blocks prefix inheritance. A nonempty value computes go_package, changing Go options only.", type: "string" }, "generate.managed": { @@ -86,6 +102,41 @@ The easyp.gen.yaml file specifies **consumer-side code generation r ## Example Configurations +### Global and module-specific source selection + +Global filters work without repeating the local module declared in protobuf.mod: + +~~~yaml +version: v1 +generate: + paths: [api/easyp] +~~~ + +With roots api, this selects api/easyp on disk while protobuf import names +start with easyp/. Paths are relative to the selected module directory, even +when the generator config is elsewhere. Import roots and plugin output paths +remain unchanged. + +Different modules can restrict their own sources: + +~~~yaml +generate: + modules: + - module: proto/users + paths: [schemas/api] + packages: [users.v1] + - proto/orders + packages: [users.v1, orders.v1] +~~~ + +Global and module-specific filters intersect. Every global selector must match +a resulting source across the selected modules; each module-specific selector +must match within that module. Missing selectors fail before plugins or descriptor +writes, including projects without plugins. Required imports stay available. +Identical repeated module selections are idempotent; conflicting filters for +the same resolved module in one project fail. Filter order and repeated values +do not change their meaning. + ### Project-Level Generator (backend/easyp.gen.yaml) ~~~yaml diff --git a/content/docs/reference/easyp-gen-yaml.ru.mdx b/content/docs/reference/easyp-gen-yaml.ru.mdx index 6ab79af..36d8f6f 100644 --- a/content/docs/reference/easyp-gen-yaml.ru.mdx +++ b/content/docs/reference/easyp-gen-yaml.ru.mdx @@ -24,6 +24,22 @@ description: "Полная спецификация файла easyp.gen.yaml, }, "generate.modules": { description: "Идентификаторы модулей или локальные пути относительно workspace. Зависимости используют ближайший protobuf.mod рядом с конфигом или выше в пределах workspace и его lock. Без списка выбирается этот модуль; без манифеста — каталог проекта.", + type: "(string | object)[]" + }, + "generate.modules[].module": { + description: "Имя модуля или путь его каталога относительно workspace. Строка — сокращение без собственных фильтров.", + type: "string" + }, + "generate.modules[].paths": { + description: "Буквальные пути файлов или поддеревьев относительно каталога этого модуля, пересекаются с общими фильтрами.", + type: "string[]" + }, + "generate.modules[].packages": { + description: "Точные имена protobuf-пакетов этого модуля, пересекаются с общими фильтрами.", + type: "string[]" + }, + "generate.paths": { + description: "Буквальные пути относительно каталога каждого выбранного модуля. Можно использовать без списка modules; отсутствие или пустой список выбирает все пути.", type: "string[]" }, "generate.packages": { @@ -72,7 +88,7 @@ description: "Полная спецификация файла easyp.gen.yaml, type: "object" }, "options.go.package_prefix": { - description: "Вычисляет go_package, меняя только Go-опции. Полный managed mode требует generate.managed.enabled: true.", + description: "Необязательный префикс: отсутствие допускает наследование, явная пустая строка его блокирует. Непустой префикс вычисляет go_package и меняет только Go-опции.", type: "string" }, "generate.managed": { @@ -86,6 +102,39 @@ description: "Полная спецификация файла easyp.gen.yaml, ## Примеры конфигураций +### Общие фильтры и фильтры отдельных модулей + +Общие фильтры можно задать без повторного указания локального модуля из protobuf.mod: + +~~~yaml +version: v1 +generate: + paths: [api/easyp] +~~~ + +С roots api выбирается каталог api/easyp на диске, а имена protobuf-импортов +начинаются с easyp/. База пути — каталог выбранного модуля, даже если +конфиг генератора находится в другом месте. Корни импортов и выходные пути плагинов сохраняются. + +У разных модулей можно ограничить собственные исходники: + +~~~yaml +generate: + modules: + - module: proto/users + paths: [schemas/api] + packages: [users.v1] + - proto/orders + packages: [users.v1, orders.v1] +~~~ + +Общие фильтры пересекаются с фильтрами модулей. Каждый общий selector должен +совпасть с итоговым исходником хотя бы одного модуля; собственный selector — +с исходником именно своего модуля. Пропуски вызывают ошибку до плагинов и записи +descriptors, включая проекты без плагинов. Необходимые импорты остаются доступны. +Одинаковые повторные записи модуля не дублируют генерацию; разные фильтры одного +модуля в одном проекте вызывают ошибку. Порядок и повторение значений фильтра не меняют его смысл. + ### Проектный генератор (backend/easyp.gen.yaml) ~~~yaml