# 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 <previous-change-id>
```

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.
