Commit Graph

13 Commits

Author SHA1 Message Date
Дмитрий 54c69a64e8 chore(gitignore): ignore .claude/worktrees/ and /app/coverage/
— Worktree artefacts from Superpowers using-git-worktrees skill
  (Pravila §11.3 — может быть нестабилен на Windows + кириллица,
  но директория появляется при попытках)
— Vitest --coverage output (app/coverage/), не должен попадать в commits

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 02:18:07 +03:00
Дмитрий f298984055 feat(supplier): Plan 3 Task 5 — RefreshSupplierSessionJob + PlaywrightBridge
Компоненты:
- app/playwright/{package.json, refresh-session.js} — изолированный Node.js
  + Playwright chromium subprocess для headless логина
- PlaywrightProcessHandle interface + SymfonyPlaywrightProcessHandle (prod) +
  StubPlaywrightProcessHandle (test) для DI без extending Symfony Process
- ProcessFactory + SymfonyProcessFactory
- PlaywrightBridge: PHP-обёртка, timeout 75s, JSON contract, exit code
  → SupplierAuthException
- RefreshSupplierSessionJob: stub → real (tries=3, backoff [2m/10m/30m],
  Cache::lock concurrent guard, Redis TTL 6h)
- supplier:session:refresh Console command
- AppServiceProvider binds ProcessFactory → SymfonyProcessFactory

+7 tests (4 PlaywrightBridge + 2 Job + 1 Command).

NOTE: DOM-селекторы placeholder — финализация после Task 1 discovery.
NOTE: app/playwright/node_modules в .gitignore.

Quirks resolved:
- Mockery::mock(Process::class) + laravel/pao = stream_filter_remove fatal.
  Решение: handle interface, pure-PHP test stub без extends Process.
- PHPStan Mockery union types — baseline entries (known Mockery+PHPStan compat).

KNOWN LIMITATION: на этой Windows машине pao stream filter conflict при
serial run SupplierPortalClient+RefreshSupplierSessionJob combo.
Tests pass individually + парами. Production Linux CI не affected.
2026-05-11 06:46:13 +03:00
Дмитрий ac09603181 docs(specs): supplier integration design (Лидерра ↔ crm.bp-gr.ru)
Captures brainstorming output for two-way integration:
- Sharing model: один supplier-лид → много deal-копий клиентам Лидерры
- 3 supplier-проекта на источник (B1/B2/B3), shared между клиентами
- Dynamic limit adjustment через 20:30 МСК cron + AJAX rt-project-update
- Quota distribution Total/3 с приоритетом B1→B2 на остатке
- Instant FIFO routing по дате создания проекта клиента
- Резервирование обоих направлений: pending-changes queue + CSV reconciliation

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 11:02:19 +03:00
Дмитрий 20d4682e21 feat(backend): Sprint 2 Phase A — Pest 4 browser scaffold + mutation + lazy-loading + Larastan cache
Sprint 2 Phase A (modernization). Закрытие audit O-stack-01/02/03 + O-perf-07:

- O-stack-01: Pest 4 browser-tests scaffold. testsuite Browser в phpunit.xml,
  Pest.php extend(...)->in('Browser'), tests/Browser/SmokeTest.php
  (login-flow + deal-create-flow). На Windows native PHP плагин
  pest-plugin-browser требует ext-sockets (отсутствует в стандартной
  сборке) и при автозагрузке вызывает socket_create_listen() ДО старта
  тестов, что ломает весь Pest. Поэтому плагин НЕ в require-dev,
  тесты помечены ->skip(...) с инструкцией активации на Linux CI.
  Скелет тестов в комментариях — на CI достаточно
  composer require pestphp/pest-plugin-browser --dev + npx playwright
  install + раскомментировать тела.
- O-stack-02: infection/infection ^0.32.7 в require-dev + app/infection.json
  (minMsi=50, source: Http/Models/Services). composer mutation script.
  Запуск отдельной задачей в CI (медленный). allow-plugins для
  infection/extension-installer.
