Commit Graph
58 Commits
Author SHA1 Message Date
Pontoporeia 541470b9bb feat(provision): idempotent setup for local dev and remote server 2026-09-18 16:26:36 +02:00
Pontoporeia d5c1dfb23d docs: keep only reference documentation, archive one-offs 2026-09-18 16:26:36 +02:00
Pontoporeia 8accb88452 update: CSS per-page split and lightningcss unusedSymbols report
docs: record CSS template inventory + decide unusedSymbols-before-split ordering

feat(css): add content-source collector + dynamic-class safelist for unusedSymbols report

- scripts/css-content-sources.mjs: buildCorpus() gathers templates/public/src
  PHP + first-party js/app JS (vendor excluded), returns {corpus, sources,
  totalBytes, safelist, prefixes}
- Mined 22 exact runtime classes + 5 DB/state-derived suffix prefixes from
  status-badge.php, SystemController statusClass/logLineClass, and class=<?=?>
  ternaries
- docs/css-split-analysis.md notes content-corpus section
- td: #11 collect-content-sources done; feeds #12 report script

feat(css): unusedSymbols report script + just css-report recipe

- scripts/css-unused-report.mjs: per-bundle class/id extraction vs buildCorpus()
  corpus + safelists; measures reclaimable bytes via lightningcss transform
  unusedSymbols (report-only, no stripping to disk)
- just css-report: rebuild CSS then run the report
- css-content-sources.mjs: add VENDOR_CLASS_PREFIXES (filepond--*, htmx-*)
- RESULT: 216,383B total, ~6.2KB (2.9%) reclaimable; FilePond/HTMX exclusion
  corrected inflated 26% (56KB) false-positive down to honest 2.9%
- docs/css-split-analysis.md findings table + TODO 12/13 done

docs(css): record go/no-go decision — split NO-GO, pruning conditional-go

- Decision analysis in docs/css-split-analysis.md
- ~6.2KB (2.9%) reclaimable of 216KB; base.min.css only 484B (2.3%)
- SPLIT NO-GO: base.css already well-used; parked u/w/x/y(/z) as deferred
- PRUNING conditional-go on hand-verifiable dead selers from source, never dist;
  re-run just css-report after each edit; keep needs-review + vendor-prefix cls
- td: task 14 done; split stream 41 tasks -> 2 pending / 32 done / 7 deferred

todo: defer CSS pruning stream (10/u/w/x/y/z), context updated
2026-09-18 16:26:36 +02:00
Pontoporeia a31e4ab307 Recherche insensible aux accents sur toutes les barres de recherche (publique + backoffice).
Ajoute une fonction SQLite UDF accfold() (app/src/AccentFolding.php) qui plie les caractères accentués latin vers leur base ASCII (é→e, ç→c, …), et l'applique à chaque condition de recherche côté colonne ET côté terme (accfold(column) LIKE accfold(:term)). Comme le runtime n'a ni intl (Normalizer) ni iconv, le repli passe par une map de translitération manuelle (Western Latin-1 + Latin Extended-A, NULL-safe).

Couvert :
- recherche publique (searchTheses / countSearchResults) : titre, sous-titre, synopsis, auteurs, promoteurs, tags ;
- popover étudiant (getThesesByAuthorName / getThesesForAuthors) : a.name ;
- recherche backoffice (getThesesList / getThesesListCount) : titre, sous-titre, identifiant, auteur.

L'UDF est enregistré dans Database::registerSqliteFunctions() (appelé par le constructeur et par le harnais de test TestDatabaseInstance). Évite aussi la dépréciation PHP 8.5 de PDO::sqliteCreateFunction() : la connexion est créée via \Pdo\Sqlite quand disponible (createFunction()) avec repli sur PDO (sqliteCreateFunction()) sur les anciens runtimes ; les tests passent de @dataProvider docblock à l'attribut #[DataProvider] (fin de la dépréciation PHPUnit). Détache .php-cs-fixer.cache (gitignoré) pour ne plus polluer le working copy.

