Application updates

Q-Putaway has two independent update paths.

1. Browser / PWA update (automatic)

When new static files are deployed, the service worker detects a new version and shows "A new version is available". Users choose Update now (warned first if a form has unsaved changes, and blocked while an operation is running) or Later. Only the screens and scripts in the browser are refreshed; obsolete caches are deleted. This never updates PHP files on the server.

2. Server update (Super Admin)

Administration → Updates shows the current version and schema version, the update history, and an optional "check for updates" (when updates.feed_url is configured; it never installs automatically).

Package format

A .zip containing:

  • manifest.json: {version, min_version, notes, files: [{path, sha256}]}
  • manifest.sig: a base64 Ed25519 detached signature of manifest.json
  • the files themselves

Applying

  1. Upload the package. Q-Putaway verifies the signature against updates.public_key in config/config.php, verifies every file hash and checks compatibility (min_version ≤ current < version).
  2. It refuses unsafe paths (.., absolute paths, backslashes, null bytes, dotfiles, config/, storage/), so configuration, uploads, backups and credentials are never overwritten.
  3. The package is staged in storage/updates/staging/.
  4. Apply (with password confirmation) first creates a database backup and a rollback archive of every file that will be replaced, then copies the files and runs pending migrations. The result is recorded in the update history and the audit log.
  5. Rollback restores the files from the rollback archive. Database changes from migrations need the pre-update backup to be restored.

Updates stay disabled until a public key is configured.

For the vendor: signing packages

php tools/keygen.php /secure/place/qputaway-update.key   # prints the public key → put it in config/config.php updates.public_key
php tools/build_update.php --key=/secure/place/qputaway-update.key --version=1.0.1 --min=1.0.0 --notes="Fixes" file1 file2 …
# or build from a git range:  --git=v1.0.0..HEAD

Keep the private key offline. Bump app/version.php (QP_VERSION, and QP_SCHEMA_VERSION when migrations are added) in every release.