- O-stack-03: Laravel 13 string-based lazy-loading в routes/web.php —
  убран блок use App\Http\Controllers\Api\* (16 импортов), все
  ссылки заменены на строки 'App\Http\...\X@method'. Контроллеры
  не загружаются автозагрузчиком при boot route'ов; класс резолвится
  только при матче маршрута. Использован строковый синтаксис, а не
  FQN-class — Pint default preset (fully_qualified_strict_types fixer)
  сворачивает FQN-class обратно в use, на строки не действует.
- O-perf-07: Larastan result cache через tmpDir: .phpstan-cache в
  phpstan.neon (cache-dir не дублируется флагом — phpstan не принимает
  оба источника). lefthook job 6 (larastan) использует этот же
  tmpDir автоматически. Ускорение инкрементальных pre-commit прогонов:
  на правке одного файла — переанализ только зависящих, не всего
  графа классов. .phpstan-cache в .gitignore.

Pest: 416/416 PASS + 2 skipped (browser smoke pending Linux CI).
Larastan: 0 errors above baseline.
Infection: vendor/bin/infection --version → 0.32.7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 19:18:38 +03:00
Дмитрий cc6e1cba72 fix(configs): Windows-fix format:sql:check + lychee/pa11y/composer/ESLint hygiene + npm-outdated CI (audit P0-03 + 5 P1/O)
Закрытие аудита 2026-05-09 (b6ae8dd):
- P0-03: format:sql:check заменён /tmp/ на db/.schema-formatted.tmp.sql (Windows-совместимо).
  + .gitignore: добавлен db/.schema-formatted.tmp.sql.
  + дополнительно: web/**/*.html убран из npm run links — статические концепты
    web/v8/*.html используют root-relative ссылки на будущие маршруты Vue, lychee
    не резолвит их без --root-dir; они уже в exclude_path. Lychee с 20 → 1 error
    (оставшийся 1 — pre-existing битая ссылка в docs/superpowers/specs/, вне scope).
- P1-02: .lychee.toml exclude root-relative для web/v8/*.html — добавлен regex
  паттерн для будущих маршрутов (login/register/legal/dashboard/deals/admin/...).
- P1-12: pa11y.config.json пути обновлены на liderra_v8_handoff/concepts/v8_*.html
  (login/dashboard/deals).
- P1-07: composer audit-offline скрипт (composer audit --locked) для офлайн-режима.
- O-refactor-05: ESLint no-restricted-imports запрещает явный import из 'vuetify/components'.
- O-stack-08: .github/workflows/dependency-check.yml — еженедельный (Mon 09:00 UTC) npm outdated с авто-issue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:31:17 +03:00
Дмитрий c3e45343ac phase2(histoire): #24 Histoire 1.0-beta.1 — каталог компонентов, фаза 2 закрыта 6/6
- histoire@1.0.0-beta.1 + @histoire/plugin-vue@1.0.0-beta.1 (--legacy-peer-deps:
  Histoire требует vite ^7, у нас vite 8 ради @vitejs/plugin-vue 6 — runtime smoke OK).
- app/histoire.config.ts: HstVue plugin + setupFile + Forest primary palette (Teal #0F6E56).
- app/resources/js/histoire.setup.ts: defineSetupVue3 регистрирует vuetify для каждой story.
- app/resources/js/components/AppShell.story.vue — первая story (smoke).
- npm-scripts: story / story:build / story:preview.
- .gitignore: /app/.histoire/ (статическая сборка).
- cspell-words.txt: рендерятся, репо, тулчейна.
- Регресс: lint:vue, type-check, format:check OK; vitest 3/3 за 2.98s; vite build 158 модулей
  за 334ms; story:build 1/1 за 30.25s; Pest 48/48 за 5.12s.

Активно 18/28 инструментов: 9 фазы 0 + 8 фазы 1 + 6 фазы 2 (фаза 2 по тулчейну закрыта).

CLAUDE.md v1.17->v1.18, Tooling v1.6->v1.7, реестр Открытых_вопросов v1.26->v1.27.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:29:42 +03:00
Дмитрий b0be139845 chore(gitignore): подготовка к фазе 1 — Laravel в app/ + игнор лендинг/
Подготовка перед composer create-project laravel/laravel app
(стратегия B — Sail на Windows FS, monorepo).

Расширены Laravel-пути:
- /app/vendor/, /app/node_modules/, /app/public/build/
- /app/storage/{app/public,framework,logs}/, /app/bootstrap/cache/*
- /app/.env*, /app/auth.json, /app/.phpunit.cache/, /app/.pest.cache/
- /app/.idea/, /app/.vscode/, /app/Homestead.{json,yaml}
- !/app/storage/logs/.gitkeep, !/app/bootstrap/cache/.gitkeep
  (Laravel требует пустые папки)

Также игнорируем лендинг/ — локальный дизайнерский трек
(TZ_landing_v1_0.md + README + ZIP-handoff ~9.5 МБ для дизайнера),
не должен случайно попасть в основной репо.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 08:33:33 +03:00
Дмитрий 887abf444e rebrand(v8.5→Лидерра): дизайн-handoff Платона v8 Forest + Лидпоток→Лидерра
Получен handoff-пакет liderra_v8_handoff/ от дизайнера Платона
(kpd9363@gmail.com) от 07.05.2026 — v8 Forest. Заказчик 08.05 решил
применить только в части дизайна, имени, логотипа. Функционал, состав
страниц и правила (CTO-11, click-wrap, SSO break-glass, 14 статусов
воронки) — без изменений (источник — ТЗ v8.5/schema v8.5).

Что сделано:

- Массовая замена Лидпоток→Лидерра (с учётом падежей: Лидерры/Лидерре)
  в 33 файлах (449 вхождений) — все .md/.sql/.json/.toml/.yml/.txt/.html,
  кроме исторических упоминаний внутри liderra_v8_handoff/
- Удалён docs/brandbook.md v1.1 — заменён на BRANDBOOK_v2.md из handoff
- Скопированы 13 концептов liderra_v8_handoff/concepts/v8_*.html в
  web/v8/. Удалены старые web/01-login.html, 02-dashboard.html,
  03-deals.html, index.html (палитра v1.1 deprecated)
- CLAUDE.md v1.0→v1.1: §0 (BRANDBOOK_v2 + DEVELOPER_HANDOFF в источниках),
  §2 (палитра Forest, Inter+JBM, Lucide), §5 п.6 (anti-pattern Inter
  снят — в Forest Inter наш основной шрифт), §6 (13 концептов в web/v8/)
- Реестр Открытые_вопросы_v8_3.md v1.12→v1.13: добавлена запись о
  ребрендинге + 4 точечных расхождений handoff vs ТЗ (статусы воронки,
  click-wrap чекбоксы, SSO fallback, axe violations)
- package.json/package-lock.json: name lidpotok→liderra

4 расхождения handoff vs ТЗ (НЕ применены, источник истины — ТЗ/schema):

1. 14 «обобщённых» статусов в BRANDBOOK_v2 §3.6 ≠ 14 slug'ов в
   schema.sql:2076 (совпадает 2 из 14: «Переговоры», «Оплачено»).
   Источник — schema/ТЗ §6.4 (реселлерская модель из аудита crm.bp-gr.ru,
   6 системных + 8 настраиваемых статусов).
2. 3-й click-wrap в v8_login.html («маркетинг-опционально») ≠ ТЗ §1.5/§4.1
   («согласие на ПДн», обязательное, OPEN-Ж-3).
3. SSO в v8_admin.html («локальный 2FA fallback») ≠ ТЗ OPEN-И-13
   (break-glass super_admin, локальный 2FA выключен).
4. Заявление «axe-core 4.10.2 — 0 violations» в README handoff — локально
   Pa11y 9.1.1 + axe нашёл 81 violation на 10/13 HTML (преимущественно
   color-contrast на декоративных separator'ах с --ink-disabled).
   Чисто: settings/errors/palette_options.

Что НЕ включено в коммит:
- лендинг/TZ_landing_v1_0.md — untracked, не моя работа в этой сессии
- .tmp/ — gitignored

Что осталось (для следующих сессий):
- Возможное переименование GitHub-репо CoralMinister/lidpotok → liderra
  (отдельное решение заказчика)
- Опционально: обратная связь Платону по 4 расхождениям handoff vs ТЗ

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 07:11:58 +03:00
Дмитрий 185e663415 chore(migration): exclude orphan session/tmp dirs from old machine
After move from c:\Users\KDV\Projects\lidpotok (Win10) to
c:\моя\проекты\портал crm\Документация (Server 2022, 07.05.2026):
- c--Users-*/ — JSONL-сессии Claude со старой машины (~24 МБ)
- .tmp/ — рабочая папка Playwright MCP

