Skip to main content
Mirror of LMS_Backend/clean_up.md (generated 08/10/2026; Section H added 09/10/2026). Scope: what bloats the repo, what is tracked but regenerable or junk, which composer packages are unused / abandoned / outdated, and the backend updates & optimizations already flagged across LMS_Frontend/major_code_updates.md. Nothing has been executed yet unless marked ✅. Statuses re-checked against the code on 06/11/2026.

Why the repo is heavier than it needs to be

The tracked tree is ~22.2 MB across 935 files (pack ~13.4 MiB):
  • graphify-out/ IS the problem, exactly like it was in the frontend repo: the ignore rule exists in .gitignore but is commented out (#graphify-out/). 538 files including a 2.3 MB graph.json and a 2.0 MB graph.html — regenerable local tool output.
  • 10 .DS_Store files are tracked (root, app/, app/Http/, database/, public/, public/images/, resources/, resources/views/, storage/, tests/).
  • vendor/ (158 MB) and node_modules/ (34 MB) are correctly ignored — nothing to do there.

A. Untrack + gitignore (biggest win, zero risk) — ⬜ pending

Estimated saving: ~12.2 MB and ~550 files (≈55% of the tracked tree).

B. public/ images — unreferenced files + oversized referenced ones

B.1 Zero references in app/, database/, resources/, config/, routes/ (~560 KB)

Verify against the live databases before deleting: a public image can be referenced by a URL stored in an existing DB row (platform / landing settings, partner rows) even when no code or seeder mentions it anymore.

B.2 Referenced but oversized — compress / convert (keep the file names)

The landing-page defaults (LandingPage model, seeder and observer all point at them) — keep the paths, shrink the bytes: A 2.9 MB PNG served as a landing background is also a runtime cost for every visitor, not just a git one. Compressing these three should save ~3 MB in-repo and on the wire.

B.3 Keep as-is

  • resources/fonts/certificate/Montserrat-{Light,Regular,SemiBold,Bold}.ttf (~1.8 MB) — required by CertificateImageService (the GD-drawn og:image share previews, Update 83). An Arabic font will have to join them when the RTL-shaping issue (known issue 30) is fixed.
  • public/images/platform_logo.png, verify_mail_image.jpg, favicon.png — referenced by mails, PDFs and blade views.

C. Root-level clutter (tidiness only) — ⬜ pending

The x_README_API_Documentation/ folder no longer exists in the backend repo (neither tracked nor on disk), yet the backend’s own CLAUDE.md §9 still lists 14 of its files as the endpoint documentation to consult, and this documentation repo’s CLAUDE.md points to it too. Either restore the folder (e.g. under docs/) or update both CLAUDE.md files — today those references send a developer (or an AI agent) to files that are not there.

D. Composer packages — unused, duplicated, abandoned

D.1 ✅ Duplicated / dead CORS packages (remove first)

✅ DONE 19/10/2026 — one CORS middleware, no abandoned package. \Fruitcake\Cors\HandleCors left app/Http/Kernel.php, and barryvdh/laravel-cors + fruitcake/laravel-cors left composer.json and composer.lock (Update 126). Only Laravel’s own HandleCors runs now, reading config/cors.php. Checked locally on 06/11/2026: OPTIONS preflights and a real GET on /api/* each answer with one Access-Control-Allow-Origin header. fruitcake/php-cors stays in composer.lock on purpose: it is the library HandleCors calls, a dependency of laravel/framework, not one of the abandoned packages. The text below is the original finding. Still to do: the minimum-stability bonus (Section G.3).
composer.json requires both barryvdh/laravel-cors and fruitcake/laravel-cors, both pinned to the unstable dev-develop ref, and both are officially abandoned (composer prints the warning on every install). Laravel 10 ships its own CORS middleware, and app/Http/Kernel.php currently stacks two CORS middlewares globally:
Action: drop \Fruitcake\Cors\HandleCors::class from the Kernel, remove both packages, keep config/cors.php (the framework middleware reads the same file). Bonus: with the two dev-develop constraints gone, "minimum-stability": "dev" can likely return to "stable". ⚠️ Re-verify CORS afterwards (/api/* preflights from the web app; remember /storage/* images are answered by nginx, not Laravel — Update 19).

D.2 Zero usage found — removal candidates

⚠️ After each removal: composer update --lock, boot the app, run the test suite.

D.3 Keep (verified in use)

DONE 24/10/2026 — one PDF engine. barryvdh/laravel-snappy (with knplabs/knp-snappy), config/snappy.php, the PDF → SnappyPdf alias and the WKHTML_PDF_BINARY / WKHTML_IMG_BINARY variables are removed. admin_dashboard_pdf now renders with dompdf: its three flexbox rules became tables and the fixed footer moved into the bottom page margin (checked on a 5-page sample). Guarded by tests/Feature/AdminDashboardPdfTest.php. The wkhtmltopdf binaries can be uninstalled from the servers once this code is deployed: see Wkhtmltopdf removal.

D.4 Version freshness — installed vs latest (composer outdated --direct, run 08/10/2026)

The Installed and Latest columns stay the 08/10/2026 snapshot; the Status column was re-checked against composer.lock on 06/11/2026.
Like the frontend table: this is the map, not an instruction to upgrade. The Laravel 10 → 11/12 jump is a real migration (new skeleton, config changes, Sanctum 4). But unlike the frontend’s gaps, the framework one has a security dimension: Laravel 10 no longer receives security fixes, so the upgrade should be planned as its own project, not just noted.
✅ DONE 25/10/2026 — Laravel 12.70.1 (12.70.2 since 01/11/2026). Laravel 10.49 → 12.70.1 in one step (Carbon 3, Symfony 7.4), with Sanctum 4, rappasoft auth-log 6 (+ its upgrade migration), PHPUnit 11 and Collision 8; the classic Laravel 10 structure is kept. config.platform.php = 8.2.35 keeps the lock installable on the TEST server’s PHP 8.2. The 166 tests passed unchanged. Details and deploy steps: README → Laravel 12 upgrade. Laravel 13 is the next step (it needs PHP 8.3+, so not before the TEST server leaves 8.2).

E. Code style & static analysis

  • ./vendor/bin/pint --test currently fails on 157 files repo-wide (measured 08/10/2026) — class_attributes_separation, concat_space, single_quote, blank-line rules, etc. The known-issues table (row 10) only tracks the handful relevant to recent work; the full debt is bigger. Fix: one formatting-only commit (./vendor/bin/pint), ideally right after open branches merge so it doesn’t create conflicts; from then on run Pint per-touched-file.
  • nunomaduro/phpinsights is installed (config/insights.php) but wired into no CI — either adopt a minimum score in CI or drop the dev dependency.

F. Two language directories — consolidate ⚠️

Both lang/ (Laravel 9+ root location: en, ar — framework files plus category.php) and resources/lang/ (legacy location: en, fr, ar — the messages.php used by the localized certification responses of Update 56, plus validation.php copies) exist. Neither tree is complete: root lang/ has no fr, and the two validation.php variants can drift apart. Fix: pick one location (root lang/ is the Laravel 10 convention), merge the trees so all three locales carry every file, delete the other directory, and run the localized-message tests (CertificationIssuedOnceTest covers the fr/ar messages) to prove translations still resolve.

G. Backend updates & optimizations backlog

Everything below was flagged in LMS_Frontend/major_code_updates.md (update number in parentheses). The security rows also live in Issues & Errors.

G.1 🔴 Security hardening (do these first)

G.2 🔥 Payload & performance optimizations

G.3 Framework & infrastructure


H. Production database — orphaned Laravel Telescope tables (≈6.6 GB) ✅

✅ DONE 06/11/2026 — Telescope is removed from the production environment. The finding and the steps stay below as the record of the work.
Found 09/10/2026 on theteamdb_prod (phpMyAdmin on Plesk) with the table-size query of Monitoring & Logs. Full runbook (server checks, code removal if needed, SQL, the keep-but-bounded alternative) on that page.
Laravel Telescope is not in the repository: nothing in composer.json / composer.lock, no config/telescope.php, no TelescopeServiceProvider, no Telescope migration, and git log --all -S telescope is empty on every branch. The package was either installed on the server outside git or removed from the code without dropping its tables. Either way the two tables are dead weight (≈98 % of the database) that nothing in the app reads, so dropping them cannot break the app — once step 1 confirms the server matches the repo.
  1. ✅ Check the server (SSH / Plesk terminal, backend root): composer show laravel/telescope must answer “not found”; grep -rn -i telescope composer.json config/app.php app/Providers .env and php artisan route:list | grep -i telescope must print nothing. If Telescope IS installed there, remove it first (runbook, “Removing Telescope safely”) — the database steps are the same afterwards.
  2. ✅ Prove nothing writes: SELECT MAX(sequence) FROM telescope_entries; twice, 5 minutes apart — same value.
  3. ✅ Drop (phpMyAdmin → SQL; child table first because of the foreign key): DROP TABLE IF EXISTS telescope_entries_tags; DROP TABLE IF EXISTS telescope_entries; DROP TABLE IF EXISTS telescope_monitoring; then DELETE FROM migrations WHERE migration LIKE '%create_telescope_entries_table%';
  4. ✅ Re-run the size query: the database goes from ≈6.7 GB to ≈0.1 GB. Needs innodb_file_per_table = ON (the MySQL default — SHOW VARIABLES LIKE 'innodb_file_per_table';); if OFF the space is reused inside ibdata1 but the file never shrinks.
No backup of the rows is worth taking (request / query debug logs, 6 GB of them); a schema-only dump (mysqldump --no-data theteamdb_prod telescope_entries telescope_entries_tags telescope_monitoring) is enough to recreate the empty tables if Telescope ever comes back. php artisan telescope:prune / telescope:clear are NOT the tool: they delete 1,000 rows at a time and would run for hours on 7.5 M rows — and the commands do not exist without the package. DROP TABLE takes seconds.

Execution order

  1. ⬜ Section A — .gitignore additions, git rm -r --cached graphify-out, drop the .DS_Stores and @php. ~12.2 MB / ~550 files gone, zero functional risk.
  2. 🔶 Section D.1 — kill the duplicated abandoned CORS packages + the second Kernel middleware; re-verify CORS; restore minimum-stability: stable. ✅ Packages + middleware gone 19/10/2026, CORS re-checked 06/11/2026; only minimum-stability is left.
  3. ⬜ Section D.2 — remove jwt-auth + geoip (+ configs + the User JWT interface); run the suite.
  4. ⬜ Section B — compress the three landing PNGs (~3 MB); delete the unreferenced images after a DB check (~560 KB).
  5. ⬜ Section E — one Pint formatting-only commit (157 files).
  6. ⬜ Section F — consolidate the two lang trees.
  7. ⬜ Section C — move the root diagrams / notes into docs/; fix the x_README_API_Documentation references in both CLAUDE.md files.
  8. 🔶 Section G — the G.1 security rows go first (tracked in Issues & Errors); G.2 / G.3 are the optimization backlog; the Laravel upgrade is its own project.
  9. ✅ Section H (done 06/11/2026) — drop the orphaned Telescope tables on production (≈6.6 GB, 98 % of the database). Independent of the repo, the only item with an immediate payoff: do it first.
Like the frontend: doing Sections A–C before the next history-sensitive operation keeps the repo permanently light — files removed later still live in pack history otherwise.