Commit Graph
85 Commits
Author SHA1 Message Date
Pontoporeia 554ba3ee8d fix(admin): stop logging out active long-form work; raise idle timeout to 4h
The admin idle timeout (30 min) was refreshed only by navigations and HTMX
requests. During long encoding sessions on an open form there are none, so
an actively-typing admin was logged out mid-work after ~30-45 min.

Add an activity-driven keepalive:
- /admin/session-keepalive.php: 204 when authenticated (refreshes
  admin_last_activity via AdminAuth::isAuthenticated()), 401 otherwise.
- admin-session-keepalive.js: marks activity only on real user input
  (pointer/keyboard/input/scroll/wheel/touch/focus) and pings at most once
  per 5 min while the tab is visible. A genuinely idle tab never pings, so
  the idle timeout still applies.

Raise the idle window 30 min -> 4 h: for a single-/few-admin back-office
whose main workflow is data entry, 30 min still kicked admins who stepped
away mid-form. With the keepalive in place, 4 h means "no interaction at
all", not "no navigation". Absolute timeout stays 12 h.

Also fix session ID rotation, which never fired: it used
`$absolute % IDLE_TIMEOUT_SECONDS === 0`, i.e. required a request to land
exactly on a multiple of the interval relative to login time. Replaced with
an explicit admin_last_rotation timestamp and a ROTATION_INTERVAL_SECONDS
(30 min) constant decoupled from the idle timeout, so raising the idle
window does not widen the fixation/replay window.

Refactor AdminAuth::enforceSessionTimeout() to return bool instead of
redirecting/exiting, so the keepalive endpoint can report 401 cleanly
rather than letting fetch follow a redirect to the login page.

Smoke test (just smoke-session-keepalive) covers activity refresh, 2 h idle
accepted, rotation firing, idle rejection+destruction, and unauthenticated
rejection. Docs updated.
2026-09-18 16:26:49 +02:00
Pontoporeia b1715b210d fix(deploy): restore www-data ownership after deploy-code to prevent HTTP 500 2026-09-18 16:26:49 +02:00
Pontoporeia 64fd92b913 test-env: podman-compose fresh-Debian harness + ssh/rsync deploy shims
Add a test environment that simulates a blank Debian trixie box (systemd
+ sshd container) and routes the project's real 
📦 Linting CSS + JS (biome)…
Checked 71 files in 140ms. No fixes applied.

📦 Building CSS bundles…
🎨 Building CSS bundles…

  ✓ base.min.css (22,317 bytes)
  ✓ admin.min.css (55,602 bytes)
  ✓ form.min.css (41,855 bytes)
  ✓ public.min.css (4,310 bytes)
  ✓ tfe.min.css (9,089 bytes)
  ✓ repertoire.min.css (13,166 bytes)
  ✓ content-page.min.css (3,683 bytes)
  ✓ not-found.min.css (672 bytes)
  ✓ system.min.css (7,408 bytes)
  ✓ file-access.min.css (3,733 bytes)
  ✓ form-base.min.css (19,110 bytes)
  ✓ partage-form.min.css (37,229 bytes)

✅ CSS bundles done — 218,174 bytes total


📦 Building JS bundles…
📦 Building JS bundles…

  ✓ admin.min.js (60,911 bytes)
  ✓ public.min.js (22,022 bytes)
  ✓ form.min.js (41,547 bytes)
  ✓ partage.min.js (42,441 bytes)

✅ JS bundles done


