diff --git a/TODO.md b/TODO.md
index 2ae6365..455abb9 100644
--- a/TODO.md
+++ b/TODO.md
@@ -21,6 +21,18 @@
- [x] `duration_pages`/`duration_minutes` saved in `updateThesis()` and read back in `getThesisRawFields()`
- [x] `beforeunload-guard` applied to add and partage forms too
+- [x] Audit + fix direct PHP URL references blocked by nginx catch-all `deny all`
+ - [x] `/request-access.php` fetch in `tfe.php` → `/request-access`
+ - [x] `/media.php?path=` in `form.php` (×2) and `admin/recapitulatif.php` → `/media?path=`
+
+- [x] Fix 403 on `/language-autre-fragment.php` from `edit.php`
+ - [x] Root cause: standalone root-level PHP file blocked by nginx catch-all `deny all`
+ - [x] Moved logic to `partage/language-autre-fragment.php` (shared include)
+ - [x] Added route `/partage/language-autre-fragment` in `partage/index.php`
+ - [x] Added `admin/language-autre-fragment.php` (AdminAuth gated, includes shared logic)
+ - [x] `form.php` picks URL based on `$mode` (`partage` vs admin)
+ - [x] Deleted `public/language-autre-fragment.php`; nginx unchanged
+
- [x] Merge banner images into cover images
- [x] Migration 016: copy `storage/banners/*` → `storage/covers/`, insert `thesis_files` cover records, clear `banner_path`, remove banners dir
- [x] Remove banner fieldset from edit form (`form.php`)
diff --git a/app/public/admin/language-autre-fragment.php b/app/public/admin/language-autre-fragment.php
new file mode 100644
index 0000000..609095c
--- /dev/null
+++ b/app/public/admin/language-autre-fragment.php
@@ -0,0 +1,17 @@
+
-
-
-
-
-
-
- Si votre TFE contient une langue absente de la liste, précisez-la ici.
-
-
-
-
-
-
-
- Si votre TFE contient une langue absente de la liste, précisez-la ici.
-
-
-
-
diff --git a/app/public/partage/index.php b/app/public/partage/index.php
index a6b0b8c..280eae6 100644
--- a/app/public/partage/index.php
+++ b/app/public/partage/index.php
@@ -21,6 +21,13 @@ $parts = explode('/', $path);
$slug = $parts[0] ?? '';
$action = $parts[1] ?? '';
+// Special route: /partage/language-autre-fragment (HTMX fragment, no auth needed)
+if ($slug === 'language-autre-fragment' && $_SERVER['REQUEST_METHOD'] === 'POST') {
+ App::boot();
+ require_once __DIR__ . '/language-autre-fragment.php';
+ exit;
+}
+
// Special route: /partage/format-website-fragment (HTMX fragment, no auth needed)
if ($slug === 'format-website-fragment' && $_SERVER['REQUEST_METHOD'] === 'POST') {
App::boot();
diff --git a/app/public/partage/language-autre-fragment.php b/app/public/partage/language-autre-fragment.php
new file mode 100644
index 0000000..1f5fb3b
--- /dev/null
+++ b/app/public/partage/language-autre-fragment.php
@@ -0,0 +1,36 @@
+
+
+
+
+
+ >
+ Si votre TFE contient une langue absente de la liste, précisez-la ici.
+
+
+
diff --git a/app/templates/admin/recapitulatif.php b/app/templates/admin/recapitulatif.php
index 5a71090..69a828f 100644
--- a/app/templates/admin/recapitulatif.php
+++ b/app/templates/admin/recapitulatif.php
@@ -98,7 +98,7 @@
diff --git a/app/templates/partials/form/form.php b/app/templates/partials/form/form.php
index 34b2a32..f9c3aa7 100644
--- a/app/templates/partials/form/form.php
+++ b/app/templates/partials/form/form.php
@@ -173,7 +173,7 @@ $checkedFormatsForSiteWeb = $checkedFormatsForSiteWeb ?? [];
$options = $languages;
$checked = $formData["languages"] ?? [];
$required = true;
- $hxPost = "/language-autre-fragment.php";
+ $hxPost = $mode === 'partage' ? "/partage/language-autre-fragment" : "/admin/language-autre-fragment.php";
$hxTarget = "#language-autre-row";
$hxSwap = "outerHTML";
include APP_ROOT . "/templates/partials/form/checkbox-list.php";
@@ -252,7 +252,7 @@ $checkedFormatsForSiteWeb = $checkedFormatsForSiteWeb ?? [];