Files
JobcardSystem/docs/uat-checklist.md
T

12 KiB

JOBcard UAT checklist

Run this checklist against a production-like deployment over HTTPS with a fresh backup available. Record the date, application version, PHP/MariaDB versions, tester and evidence for each item. Do not record passwords, API keys or credential values in the evidence.

Pre-flight and deployment

  • The virtual host/document root is public/; the repository root, .env, SQL files and storage/ are not web-accessible.
  • .env is present outside the public root, has restrictive permissions (for example chmod 600 .env), and contains production-only values.
  • php bin/healthcheck.php passes with no secret values printed.
  • HTTPS is enabled and HTTP redirects to HTTPS; the certificate and hostname are valid.
  • A backup was taken before UAT and its location/time is recorded separately from this checklist.

Administrator

  • Sign in with the bootstrap Administrator account; invalid credentials are rejected.
  • The dashboard loads and the Administrator can view clients, jobcards, SLA data, reports and audit events.
  • Create, deactivate and reactivate a test Accounts user and a test Technician user.
  • Assign roles/permissions; verify an unauthorized permission is not granted by merely hiding a navigation link.
  • Assign a Technician to a test jobcard and verify the assignment is visible in the expected workflow.
  • Review audit events for login and test administrative changes; confirm timestamps and actor are present.
  • Verify sensitive credentials are masked by default, access is permission-controlled, and reveal/access is audited (where that module is enabled).

Accounts

  • Create and edit a client, including contact details and preferred contact method.
  • Add a primary contact and verify duplicate primary contacts are rejected.
  • Create a jobcard with client, priority and requested work; verify its reference number and initial status.
  • Assign a Technician, update the jobcard through the supported statuses, and verify status history.
  • Configure an SLA agreement and verify allocated/used/remaining hours and period boundaries.
  • View reports and export a report if permitted; verify exported data contains only intended fields and no internal notes or credentials.
  • Verify validation errors are understandable and do not discard unrelated entered fields.

Technician

  • Sign in as a Technician and verify only assigned jobcards are accessible.
  • Verify a Technician cannot access another Technician's jobcard by changing an ID in the URL or form payload.
  • View assigned work, update allowed status/work fields, and add technician notes.
  • Record a valid time entry and verify hours and SLA usage update correctly.
  • Verify invalid, negative, overlapping or unauthorized time-entry cases are rejected according to the configured rules.
  • Verify internal notes, credentials, user administration and unrestricted reports are not exposed to Technician accounts.

Security and recovery

  • Invalid and expired sessions redirect to login; logout invalidates the session.
  • Verify CSRF protection rejects missing or invalid tokens on every state-changing form.
  • Verify output escaping with a test value containing HTML/script characters; no script executes.
  • Verify prepared statements/parameterized inputs by testing quote and SQL-like characters in names, notes and searches.
  • Confirm login/session cookies use Secure, HttpOnly and SameSite settings appropriate to the deployment.
  • Confirm production error responses do not disclose stack traces, SQL, filesystem paths or secrets; server logs are access-controlled.
  • Confirm .env, backups and uploaded files cannot be downloaded through the web server.
  • Verify brute-force/rate-limit and account deactivation controls if configured by the host/application.

Reports

  • Run reports for an empty date range, a normal range and a boundary date; totals are deterministic and timezone expectations are documented.
  • Verify role-specific report visibility and filters; direct URL access cannot bypass authorization.
  • Verify CSV/other exports handle commas, quotes, line breaks and formula-like values safely.
  • Compare a report total with the underlying test jobcards/time entries and retain the comparison evidence.

Final-scope acceptance cases

