# Спека: починка CsvWebhookRaceTest + PII-scrubbing на остальные каналы

## Цель

Две дешёвые backend-правки: (C) починить устаревший setup `CsvWebhookRaceTest`
(3 падения «Deal не создан»); (A) расширить PII-scrubbing на каналы логов
`stderr`/`papertrail`/`slack` (помимо уже покрытых `single`/`daily`). Обе —
аддитивны, низкий риск.

## C — root cause и фикс {#D1}

`LeadRouter` определяет eligibility через `project_routing_snapshots` за активную
дату слепка (slepok-инвариант, Task 2.5/2.9): `FROM project_routing_snapshots snap
WHERE snap.snapshot_date = ?`. `CsvWebhookRaceTest.beforeEach` создаёт живой
`Project`, но НЕ создаёт снимок → `RouteSupplierLeadJob` не находит eligible-проект
→ `Deal` не создаётся. На проде снимок создаёт cron — продукт цел; это устаревший
setup теста относительно snapshot-маршрутизации (рабочие supplier-тесты снимок
создают). Фикс — добавить в `beforeEach` после `linkProjectToSupplier(...)`:

```php
createRoutingSnapshotFromProject($this->project, null, 'site', 'race-csv.ru', 100);
```

(зеркалит проект: signal_type=site, signal_identifier=race-csv.ru, daily_limit=100,
дата null=сегодня). Меняется только тест-setup.

## A — PII-scrubbing на остальные каналы {#D2}

Процессор `App\Logging\PiiScrubbingProcessor` уже есть и протестирован; каналы
`single`/`daily` покрыты через tap. Расширить:

- `slack` (driver `slack`) → добавить `'tap' => [\App\Logging\ScrubPii::class]`.
- `papertrail` и `stderr` (driver `monolog`, имеют `'processors' => [PsrLogMessageProcessor::class]`)
  → добавить `\App\Logging\PiiScrubbingProcessor::class` в их `processors` массив.

`null`/`emergency`/`stack`/`syslog`/`errorlog` не трогаем (stack делегирует в single;
null discard; syslog/errorlog — системный лог, отдельный контур).

## Граничные случаи {#D3}

- C: один снимок в beforeEach покрывает все тесты файла (каждый прогон — свежий
  beforeEach; дата=сегодня активна на момент прогона; daily_limit=100 ≥ нужного).
- A: для `monolog`-каналов процессор добавляется В КОНЕЦ массива processors (после
  PsrLogMessageProcessor), порядок не критичен для маскирования; config остаётся
  валидным PHP (любой тест-boot это подтвердит).

## Критерий приёмки {#D4}

`php artisan test tests/Feature/Supplier/CsvWebhookRaceTest.php tests/Feature/Logging/PiiScrubbingProcessorTest.php`
— оба файла зелёные: CsvWebhookRaceTest (3 ранее падавших проходят), PII-процессор
(6/6, заодно подтверждает, что config/logging.php загружается без ошибок).

## Переговоры

### Круг 1

Открытая точка для наставника: C-fix меняет ТОЛЬКО setup теста (а не код продукта) —
корректно, т.к. root cause = устаревший setup, не дефект; A — аддитивное расширение
уже протестированного процессора на остальные каналы. Прошу наставника зафиксировать
forward-рекомендацию по обеим правкам (правка теста уместна; покрытие каналов полно).

```verified-context-json
[
  {
    "id": "ctx-link",
    "kind": "EXTRACTED",
    "ref": "app/tests/Feature/Supplier/CsvWebhookRaceTest.php",
    "anchor": "linkProjectToSupplier($this->project, $this->sp);"
  },
  {
    "id": "ctx-router",
    "kind": "EXTRACTED",
    "ref": "app/app/Services/LeadRouter.php",
    "anchor": "FROM project_routing_snapshots snap"
  }
]
```
