dee2ebbcf8af7aada76d1237c5dcef8dee936ffd
1207 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
75897b1636 |
phase2(rate-limit): login + 2FA verify (5/15min) + frontend lockout
- AuthController: RateLimiter::hit/clear на login + verifyTwoFactor по ключу email|ip / pending_user_id|ip - 429 + Retry-After header + JSON retry_after (lockoutResponse helper) - ТЗ §22.4.4: 5 попыток / 15 мин; success чистит throttle; inactive user тоже расходует попытки - extractRateLimitRetry в api/client.ts; auth-store.lockoutSeconds; v-alert в LoginView/TwoFactorView - Pest +6 в RateLimitTest.php (73/73 за 8.07с, 246 assertions) - Vitest +4 в auth-store + LoginView (149/149 за 12.31с) - Quirk: wrong-password в тестах ≥8 символов (LoginRequest::min:8) — иначе валидация падает до controller - Quirk: vi.mock api/client в auth-store.spec — иначе axios.isAxiosError в jsdom возвращает false для plain Error - TODO (отдельные коммиты): IP-lockout 10/час через auth_log + email при 3 неудачах - Регресс: lint+type+format OK; build 886ms; story:build 21/28 за 37.19с; Pint+Stan passed - CLAUDE.md v1.35→v1.36, реестр v1.44→v1.45 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1d1353931d |
phase2(user-chip): реальный user в AppLayout/AdminLayout + Logout-menu
- AppLayout: userInitials/userShortName computed из auth-store, fallback цепочка → email → '?' / 'Гость'
- AdminLayout: тот же паттерн с админ-defaults 'АО' / 'Админ Оператор'
- v-menu offset=8 на user-chip: email + Настройки/Выйти из админки + Выйти
- handleLogout async: auth.logout() (swallows API errors) → router.push('/login')
- Vitest +3 в AppLayout.spec.ts (всего 145/145): store-mock + null-user + email-fallback
- AppShell.spec.ts получил createPinia в plugins
- Регресс: lint+type+format OK, vitest 145/145 за 11.01с, build 855ms, story:build 21/28 за 32.11с, Pest 67/67 за 6.16с
- CLAUDE.md v1.34→v1.35, реестр v1.43→v1.44
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
374724a7a3 |
phase2(auth-2fa): TOTP-verify endpoint + TwoFactorView интеграция
- pragmarx/google2fa@^9.0 для TOTP RFC 6238.
- AuthController::login изменён: при totp_enabled=true НЕ делает Auth::login,
сохраняет auth.pending_user_id+pending_remember в session, возвращает
requires_2fa=true. /me=401 пока 2FA не пройдена.
- AuthController::verifyTwoFactor: читает pending_user_id, верифицирует TOTP
через Google2FA::verifyKey($secret, $code, window: 1) (окно ±1 = 30s).
Success → Auth::login + regenerate + clear pending + last_login_at.
- VerifyTwoFactorRequest: regex /^\d{6}$/.
- /api/auth/2fa/verify публичный (нет session-auth до verify).
Frontend:
- auth-store::login: при requires_2fa=true user остаётся null (иначе
isAuthenticated=true и guard пустит на /dashboard минуя 2FA).
- auth-store::verifyTwoFactor action.
- api/auth.ts::verifyTwoFactor(code).
- TwoFactorView: onMounted redirect на /login если нет pending state;
submit → verify → /dashboard; на error - clear code + focus first cell.
userEmail из auth.user?.email.
Pest +6 (всего 67/67 за 6.97s, 194 assertions): login для 2FA НЕ создаёт
session + verify success/неверный код/без login/валидация формата +
после verify /me=200.
Vitest +3 (всего 142/142 за 10.75s): login pending vs success state +
verifyTwoFactor success/reject. TwoFactorView spec получил setActivePinia
+ requires2fa=true для bypass onMounted-redirect.
PHPStan baseline +26 Pest TestCall warnings (накопительно).
Регресс: pint+stan passed; vitest 142/142; vite build 908ms;
story:build 21/28 за 31.28s; Pest 67/67 за 6.97s.
CLAUDE.md v1.33->v1.34, реестр Открытых_вопросов v1.42->v1.43.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
59299d3c2b |
phase2(auth-frontend): axios + Pinia + auth-store + auth-guards + form integration
- axios@^1.16 + pinia@^3.0 (--legacy-peer-deps). - api/client.ts: axios с withCredentials+withXSRFToken (Sanctum SPA auto-XSRF). ensureCsrfCookie() + extractValidationErrors/Message helpers. - api/auth.ts: типизированные login/register/me/logout с AuthUser interface. - stores/auth.ts: Pinia composition-store (user/loading/requires2fa + isAuthenticated computed + login/register/fetchMe/logout actions). logout() catch-swallow - UI всегда выходит локально. - LoginView/RegisterView: useAuthStore интеграция, real POST через store, errors из 422 на v-text-fields, redirect на /dashboard или /2fa, :loading на btn'ах. - Auth-guard в router.beforeEach: meta.requiresAuth на 10 routes (6 app + 4 admin), meta.guestOnly на login/register/forgot. При первом переходе fetchMe() restore-session. Unauth → /login?redirect=<original>. - / redirect → /dashboard (auth-guard перехватит если не залогинен). - Pinia в app.ts через app.use(createPinia()). - cspell-words.txt: мокаем. Vitest +10 (всего 139/139 за 10.11s): - auth-store 7 (initial state + login success/reject + register + fetchMe success/401 + logout swallow). - router 5 переписан (login.guestOnly + 6 protected + admin layout + 3 error без auth + unauth /dashboard → /login?redirect). - LoginView/RegisterView/router тесты получили createPinia в plugins. - vi.mock api/auth в router+auth-store specs. Регресс: lint+type+format OK; vitest 139/139; vite build (main app-chunk 105→153.64 KB +axios+pinia+auth gzipped 54.54 KB) 806ms; story:build 21/28 за 31.73s; Pest 61/61 за 5.86s. CLAUDE.md v1.32->v1.33, реестр Открытых_вопросов v1.41->v1.42. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
04b90afda4 |
phase2(auth-backend): Sanctum SPA mode + AuthController + 13 Pest tests
- laravel/sanctum@^4.3 install. SPA mode (cookie-based session, не tokens). personal_access_tokens migration удалена (для SPA не нужна). - AuthController (Api/): login + register + me + logout с детальной валидацией + кастомные русские error-messages. - LoginRequest + RegisterRequest Form Requests. Register требует accept_offer:accepted + accept_pdn:accepted (по ТЗ §1.5/§4.1, БЕЗ маркетингового click-wrap'а - расхождение #2 handoff vs ТЗ). - User::fillable += last_login_at, last_active_at. - Auth-routes в web.php (НЕ api.php): Sanctum SPA нуждается в session-cookie middleware из web-группы (laravel.com/docs/sanctum#spa-authentication). - cspell-words.txt: pdn, залогинен. Pest +13 (всего 61/61 за 6.22s): - login success + 2FA-flag + invalid pass + missing email + blocked + format validation + last_login_at update + register success/duplicate/без accept + me 401/200 + logout 200. - Logout-test упрощён до 200+message - Pest cookie-jar держит session между запросами теста, full flow через browser-mode (отдельный коммит). - phpstan-baseline: +25 ignored Pest TestCall warnings (Larastan+Pest quirk). Регресс: pint+stan passed; vitest 129/129 за 9.59s; vite build 802ms; story:build 21/28 за 30.39s; Pest 61/61 за 6.22s. CLAUDE.md v1.31->v1.32, реестр Открытых_вопросов v1.40->v1.41. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
da65cf4bf7 |
phase2(admin): AdminLayout + AdminTenantsView - админка SaaS (12/13 концептов)
- AdminLayout: отдельный sidebar теало-нуар с под-брендом ADMIN (red error 10px JBM uppercase) + 4 nav (Тенанты 142 / Биллинг / Инциденты 3 / Система) + topbar с crumb «Админка → currentPage» + admin-user-chip с error-color avatar. - AdminTenantsView (/admin/tenants): page-head + 5-stats + Экспорт + search/Статус/Тариф фильтры + v-data-table 7 колонок (Тенант с двухстрочным name+inn / Статус-chip 4 цвета / Тариф / Баланс ₽ с error-color при <0 / Желаем×факт / MRR с «—» / Активность). - mockTenants.ts соответствует schema v8.7 §3: 4 статуса × 5 тарифов, 7 mock с разнообразием (active/trial/overdue/suspended) + AdminStats (142/128/9/5/ 1 248 600 ₽). - AdminPlaceholderView универсальный для Биллинг/Инциденты/Система с описаниями ссылающимися на schema v8.7 (incidents_log §9 / system_settings §10). - AppShell расширен meta.layout='admin'. Router: /admin redirect на /tenants + 4 admin-route'а с lazy-imports. Web.php fallback покрывает /admin/*. - cspell-words.txt: Екб. Vitest +11 (всего 129/129 за 10.02s): - заголовок + 5 stats (regex nbsp в 1 248 600 ₽) + 7 columns + 7 rows + Окна Москва ИНН + overdue −1 200 + trial 4 дня + suspended + search filter «Натяжные» → 1 row + Экспорт/Статус/Тариф кнопки. Регресс: lint+type+format OK; vitest 129/129; vite build (admin views в lazy-chunks; main 104.99 KB); story:build 21/28 за 30.32s; Pest 48/48 за 4.89s. CLAUDE.md v1.30->v1.31, реестр Открытых_вопросов v1.39->v1.40. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
034657788d |
phase2(errors): ErrorView 404/403/500 + Laravel fallback
- ErrorView универсальный с конфигурацией через route.meta.errorCode
(404/403/500). По v8_errors.html: full-bleed теало-нуар bg, top-brand,
err-code 96px JBM с accent на средней цифре, title/desc, 2 actions,
опциональные status-list (500) и err-id с copy-btn (403/500).
- AppShell: meta.layout='error' → RouterView напрямую (ErrorView сам
предоставляет v-app).
- Router: /403, /500, catch-all /:pathMatch(.*)* → ErrorView с meta.errorCode.
- web.php: явные Route::view + Route::fallback (срабатывает после Pest
runtime-routes, не ломает SetTenantContextTest).
- cspell-words.txt: резолвится, роуты.
Vitest +8 (всего 118/118 за 9.39s):
- 404 default + 403 с REQ-ID + 500 с INC-ID + status-list (API/Telegram/YooKassa) +
404 actions (На дашборд + Назад) + 403 mailto-link + 500 status-link +
brand-блок + 404 НЕ содержит REQ/INC/status-list (regression-guard).
- stubs:{VApp/VMain} как passthrough — обходим Vuetify layout-injection в jsdom.
Регресс: lint+type+format OK; vitest 118/118; vite build (ErrorView lazy-chunk;
main app-chunk 101.01KB упал на 7KB благодаря shared chunk'ам); story:build
19/26 за 30.96s; Pest 48/48 за 4.88s (fallback не сломал runtime-routes).
CLAUDE.md v1.29->v1.30, реестр Открытых_вопросов v1.38->v1.39.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
4de39e70b2 |
phase2(reports): ReportsView - асинхронная генерация отчётов с очередью
- ReportsView (/reports): form-card (Запросить) + jobs-list panel. Form: 4 type-cards radio-grid (Сделки/Менеджеры/Источники/Биллинг) + date-range + Проект/Менеджер v-select + 4 fmt-кнопки (CSV/XLSX/JSON/PDF) + quota-banner alert (CTO-7: 2/3 одновременных + CTO-6: 3 попытки/7 дней) + Запустить/Сброс. - Jobs-list: 5 mock-rows × 4 статуса (done/running/queued/failed) с icon + meta JBM (FORMAT · size · rows · timeText) + status-chip + actions (Скачать done / Повторить failed && attempt<3 / Отменить queued / Удалить done|failed). v-progress-linear для running 62%. - composables/mockReports.ts: type unions (4×4×4) + 5 mock-jobs + MOCK_QUOTA (CTO-6/7 значения). - Маршрут /reports (meta.layout=app, lazy-import) в router + web.php. Vitest +12 (всего 110/110 за 9.38s): - заголовок + page-stats + 4 type-cards + дефолт active + 4 формата + quota-banner («2 из 3» / «3 попыток retry» / «7 дней») + 5 job-rows + done-«Готов»+Скачать-aria + running-«62%»+progressbar role + queued-Отменить + failed-«Ошибка»+«S3 timeout»+Повторить-aria + клик-переключение active. Регресс: lint+type+format OK; vitest 110/110; vite build (ReportsView lazy-chunk; main 108.19 KB); story:build 18/25 за 30.77s; Pest 48/48 за 4.58s. CLAUDE.md v1.28->v1.29, реестр Открытых_вопросов v1.37->v1.38. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
394663597f |
phase2(settings): SettingsView - 8 вкладок (4 реализованы, 4 placeholder)
- SettingsView (/settings): sidebar tabs-rail (md=3, 8 v-list-item с mdi-icon) + content-pane (md=9 v-card outlined min-height 480px). activeTab ref переключает рендер вкладки. Реализованы: - ProfileTab: avatar 80px + 5 form-fields (имя/email disabled/телефон/TZ/роль). - SecurityTab: 3 cards (Пароль / 2FA включена + recovery codes + Отключить / Активные сессии 3 mock с Завершить-btn). - ApiTab: API-ключ password+eye-toggle + Webhook (URL + signing secret HMAC). Текст про дедуп (tenant_id, source_crm_id) 24ч и антифрод по phone (§10.8.1). - NotificationsTab: матрица 8x3 (events × channels) соответствует schema v8.7 §4 users.notification_preferences JSONB. 8 событий (new_lead, duplicate_detected, low_balance, tariff_charge, reminder_due, manager_assigned, webhook_failed, monthly_report) × 3 канала (email/sms/in_app). + sound_enabled switch. Placeholder: - PlaceholderTab универсальный с props title/description + v-alert «В разработке». - Используется для Проекты / Команда / Интеграции / Тихие часы. Маршрут /settings (meta.layout=app, lazy-import) в router + web.php. .gitleaks.toml: settings/*.vue в allowlist (фиктивный профиль). cspell-words.txt: смыслово. Vitest +8 (всего 98/98 за 8.42s): - 8 nav-tabs + все названия + дефолт «Профиль» + Проекты → «В разработке» + Уведомления показывает «События × каналы» + 5 событий матрицы + Безопасность: 2FA + сессии + API: API-ключ + Signing secret HMAC. Регресс: lint+type+format OK; vitest 98/98; vite build (SettingsView lazy-chunk; main app-chunk 107.85KB); story:build 17/24 за 31.7s; Pest 48/48 за 5.03s. CLAUDE.md v1.27->v1.28, реестр Открытых_вопросов v1.36->v1.37. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c8012896e3 |
phase2(billing): BillingView - финансовый экран биллинга и тарифов
- BillingView (/billing): page-head со stats (кошелёк/лиды/runway-дни) + pending banner v-alert info («1 платёж в обработке через ЮKassa, auto-cancel 30 мин») + 3 wallet-cards (Кошелёк ₽ primary card теало-нуар + LIVE; Баланс лидов ГЦК; Тариф «Команда» 990₽/мес + 3 фичи) + transactions panel (4 tabs + v-data-table 5 колонок: Дата/Операция/ID/Статус-chip/Сумма ± JBM tnum) + invoices list (PDF + 1С 8.3 XML). - composables/mockBilling.ts соответствует схеме v8.7 §4.4-4.5: 8 mock транзакций (types: topup/lead_charge/refund/tariff_charge; statuses: pending/completed/rejected) + 4 invoices (pdf/xml_1c83) + pending payment. - Маршрут /billing (meta.layout=app) в router + web.php. Format helpers: «+ N ₽» / «− N ₽» / «— 0 ₽» rejected; Intl.NumberFormat ru-RU. Vitest +11 (всего 90/90 за 7.96s): - заголовок + page-stats nbsp regex + pending banner + 3 wallet-cards + 3 фичи тарифа + 4 tabs + дефолт «Все» 8 строк + format «+/−» + rejected «— 0 ₽» + 4 invoice rows + PDF/1С 8.3 XML labels. Регресс: lint+type+format OK; vitest 90/90; vite build (BillingView lazy-chunk; VDataTable вынесен в общий chunk 79.84KB - shared с DealsView); story:build 16/23 за 32.16s; Pest 48/48 за 4.89s. CLAUDE.md v1.26->v1.27, реестр Открытых_вопросов v1.35->v1.36. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
45239f6602 |
phase2(deal-drawer): DealDetailDrawer - правая панель с деталями сделки
- DealDetailDrawer (v-navigation-drawer right temporary 480px):
- hero (#id eyebrow + name h5 + close + tel:link + clock + status-chip)
- section Параметры (2-col grid: Проект/Стоимость/Менеджер/Источник)
- section Активность (timeline 6 events с iconified vertical-line)
- mockDealEvents.ts: 6 mock-events (created/balance_charged/assigned/viewed/
status_changed/commented) - соответствуют ActivityLog event-константам v8.7.
- Интеграция в DealsView (@click:row) и KanbanView (через @open-deal от карточки).
- cspell-words.txt: iconified, мапы, резолвятся, резолвером, stub'ить, инлайнен.
Vue3 quirk: v-navigation-drawer требует layout-injection от v-app/v-layout,
но в Vitest vite-plugin-vuetify auto-import не работает. Решение:
- DealsView/KanbanView тесты: stubs:{DealDetailDrawer:true}
- DealDetailDrawer тесты: stubs:{VNavigationDrawer:passthrough-div}
Vitest +8 (всего 79/79 за 7.57s):
- DealDetailDrawer 8 (open=false скрытие, deal=null no-content, hero+id,
tel:link, status-chip, params, timeline 6 items, emit update:open(false)).
Регресс: lint+type+format OK; vitest 79/79; vite build (drawer инлайнен в
DealsView+KanbanView lazy-chunks); story:build 15/22 за 31.55s; Pest 48/48.
CLAUDE.md v1.25->v1.26, реестр Открытых_вопросов v1.34->v1.35.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
c8131a39c8 |
phase2(kanban-dnd): vuedraggable@4 - drag-and-drop карточек между 14 колонками
- vuedraggable@^4.1.0 + sortablejs@1.14.0 (--legacy-peer-deps). - KanbanColumn: <draggable v-model="localDeals" group="kanban-deals" item-key="id" ghost-class="ghost-card" drag-class="drag-card" animation="150"> + #footer empty-state «пусто · перетащите сюда». - DraggableChangeEvent типизирован (added/removed/moved discriminated union). - KanbanView: const → reactive<Record<slug, MockDeal[]>> (vuedraggable v-model требует независимые arrays); shallow-clone {...d} чтобы не мутировать MOCK_DEALS. - onColumnChange: при event.added → element.statusSlug = targetSlug. TODO: POST /api/deals/{id}/transition с проверкой allowed-переходов. - cspell-words.txt: vuedraggable, симулируется. Visual: ghost-card opacity 0.4 + ivory-tint bg, drag-card rotate 1deg. Vitest +1 (всего 71/71 за 7.48s): эмулирует $emit('change', {added}) → проверяет statusSlug update. Полный mouse-DnD не симулируется — JSDOM не умеет drag-events, но event-handler логика покрыта. Регресс: lint+type+format OK; vitest 71/71; vite build (KanbanView lazy-chunk вырос до 180.53KB - SortableJS-обёртка, грузится только на /kanban); story:build 14/20 за 30.45s; Pest 48/48 за 4.88s. CLAUDE.md v1.24->v1.25, реестр Открытых_вопросов v1.33->v1.34. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d39934c8d9 |
phase2(kanban): KanbanView - 14 колонок по lead_statuses (БЕЗ DnD)
- KanbanCard: компактная карточка (name/phone/project/cost/manager-avatar),
emit('open',id) на click для будущего DealDetailDrawer.
- KanbanColumn: header с border-top по colorHex статуса (--accent CSS-var) +
name+count+total ₽; body с v-for карточек + empty-state «пусто».
- KanbanView: orchestrator, 14 колонок (по LEAD_STATUSES) с группировкой
MOCK_DEALS по statusSlug, horizontal-scroll с custom scrollbar.
- Маршрут /kanban (meta.layout=app) в router + web.php.
- .gitleaks.toml: tests/Frontend/*.spec.ts в allowlist (assertion на mock-телефоны).
- cspell-words.txt: инлайн, vueuse.
DnD НЕ реализован на MVP - отдельный коммит после выбора библиотеки
(vue-draggable-next или @vueuse/integrations/useSortable).
Vitest +14 (всего 70/70 за 7.37s):
- KanbanCard 3 (data + initials + emit open)
- KanbanColumn 5 (header + total + empty + accent CSS-var case-insensitive +
проброс openDeal)
- KanbanView 6 (заголовок + 14 columns + правильные status'ы + stats + кнопка +
DnD-предупреждение)
Регресс: lint+type+format OK; vitest 70/70; vite build (KanbanView lazy-chunk);
story:build 14/20 за 31.17s; Pest 48/48 за 5.06s.
CLAUDE.md v1.23->v1.24, реестр Открытых_вопросов v1.32->v1.33.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
a51a94830c |
phase2(deals): DealsView - центральный экран CRM (список сделок)
- DealsView (/deals): page-head со stats (всего/в работе/ждут оплату) + Экспорт/Новая сделка кнопки. filter-bar с 5-tab chiprow (Все/Активные/ Ждут оплату/Закрытые/Невалидные) + поиск по name/phone/project. v-data-table с 6 колонками: Лид (avatar+name+phone), Статус (tonal-chip с colorHex из lead_statuses), Проект, Менеджер, Стоимость (Intl.NumberFormat ru-RU JBM tnum), Время (formatRelative мин/ч/д назад). show-select для будущих bulk-actions. Empty-state. - composables/mockDeals.ts: 12 mock-сделок + DEALS_TABS (5 срезов с slug[]). - Маршрут /deals (meta.layout=app) в router + web.php. - .gitleaks.toml: mockDeals.ts в allowlist (фиктивные имена/телефоны). Vue regex quirk: ESLint no-irregular-whitespace в regex с literal nbsp - \s в JS уже matches U+00A0/U+202F из Intl.NumberFormat, использовать \s+. Vitest +8 (всего 56/56 за 5.66s): заголовок + page-stats + 5 tabs + дефолт active-фильтр (5/12 строк) + кнопки + 6 колонок + format «2 400 ₽» + format «7 мин назад». Регресс: lint+type+format OK; vitest 56/56; vite build (DealsView lazy-chunk 87.54KB - v-data-table крупный, но грузится только на /deals); story:build 11/15 за 31.93s; Pest 48/48 за 4.96s. CLAUDE.md v1.22->v1.23, реестр Открытых_вопросов v1.31->v1.32. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
290e7dbc34 |
phase2(charts): ActivityChart + FunnelChart - Dashboard закрыт по дизайну
- ActivityChart: native SVG line chart (без chart-library, чтобы не +400KB зависимость для статичных дашборд-графиков). Y-grid 5 линий, area-gradient, 7 точек (предпоследняя выделена primary teal как «сегодня»), 3 tabs (Принято/Оплачено/Отказ). - FunnelChart: segmented bar по 14 статусам + funnel-list (sort desc). - composables/leadStatuses.ts: snapshot 14 статусов из db/schema.sql:2130 (НЕ из BRANDBOOK §3.6 - расхождение #1 handoff vs ТЗ из реестра v1.13). 14 правильных slug'ов: new/viewed/worked/base/missed/negotiations/ waiting_payment/partnership/paid/closed/test_drive/hot/replacement/final_missed. - DashboardView интегрирует оба чарта в charts-row (md=7+5). - cspell-words.txt: ldot, композаблом, инлайнингом, инлайнены. Vue compiler quirk: withDefaults factory не разрешает референсить module-level const'ы (checkInvalidScopeReference). Обходим инлайнингом литерала. Vitest +13 тестов (всего 48/48 за 5.5s): - ActivityChart 6 (3 tabs + 7 circles + 'сегодня' + custom points + legend) - FunnelChart 7 (14 segments + 14 list-items + assertion на отсутствие 'Думает'/'Спам' из handoff + сортировка + colorHex + total) Stories +2 с 3 variants каждый (Histoire 10/14 за 30.43s). Регресс: lint+type-check+format OK; vitest 48/48; vite build (DashboardView chunk 14.9->21.17 KB с чартами); story:build 10/14 за 30.43s; Pest 48/48 за 5.10s. CLAUDE.md v1.21->v1.22, реестр Открытых_вопросов v1.30->v1.31. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1e233a70c8 |
phase2(dashboard): AppLayout + DashboardView - default-layout приложения
- AppLayout: v-navigation-drawer (теало-нуар sidebar 240px) + brand-block + nav-tree из 8 пунктов в 3 группах (Работа/Финансы/Команда), v-app-bar с crumb «Рабочая область → currentPage» + search ⌘K + bell + user-chip. Mobile (md<): drawer toggleable. - DashboardView: page-head «Доброе утро, Иван» + page-meta + range-toggle 4 опции (Сегодня/7д/30д/Период). KPI-row из 4 cards: 3 outlined (получено лидов/конверсия/активные проекты) + 1 hero balance с runway-bar 4/7 заполненных сегментов teal #32C8A9. - AppShell упрощён до layout-mapper (route.meta.layout 'app'/'auth'). - Маршрут /dashboard (meta.layout='app') в router + web.php. - histoire.setup расширен 8 app-stub-маршрутами для AppLayout. - Vitest +11 тестов: AppLayout 6 (brand+3 группы+8 пунктов+счётчики+crumb), DashboardView 5, AppShell.spec.ts переписан под layout-mapper. - cspell-words.txt: JBM. Регресс: lint+type-check+format OK; vitest 35/35 за 4.92s; vite build DashboardView lazy-chunk 14.9KB; story:build 8/8 за 28.97s; Pest 48/48 за 4.88s. CLAUDE.md v1.20->v1.21, реестр Открытых_вопросов v1.29->v1.30. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
19096552b4 |
phase2(auth): закрыты 4 оставшихся auth-экрана из v8_login.html
- RegisterView: email + password (strength-meter 0..4) + 2 click-wrap'а (оферта + ПДн). 3-й «маркетинг» из handoff НЕ реализован (расхождение #2 реестра v1.13 - handoff противоречит ТЗ §1.5/§4.1). - TwoFactorView: 6 input-cell с auto-focus вперёд при вводе цифры, Backspace назад при empty, paste 6 цифр заполняет все. - ForgotPasswordView: email + alert «5 попыток / 15 минут» по ТЗ §1.7. - RecoveryCodesView: 8 кодов в 2-column grid + Скачать .txt (Blob/URL.createObjectURL) + Копировать (navigator.clipboard) + warning о невозможности повторного просмотра. Router: 4 новых маршрута (/register, /2fa, /forgot, /recovery), все meta.layout='auth', lazy-imports. Vitest +14 тестов (всего 24/24 за 3.29s): - RegisterView 4 (вкл. assertion на отсутствие маркетингового click-wrap) - TwoFactorView 3, ForgotPasswordView 3, RecoveryCodesView 4 Stories +4 (Histoire 6/6 за 29.17s). Регресс: lint+type-check+format OK; vitest 24/24; vite build 5 lazy-chunks для views + Vuetify в отдельные chunks (app chunk 198KB→78KB); Pest 48/48 за 4.85s. CLAUDE.md v1.19→v1.20, реестр Открытых_вопросов v1.28→v1.29. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e909a95a8d |
phase2(login): vue-router 4 + AuthLayout + LoginView - первый реальный экран
- vue-router@^4.6.4 (--legacy-peer-deps из-за Histoire vs Vite 8 peerDep). - resources/js/router/index.ts: createWebHistory + lazy-imports + meta.layout. Маршрут / -> /login, /login -> LoginView (meta.layout=auth). - resources/js/layouts/AuthLayout.vue: двухпанельный (brand-pane тёмный с radial-gradient акцентами + form-pane warm ivory). На mobile brand-pane скрыт. - resources/js/views/auth/LoginView.vue: форма Vuetify по v8_login.html секция #form-login - email/password (autocomplete + eye-icon), primary submit, Yandex 360 SSO, RouterLink на /register и /forgot. - AppShell.vue: layout-mapper по route.meta.layout (default/auth). - routes/web.php: явные Route::view для 6 SPA-путей (НЕ catch-all - он перехватывал /_test/* в Pest beforeEach и валил 5 SetTenantContextTest). - Vitest: +LoginView.spec.ts (5), +router.spec.ts (2), AppShell.spec.ts переписан (3). Vitest 10/10 за 3.01s. - LoginView.story.vue для Histoire. Setup расширен memory-router'ом. - cspell-words.txt: рендерят, коммиты, Лидерру. - Регресс: lint:vue OK, type-check OK, format:check OK, vitest 10/10, vite build 212 модулей за 383ms (LoginView lazy-chunk 43.5KB JS / 51.7KB CSS), story:build 2/2 за 29.94s, Pest 48/48 за 4.86s. CLAUDE.md v1.18->v1.19, реестр Открытых_вопросов v1.27->v1.28. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
952373fce5 |
phase2(trigger): Vue 3 + Vuetify 3 + ESLint+Prettier+Vue + vue-tsc + Vitest
Триггер фазы 2 выполнен — первый коммит в app/resources/js/. Активирует 5 из 6 инструментов фазы 2 (CLAUDE.md §3.3) — без Histoire (отдельно). Tailwind удалён (правило CLAUDE.md §5 п.2). Стек: - vue@3.5, vuetify@3.12, @vitejs/plugin-vue@6 (для Vite 8 совместимости — @vitejs/plugin-vue@5 поддерживает только Vite 5/6), vite-plugin-vuetify@2 (auto-import), sass-embedded - eslint@10 (flat-config), eslint-plugin-vue@10, @vue/eslint-config-typescript@14, eslint-config-prettier, prettier@3.8 - typescript@6, vue-tsc@3.2 - vitest@4.1, @vue/test-utils, jsdom, @vitest/coverage-v8 Конфиги: - app/vite.config.js — vue + vuetify auto-import - app/vitest.config.ts — jsdom + setup file для ResizeObserver/ IntersectionObserver/matchMedia/CSS.supports stubs (без них Vuetify падает в JSDOM) - app/eslint.config.js — flat-config - app/.prettierrc.json, app/tsconfig.json Frontend-структура: - resources/js/app.ts — точка входа - resources/js/plugins/vuetify.ts — палитра Forest (Teal/ivory/теало-нуар из BRANDBOOK_v2 §3) - resources/js/components/AppShell.vue — первый компонент: v-app + v-app-bar + v-card - resources/css/app.css — Inter (UI, opsz axis), JetBrains Mono (.numeric, tnum) - resources/views/welcome.blade.php — упрощён под Vue mount Smoke-тесты Vitest 3/3 за 2.8 сек: - монтируется без ошибок - содержит «Лидерра.» - рендерит chip с фазой 2 Build: 158 модулей за 386 ms (184 KB JS / 295 KB CSS gzipped). npm-scripts: lint:vue, format, format:check, type-check, test:vue. lefthook job #8 (ESLint на staged .ts/.vue) добавлен в pre-commit. Полный type-check (vue-tsc) и Vitest — отдельно вручную (медленно для pre-commit: ~3 сек на каждый). CLAUDE.md v1.16 → v1.17 (фаза 1 → фаза 2 в §6). Реестр Открытые_вопросы v1.25 → v1.26. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
ba97f952cc |
phase1(webhook): failed() callback + FailedWebhookJob модель — упавшие jobs после 3 ретраев
После исчерпания всех 3 ретраев Laravel вызывает failed(\Throwable $e) —
упавший job сохраняется в failed_webhook_jobs для ручного разбора и
повторного запуска через админку.
Реализация:
- app/app/Models/FailedWebhookJob.php — Eloquent для failed_webhook_jobs
- ProcessWebhookJob::failed() через DB::table->insert (не Eloquent::create)
чтобы обойти RLS: failed-callback запускается вне транзакции воркера,
SET LOCAL app.current_tenant_id не выставлен, политика бы отвергла INSERT.
Запись должна попасть в БД даже в катастрофическом сценарии.
- payload через json_encode(JSON_UNESCAPED_UNICODE) — UTF-8 кириллица
сохраняется
Sentry::captureException оставлен как TODO для production (на dev-стеке
нет DSN).
3 новых Pest-теста:
- failed() пишет упавший job с webhookLogId (через DB::table('webhook_log')
для FK satisfaction)
- failed() работает БЕЗ webhookLogId (NULL ok — soft FK)
- failed() записывает payload с UTF-8 кириллицей корректно
Pest 48/48 зелёные за 4.7 сек. Pint + Larastan чисто.
Webhook-flow покрыт полностью на dev-стеке (за исключением Sentry и
SendNewLeadNotificationJob — Биз-20 Telegram, ждёт настоящего бота).
CLAUDE.md v1.15 → v1.16. Реестр Открытые_вопросы v1.24 → v1.25.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
1d4738dfa2 |
phase1(infra): partitions:create-months — Artisan-команда (замена pg_partman)
Закрыт пункт «pg_partman replacement» из project_phase1_strategy.md
(расширение pg_partman недоступно на native Windows-стеке без сборки
из исходников).
Реализация:
- app/app/Console/Commands/PartitionsCreateMonths.php
- signature: partitions:create-months {--ahead=2}
- создаёт партиции для deals + supplier_lead_costs (обе по received_at)
- идемпотентна (проверка через pg_class WHERE relkind='r' перед CREATE)
- запускать ежесуточно через Windows Task Scheduler / cron
Smoke-test на dev: --ahead=8 создал 6 партиций (Nov 2026 - Jan 2027) +
12 skipped. После migrate:fresh партиции возвращаются к initial 6.
4 новых Pest-теста в PartitionsCreateMonthsTest:
- создание партиций на 8 месяцев вперёд для обеих таблиц
- идемпотентность (повторный --ahead=5 → 0 created, 12 skipped)
- --ahead=0 создаёт только текущий месяц
- INSERT в deals с received_at в новой партиции корректно роутится
Тесты используют beforeEach/afterEach для cleanup'а через
DROP TABLE ... CASCADE (FK webhook_dedup_keys на партицию propagates).
Pest 45/45 зелёные за 4.9 сек. Pint + Larastan чисто (phpstan-baseline
регенерирован для динамических свойств $this в Pest closure'ах).
CLAUDE.md v1.14 → v1.15. Реестр Открытые_вопросы v1.23 → v1.24.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
2d9e84ef1d |
phase1(antifraud): DuplicateDetector сервис (Биз-19) — антифрод-дедуп по phone в окне 24ч
Закрыт Биз-19 (§10.8.1) на код-уровне. При создании НОВОЙ сделки сервис
DuplicateDetector ищет master по (tenant_id, phone) в окне 24 ч. Если
найден — новой сделке проставляется duplicate_of_id = master.id, баланс
НЕ списывается, SupplierLeadCost НЕ создаётся. ActivityLog пишется с
context.duplicate_of = master.id.
Реализация:
- app/app/Services/DuplicateDetector.php — отдельный сервис:
findMaster(tenantId, phone, ?Carbon $now): ?Deal. Ищет deals с
duplicate_of_id IS NULL и received_at >= now - 24h. Возвращает
первую по received_at ASC или null. WINDOW_HOURS = 24 — константа.
- App\Jobs\ProcessWebhookJob::handle() — после upsertDeal() для новой
сделки вызывает findMaster(). Если master !== создаваемая сделка —
markAsDuplicate(): UPDATE duplicate_of_id + ActivityLog с context.
- DI через app(DuplicateDetector::class) внутри handle() (не в
сигнатуре — для совместимости с прямыми вызовами из Pest без
Bus::dispatchSync).
4 новых Pest-теста:
- master в окне 24ч → дубль, баланс НЕ списывается
- master старше 24ч → НЕ дубль, баланс списан дважды
- дубли изолированы по tenant_id
- ActivityLog для дубля содержит context.duplicate_of
Pest 41/41 зелёные за 4.1 сек. Pint + Larastan чисто.
CLAUDE.md v1.13 → v1.14. Реестр Открытые_вопросы v1.22 → v1.23.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
1ba25e6b4e |
phase1(webhook): закрыты TODO в ProcessWebhookJob — BalanceTransaction/ActivityLog/RejectedDealsLog/SupplierLeadCost
Закрыты 4 TODO в Webhook PoC. Job теперь полностью реализует §5.5
narrative ТЗ за исключением DuplicateDetector (Биз-19) и
SendNewLeadNotificationJob (Биз-20) — отдельные ветви.
5 новых Eloquent-моделей:
- app/app/Models/BalanceTransaction.php — списание lead_charge -1,
type-константы (TYPE_LEAD_CHARGE и т.д.)
- app/app/Models/ActivityLog.php — event=deal.created с
context.source=webhook, event-константы
- app/app/Models/RejectedDealsLog.php — zero_balance ветка вместо
Log::info (payload сохраняется для возможного восстановления)
- app/app/Models/SupplierLeadCost.php — composite PK (id, received_at),
snapshot cost_rub из suppliers, supplier_id resolves через
project_suppliers m2m (первый активный по sort_order)
- app/app/Models/Supplier.php — минимальная для FK target
Job-структура реструктурирована: handle() оркестрирует, делегирует в
logRejection() / chargeNewLead() / resolveSupplierId() / upsertDeal().
Все INSERT'ы в одной DB::transaction — атомарность Ю-2 (deal +
balance_transaction + supplier_lead_cost появляются вместе).
Graceful skip SupplierLeadCost если у проекта нет активного supplier
через project_suppliers + Log::warning. TODO для production: SystemSetting
fallback.
6 новых Pest-тестов в ProcessWebhookJobTest:
- BalanceTransaction lead_charge -1 для новой сделки
- Дубль vid НЕ создаёт BalanceTransaction
- ActivityLog event=deal.created с context.source=webhook
- RejectedDealsLog reason=zero_balance при balance_leads=0
- SupplierLeadCost snapshot cost_rub (helper seedSupplierForProject)
- SupplierLeadCost graceful skip без активного supplier
Pest 37/37 зелёные за 3.9 сек. Pint + Larastan чисто (ide-helper:models
регенерирован для 5 новых моделей).
CLAUDE.md v1.12 → v1.13. Реестр Открытые_вопросы v1.21 → v1.22.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
4803fa0200 |
phase1(webhook): Deal/WebhookDedupKey + ProcessWebhookJob (advisory lock) — CTO-17 addendum
Webhook PoC раскрыл архитектурный пробел в schema v8.6: §5.5-спецификация
делает INSERT в webhook_dedup_keys ДО INSERT в deals (атомарный захват
ключа), но FK был immediate. Решение в две стадии:
1. schema.sql v8.6 → v8.7 — DEFERRABLE INITIALLY DEFERRED на FK
(deal_id, deal_received_at) → deals. ON DELETE CASCADE остаётся
immediate. В bare-транзакции production worker'а решает проблему.
2. Pivot Job на pg_advisory_xact_lock — Pest-тесты с DatabaseTransactions
trait всё равно падали: PG проверяет deferred FK на RELEASE SAVEPOINT,
не на outer COMMIT. Воспроизведено standalone PHP-скриптом, это
PG-семантика subtransactions. Advisory lock работает identically
в любой вложенности транзакций. DEFERRABLE FK сохранён в schema
как defense-in-depth для batch-импортов без savepoint.
Backend стек:
- app/app/Models/Deal.php — composite PK через override
setKeysForSaveQuery (PG требует id+received_at для partition pruning)
- app/app/Models/WebhookDedupKey.php — мини-модель для тестов и debug
- app/database/factories/DealFactory.php — fake данные с received_at
в текущей партиции
- app/app/Jobs/ProcessWebhookJob.php — advisory-lock-based upsert
по §5.5 v8.7. PoC scope: dedup + balance check + project findOrCreate.
TODO для следующих ветвей: BalanceTransaction, SupplierLeadCost,
ActivityLog, RejectedDealsLog, DuplicateDetector (Биз-19).
- app/tests/Feature/DealModelTest.php — 6 тестов composite PK + связи
- app/tests/Feature/ProcessWebhookJobTest.php — 6 тестов: новая сделка,
дубль vid, balance=0, изоляция тенантов, findOrCreate проекта,
ON DELETE CASCADE.
Pest 31/31 за 2.7 сек. Pint + Larastan чисто (phpstan-baseline регенерирован,
scanFiles _ide_helper_models.php добавлен в phpstan.neon).
Документы:
- db/CHANGELOG_schema.md §W (две стадии решения)
- narrative §2.4/§5.5/§6.5/§11 синхронизированы под advisory lock
- Реестр Открытые_вопросы v1.20 → v1.21
- CLAUDE.md v1.11 → v1.12
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
e7c075919a |
phase1(hygiene): narrative ↔ schema v8.6 webhook dedup — закрытие техдолга v1.19
Точечная in-place синхронизация SQL/PHP-примеров webhook handler'а в narrative
ТЗ под двустадийную dedup-логику schema v8.6 (CTO-17). 8 разделов, без bump'а
версии файла (как для L13-гигиены
|
||
|
|
f502b0058d |
phase1(backend): multi-tenant фундамент развёрнут — schema v8.5→v8.6 + migrate:fresh
Backend multi-tenant фундамент развёрнут на dev-БД liderra: 68 таблиц (52 обычных + 16 партиций) + 36 RLS-policies + 5 функций + 13 триггеров. `php artisan migrate:fresh` за 870 ms через одну raw-SQL миграцию `load_initial_schema.php` (DB::unprepared с db/schema.sql). Первый реальный запуск schema.sql на pristine PG 16 поймал 2 несовместимости v8.5, исправлены архитектурно (CTO-17): 1. CREATE UNIQUE INDEX на партиционированной deals (schema:1263) PG требует partition key (received_at) в UNIQUE; включить нельзя — ломает идемпотентность webhook'ов. Решение: новая таблица webhook_dedup_keys (не партиционированная, PK (tenant_id, source_crm_id) → deal_id, composite FK на deals(id, received_at) ON DELETE CASCADE, RLS tenant_isolation USING+WITH CHECK). UNIQUE INDEX в deals заменён на обычный. Webhook handler — двустадийная UPSERT. 2. GENERATED ALWAYS AS на pd_subject_requests.deadline_at (schema:1999) `+ INTERVAL '30 days'` не immutable. Решение: обычная TIMESTAMPTZ NOT NULL + триггер trg_pd_subject_requests_deadline + функция set_pd_subject_request_deadline(). Изменения: - db/schema.sql: v8.5 → v8.6 (заголовок, 1 новая таблица, 1 RLS-policy, 1 функция, 1 триггер, замена UNIQUE на обычный INDEX, замена GENERATED на TIMESTAMPTZ NOT NULL) - db/CHANGELOG_schema.md: новая запись §X v8.5→v8.6 - db/00_create_roles.sql (NEW): deployment-скрипт 4 ролей PG для production (crm_app_user, crm_admin_user BYPASSRLS, crm_migrator BYPASSRLS+CREATEDB, crm_audit_writer). На dev — postgres superuser (schema §13 разрешает) - db/02_grants.sql (NEW): GRANT/REVOKE из закомментированных секций §13 schema. REVOKE на 6 saas-таблицах для crm_app_user (defense-in-depth поверх RLS, OPEN-И-14). REVOKE DELETE на 4 финансовых таблицах для crm_admin_user (только soft markers) - app/database/migrations: удалены 3 default Laravel (users/cache/jobs дублировались с нашей schema), создан 0001_01_01_000000_load_initial_schema.php - .squawk.toml: + excluded_paths для db/00_create_roles.sql (psql client-side variables :'name' не парсятся libpg_query) - docs/Открытые_вопросы_v8_3.md: v1.18 → v1.19, CTO-17 закрыт фиксом, 70 ✅ / 5 🟦 / 4 ⏸. Техдолг: ТЗ §15-16 webhook handler нужно обновить под двустадийную dedup-логику - CLAUDE.md: v1.9 → v1.10 (§0 ссылки на schema v8.6 + реестр v1.19; §2 метрики БД 54→55/91→92/35→36/12→13/4→5; §6 фундамент развёрнут) - cspell-words.txt: +9 новых терминов Smoke-test через Boost MCP database-query: - 68 таблиц (включая webhook_dedup_keys + 16 партиций) - 36 RLS-policies - 35 RLS-enabled (relkind='r'; +2 partitioned 'p' = 37 total) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e81eeef1fe |
phase1(db-tooling): squawk v2.51 + pgFormatter v5.9 — закрытие тулчейна фазы 1
Активны Прил. Н #15 squawk и #16 pgFormatter; фаза 1 по тулчейну закрыта 13/17 (без #17 pg_partman — Windows native стек). squawk: - bin/squawk.exe (npm i -g squawk-cli + копия из ~/AppData/... /squawk-cli/js/binaries/squawk → bin/squawk.exe; npm-wrapper не находит spawn-target без .exe на Windows) - .squawk.toml: 9 правил исключено (5 bootstrap-неприменимых + 4 дизайнных решения проекта). Smoke-test на db/schema.sql — 0 issues. - lefthook.yml: pre-commit job на staged *.sql - npm run lint:sql pgFormatter: - bin/pgFormatter/ (pg_format + lib/ из v5.9 release tarball, запуск через Cygwin Perl 5.42.2 из Git for Windows — без отдельной установки ActivePerl/Strawberry) - Без авто-fix хука: diff vs db/schema.sql 3255 строк (UPPERCASE→lowercase для типов, плотный одностроковый стиль, перетасовка inline-комментариев) — стиль schema.sql ручной, авто-fix недопустим - Только ручной режим: npm run format:sql:check (dry-run + diff), npm run format:sql (пишет в db/schema.sql.formatted для review) Документы: - Tooling Прил. Н v1.5 → v1.6 (§0 «Что нового», §3.3 таблица, §10.1 п.8 ⏸→✅, §11.4 уточнение по Cygwin Perl) - CLAUDE.md v1.8 → v1.9 (§0 ссылка, §6 текущая фаза 17/28, колонтитул) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
59f8ca04bb |
phase1(hooks-fix): сужение pre-push lychee + 2 битых ссылки + allowlist demo HTML
При первом запуске pre-push hook'ов после установки lefthook (`4eee06f`)
обнаружились 3 проблемы — все легитимны, не в самом lefthook'е:
1. **gitleaks-full-history** ловил 42 хита `ru-phone-unmasked` в HTML-концептах
handoff Платона (liderra_v8_handoff/concepts/v8_*.html и web/v8/v8_*.html).
Это ДЕМО-данные для визуализации, не реальные ПДн. Добавлены в allowlist
.gitleaks.toml: `liderra_v8_handoff/concepts/.*\.html` + `web/v8/.*\.html`
+ `app/composer.lock`.
2. **lychee-links** ловил 21 ошибку «Cannot resolve root-relative link» на
ссылки `/login`, `/register`, `/legal/*` в HTML-концептах. Эти маршруты
появятся только в фазе 2+ (Vue+Vuetify реализация). Сужен glob
pre-push lychee — выкинут `web/**/*.html`. Дополнительно добавлены
`liderra_v8_handoff/concepts` и `web/v8` в .lychee.toml exclude_path
как защита для других вариантов запуска.
3. **2 РЕАЛЬНЫХ битых ссылки** в narrative — спасибо lychee, нашёл:
- `docs/CRM_bp-gr_Инструкция_v8_5.md:6128` ссылался на `brandbook.md`,
но этот файл удалён 08.05.2026 (заменён на `liderra_v8_handoff/docs/
BRANDBOOK_v2.md` v8 Forest). Исправлен относительный путь.
- `README.md:88` ссылался на `docs/README_АРХИВ_v8_4.md`, но переименован
в `_v8_5.md` коммитом `4ffc19a` от 07.05.2026. Поправлено + bump v8.4→v8.5
в подписи.
Финальный smoke-test после правок:
- gitleaks detect (full history): «no leaks found»
- lychee на narrative .md: 122 OK / 0 Errors / 5 Excluded
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
9ee31b71cb |
phase1(docs): Tooling v1.5 + CLAUDE.md v1.8 — фиксация фактической установки Boost
Doc hygiene после установки Boost ( |
||
|
|
3a9ed7101e |
phase1(hygiene): narrative ↔ Laravel 13 — закрытие техдолга v1.17
Точечная синхронизация трёх narrative-документов под Laravel 13 (один токен на файл, без bump'а версии каждого): - docs/CRM_bp-gr_Инструкция_v8_5.md:6219 - docs/Vybor_oblaka_v8_3.md:3 - docs/Админка_SaaS_v8_2.md:103 Не трогалось намеренно (исторические записи): - docs/Объединённый_конспект.md:149 — Часть I, фиксация решений v8.0 на 03.05 - docs/Открытые_вопросы_v8_3.md:354 → 361 — фиксация результата аудита Реестр Открытые_вопросы v1.17 → v1.18 (новый блок «закрыт техдолг»). Оперативная карта CLAUDE.md v1.6 → v1.7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
63c7364e6e |
reopen(stack): Laravel 11 → Laravel 13 — фиксация переоткрытия
Произошло так: 08.05.2026 при `composer create-project laravel/laravel app` я не зафиксировал `^11` — Composer подтянул свежайшую `laravel/framework: ^13.7` (Laravel 13.7, релиз ~Feb 2026), вместо ожидаемого Laravel 11 LTS. Smoke-test'ы подтвердили работоспособность Laravel 13: - php artisan migrate: 3/3 default-миграций OK - pestphp/pest 4.7.0: 2/2 за 281 ms - laravel/pint 1.29: pint --test passed - larastan/larastan 3.9.6 + phpstan 2.1.54: analyse passed (с baseline) - barryvdh/laravel-ide-helper 3.7.0: ide-helper:generate OK Live-проверка совместимости 5 ключевых плагинов: - laravel/boost v2.4.6: composer dry-run резолвит lock без conflict - остальные 4 — установлены и запущены без issue Заказчик 08.05 (поздний вечер) принял Laravel 13 как latest stable. Откат дороговат — rm -rf app/ + повторение всей сессии (~10-15 мин). По правилу «явная фиксация переоткрытий» обновлены 3 источника: - CLAUDE.md v1.5→v1.6: §2 backend (Laravel 11 → Laravel 13 + объяснение обстоятельств), §0 источники (Tooling v1.4, Реестр v1.17), футер - docs/Tooling_v8_3.md v1.3→v1.4: блок «Что нового в v1.4» (live- проверка совместимости 5 плагинов + установка Pint/Larastan/IDE Helper) - docs/Открытые_вопросы_v8_3.md v1.16→v1.17: блок «Что изменилось в v1.17» с обстоятельствами, импактом и техдолгом Техдолг (для следующих сессий): синхронизация narrative ТЗ + 2 других архивных документов под Laravel 13: - docs/CRM_bp-gr_Инструкция_v8_5.md (строка 6219, главное ТЗ) - docs/Vybor_oblaka_v8_3.md (строка 3, аналитическая записка по облаку) - docs/Админка_SaaS_v8_2.md (строка 103, описание стека админки) Не блокер для разработки, но нарушает связность архива. Включить в hygiene-проход при следующем апдейте narrative до v8.6. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
30f0335f5f |
phase1(test): Pest 4 swap + reopen(CTO-12) — Pest 3 → Pest 4
Произошло так: при `composer require pestphp/pest pestphp/pest-plugin-laravel --dev --with-all-dependencies` я не зафиксировал `^3` — composer подтянул свежайшую Pest v4.7.0 + pest-plugin-laravel v4.1.0. Smoke-test (`./vendor/bin/pest`) на default-тестах Laravel 11 прошёл 2/2 за 281 ms — backward-compat с Pest 3 syntax подтверждён. Заказчик 08.05 (поздний вечер) принял Pest 4 после live-проверки на стеке. Бонус Pest 4: browser testing (без Dusk), stress testing, mutation testing v2. Откат дёшев — `composer require pestphp/pest:^3`. Что сделано: - composer remove phpunit/phpunit (был direct dev-dep) — phpunit остался как транзитивная зависимость Pest - composer require pestphp/pest:^4.7 pestphp/pest-plugin-laravel:^4.1 --dev - Pest.php создан через `vendor/bin/pest --init` (`tests/Pest.php`) - `vendor/bin/pest` smoke-test: 2 passed (Unit/Feature ExampleTest), 281 ms - `vendor/bin/pest --init` упал на интерактивном промпте «Wanna show Pest some love?» в non-interactive PowerShell — Pest.php к этому моменту уже создан, нефатально Reopen(CTO-12): по правилу «явная фиксация переоткрытий» обновлены 3 источника: - docs/Открытые_вопросы_v8_3.md v1.15→v1.16: блок «Что изменилось в v1.16», таблица §0 (CTO-12 переоткрыт+закрыт), запись §3 (Pest 4 + обоснование), финальный список §X (Pest 4) - docs/Tooling_v8_3.md v1.2→v1.3: блок «Что нового в v1.3», §3.1 п.4 (Pest 4 в boost:install), §3.4 строка 18 (Pest 4 + бонусы), §6 п.2 (конфликт Pest↔PHPUnit), §10.1 п.9 (процедура установки + warning про --init на Windows non-interactive) - CLAUDE.md v1.4→v1.5: §0 источники (Tooling v1.3, Реестр v1.16), §3.2 строка 18 (Pest 4), §7 п.5 (Pest 4 в boost:install), футер с историей версий Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
477e866726 |
phase1(stack): native Windows вместо Sail — Tooling v1.2, CLAUDE.md v1.4
Обнаружено 08.05.2026 (вечер): машина — VPS на OpenStack (Manufacturer = OpenStack Foundation, HypervisorPresent = True). Provider не пробрасывает nested virtualization в guest VM (VirtualizationFirmwareEnabled = True на CPU, но KVM на хосте блокирует VT-x для гостя). Docker Desktop показывает «Virtualization support not detected, Engine stopped». Следствие: ранее обсуждённые варианты A (полный WSL2) и B (Sail на Windows FS) — физически невозможны на этой машине. Переход на вариант D — native Chocolatey-стек. Изменения: - Tooling v1.1 → v1.2: §3.1 п.2/п.3 — Sail удалён из allow-list Boost. Шапка обновлена под native-стек. Блок «Что нового в v1.2» с обоснованием. - CLAUDE.md v1.3 → v1.4: §0 (версия Tooling v1.2), §6 (стек dev = native PG 16 + Memurai + PHP 8.3), §7 п.3 (Sail отключён в boost:install). Футер. Установлено 08.05 вечер: - ❌ Docker Desktop — удалён (choco uninstall docker-desktop) - ⏳ PostgreSQL 16.13 — устанавливается (choco install postgresql16) - ⏳ Memurai Developer 4.1.8 — устанавливается (Redis 7-совместимый, free до 1GB RAM) pg_partman/pg_audit/pg_anonymizer на native Windows — ручная замена. На MVP: партиции через php artisan cron-команду (Биз-партиции уже в schema v8.5), audit-trigger'ы уже встроены. Подробное обоснование и триггеры пересмотра — в personal memory project_phase1_strategy.md (не коммитим). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
7f28721723 |
fix(typo): laravel/liderra → laravel/laravel в триггере фазы 1
CLAUDE.md §6 и Объединённый_конспект Часть X указывали `composer create-project laravel/liderra app`. Такого Composer- шаблона на Packagist нет. `liderra` — название нашего продукта, а не пакета. Правильный official-стартер: `laravel/laravel`. Замечено при smoke-test окружения 08.05 (готовка к фазе 1, вариант B — Sail на Windows FS). Без этого фикса первая команда фазы 1 упала бы. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e1641f2e16 |
docs(hygiene 08.05): Часть X конспекта — ребрендинг + CTO-12 + Диз-1
Доделка консистентности архива по итогам сессии 08.05.2026 (коммиты |
||
|
|
63c7c83d82 |
close(Диз-1): HTML-прототипы покрыты handoff'ом Платона — реестр v1.15, CLAUDE.md v1.3
Решение заказчика 08.05.2026: формально закрыть Диз-1 (P1) — handoff v8 Forest от Платона покрыл HTML-прототипы на 100%+ (13 экранов в web/v8/ против 8 запланированных + 3 экрана ошибок). Прил. Л не выпускается (избыточно после handoff'а). Точечные расхождения handoff vs ТЗ (зафиксированы в шапке v1.13) реализовывать по ТЗ/schema: - 14 «обобщённых» статусов в BRANDBOOK_v2 §3.6 ≠ 14 slug'ов в schema - 3-й click-wrap в v8_login.html ≠ ТЗ §1.5/§4.1 - SSO «локальный 2FA fallback» в v8_admin.html ≠ ТЗ OPEN-И-13 axe: 81 violation на 10/13 HTML (color-contrast на декоративных separator'ах) — исправлять при реализации в Vue+Vuetify. Изменения: - Открытые_вопросы_v8_3.md v1.14 → v1.15: Диз-1 в §5 → ✅; сводка §0 (дизайнер 2→3 закрыто, итого 78/68→69 ✅, 5→4 ⏸, 4→3 P1) - CLAUDE.md v1.2 → v1.3: §0 (версия реестра v1.15), §6 (P0-блокер упоминание Диз-1 закрыт), футер Открыто на 08.05.2026: **4 ⏸ продуктовых** — Б-1 (P0) + 3 P1 (Диз-3, DO-2, DO-4), все ждут Б-1. Один настоящий блокер — Б-1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
62a85f2a08 |
close(CTO-12): Pest 3 — реестр v1.14, Tooling v1.1, CLAUDE.md v1.2
Выбран Pest 3 (не PHPUnit). Обоснование: - datasets лаконично покрывают 14 статусов воронки и 34 RLS-политики - architecture testing закрепляет правила Claude на код-уровне (например, integration тесты не моки́руют БД — линт вместо памяти) - родной для Laravel/Boost (Nuno Maduro в core team) — один guideline вместо разрыва на boost:install - Pest на PHPUnit под капотом — откат дёшев Изменения: - Открытые_вопросы_v8_3.md v1.13 → v1.14: запись о закрытии в §3, сводка §0 (CTO 15→16 закрыто, итого 77→78 / 67→68 ✅) - Tooling_v8_3.md v1.0 → v1.1: §3.1 п.4, §3.4, §6 п.2, §10.1 п.9 - CLAUDE.md v1.1 → v1.2: §0 (версии источников), §3.2 строка 18, §7 п.5, футер Импакт: при composer create-project (триггер фазы 1) — вместо шага «решить Pest или PHPUnit» теперь composer require pestphp/pest --dev --with-all-dependencies + vendor/bin/pest --init. Guideline PHPUnit на boost:install отключить. P0-блокер фазы 1 остаётся один — Б-1 (юр. лицо). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
a4d15ee1d5 |
docs(hygiene v8.5): Часть IX конспекта + дельта v8.5 ER-диаграмм
Доделка консистентности архива после реализации v8.5 (коммиты |
||
|
|
4ffc19a7d2 |
docs(narrative): v8.4 → v8.5 — реализация 27 решений аудита C
Завершает блок реализации v8.5 после schema-коммита
|
||
|
|
aabf827f76 |
docs(audit-C): закрытие 27 вопросов аудита C → реестр v1.12
Решение заказчика 07.05.2026: «A везде» по всем 27 вопросам аудита C. 8 P0 разблокированы для триггера фазы 1 (composer create-project): - Биз-17 (manual routing), Биз-18 (TTFR 15 мин + alert), Биз-19 (24ч-дедуп без списания, duplicate_of_id) - CTO-13 (e2e SET LOCAL+PgBouncer тест в спринте 1) - OPEN-И-13 (OIDC+JIT+break-glass), OPEN-И-14 (WITH CHECK + REVOKE), OPEN-И-15 (append-only + hash-chain + crm_audit_writer), OPEN-И-16 (Sentry whitelist+regex) 12 P1 + 7 P2 закрыты с импактом на schema/narrative (см. §13.10.4 — schema → 54 таблицы, +6 триггеров, +1 роль). Реализация v8.5 — отдельный коммит (схема + narrative + CHANGELOG). Сводка §0: 67 ✅ / 5 🟦 / 5 ⏸ (1 P0 Б-1, 4 P1 ждут Б-1 или у Claude). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
4d65d6a523 |
docs(audit-C): раздел 13 — 27 новых вопросов из аудита C (07.05.2026)
Аудит C — архитектурно-функциональный (CRM-best-practices vs narrative v8.4) + STRIDE threat modeling. Запускались два независимых read-only general-purpose агента: C-1 (арх) и C-2 (security). Найдено 27 новых открытых вопросов: - Бизнес/продукт (8): Биз-17..24 — автораспределение, TTFR-SLA, антифрод дублей, Telegram, маркетинг-конверсии, lead scoring, гео-таргетинг сделок, нотификация просрочки. - CTO (4): CTO-13..16 — SET LOCAL+PgBouncer тест (P0), UTM в deals, impersonation two-person, skill-based routing. - OPEN-И — DevOps/security (14): OPEN-И-13..26 — Yandex 360 SSO flow, RLS WITH CHECK + REVOKE, append-only audit hash-chain, Sentry PII scrubbing, ротация секретов cron, DNS-rebinding, лимит api_keys, signed URL, anti-DDoS, crypto-shred, audit-writer role, pg_anonymizer, эскалация лидов, call_recordings задел. - Юрист (1): Ю-9 — 152-ФЗ ст.21 ч.5 запрет impersonation в processing_restricted. 8 P0 (4 архитектура + 4 security), 12 P1, 7 P2. Каждый вопрос с тремя вариантами решения A/B/C и рекомендуемым. Закрытий нет — правило §2.2. Все 5 ⏸ из v1.10 в работе. Версия Открытые_вопросы v1.10 → v1.11. Сводка §0 пересчитана: 50 → 77 продуктовых, 5 → 32 ⏸, 1 → 9 P0, 4 → 16 P1, 0 → 7 P2. cspell-words.txt: +антифрод, TTFR, UTM, utm. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
574154bcf9 |
fix(schema+narrative): B-5 — schema P1 + синхронизация метрик
schema.sql v8.4 (hotfix Z.5.3-Z.5.6): - outbound_webhook_subscriptions.events: убран DEFAULT '[]' (конфликт с CHECK jsonb_array_length>0). NOT NULL остался — приложение должно явно передать список событий ≥1. - deal_tag_pivot: добавлены ENABLE RLS + CREATE POLICY tenant_isolation через JOIN на deal_tags(tenant_id) — паттерн как у saas_invoice_items. - Шапка schema.sql:107-108: «33 политики / 34 защищённых» → «34/34, 1:1» (после правки выше). CHANGELOG_schema.md: расширена запись Z.5 (Z.5.3-Z.5.6) с финальными метриками. narrative v8.4: - §1.4, §3.2, §7.1, §22.6, §27 «33 политики на 34» (5 мест) → «34/34, 1:1». Шапка «Что нового в v8.4»: +3 RLS вместо +2 (с учётом hotfix). Прил. Б+В: - Шапка ссылалась на «schema.sql v8.3, 51 таблица» → актуально: «schema.sql v8.4, 53/86/34/34, при расхождении приоритет за schema.sql». Добавлены изменения v8.4 в перечень того, что не отражено в ER. cspell-words.txt: добавлено «партиционированной» (склонение, нужно для CHANGELOG Z.5.4). Метрики schema.sql v8.4: 65 CREATE TABLE (53+12), 86 индексов, 34 RLS-политики, 34 ENABLE RLS, 3 роли БД. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
08c8b3705c |
fix(narrative): B-4 — внутренняя консистентность v8.4
- §1.4/§3.2/§22.6/§23.* «29 политик» (4 места) → «33 политики на 34 защищённых таблицах» (расхождение по `saas_invoice_items` — намеренное, защита косвенно через FK на `saas_invoices`). - §3.2: ссылка «schema.sql v8.1, раздел 12» → «db/schema.sql v8.4». - §7.* «обновление updated_at через trigger» (стр. 1594) уточнено: Eloquent `$timestamps = true` (application-уровень). Trigger в БД не вводим на MVP, чтобы не дублировать ORM. В schema.sql triggers нет. - §7.3 — добавлен явный disclaimer: источник истины = `db/schema.sql`, inline-DDL ниже могут отставать (см. CHANGELOG_schema.md). - §4.1 (стр. 660-666): добавлен 3-й чекбокс «Согласие с Политикой конфиденциальности» — синхронизация с §1.5 (3 click-wrap, OPEN-Ж-3). - §5.1 (стр. 5693): «Только webhook (без CSV в MVP)» → «webhook основной + CSV-импорт опциональный модуль (раздел 6) + ручное создание (раздел 10.7)» — синхронизация с §1.5 и §6. - Заключение (стр. 5878): шапка v8.1 от 03.05.2026 → v8.4 от 06.05.2026, P0-блокеры 9→1 (Б-1), следующие шаги переписаны с учётом фактического статуса. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1ffd5c1609 |
fix(narrative): B-3 — домены и сервисы синхронизированы с DO-1/Ю-7
- Все 15 упоминаний placeholder-домена `crm-аналог.ru` заменены на `lidpotok.ru` (имя проекта; DO-2 «купить домен» — отдельный P1). Затронуты: webhook URL, register/verify-email links, wildcard subdomains, *.lidpotok.ru SSL, staging.lidpotok.ru, status.lidpotok.ru, admin@lidpotok.ru. - Таблица §11.1 (стр. 363-364): «Yandex / VK Cloud (prod)» → только «Yandex Object Storage (prod, по DO-1)». Email: «Mailgun / SendGrid / собственный SMTP» → «Unisender Go (по Ю-7)». - §17.7 Library (стр. 2845): «SMTP / Mailgun API» → «SMTP-relay (Unisender Go, см. Ю-7)». - §22.* (стр. 4497-4499): список РФ-провайдеров получил пометку «✅ Yandex Cloud — выбран по DO-1, VK/Selectel — альтернативы Прил. К не выбраны». Это точнее, чем простой перечень. Историческая запись «Ю-7 — Mailgun → Unisender Go» в §1.* шапки оставлена как есть (показывает решение Ю-7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
bfe6c9b685 |
fix(docs): B-2 — арифметика и опечатки в Открытые_вопросы и Tooling
- Открытые_вопросы §0 v1.10 (стр. 17): «✅ 30 → 40, ⏸ 13 → 5, P2 10 → 0» → «✅ 33 → 40, ⏸ 12 → 5, P2 7 → 0». Исходные значения соответствуют таблице §0 v1.9 (стр. 24: «33 / 5 / 12»). OPEN-К-1/К-7 учитываются в счётчике приложения К, не в счётчике «продуктовых». - Открытые_вопросы CTO-12 (стр. 25): убрана несуществующая ссылка «Дефолт по Прил. Н §3.4: PHPUnit». В §3.4 такого дефолта нет — только требование «выбрать ОДИН до установки Boost» (§3.4 + §6 п. 2). - Tooling §6 (стр. 184): ссылка `см. §11` для Lighthouse → `см. §12` («Что вне 28 инструментов»). §11 — про Windows/PowerShell. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
4321251bc1 |
docs(archive): README v8.3.3 → v8.4 (синхронизация с narrative v8.4)
- Переименование: docs/README_АРХИВ_v8_3.md → _v8_4.md. - Шапка: версия v8.3.3 → v8.4, состав 18 → 17 файлов в docs/ (минус удалённый Plan_narrative_v8_4.md). - Эволюция версий: добавлена запись v8.4 (06.05.2026 поздний вечер, финал narrative + переименование + schema v8.4 + регистр v1.10). - Главный narrative: имя файла _v8_3 → _v8_4, размер ~310→~340 КБ, описание расширено под все 13 разделов плана v8.4. - Прил. А (schema.sql): v8.3 → v8.4, метрики 51/81/31 → 53/86/33, +outbound_webhook_subscriptions/deliveries (закрытие тех-долга §19.10). - Прил. Е (Открытые_вопросы): v1.6 → v1.10 (40✅/5🟦/5⏸, 0 P2). - «Что осталось мне (Claude)»: v8.4 narrative ✅ выполнено; Прил. Л — 3/8 готово, осталось 04..08. - История версий: добавлена строка v8.4. - Обновлены кросс-ссылки в CLAUDE.md (§0), README.md, db/CHANGELOG_schema.md, docs/Tooling_v8_3.md, docs/CRM_bp-gr_Инструкция_v8_4.md. - Исторические упоминания старого имени в Объединённый_конспект.md, Analiz_originala_v8_3.md, Pravila_raboty_Claude_v1_1.md и в записях прошлых версий — оставлены намеренно (правило §4.4 правил работы Claude — прослеживаемость решений). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c8db9a26c4 |
docs(narrative): v8.4 финал (§23.10 + 13/13 + rename _v8_3 → _v8_4)
- §23.10 Админка SaaS: расширен с 5 до 10 подсекций — Биз-16 (колонка «Желаемое × факт сегодня» с цветовым кодированием), Ю-2 (поставщики, дашборд маржи, сверка счетов), OPEN-Д-5/И-1 (incidents_log: 8 типов × 4 severity, 24ч SLA уведомления РКН для data_breach по 152-ФЗ ст.18.1 ч.3.1), Прил. Д (workflow обращений субъектов ПДн с 30-дневным SLA), таблица преимуществ vs оригинал. - Шапка narrative: убрано «in progress», блок «Что нового в v8.4» дополнен §23.10. Подвал: имя файла v8.4. - Переименование: CRM_bp-gr_Инструкция_v8_3.md → _v8_4.md. - Кросс-ссылки обновлены: CLAUDE.md (§0/§2/§6/§8 — версии, метрики схемы 53/86/33, счётчик прототипов 3/8), README.md (версии, статусы прототипов, репо CoralMinister), db/schema.sql, db/CHANGELOG_schema.md, web/index.html. - .lychee.toml: exclude приватного github.com/CoralMinister/lidpotok (404 анонимно — норма). - Plan_narrative_v8_4.md удалён (план v8.4 выполнен полностью, 13/13). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
60897e0ed2 |
docs(narrative): v8.4 +4 разделов (§5, §8, §9, §12)
§5 Источник данных — Webhook: - §5.1 переписан: 3 канала ingress (webhook ~95%, manual ~3%, CSV ~2%) - Добавлен блок про outbound webhook как уникальное преимущество с привязкой к §19.10 и 7 линиям доказательств §8 Воронка и статусы: - §8.1: 14 статусов с явным разделением 6 системных vs 8 настраиваемых, цвета hex из брендбука v1.1, описание каждого статуса - §8.2: free state machine (CTO-2) с 4-пунктным обоснованием - §8.5 переписан в 4 подсекции: что настраивается (только название на MVP), примеры, резолв через Redis-кеш, UX inline-редактирования §9 Мои Проекты (большой раздел): - 5 → 10 подсекций - §9.2: таблица с лимитами/регионами/днями - §9.4: карточка проекта 11 секций (паритет с оригиналом, партии 10.3-10.7) - §9.5: EffectiveLimitCalculator (главное расхождение №2 с оригиналом): динамический effective_daily_limit_today, 5 триггеров пересчёта, логирование в project_limit_adjustments - §9.6: project_suppliers m2m - §9.7: soft-delete + retention 180 дней (Биз-14, cron disabled до Б-1) - §9.8: capabilities поставщиков B1/B2/B3 (партия 13.3.5) - §9.9: расширенные действия. §9.10: окно обслуживания (паритет не делаем) §12 Дашборд: - §12.5.6 «Конверсия проектов» (паритет с /admin/visit/rt-stat, партия 12.1): 17 колонок (id/тег/проект/статус/источник/обработано + 11 status-колонок), формат N (XX.XX%), monotone per column, total-row, видимость через users.preferences - Наши расширения сверх паритета: экспорт XLSX через report_jobs + drill-down из ячейки в /deals - +2 эндпоинта в §12.6 Шапка narrative обновлена. План v8.4: 12/13 ✅ (было 8/13). Осталось только §23.10 Админка SaaS (большой). cspell-words.txt: +резолв, +пунктным. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |