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.gitignorebut is commented out (#graphify-out/). 538 files including a 2.3 MBgraph.jsonand a 2.0 MBgraph.html— regenerable local tool output.- 10
.DS_Storefiles are tracked (root,app/,app/Http/,database/,public/,public/images/,resources/,resources/views/,storage/,tests/). vendor/(158 MB) andnode_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 byCertificateImageService(the GD-drawnog:imageshare 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:
\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 --testcurrently 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/phpinsightsis 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 ⚠️
Bothlang/ (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 inLMS_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.
- ✅ Check the server (SSH / Plesk terminal, backend root):
composer show laravel/telescopemust answer “not found”;grep -rn -i telescope composer.json config/app.php app/Providers .envandphp artisan route:list | grep -i telescopemust print nothing. If Telescope IS installed there, remove it first (runbook, “Removing Telescope safely”) — the database steps are the same afterwards. - ✅ Prove nothing writes:
SELECT MAX(sequence) FROM telescope_entries;twice, 5 minutes apart — same value. - ✅ 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;thenDELETE FROM migrations WHERE migration LIKE '%create_telescope_entries_table%'; - ✅ 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 insideibdata1but the file never shrinks.
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
-
⬜ Section A —
.gitignoreadditions,git rm -r --cached graphify-out, drop the.DS_Stores and@php. ~12.2 MB / ~550 files gone, zero functional risk. -
🔶 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; onlyminimum-stabilityis left. -
⬜ Section D.2 — remove
jwt-auth+geoip(+ configs + theUserJWT interface); run the suite. - ⬜ Section B — compress the three landing PNGs (~3 MB); delete the unreferenced images after a DB check (~560 KB).
- ⬜ Section E — one Pint formatting-only commit (157 files).
- ⬜ Section F — consolidate the two lang trees.
-
⬜ Section C — move the root diagrams / notes into
docs/; fix thex_README_API_Documentationreferences in both CLAUDE.md files. - 🔶 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.
- ✅ 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.