Commit Graph

5 Commits

Author SHA1 Message Date
Дмитрий 9ff19f3cc3 @
feat(bot): всеобъемлющая инструкция (36 статей) + 31 узкая экскурсия, которая открывает окна

Живой урок владельца 12.07.2026: «дубли чистятся в 2-х местах, а бот выдумал третье»,
«стыдно такого бота показывать», «видео показываем полное, а я спрашиваю про одно —
надо резать», «надо не только кнопку показывать, а и что за ней».

База знаний: 17 обзорных статей → 36 узких по темам. Портал обойдён целиком
(5 агентов): все экраны, окна, подсказки «(?)», тексты ошибок, внутренние правила.
Новое, чего бот не знал: дубли в ДВУХ местах (Поле и Предложения) + окно «источник
уже есть»; правило 18:00; почему приходит меньше лимита; оплата по счёту и акты;
списания; безопасность и 2FA; отчёты; массовые действия; регистрация.

Экскурсии: 15 → 31, каждая на свою тему (3–7 шагов). Раннер GuidedTour научен
шагу `open` — сам открывает окно/вкладку и подсвечивает то, что ВНУТРИ
(окно дублей, форму подбора, диалог пополнения, панель тарифов, карточку сделки).
99 новых якорей data-tour расставлено по всему порталу (4 агента).

Поиск: веса в tsvector (заголовок A / синонимы B / текст C) — иначе на «чистка
дублей» первой всплывала статья «Списания» из-за мимоходного упоминания «поля».

Тесты: Pest бот 39/39, Vitest 1222/1222. Новые сторожа: у каждой статьи есть
экскурсия; экскурсия не короче 3 и не длиннее 7 шагов; каждая цель экскурсии
реально существует в разметке; экскурсии про действия обязаны открывать окно.
Живая проверка в браузере: экскурсия про дубли сама открыла окно объединения
и перешла на второе место чистки.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@
2026-07-12 12:56:22 +03:00
Дмитрий c986cce4e5 feat(security): рабочая «Завершить сессию» — реальный отзыв активных сессий
UI-аудит: вкладка Безопасность показывала фейк-сессии с мёртвой кнопкой.
Теперь — реальные активные сессии + рабочий отзыв.

- UserSessionTracker (новый): запись сессии при входе (login + 2FA verify +
  recovery-use) в существующую таблицу user_sessions; отзыв = удаление строки
  + удаление сессии из Redis по session_id (реальный выход с устройства);
  logout снимает текущую сессию из списка. Best-effort (не ломает вход/выход).
- AccountController: GET /api/account/security отдаёт реальные сессии;
  DELETE /api/account/sessions/{id} — отзыв (только свои; чужая → 404).
- Фронт SessionsTable: список + кнопка «Завершить» (кроме текущей).
- phpstan-baseline обновлён (Pest-$this нового теста).

Pest: 10/10. Верификация: Playwright (2 сессии → «Завершить» → исчезла).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 17:15:26 +03:00
Дмитрий 8927506819 feat(security): реальная смена пароля + недавние входы вместо mock-заглушек
UI-аудит раунд 2, вкладка «Безопасность» — убраны фейк-данные и мёртвые кнопки.

Backend (schema-free, без смены SESSION_DRIVER):
- AccountController + ChangePasswordRequest: POST /api/account/change-password —
  проверка текущего пароля (Hash::check против password_hash), новый >=10 симв +
  confirmed, лог password_changed/password_change_failed в auth_log (hash-chain).
- GET /api/account/security: last_password_change_at (max по password-событиям
  auth_log) + recent_logins (реальные login_success: устройство/IP/время).
- Роуты под auth:sanctum + throttle:auth-password.
- Pest: 6 тестов. Регрессия Account+Auth — 23/23 GREEN. phpstan-baseline обновлён
  (Pest-$this false-positives нового теста, как у прочих тестов).

Frontend:
- api/account.ts.
- ChangePasswordCard: реальная дата + диалог (текущий/новый/подтверждение,
  show/hide, обработка 422 неверного текущего пароля).
- SessionsTable -> «Недавние входы»: реальный список из API, убраны 3
  захардкоженных фейк-сессии + мёртвая кнопка «Завершить».

NB: индивидуальный отзыв cookie-сессий требует database-драйвера сессий
(инфра-решение владельца) — отдельный follow-up. Сейчас входы — честный read-only.

Верификация: type-check, build, Playwright (диалог: неверный->ошибка,
смена->дата 21.06, восстановление password123; недавние входы — реальные).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 15:03:43 +03:00
Дмитрий cb05657f30 chore(format): prettier --write across 37 .vue/.ts files
Phase 1B audit found 48 files failing `prettier --check`. Auto-apply
via `npx prettier --write resources/js/**/*.{ts,vue,css}` produced
style-only changes:
- consistent quote style
- trailing comma normalization
- spaces around : in v-card style="position: relative" attrs
- explicit ; insertion

No semantic changes. No code-behavior changes. Production-code only;
test files batched separately into `test(frontend):` commit.

Verification:
- npx vitest run → 79/79 files, 614/614 + 3 skipped (no regression).
- npx vue-tsc --noEmit → 0 errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 20:24:33 +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