diff --git a/CLAUDE.md b/CLAUDE.md index d6039d28..0ef36927 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -81,6 +81,29 @@ Configure two frontend origins in both Laravel (`config/cors.php` via env) and t ### Database +Crewli uses **MySQL 8.0 exclusively** across all environments: + +- **Local development**: MySQL 8.0 via `docker-compose.yml` (`bm_mysql` container, port 3306). Run `make services` to start. +- **Testing**: MySQL 8.0 via the same Docker container, separate `crewli_test` database. Run `make test-db-create` once, then `make test`. +- **Staging/production**: MySQL 8.0 on the deployment VPS. + +**SQLite is forbidden** in all environments. Reasons: + +- SQLite has known quirks around foreign-key constraints (rebuild-on-FK-add cascades), JSON queries (key-order non-determinism on round-trip differs from MySQL), and concurrent writes that mask bugs which MySQL would surface in production +- Cross-database query syntax differences cause silent test/production drift (e.g. `sqlite_master` vs. `information_schema`, VARCHAR length enforcement) +- Crewli's enterprise-grade product philosophy doesn't tolerate "but it works on SQLite" as a passing test + +If a contributor finds SQLite references in `phpunit.xml`, `.env.testing`, or any config file, treat it as a regression and fix immediately. + +When writing migrations or queries: + +- Use Laravel's query builder where possible — it handles cross-DB syntax consistently +- For raw SQL, write MySQL syntax (no need for SQLite fallbacks). Index introspection: query `information_schema.STATISTICS`, never `sqlite_master`. +- Foreign keys go on every relation column. The `nullOnDelete` / `cascadeOnDelete` choice is per the relationship's domain semantics; "no FK" is not an option. +- Tests that round-trip JSON data via MySQL JSON columns must use `assertEquals` (structural equality) rather than `assertSame` on associative arrays — MySQL JSON may reorder object keys. + +Other database rules: + - Primary keys: ULID via `HasUlids` (not UUID v4, not auto-increment on business tables) - Create migrations in dependency order: foundation first, then dependent tables - Always add composite indexes as documented in the design document (section 3.5)