Дмитрий
084a952bfa
feat(models): add SupplierSyncLog model + factory (audit trail для AJAX-sync)
...
- app/Models/SupplierSyncLog.php — fillable + casts (jsonb arrays + datetime)
+ supplierProject() BelongsTo relation (nullable, ON DELETE SET NULL —
лог переживает удаление supplier-проекта для audit-trail).
$timestamps = false (только created_at, без updated_at — append-only)
- database/factories/SupplierSyncLogFactory.php — реалистичные действия из enum
- tests/Feature/Models/SupplierSyncLogTest.php — 4 теста: factory,
supplier_project relation, jsonb array casts, nullable FK lifecycle
Pest: 463 / 461 passed / 2 skipped (457 + 4 новых = 461).
Larastan: 0 errors. Pint passed.
Spec: §4.3
Plan: Task 9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 16:53:55 +03:00
Дмитрий
31f813315d
feat(models): add LeadCharge ledger model + factory + relations to Tenant/Deal
...
- app/Models/LeadCharge.php — fillable + casts (datetime + integer)
+ tenant() BelongsTo relation
+ deal() BelongsTo relation (по deal_id, без deal_received_at — composite PK
на партиционированной обеспечивается БД-уровнем через FK)
+ accessor priceRubles (kopecks → float)
- database/factories/LeadChargeFactory.php — НЕ создаёт реальный Deal автоматически
(composite FK requires (deal_id, deal_received_at) пары); тесты с FK-целостностью
явно создают Deal::factory() и передают пару в state()
- tests/Feature/Models/LeadChargeTest.php — 4 теста: factory, tenant relation,
deal relation, priceRubles accessor. testing_rls_user setup в beforeEach
для проверки RLS context из не-superuser контекста.
Quirk: SET LOCAL app.current_tenant_id НЕ принимает параметрическое связывание PG —
используем string interpolation с {$tenant->id} как в RlsSmokeTest pattern.
ide-helper:models -W -M -N синхронизировал docblocks (WebhookDedupKey).
Pest: 459 / 457 passed / 2 skipped (453 + 4 новых = 457).
Larastan: 0 errors. Pint passed.
Spec: §7.4
Plan: Task 8
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 16:52:10 +03:00
Дмитрий
71e38ee0a9
feat(models): add PricingTier model with kopecks→rubles accessor + current() snapshot
...
- app/Models/PricingTier.php — fillable + casts (date, boolean, integer)
+ accessor priceRubles (kopecks → float rubles)
+ scopeActive (is_active=true AND effective_from <= today)
+ static current() — keyed by tier_no Collection<int, PricingTier>
- database/factories/PricingTierFactory.php — реалистичные ступени (300/700/1000/.../null)
- tests/Feature/Models/PricingTierTest.php — 4 теста: factory, accessor,
scopeActive, current() snapshot всех 7 ступеней
ide-helper:models -W -M -N перегенерил docblocks (WebhookDedupKey synced
после schema v8.16).
Pest: 455 / 453 passed / 2 skipped (449 + 4 новых = 453).
Larastan: 0 errors. Pint auto-fix.
Spec: §7.2
Plan: Task 7
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 16:48:00 +03:00
Дмитрий
62aa55f033
feat(models): add SupplierProject Eloquent model + factory + tests
...
- app/Models/SupplierProject.php — fillable + casts (jsonb arrays + datetime)
+ scopes: active() (inactive_since IS NULL), staleSince(N days),
forSignal(signal_type, unique_key)
- database/factories/SupplierProjectFactory.php — корректно учитывает
chk_supplier_projects_b1_not_for_sms (B1 не порождает SMS-проекты)
- tests/Feature/Models/SupplierProjectTest.php — 6 тестов: factory,
array casts (workdays + regions), scopeActive, scopeStaleSince,
scopeForSignal (3 платформы на один домен — UNIQUE (platform,unique_key))
ide-helper:models -W -M -N перегенерил docblocks для 4 существующих моделей
(SaasAdminAuditLog, SystemSetting, UserRecoveryCode, ImpersonationToken) —
синхронизировал @property после schema v8.16.
Pest: 451 / 449 passed / 2 skipped (было 443+6 новых от Task 6 = 449).
Larastan: 0 errors. Pint: passed.
Spec: §2.2
Plan: Task 6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 13:59:39 +03:00
Дмитрий
757f963929
fix(db): consolidate Plan 1 Tasks 1-5 into schema.sql (project convention)
...
Project convention использует schema.sql как single source of truth + один
load_initial_schema migration вместо incremental migrations. Мои 5 incremental
миграций конфликтовали с migrate:fresh: load_initial_schema применял
обновлённый schema.sql v8.16, а потом 000001-000005 пытались добавить уже
существующие колонки/таблицы (`signal_type already exists`).
Изменения:
- Удалены 5 incremental миграций 2026_05_10_00000{1..5}_*.
Все DDL уже в schema.sql (v8.11 → v8.16, 4 commits 2ebe000/9b99d81/
b08e1ed/7f694f7/9cf380f).
- В schema.sql lead_charges FK на partitioned deals(id, received_at)
вынесен в самый конец файла (после section 5 с deals), DEFERRABLE
INITIALLY DEFERRED. Иначе DB::unprepared() выдаёт "deals не существует"
на load.
- Тесты в tests/Feature/Integration/ остаются — они проверяют
структурные свойства (column existence, constraint name, RLS via
pg_class) через information_schema, не зависят от того как именно
schema создалась.
Verification:
- migrate:fresh OK на обеих БД (liderra + liderra_testing)
- Pest: 445 tests / 443 passed / 2 skipped / 0 failed
(было 421 baseline + 24 новых для Tasks 1-5 = 443; +2 skipped browser tests)
- Larastan: 0 errors
- Pint: passed
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 13:50:39 +03:00
Дмитрий
9cf380f170
feat(db): create supplier_sync_log audit table (SaaS-level, append-only)
...
Append-only journal AJAX-синхронизаций с поставщиком crm.bp-gr.ru.
Используется для retry, отладки rt-project-* и алертов менеджеру.
- 9 columns: id, supplier_project_id (nullable FK SET NULL),
action, request_payload (jsonb), response_body (jsonb),
http_status, error_message, duration_ms, created_at
- 1 CHECK chk_supplier_sync_log_action
(create/update/delete/disable/session_refresh)
- 3 индекса: supplier_project_id, action, created_at
- REVOKE ALL FROM crm_app_user (DO $$ conditional)
- No RLS (SaaS-level)
Spec: §4.3
Plan: Task 5
Test: 4/4 passed (table, action enum, FK, no RLS).
Schema v8.15 → v8.16. Метрики: 60 таблиц (+1) / 108 индексов (+3).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 13:42:46 +03:00
Дмитрий
7f694f78e0
feat(db): create lead_charges ledger (tenant-scoped RLS, FK to partitioned deals)
...
Append-only ledger списаний за каждый доставленный лид. Tenant-scoped
с RLS tenant_isolation (ENABLE + FORCE + USING/WITH CHECK).
- 8 columns: id, tenant_id, deal_id, deal_received_at, tier_no,
price_per_lead_kopecks, charged_at, created_at
- Composite FK lead_charges_deals_fk(deal_id, deal_received_at) →
deals(id, received_at) DEFERRABLE INITIALLY DEFERRED
(deals партиционирована — DEFERRABLE для атомарного deal+charge)
- 2 индекса: (tenant_id, charged_at), (deal_id, deal_received_at)
- RLS на (tenant_id = current_setting('app.current_tenant_id')::bigint)
- GRANT SELECT, INSERT для crm_app_user (без UPDATE/DELETE — append-only)
Spec: docs/superpowers/specs/2026-05-10-supplier-integration-design.md §7.4
Plan: docs/superpowers/plans/2026-05-10-supplier-foundation-plan.md Task 4
Test: 3/3 passed (table exists, composite FK to deals, RLS enforces
tenant isolation via testing_rls_user role).
Schema v8.14 → v8.15. Метрики: 59 таблиц (+1) / 105 индексов (+2) /
39 RLS (+1) / функции/триггеры без изменений.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 13:38:17 +03:00
Дмитрий
b08e1edb33
feat(db): create pricing_tiers table (7-step volume billing, kopecks integer)
2026-05-10 12:54:02 +03:00
Дмитрий
9b99d81deb
feat(db): create supplier_projects table (SaaS-level aggregate, B1/B2/B3 platforms)
...
Plan 1/5 Task 2 — SaaS-level агрегатная сущность для проектов у поставщиков.
Несколько Лидерра-tenant'ов могут шарить один supplier_project (sharing-model
spec §2.3): для site/call — по domain/phone; для sms — по (sender, keyword)
на B2 или (sender) на B3. RLS НЕ применяется (таблица не tenant-scoped),
defense-in-depth через REVOKE ALL FROM crm_app_user.
Колонки: platform, signal_type, unique_key (TEXT), supplier_external_id,
current_limit, current_workdays/regions (jsonb), sync_status (pending/ok/failed),
last_synced_at, inactive_since (TTL 180 дней), timestamps.
CHECK constraints (chk_supplier_projects_*):
- platform IN (B1, B2, B3)
- signal_type IN (site, call, sms)
- sync_status IN (pending, ok, failed)
- NOT (platform=B1 AND signal_type=sms) — B1 не поддерживает СМС
Indexes: UNIQUE(platform, unique_key); btree на sync_status, inactive_since.
Тесты: 6/6 (table+columns / unique / platform CHECK / sync_status CHECK / no RLS / no privileges).
Schema: v8.12 → v8.13. Метрики: 56→57 таблиц / 98→101 индексов; RLS/функции/триггеры без изменений.
2026-05-10 12:47:25 +03:00
Дмитрий
2ebe000271
feat(db): extend projects for supplier integration (signal_type, identifier, sms_senders, sms_keyword, delivered_in_month, b1/b2/b3 FK placeholders)
...
Plan 1/5 Task 1. Adds 8 columns + 3 CHECK constraints + 1 composite index
to projects table for supplier integration foundation. Schema bumped
v8.11 to v8.12. Spec: docs/superpowers/specs/2026-05-10-supplier-integration-design.md §2.1.
7/7 Pest tests pass; rollback verified.
2026-05-10 12:40:02 +03:00
Дмитрий
7ab7cf51cb
docs(plans): supplier integration plan 1/5 — Foundation (schema + models + validators)
...
12 tasks + 3 verification gates covering:
- 5 migrations: extend projects, supplier_projects, pricing_tiers, lead_charges, supplier_sync_log
- 4 new Eloquent models + factories + Pest unit tests
- Project model extension with signal_type/sms_*/supplier_b1/b2/b3 relations
- 3 signal validators (Domain, Phone, SmsSender) with edge-case datasets
- SupplierProjectResolver service with B1+SMS guard
- Comprehensive verification gate: Larastan + squawk + pgFormatter + cspell + markdownlint + cycle-check + code-review subagent
Spec: docs/superpowers/specs/2026-05-10-supplier-integration-design.md §2, §7
cspell-words: +vashinvestor
.gitleaks.toml allowlist: +test phones for validator datasets
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 12:10:04 +03:00
Дмитрий
3f463f48ea
docs(specs): close all 7 open questions in supplier integration design
...
Q1 SMS validation: B2 = (sender, keyword), B3 = sender only; B1 not available
Q2 Supplier pricing: фиксированная цена за лид
Q3 Liderra billing: 7-tier volume pricing, monthly reset (config in admin)
Q4 Geo filter: MVP, union at supplier + filter on our side
Q5 Webhook auth: defense-in-depth (IP allowlist + secret token in URL)
Q6 Cookie/CSRF refresh: hourly headless Playwright cron + reactive on 401/403
Q7 supplier_project TTL: immediate disable, delete after 180 days no activity
cspell-words.txt: +геофильтр, логинится, encrypter, PHPSESSID
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 11:39:29 +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
Дмитрий
528fe16166
docs(plans): Sprint 6 Phase A — Reports backend implementation plan
...
6 tasks: 3 providers (managers/sources/billing) + registry extension +
S3 disk abstraction + file download endpoint. TDD with Pest 4.
Corrects schema column names vs spec (manager_id, type, balance_rub_after)
and uses May 2026 test dates (partitions start 2026-05-01).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-10 09:38:43 +03:00
Дмитрий
2a6f0289db
docs(spec): Sprint 6 Post-MVP backend design (Reports + Notifications + AdminTenantDetail)
2026-05-10 09:13:45 +03:00
Дмитрий
e5848bddec
feat(tooling): Trivy CI workflow prep — disabled until YC Docker ( #26 )
2026-05-10 08:45:17 +03:00
Дмитрий
7123123b48
chore(claude): allow npm run sast in settings.json ( #25 )
2026-05-10 08:43:52 +03:00
Дмитрий
40125ba5a5
feat(tooling): Semgrep MCP server in .mcp.json ( #25 )
2026-05-10 08:42:25 +03:00
Дмитрий
53fb1ec27e
feat(ci): Semgrep SAST workflow — push/PR to main ( #25 )
2026-05-10 08:40:52 +03:00
Дмитрий
5983cc17e3
feat(tooling): Semgrep config + npm run sast script ( #25 )
2026-05-10 08:39:34 +03:00
Дмитрий
3112584ab8
chore(deps): add Dependabot config — npm×2 + composer weekly ( #27 )
2026-05-10 08:36:36 +03:00
Дмитрий
3c13cc5d64
docs(rules): третий аудит нормативки — закрытие 13 находок (CLAUDE.md v1.86 + PSR_v1 v1.7 + Tooling v1.15)
...
P0 (4) — арифметические конфликты в CLAUDE.md, прошли мимо второго аудита:
- §3 header «Карта 28 инструментов» → «33» (header застрял с pre-FD эпохи)
- §3.4 header «(+5, итого 28)» → «итого 29» (после #30 в фазу 2)
- §3.3 footer «из 30 номеров минус #1 = 29» → «33 номеров: 29 phase-active + 3 off-phase + 1 historic»
- §6 «Активно: 19 инструментов из 29» (vs раскладка 9+8+7=24) → «24» в обоих местах
P1 (5) — sync stale `+`-refs после второго аудита:
- PSR_v1 шапка: «CLAUDE.md v1.84+/Pravila v1.9+» → «v1.86+/v1.10+»
- Tooling шапка: «Pravila v1.9+/PSR_v1 v1.5+/CLAUDE.md v1.84+» → «v1.10+/v1.7+/v1.86+»
- CLAUDE.md §5 п.5 «PSR_v1 v1.5+» → «v1.7+»
P2 (2) — внутренние несогласованности:
- PSR_v1 line 4/856 «slot уровня 2.5» → «уровня 2b» (описка внутри changelog'а v1.6)
- CLAUDE.md §3.3 #33 «вне Pravila §13» → «вне UI-пула §13» (Pravila §13.2 v1.10 включает claude-md-management как infrastructure subsection)
Sync-правки в connected files:
- README.md + README_АРХИВ_v8_5.md «карта 28 инструментов» → «33»
- Tooling §11.5/§12 «не входят в 28 инструментов» → «33 формализованные позиции»
Через `/claude-md-management:claude-md-improver` с cross-impact-анализом перед каждой группой правок. Pravila v1.10 без изменений (cross-refs к нему уже актуальны).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 06:32:17 +03:00
Дмитрий
07ed3f1be6
docs(rules): второй аудит нормативки — закрытие 15 находок (CLAUDE.md v1.85 + Pravila v1.10 + PSR_v1 v1.6 + Tooling v1.14)
...
Закрыто 15 находок второго аудита правил использования плагинов и скилов
(4 P0 реальных противоречий + 7 P1 stale-refs + 4 P2 структурных).
Через `/claude-md-management:claude-md-improver`.
P0 — реальные противоречия:
- Tooling §10.3 шаг 2: «3 skills» → «14, все запреты сняты Pravila §11»
(закрыта внутри-документная контрадикция с §4.1 того же файла)
- CLAUDE.md §6: арифметика «33» исправлена (+1 заменённый PG MCP
исторически; раньше 19/29 + 3 = 32, не 33)
- Pravila §13.2: «v1.4 (15 правил)» → «v1.6 (16 правил R0–R15)»
- Tooling §13: добавлены v1.13 + v1.14 entries (раньше история
обрывалась на v1.12, хотя шапка описывала v1.13)
P1 — массовый stale-refs дрейф v1.4→v1.6 + v1.12→v1.14:
- CLAUDE.md §0 cross-refs (Pravila/PSR_v1/Tooling rows), §3.3 #31 , #32 , §5 п.12
- Pravila §11.5 («10 правил»→«16»), §13.9, §13.10
- Tooling §4.4 («10 правил»→«16»), §4.5, §4.6, §4.7
P2 — структурные:
- Tooling Прил. Н добавлен explicit-слотом уровня 2b в priority chain
(CLAUDE.md §1, PSR_v1 R0.1 таблица, Tooling §7) — раньше формальная
дыра «PSR_v1 R0.1 говорит stack ниже Tooling, но Tooling нет ни
в одной priority chain»
- PSR_v1 R0.4.A свёрнут до cross-ref на Pravila §12.3 SoT — устранён
риск дрейфа формулировок (раньше параллелил список разной формулировкой)
- Pravila §0 +note про §11 локальное override-исключение над §2.2/§4.5/§8.4
(раньше §11 формально стоял ниже §9 в цепочке вопреки фактическому
override §2.2/§4.5/§8.4 при skill-инвокации)
- PSR_v1 R0.6 hard-стопы пронумерованы 1–11 для надёжности cross-refs
«пункт 9/10/11» (раньше буллет-list, ссылки молча ломались)
Все 4 файла нормативной документации внутренне непротиворечивы.
История версий синхронизирована.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 05:56:43 +03:00
Дмитрий
ffe34e1b17
docs(registry): Sprint 4 «Audit tail» closure record (v1.76→v1.77)
...
Sprint 4 закрыл 3 оставшихся audit O-* пункта (5 коммитов f77c91d..b912724):
- O-perf-04: keyset pagination в DealController::index + 3 Pest-теста
- O-refactor-04 хвост: 8 Vue-компонентов >300 строк разделены (AppLayout
R0.6 hard-стоп снят явным запросом заказчика)
- O-refactor-06: rollup-plugin-visualizer + knip + cleanup ~165 строк
dead-code в composables/
Acceptance закрыт за исключением 2 known DealsView/DealDetailDrawer
(intentional Sprint 3 defineExpose-контракт).
Регрессия: Pest 421 / Vitest 416 / Larastan 0 / vue-tsc 0 / ESLint 0 / build OK.
Sprint 0 push выполнен (4f36bd3..8c6374d, 21 коммит). PAT Workflows R&W
подтверждена через API-диагностику.
CLAUDE.md/Pravila/Tooling/Plugin_stack_rules — параллельно обновляются
другой сессией (PSR_v1 v1.4 формализация UPM/21st/R15 motion в локальных
коммитах 833e3e6 + cf1aabb ), не трогаю в этом коммите.
cspell-words: +oxc (oxc-parser Windows quirk knip), +консты (Russian slang).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 05:06:47 +03:00
Дмитрий
27dec3d459
docs(rules): аудит нормативки — закрытие 14 находок (CLAUDE.md v1.84 + Pravila v1.9 + PSR_v1 v1.5 + Tooling v1.13)
...
Audit конфликтов и запутанностей между CLAUDE.md / Pravila / PSR_v1 / Tooling
выявил 14 находок (3 🔴 high, 6 🟡 medium, 5 🟢 low). Все правки — через
paired stack: writing-plans → executing-plans → claude-md-improver (для
CLAUDE.md по §5 п.10) → verification-before-completion с grep-evidence.
Ключевые правки:
1. claude-md-management формализован #33 в Tooling §4.7 — пятый
включённый плагин (категория «инфраструктурная», вне UI-пула).
Tooling §0 счётчик 31 → 33 (3 off-phase tools).
2. Tooling §7 + PSR_v1 уровнем 3 — иерархия source of truth расширена
с 5 до 7 уровней, sync с CLAUDE.md §1.
3. Tooling §6 +5 конфликтов v1.4 — UPM↔FD, 21st↔Vuetify, 21st↔App*,
framer↔motion-v, UPM↔21st (с 5 до 10 строк).
4. Pravila §12.3 объявлен Single Source of Truth для exclusions §12;
PSR_v1 R0.4.A + CLAUDE.md §5 п.11 — cross-ref сюда.
5. Pravila §13.6 +tier-таблица hard-rule (explicit / transitive /
standard) — снимает скрытую иерархию между §12 и §13.9/§13.10.
6. PSR_v1 R10.1 разбит на 3 блока: enabledPlugins / built-in skills
Claude Code / MCP-серверы — раньше всё было одним списком.
7. PSR_v1 R8 +тай-брейкер FD↔21st (последовательно, FD ведущий).
8. PSR_v1 R10.4 + R14.7 — tier-метки transitive hard-rule с явным
указанием, что Pravila §9 «Отступления» к ним не применяется.
9. Scope-метки приоритетных цепочек — Pravila §0 (внутрипараграфный),
CLAUDE.md §1 (межфайловый), PSR_v1 R0.1 (scope головенства stack'а).
Снимает путаницу 4-х представлений.
10. CLAUDE.md §5 п.5 свёрнут до 2 строк со ссылкой на PSR_v1 R14
(был копией PSR_v1 на 12 строк).
11. Tooling §4.6 — settings.json → ~/.claude.json (где реально лежит
API-ключ 21st).
cspell-words.txt: +внутрипараграфный, внутрипараграфные, скилов
(новые термины из scope-меток и plan-файла).
Намеренно оставлено: R0.6 пункт 11 ⊂ пункт 6 (motion-специальный flow);
Pravila §13.10 формально избыточен (явная запись лучше транзитивного).
Plan: docs/superpowers/plans/2026-05-10-rules-audit-fixes-plan.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 05:06:16 +03:00
Дмитрий
b912724cf7
chore(frontend): Sprint 4 Phase C — bundle analyzer + dead-code cleanup (audit O-refactor-06)
...
- rollup-plugin-visualizer + script `npm run build:analyze` (env BUILD_ANALYZE=1)
Output: storage/bundle-analyze.html (gzip + brotli sizes), gitignored.
- cross-env установлен для Windows-совместимости env-переменной build:analyze.
- knip + knip.config.ts (entry app.ts + router/index.ts; ignore *.story.vue + tests/).
ВАЖНО: knip падает с oxc-parser ArrayBuffer fail на этой машине
(Windows quirk feedback memory) — конфиг сохранён для будущих запусков на
Linux/macOS CI. Dead-code search выполнен вручную через grep по composables/.
- Удалены 4 unused exports + 4 private helpers, инициируемых только ими:
* mockReports.ts: MOCK_JOBS, QuotaInfo (interface), MOCK_QUOTA
* reportsMapper.ts: reportTypes()
* mockTenantDetail.ts: expandTenantDetail() + 4 SAMPLE_* consts
(SAMPLE_USERS/SAMPLE_PROJECTS/SAMPLE_BALANCE_HISTORY/SAMPLE_ACTIVITY)
* useCsvDownload.ts: csvEscape() — снят `export` (используется внутри файла)
ESLint + vue-tsc + Vitest 416/416 + build — зелёные.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:59:58 +03:00
Дмитрий
79ff60ffd9
refactor(frontend): Sprint 4 Phase B/3 — split 2 utility views (audit O-refactor-04 хвост)
...
ErrorView 320→178 (+ ErrorBrand 54 + ErrorIllustration 31 + ErrorActions 55 + ErrorMeta 102).
DashboardView 302→84 (+ DashboardPageHead 65 + DashboardKpiRow 97 + DashboardBalance 124).
State (config, errorCode в ErrorView; range/kpis/balance в DashboardView) остаётся
в parent ради единого route.meta-driven flow + future API-fetch'а (Phase B/1 паттерн).
DashboardPageHead использует Vue 3.5 defineModel<T>() для двусторонней привязки range.
Sub-components читают только props — без Pinia stores (mock-data flow).
Все sub-components <250 строк (acceptance threshold). Shell line counts: 178/84.
ЗАМЕЧАНИЕ по acceptance «0 components >300»: НЕ закрыто полностью. 2 файла остались
выше порога — DealsView 560 + DealDetailDrawer 386. Зафиксировано в Sprint 3 Phase C
commit 6c2f0ce : bulk-action функции (applyBulkStatus/applyBulkDelete/applyBulkExport/
undoBulkDelete/applyBulkRestoreFromTrash) и comment/reminders fetch экспонируются
через defineExpose в Vitest-тестах напрямую — дальнейшая декомпозиция требует
изменения тест-контракта (отдельным flow, не вошло в Sprint 4 Phase B).
Phase B/3 закрывает 8/12 audit-кандидатов O-refactor-04: 3 в Sprint 3 Phase C
(Top-3) + 5 в Sprint 4 Phase B/1+B/2 (admin/layout/billing/security/reminders) +
2 в B/3 (errors/dashboard). Оставшиеся: 2 крупных deals-view (defineExpose-blocked)
+ ImpersonationDialog уже <300 органически.
Регрессия: ESLint 0 + vue-tsc 0 + Vitest 416/416 + build OK 989 ms.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:53:09 +03:00
Дмитрий
849bc73290
refactor(frontend): Sprint 4 Phase B/2 — split 3 user views (audit O-refactor-04 хвост)
...
BillingView 416→114 (+ BalanceCard 155 + TransactionsTable 113 + InvoicesTable 90
+ billingFormatters 51 composable: formatPlain/formatCost/statusChipColor/
statusLabel/formatLabel/formatIcon/txAmountClass).
SecurityTab 354→39 (+ ChangePasswordCard 17 + TwoFactorCard 218 + RecoveryCodesCard 104
+ SessionsTable 66; auth-store читается напрямую в каждом sub-component).
RemindersView 345→183 (+ RemindersFilters 51 + RemindersList 173;
ReminderDialog уже отдельный с прошлой фазы — служит как ReminderForm).
State (`activeTab`, `editingReminder`, `deletingReminderId` в RemindersView)
остаётся в parent ради единого reload-flow + confirm-dialog'ов. Auth-store
читается напрямую в TwoFactorCard/RecoveryCodesCard через useAuthStore() —
без prop-drilling. Reminders-store читается напрямую в RemindersFilters/
RemindersList.
Все sub-components <250 строк (acceptance threshold). 3 view-shells: 114/39/183.
Регрессия: ESLint 0 + vue-tsc 0 + Vitest 416/416 + build OK 968 ms.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:46:14 +03:00
Дмитрий
30ef61dff8
refactor(frontend): Sprint 4 Phase B/1 — split 3 admin/layout views (audit O-refactor-04 хвост)
...
3 view'а с >300 строк разделены на shell + sub-components:
AdminTenantsView 377→155 (+ TenantsStatsHeader 82 / TenantsFilters 93 / TenantsTable 116).
AdminTenantDetailView 436→109 (+ TenantDetailHeader 158 / TenantDetailTabs 176
+ adminTenantDetailFormatters 43 composable).
AppLayout 466→78 (+ AppSidebar 155 / AppTopbar 269; R0.6 hard-стоп снят
явным запросом заказчика 10.05.2026).
State (filterStatuses, tenantsState, activeTab, tenant, drawerOpen) остаётся
в parent view'ах ради `defineExpose`-контракта Vitest тестов. Sub-components
читают Pinia stores напрямую (auth + notifications + reminders) — без
prop-drilling.
AppTopbar 269 строк <300 — acceptance threshold выдержан (можно дальше split на
NotificationsDropdown + UserMenu в отдельном flow, не критично).
Регрессия: ESLint 0 + vue-tsc 0 + Vitest 416/416 + build OK 1.17 сек.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:38:08 +03:00
Дмитрий
cf1aabb32e
chore(cspell): добавлены UPM, gsap, LLM в словарь проекта
...
Сопровождает v1.83 docs-патч (PSR_v1 v1.4 формализация UPM + 21st Magic MCP).
Без этих записей pre-commit hook cspell блокирует коммит на CLAUDE.md /
PSR_v1 / Pravila / Tooling / CHANGELOG_claude_md, где термины используются.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:34:15 +03:00
Дмитрий
833e3e6083
docs(rules): PSR_v1 v1.4 — формализация UPM + 21st Magic MCP + R15 motion-системы
...
Триггер: пользователь спросил «хочу добавить плагины 21st, framer motion,
UI UX max — проанализируй конфликты». Проверка показала: UPM (skill) и 21st
Magic MCP (`magic` сервер) уже фактически включены в ~/.claude/settings.json
и ~/.claude.json, но в правилах не описаны. Framer Motion — React-only
runtime npm-библиотека, не Claude-плагин, физически не работает в Vue.
Через цикл brainstorming → 3 варианта → итерации согласовано: формализовать
UPM + 21st; для motion — двухуровневая R15 (framer-motion hard-запрет
навсегда + motion-v узкое окно по 4 условиям).
PSR_v1 v1.3 → v1.4 (главный артефакт):
- R6 → R6.0 универсальная таблица фильтра для FD/UPM/21st
- R6.1 hard-override Forest расширен на все три плагина
- R10.1 +21st row, ослабление UPM (FD молчит ИЛИ R12 третий вариант)
- R11.5 (новое) активация UPM в R12 архитектурном
- R11.6 (новое) иерархия 7 motion-источников
- R0.6 +3 hard-стопа (App* через 21st, Vuetify-эквивалент, motion-v)
- R13 +9 строк matrix'а
- R14 (новое, 7 подразделов) pipeline UPM + 21st
- R15 (новое, 7 подразделов) motion-системы
- R8 +7 тай-брейкеров
Pravila v1.7 → v1.8: §13 расширен на расширенный пул, §13.10 hard-link на R14.
Tooling Прил. Н v1.11 → v1.12: #31 UPM + #32 21st (off-phase tools), §9.2
motion-runtime denylist (framer-motion + react-spring R15.1; motion-v + gsap
+ anime + lottie + popmotion R15.2/R15.7). 31 формализованных позиций
(19/29 активных по фазам + 2 off-phase).
CLAUDE.md v1.82 → v1.83: §0 cross-refs, §2 +Animation default stack, §3.3
+#31 UPM +#32 21st, §5 п.5 расширен, §5 п.12 motion-runtime новый,
§6 обновлён, §9 +entry.
cspell-words.txt: +UPM +gsap +LLM (валидные термины проекта).
Через /claude-md-management:claude-md-improver. 6 файлов, 0 изменений
в коде проекта (resources/js/, app/, db/ нетронуты), 0 npm install.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:33:42 +03:00
Дмитрий
f77c91d5fa
feat(backend): Sprint 4 Phase A — keyset pagination в DealController::index (audit O-perf-04)
...
Опциональный query-параметр `cursor` (base64-encoded JSON {r:received_at, i:id}).
При cursor — keyset через PG row constructor `(received_at, id) < (?, ?)`
с использованием существующего индекса (received_at DESC, id DESC).
O(1) на любой глубине, без COUNT(*) (total не возвращается в keyset-режиме).
Без cursor — backward-compat OFFSET-путь: total + offset для существующего
frontend. Оба режима возвращают next_cursor (NULL = последняя страница).
Trick "+1 fetch" — узнаём про следующую страницу одним SELECT'ом без COUNT.
3 новых Pest-теста: keyset-навигация через cursor, 422 на невалидный cursor,
next_cursor flow. Pest 421/421 (419 + 2 skipped browser, +3 от 418 baseline).
phpstan-baseline.neon регенерирован: +2 occurrences pattern
`received_at?->toIso8601String()` (cursor build) + 7 occurrences тестовых
helper-properties Pest TestCall — все известные ignored patterns, не реальные ошибки.
Frontend integration в useDealsList/DealsView — отдельным шагом
(не блокирует backend deploy, OFFSET путь жив).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:29:54 +03:00
Дмитрий
8c6374d278
docs(spec-roadmap): fix broken link to memory/project_state.md (outside repo)
...
lychee pre-push hook поймал invalid markdown link на memory/project_state.md —
файл живёт в C:\Users\Administrator\.claude\projects\... (Claude auto-memory),
не в репозитории. Заменено на plain-text упоминание.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 04:12:58 +03:00
Дмитрий
823daf4f9f
docs(plan-sprint4): implementation plan «Audit tail» + revised spec scope
...
Sprint 4 — закрытие 3 оставшихся audit O-* пунктов:
- Phase A: O-perf-04 keyset pagination в DealController::index
- Phase B (1+2+3): O-refactor-04 хвост, split 8 Vue-компонентов >300 строк
- Phase C: O-refactor-06 dead-code detection через rollup-plugin-visualizer + knip
Spec ревизия: Sprint 4 уменьшен с 8 до 3 пунктов после факт-чека —
O-perf-07/O-refactor-05/O-refactor-07/O-stack-02/O-stack-03 уже закрыты
в Sprint 1–2 (Sprint 1 ESLint vuetify rule, Sprint 2 Phase A: Pest browser
scaffold, infection mutation, lazy-loading, Larastan cache; CLAUDE.md
header фактически 30 строк после 5b13c95 changelog extraction).
Финальная регрессия: Pest 419+ / Vitest 430+ / Larastan + ESLint + vue-tsc 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 03:57:46 +03:00
Дмитрий
77b018dff8
docs(spec-roadmap): дизайн roadmap'а до production — 3-track структура (A/B/C)
...
Покрывает категории A (audit-хвосты), B (Phase 3 tooling), C (Post-MVP backend),
D (Б-1-зависимые фичи), E (production deploy в YC). Категория F (юр. тексты) —
external; G (push 18 коммитов) — Sprint 0 precondition.
Двухдорожечная структура:
- Track A (Sprint 4–6): не зависит от Б-1, стартует сразу после push
- Track B (Sprint 7–9): после получения реквизитов ООО — YC infra + CI/CD + SSO + лендинг + hardening + soft-launch
Definition of done «production launch» в §1, per-sprint acceptance в §5,
9 рисков с mitigations в §6, 5 open questions для будущей детализации в §7.
Базовый HEAD: 6c2f0ce (после Sprint 3 Phase C).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 03:51:05 +03:00
Дмитрий
6c2f0ce682
refactor(frontend): Sprint 3 Phase C — Top-3 Vue components split (audit O-refactor-04)
...
Sprint 3 Phase C. Закрытие audit O-refactor-04 (частичное — Top-3 из 12):
- DealsView.vue: 852 → 560 строк. Выделены: DealsFilters (123), DealsBulkBar (150),
DealsTable (165). CSV-utilities (csvEscape/triggerCsvDownload/triggerBlobDownload/
buildCsvString) вынесены в composables/useCsvDownload.ts.
- ReportsView.vue: 592 → 261 строк. Выделены: ReportRequestForm (тип отчёта,
даты, фильтры, формат, submit/reset), ReportJobsList (список заданий со
статусами и actions retry/cancel/delete).
- DealDetailDrawer.vue: 580 → 386 строк. Выделены: DealDetailHero (header +
phone-link + status-chip), DealDetailTimeline (activity log с MOCK_EVENTS).
Comment- и Reminders-секции оставлены inline — связаны с API и defineExpose.
DealsView и DealDetailDrawer остались выше 350-целевого уровня: bulk-action
функции (applyBulkStatus/applyBulkDelete/applyBulkExport/undoBulkDelete/
applyBulkRestoreFromTrash) и comment/reminders fetch — экспонируются через
defineExpose в Vitest-тестах напрямую, дальнейшая декомпозиция требует
изменения тест-контракта (отдельным flow).
Layout-структуры (AppLayout 466, AuthLayout, AppShell) НЕ ТРОНУТЫ — R0.6 hard-стоп.
Остальные 9 components >300 строк (AdminTenantDetailView, BillingView,
AdminTenantsView, SecurityTab, RemindersView, ErrorView, DashboardView,
ImpersonationDialog, далее) — вне scope Sprint 3, отдельным flow по запросу.
vue-tsc: 0 errors. ESLint: 0. Vitest: 416/416 PASS. Build: success (1.15s).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 20:28:25 +03:00
Дмитрий
cd13e6c8bb
refactor(backend): Sprint 3 Phase B — AuthController split (3 classes by analogy)
...
Sprint 3 Phase B. Закрытие audit O-refactor-02:
- O-refactor-02: AuthController (595 строк) → split на 3 класса (по аналогии с
Sprint 3 Phase A DealController split):
* AuthController (343) — core auth: login/register/logout/me +
updateNotificationPreferences + helpers (loginThrottleKey, isIpLockedOut,
maybeNotifySuspiciousLogin, logAuthEvent, lockoutResponse, userResource)
* TwoFactorController (217, новый) — 2FA verify + recovery codes use
(login-flow продолжение). Setup/enable/disable остались в
TwoFactorSetupController (с Sprint 1).
* PasswordResetController (146, новый) — forgot/reset password
API endpoints без изменений (только routing — controller@method обновлён в web.php):
- POST /api/auth/2fa/verify → TwoFactorController@verifyTwoFactor
- POST /api/auth/2fa/recovery-use → TwoFactorController@useRecoveryCode
- POST /api/auth/forgot → PasswordResetController@forgotPassword
- POST /api/auth/reset-password → PasswordResetController@resetPassword
Helpers lockoutResponse и userResource дублируются между классами (1:1) — по
принципу Phase A: «копируй методы 1:1, не оптимизировать на ходу». Будущая
итерация может вынести в trait/base controller, если появится 4-й класс.
Pest: 416/416 PASS + 2 skipped.
Larastan: 0 errors.
Pint: passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 20:14:33 +03:00
Дмитрий
86dc930915
refactor(backend): Sprint 3 Phase A — DealController split + N+1 fix + export streaming
...
Sprint 3 Phase A. Закрытие audit O-refactor-01 + O-perf-01 + O-perf-05.
O-refactor-01: DealController (802 строки) → split на 3 контроллера
по ответственности:
* DealController (466 строк) — single-resource CRUD (index/show/store/update).
* DealBulkActionController (264 строки, новый) — bulk transition/destroy/restore.
* DealExportController (120 строк, новый) — export() с streaming.
API endpoints без изменений; в routes/web.php обновлены только controller@method.
O-perf-01: N+1 в bulk-actions устранён в новом DealBulkActionController.
* transition: SELECT (id, status) → filter NO-OP → bulk-UPDATE
whereIn(changed)->update(status) + ActivityLog::insert(массив).
100 сделок: ~200 SQL → 2 SQL (после SELECT 1 UPDATE + 1 INSERT).
* destroy/restore: SELECT id'шников живых/удалённых → bulk-UPDATE
deleted_at + ActivityLog::insert. Аналогично 2 SQL вместо N.
Defense-in-depth where(tenant_id) сохранён — DealTransitionTest
«не апдейтит чужие сделки» проходит.
O-perf-05: export() переписан на OpenSpout streaming (composer require
openspout/openspout ^5.3). PhpSpreadsheet строил весь .xlsx в памяти
(10K сделок ≈ 100+ MB RAM). Теперь:
* Writer::openToFile('php://output') + Row::fromValues + chunkById(500).
* StreamedResponse → пик памяти O(1) от размера экспорта.
* CSV: OpenSpout Options(FIELD_DELIMITER=';', SHOULD_ADD_BOM=true) —
Excel-friendly RU-локаль сохранена.
* XLSX: getCurrentSheet()->setName('Сделки'), header через
Row::fromValuesWithStyle с (new Style)->withFontBold(true).
DealCreateTest.php (4 теста про export): getContent() → streamedContent()
для StreamedResponse + getCell()->getFormattedValue() для inline-string
ячеек, которые OpenSpout пишет как RichText (PhpSpreadsheet writer писал
как plain shared-string). Логика тестов и assertion'ы не меняются.
Verification:
Pest: 416/416 passed (+ 2 skipped), 1388 assertions, 47.5s.
Larastan: 0 errors above baseline.
Pint: passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 20:08:20 +03:00
Дмитрий
f52402fabe
docs(handoff): Sprint 2 Phase C — Google Fonts API v2 + @font-face fallback strategy (audit O-stack-10)
...
Sprint 2 Phase C (modernization). Закрытие audit O-stack-10:
- DEVELOPER_HANDOFF §4.5 — Google Fonts API v2 + @font-face fallback strategy
(расширение раздела о Sprint 1 Phase E font-display стратегия §4.4).
- Документировано: когда нужен fallback (расширенная аудитория Chrome 50-99 / Safari 12-14),
шаблон @font-face блоков, migration path (скачивание + размещение), trade-offs.
- Текущее решение Лидерры: только API v1 + display=swap (целевая аудитория Chrome 100+).
- Решение пересмотреть при GDPR/audit/статистике старых браузеров.
O-stack-06 (FD plugin в ~/.claude/settings.json) — manual user step, выводится в
финальном отчёте Sprint 2 (файл вне git).
O-refactor-07 (CLAUDE.md §0 reorg) — уже фактически реализовано в §9 (полная
история перенесена в docs/CHANGELOG_claude_md.md ранее, оставлены 2 последние
версии в шапке).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 19:39:26 +03:00
Дмитрий
2d7d7d1188
feat(frontend): Sprint 2 Phase B — Vue 3.5 defineModel + Vuetify 3.12 typed slots + lazy-imports + ESLint check
...
Sprint 2 Phase B (modernization). Закрытие audit O-stack-04/05/07 + O-perf-06:
- O-stack-04: Vue 3.5 defineModel() в 3 диалогах (NewDealDialog,
ImpersonationDialog, ReminderDialog) — boilerplate −5 строк/файл.
+ useTemplateRef() в TwoFactorView (input v-for refs).
- O-stack-05: Vuetify 3.12 типизированные слоты VDataTable
(DealsView + AdminTenantsView) — inline-аннотации `{ item }: { item: T }`
на 6+7 scoped-slot bindings; vue-tsc проверяет доступ к полям статически.
- O-stack-07: ESLint flat-config verified — header-comment добавлен
в eslint.config.js. Legacy .eslintrc.json не используется.
- O-perf-06: defineAsyncComponent() для тяжёлых диалогов в 3 местах:
DealsView (DealDetailDrawer + NewDealDialog), DealDetailDrawer
(ReminderDialog), RemindersView (ReminderDialog). KanbanView оставлен
sync — async-загрузка приводила к EnvironmentTeardownError в jsdom
(KanbanView.spec.ts), see in-file comment. Сборка показывает chunk'и
ImpersonationDialog (7.61 kB), DealDetailDrawer (11.12 kB), NewDealDialog
и ReminderDialog как отдельные lazy-bundles.
vue-tsc: 0 errors. ESLint: 0. Vitest: 416/416 PASS. Build: success.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 19:36:02 +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
Дмитрий
42b3f3f9e4
docs(spec-sprint2): дизайн Спринта 2 «Modernization» — 12 O-* находок
...
Scope: 8 O-stack + 2 O-perf + 2 O-refactor (low/medium risk, без архитектурных
рефакторингов). Default-выборы для design-решений зафиксированы в spec'е.
4 фазы: A.Backend (Pest 4 browser + mutation + Laravel 13 lazy + Larastan cache)
→ B.Frontend (Vue 3.5 + Vuetify 3.12 + lazy-imports + ESLint check)
→ C.Docs (Google Fonts + CLAUDE.md §0 reorg + FD plugin checklist)
→ D.Hygiene (dead-code report).
Не входит — 6 Sprint 3 пунктов (high risk, R0.6 hard-стопы).
Бюджет: 5-6 часов агентов.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 18:51:55 +03:00
Дмитрий
97bdb784d6
docs(registry): новые открытые вопросы по аудиту P1-10/11/09
...
Phase F Спринта 1 «Hygiene». Закрытие аудита 2026-05-09 (b6ae8dd ) для registry-блока:
- P1-10: новый CTO-18 в §3 — auth+tenant middleware на /api/deals на pre-prod.
Trigger: prod-миграция (после Б-1). MVP-flow с tenant_id query-param остаётся.
- P1-11: cross-link к Б-1 в §10 — /api/admin/* без auth = часть SSO-блока.
- P1-09: новый OPEN-FE-1 в §8.5 (новый раздел Frontend tooling) — Histoire 1.0-beta.1
↔ Vite 8 совместимость. Trigger: релиз Histoire с peerDep vite ^8.
Все 3 пункта аудита P1, не правки в коде. После Sprint 1 эти пункты остаются
открытыми в реестре с явными triggers закрытия.
lychee: 0 errors. cspell: 0 issues.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 18:45:48 +03:00
Дмитрий
e4673bea65
docs(handoff): status-slug mapping table + axe-claim documentation + font-display strategy (audit P1-04/05 + O-stack-09)
...
Phase E Спринта 1 «Hygiene». Закрытие аудита 2026-05-09 (b6ae8dd ) для handoff-блока:
- P1-05: BRANDBOOK_v2 §3.6.1 — таблица mapping 14 schema-slug ↔ имя статуса ↔ OKLCH-cell.
Источник истины по slug'ам — db/schema.sql; по именам/цветам — brandbook.
- P1-04: DEVELOPER_HANDOFF axe-claim связан с воспроизводимым evidence через ссылку на
Sprint 1 Phase C pa11y.config fix (cc6e1cb ); перепрогон через `npm run a11y`.
- O-stack-09: DEVELOPER_HANDOFF §4.4 — Font loading strategy
(&display=swap + WOFF2 + preconnect + совместимость).
Bonus hygiene в рамках handoff scope:
- DEVELOPER_HANDOFF: 4× MD051 fix anchor #3-дизайн-токены--css-variables → одинарный дефис.
- cspell-words.txt: +8 pre-existing handoff terms для разблокировки pre-commit
(skopirovat, platежи, Стейт, Канбана, nocall, tbl, ekrany, numpy).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 18:42:21 +03:00
Дмитрий
e2de8bf8a2
docs(narrative): sync versions + Histoire 21/43 + cross-refs (audit P1-01/03/06/08 + P2-03 + post-A)
...
Phase D Спринта 1 «Hygiene». Закрытие аудита 2026-05-09 (b6ae8dd ):
- P1-01: README.md обновлён (CLAUDE.md ссылка с 28→29 инструментов и 5→6 уровней;
Tooling v1.0→v1.10; Pravila v1.2→v1.6; PSR_v1 v1.3 добавлен; schema v8.5→v8.11
(56 базовых + 12 партиций / 97 индексов / 38 RLS / 5 функций / 13 триггеров)).
- P1-03: CLAUDE.md Histoire 21/28 → 21/43 (заменено все вхождения, включая §0 и §3.3).
- P1-06: Pravila §13.9 cross-ref на Plugin_stack_rules_v1 теперь с (v1.3).
- P1-08: Tooling §2.1 п.7 Stylelint раздел дополнен версией stylelint-config-standard ^40.0.0.
- P2-03: CLAUDE.md F-K cross-link на Plugin_stack_rules_v1.md#история-версий.
- post-A: метрики schema в CLAUDE.md синхронизированы до v8.11 (97 / 38).
Также фикс битой ссылки в spec'е Sprint 1 (lychee 1 error → 0): относительный путь
до Plugin_stack_rules_v1.md из docs/superpowers/specs/ исправлен на ../../
Bump версий:
- CLAUDE.md v1.81 → v1.82
- Pravila v1.6 → v1.7
- Tooling Прил. Н v1.10 → v1.11
Все правки CLAUDE.md/Pravila/Tooling — через claude-md-management:claude-md-improver
(CLAUDE.md §5 п.10). README.md и spec — обычные правки.
lychee: 0 errors. markdownlint: 0 errors. cspell на web/v8/* — out-of-scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 18:36:36 +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
Дмитрий
56195c8a59
fix(backend): tenant middleware на auth-routes + HasPasswordRules trait + test password (audit P0-01 + O-refactor-03 + P2-01)
...
Закрытие аудита 2026-05-09 (b6ae8dd ):
- P0-01: применён 'tenant' middleware (alias уже в bootstrap/app.php:17) к 3 auth:sanctum-группам:
/api/notifications, /api/reminders, /api/reports/jobs (web.php:44/52/63).
/api/deals и /api/admin/* остаются без auth (P1-10/Б-1) — в реестр Спринта 1 Phase F.
- O-refactor-03: HasPasswordRules trait извлекает rules + messages, подключён в Login/Register.
- P2-01: bcrypt('test') → bcrypt('test1234') в AdminIncidentsIndexTest (≥8 chars).
- bonus-fix: SetTenantContext::resolveTenantId — property_exists() заменён на isset() для
Eloquent magic-attributes (auth-путь резолюции tenant_id никогда не работал из-за этого
бага; тесты-смоки middleware покрывали только X-Tenant-Id header / subdomain). Без фикса
P0-01 ломает 58 тестов в /api/notifications + /api/reminders + /api/reports/jobs.
Pest: 416/416 PASS.
Larastan: 0 errors.
Pint: clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 18:22:30 +03:00
Дмитрий
e01caa3e38
fix(db): RLS на impersonation_tokens + 2 missing FK indices (audit P0-02 + O-perf-02/03)
...
schema.sql v8.10 → v8.11. Закрытие аудита 2026-05-09 (b6ae8dd ):
- P0-02: ALTER TABLE impersonation_tokens ENABLE ROW LEVEL SECURITY
+ CREATE POLICY tenant_isolation. Закрывает RLS-gap (39 vs 37 → 40 vs 38).
- O-perf-02: CREATE INDEX idx_failed_webhook_jobs_log на webhook_log_id.
- O-perf-03: CREATE INDEX idx_rejected_deals_log_webhook на webhook_log_id.
Метрики v8.11: 56 базовых + 12 партиций / 97 индексов / 38 RLS / 5 функций / 13 триггеров.
CHANGELOG_schema.md обновлён.
squawk: 0 issues.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 18:15:33 +03:00
Дмитрий
93b1af40d0
docs(plan-sprint1): implementation plan для Спринта 1 «Hygiene»
...
По spec'у 2026-05-09-sprint1-hygiene-design.md (08bbe4d ). 41 атомарный task в 6 фазах:
- Phase A. DB (A1-A7, ~20 мин): RLS impersonation_tokens + 2 FK indices + CHANGELOG
schema v8.10→v8.11 + verify squawk/grep (38 RLS, 97 indexes).
- Phase B. Backend (B1-B7, ~40 мин): apply 'tenant' middleware к 3 auth:sanctum-группам
(alias уже в bootstrap/app.php) + HasPasswordRules trait + test password ≥8 +
verify Pest 416/416 + Larastan 0.
- Phase C. Configs (C1-C8, ~40 мин): format:sql:check Windows fix + .lychee.toml exclude
+ pa11y.config paths + composer audit-offline + ESLint anti-vuetify + npm-outdated CI.
- Phase D. Docs (narrative, D1-D5, ~45 мин): README versions + CLAUDE.md/Pravila/Tooling
через claude-md-management:claude-md-improver skill (CLAUDE.md §5 п.10).
- Phase E. Docs (handoff, E1-E4, ~45 мин): BRANDBOOK status-slug mapping table +
DEVELOPER_HANDOFF axe-claim doc + font-display strategy.
- Phase F. Registry (F1-F3, ~15 мин): Открытые_вопросы — новый CTO для P1-10 +
Б-1 cross-link для P1-11 + новый OPEN для P1-09 (Histoire-Vite).
Зависимости: B и D зависят от A (CHANGELOG ссылки + метрики schema).
Бюджет: 2.5-3.5 часа агентов.
Cspell-словарь дополнен: Митигация, закоммитить.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 18:12:26 +03:00
Дмитрий
08bbe4d9c8
docs(spec-sprint1): дизайн Спринта 1 «Hygiene» исправления аудита 2026-05-09
...
Spec через superpowers:brainstorming. Scope: 22 правки + 3 записи в реестр:
- 3 P0 (RLS impersonation_tokens, SetTenantContext middleware, format:sql:check Windows)
- 10 P1 (P1-10/P1-11 → реестр)
- 3 P2 (test password, орфо, F-K расшифровка)
- 6 low-risk O-* (2 FK indices, password rules trait, ESLint anti-vuetify, npm CI, font-display docs)
6 фаз / 6 коммитов: A.DB → B.Backend → C.Configs → D.Docs(narrative) → E.Docs(handoff) → F.Registry.
Зависимости: B/D зависят от A (CHANGELOG schema метрики).
Бюджет: 2.5-3.5 часа агентов в субагентном режиме.
CLAUDE.md/Pravila/Tooling правки в Фазе D — обязательно через
claude-md-management:claude-md-improver (CLAUDE.md §5 п.10).
Не входит: Спринт 2 (modernization) и Спринт 3 (big refactors) — отдельные spec'и.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-09 17:51:16 +03:00