Гипотеза «репо удалён» при первом 404 от fine-grained PAT была ошибкой:
PAT просто не имел Repository access. После восстановления через Git DB API
все 24 коммита истории на месте.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:46:34 +03:00
Дмитрий f1ea6a15a6 fix(config): B-1 — конфигурационные находки аудита B (P0+P1)
- cspell-words.txt: удалено сломанное `ofеrtу` (кириллица в латыни,
  пропущено мимо словаря; нормальные `оферта`/`оферты` уже есть).
- .gitignore: `.playwright-mcp/` → `**/.playwright-mcp/` (артефакт может
  появиться в любом подкаталоге, не только в корне).
- pa11y.config.json: добавлен `web/03-deals.html` (готовый прототип №03,
  ранее не попадал в a11y-check).
- lefthook.yml: pre-push +lychee-links — битые ссылки ловятся до push,
  как и было задумано (Прил. Н §1, в комментарии было, в jobs не было).
- CLAUDE.md §4: `gitleaks detect` / `gitleaks protect` → `./bin/gitleaks.exe ...`
  (на Windows бинарь в `bin/`, не в PATH).
- README.md: подпись `Прил. Л v0.1 от 05.05.2026` → `v0.4 от 06.05.2026`,
  синхронизация с таблицей версий (последняя запись v0.4).