✅ Build complete


              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=461/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=458/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=411/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=411/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=401/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=360/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=325/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=319/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=309/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=302/469)
              0   0%    0.00kB/s    0:00:00 (xfr#0, to-chk=280/469)
            700   0%    0.00kB/s    0:00:00  
         55,602   1%   52.36MB/s    0:00:00 (xfr#1, to-chk=265/469)
         55,602   1%   52.36MB/s    0:00:00 (xfr#1, to-chk=250/469)
        116,513   2%  110.45MB/s    0:00:00 (xfr#2, to-chk=264/469)
        138,830   2%  131.73MB/s    0:00:00 (xfr#3, to-chk=263/469)
        142,513   2%  135.24MB/s    0:00:00 (xfr#4, to-chk=262/469)
        146,246   2%  138.80MB/s    0:00:00 (xfr#5, to-chk=261/469)
        165,356   2%  157.03MB/s    0:00:00 (xfr#6, to-chk=260/469)
        207,211   3%  196.94MB/s    0:00:00 (xfr#7, to-chk=259/469)
        248,758   4%  236.57MB/s    0:00:00 (xfr#8, to-chk=258/469)
        249,430   4%  237.21MB/s    0:00:00 (xfr#9, to-chk=257/469)
        286,659   5%  272.71MB/s    0:00:00 (xfr#10, to-chk=256/469)
        329,100   5%  313.19MB/s    0:00:00 (xfr#11, to-chk=255/469)
        333,410   6%  317.30MB/s    0:00:00 (xfr#12, to-chk=254/469)
        355,432   6%  338.30MB/s    0:00:00 (xfr#13, to-chk=253/469)
        368,598   6%  350.85MB/s    0:00:00 (xfr#14, to-chk=252/469)
        376,006   6%  357.92MB/s    0:00:00 (xfr#15, to-chk=251/469)
        385,095   6%  366.59MB/s    0:00:00 (xfr#16, to-chk=250/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=250/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=235/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=230/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=193/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=192/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=189/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=156/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=156/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=147/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=135/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=134/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=129/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=120/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=93/469) 
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=78/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=77/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=71/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=71/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=64/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=43/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=39/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=34/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=33/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=25/469)
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=8/469) 
        385,095   6%    2.96MB/s    0:00:00 (xfr#16, to-chk=0/469)
📋 Deploying nginx configuration…
xamxam.conf

sent 145 bytes  received 125 bytes  540.00 bytes/sec
total size is 10,012  speedup is 37.08
deploy-server.sh

sent 1,089 bytes  received 107 bytes  797.33 bytes/sec
total size is 8,519  speedup is 7.12 recipes to it
via safe ssh/rsync shims, so setup scripts can be validated without touching
production. Includes provision-server-packages.sh, setup.sh/teardown.sh,
server Dockerfile + helper, and the rendered ssh config.

Validated end-to-end against the box:
- provisioning (apt nginx, php8.4-fpm, composer),
- scripts/setup-server.sh (group/user/dir bootstrap),
- just deploy-code (transfer; surfaced the deploy-code --chown regression).
2026-09-18 16:26:49 +02:00
Pontoporeia 3f352b0d26 feat(admin): cleanup page — remove 'Fichiers temporaires' level, promote sections to h2 TOC entries 2026-09-18 16:26:49 +02:00
Pontoporeia 1ed69a2c1a refactor(justfile): de-dup deploy-code, move nginx/setup to deploy-nginx 2026-09-18 16:26:48 +02:00
Pontoporeia fc66b37801 feat(home): htmx lazy-load cover images
Replace the eager <img> on the home page with an htmx placeholder <figure>
that fetches a /cover-fragment endpoint when it scrolls into view
(hx-trigger="revealed"), so heavy cover bytes load only on demand.
Add spinner + settle-fade transition CSS, and load htmx.min.js on home.
2026-09-18 16:26:36 +02:00
Pontoporeia 541470b9bb feat(provision): idempotent setup for local dev and remote server 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 30a16f9e9e fix: display db timestamps in Brussels time
(heure de dépôt was showing UTC)

- feat: add date_depot column (real TFE deposit date)
with CSV round-trip + Brussels→UTC sanitization
- fix: keep PHP default tz at UTC to preserve token/share-link
 expiry consistency; convert to Brussels only in db_datetime()
2026-09-18 16:26:36 +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 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 912b38583b Add --quiet flag to build.mjs for cleaner 'just dev' output 2026-07-08 13:50:03 +02:00
Pontoporeia 3e93150c76 justfile: standardise test recipes to lint-php/lint-css/lint-js/test + add fix recipe
- Removed ambiguous aliases: phpstan, cs-check, syntax
- Split lint-biome into lint-css and lint-js with correct paths
- Added lint meta-recipe and fix recipe (biome --unsafe + php-cs-fixer)
- Fixed FormBootstrap dead null check, CSS shorthand override bug
- Updated phpstan baseline, suppressed noDescendingSpecificity/noInnerDeclarations
- Applied ~74 biome auto-fixes across CSS/JS
2026-07-05 11:07:41 +02:00
Pontoporeia 34b5d3e585 justfile: standardise test recipes to lint-php/lint-css/lint-js/test + add fix recipe
- Removed ambiguous aliases: phpstan, cs-check (both pointed to lint-php which
  also ran php-cs-fixer, making the names misleading)
- Removed syntax (php -l) — redundant, phpstan already catches parse errors
- Split lint-biome into lint-css and lint-js with correct paths
- Added lint meta-recipe that runs all three linters
- Added fix recipe: biome check --write (CSS/JS format+lint) + php-cs-fixer fix (PHP)
- Updated build-lint to delegate to lint-css + lint-js
2026-07-05 10:50:42 +02:00
Pontoporeia 6ecd3d4540 Fix biome lint errors: remove duplicate CSS properties, apply safe auto-fixes
CSS:
- Remove duplicate 'background' fallbacks in base.css, header.css, search.css
  (solid color declared before gradient — gradient always wins)
- Remove duplicate 'padding' in admin.css .admin-import-log

JS (biome --write safe fixes applied):
- function() → arrow functions in all IIFEs and callbacks
- forEach/callback → arrow functions
- evaluePtrn → parseInt(x, 10) in admin-contacts-form.js
- Cleaned label text in build.mjs lint step

Remaining warnings are intentional: !important overrides, descending
specificity (admin.css cascade), noUnusedVariables (functions exported
to window/onclick), useTemplate style preference.
2026-06-24 13:57:00 +02:00
Pontoporeia 9f8a4be84e Add dev-watch recipe with chokidar-cli for live rebuild on CSS/JS changes
- just dev now spawns a background chokidar watcher alongside the PHP server
- CSS/JS changes auto-rebuild into dist/ (~200ms per rebuild)
- just stop kills both the PHP server and the watcher
- just dev-watch still available standalone for split-terminal workflows
- chokidar-cli added as devDependency
2026-06-24 13:12:41 +02:00
Pontoporeia 20fe4b6c8c Add biome + rolldown + lightningcss build pipeline for JS/CSS bundling & minification
- package.json with biome, rolldown, lightningcss devDependencies  
- biome.json: add CSS formatter support
- scripts/build-css.mjs: lightningcss resolves @import chain, bundles/minifies CSS  
- scripts/build-js.mjs: rolldown per-entry JS bundling (no code splitting)
- scripts/build.mjs: orchestrator for both CSS + JS
- scripts/check-build.mjs: staleness checker for CI/deploy guard
- justfile: add build, build-css, build-js, build-install, build-check recipes
- justfile: deploy recipe now runs build before deploy-code
- head.php + form-page.php: use dist/base.min.css instead of style.css
- All controllers + FormBootstrap: reference dist/*.min.{css,js}
- admin footer: load admin.min.js for all admin pages
- repertoire: use public.min.js instead of individual app JS files
- Fix stray '}' syntax error in admin.css line 305
- .gitignore: add app/public/assets/dist/
2026-06-24 13:09:50 +02:00
Pontoporeia 03c9c3566f Add SQLite indexes for contenus page language/tag queries + WIP: Peertube orphans, dialogs, contact decoupling, context note, finality types 2026-06-21 16:36:34 +02:00
Pontoporeia 928e074d24 fix: update dev server PHP limits in justfile to match large video uploads
The just dev command hardcodes upload_max_filesize=512M and
post_max_size=520M via -d flags, which override .user.ini.
Raised to 8192M/8704M to match the JS-side 8GB video size
caps.  Also raised max_execution_time and max_input_time to
600s to accommodate large file transfers and PeerTube uploads.
2026-06-15 16:35:13 +02:00
Pontoporeia d588ae004d Reintroduce TFE duration metadata: DB columns, form fields, controllers, views, and migration
Add 'unsafe-eval' to CSP script-src directives (htmx requires Function())
2026-06-15 15:56:52 +02:00
Pontoporeia 00fed5f0e3 Add periodic cleanup of orphaned drafts: cleanup job, just command, deploy cron 2026-06-11 13:05:34 +02:00
Pontoporeia a45a2c9ac4 Changed dev serve recipe to be just dev 2026-06-10 00:17:41 +02:00
Pontoporeia d33a56981e Fix: deploy-deps patches classmap path (app/src/ → src/) for flat server layout before composer install 2026-05-31 17:46:02 +02:00
Pontoporeia 47405e5334 Fix: split deploy recipe into deploy-code/deploy-deps/deploy-migrate; deploy-deps always syncs composer.json+composer.lock, runs composer install only when lockfile checksum changed 2026-05-31 17:46:02 +02:00
Pontoporeia 4e409c409d Fix: add ZipArchive guard to export-files.php, add composer install step + composer.json sync to deploy recipe 2026-05-20 12:49:23 +02:00
Pontoporeia a047062d87 Phase 4 cleanup: migrate old tests to PHPUnit, add ErrorHandler/PureLogic/SearchController tests, remove app/tests/, update justfile test target 2026-05-20 01:55:58 +02:00
Pontoporeia 728f05502c Combine phpstan, cs-check, cs-fix into lint-php recipe; fix lint issues + test failures + duplicate detection bug 2026-05-20 00:31:19 +02:00
Pontoporeia defc919cd0 cleanup modal: list stale files to remove; storage restructure: documents/ → {objet}/ 2026-05-19 23:58:51 +02:00
Pontoporeia 4da317de0a deploy: remove .env from generic file perm check, remove router.php check (dev-only file) 2026-05-19 23:58:51 +02:00
Pontoporeia 2cb8d71fe9 Fix dialog margins, add admin-dialog__body/styles, give trash page horizontal margins 2026-05-19 23:58:51 +02:00
Pontoporeia ae9a8a62c0 deploy: exclude storage/{tmp,documents,theses,triage,backups,logs} from rsync + fix .env perm check to 640 2026-05-19 00:33:28 +02:00
Pontoporeia 1ff3c70ebe fix: track vendor JS files, add 'unsafe-inline' to public CSP, gitignore filepond tmp
- Track vendor JS files (filepond, htmx, overtype) that were moved
  to app/public/assets/js/vendor/ but never tracked → missing from deploys
- Add script-src 'self' 'unsafe-inline' to main CSP header so public
  pages (jury fieldset, repertoire, partage) can use inline scripts
  and onclick handlers
- Add storage/tmp/filepond/* to .gitignore with .gitkeep, and exclude
  from deploy rsync to avoid syncing local test uploads to production
2026-05-19 00:08:06 +02:00
Pontoporeia 04094d802d fix: harden security based on pentest scan findings
- Add Content-Security-Policy to main nginx server block (was only on /admin/)
- Add Cross-Origin-Opener-Policy and Cross-Origin-Resource-Policy headers
- Add includeSubDomains to HSTS header
- Set HttpOnly, Secure, SameSite=Lax session cookie params on public pages
  (AdminAuth already hardens the /admin session with SameSite=Strict)
- Update xamxam.conf.reference and SECURITY_HEADERS.md to match
2026-05-19 00:08:06 +02:00
Pontoporeia cb6394e119 add incremental migration runner to deploy recipe — execute whole SQL files (not semicolon-split), catch 'no such column' for idempotent re-runs, merge into migrate.sh 2026-05-19 00:08:06 +02:00
Pontoporeia c1960d224b fix deploy: multiple deploy recipe fixes — upload xamxam.conf before deploy-server.sh, sudo rsync for chown, migrate.sh via sqlite3, chmod WAL/SHM sidecar files, deploy-verify-permissions awk fix, .env sudo perms 2026-05-19 00:08:06 +02:00
Pontoporeia 206a6427e7 style: unify recap+edit file figure styling — two-column grid dl, vertical spacing, admin-back-btn sizing, standardise file display and delete-to-trash SVG icons 2026-05-19 00:08:06 +02:00
Pontoporeia 28ef35dce5 fix: make schema.sql fully idempotent — add IF NOT EXISTS to all CREATE INDEX, CREATE TRIGGER, and CREATE VIEW statements 2026-05-19 00:08:06 +02:00
Pontoporeia 973444bdbb feat(backup): deploy cron-based SQLite backups to production
- Create deploy/xamxam-backup.cron with hourly (30d) and daily (90d) jobs
- Add just recipes for deploying backup infrastructure:
  - deploy-backup-script: upload backup-sqlite.sh to /usr/local/bin
  - deploy-backup-cron: install cron.d file, create /var/backups/xamxam + log
  - deploy-backup: one-shot convenience (script + cron)
  - deploy-check-backup-log: tail the backup log
  - deploy-list-backups: ls remote backup directory
  - trigger-backup: manually invoke backup on server
  - test-restore: scp, gunzip, verify a remote snapshot
- Add reminder to run deploy-backup after first deploy
- Replace 'Contenu (Markdown)' label with 'Syntax Markdown' link (cheatsheet)
2026-05-19 00:08:06 +02:00
Pontoporeia be50ac5eb0 fix(production): fix multiple remote server errors from nginx logs
- Fix 413 Request Entity Too Large: bump client_max_body_size to 256M,
  PHP post_max_size/upload_max_filesize to 256M, fastcgi timeouts to 300s
- Fix missing v_smtp_active view: add IF NOT EXISTS to all CREATE VIEW
  statements in schema.sql for idempotent migrates
- Fix bars.svg 404: create animated SVG spinner in app/public/assets/img/
- Fix nginx rate limiting: increase admin zone from 60r/m (1 r/s) to
  300r/m (5 r/s) with burst=30 to handle ~11 concurrent HTMX fragment
  GETs on contenus.php page load
- Add deploy-nginx recipe to justfile for uploading nginx config to server
- Database readonly issue mitigated by existing --chown + deploy-server.sh
  permissions fix
- Add comprehensive PHP/JS debugging logs for settings checkboxes:
  per-field raw POST values in error_log, console.log on htmx:beforeSend,
  htmx:sendError, htmx:afterRequest, toast lifecycle
- Fix toast auto-remove script: use getElementById with unique ID instead
  of querySelector which could remove wrong toast on rapid clicks
2026-05-19 00:08:06 +02:00
Pontoporeia 72f7192156 feat(deploy): add deploy-verify-permissions recipe + upload/run deploy-server.sh before verification + run migrations in deploy 2026-05-19 00:08:06 +02:00
Pontoporeia 3136fa7113 fix: settings checkboxes — fix unchecked state handling, split into separate forms to avoid cross-resets, use HTMX auto-save with hidden value=0 inputs 2026-05-19 00:08:06 +02:00
Pontoporeia 926659087f feat: implement SQLite backup & data integrity plan (Phases 2-4) 2026-05-19 00:08:06 +02:00
Pontoporeia c0163ca4d5 fix: exclude entire var/ from rsync --delete to preserve logs 2026-05-19 00:08:06 +02:00
Pontoporeia 8db7b6e9eb feat: FilePond production hardening — extension-based validation, server-side size limits (2GB), annexe validation, drop accept attributes, FilePond file styling 2026-05-19 00:08:05 +02:00
Pontoporeia 11e61226e2 fix: justfile shebang recipes indentation (spaces → tabs) 2026-05-13 17:59:13 +02:00
Pontoporeia 95fcbc919a Remove required from all admin add/edit form inputs
- Skip required-field validation for orientation/ap/finality/licence/jury in admin add+edit
2026-05-13 17:59:13 +02:00
Pontoporeia e3896811c4 Fix migrations and deploy issues + errors + linting
- scan both pending/ and applied/ dirs so remote catch-up works
- fix remote 500s: run.php handles per-statement errors so VIEW rebuilds run after duplicate columns; replace mb_strimwidth with substr (no mbstring extension on server)
- add missing migration: 015_license_custom.sql (column existed in schema.sql but was never migrated)
- remote: fgetcsv enclosure single-char + AdminLogger permission-denied
guard + deploy always migrates
- fix admin-filters wrapping: restore flex-wrap, flex-basis on
inputs/selects, shrink-protect buttons
- fix phpstan: remove redundant ?? [] after isset guard in
ThesisEditController
- biome: exclude vendored min.js via includes patterns;
lint whole js dir; modernise beforeunload-guard.js
2026-05-08 22:58:05 +02:00