# Phase 1 Data Model

| Table | Purpose | Important controls |
|---|---|---|
| `users` | Authorised office identities | ULID primary key, unique normalised email, active flag, encrypted Fortify TOTP fields, login timestamps |
| `roles` | Six stable business roles | Unique slug; system-role marker |
| `permissions` | Granular server-side abilities | Unique slug and functional group |
| `role_user` | Staff role assignments | Assignment time and optional assigning user |
| `permission_role` | Role permission mapping | Composite uniqueness |
| `activity_logs` | Security and important office events | Append-only model, request ID, keyed IP hash, filtered changes, no update timestamp |
| `sessions` | Short-lived server-side web sessions | Encrypted payload; framework IP/user-agent metadata must follow the session-retention policy |
| `password_reset_tokens` | Time-limited recovery tokens | Laravel broker expiry and throttling |
| `cache`, `cache_locks` | Rate limiting and cache state | Database-backed for shared hosting |
| `jobs`, `job_batches`, `failed_jobs` | Future background processing | Prepared but no Phase 1 business jobs |

## Deliberately absent

There is no `messages`, `message_verifications`, `quotes`, `quote_items`, `content_versions`, `packages`, `legal_documents`, or client table in Phase 1. The public contact controller discards the request without validating, storing, logging, or emailing its content. These tables and their retention rules enter only through reviewed later migrations.

## Future migration rule

Later phases must add new migrations; never edit a migration already applied to staging or production. Every client-data table needs an explicit owner, state model, retention rule, export rule, deletion/anonymisation rule, and audited administrative actions before activation.
