Commit Graph
673 Commits
Author SHA1 Message Date
Pontoporeia 55c714a35d Reorganise docs: move historical files to archive/, merge overlapping docs
- Move 12 historical/superseded docs + 1 session log + 1 PDF + 1 HTML plan to archive/
- Merge 4 VM-crash docs into archive/vm-crash-incident.md
- Merge LDAP plan + spec into ldap.md
- Merge FilePond race investigation into filepond-crash-analysis.md
- Merge SPECS.md client notes into spec-sheet.md appendix
- Update README index and security.md cross-reference
2026-08-24 11:36:02 +02:00
Pontoporeia e4b48867aa Add sso-diagnose.sh: verify all peertube-sso-incident claims into a log
- docs: record the open identity-forwarding question, auth contracts, and responsibility boundary
2026-08-24 11:36:02 +02:00
Pontoporeia f31addb6bc add password-reset smoke test + AdminAuth DI + OneTimeToken empty-context redeem fix 2026-08-24 11:36:02 +02:00
Pontoporeia ddae5d8fef add password-reset flow: request endpoint + reset page + login link (shared OneTimeToken) 2026-08-24 11:36:02 +02:00
Pontoporeia d7184e4447 migrate file-access tokens onto shared OneTimeToken model (hash-at-rest) 2026-08-24 11:36:02 +02:00
Pontoporeia 3f1dcf5d43 test: add characterization tests for file-access token lifecycle 2026-08-24 11:36:02 +02:00
Pontoporeia abb735253e extract shared OneTimeToken model for single-use tokens + AdminAuth reset API 2026-08-24 11:35:22 +02:00
Pontoporeia 802b601b59 admin parametres: remove the remove-credentials danger zone 2026-08-24 11:35:22 +02:00
Pontoporeia c205a00c3f admin parametres: hr separator between current/new password, drop new-password top border 2026-08-24 11:35:22 +02:00
Pontoporeia 138b59f66c admin parametres: add shared Identifiants section, trim Emails, restructure PeerTube fieldsets
- admin parametres: move Compte administrateur into Identifiants as a fieldset
- admin parametres: space the account fieldset and drop confirm-password top border
- admin parametres: tighten param-form row spacing, relabel password button
- admin parametres: move password submit button outside the account fieldset
2026-08-24 11:35:22 +02:00
Pontoporeia fb5e856288 admin: backup logs via parameters.php, nextcloud secondary backup
- surface backup/cleanup cron logs + backup freshness status
- email xamxam@erg.be when SQLite backups go stale (backup watchdog)
- sync SQLite snapshots to Nextcloud WebDAV + remote-freshness watchdog
- precise retention pruning, manual sync in check recipe, and Nextcloud-sync docs
2026-08-24 11:34:57 +02:00
Pontoporeia 3e721b19f0 ui: system logs style update
- Increase padding in admin log dropdown selects
- Move admin log filters above the Journaux tabs
2026-08-24 11:34:34 +02:00
Pontoporeia d2cef85966 logs: standardise log filenames to xamxam-{service}-{date}.log 2026-08-24 11:34:34 +02:00
Pontoporeia 7b6d79c133 diag: invalid_grant is SSO auth-method mismatch, not bad creds
- feat: creds-test.sh gum probe for SMTP vs PeerTube auth + PeerTubeService::probeAuth()
- feat: app-token.sh gum probe for long-lived PeerTube app token (client_credentials)
- docs: add copy-paste proof commands to demonstrate the SSO break to admins
2026-08-24 11:33:34 +02:00
Pontoporeia 5460041989 feat: allow exporting an empty CSV template for imports 2026-08-24 11:33:34 +02:00
Pontoporeia 7938ab39c0 feat: add custom 404 page rendered via the site layout 2026-08-24 11:32:02 +02:00
Pontoporeia e9747edce0 docs: verify and refactor documentation to match current codebase 2026-08-24 11:31:38 +02:00
Pontoporeia b2cdbd0174 fix: CSV import VALUES placeholder count mismatch (27 values for 26 columns) 2026-07-10 19:07:19 +02:00
Pontoporeia 64323fd17e sort TFE files by display category on public page: note d'intention → TFE → image → video → audio → website → annexes 2026-07-10 19:07:14 +02:00
Pontoporeia 9965529fd4 nginx: open CSP frame-src from hardcoded domain whitelist to https: scheme-wide 2026-07-10 17:26:02 +02:00
Pontoporeia 6e1d54511d fix: remove redundant query= param from filter-specific metadata links on TFE page
Clicking orientation, AP program, finality, year, format, or keyword links
on the TFE page was passing both a dedicated filter param AND a query=
param. The query= text search doesn't look at the filter columns
(orientation, ap_program, etc.), so the AND combination yielded zero
results when the filter value didn't appear in title/authors/etc fields.

