# Локальное окружение

Разработка идёт на Windows с Laragon. Глобальная версия PHP в Laragon не меняется, поэтому другие проекты
не затрагиваются: инструменты проекта подключаются в конкретную сессию терминала.

| Компонент | Версия | Где лежит |
|---|---|---|
| PHP | 8.5 (TS, x64) | `D:\laragon\bin\php\php-8.5.11-Win32-vs17-x64` |
| PostgreSQL | 17 (ICU `ru-RU`, UTF-8) | `D:\laragon\bin\postgresql\postgresql-17.11`, данные — `D:\laragon\data\postgresql` |
| Composer | 2.9 | `D:\laragon\bin\composer` |
| Node.js | 22 | `D:\laragon\bin\nodejs\node-v22` |

Пути можно переопределить переменными `LARAGON_ROOT`, `LOYAL_PHP_DIR`, `LOYAL_NODE_DIR`, `LOYAL_PG_DIR`,
`LOYAL_PG_DATA`.

## Первый запуск

По умолчанию Windows запрещает запуск PowerShell-скриптов. Один раз разрешите локальные скрипты для своего
пользователя (или запускайте их через `powershell -ExecutionPolicy Bypass -File ...`):

```powershell
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
```

Затем в корне проекта:

```powershell
. .\scripts\dev\env.ps1                    # PHP 8.5, Composer, Node, psql — в PATH текущей сессии
composer install
copy .env.example .env
php artisan key:generate
php artisan pii:generate-keys              # ключи шифрования ПДн (ADR-0008); не теряйте их
.\scripts\dev\postgres.ps1 init            # кластер PostgreSQL; пароль суперпользователя попадёт в .env
```

Заполните в `.env` пароли ролей `DB_PASSWORD`, `DB_OWNER_PASSWORD`, `DB_SYSTEM_PASSWORD` (любые случайные
строки) и создайте роли и базы:

```powershell
php artisan db:bootstrap --database=loyal --database=loyal_test
composer migrate                           # миграции от имени владельца схемы
composer check                             # Pint, Larastan, Deptrac, тесты
```

Сотрудник для входа в кабинеты (ADR-0013): `php artisan staff:create admin@example.test --name="Администратор"`
(команда дважды спросит пароль), затем `php artisan staff:grant admin@example.test --platform --role=admin`. Консоль
платформы — `http://localhost:8000/console` (`php artisan serve`): при первом входе консоль попросит подключить
приложение-аутентификатор (Яндекс Ключ, Google Authenticator и др.) и покажет коды восстановления. Готовые
демо-записи — оператор и владелец демо-мерчанта с паролем из `database/seeders/LocalCabinetSeeder.php` — создаёт
`php artisan db:seed --class=LocalCabinetSeeder` (только в окружении `local`, повторный запуск ничего не дублирует).
Ресурсы Filament публикует `php artisan filament:assets` (выполняется после `composer install`).

Письма сотрудникам (ссылка «Забыли пароль?», письмо о сбросе 2FA) уходят через очередь: без запущенной очереди
(`composer dev` или `php artisan queue:work`) их нет. Локально `MAIL_MAILER=log` — письмо со ссылкой появляется в
`storage/logs/laravel.log`. Ссылки в письмах строятся от `APP_URL` (и `CONSOLE_DOMAIN` для консоли), поэтому
`APP_URL` должен совпадать с адресом, по которому открываются кабинеты. Вне разработки нужны асинхронная очередь
(`QUEUE_CONNECTION` не `sync`) и почтовый драйвер, который доставляет письма (`MAIL_MAILER` не `log` и не `array`):
иначе письма сотрудникам не уходят.

Пригласить оператора можно в консоли («Приглашения в консоль»): локально письмо со ссылкой появится в
`storage/logs/laravel.log`, ссылка откроется на `APP_URL`. Принятое приглашение ведёт на вход, где нужно подключить
приложение-аутентификатор.

Для `cmd.exe` вместо `env.ps1` есть `scripts\dev\env.cmd`.

## Каждый день

```powershell
. .\scripts\dev\env.ps1
.\scripts\dev\postgres.ps1 start           # stop | status | psql
composer dev                               # сервер, очередь и Vite
```

## Команды

| Команда | Что делает |
|---|---|
| `composer check` | всё, что проверяет CI: Pint, Larastan, Deptrac, Pest |
| `composer test` | тесты (Pest) на базе `loyal_test` |
| `composer lint` / `composer fix` | проверка / исправление стиля (Pint) |
| `composer analyse` | статический анализ (Larastan, уровень 8) |
| `composer deptrac` | проверка границ модулей |
| `composer migrate` | миграции от имени владельца схемы |
| `php artisan db:bootstrap` | роли, базы и права по умолчанию (только local и CI) |
| `php artisan make:module <name>` | новый модуль; затем `composer update modules/<name>` и строка в `deptrac.php` |
| `php artisan staff:create` / `staff:grant` / `staff:revoke` / `staff:disable` | учётные записи сотрудников и их роли |

## Что важно знать

- **Роли БД.** Приложение работает ролью `loyal_app`, на которую действует RLS; миграции выполняет
  `loyal_owner`; межтенантные процессы — `loyal_system` (ADR-0002). Без контекста тенанта роль приложения
  видит ноль строк в таблицах тенантов.
- **Тесты.** Feature-тесты идут через роль приложения внутри транзакции, которая откатывается после теста.
  Соединение `pgsql_system` — отдельная сессия: данных тестовой транзакции оно не видит. Если тесту нужна
  системная роль, фикстуры коммитятся через неё и удаляются в конце (пример —
  `app-modules/tenancy/tests/Feature/SystemRoleTest.php`).
- **Linux-only компоненты.** Horizon и Octane требуют `pcntl` и не работают на Windows. Локально очередь
  обрабатывает `php artisan queue:work`; Horizon и Octane проверяются в Docker и CI.
- **Cookie сеанса и хосты.** Локально приложение работает по http, поэтому в `.env` стоит
  `SESSION_SECURE_COOKIE=false`. В production нужны `SESSION_SECURE_COOKIE=true`, `SESSION_COOKIE=__Host-loyal_session`
  и `APP_DEBUG=false`, а консоли — свой хост в `CONSOLE_DOMAIN` (кабинеты остаются на хосте `APP_URL`): иначе страницы
  кабинетов отвечают ошибкой 500, а команды и API продолжают работать. За обратным прокси задайте его адреса в
  `TRUSTED_PROXIES`. Время в кабинетах показывается в поясе `CABINET_TIMEZONE` (по умолчанию `Europe/Moscow`).
- **PostgreSQL Laragon.** Laragon запускает собственный PostgreSQL (`data\postgresql-17`) на порту 5432, поэтому
  кластер проекта слушает порт из `DB_PORT` — 5433 (`postgres.ps1 init` берёт его из `.env`). Запускайте кластер
  проекта командой `.\scripts\dev\postgres.ps1 start`; экземпляр Laragon ему не мешает.
