# How it Works
Project Forge WMS technical and operational architecture
System Update installs an approved Project Forge WMS GitHub Release on a staging or production server. It downloads a packaged, checksummed release. It does not run git pull, require a Git working tree, copy staging files to production, or invoke Plesk Git deployment.
Developer → Git tag → GitHub Release → Staging → Production
Staging and production independently download the same immutable release assets from GitHub.
Component | Responsibility |
|---|---|
| Application version, numeric build, requirements, database version, release date, and release notes. |
| Validates the tag, builds the ZIP, calculates SHA-256, and creates a GitHub prerelease. |
| Administrator UI, AJAX endpoints, release discovery, validation, installation, backup, and status. |
| CLI worker that claims and executes one queued update job. |
| Stores queued, running, completed, and failed jobs. |
| Private downloads, extraction, backups, locks, logs, and installed-file inventory. |
| Private channel and GitHub token shared by web PHP and the CLI worker. |
Channel | Eligible releases | Use |
|---|---|---|
| Non-draft prereleases and stable releases | Test before production approval. |
| Non-draft stable releases only | Install explicitly promoted releases. |
Every new tag is published as a prerelease. After staging installs and approves it, an operator edits the same GitHub Release and clears its prerelease flag. Promotion must not create another tag, rebuild the ZIP, replace an asset, or change the checksum.
modules/system_update/ajax/check_update.php.A release is newer when its numeric build is greater, or when builds tie and its semantic version is greater.
Read-only: Check for Updates does not modify files or queue installation.
ajax/start_update.php validates POST, authorization, CSRF, tag, channel, and concurrency.system_update job with status queue.job_status.php. Polling only reads status; it does not execute the job.ScheduleScripts/system_update.php.Plesk: use Scheduled Task type Run a PHP script, not Run a command. Command tasks are chrooted and may not contain PHP.
Script: ScheduleScripts/system_update.php
PHP: 8.5
Schedule: * * * * *
Phase | Operation |
|---|---|
download | Resolve metadata and download ZIP/checksum using authenticated GitHub asset API URLs. |
verify | Compare ZIP SHA-256 with the published checksum. |
extract | Reject traversal, absolute paths, unsafe links, and size/count violations; extract privately. |
preflight | Validate runtime, protected paths, storage placement, package layout, disk space, and migrations. |
backup | Back up managed overwritten/removed files and record new files. |
install | Overlay managed files and remove only obsolete files proven by a trusted inventory. |
migrate | Run pending SQL migrations when present. |
post-update | Verify required files and installed manifest; write new inventory. |
cleanup | Remove temporary data and release the lock. |
complete / failed | Record terminal state and administrator message. |
httpdocs and never returned to the browser.DOCUMENT_ROOT.The private configuration file returns this array:
return [
'channel' => 'staging', // production on production
'github_token' => 'TOKEN_VALUE',
];
Recommended private-config mode: 0640, owned by the website user and subscription group.
APP_ROOT/config/system_update.php
APP_ROOT/storage/system_updates/downloads/
APP_ROOT/storage/system_updates/extracted/
APP_ROOT/storage/system_updates/backups/
APP_ROOT/storage/system_updates/locks/
APP_ROOT/storage/system_updates/logs/
APP_ROOT/ScheduleScripts/system_update.php
Job logs use storage/system_updates/logs/{job_id}.log.
Before migrations start, rollback attempts to restore overwritten files, remove newly created managed files, and restore obsolete managed files removed during installation.
Database: updater file backups are not database dumps. SQL migrations are not automatically rolled back and may partially apply. A verified external database backup and recovery plan are required before migrations.
done and phase is complete.