# Migration History Consolidated record of structural migrations performed on posterg-website. --- ## Migration 1: YAML → SQLite (2026-01) ### What Changed Replaced flat YAML file storage with a normalized SQLite database. **Before:** Form data saved as individual YAML files in `data/yaml/`, with file uploads in `data/content/` and `data/cover/`. **After:** All thesis data stored in a relational SQLite database with 19 tables (11 core, 5 junction, 3 reference), 2 views, proper normalization (3NF), auto timestamps, cascade deletes. ### Key Changes - `Database.php` — PDO wrapper with transaction management, find-or-create methods, lookup helpers - `index.php` — Dynamically loads form options from DB; added subtitle, synopsis, finality, languages, formats - `formulaire.php` — Complete rewrite: transaction-based processing, prepared statements, random cryptographic filenames - `thanks.php` — Reads from DB using thesis ID, displays data from `v_theses_full` view ### YAML → Database Mapping | YAML Field | Database Location | |------------|-------------------| | `auteurice` | `authors.name` | | `email` | `authors.email` | | `année` | `theses.year` | | `titre` | `theses.title` | | `description` | `theses.synopsis` | | `orientation` | `theses.orientation_id` | | `ap` | `theses.ap_program_id` | | `promoteurice` | `supervisors.name` + `thesis_supervisors` | | `tag` | `keywords.keyword` + `thesis_keywords` | | `files` | `thesis_files` table | ### Data Migration Path For importing existing YAML data: 1. Parse YAML files with `Symfony\Yaml\Yaml::parseFile()` 2. Insert into DB within transactions 3. Verify with `SELECT COUNT(*) FROM theses; SELECT * FROM v_theses_full LIMIT 5;` --- ## Migration 2: Repository Restructure (2026-02) ### What Changed Restructured from `apps/public/` + `apps/admin/` + `shared/` layout to idiomatic PHP website layout. **Before:** ``` posterg-website/ ├── apps/public/ # Public website ├── apps/admin/ # Admin panel ├── shared/ # Shared PHP libraries └── database/ ``` **After (intermediate):** ``` posterg-website/ ├── index.php # Public root ├── admin/ # Admin panel ├── lib/ # Shared libraries (was shared/) ├── inc/ # Templates (header/footer) ├── assets/ # Static files ├── database/ └── vendor/ ``` ### Key Changes - Moved `apps/public/*` to root - Moved `apps/admin/` to `admin/` - Renamed `shared/` to `lib/` - Updated all `require` paths - Added php-live-reload to `vendor/` --- ## Migration 3: Public Directory Structure (2026-02) ### What Changed Moved web-accessible files into `public/` subdirectory so only `public/` is the DocumentRoot. **Before:** All files (including config, DB, source) in DocumentRoot — security relied on nginx deny rules. **After:** ``` posterg-website/ ├── public/ # DocumentRoot — only this exposed │ ├── index.php │ ├── search.php │ ├── admin/ │ └── assets/ ├── config/ # Private ├── includes/ # Private (was inc/) ├── src/ # Private (was lib/) ├── storage/ # Private (DB + uploads) └── var/ # Private (cache, logs) ``` ### Key Changes - `config/bootstrap.php` — Central path management with constants (APP_ROOT, PUBLIC_ROOT, etc.) - All public PHP files updated to use bootstrap and relative paths - Dev server: `php -S 127.0.0.1:8000 -t public/` - Deployment: rsync to `/var/www/posterg/` (not `/var/www/html/`) - Nginx DocumentRoot: `/var/www/posterg/public` ### Security Impact | Resource | Before | After | |----------|--------|-------| | Database | Accessible if nginx misconfigured | Physically outside web root | | Config | One deny rule away | Physically private | | Source code | Exposed | Physically private | | Dev server | Exposed everything | Matches production security | --- ## Migration 4: Simplification (2026-02) ### What Changed Removed package-oriented complexity from the `public/` migration. - Removed `var/` directory (completely unused for this website) - Renamed `resources/views/` → `includes/` (simpler, clearer) - Simplified `config/bootstrap.php` from 66 → 33 lines - Removed 10+ unused constants (VAR_ROOT, CACHE_ROOT, LOGS_ROOT, etc.) - Replaced `view()` helper with standard PHP `include` ### Result Only essential constants remain: `APP_ROOT`, `STORAGE_ROOT`, plus environment detection. Security unchanged (still uses `public/` as DocumentRoot). --- ## Rollback Notes All migrations are tracked in jj. To view history: ```bash jj log jj edit ``` The YAML-based code was kept as a fallback during the SQLite migration. The old `/var/www/html/` structure was kept as a backup during the directory structure migration.