294 tests PHPUnit verts sans dépréciation, phpstan niveau 5 OK.
2026-09-18 16:26:36 +02:00
Pontoporeia 6e1fc6a781 Add admin-only route to open Interdit thesis files from backoffice:
- reliable tab title /favicon wrapper,
- Content-Disposition filename,
- admin media route hardened to thesis-file prefixes only (defense-in-depth)
2026-09-18 16:26:36 +02:00
Pontoporeia 3316a352e3 docs: add environment/runtime requirements spec 2026-09-18 16:26:36 +02:00
Pontoporeia 307988eb3c feat: enforce idle + absolute timeouts on admin session 2026-09-18 16:26:36 +02:00
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 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 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 e9747edce0 docs: verify and refactor documentation to match current codebase 2026-08-24 11:31:38 +02:00
Pontoporeia 00a106138e Docs: ajouter nombre de commits par groupe fonctionnel dans livraisons mensuelles 2026-06-29 17:57:13 +02:00
Pontoporeia 4b6f9212b5 Docs: regrouper livraisons par familles fonctionnelles dans chaque mois 2026-06-29 17:49:02 +02:00
Pontoporeia 4ea12f0172 Docs: livraisons par mois extraites de commits.txt 2026-06-29 17:38:57 +02:00
Pontoporeia 0ff6ee78d9 #todo add gzip + inline-js extraction tasks from analysis 2026-06-24 12:49:14 +02:00
Pontoporeia ecb90ba5dd Add accordion + active-filter chip bar for mobile repertoire
- repertoire-index.php: wrap each filter column in rep-accordion with toggle
  button, chevron, badge (active filter count); add rep-chip-bar with
  removable active-filter chips above the columns
- repertoire.css: mobile (≤640px) accordion mode — columns collapse to
  single-open accordion sections with 48px touch targets; chip bar becomes
  sticky; desktop/tablet layout unchanged via display:none on toggle elements
- repertoire.php: JS for single-accordion-open behavior on mobile, HTMX
  re-init after swap, resize-breakpoint cleanup
- docs/repertoire-mobile-propositions.md: analysis + 4 architecture proposals
2026-06-22 16:32:26 +02:00
Pontoporeia 6d93199fa2 docs: HTMX/destroy race hypothesis investigation — REFUTED
Investigation verdict:
- HTMX does NOT swap the FilePond container on the edit page; the
  htmx:targetError in the crash log is unrelated noise
- The pre-destroy abort in destroyFilePondsIn has a wrong status check
  (filters for nonexistent status 4, misses status 7 LOADING) but is
  moot because no HTMX swap targets the FilePond container
- The load-file-error -> DID_THROW_ITEM_INVALID path is vulnerable
  (passes t.status directly, unlike every other error handler which
  wraps it), but for local files the LOAD_FILE plugins always wrap
  rejections properly
- Likely actual trigger: Firefox XHR abort edge case in server.load
  for the existing cover file, racing with addition of a new local file
  that replaces it in the single-file queue
2026-06-10 00:18:49 +02:00
Pontoporeia d8d925243e docs: add filepond crash analysis report
Documents the 'can't access property main, n.status is undefined'
crash in FilePond 4.32.12. Root cause: vendor code in filepond.min.js
has a property name mismatch — createResponse objects use .code but the
load-file-error handler reads .status. When action.status is undefined,
the view writers crash.

Proposes Option B (custom load function) as the cleanest fix.
2026-06-10 00:18:49 +02:00
Pontoporeia 38ef550397 feat: render actual elements in markdown cheatsheet instead of labels
Replace text labels (h1, bold, italic) with rendered HTML in the Rendu column:
headings, strong, em, del, code, links, blockquote, lists, hr, sup, small
2026-06-10 00:18:49 +02:00
Pontoporeia 4a2b000fca Add Charte static page (public + admin editing) 2026-06-10 00:18:49 +02:00
Pontoporeia 6246174fc5 Export: add LINK.txt with PeerTube watch URLs to file ZIP export 2026-05-31 17:46:02 +02:00
Pontoporeia ae66c2baad Integrate Monolog: replace four logging systems with single PSR-3 factory
- Add monolog/monolog dependency (^3.10)  
- Create app/Logger.php central factory with channels: app, admin, error, audit
- Each channel gets RotatingFileHandler (30-day retention) with pass-through LineFormatter
  preserving existing JSON format contracts
