# De-librairisation Plan ## Why XAMXAM currently contains ~3,300 lines of custom code implementing common infrastructural concerns that well-maintained ecosystem libraries have already solved — correctly, securely, and with years of security audits and edge-case hardening behind them. By replacing these bespoke implementations with off-the-shelf packages we: - **Eliminate attack surface** — we stop maintaining our own SMTP client, HTTP client, and Markdown parser. - **Reduce maintenance burden** — each line of infrastructure code we own is a line we must understand, debug, and keep secure. Off-the-shelf libs shift that to dedicated maintenance teams. - **Gain features for free** — DKIM signing, TLS 1.3, connection pooling, async I/O, proper content security — all things we would never build ourselves. - **Make the codebase smaller and more readable** — the remaining code is *actual application logic*, not protocol plumbing. ## What we replace | # | Component | Current size | Replaced by | Why | |---|-----------|-------------|--------------|-----| | 1 | Markdown parser | ~1770 lines | `league/commonmark` 2.x | Parsedown 1.8.0 is unmaintained since 2019. It has known XSS vulnerabilities fixed in later versions that never shipped. `league/commonmark` is the de-facto standard, actively maintained, security-audited, and supports GFM extensions (tables, strikethrough, autolinks). | | 2 | SMTP client | ~680 lines | `phpmailer/phpmailer` 6.x | Raw socket SMTP with manual STARTTLS negotiation is one of the hardest things to get right in application code. PHPMailer handles TLS 1.3, DKIM, MIME encoding, character sets, connection pooling — all things our custom code does not. | | 3 | HTTP client | ~200 lines | `guzzlehttp/guzzle` 7.x | `PeerTubeService::httpRequest()` uses `file_get_contents()` with `stream_context_create()`. Manual JSON parsing, no retry logic, no connection reuse, fragile error handling. Guzzle is the PHP HTTP standard. | | 4 | Encryption | ~86 lines | `defuse/php-encryption` 2.x | Our AES-256-GCM implementation is actually correct, but home-rolled crypto is never recommended. `defuse/php-encryption` is the recommended library by the PHP security community. **Requires migration of existing encrypted data.** | ## What we keep (and why) | Component | Why keep | |-----------|----------| | `password_hash()` / `password_verify()` | Already the correct approach — PHP's built-in bcrypt. No library needed. | | CSRF (`App.php`) | Implementation is correct: 256-bit random token, `hash_equals()` verification, rotated after mutations. A Symfony CSRF component would be an upgrade but not urgent. | | Rate limiter (`RateLimit.php`) | Adequate for current scale. A concurrent-safe Symfony rate-limiter would be better but the file race condition is low-risk at our traffic levels. | | PHP templates | Plain PHP `include` with `extract()` is fast, simple, and well-understood. Auto-escaping (Twig) would be a security upgrade but the migration cost is high and content is mostly admin-controlled. | | Logging | `error_log()` with JSON-lines is sufficient. Monolog would be cleaner but adds no security benefit. | ## Composer setup The project currently has no `composer.json`. PHP CS Fixer and PHPStan were installed manually into `vendor/bin/`. We will: 1. Create `composer.json` with the four packages above. 2. Run `composer install` to populate `vendor/`. 3. Keep existing PHP CS Fixer and PHPStan configs — they already work. ## Migration order (by risk) ### Phase 1: Markdown parser (low risk, high payoff) - **Surface**: 4 files import Parsedown - **API similarity**: `$pd->text($input)` → `$converter->convert($input)` - **SafeMode equivalent**: `league/commonmark` is safe by default (no raw HTML in safe mode) - **No data migration needed**: input is Markdown strings, output is HTML — both are ephemeral and regenerated on each page load - **Files to change**: - `app/src/Controllers/AboutController.php` - `app/src/Controllers/LicenceController.php` - `app/templates/partials/form/form-help-block.php` - `app/public/admin/form-help-inline-fragment.php` ### Phase 2: HTTP client (low risk, PeerTube-specific) - **Surface**: `app/src/PeerTubeService.php` only - **No data migration needed**: purely a transport layer replacement - **Can be done independently of Phase 1** ### Phase 3: SMTP client (medium risk, needs testing) - **Surface**: `app/src/SmtpRelay.php` - **API change**: `SmtpRelay::send($db, $to, $subject, $htmlBody)` signature stays, but internals replaced with PHPMailer - **No data migration needed**: SMTP settings in DB are read identically - **Must test**: actual email sending to a real SMTP server before deploying ### Phase 4: Encryption (highest risk, requires migration) - **Surface**: `app/src/Crypto.php`, `app/src/ShareLink.php`, `app/src/AdminAuth.php` - **Affects**: encrypted passwords in `share_links.encrypted_password`, SMTP password in `site_settings` - **Migration required**: decrypt all values with old Crypto, re-encrypt with defuse/php-encryption, write migration script - **Do last**, and only if the risk/reward is worth it (our current implementation is actually correct) ## Target state After all phases, the codebase loses ~2,700 lines of infrastructure code and gains four well-maintained dependencies with known security postures and upgrade paths.