5.9 KiB
Maintenance and backup repairs — October 20, 2026
This follow-up addresses the three code findings in the production review. No schema migration is needed. Tests use disposable local databases, not the development or production database. Deployment and production-host acceptance work in that review still applies.
Editor replacement
- Removed the CKEditor 24 bundle and its references from all four alert/popover add/edit forms. Replaced it with locally hosted SunEditor 3.3.3.
- Current CKEditor requires a commercial license key or GPL-compatible usage;
neither was established for this project. The review allowed a maintained
replacement. SunEditor uses the MIT license, included verbatim in
THIRD-PARTY-NOTICES.md. No commercial key or runtime CDN is required. - Kept headings, bold, italic, underline, links, lists, font family/size/color, indentation, alignment, horizontal rules, tables, undo and redo. Upload and remote media tools are not enabled.
- Added the shared
js/rich-text.jsadapter. Save buttons stay disabled until initialization completes. Initialization failure or timeout produces a visible message. Saving copies editor HTML into the original form field; an empty editor remains an empty optional field. - Added versioned JavaScript/CSS, archive integrity and individual asset hashes
to
browser-dependencies.json. Source checks verify the installed asset hashes and removal of the old bundle. The release builder includes the replacement, its license and dependency metadata.Base::VERSIONchanged to1.01to refresh cached form scripts. - Browser coverage exercises actual add/save/reopen/edit flows for both forms, including legacy table markup, fonts, lists, links and text formatting; formatted paste; filtering scripts, event attributes and unsafe links; failed asset loading; and the existing content security policy.
- SunEditor 3 targets modern browsers (Chrome/Edge 119+, Firefox 125+, Safari 17.2+). Unusual legacy HTML may be normalized by its content model; arbitrary HTML is not promised to round-trip byte for byte. Existing server output protections remain necessary; client filtering is not a server trust boundary.
Upstream sources: SunEditor release, installation and license, CKEditor licensing.
Server-side maintenance validation
- Added
classes/MaintenanceValidation.php, shared by create and edit handlers inAlerts.phpandPopovers.php. - Alert titles and popover names/titles are required and limited to 100 Unicode characters. Optional popover placeholders allow 100 characters. Optional alert messages and popover HTML allow 1,000 characters, matching existing columns.
- Rejects malformed text, null bytes, and control characters in single-line fields. Required fields reject Unicode whitespace-only values. Limits count characters rather than UTF-8 bytes.
- Alert dates and times must be present and use exact
YYYY-MM-DDandHH:MMformats. Rejects invalid calendar dates, impossible times, nonexistent local daylight-saving times, years outside the database range, and expiration before the start. Equal start/expiration remains allowed. - Invalid requests return HTTP 422 with a specific error before any write. Title-only alerts and popovers without optional body text remain supported.
- Alert/popover lookup, update and deletion IDs now use strict integer validation. The popover uniqueness lookup still allows its create form's zero exclusion ID.
- Added direct HTTP tests that verify both rejection and unchanged table fingerprints. Fixed the isolated test fixture connection to use UTF-8 so Unicode assertions read the stored text correctly.
Backup memory usage and failure cleanup
- Added
classes/BackupValidation.php. Completion validation reads at most the final 8 KiB of the dump instead of loading the whole file into PHP memory. - Requires the completion comment at the end, rejects missing/truncated dumps, and accepts Windows or Unix line endings. Existing process exit-status, streaming checksum, atomic completion and protected output handling remain.
- Moved temporary output/credential creation into the cleanup-protected block and handles credential-file creation failure safely.
- Added a 64 MiB file test under a 16 MiB PHP memory limit, including checksum generation and measured peak-memory assertion. Additional tests cover missing, tiny and incomplete files and a completion comment before unfinished data.
- Deployment tests exercise a real scratch-database dump and a failed dump process, checking nonzero failure status and removal of temporary credentials, partial output and success metadata. Release tests verify the new files.
Verification
The full regression entry point is tests/run.py; it now includes the new
maintenance HTTP and bounded-memory backup suites. It also runs source validation,
authentication, authorization, club/ledger, concurrency, browser and deployment
checks. The complete run passed 374 checks plus five concurrency scenarios:
| Suite | Passed |
|---|---|
| Authentication service/templates | 49 |
| Maintenance unit checks | 52 |
| Authentication HTTP | 27 |
| Project HTTP | 99 |
| New maintenance HTTP | 47 |
| Production security and ledger | 42 |
| Restricted database privileges | 5 |
| Browser flows | 28 |
| Backup validation | 9 |
| Deployment tools/release packaging | 16 |
Source validation also passed for 44 PHP files, 56 JavaScript files and 39 XSL stylesheets, including jQuery and SunEditor integrity checks. The isolated loopback database server was stopped after the disposable databases were removed. No development database records, real passwords, production services or email recipients were changed by this work.