- Rewrite AppLogger as thin facade delegating to Logger::get('app')
- Rewrite ErrorHandler::log() to delegate to Logger::get('error')
- Rewrite AdminLogger file output to delegate to Logger::get('admin'), keep DB writes
- Add Monolog file shadow to Audit via Logger::get('audit') (Option A per monolog-plan)
- Log level controlled by LOG_LEVEL env var (defaults: DEBUG in cli-server, WARNING otherwise)
- Graceful NullHandler fallback when log directory is not writable
- Update SystemController LOG_FILES: remove php_error, add app/admin/error/audit
- JSON app logs parsed to readable one-liners in the log viewer
- Remove nginx config tab (parametres + fragment + template + css)
- Friendly empty-state message when app log files don't exist yet (notYet)
- PHP tail fallback when exec() unavailable
- All 228 PHPUnit tests pass, no call sites changed
2026-05-20 12:28:31 +02:00
Pontoporeia 7a4d0fafb2 Add PHPUnit setup (Phase 0) and pure-logic tests (Phase 1): Crypto, EmailObfuscator, SystemController helpers, StudentEmail, TfeController OG tags 2026-05-20 01:35:56 +02:00
Pontoporeia 4683ba4116 Add composer.json with league/commonmark, guzzlehttp/guzzle, phpmailer/phpmailer; wire autoloader into bootstrap; document de-librairisation strategy and PHP extension setup 2026-05-20 00:53:42 +02:00
Pontoporeia 926659087f feat: implement SQLite backup & data integrity plan (Phases 2-4) 2026-05-19 00:08:06 +02:00
Pontoporeia 7e987d281c fix: add hx-swap="none" to admin auto-save checkboxes to prevent page swap 2026-05-19 00:08:06 +02:00
Pontoporeia cf9bd5cd5d feat: require 3 mots-clés in partage, language asterisk toggle, admin auto-save checkboxes
- tag-search: add minTags/required params, counter shows red if < 3, accent if ≥ 3
- form.php: pass minTags=3 for partage mode keywords
- checkbox-list: support labelHtml for raw HTML label with targetable asterisk span
- language-autre-fragment: OOB swap updates #languages-required-asterisk when autre pills change
- language-search: client-side update #languages-required-asterisk on pill add/remove
- contenus.php: replace 3 form+submit-button fieldsets with HTMX auto-save checkboxes
- settings.php: detect HX-Request header, return OOB CSRF token updates, skip redirect
2026-05-19 00:08:06 +02:00
Pontoporeia 13d26ded66 Replace HTMX+PHP file upload queues with client-side JS
Drops the session-backed HTMX incremental upload system in favour of a
single JS module that manages `File` objects client-side and injects
them into `FormData` on submit.

Key changes:

* `file-upload-queue.js`: client-side queues with validation, reorder
  (SortableJS), removal, dirty-state tracking, and fetch-based submit
  with manual redirect handling
* `fichiers-fragment.php`: empty queue containers for JS-managed queues;
  HTMX format switching still works with queue rehydration after swap;
  annexe uploads now support multiple files
* Form UI cleanup: moved existing files and cover preview into the
  `Fichiers` fieldset (edit mode); removed redundant queue labels while
  keeping labels for single-file inputs (`couverture`,
  `note d'intention`); added delete buttons for existing files
* `ThesisFileHandler.php`: added
  `handleTfeQueueFiles()`/`handleAnnexeQueueFiles()` reading from
  `$_FILES['queue_file']`; introduced `extractFilesSubArray()` for
  nested upload arrays; removed session-based queue handling
* `ThesisCreateController.php` &
  `ThesisEditController.php`: switched to extracted
  `['queue_file']` uploads
* `beforeunload-guard.js`: now also watches
  `window.__xamxamDirty`
* Deleted obsolete PHP upload/remove/reorder queue endpoints for
  `partage` and `admin`
* Cleaned up route dispatch in `partage/index.php`
* Misc form and styling updates in templates/CSS
* Added `docs/cms-migration-plan.html`
2026-05-19 00:08:05 +02:00
Pontoporeia 7793b6f86d add file export system for admins
- ExportController: getAllThesisFiles(), buildExportManifest(), createExportZip()
  builds a ZIP archive with manifest.json + files/ mirror of storage/theses/
- Database: getAllThesisFilesForExport() queries all thesis_files + identifier
- AdminLogger: logFilesExport() audit log entry
- admin/actions/export-files.php: thin dispatcher, streams zip with headers
- templates/admin/index.php: 'Exporter fichiers' button next to CSV export
2026-05-07 16:40:16 +02:00
Pontoporeia 19784090a3 fix: pass PHP upload limits via -d flags in justfile serve recipe
php -S (built-in dev server) ignores .htaccess and .user.ini entirely.
The POST Content-Length limit was still 8M from /etc/php/php.ini.
Pass upload_max_filesize=512M, post_max_size=520M, memory_limit=256M,
max_execution_time=300, max_input_time=300 directly on the CLI.
2026-05-05 11:04:52 +02:00
Pontoporeia 6a37d21f3f docs: add file-uploads.md — accepted types, limits, storage, ordering, security 2026-05-05 11:04:52 +02:00
Pontoporeia 2188ff5479 docs: add SMTP 550 postfix fix report for mail admin 2026-05-05 11:04:52 +02:00
Pontoporeia ab51bf3a66 fix: deploy-server.sh cleans up legacy posterg configs and prunes old xamxam backups 2026-05-05 11:04:52 +02:00
Pontoporeia 1b02ccb1d5 fix: mark languages as required, add required-field visual indicators on both forms
- checkbox-list.php: support $required prop → adds required + aria-required on fieldset
- add.php: languages checkbox now marked required (matches server-side validation)
- partage/index.php: same for student form
- admin.css: dashed border on required inputs, bold labels, red asterisk via :has(), "Champs obligatoires" note
- Both forms now show "* Champs obligatoires" note at top