Also fix the language link: it was passing language as query= which
searches only title/authors/etc, not the languages column. Now uses
the dedicated language= param (DB layer already supported it, and
collectSearchParams now collects it).
2026-07-10 17:20:21 +02:00
Pontoporeia 14c21586c5 fix: clamp student popover position to stay within viewport vertically 2026-07-10 17:11:10 +02:00
Pontoporeia d8f85b03ad fix: use getElementById for relink FilePond pool lookup
FilePond 4.x wraps the original input element in its own DOM structure
which can break CSS attribute selectors. querySelector with
.tfe-file-picker[data-queue-type='...'] returned null even though the
element existed and was initialized.

Switched to getElementById with a queueType→inputId map:
  cover → couverture
  note_intention → note_intention
  tfe → tfe-files-input
  annexe → annexe-files-input

getElementById is both faster and immune to FilePond's DOM wrapping.
2026-07-10 16:42:56 +02:00
Pontoporeia 6da45435f5 fix: relinked files now appear in FilePond UI immediately
Switched from pond.addFile(type:'limbo') to pond.addFiles([{source, options:{type:'local'}}])
in both XamxamRelinkFile and XamxamRelinkPeerTube.

addFile with type 'limbo' doesn't trigger server.load to fetch the file
for the preview/thumbnail. The data-existing-files format (type:'local')
correctly tells FilePond to call server.load for the file identified by
the source (DB ID), rendering it properly in the pool.
2026-07-10 16:36:30 +02:00
Pontoporeia 7013f79fc0 fix: merge corbeille lists + bulk restore button in cleanup
- Single unified 'Corbeille' table replaces the two separate lists
  (stale/orphelin + restorable). Each row has a Statut column showing
  '↺ Restaurable' or 'Orphelin', plus a checkbox for bulk ops.

- Checkboxes on restorable rows carry data-restorable='1' attribute
  so the bulk JS can distinguish them.

- Bulk actions bar now has both 'Supprimer la sélection' and
  '↺ Restaurer la sélection' buttons. The restore button only appears
  when at least one restorable item is checked.

- New cleanupBulkRestore() JS function populates a dedicated hidden
  form and confirms before submitting. Only restorable items are sent.

- restore-trash.php refactored to handle both single (trash_file) and
  bulk (trash_files[]) inputs via a loop, accumulating restored/skipped
  counts and re-rendering the fragment on HTMX requests.
2026-07-10 16:33:06 +02:00
Pontoporeia 3cecee10c9 fix: prevent file deletion on relink + restore button now visible + OOB-style in-place update
Two critical fixes:

1. Relink flow no longer destroys/recreates FilePond instances:
   The relink (XamxamRelinkFile) and PeerTube relink (XamxamRelinkPeerTube)
   previously refreshed the entire fichiers fragment via HTMX after
   pond.addFile(). This triggered destroyFilePondsIn on ALL pools, which
   could fire server.remove callbacks and move existing files to corbeille.
   Now just closes the modal — the file is already added to the pool in-place,
   and syncOrderInput creates the hidden form input.

2. Cleanup page « Corbeille (restaurable) » now actually shows files:
   _cleanup-stats-data.php previously classified trash files by checking if
   the thesis_files DB row still existed. But both deleteThesisFileToTrash
   and FilepondHandler::handleRemove DELETE the DB row. So ALL trash files
   appeared as `stale` (not restorable). Now uses the JSON sidecar file
   presence as the classification criterion — if the sidecar exists and is
   recent, the file is restorable regardless of DB row state.