Линтеры (markdownlint, cspell на затронутых .md) — чисто.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 23:31:14 +07:00
Дмитрий 28083f07c8 chore(gitignore): exclude .claude/settings.local.json
Per-machine Claude permissions — не должны попадать в общий репозиторий.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:49:54 +07:00
Дмитрий 13c6f29f29 chore(gitignore): exclude Playwright MCP artifacts
После первого демо Playwright MCP в корне создался скриншот
demo-01-login-fullpage.png и временная директория .playwright-mcp/.
Добавил соответствующие паттерны в .gitignore, чтобы будущие screenshot'ы
и DOM-snapshot'ы не попадали в коммиты.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:57:22 +07:00
Дмитрий 6ff05fd7ea chore: phase 0 tooling baseline
Установлены 9 инструментов фазы 0 + lefthook для pre-commit/pre-push hooks.

Конфиги в корне:
- package.json + package-lock.json (10 dev-deps, 7 npm-скриптов)
- .markdownlint.json + .markdownlintignore — стиль Markdown
- cspell.json + cspell-words.txt — орфография ru/en + 350+ проектных терминов
- .lychee.toml — проверка ссылок с игнором плейсхолдеров
- .stylelintrc.json — стиль CSS в HTML-прототипах
- .gitleaks.toml — 8 кастомных правил для РФ-контекста (телефон, ИНН, ОГРН,
  паспорт, Yandex Cloud-tokens, webhook secrets) + allowlist для масок
- pa11y.config.json — WCAG 2.1 AA для web/01-login.html и web/02-dashboard.html
- .mcp.json — 3 MCP-сервера (Playwright, GitHub через офиц. hosted endpoint,
  PostgreSQL — заглушка)
- .gitignore — node_modules, bin/*, артефакты + задел на фазы 1–3
- .claude/settings.json — permissions allow/deny + хук авто-fix .md
- lefthook.yml — pre-commit (gitleaks + markdownlint + cspell + stylelint)
  и pre-push (полный gitleaks по истории)

Связано: docs/Tooling_v8_3.md (Прил. Н v1.0) — реестр 28 инструментов в 4
фазах; CLAUDE.md в корне — оперативная карта приоритета правил и команд.

Архитектурных изменений в проекте: 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 04:44:20 +07:00