b9917a90d4b5492c8fe84fc62a72594de85a3ffe
506 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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-гигиены
|
||
|
|
5560ebbdfd |
phase1(eloquent): Tenant/User/Project models + SetTenantContext middleware
Первый Eloquent-слой над schema v8.6 + middleware для RLS-фильтрации HTTP-запросов. Pest 19/19 passed (1672 ms): 4 RLS smoke + 8 model smoke + 5 middleware + 2 default. app/app/Models/ (NEW Tenant.php, Project.php; MODIFIED User.php): - Tenant — saas-уровневая модель (БЕЗ RLS, тенант-родитель). Soft Deletes. hasMany Users, Projects. - User — переписан под нашу схему: password_hash вместо password, first_name/last_name вместо name, override getAuthPassword/Name для Laravel auth-интеграции. Soft Deletes. belongsTo Tenant. - Project — tenant-aware с RLS. belongsTo Tenant. app/database/factories/ (NEW TenantFactory, ProjectFactory; MODIFIED UserFactory): - TenantFactory: уникальный subdomain через Str::random + дефолты (timezone Europe/Moscow, locale ru, is_trial true, api_key_limit 5). - UserFactory: tenant_id через Tenant::factory() chain, email unique через faker, password_hash через Hash::make. - ProjectFactory: tenant_id через factory chain, дефолты под schema.sql (region_mask 255, delivery_days_mask 127, assignment_strategy manual). app/app/Http/Middleware/SetTenantContext.php (NEW, alias `tenant`): - Резолюция tenant_id (приоритет): auth()->user() → subdomain (3+ parts HTTP_HOST) → X-Tenant-Id header (только dev/testing). - Без контекста → 403 Forbidden с явным сообщением. - SET LOCAL app.current_tenant_id внутри транзакции (DB::beginTransaction + SET LOCAL + next() + commit/rollback). PgBouncer-safe (Прил. И Г.1 кейс 2). - Зарегистрирован в bootstrap/app.php через $middleware->alias(). app/tests/Feature/ (NEW TenantModelsTest, SetTenantContextTest): - TenantModelsTest (8 тестов): factories + связи (Tenant→users/projects, User→tenant, Project→tenant) + проверка User::getAuthPassword override. - SetTenantContextTest (5 тестов): 403 без контекста, X-Tenant-Id header, игнор не-числового header, subdomain резолюция через absolute URL, middleware устанавливает app.current_tenant_id для last query. Сопутствующие правки: - app/.gitignore: + _ide_helper_models.php (сгенерированный, как и _ide_helper.php — не в репо) - app/phpstan-baseline.neon: regenerated — Pest dynamic methods ($this->get(), withHeaders()) и factory-return-type mismatch (Larastan v3 не понимает array<string, mixed> vs array<model property of T>) + Request::user/header (Larastan тип hint мисс) + console.php $this в Closure — все в baseline до миграции на typed properties / pest extension - CLAUDE.md §6: Pest 6/6 → 19/19, добавлены модели + middleware - memory project_state.md, MEMORY.md: обновлены под новый этап Не сделано в этой сессии (отложено): - Deal model — composite primary key (id, received_at) + partitioned parent. Эта модель сложнее по архитектуре Eloquent. - ide-helper:models -W -M -N запускался — добавил @mixin IdeHelperX и сгенерил _ide_helper_models.php; но т.к. этот файл gitignored, @mixin строки удалены из моделей (PHPStan не нашёл бы класс на CI). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c6f9c62da0 |
phase1(rls-smoke): CTO-13 — Pest 4 RLS smoke-test (4/4 passed, 662 ms)
Реализованы кейсы 1 + 4 из Прил. И Г.1 «CTO-13: RLS smoke-test через PgBouncer» как первая проверка RLS-фундамента schema v8.6 ДО первого PR с tenant-моделью. app/tests/Feature/RlsSmokeTest.php (NEW): - кейс 1 (× 2 теста): SET LOCAL app.current_tenant_id изолирует SELECT в deals — оба тенанта видят только свои 2 deals из 4 общих. - кейс 1 расширенный: RLS работает на projects (не только deals) — тот же tenant-контекст применяется ко всем 36 политикам. - кейс 4: WITH CHECK блокирует INSERT в projects с чужим tenant_id — ожидается QueryException (RLS WITH CHECK violation). Стек теста: - testing-роль `testing_rls_user` NOLOGIN (создаётся идемпотентно через DO $$ ... IF NOT EXISTS $$). На dev superuser обходит RLS — поэтому через SET LOCAL ROLE переключаемся на NOLOGIN-роль без BYPASSRLS. - DatabaseTransactions trait вместо RefreshDatabase — каждый тест в транзакции, ROLLBACK сбрасывает SET LOCAL ROLE и тестовые данные. - Отдельная БД liderra_testing (создана `CREATE DATABASE` через psql, мигрирована `DB_DATABASE=liderra_testing artisan migrate:fresh` 743 ms). - phpunit.xml: DB_CONNECTION sqlite → pgsql, DB_DATABASE liderra_testing. Pest 6/6 passed (RlsSmokeTest 4/4 + ExampleTest 2/2) за 723 ms total. Кейсы НЕ покрытые (отложены): - Кейс 2-3 (PgBouncer transaction-pooling reuse, job retry): production- только, на native Windows-стеке нет PgBouncer - Кейс 5 (REVOKE на 6 saas-таблицах для crm_app_user): требует ролей из db/02_grants.sql, на dev не созданы (только postgres-superuser) Сопутствующие правки: - .gitleaks.toml: + allowlist path для app/tests/*.php (фиктивные телефоны вида +79000010001 в фикстурах — не реальные ПДн) - app/phpstan-baseline.neon: regenerated — Pest dynamic $this properties ($this->tenant1Id и т.п.) не парсятся PHPStan без pest-extension, занесены в baseline (12 entries) до миграции на typed-properties - CLAUDE.md §6: Pest 2/2 → 6/6, добавлено упоминание CTO-13 smoke-test - memory project_state.md, MEMORY.md: smoke-test реализован Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
4eee06fb22 |
phase1(hooks): lefthook auto-install + Pint + Larastan pre-commit hooks
Закрывает Tooling §10.1 шаги 10/11 («хуки в .claude/settings.json для Pint/Larastan» — реализация через lefthook, как и было обещано в CLAUDE.md §3.5: «Pre-commit (gitleaks, link-check) — не здесь, отдельно через git hooks (lefthook)»). Добавлено в lefthook.yml: - pre-commit job #5 «pint»: glob app/**/*.php, root app/, `php vendor/bin/pint {staged_files}` + stage_fixed: true (авто-fix форматирования PSR-12 на staged PHP) - pre-commit job #6 «larastan»: glob app/**/*.php, root app/, `php vendor/bin/phpstan analyse --no-progress --memory-limit=512M` (полный анализ при любой правке *.php — phpstan нужен граф классов, точечный анализ только staged невозможен) Хуки установлены через `npx lefthook install` — .git/hooks/pre-commit и .git/hooks/pre-push сгенерированы. Smoke-test: - pint --test (на default scaffold) → passed - phpstan analyse --no-progress → 0 ошибок выше baseline (3 в baseline) Это опционально-блокирующий слой: при коммите .php — Pint авто-форматирует, Larastan ловит ошибки выше phpstan-baseline.neon. Обход — `LEFTHOOK=0 git commit` (использовать только для emergency). 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 ( |
||
|
|
0eb2f72da2 |
phase1(security): roave/security-advisories — CVE-блокировка на install (Прил. Н #13)
Метапакет roave/security-advisories:dev-latest добавлен в require-dev. Это conflict-only пакет — он не содержит кода, а просто помечает известные CVE-версии других пакетов как несовместимые. При попытке установки/обновления таких версий composer падает с conflict-resolution до того, как уязвимый код попадёт в vendor/. Текущий снапшот зависимостей чист: «No security vulnerability advisories found» при установке (95 пакетов). Закрывает Прил. Н #13. Не требует конфигурации, бинарников, env. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e04f53b103 |
phase1(boost): laravel/boost v2.4.6 + Vuetify guideline (Прил. Н #10)
Установка Laravel Boost вручную (без `php artisan boost:install`):
wizard падает в обоих режимах из-за двух багов окружения:
- интерактив: PHP fatal на кириллице-пути при рендере laravel/prompts
multiselect (нет UTF-8 codepage в Windows PowerShell)
- --no-interaction: ConfiguresPrompts::multiselectFallback возвращает
null → array_map() crash в L13 framework
Manual setup вместо wizard'а:
- app/composer.json: laravel/boost ^2.4 + транзитивы (laravel/mcp v0.7,
laravel/roster v0.5.1, symfony/yaml v7.4)
- app/boost.json: agents=[claude_code], guidelines=true, mcp=true
- .mcp.json (корень): добавлен блок laravel-boost — command=php,
args=[app/artisan, boost:mcp]. Заменяет PostgreSQL MCP из фазы 0
(был убран в _comment_postgres ещё ранее).
- app/.ai/guidelines/vuetify.md: кастомный Vuetify 3 guideline по
Tooling §10.2 + Forest-палитра + 14 slug'ов воронки берутся из
schema.sql:2076 (НЕ из BRANDBOOK_v2 §3.6).
Smoke-test (boost:mcp via JSON-RPC):
- protocolVersion 2024-11-05, serverInfo "Laravel Boost"
- 9 tools: application-info, browser-logs, database-(connections|query|
schema), get-absolute-url, last-error, read-log-entries, search-docs
Уточнение к CLAUDE.md §7: «отключать guidelines Inertia/Livewire/Tailwind/
Filament/Sail/PHPUnit» — избыточно. Boost через laravel/roster детектит
установленные пакеты из composer.lock; то, что не установлено, не серверит.
Pest 4 будет detected, PHPUnit guideline не активируется (PHPUnit убран
из direct deps в коммите
|
||
|
|
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> |
||
|
|
03456833eb |
phase1(tooling): Pint + Larastan + IDE Helper (Прил. Н #11/#12/#14)
Установлены 3 dev-инструмента из Прил. Н фазы 1: - laravel/pint v1.29 (форматтер PHP, Прил. Н #11) — Laravel preset по умолчанию. Команды: composer pint, composer pint:test - larastan/larastan v3.9.6 + phpstan/phpstan v2.1.54 (статанализ PHP, Прил. Н #12) — level 5, paths app/bootstrap/config/database/ routes/tests. Команда: composer stan - barryvdh/laravel-ide-helper v3.7.0 (IDE-stubs, Прил. Н #14) — команда: composer ide-helper. Артефакт _ide_helper.php в gitignore Конфиги: - app/phpstan.neon — base config с includes на larastan extension и baseline. Включены checkOctaneCompatibility и checkModelProperties - app/phpstan-baseline.neon — зафиксированы 3 ошибки в default Laravel scaffold (UserFactory return type covariance + 2× ExampleTest always-true). Двигаемся вверх с этого baseline'а. Composer scripts (composer.json): - pint, pint:test (форматирование / dry-run проверка) - stan (PHPStan analyse с memory-limit 512M) - ide-helper (generate + meta) Smoke-test'ы все 3 прошли: Pint passed, PHPStan passed (с baseline), ide-helper:generate написал _ide_helper.php. Фикс окружения: на этой машине composer require падал с "Permission denied на vendor/composer/tmp-XXX.zip" из-за race condition параллельных curl'ов. Решение: COMPOSER_MAX_PARALLEL_HTTP=1 (сохранено в memory feedback_environment). 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> |
||
|
|
4d38f75826 |
phase1(scaffold): Laravel 11 + predis + .env под PG 16 + Memurai
Триггер фазы 1 запущен 08.05.2026 (вечер): composer create-project laravel/laravel app Стек подтверждён native (без Docker/WSL2/Sail): - PostgreSQL 16.13 (Chocolatey, Windows-сервис, port 5432) - Memurai Developer 4.1.8 (Redis 7-совм., port 6379) — TCP +PONG OK - PHP 8.3.31 + 11/11 Laravel-required ext (pdo_pgsql, mbstring, openssl, tokenizer, xml, ctype, json, bcmath, fileinfo, curl, pgsql) - Composer 2.9.7 Что в коммите (59 файлов, 11059 строк скаффолда Laravel 11 + правки): - composer require predis/predis (v3.4.2) — PHP-only Redis-клиент, т.к. php_redis ext не установлен (см. project_phase1_strategy.md) - app/.env (gitignored) — APP_NAME=Liderra, APP_LOCALE=ru, APP_TIMEZONE=Europe/Moscow, DB_CONNECTION=pgsql → liderra@localhost, REDIS_CLIENT=predis - app/.env.example — те же правки без секретов (для команды) Smoke-test PG ↔ Laravel ↔ pdo_pgsql прошёл: 3/3 default-миграций → 9 таблиц в liderra (cache, cache_locks, failed_jobs, job_batches, jobs, migrations, password_reset_tokens, sessions, users). Артефакт стартера app/database/database.sqlite (0 B) удалён — sqlite не используется. Что НЕ в этом коммите (следующие шаги фазы 1): - Pest 3 swap (CTO-12) — composer remove phpunit + require pest - Laravel Boost MCP + 9 guidelines disable по CLAUDE.md §5/§7 - Pint, Larastan, Roave/SecurityAdvisories, IDE Helper, squawk, pgFormatter (Прил. Н #11–18) - resources/boost/guidelines/vuetify.blade.php 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> |
||
|
|
b0be139845 |
chore(gitignore): подготовка к фазе 1 — Laravel в app/ + игнор лендинг/
Подготовка перед composer create-project laravel/laravel app
(стратегия B — Sail на Windows FS, monorepo).
Расширены Laravel-пути:
- /app/vendor/, /app/node_modules/, /app/public/build/
- /app/storage/{app/public,framework,logs}/, /app/bootstrap/cache/*
- /app/.env*, /app/auth.json, /app/.phpunit.cache/, /app/.pest.cache/
- /app/.idea/, /app/.vscode/, /app/Homestead.{json,yaml}
- !/app/storage/logs/.gitkeep, !/app/bootstrap/cache/.gitkeep
(Laravel требует пустые папки)
Также игнорируем лендинг/ — локальный дизайнерский трек
(TZ_landing_v1_0.md + README + ZIP-handoff ~9.5 МБ для дизайнера),
не должен случайно попасть в основной репо.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
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> |
||
|
|
3dca049f9c |
chore(cspell): +opsz/+tnum/+rgba — термины из CLAUDE.md v1.1 §2/§3
Автодобавлены pre-push lefthook'ом после коммита
|
||
|
|
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-коммита
|
||
|
|
038a884daf |
schema(v8.5): реализация 27 решений аудита C — DDL + CHANGELOG + метрики
Закрывает все 27 решений из Открытые_вопросы v1.12 §13.10 на уровне schema.sql. Narrative-обновление (§10/§12.5.5/§14/§17/§19.10/§22/§23.10/ Прил.И) — отдельным коммитом. Метрики v8.4 → v8.5: - 53 → 54 таблицы (+1: project_user_assignments) - 86 → 91 индекс (+5) - 34 → 35 RLS-политик (+1) + WITH CHECK на 2 существующих - 34 → 35 ENABLE RLS (+1) - 3 → 4 роли (+crm_audit_writer) - 0 → 12 триггеров (5×2 audit append-only + 1 report_jobs export + 1 deals lead_score) - 0 → 4 функции (audit_chain_hash, audit_block_mutation, report_jobs_log_export, calc_lead_score) - +26 колонок: suppliers.quality_score; saas_admin_users (sso_provider, is_break_glass); impersonation_tokens (second_approver_id, second_approval_at); tenants (api_key_limit, telegram_bot_token); projects (assignment_strategy, ttfr_target_minutes); users (telegram_user_id); deals (assigned_at, escalated_count, duplicate_of_id, utm_source/medium/campaign/content, region_code, city, time_in_form_seconds, lead_score); +log_hash на 5 audit-таблицах - ALTER api_keys.expires_at SET NOT NULL DEFAULT NOW()+365d - REVOKE ALL на 6 saas-таблицах от crm_app_user P0 (8) разблокировали триггер фазы 1 (composer create-project): - Биз-17 (manual routing), Биз-18 (TTFR 15м), Биз-19 (24ч-дедуп без списания) - CTO-13 (e2e SET LOCAL+PgBouncer тест в спринте 1; план в narrative) - OPEN-И-13 (OIDC+JIT+break-glass), OPEN-И-14 (WITH CHECK + REVOKE) - OPEN-И-15 (append-only audit + hash chain + crm_audit_writer) - OPEN-И-16 (Sentry whitelist+regex; конфигурация в Laravel, не DDL) Self-review: 0 orphan-FK, 0 дубликатов CREATE TABLE, метрики совпадают с grep'ами; markdownlint+cspell чистые. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
185e663415 |
chore(migration): exclude orphan session/tmp dirs from old machine
After move from c:\Users\KDV\Projects\lidpotok (Win10) to c:\моя\проекты\портал crm\Документация (Server 2022, 07.05.2026): - c--Users-*/ — JSONL-сессии Claude со старой машины (~24 МБ) - .tmp/ — рабочая папка Playwright MCP Гипотеза «репо удалён» при первом 404 от fine-grained PAT была ошибкой: PAT просто не имел Repository access. После восстановления через Git DB API все 24 коммита истории на месте. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
f1ea6a15a6 |
fix(config): B-1 — конфигурационные находки аудита B (P0+P1)
- cspell-words.txt: удалено сломанное `ofеrtу` (кириллица в латыни, пропущено мимо словаря; нормальные `оферта`/`оферты` уже есть). - .gitignore: `.playwright-mcp/` → `**/.playwright-mcp/` (артефакт может появиться в любом подкаталоге, не только в корне). - pa11y.config.json: добавлен `web/03-deals.html` (готовый прототип №03, ранее не попадал в a11y-check). - lefthook.yml: pre-push +lychee-links — битые ссылки ловятся до push, как и было задумано (Прил. Н §1, в комментарии было, в jobs не было). - CLAUDE.md §4: `gitleaks detect` / `gitleaks protect` → `./bin/gitleaks.exe ...` (на Windows бинарь в `bin/`, не в PATH). - README.md: подпись `Прил. Л v0.1 от 05.05.2026` → `v0.4 от 06.05.2026`, синхронизация с таблицей версий (последняя запись v0.4). Линтеры (markdownlint, cspell на затронутых .md) — чисто. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
7619ac0345 |
fix(schema+package): D-блок P0 — forward FK + битые partial-индексы + npm links
- schema.sql: forward FK saas_admin_sessions.impersonating_tenant_id и impersonation_tokens.tenant_id → tenants(id) вынесены в ALTER TABLE после CREATE TABLE tenants (миграция с нуля больше не падает на forward-reference). - schema.sql: partial-индексы idx_saas_admin_sessions_expires и idx_sessions_expires переведены на полное поле expires_at — PostgreSQL не разрешает NOW() в предикате частичного индекса (STABLE, не IMMUTABLE). - package.json:10 (links): lychee → bin\lychee.exe — Windows-cmd корректно резолвит относительный путь только через backslash. - CHANGELOG_schema.md: запись Z.5 (hotfix v8.4) с метриками 53/86/33/34. Метрики schema.sql v8.4 не меняются. Self-review §8 CLAUDE.md пройден. 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> |
||
|
|
a05b09a025 |
schema(v8.4)+docs(narrative): §7 + outbound_webhook_* DDL
schema.sql v8.3 → v8.4 (закрывает тех-долг §19.10): - +outbound_webhook_subscriptions (15 полей: target_url, secret_hash, secret_prefix, events JSONB, custom_headers, is_active, paused_at, consecutive_failures, …) + 2 индекса - +outbound_webhook_deliveries (16 полей с retry-флоу: attempt_number 1-7, status pending/success/failed/permanently_failed, scheduled_at, next_retry_at, response_body, …) + 3 индекса - +RLS-политики tenant_isolation для обеих таблиц - Шапка обновлена: 51→53 таблицы, 81→86 индексов, 31→33 RLS, 32→34 ENABLE RLS db/CHANGELOG_schema.md: новая запись §Z (v8.3 → v8.4) с обоснованием, сводной таблицей, описанием новых таблиц/индексов, разъяснением что crm_connections/crm_field_mappings отложены до спринта 14-15 (amoCRM). narrative §7: синхронизация с фактическим schema.sql v8.4. - §7.1: метрики обновлены (53/12/86/33/34), карта таблиц расширена до полного списка (включая ранее отсутствовавшие tenant_custom_domains, user_recovery_codes, user_sessions, project_suppliers, project_limit_adjustments, incidents_log, report_jobs, document_sequences, outbound_webhook_*) - §7.3: DDL deals — удалены reminder_text/reminder_at/idx_deals_reminder (синхронизация с v8.3, партия 12.2.5). Добавлены DDL reminders v8.3, outbound_webhook_subscriptions, outbound_webhook_deliveries Шапка narrative: блок «Что нового в v8.4» обновлён (+§7). План v8.4: 8/13 ✅ (было 7/13). cspell-words.txt: +воркер, +деплой формы. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1909dcea21 |
chore(claude): синхронизация settings.json и CLAUDE.md §3.5
- settings.json: канонический $schema (json.schemastore.org), удалены _comments (схема их отвергает) и поле comment в hook - CLAUDE.md: добавлен §3.5 «Заметки к settings.json» — комментарии переехали из JSON в CLAUDE.md как единый источник истины Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
28083f07c8 |
chore(gitignore): exclude .claude/settings.local.json
Per-machine Claude permissions — не должны попадать в общий репозиторий. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
63b45217dc |
docs(narrative): v8.4 +§22 (CSP + prompt injection + антипаттерны)
§22.2 Транспортный уровень: CSP-строка расширена до полной политики (script-src без 'unsafe-inline', object-src 'none', frame-ancestors 'none', report-uri /csp-report). §22.11 «Защита от prompt injection в DOM» (новый, 4 уровня): - 22.11.1 — полная CSP-политика с 13 директивами - 22.11.2 — CI-линтер запрещает в DOM элементы с ID/class на префиксы claude-/gpt-/agent-/ai- - 22.11.3 — DOMPurify-конфиг для всех v-html - 22.11.4 — методология аудита third-party скриптов (31 keyword grep + SRI-хеши + ежеквартальный re-audit) - 22.11.5 — что НЕ делаем (не блокируем легитимных AI-агентов) Контекст — атака `claude-agent-stop-container/glow-border/animation-styles`, найденная во ВСЕХ страницах crm.bp-gr.ru (партии 10, 12-15 аудита). §22.12 «Антипаттерны оригинала» (новый): - 22.12.1 — защита формы смены пароля (vs пароль в `<input type="text">` оригинала, партия 14.3.4) - 22.12.2 — защита форм интеграций (vs API credentials в `<input type="text">` всех 5 карточек оригинала, партия 15.2.3) - 22.12.3 — code review checklist (7 пунктов) Шапка narrative обновлена. План v8.4: 7/13 ✅ (было 6/13). cspell-words.txt: +санитизация, +санитизируются. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
6648fdd52f |
docs(narrative): v8.4 +3 разделов (§14, §18.4, §19.10)
§14 Activity Log: 17 событий (+6 новых: project_changed, phone_changed, phones_changed, contact_name_changed, reminder_completed, restored). §14.7 vs оригинал — таблица «что не логирует crm.bp-gr.ru» (партия 11.4). §18.4 Безопасность: §18.4.1 Биз-9 (2FA на всех тарифах), §18.4.3 retention auth_log, §18.4.4 уведомления о подозрительной активности (6 типов алертов), §18.4.5 vs оригинал — 7 функций безопасности (партии 14.3.2–14.3.4). §19.10 Outbound webhook: статус MVP по OPEN-И-2 (был «v2, не реализуется»). 10 подсекций: 7 линий доказательств уникальности (партии 9–15), формат запроса, HMAC SHA-256, retry до 24ч, защита от SSRF, rate-limit. Шапка narrative: блок «Что нового в v8.4» обновлён. План: 6/13 ✅ (было 3/13). Тех-долг — DDL outbound_webhook_subscriptions + outbound_webhook_deliveries при правке §7 v8.4. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
938066fefe |
docs(narrative)+web: narrative v8.4 partial (§1, §17, §26) + HTML-прототип 03 «Список сделок»
Narrative переработан под решения 04–06.05 + аудит партий 1–15: - §1.4.1 — 7 конкурентных преимуществ vs оригинал crm.bp-gr.ru - §1.5 — 3 формата ingress (webhook/manual/CSV), 3 чекбокса click-wrap - §17.8 — Тихие часы (start_hour/end_hour 0..23, минимум 3 часа, общий timezone тенанта), паритет с партией 13.2.1 - §26 — полная замена под брендбук v1.1: палитра Teal (#0F6E56), сетка 4px, JetBrains Mono, маскирование credentials как антипаттерн оригинала. Шапка narrative — блок «Что нового в v8.4» с маппингом 11 закрытых вопросов из реестра v1.10. Остальные 9 разделов плана — в Plan_narrative_v8_4.md (отдельные сессии). web/03-deals.html — прототип «/deals»: - Sidebar + topbar + balance widget (как 02-dashboard) - Sticky-фильтры: поиск FTS, проект, статус, менеджер, период, теги, «только с напоминанием», кнопки Колонки/Экспорт/Создать - Bulk-actions bar при выборе строк - Таблица 20 демо-строк с 14 цветными статусами (включая 🔥 Горячий) - Pagination, low-balance баннер, чекбоксы, sort-индикаторы - Телефоны маскированы по правилу gitleaks `ru-phone-unmasked` и брендбуку §9 (формат +7 (XXX) ***-XX-XX) - web/index.html: 03 → готов, счётчик 3/8 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
4df66c3776 |
docs(archive): close 11 P1/P2 defaults → registry v1.10, add Plan_narrative_v8_4
Закрытие 11 вопросов с дефолтами (утверждено 06.05.2026): - Биз-6 — режим «по запросу» (15 партий аудита уже сделано) - Биз-10..13 — модель reminders, один кошелёк ₽, телефония Post-MVP, magic-link 24ч - Биз-14..16 — TTL 180д, OSINT не делаем, desired_daily_numbers - OPEN-К-1, К-7 — Cloud Boost grant и CVoS отложены - OPEN-И-12 — контакты эскалации в Notion private до DO-4 Сводка после v1.10: 50 продуктовых = 40 ✅ + 5 🟦 + 5 ⏸ (Б-1 P0; Диз-1/3, DO-2/4 — все P1 ждут Б-1 или у Claude). Все P2 закрыты. Plan_narrative_v8_4.md — компактный план переписывания 13 разделов ТЗ под решения 04–06.05 + аудит партий 1–15. Сам narrative не трогали. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
13c6f29f29 |
chore(gitignore): exclude Playwright MCP artifacts
После первого демо Playwright MCP в корне создался скриншот demo-01-login-fullpage.png и временная директория .playwright-mcp/. Добавил соответствующие паттерны в .gitignore, чтобы будущие screenshot'ы и DOM-snapshot'ы не попадали в коммиты. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |