Skip to content

Development

Source layout

The service is procedural PHP with shared functions loaded by lib/bootstrap.php. UI entry points live at the root and in reports/; JSON endpoints live in api/ and action/. The report engine is an externally supplied WAR. The lone ReportServlet.java is not accompanied by its referenced classes or a Java build manifest.

No Composer/npm/Maven/Gradle manifest, lockfile, automated test suite, test configuration, linter configuration, or CI definition exists in the service directory.

Observed coding standards

  • Files use declare(strict_types=1) where modernized and procedural jrs_* helpers loaded from lib/bootstrap.php.
  • Database values use pg_query_params(); dynamic application table names go through jrs_table().
  • Report keys must pass jrs_report_key()/jrs_is_valid_report_key().
  • HTML output must use jrs_html() and JSON endpoints set an explicit content type.
  • Apply service-level and report-level ACL helpers before protected operations.
  • Keep report definitions backward-compatible with accepted aliases (parameters/params, datasource/datasourceName) where existing readers support them.
  • Treat SQL-backed parameter definitions as trusted code and use read-only report datasource roles.

No formal formatter, PHP style guide, static-analysis baseline, or enforced lint policy was found.

Local setup

  1. Create the application database and apply database/schema.sql.
  2. Replace the hardcoded secret in config.php; do not rely on legacy JRS_DB_* variables.
  3. Run Tomcat/Compose and ensure the service can reach 127.0.0.1:9099.
  4. Start PHP:
php -S 127.0.0.1:8080
  1. Visit /reports/index.php.

With no resolvable Central DSN, auth code enters local-development mode and grants an administrator identity. Never use that configuration to validate production authorization.

Manual verification

There is no automated test command. A proportionate source-backed smoke test is:

php -l config.php
php -l lib/bootstrap.php
php -l reports/execute_report.php
php -l scripts/run_schedule.php
docker compose -f docker/report-server/docker-compose.yml config

Then verify:

  1. App DB connectivity and all five tables.
  2. Datasource save and context.xml generation.
  3. Tomcat startup and JNDI lookup.
  4. Report publish, JSON/JRXML persistence, HTML render, PDF and XLSX export.
  5. Central login, service permission, report permission, and anonymous Public behavior.
  6. Manual schedule run, output file, execution history, and email path.
  7. On Linux, timer creation, symlinks, enablement, execution, and cleanup.

Debugging

  • PHP/auth/resource/scheduler errors use the PHP error log.
  • JRS_AUTH_DEBUG=1 or JRS_AUTH_LOGIN_TRACE=1 enables [jrs-auth] logs.
  • JRS_RESOURCE_SYNC_VERBOSE=1 logs existing Central resources.
  • Schedule runs append to schedules/logs/schedule-<id>.log and emit CLI output to systemd journal/its configured append target.
  • Tomcat logs servlet report paths and stack traces.
  • debug/session.php returns a limited auth probe only when debug is enabled.

debug.php exposes a raw session cookie/hash, hardcoded database credential, and user/session records. debug/param_pipeline_php.php reflects request values. Remove or block both in any non-isolated environment.

Useful runtime checks:

systemctl status jrs-schedule-<id>.timer
systemctl cat jrs-schedule-<id>.service
journalctl -u jrs-schedule-<id>.service
docker compose -f docker/report-server/docker-compose.yml logs report-server

Report development

Report definitions live in reports/json/*.report.json; JRXML/compiled files live in docker/report-server/reports/. Report keys are normalized to lowercase letters, digits, _, and -.

SQL-backed select parameters use a source beginning with sql: and execute directly against the selected report datasource. The SQL is trusted definition content and is not parameterized. Use a read-only datasource role, review report definitions as code, and do not incorporate user input into those queries.

The viewer forwards non-reserved parameters to Jasper. The servlet source treats repeated values as collections and has an explicit collection override only for p_boro.

Adding an endpoint

  1. Add the PHP entry point under api/ for a public JSON integration route, action/ for an existing UI form contract, or reports/ for report runtime/management behavior.
  2. Load lib/bootstrap.php, enforce an explicit request method, and set response content types.
  3. Choose the required gate: Central login, platform admin, service:jasper_reports, and/or jasper_report:<key>.
  4. Validate and normalize all path/query/form values; use parameterized SQL and safe filesystem path helpers.
  5. Define stable success and error status codes. Avoid the current legacy pattern of 200 with success:false for new APIs.
  6. Add focused tests or, until a test harness exists, a repeatable curl smoke test covering success, method rejection, invalid input, missing auth, denied ACL, and dependency failure.
  7. Update docs/api.md, docs/openapi.yaml, examples, CLI mapping, and configuration documentation.

Adding a database table or column

  1. Design explicit types, nullability, defaults, checks, foreign keys/delete behavior, and indexes.
  2. Add an upgrade migration before changing runtime queries. database/schema.sql alone cannot upgrade existing tables, and no migration runner currently exists.
  3. Update database/schema.sql so fresh installs reach the same final schema.
  4. Use jrs_table() for application-schema qualification and parameterized queries for values.
  5. Test both a fresh database and every supported prior schema; include backup and rollback instructions for operators.
  6. Document the model, relationships, indexes, initialization, and compatibility behavior in docs/database.md.

Change and release process

The Git history for this service begins in May 2026. There are no release tags, release manifest, packaged artifact procedure, or version constant. Before a release:

  1. Review PHP syntax and manual smoke tests.
  2. Validate schema compatibility, especially scheduler columns.
  3. Rotate/remove secrets and regenerate Tomcat context.
  4. Pin and record the WAR/JDBC/container artifacts actually deployed.
  5. Back up PostgreSQL and filesystem state.
  6. Record user-visible changes in docs/changelog.md.
  7. Create a version tag only through the repository's agreed release process.

The 1.0.0 changelog entry is a documentation baseline requested for this repository, not evidence of an existing product release or tag.