Skip to content

Development guide

Setup

Use an isolated Linux VM when changing workers, systemd, filesystem permissions, or publishing. A PHP built-in server can support limited UI work, but it does not reproduce Apache prepending, systemd, FIFO, or service mount behavior.

  1. Create a disposable PostgreSQL/PostGIS database and apply installer/setup.sql once.
  2. Create a secret-free admin/incl/const.php matching configuration.md.
  3. Select local auth only for isolated development, or provide a development Central instance.
  4. Install PHP 8.1+ with extensions: pgsql, curl, yaml, zip, gd, ssh2, and sodium when testing secret helpers.
  5. Install worker dependencies only for the project types under test.

Do not develop against the checked-in credentials. Generated INI/YAML and rsync scripts contain plaintext passwords; keep the entire environment disposable.

Coding model

  • Pages live under admin/; mutations generally live under admin/action/.
  • Shared auth should enter through incl/geosync_auth_prepend.php.
  • Domain classes in admin/class/ accept a PostgreSQL connection and often owner/sharing context.
  • SQL uses the procedural pgsql API. Prefer pg_query_params for new code; much legacy SQL is string-built and should not be copied.
  • UI actions typically return {success, message} JSON.
  • Worker settings are persisted by daemon_Class into <id>.ini or <id>.yaml.
  • Service operations must go through the backend FIFO, not direct web-server systemctl execution.

Tests

There is no first-party automated test suite or test command. Files under vendor/**/tests test vendored dependencies and are not GeoSync tests; mtest.php is an ad-hoc script, not a harness.

Minimum change verification:

php -l path/to/changed.php

Then exercise on a disposable integration host:

  • unauthenticated, authenticated non-admin, and admin requests;
  • ownership checks and invalid IDs;
  • create/update/delete and generated config content;
  • FIFO command and systemd status;
  • first sync, update sync, single_run, and destructive force_init;
  • unavailable remote/PostgreSQL/upstream behavior;
  • logs and filesystem permissions.

For new code, introduce focused unit/integration tests with an explicit runner rather than treating manual QA as sufficient. No coverage threshold is currently defined.

Debugging

  • Enable PHP error logging in development, but never display errors or connection strings in production.
  • Inspect Apache/PHP logs, journalctl -u qz-sync-backend, journalctl -u '<type>-sync@<id>', /var/log/qz_sync_backend.log, and /var/log/qz_sync<id>.log.
  • Compare admin/incl/const.php, /etc/default/qz-sync-backend, service unit paths, and generated project files.
  • Run a worker as user quartz with one project ID only after redacting output and backing up data.
  • Query metadata and target PostGIS independently to distinguish control-plane from worker failures.
  • For proxy failures, verify the exact method/path allow-list and upstream ports. The checked-in analysis unit port does not match the PHP default.

Add an admin endpoint

  1. Add an action under admin/action/ and require incl/geosync_auth_prepend.php before application work.
  2. Start/ensure the session and require constants/classes.
  3. Enforce the required legacy access level and record ownership; Central mode currently maps authorized platform admins to that session.
  4. Validate method and all input. Use parameterized SQL and fixed allow-lists for identifiers/operations.
  5. Return a deliberate status code, content type, and stable JSON shape.
  6. Add the UI caller and integration checks.

If adding a path proxied by api/proxy.php, add it under the exact service and HTTP method in $allowed; unknown service/path combinations are intentionally rejected. Decide whether PHP handles it locally or forwards it, do not pass untrusted arbitrary upstream URLs, and update api.md plus openapi.yaml.

Add a database table

  1. Add an idempotent numbered SQL migration; do not edit only installer/setup.sql.
  2. Update installer/setup.sql so new installations reach the same final schema.
  3. Specify ownership, foreign keys, delete behavior, uniqueness, defaults, and indexes.
  4. Use a transaction where PostgreSQL permits it and provide a backup/rollback plan.
  5. Update classes/actions with parameterized queries and ownership checks.
  6. Test both clean install and upgrade from the previous schema.

There is no migration runner or schema-version table. Operators must apply migrations explicitly and record completion. The current sync_secrets class is incomplete because no DDL is supplied; add migration/setup DDL before using it.

Worker changes

Keep installer/ copies and usr-local-bin/ copies synchronized where both exist. Verify current deploy/ units and installer service templates. Preserve graceful SIGTERM behavior and avoid logging credentials. Any change to generated config keys must update project creation, daemon editing, workers, and this documentation.

Release process

No automated release workflow, version file, artifact build, or tags exist. Use this baseline process:

  1. Freeze scope and update changelog.md under an Unreleased section.
  2. Run PHP syntax checks and the manual integration matrix for all affected project types/auth modes.
  3. Validate clean schema plus every migration on backups or disposable databases.
  4. Review generated files and repository history for secrets; rotate any exposure.
  5. Confirm service units, external dependency versions, and rollback/backup steps.
  6. Move changelog entries to a dated semantic version, create an annotated tag, and publish deployment notes/artifacts through the organization’s approved process.

1.0.0 in the changelog is a documentation baseline because the repository has no tags; it is not evidence of a previously shipped artifact.