Read this when changing MySQL connections, mappers, transactions, or persistence invariants. # MySQL Persistence ## Implementing Files | File | Key symbols | |---|---| | `src/Core/System/System.php` | F3 `DB\SQL` connection and PDO options | | `src/Core/System/User.php` | `users` mapper, role serialization, password hash generation | | `src/Core/System/Notifications.php` | `notifications` mapper and table-wide clear operation | | `src/Core/Api/UserController.php` | Account CRUD, row locks, transactions, duplicate detection | | `phengine.sql` | Schema, unique index, and sample data | ## Flow 1. F3 globals provide DSN and database credentials to `System`. 2. `System` creates the `DB\SQL` connection with PDO exceptions and stores it as F3 `DB`. 3. Mappers obtain the global connection and issue F3 mapper operations. 4. User updates/deletes begin a transaction, lock user rows, enforce account invariants, then commit or roll back. ## Trust Boundaries | Boundary | Mechanism | Location | |---|---|---| | Connection secrets | Values originate in runtime configuration, not request input | `cfg/config.bin` loaded by `index.php` | | Request values in queries | Mapper predicates use placeholders for username/ID lookups | `User`, `AuthController`, `UserController` | | Duplicate identities | Application precheck plus `uq_users_username` database constraint | `UserController`, `phengine.sql` | | Final administrator race | Transaction and `SELECT id FROM users FOR UPDATE` serialize checks and mutations | `UserController` | | Role deserialization | `unserialize(..., ['allowed_classes' => false])` prevents object instantiation | `User::__construct()` | | Table-wide notification deletion | Only authenticated, CSRF-protected notification API path reaches `emptyAll()` | `NotificationController::delete()` | ## Config - Driver: MySQL DSN from F3 `DSN` global. - PDO: `ERRMODE_EXCEPTION` is set; persistence is enabled on Linux or CLI. - F3 query logging: disabled with `$db->log(false)` to avoid known framework memory leakage. See [database conventions](../conventions-database.md) and [identity spec](../identity/spec.md).