.NET Разработчик
6.72K subscribers
479 photos
4 videos
14 files
2.39K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 2720. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.

39. Преимущества микросервисов
«Расскажите о преимуществах использования микросервисной архитектуры в приложениях .NET?»

Хороший ответ
Микросервисная архитектура предлагает ряд преимуществ для разработки сложных приложений, особенно в средах, требующих гибкости, масштабируемости и высокой доступности.

- Масштабируемость: микросервисы могут масштабироваться независимо, что позволяет более эффективно использовать ресурсы. Вы можете масштабировать части системы, требующие больше ресурсов, без масштабирования всего приложения.

- Гибкость: микросервисы позволяют небольшим автономным командам разрабатывать, развёртывать и масштабировать свои сервисы независимо друг от друга. Это приводит к более быстрым циклам разработки и упрощает экспериментирование и инновации.

- Устойчивость: независимость сервисов повышает общую устойчивость системы. При сбое в одном сервисе остальные могут продолжать работать.

- Гибкость развёртывания: микросервисы могут развёртываться независимо. Это особенно полезно в средах непрерывного развёртывания, где необходимо часто выпускать обновления.

- Технологическая диверсификация: команды могут выбирать лучший инструмент для решения своих конкретных задач, повышая общую эффективность.

Часто встречающийся неверный ответ
«Можно разбить приложение на более мелкие проекты для каждой сущности или группы сущностей. Это делает приложение микросервисной архитектурой.»

Почему это неверно
- Непонимание концепции микросервисов: ответ демонстрирует фундаментальное непонимание того, что такое микросервисы. Микросервисы — это не просто разбиение приложения на части, а определение сервисов на основе бизнес-возможностей и границ предметной области.

- Чрезмерное упрощение проектирования архитектуры: сведение микросервисов к операциям CRUD для каждой сущности может привести к сильно фрагментированной архитектуре с избыточными накладными расходами, сложным управлением данными и увеличенной задержкой из-за межсервисного взаимодействия.

- Отсутствие стратегического понимания: в ответе игнорируются стратегические элементы микросервисов, такие как независимое развёртывание, масштабируемость и изоляция отказов. Простое разделение приложения на более мелкие части без учёта этих факторов не даёт реальных преимуществ.

Этот неверный ответ может быть следствием поверхностного понимания микросервисной архитектуры или перевода стратегий разделения монолитных систем в контекст микросервисов без адаптации к основным принципам, определяющим микросервисы.

Источник:
https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
1👎7👍1
День 2721. #ЗаметкиНаПолях #AI
Превращаем Claude из Автодополнителя в Коллегу. Начало
Claude не «плохо разбирается в .NET». Он слеп. Вы просите его «добавить конечную точку», а он уверенно:
- изобретает структуру папок, которая не соответствует вашему репозиторию;
- добавляет шаблоны, которые вы не используете;
- пропускает ваш рабочий процесс сборки/тестирования;
- нарушает соглашения и заставляет вас убирать за ним.
Это не проблема ИИ. Это проблема адаптации.


Решение — один файл, который становится системой оперирования вашим проектом для Claude: CLAUDE.md.

