# Decision log

Short, dated architectural decisions. Newest first.

## 2026-08-26 — Laravel 12 + PHP 8.4 instead of Laravel 10 + PHP 8.1

**Context.** The prompt package fixed Laravel 10 / PHP 8.1 to match "the current
hosting". Two facts changed that premise during setup:

1. The target cPanel hosting actually runs **PHP 8.4** (and MySQL 8.4), and lets
   you select the PHP version per domain.
2. Modern Composer **refuses to install any Laravel 10.x release** because the
   whole 10.x line is flagged by unpatched security advisories (Laravel 10 left
   security support in Feb 2025). Installing it would require disabling
   Composer's security policy and shipping known-vulnerable code — unacceptable
   for a system handling passports, payments and personal data.

**Decision.** Build on **Laravel 12** (PHP 8.2–8.4), a fully supported,
advisory-free stack. Every architectural decision from the prompt is preserved:
modular monolith, central + per-tenant databases, domain-based tenant
resolution, DECIMAL money, UTC storage, private tenant files, `/api/v1` +
Sanctum, `database` queue via cron.

**Consequences.** Local build/test toolchain uses portable **PHP 8.3** (Laravel
12 requires 8.2+; the machine's VC++ runtime supports 8.3 without an admin
install). Production runs PHP 8.4. Code targets 8.2+ so it runs on both.

## 2026-08-26 — Local build & test, server is deploy-only

**Context.** The production host is cPanel shared hosting with **no SSH/terminal**
and only an ancient Node (10.x). It cannot run `composer install`, `artisan
migrate`, `npm run build` or the test suite.

**Decision.** The developer machine is the **build & test** environment
(portable PHP 8.3 + Node 24 + Composer, see `docs/installation/local-development.md`).
The server is a **deploy target**: it receives the code, a locally-built
`vendor/`, compiled `public/build/` assets, and runs migrations via the central
catalog once uploaded (see `docs/installation/shared-hosting-cpanel.md`).

## 2026-08-26 — Custom tenancy layer (no heavy package)

**Decision.** Implement a focused tenancy layer (`app/Modules/Tenancy`) rather
than adopt a large third-party package, because the prompt's catalog schema
(encrypted per-tenant credentials, domain states, plans/features/subscriptions,
schema-version tracking) is specific and benefits from being explicit and
dependency-light on a locked-down host.

## 2026-08-26 — SQLite for tests, portable migrations

**Decision.** The test suite uses in-memory SQLite for the central catalog and
per-test SQLite **files** for tenants, which makes tenant-isolation tests fast
and hermetic. Migrations avoid MySQL-only SQL so they run identically on SQLite
(tests) and MySQL 8 (production).

## 2026-08-26 — Tenant-scoped Sanctum tokens

**Decision.** `personal_access_tokens` lives in each **tenant** database, and
Sanctum is pointed at a tenant-connection token model
(`App\Modules\Identity\Models\PersonalAccessToken`). Tokens are thus isolated
per tenant, like all other tenant data.
