How it Works
Project Forge WMS technical and operational architecture
1. Purpose and Deployment Model
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.
2. Major Components
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. |
3. Release Channels and Immutability
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.
4. Check for Updates
- The browser calls
modules/system_update/ajax/check_update.php. - The endpoint validates the local manifest.
- The GitHub Releases API is queried using the private token.
- Drafts and releases disallowed by the configured channel are removed.
- The updater requires an exactly named ZIP and SHA-256 asset.
- The remote manifest is validated and compared with the local manifest.
- Update is enabled only when a valid newer release is identified.
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.
5. Queue, Monitor, and Execute
ajax/start_update.phpvalidates POST, authorization, CSRF, tag, channel, and concurrency.- It creates a
system_updatejob with statusqueue. - The browser polls
job_status.php. Polling only reads status; it does not execute the job. - Plesk runs
ScheduleScripts/system_update.php. - The worker atomically claims the job and executes the update service.
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: * * * * *
6. Installation Phases
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. |
7. Security Controls
- Token and channel are stored outside
httpdocsand never returned to the browser. - Updater storage must resolve outside
DOCUMENT_ROOT. - Downloads require HTTPS, approved GitHub hosts, authenticated asset API URLs, and approved redirect hosts.
- SHA-256 is verified before extraction.
- CSRF is mandatory for the update POST.
- Atomic job claiming and a lock prevent concurrent installation.
- Configuration, uploads, attachments, environment files, storage, logs, and backups are protected.
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.
8. Storage and Logs
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.
9. Backup and Recovery Limits
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.
10. Definition of Success
- Job status is
doneand phase iscomplete. - Local manifest equals the installed release version and build.
- A new check no longer offers the installed release.
- Protected paths and private configuration remain unchanged.
- Critical WMS smoke tests pass.
- The installed artifact checksum equals the approved GitHub checksum.
No comments to display
No comments to display