Also removed unused DB query from _cleanup-stats-data.php.
2026-07-10 16:29:04 +02:00
Pontoporeia ed19e30cf0 repertoire keyword column: smaller font (step--1), tighter line-height (1.15), no hyphenation 2026-07-10 15:59:48 +02:00
Pontoporeia 0045c06fef fix: prevent keyword word-breaking in repertoire columns 2026-07-10 15:51:03 +02:00
Pontoporeia c1a05efcda fix: bypass /tmp tmpfs for file uploads by redirecting PHP upload_tmp_dir to storage partition 2026-07-10 15:42:07 +02:00
Pontoporeia 1293b1be6c remove TOC temporary debug error_log calls 2026-07-10 15:23:52 +02:00
Pontoporeia c67262673f paramètres: fix logs Copier button scrolling out of view on horizontal scroll
Wrap .log-output and the copy button in a .log-output-wrapper div
with position:relative, so the button sits outside the overflow-x:auto
scroll container and stays fixed at the top-right corner.
2026-07-10 15:21:29 +02:00
Pontoporeia 3e3d829d11 fix: website iframe overlay — icon button bottom-right, no blur, tooltip 2026-07-10 15:18:42 +02:00
Pontoporeia 3d5d972ad0 fix TOC invisible: add open attr to details.toc — extractToc works but closed details + desktop pointer-events:none hid content; also make apropos TOC dynamic
fix: website iframe overlay — icon button bottom-right, no blur
2026-07-10 15:18:42 +02:00
Pontoporeia 250e33b571 fix: add frame-src CSP for videos.erg.be and depnum.happyngreen.fr 2026-07-10 15:18:42 +02:00
Pontoporeia 018d699ebd apropos: dynamic TOC via extractToc, HeadingPermalinkExtension, debug logging for TOC diagnosis 2026-07-10 15:07:14 +02:00
Pontoporeia 2461f526bf fix: prevent line breaks before punctuation in TFE titles and meta labels
- Override aggressive word-break: break-word from base.css
  with word-break: normal + overflow-wrap: break-word + hyphens: auto
  on .tfe-title, .tfe-author, .tfe-meta-item
- Replace regular spaces before colons with   in all meta labels
  (French typographic rule: non-breaking space before double punctuation)
- Rebuild tfe.min.css
2026-07-10 14:47:52 +02:00
Pontoporeia bbf063f3eb fix: header font-size + css syntax error 2026-07-10 14:38:58 +02:00
Pontoporeia eb0f48d320 fix: gradient across public 2026-07-10 14:32:46 +02:00
Pontoporeia 269b751fea fix: Logger default WARNING→INFO + structured PeerTube logging
Log level: production default was Level::Warning, but all facades
(AppLogger, AdminLogger, Audit) write at Monolog INFO level. This
silently discarded submission, admin action, and audit logs when
LOG_LEVEL env var was unset. Changed to Level::Info.

PeerTube: replaced raw error_log() calls in PeerTubeService::upload(),
deleteVideo(), FilepondHandler::process(), ThesisCreateController,
and ThesisFileHandler with structured logging:
- Successes → Logger::get('app')->info() (visible in App — soumissions tab)
- Failures  → ErrorHandler::log('peertube_*', ...) (visible in Erreurs tab)
Added require_once for Logger and ErrorHandler in PeerTubeService.
2026-07-10 14:16:53 +02:00
Pontoporeia f427352a71 tfe: redirect internal metadata links from /repertoire to /search
redirect internal metadata links from /repertoire to /search, add query param for search bar prefill, fix filter visibility on desktop

 redirect metadata links from /repertoire to /search, prefill search bar, fix filter visibility

 link metadata to /search, preserve keyword filter in form, show active keyword chip
2026-07-10 14:16:36 +02:00
Pontoporeia f5a7d70fbc tfe: wrap website iframe in overlay-style div with Site web badge, clearer link text 2026-07-10 14:16:05 +02:00
Pontoporeia c513ad2545 TOC: extract h1/h2/h3, indent sub-levels in charte/licence sidebar 2026-07-10 14:16:05 +02:00
Pontoporeia 485324368f content-page.css: smaller heading scale with explicit clamp values
Replace var(--step-5)/--step-3/--step-1 for h1/h2/h3 with explicit
clamp() values. New hierarchy: h1 ~2rem, h2 ~1.5rem, h3 ~1.2rem.
Also update .content-section-title to use direct clamp (was --step-3,
now matches h2). Mobile override swapped from --step-2 to explicit
clamp. Kept --step-0 for body text (consistent with site baseline).
2026-07-10 14:16:05 +02:00
Pontoporeia 83e95bc4f5 repertoire: HTMX OOB swaps for filter columns + fix fading edge cases
Switch from swapping the entire #repertoire-index block to targeted
hx-swap-oob swaps: only the <ul> list elements are replaced, while
section headers and accordion chrome stay in the DOM untouched.