В Claude Code файлы памяти, такие как ./CLAUDE.md (и модульные правила в ./.claude/rules/*.md), автоматически загружаются в качестве контекста при запуске инструмента, поэтому Claude начинает каждую сессию с картой вашего проекта и правилами, вместо того чтобы гадать.

Что на самом деле делает CLAUDE.md
Представьте CLAUDE.md как вводные инструкции для нового старшего разработчика. Однако этот «разработчик» будет:
- последовательно следовать вашим инструкциям,
- запоминать их между сессиями,
- перестанет каждый раз заново изобретать вашу архитектуру.

В документации Claude Code файл CLAUDE.md описывается как файл конфигурации проекта, который находится в вашем репозитории и автоматически загружается в контекст.

И что важно: вам не нужно начинать с нуля. Claude Code поддерживает команду /init для генерации стартового файла CLAUDE.md путём сканирования вашего репозитория — затем вы его дорабатываете.

Правило: ваш CLAUDE.md должен предотвращать дорогостоящие ошибки
Если CLAUDE.md не предотвращает одну из следующих ошибок, он не выполняет свою работу:
- неправильные шаблоны (репозитории, AutoMapper, случайные абстракции, которые вы не используете);
- неправильный рабочий процесс (изменения без плана, отсутствие тестов, отсутствие валидации);
- неправильные значения по умолчанию (тайм-ауты, отмена, повторные попытки, фоновая работа, время жизни DI).

Поэтому не пишите его как документацию. Пишите его как: ограничители + карта + команды.

Структура памяти Claude Code
Claude Code поддерживает небольшую иерархию файлов памяти, включая:
- ./CLAUDE.md для общей памяти проекта,
- ./.claude/rules/*.md для модульных правил,
- ~/.claude/CLAUDE.md для ваших личных глобальных настроек,
- ./CLAUDE.local.md для ваших личных заметок по проекту (и он НЕ предназначен для того, чтобы его коммитили).
Это означает, что вы можете:
- держать краткий корневой файл CLAUDE.md,
- поместить подробные правила в .claude/rules/,
- хранить ваши личные данные в CLAUDE.local.md, не засоряя репозиторий.

Минимально необходимый CLAUDE.md для бэкенда на .NET 10
Создайте CLAUDE.md в корневом каталоге вашего репозитория:
## What this repo is
- .NET 10 backend API focused on scalability, p95/p99 latency, and production reliability.
- Prefer simple, copy/pasteable patterns over "clever architecture".

## Tech stack --> Зависит от ваших условий
- .NET 10 / C# (modern style)
- ASP.NET Core (Minimal APIs)
- Dapper (NOT EF Core)
- Redis (IDistributedCache / StackExchange.Redis depending on project)
- Azure hosting (App Service / Containers)
- Observability: Application Insights (logs + metrics)

## Repo map --> Измените, чтоб соответствовало вашим папкам
- src/Api/ → endpoints, DI, middleware, startup
- src/App/ → use-cases/services (business orchestration)
- src/Infra/ → DB, Redis, HTTP clients, external integrations
- tests/ → unit + integration tests

## Hard rules (do not violate)
- NEVER add new framework layers or "Clean Architecture cosplay".
- NEVER introduce patterns we don't use (AutoMapper, repositories, magic abstractions).
- Always pass CancellationToken through all async calls.
- No sync-over-async (no .Result/.Wait).
- No Task.Run inside request handlers.
- Outbound HTTP MUST have timeouts + cancellation.
- Caching MUST have: time budget, stampede protection strategy, and key versioning.

## Default workflow
1) Ask for missing requirements before changing code.
2) Propose a plan + list files to touch.
3) Implement smallest change that works.
4) Add/update tests when relevant.
5) Provide commands to verify (build/test/run).

## Commands --> Измените на нужные вам
- Build: `dotnet build`
- Test: `dotnet test`
- Run API: `dotnet run --project src/Api`
- Format: `dotnet format`

## Output format
- Prefer short sections, small code blocks, and explain trade-offs.
- When making changes: show diff-level guidance + why.


Этого достаточно, чтобы избежать 80% гаданий Claude.

Далее сделаем его жутко эффективным.

Окончание следует…

Источник:
https://medium.com/codetodeploy/claude-md-for-net-10-turn-claude-from-autocomplete-into-a-teammate-5ae9d5ad0b92
👎6👍1
День 2722. #ЗаметкиНаПолях #AI
Превращаем Claude из Автодополнителя в Коллегу. Окончание

Начало

Модульные правила: прекратите повторяться и остановите импровизации Claude
Claude Code поддерживает модульные правила в папке .claude/rules/*.md.

Создадим:
1. .claude/rules/api-conventions.md:
# API conventions (Minimal APIs) ---> Зависит от ваших настроек
- Prefer Minimal APIs (`MapGet/MapPost`) over controllers.
- Endpoints must accept CancellationToken.
- Validate inputs early. Return ProblemDetails for errors.
- For outbound calls: use IHttpClientFactory + timeouts.
- For "slow work": queue it (don't run it in the request).


2. .claude/rules/perf-reliability.md:
# Perf + reliability rules
- All outbound HTTP:
- Timeout per request
- CancellationToken wired through
- Retry ONLY for safe idempotent calls (and never infinite)
- Redis:
- Cache calls get a small time budget (fail fast)
- Stampede protection for hot keys (singleflight or equivalent)
- TTL jitter for large fleets
- Logging:
- Avoid high-cardinality fields
- Avoid expensive structured logs in hot paths


3. .claude/rules/security.md:
# Security rules
- No secrets in code or CLAUDE.md.
- Avoid putting sensitive IDs/tokens in query strings.
- Auth must be explicit on endpoints (no accidental public routes).
- CORS must be restrictive (no AllowAnyOrigin in prod configs).

Теперь корневой CLAUDE.md остаётся коротким и читаемым, а правила — таргетированными.

Как быстро сделать Claude полезным?
Собственные рекомендации Claude сводятся к следующему: относитесь к CLAUDE.md как к живому конфигурационному файлу, который вы совершенствуете со временем.

Пошагово:
- Запустите /init один раз, чтобы получить начальный файл.
- Удалите всё «сферическое в вакууме». Сохраняйте только специфичные для репозитория правила.
- Каждый раз, когда Claude делает что-то не то, добавляйте правило, которое это предотвращает.
- Переместите большие фрагменты правил в .claude/rules/, чтобы корневой файл оставался чистым.
- При переключении задач очищайте контекст с помощью /clear, чтобы Claude не переносил старые неактуальные детали в следующую имплементацию.
В блоге Claude также упоминается использование клавиши # для добавления инструкций, которые вы постоянно повторяете (так что они накапливаются в CLAUDE.md со временем).

Что добавлять (а что нет)
1. Добавить (полезно)
- точные версии технологий + фреймворки, которые вы действительно используете;
- карту папок + «где что находится»;
- ваши строгие правила (тайм-ауты, отмена, отсутствие Task.Run, отсутствие синхронного кода поверх асинхронного);
- команды сборки/тестирования/запуска;
- шаблоны, которые вы не хотите, чтобы предлагались.

2. Не добавлять (мало полезно или опасно)
- секреты, токены, строки подключения (никогда!);
- правила стиля, которые уже применяются вашим форматтером;
- «войну-и-мир» документации, которую Claude всё равно сможет просмотреть.

Цель не в том, чтобы научить Клода .NETу. Цель — научить Клода вашему репозиторию.

Простой «тестовый промпт» для проверки вашего CLAUDE.md:
«Добавь новую конечную точку, которая вызывает нижестоящий HTTP-сервис и безопасно кэширует ответ. Сначала покажи план, затем реализуй».


Если Claude (например):
- использует минимальный API;
- использует CancellationToken по всей цепочке;
- устанавливает тайм-аут запроса;
- избегает Task.Run;
- добавляет безопасные шаблоны кэширования
…ваш CLAUDE.md работает.

Если он импровизирует, в вашем CLAUDE.md отсутствуют правила.

Итого
Если вы серьёзно относитесь к разработке с использованием ИИ в .NET, перестаньте настойчиво промптить и начните лучше проводить адаптацию. CLAUDE.md поможет превратить Claude из «умного автозаполнения» в «надёжного члена команды».

Источник:
https://medium.com/codetodeploy/claude-md-for-net-10-turn-claude-from-autocomplete-into-a-teammate-5ae9d5ad0b92
👎6👍2
День 2723. #TipsAndTricks
Пагинация в EF Core
Если вы повторяете одну и ту же логику пагинации — Count, Skip и Take — во всём приложении, вы добавляете ненужный код. Рассмотрим более чистый способ.

Проблема
Рассмотрим класс:
public class PagedProductsDto
{
public IEnumerable<ProductDto> Records { get; set; } = [];
public int TotalCount { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int PageCount { get; set; }
}

В самом классе нет ничего плохого. Он содержит все необходимые свойства для пагинации: записи, общее количество, страница, размер страницы и количество страниц. Проблема в том, что он тесно связан с товарами. Если бы мы хотели добавить аналогичный класс, например, для пользователей, нам пришлось бы создать новый класс.

Создадим универсальный класс PagedResults
Он будет принимать в качестве обобщённого параметра тип возвращаемой записи:
public class PagedResults<T>
{
public IEnumerable<T> Records { get; }
public int TotalCount { get; }
public int Page { get; }
public int PageSize { get; }
public int PageCount { get; }
}

В Records мы используем IEnumerable, чтобы обозначить его как доступный только для чтения.

Свойства имеют только аксессор, т.е. доступны только для чтения. Поэтому единственный способ установить их — через конструктор, где мы вычислим все необходимые значения:
public class PagedResults<T>
{
// …
public PagedResults(
IEnumerable<T> records,
int totalCount,
int page,
int pageSize
)
{
Records = records;
TotalCount = totalCount;
Page = page;
PageSize = pageSize;
PageCount = totalCount > 0 && pageSize > 0 ?
(int)Math.Ceiling((double)totalCount / pageSize) : 1;
}
}


Используем в EF
Создадим метод расширения для IQueryable, который позволит применять пагинацию к любым нашим запросам:
public static async Task<PagedResults<T>>
ToPagedResultsAsync<T>(
this IQueryable<T> query,
int page,
int pageSize,
CancellationToken ct = default)
{
var total = await query.CountAsync(ct);

var records = await query
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync(ct);

return new PagedResults<T>(records, total, page, pageSize);
}

Теперь методы получения результатов короткие, и это применимо к любым сущностям:
public Task<PagedResults<ProductDto>> 
GetPagedProductsAsync(
int page,
int pageSize,
CancellationToken ct = default)
{
return _dbContext.Products
.Include(x => x.Category)
.AsNoTracking()
.Select(x => new ProductDto
{
Id = x.Id,
Name = x.Name,
// …
})
.ToPagedResultsAsync(page, pageSize, ct);
}


Источник:
https://www.roundthecode.com/dotnet-tutorials/pagedresults-ef-core-one-class-endless-reuse
День 2724. #Оффтоп
Можно Установить Пакет, но Владеете ли вы им? Начало

Создавайте форки зависимостей, ограничивайте их только вашими вариантами использования, никогда не обновляйте без крайней необходимости. Обновление гораздо рискованнее, чем обнаружение скрытых ошибок (которые можно отслеживать, а CVE – мониторить). Если вы обновляете зависимость, вы должны проанализировать каждый коммит во всё транзитивном наборе зависимостей. Если вы не видите ничего убедительного, не обновляйте!
Я помню, как в HashiCorp инженеры иногда пытались обновить зависимость или заменить самодельную библиотеку внешней, и я всегда спрашивал: «Покажите мне нужный коммит». Не обновляйте просто так.
Я очень доволен таким подходом, учитывая все эти атаки на цепочки поставок.

Это от Митчелла Хашимото

Вроде звучит здраво. Но есть проблема. Можно создать форк небольшой библиотеки и сократить её до того, что вам нужно. Но можно ли создать форк React и поддерживать его? Думаю, большинство команд не смогут. Поэтому совет «создавайте форки зависимостей» прекрасен до тех пор, пока зависимость не становится слишком большой.

Дело не ограничивается созданем форка. Дело в том, чтобы точно знать, за что вы взялись, и быть готовым взять на себя ответственность. Мы устанавливаем зависимость и берём на себя все проблемы, возникающие с зависимостями:
- атаки на цепочку поставок,
- лицензионные споры,
- недоработанные спецификации,
- проблемы, о которых узнаешь только после поломки…
Все они сводятся к тому, что мы стали зависеть от чужого продукта, даже не принимая на себя такого решения.

Устанавливать или нет?
Установить Automapper или написать маппинг вручную? Конечно, гораздо проще установить пакет и передать его обслуживание на аутсорс. Особенно когда вы спешите, вы ставите, что есть, и это может быть неплохим промежуточным решением, но затем стоит задуматься о следующем шаге.

Посмотрите, какие пакеты на самом деле попадают под все эти атаки на цепочки поставок. Почти всегда это мелочи. Помните инцидент с Left-pad? Обычно это какой-нибудь крошечный или низкоуровневый вспомогательный код, о котором никто не задумывается. Они повсюду, они тривиальны, и именно поэтому никто за ними не следит. Поэтому их так легко написать самому. Так что написание небольшого вспомогательного кода от руки — это не паранойя. Это более спокойный вариант, и это один из немногих случаев, когда точно знаешь, что находится в твоей системе.

Будьте дотошны в выборе зависимостей, которые вы устанавливаете, посмотрите, сколько зависимостей они подключают, и учитывайте это при принятии решения. Само число не имеет значения. Оно просто показывает, насколько вы соглашаетесь владеть чем-то, даже не видя этого.

И прямые зависимости – ещё не худшее. Чаще всего можно их прочитать и понять, что они делают. Страшно то, что происходит с транзитивными зависимостями, вплоть до самых нижних уровней, — то, что вы не выбирали, не видите и на что не можете повлиять.

Поэтому дело не в достижении нулевого количества зависимостей, а в наличии только тех, которые мы осторожно согласовали. Нельзя принимать решения, основываясь на том, чего не видишь, и если у вас нет даже базовых знаний (например, списка) того, от чего вы зависите, то любой разговор о рисках в цепочке поставки превращается в гадание.

Инвентаризация зависимостей
В большинстве сред существуют инструменты для генерации SBOM (Software Bill of Materials) — инвентаризации дерева зависимостей. Проблема в том, что большинство организаций никогда в жизни не создавали ни SBOM, ни инвентаризации, ничего нигде не записано. Поэтому в день следующего Log4Shell, а он обязательно будет, они не смогут ответить на самый первый вопрос, который им зададут: используем ли мы это, и если да, то где?

Окончание следует…

Источник:
https://www.architecture-weekly.com/p/you-can-fork-a-package-but-can-you
👍3
День 2725. #Оффтоп
Можно Установить Пакет, но Владеете ли вы им? Окончание

Начало

Фактор автобуса и неожиданные изменения
Есть ещё один фактор, когда популярный пакет меняет условия. Fluent, Assertions, MassTransit и AutoMapper стали коммерческими. Moq выпустил обновление, незаметно хешировавшее ваш email в Git и отправлявшее его на сервер. И почти каждый раз реакция в .NET-компаниях – это смесь:
- срочно удаляем и пишем своё,
- ищем бесплатную альтернативу,
- обращаемся к Microsoft с просьбой купить библиотеку или предоставить замену.

Это решение не той проблемы. Проблема в том, что мы взяли на себя критически важную зависимость, так и не признав её критически важной, и ни разу не подумали о том, что будем делать, если условия изменятся. Замена пакета ничего не исправит, лишь повторит ту же ошибку.

Эпизод с IdentityServer — более наглядный пример. Люди были недовольны тем, что им внезапно пришлось платить. Затем они назвали это критически важным компонентом безопасности. А потом спросили, какие есть бесплатные альтернативы. Критически важный компонент безопасности, который вы хотите получить бесплатно, либо готовы тут же заменить на аналог... Что может пойти не так?

Несложная математика. Возьмём стоимость лицензии в год. И сколько бы стоило нанять инженера для разработки и поддержки собственной версии. Сравните варианты и решите.

LLM как форк
Изначальная мысль Митчелла интересна, учитывая нынешнюю ситуацию. Кажется, LLM меняют дело, так что написание собственного кода внезапно становится тривиальным, и вопрос зависимостей смягчается. Но всё не так просто. Написание чего-то небольшого никогда не было сложной задачей. Сложнее владеть этим, понимать, поддерживать, устранять инциденты в 2 часа ночи, и никакая модель не снимет с вас эту ответственность.

LLM (возможно) cмогут изменить стоимость производства кода. Но это не решает проблему «установить, не принимая решения». Раньше было «установить и двигаться дальше». Теперь — «навайбить» и двигаться дальше. То же отсутствие ответственности и владения.

Тенденция не нова. Это классическое «теневое ИТ» (инструменты и системы, которые люди создают или внедряют внутри компании, не получая одобрения от тех, кто официально должен их утверждать). Таблица Excel, незаметно управляющая целым отделом; небольшой скрипт, от которого теперь зависит половина команды; интеграция, о которой никто в команде никогда не слышал. Это всегда существовало, потому что люди обходят медленные механизмы управления, чтобы выполнить свою работу, и в большинстве случаев никто не замечает этого, пока система не сломается. В случае с LLM это стало более заманчивым, чем когда-либо.

Что делать?
Мы не можем исправить всю индустрию ПО, но можем исправить то, как работают наши инженерные команды. Вместо того чтобы ждать, пока автоматизированные аудиты начнут кричать на нас, или в панике удалять пакеты, вот простое, регулярное упражнение для вашей организации.

1. Инвентаризация: перечислите используемые вами зависимости (используйте инструменты SBOM).
2. Критичность: определите, какие из этих пакетов абсолютно критически важны для вашей системы.
3. Жизненный цикл: разработайте чёткую стратегию обновления и версионирования. Вы обновляете их просто так, или ищете конкретные полезные коммиты, как предлагает Митчелл?
4. Фактор автобуса: что произойдет, если автора критически важного пакета «собьёт автобус», он выгорит или попросит денег?
5. Смягчение последствий: разработайте конкретный план резервного копирования на этот сценарий. Сделать форк? Оплатить лицензию?
6. Время отклика: как быстро вы сможете обновить и развернуть приложение, если произойдет серьезное нарушение безопасности в какой-либо из зависимостей. Если стратегия заключается в её замене, насколько быстро вы сможете заменить?

Создание надежного ПО требует целенаправленности. Нам не нужно писать всё с нуля, но мы должны точно определить, что мы включаем в наше ПО. Архитектура — это не только написание кода; это выбор того, какие обязательства вы готовы взять на себя.

Источник: https://www.architecture-weekly.com/p/you-can-fork-a-package-but-can-you
👍3
Недавно обновлял резюме и наткнулся на старую версию из 2018 года. Ох, были же времена, когда гордо писали: «уверенный пользователь ПК, MS Office» 😄 А ведь, сейчас этим уже никого не удивишь

Времена меняются, и теперь «уверенный пользователь ПК» все больше про умение работать с ИИ. И как бы нам не хотелось этого принимать, но это не временный тренд, а реальность рынка. ИИ-грамотность уже становится базовым навыком. Плюс рынок всё больше ценит системное мышление и скорость принятия решений, а цена ошибки очень быстро растёт.

Один из способов прокачать этот навык — магистратура «Управление внедрением ИИ в бизнес» от МИФИ и «Школы 21».

Вы научитесь:
— работать с данными, Python, ML и нейросетями
— запускать и развивать ИИ-продукты от идеи до MVP
— управлять командами и цифровыми продуктами

Что дает обучение:
— онлайн-формат с регулярными очными интенсивами;
— студенческий билет, льготы и доступ к инфраструктуре «Школы 21»;
— отсрочка от срочной службы;

Подать заявку и узнать все подробности можно здесь.

#реклама Рекламодатель АНО «Школа 21». ИНН 7736316133
👎19👍1
День 2726. #TipsAndTricks
Исправляем Ошибку «Слишком длинное имя файла» в Windows для Git

Бывает, что при клонировании или извлечении репозитория в Windows Git выдаёт следующую ошибку:
error: unable to create file some/very/deeply/nested/path/to/a/file.ts: Filename too long (невозможно создать файл … Имя файла слишком длинное)

С вашим кодом всё в порядке, с репозиторием тоже. Проблема в Windows.

Что происходит?
В Windows существует ограничение на длину пути по умолчанию в 260 символов (печально известный MAX_PATH). Операции Git, создающие файлы с полным путём длиннее этого, завершаются с этой ошибкой. Репозитории с глубоко вложенной структурой папок (например, node_modules или сгенерированный код) постоянно сталкиваются с этой проблемой.

Решение: разрешить длинные пути в Git
В Git есть параметр конфигурации именно для этого: core.longpaths. У вас есть два способа установить его, в зависимости от ваших прав на машине.

Системно (требует прав администратора):
git config --system core.longpaths true


На уровне пользователя (не требуется прав администратора):
git config --global core.longpaths true


Если у вас нет прав администратора, версия --global применяется только к вашей учётной записи пользователя, но обычно этого достаточно, чтобы разблокировать доступ.

Примечание: это только указывает Git на необходимость поддержки длинных путей, но не решает всей проблемы. Для полноценной работы некоторых инструментов и API в Windows также требуется включение поддержки длинных путей на уровне ОС.

Включение длинных путей в Windows
Если вы хотите, чтобы длинные пути поддерживались на уровне всей системы (другие инструменты, Проводник и т. д.), вам также необходимо включить их в самой Windows. Откройте Group Policy Editor (Редактор Групповой Политики - gpedit.msc) — только для версий Enterprise/Pro. Перейдите в Computer Configuration > Administrative Templates > System > Filesystem (Конфигурация компьютера > Административные шаблоны > Система > Файловая система. Включите параметр Enable Win32 long paths (Включить длинные пути Win32).

Или через реестр, если Редактор Групповой Политики недоступен (например, Windows Home):
reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1

Чтобы изменение вступило в силу, потребуется перезагрузка.

Источник:
https://bartwullems.blogspot.com/2026/07/fixing-filename-too-long-errors-on.html