Use distinct fixture IDs for each client and record expected/observed results without including secrets in evidence. The executable contract companion is php -d assert.exception=1 tests/FinalScopeIntegrationTest.php.

  • FS-01 — Technical information: Add valid hosting/VPN/domain/database/SSH/API metadata; verify labels and usernames are trimmed, supported categories are enforced, control characters/oversized notes are rejected, and display output contains metadata only (never a credential secret).
  • FS-02 — Contact actions: Edit a contact, promote a secondary contact, and delete a primary contact; verify duplicate names/emails are rejected, only same-client primary contacts are demoted, the lowest remaining same-client contact is promoted on primary deletion, and a client's sole contact cannot be deleted.
  • FS-03 — Time corrections: Correct date, duration, notes and SLA-counting state while retaining the original time-entry ID, jobcard ID and technician ID. Verify ownership changes, corrections to voided entries, invalid ranges and missing void reasons are rejected. Confirm the original and correction/void actor are retained by the deployment's audit trail.
  • FS-04 — Custom roles: Create a custom role, assign a least-privilege permission set, rename it and remove it; verify permissions are normalized/deduplicated, server-side authorization remains enforced on direct URLs/forms, and the Administrator role cannot be renamed, deleted or permission-edited.
  • FS-05 — Notifications: Trigger assignment, status-change and SLA-threshold events; verify normalized per-user rows, stable deduplication, inactive/unknown recipients skipped, mark-read changes only the authenticated user's row, and notification bodies contain no credential or internal-note values.
  • FS-06 — Report audience separation: Compare the same fixtures in client and internal reports/print/CSV output. Client audience must omit technician identity, internal notes, credentials and other operational-only fields; internal audience may retain authorized attribution. Direct report URLs and exports must enforce the same audience and role checks.
  • FS-07 — Technician scope: With two technicians and two clients, verify each technician can list/view/update only assigned jobcards and sees only their own time totals. Changing jobcard, client, attachment, credential, report or time-entry IDs must return the documented not-found/denied response without leaking metadata or mutating another technician's records.
  • FS-08 — CSRF and method checks: Submit missing and wrong CSRF tokens to login, logout, client/contact, jobcard/status/assignment/time, attachment, credential, SLA, notification and custom-role state changes; every request must be rejected before mutation (HTTP 419 or documented equivalent). Verify GET requests are read-only and logout is POST-only.
  • FS-09 — Attachment boundary: Attempt traversal names, executable/double extensions, MIME/signature mismatches, oversized files and client-visible files without explicit approval; each must be rejected before storage. Upload a valid image/PDF and verify a generated server filename, validated MIME, X-Content-Type-Options: nosniff, no executable download behavior, and cross-client/jobcard access denial.
  • FS-10 — Credential boundary: Create a canary credential and verify the database stores only secret_ciphertext, normal views show a mask, reveal is permission-controlled, client-bound, audited and returned with Cache-Control: no-store; a different client/credential ID cannot reveal it. Do not put the canary in screenshots, tickets or UAT evidence.
  • FS-11 — Production healthcheck: Run php bin/healthcheck.php with valid configuration and capture exit status plus status-only output. Verify all current schema tables are probed, no password/APP_KEY/DSN/SQL exception/path is printed, and a disposable database missing one required table produces a non-zero exit. Run the same check after restore.

Restore verification

  • Restore the pre-UAT backup to a separate database/server, never over the live database.
  • Apply the documented upgrade (database/upgrade.sql, if the restored installation predates the current schema) and record the command/output.
  • Run php bin/healthcheck.php against the restored configuration; do not paste secret values into evidence.
  • Log in to the restored system using a test account and verify clients, jobcards, time entries, reports and audit history are present.
  • Verify restored uploads/attachments and permissions, if that module is enabled.
  • Record restore duration, backup timestamp, row/data spot checks and any missing items.
  • Confirm the live system was not modified by restore testing and securely remove the temporary restored copy when approved.

Explicit security acceptance cases

Record the request URL/route, authenticated role, test fixture IDs, expected response, observed response, and evidence for each case. Use separate Technician accounts and at least two clients/jobcards so an ID change cannot accidentally target the same tenant.

  • SEC-01 — Technician cross-client IDOR (read): Technician A requests Technician B's jobcard URL and an attachment URL belonging to that jobcard. Both requests return the same not-found/denied behavior as an unknown ID, and no client name, jobcard details, attachment bytes or metadata are disclosed.
  • SEC-02 — Technician cross-client IDOR (write): Technician A submits status, notes, assignment or time-entry payloads with Technician B's jobcard ID. CSRF-valid requests are still denied by authorization, and the target jobcard, assignments and time entries remain unchanged.
  • SEC-03 — Own-technician time isolation: Create one assigned jobcard with time recorded by Technician A and Technician B. Technician A's report/UI/export contains only A's hours; it does not include B's hours or another client's totals. Repeat with a direct report URL and CSV export.
  • SEC-04 — Credential canonical storage: Create a credential containing a unique canary secret. The database row has secret_ciphertext and no plaintext secret field/value; normal views show a mask; only an authorized reveal returns the secret once, with no-store headers and an audit event. A different client's credential ID cannot be revealed.
  • SEC-05 — Attachment safe metadata: Attempt traversal names (../x.pdf), executable/double extensions (invoice.php.jpg), MIME mismatches, oversized files, and client-visible without explicit approval. Each is rejected before storage. A valid image/PDF is stored under a generated server name, served with its validated MIME and X-Content-Type-Options: nosniff, and remains inaccessible through a different jobcard/client ID.
  • SEC-06 — Healthcheck schema contract: Run php bin/healthcheck.php with valid configuration and confirm every current schema table is probed, output contains statuses only, and no password, APP_KEY, database DSN, SQL exception, or secret value is printed. Remove/rename one required table in a disposable database and confirm a non-zero failure.
  • SEC-07 — CSRF route assumptions: For login, logout, client create/edit/contact, jobcard create/update, time, assignment, attachment, credential and SLA POSTs, submit with a missing token and a wrong token. Every request is rejected before mutation (HTTP 419 or the documented equivalent); the valid-token control succeeds. GET requests do not mutate state.
  • SEC-08 — Migration coverage and restore: Restore a pre-current-schema backup to an isolated database, run database/upgrade.sql once and a second time, and confirm feature tables/columns, permissions and the one-SLA-per-client constraint are present. Resolve/record duplicate SLA rows before the unique constraint step; rerun healthcheck and verify representative clients, jobcards, time entries, credentials and attachments.

Sign-off

  • Environment/version: ______________________________
  • Backup reference: __________________________________
  • Tester/date: _______________________________________
  • Defects and follow-up owner: _______________________
  • UAT result: [ ] Pass [ ] Pass with follow-up [ ] Fail