Server-side required fields = titre, auteurice, synopsis, année, orientation, ap, finality, languages (≥1), access_type_id, confirmation_email. All now have required attribute + visual asterisk.
2026-04-20 16:19:55 +02:00
Pontoporeia 75f808bee4 feat: extract MediaController, wire into Dispatcher, delete media.php 2026-04-20 12:32:00 +02:00
Pontoporeia c4705f6265 docs: add bookmarklet for auto-filling TFE test form
- bookmark.md with draggable link + readable source + lookup table reference
- all field selectors match actual form name attributes and schema IDs
2026-04-15 14:24:44 +02:00
Pontoporeia f4aba500e6 feat: student mode support for thanks page (admin-auth only)
- add hidden student_mode field in add.php form
- pass mode=student through redirect to thanks.php in formulaire.php
- thanks.php renders clean student thank-you page (no header, centered button)
- add CSS for .thanks-student-page, .btn-new-form, .thanks-success, .thanks-error
- admin auth always required; student mode is purely UI variant on the physical machine
2026-04-15 14:24:44 +02:00
Pontoporeia 3cd96ed28a Deduplicate and standardise documentation
- Consolidate 36 markdown files → 14 (plus TODO.md)
- Merge overlapping docs into authoritative files:
  - database.md (from DATABASE_SPECIFICATION + QUICK_SCHEMA_REFERENCE + DATABASE_CONFIG + SETUP)
  - deployment.md (from SERVER_SETUP + COMPLETE_DEPLOYMENT_GUIDE + DEPLOYMENT_STEPS)
  - security.md (from SECURITY_ANALYSIS + TODO.SECURITY)
  - development.md (from DEVELOPMENT_GUIDE + LIVE_RELOAD_SETUP + TEST_CENTRALIZATION)
  - migration-history.md (from 11 past migration docs)
- Standardise all filenames to lowercase
- Remove non-doc files (Context.md research notes, chat export)
- Remove superseded docs (SECURITY.md pre-SQLite, SECURITY_IMPLEMENTATION, README_SECURE_SEARCH)
- Fix stale cross-references
2026-04-15 14:24:44 +02:00
Théophile Gervreau-Mercier 5c5054d744 Investigating VM crash 2026-04-13 11:12:12 +02:00
Pontoporeia 480451aa2b replace EasyMDE (333KB) with OverType (118KB) in pages-edit.php
- Remove easymde.min.js (320KB) and easymde.min.css (13KB)
- Vendor overtype.min.js (118KB, v2.3.5)
- Replace <textarea name=content> + 60-line toolbar/SVG init with:
  - <input type=hidden name=content> for form submission
  - <div id=editor> as OverType mount target
  - 6-line init: value from hidden input, onChange syncs it back
- Net saving: ~215KB assets, ~54 lines of inline JS
2026-04-06 15:33:08 +02:00
Pontoporeia bf2594112b fix serve recipe: filter output to Development Server start + [200] requests only
refactor: unify CSS color variables across public and admin

- Replace old variable structure with new standardized naming:
  - Background: --bg-primary, --bg-secondary, --bg-tertiary, --bg-active
  - Text: --text-primary, --text-secondary, --text-tertiary
  - Border: --border-primary, --border-secondary
  - Status: --success, --error, --warning
  - Accent: --accent-primary, --accent-secondary, --accent-foreground, --accent-muted
- Remove admin-specific color variables (--admin-*)
- Update all CSS files to use shared variables:
  - variables.css, common.css, main.css, admin.css
  - tfe.css, search.css, apropos.css, system.css, colors.css
2026-04-02 17:22:51 +02:00
Pontoporeia 2ec5a7f38f docs: ORM assessment — verdict: keep raw PDO, no ORM needed 2026-03-28 13:49:51 +01:00
Pontoporeia 7208292c0e deploy-nginx: add recipe, upload scripts to /tmp, print sudo instructions 2026-03-02 16:08:45 +01:00
Pontoporeia e4b2205eac fix rsync permissions: setup-server.sh with setgid dirs, exclude .claude/.pi 2026-03-02 16:08:45 +01:00
Pontoporeia 52978aa658 ops: simplify justfile, guard deploy-db, extract scripts, fix .gitignore 2026-03-02 16:08:45 +01:00
Théophile Gervreau-Mercier 87971f9c23 refactor: extract templates from public/
- Created /templates for main site (header.php, footer.php)
- Created /templates/admin for admin section (head.php, footer.php)
- Removed /public/includes and /public/admin/inc
- Updated all references in code and docs
- Tests passing ✅

Cleaner separation: /public only contains web-accessible files (PHP entry points + assets)
2026-02-12 12:15:41 +01:00
Théophile Gervreau-Mercier 7fca85d1c1 refactor: rename database → storage
More semantically accurate: contains SQLite files, schema, fixtures, test data.
Updated all references in code, scripts, docs.
2026-02-12 12:12:58 +01:00