# Security and data access

## Access model

| Capability | Assessment | Review | Distribution | Administrator |
|---|---|---|---|---|
| Submit a new household assessment | Yes | No | No | Yes |
| Read submitted assessments and identity documents | Own cases | All cases | No | All cases |
| Edit submitted assessment answers | No | No | No | No |
| Comment and decide eligibility | No | Yes | No | Yes, except own assessments |
| View eligible household contact/location | Own cases | All cases | Assigned location only | All cases |
| Contact notes and kit handover | No | No | Assigned location only | Authorized by API |
| Read receiving notes | Own cases | All cases | Assigned location only | All cases |
| View/export aggregate reports | No | Yes | No | Yes |
| Manage users and view audit log | No | No | No | Yes |

Distribution responses use an explicit field allowlist. They omit identity/family identifiers, survey answers, scores, reviewer comments, ID copies and family-document copies. Distribution users see closed cases in their location for handover history. Account location changes revoke existing sessions. There is no public household endpoint or public file URL.

Application authorization is checked on each API request; hiding a menu is not the access control. An assessor can read only their own cases. Reviewers cannot approve their own assessments, including when an administrator submitted a case. Review decisions and closure lock the database row and use transactions. Review writes include the expected current status to prevent a stale browser overwriting a changed decision. A receiving-note attachment and closed status are committed together.

MEAL can read full cases/documents and aggregate reports, record independent quality checks and export staff incentives across both sites. Only MEAL and administrators can access performance/incentive reports and quality notes. MEAL cannot submit, decide eligibility, distribute, manage accounts or change settings. Quality checks cannot be recorded by the staff member who performed that work.

Every non-admin login and authenticated work/data request is restricted to the administrator-configured daily window, initially 09:00–15:00 Asia/Amman. Logout and a minimal session-status probe remain available. The probe does not renew idle activity. Administrators are exempt to maintain settings. A server recheck inside work transactions prevents commits after closing, including uploads that cross the boundary.

Incentive entries are unique per case/activity and inserted atomically with submission or receipt-backed closure. The application account has no UPDATE/DELETE permissions on the ledger, quality checks or settings history. Rate settings use a locked/versioned row, and all changes preserve before/after values and actor. Monetary amounts are integer fils. Staff incentives and quality metadata are not encrypted at rest; protect database and backups accordingly. Quality-note bodies are encrypted. CSV text values are escaped against formula injection.

## Data controls

- Household contact details, survey answers and event comments use authenticated Sodium secretbox encryption; keys are derived with separate encryption and index contexts.
- Exact duplicate detection uses keyed HMAC values rather than exposing raw identity numbers in indexes. Database unique constraints prevent duplicate household IDs, same-type identity numbers and family-document numbers, including simultaneous inserts.
- Source answers, household identifiers, location, assessment date, reference and submitter are protected by a database trigger against updates after submission. There is no assessment-update API.
- Files use random storage names, MIME/size validation, forced attachment downloads and encrypted storage outside `public`. Raster images are decoded and re-encoded, removing embedded metadata; images above 20 megapixels are rejected. Optional ClamAV scanning is fail-closed when configured.
- Passwords use Argon2id when available, with PHP's password hashing fallback. Temporary passwords must be changed before accessing records.
- Sessions use HttpOnly, Secure (production), SameSite Strict cookies, ID regeneration, 30-minute inactivity expiry and eight-hour absolute expiry by default. The account is rechecked on every request. Disabling or resetting an account revokes existing sessions.
- Mutations require a session CSRF token. SQL uses native prepared statements. Text is escaped before insertion into the UI. Reports export aggregate numeric totals rather than household PII.
- Login limits are stored in MySQL and updated with transaction locks: ten attempts per account and sixty per direct client IP per fifteen-minute window. A reverse proxy requires its normal trusted-client-IP configuration; the application never trusts arbitrary forwarded headers.
- Security headers include a content security policy, clickjacking prevention, no-sniff and private no-store responses. HSTS is sent over HTTPS.
- Audit records contain actor, action, case ID, UTC time and a keyed IP hash. They do not contain survey answers, passwords or identity numbers. The limited database account cannot update or delete audit rows.

## Practical boundaries

Duplicate prevention depends on correctly entering stable official family and identity identifiers. The system cannot prove that two deliberately different or erroneous identifiers belong to the same physical family. Do not use phone numbers as family identifiers: families may share a phone. A family without a booklet must use its official family-registration document; the identifier and uploaded document should be checked by the reviewer.

This is an online application. Unsubmitted answers and chosen files remain only in browser memory while the tab is open; there is no offline cache or server autosave. Refreshing, signing out or session expiry discards unsubmitted work. The interface warns against closing a form with changes. Browser location is validated for plausible Jordan coordinates and capture freshness but can be inaccurate or spoofed; manual selection requires a reason.

Application encryption does not protect against a fully compromised PHP server that has access to the key. It does not encrypt MySQL's score/status metadata, user directory, or audit metadata. Use appropriate server disk/backup protection, restricted host access and HTTPS. Preserve the key and protect its backup separately.

The database administrator can change the database schema or data and is outside the application's role boundary. Audit rows are append-only for the application account; they are not an external tamper-proof audit service. Closed cases cannot be reopened through the application. Correcting a wrongly submitted identity requires an authorized, audited administrative database procedure outside the ordinary workflow; do not create another family ID to bypass duplicates.

Programme retention periods, backup schedules, malware scanning service, device management and TLS certificates must be set by JHASI. No claim of a formal penetration test or legal compliance certification is made.

Implementation references: [PHP password hashing](https://www.php.net/manual/en/function.password-hash.php), [PHP supported versions](https://www.php.net/supported-versions.php), [OWASP file upload guidance](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html), [Bootstrap documentation](https://getbootstrap.com/docs/5.3/getting-started/introduction/).