- Filter column <ul>s get IDs (rep-list-years, rep-list-ap, etc.)
  and render with hx-swap-oob=true on HTMX requests
- Students <ul> gets id=rep-students as main swap target
- Filter buttons now target #rep-students instead of #repertoire-index
- Server sets $isOob=true when rendering HTMX partial responses
- Accordion re-init on swap no longer needed (headers never replaced)
- Scroll-restore updated to capture/restore per <ul> ID

Fading fixes:
- Restore rep-entry--faded class with simplified logic: any active
  filter fades entries whose matched flag is false (removed the
  $colHasMatch gate that prevented fading when a column had no matches)
- Add $noResults guard: when matched_ids is empty, force-fade all
  non-selected entries across ALL columns
- Fix keyword matched computation: use full intersection
  ($buildWhere('__none__')) instead of excluding the keyword filter.
  Previously keywords were matched against only non-keyword filters,
  so selecting a keyword would not narrow the available keyword set,
  causing entries to appear valid that would yield zero results.
2026-07-10 13:02:32 +02:00
Pontoporeia ec9c140ba2 repertoire: HTMX OOB swaps for filter columns + fix fading edge cases
Switch from swapping the entire #repertoire-index block to targeted
hx-swap-oob swaps: only the <ul> list elements are replaced, while
section headers and accordion chrome stay in the DOM untouched.

- Filter column <ul>s get IDs (rep-list-years, rep-list-ap, etc.)
  and render with hx-swap-oob=true on HTMX requests
- Students <ul> gets id=rep-students as main swap target
- Filter buttons now target #rep-students instead of #repertoire-index
- Server sets $isOob=true when rendering HTMX partial responses
- Accordion re-init on swap no longer needed (headers never replaced)
- Scroll-restore updated to capture/restore per <ul> ID

Fading fixes:
- Restore rep-entry--faded class with simplified logic: any active
  filter fades entries whose matched flag is false (removed the
  $colHasMatch gate that prevented fading when a column had no matches)
- Add $noResults guard: when matched_ids is empty (zero theses match
  all active filters), force-fade all non-selected entries across ALL
  columns. This covers the keyword edge case where per-column matched
  is computed excluding the keyword filter (many-to-many), causing
  keywords to appear valid even though the full intersection is empty.
2026-07-10 12:59:12 +02:00
Pontoporeia f86deaf02f repertoire: remove matched-first sorting and faded/disabled system for filter entries
Remove the system that sorted valid (matched) filter entries to the top and
faded/disabled unmatched ones when any filter was active. Entries now stay in
their natural alphabetical/numeric order regardless of selection state.

- Drop usort calls that reordered entries by matched status
- Simplify repFilterEntry: remove anyActive and colHasMatch params
- Remove colHasMatches computation
- Remove rep-entry--faded CSS rule
- All filter buttons remain clickable at all times
2026-07-10 12:35:45 +02:00
Pontoporeia b9c7d6c663 fix: sort repertoire Années column reverse chronological (newest first) 2026-07-10 12:29:08 +02:00
Pontoporeia dae97ab812 fix: repertoire heading font sizes 2026-07-10 12:27:24 +02:00
Pontoporeia a8dcc4bba5 Consistent scrollbar styling across browsers
- colors.css: added --scrollbar-thumb, --scrollbar-thumb-hover, --scrollbar-track, --scrollbar-corner custom properties
- base.css: consolidated all scrollbar rules (WebKit ::-webkit-scrollbar* + Firefox scrollbar-width/color), added ::-webkit-scrollbar-corner, changed selector from * to html (scrollbar-width inherits), added scrollbar-gutter: stable
- admin.css: removed redundant scrollbar-width: thin on header nav
- toc.css: removed redundant scrollbar-width: thin on desktop .toc
2026-07-10 12:00:36 +02:00
Pontoporeia 08a9b7309f fix: locked_year cleared on edit — populate edit dialog field
The openEditDialog JS function didn't populate the locked_year input
in the edit dialog, and the PHP template didn't pass locked_year as an
argument. Any edit to a link (even just changing the name) would clear
the locked academic year to NULL.

- Pass $linkLockedYear as 5th argument to openEditDialog in the template
- Accept and populate edit-locked-year input in the JS handler
2026-07-10 11:56:27 +02:00