docs: document settings framework and telecart-pulse feature

Каркас системы настроек (docs/features/settings) и фича TeleCart Pulse
с heartbeat (docs/features/telecart-pulse); спека синхронизирована с opt-in.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 15:08:05 +03:00
parent d126dc3ef0
commit adcca7cbc4
4 changed files with 192 additions and 19 deletions

View File

@@ -16,9 +16,11 @@
- **Прозрачность:** в админ-панели покупатель видит, что именно собирается, куда
отправляется и зачем.
- **Контроль:** отдельный переключатель, которым покупатель может выключить heartbeat.
- **По умолчанию включено** (текущее поведение сохраняется, но становится видимым и
управляемым).
- **Контроль:** отдельный переключатель, которым покупатель управляет heartbeat.
- **По умолчанию выключено (opt-in).** Без явного включения покупателем на сервер ничего не
уходит — в том числе у существующих установок. (Изначально планировался opt-out с дефолтом
«включено»; решение пересмотрено в пользу opt-in из-за юридических рисков сбора
идентифицирующих данных — домена и имени бота — без согласия.)
## Границы (scope)
@@ -62,12 +64,12 @@
### 1. Backend
**`module/.../configs/app.php`** — секция `pulse` (строки 8690): добавить флаг с дефолтом
`true`.
`false` (opt-in).
```php
'pulse' => [
'api_key' => '',
'heartbeat_enabled' => true, // новый флаг
'heartbeat_enabled' => false, // новый флаг, opt-in
'batch_size' => 50,
'max_attempts' => 3,
],
@@ -106,25 +108,29 @@ public function handleHeartbeat(): void
- перечислить, что отправляется: домен, имя бота, версия PHP, версия модуля, версии
OpenCart;
- указать адрес назначения: `pulse.telecart.pro`;
- получателя назвать обобщённо — «разработчику» (без адреса сервера и периодичности: они не
важны покупателю);
- явно указать, что персональные данные покупателей и заказы **не** передаются;
- описать цель мягко: для улучшения продукта и техподдержки (без акцента на проверке
лицензии).
лицензии);
- отметить, что по умолчанию отправка отключена и её можно включить/отключить в любой момент.
Точную формулировку владелец отредактирует; черновик в нейтральном тоне готовит реализация.
Итоговая формулировка согласована с владельцем (нейтральный тон, вариант с оговоркой про
отсутствие персональных данных).
### 3. Поведение для существующих установок
Дефолт `true` в конфиге мержится с сохранёнными настройками
Дефолт `false` в конфиге мержится с сохранёнными настройками
(`ApplicationFactory`: `Arr::mergeArraysRecursively`). У установок без сохранённого значения
heartbeat остаётся включённым — поведение не меняется, но теперь переключатель виден.
Когда покупатель выключает тумблер и сохраняет, значение пишется в `oc_setting`
heartbeat **выключен** — на сервер ничего не уходит, пока покупатель явно не включит тумблер.
Когда покупатель сохраняет настройку, значение пишется в `oc_setting`
(`module_telecart_settings`) и читается на backend.
### 4. Гейтинг — итоговая логика
heartbeat реально отправляется только если **одновременно**: `heartbeat_enabled = true`
**и** есть signer (секрет настроен). Переключатель — пользовательский контроль поверх
существующего серверного гейта; они независимы.
(покупатель включил) **и** есть signer (секрет настроен). Переключатель — пользовательский
контроль поверх существующего серверного гейта; они независимы.
## Тестирование
@@ -161,8 +167,7 @@ Unit-тест на `TeleCartPulseService::handleHeartbeat()`:
## Явно вне scope (YAGNI)
- Не делаем opt-in (по умолчанию остаётся включено).
- Не делаем отдельный consent-баннер на первой установке (достаточно видимого
переключателя с раскрытием).
- Делаем opt-in (по умолчанию выключено); отдельный consent-баннер на первой установке не
нужен — достаточно выключенного по умолчанию переключателя с раскрытием.
- Не трогаем события кампаний и рассылки Pulse.
- Не выносим heartbeat в отдельный namespace/фичу из `TeleCartPulse`.