Перейти к основному содержимому

Показ

Замер от: 2026-08-14 · чем проверено: ZAMER-KARTY-BLOKOV-2026-08-14.md, прогон php vendor/phpunit/phpunit/phpunit tests/Feature/Filament Для кого: кто добавляет страницу в /new или чинит «страница не появляется / отдаёт 403».

Что делает

Блок рисует интерфейс mp.hyp.ru/new на Filament 3. Отчётные данные площадок приходят через Data API; административные ресурсы пользователей, прав и настроек живут в хранилище Laravel, а запись отгрузки остаётся отдельным неприкосновенным обходом. Живые числа на 14.08: 145 страниц (описаний PageSpec), 42 описания отчётов, 49 их вариантов. По дереву — 69 страниц в app/Filament/Pages/ и 11 ресурсов в app/Filament/Resources/.

⚠️ Два счёта путать нельзя: «147 файлов упоминают PageSpec» — про файлы, а не про описания; прежнее «22 ресурса» неверно — их 11.

Точка входа в код

app/Providers/Filament/AdminPanelProvider.php — метод panel(). Здесь решается, какие страницы и ресурсы зарегистрированы в /new (список задан явно, не автообнаружением) и как строится меню.

Чем задаётся

  • specs/pages/*.yaml145 описаний страниц; specs/grids/*.yaml — их колонки. Общий маршрут UniversalReportPage отрисовывает PageSpec по коду описания. BrandPage — другой общий маршрут для отдельных описаний бренд-менеджеров; к PageSpec его относить нельзя.
  • app/Services/SpecPlatform/PrimaryNavigationCatalog.php — единый источник меню: его читают и Filament, и порождаемый каталог интерфейса; совпадение двух потребителей проверяет PrimaryNavigationTreeTest.
  • config/access-control.php + app/Services/Access/AccessManager.php — бизнес-доступ: возможности (access.reports.view…) × площадки (marketplace.wildberries…).
  • config/filament-shield.php — роли и разрешения Shield (view_any_*, page_*).

Какие правила обязан соблюдать

  • Поверхность страницы объявляется в трёх местах — панель (AdminPanelProvider::panel), меню (PrimaryNavigationCatalog) и Shield (разрешение page_* или политика ресурса). Для PageSpec маршрут панели общий — UniversalReportPage, а конкретный page_code добавляет каталог. Пропуск любого слоя молчалив: пункта нет либо прямой переход получает 403. Это самая частая ловушка блока.
  • Shield даёт ресурсу 403 только при наличии политики. Без политики его ворота не принимают решение, и запрет часто выглядит как отсутствующая страница или пункт. Это не отменяет отдельный 403 от EnforceBusinessAccess. Политики лежат в app/Policies/; обычная проверка начинается с $user->can('view_any_…').
  • Проверка прав идёт на прямые переходы, а не только на меню. Мидлварь app/Http/Middleware/EnforceBusinessAccess.php стоит на всех маршрутах /new и отвечает 403 «Эта роль не имеет доступа к разделу или маркетплейсу».
  • Отгрузку показывать можно, менять нельзя (RULES.md, «НЕПРИКОСНОВЕННОЕ»).

Чем проверяется

APP_BASE_PATH="$PWD" php vendor/phpunit/phpunit/phpunit tests/Feature/Filament

Набор включает проверки значений в ячейках (не только факта отрисовки), дерева меню и прямого доступа. APP_BASE_PATH удерживает Laravel в текущем worktree, даже когда vendor/ подключён ссылкой из основного checkout. Сверка ссылок — python3 scripts/docs/check_doc_links.py.

Поимённое соответствие «описание PageSpec → пункт меню» проверяет PrimaryNavigationTreeTest::test_every_pagespec_page_is_reachable_from_the_tree (tests/Feature/Filament/PrimaryNavigationTreeTest.php:355-381): тест собирает из настоящего меню адреса с page_code= и сверяет их с PageSpecRegistry::pages(). Выпавшая страница делает прогон красным.

Чего делать нельзя

  • Не регистрировать страницу в одном месте из трёх и не надеяться на автообнаружение: в целевом режиме /new список страниц и ресурсов задан явно (автообнаружение осталось только у прежнего /admin), и неупомянутый класс не существует как маршрут.
  • Не менять меню в обход PrimaryNavigationCatalog. У каталога два потребителя, и расхождение между ними — это мёртвые пункты, которые сервер отдаёт с кодом 200, а браузер дорисовывает надписью «Страница не найдена».
  • Не удалять страницы-дубли из прежних экранов ради «чистоты»: добавление вместо перестройки — решение владельца 07.08.2026.
  • Не ослаблять проверку прав ради «страница хотя бы открылась»: ложный успех хуже молчания.

Что НЕ установлено

  • Какие именно роли несут какие page_*-разрешения в боевой базе — базы нет, не замерено. Поэтому поимённая цепочка «описание → пункт меню → назначенное роли разрешение» доказана только до пункта меню.

Куда за подробностью

  • docs/ui/README.md — каталог страниц и как устроен интерфейс.
  • docs/ui/TWO-STACKS.md — два контура, маршруты, вход.
  • docs/domain/ACCESS-CONTROL.md — модель бизнес-доступа.
  • docs/guards/app-guards.md — сторожа A1 (бизнес-доступ) и A2 (токен API).
  • specs/pages/, specs/grids/ — описания страниц; app/Filament/Pages/UniversalReportPage.php — как описание становится экраном.