# Production Acceptance Checklist

Record evidence for each item on staging and again after production deployment.

## Hosting and configuration

- [ ] PHP is 8.1+ and all required PDO/GD/Fileinfo/OpenSSL/JSON extensions are enabled.
- [ ] All four final URLs use valid HTTPS.
- [ ] HTTP redirects to the configured HTTPS URL without reflecting a forged Host value.
- [ ] The private `unified-auth-config.php` is outside `public_html` and not downloadable.
- [ ] Hidden `.htaccess` files were preserved.
- [ ] Direct requests to portal `lib`, `database`, `client` and `tools` are denied.
- [ ] Direct requests to Staff JSON, Price Label SQLite/CSV data and Store Audit storage are denied.
- [ ] A test script uploaded with an image-like name cannot execute in any upload folder.
- [ ] Writable folders work without 777.

## Central authentication

- [ ] Initial and backup Super Administrator accounts can sign in.
- [ ] Administrator/Super Administrator TOTP setup is required.
- [ ] A used recovery code cannot be reused.
- [ ] An already-used TOTP time-step code cannot be replayed.
- [ ] Five failed/abusive attempts trigger the expected throttle/lock behaviour without revealing whether a username exists.
- [ ] A password under 14 characters or containing account details is rejected.
- [ ] A recent password cannot be reused.
- [ ] Password reset forces change and revokes existing sessions.
- [ ] Disabling a user or removing an app grant blocks the next request in that app.
- [ ] One POST logout ends access to every assigned application.
- [ ] Idle and absolute session expiry operate as configured.

## User management and privilege boundaries

- [ ] All six fixed levels appear in the correct order.
- [ ] App access can be independently enabled/denied for each user.
- [ ] Each function supports Inherit, Allow and Deny.
- [ ] App deny wins over an explicit function Allow.
- [ ] An Administrator cannot create/manage an Administrator or Super Administrator by default.
- [ ] A delegated administrator cannot grant an app or function they do not possess.
- [ ] The final active Super Administrator cannot be disabled, demoted or deleted.
- [ ] Sensitive settings require recent reauthentication.
- [ ] User, permission, password, two-factor and session changes appear in the central audit log.

## Staff Compliance

- [ ] Existing acknowledgements, training records, sign-offs, users and documents remain present.
- [ ] Employee can acknowledge policies and complete training but cannot open denied administration URLs.
- [ ] Supervisor sees only assigned staff unless granted organisation-wide visibility.
- [ ] Sign-off and reissue functions obey their separate permissions.
- [ ] Every admin POST action is denied when its function is denied, even when submitted manually.
- [ ] Manager and branch assignments remain local and correct after central sync.
- [ ] PDF/CSV reporting obeys report permission.
- [ ] Setup requires `staff.manage_settings`.

## Store Audit

- [ ] Existing users, branches, templates, audits, photos, PDFs, signatures and actions remain present.
- [ ] A user without standard-audit permission cannot open or submit a standard audit directly.
- [ ] Recurring self-audit requires both central permission and eligible local branch profile.
- [ ] Two simultaneous recurrence claims cannot create duplicate occurrences.
- [ ] Peer review/publish, corrective-action management, amendments and deletion each obey their named permission.
- [ ] A denied protected route fails closed rather than relying on hidden navigation.
- [ ] Standard review publishes one immutable PDF revision.
- [ ] Recurring completion publishes one immutable revision without signature/review.
- [ ] Upgrade/install requires `audit.manage_settings`.

## Price Label Maker

- [ ] Existing products, branches, backgrounds, requests and settings remain present.
- [ ] Landing page selects a function the user is actually allowed to use.
- [ ] Product lookup, label creation and review request submission enforce their function server-side.
- [ ] A branch-restricted user cannot select another branch by changing request parameters.
- [ ] CSV import rejects invalid headings/rows/limits and requires `labels.import_products`.
- [ ] Two simultaneous identical pending review submissions create only one pending request.
- [ ] Review processing is atomic and cannot be processed twice.
- [ ] Uploaded backgrounds/logos are validated and cannot execute scripts.
- [ ] Setup requires `labels.manage_settings`.

## Migration and operations

- [ ] Importer dry run has no blocking conflicts.
- [ ] Applied central IDs match the intended local profiles.
- [ ] Linked local password hashes are non-login markers.
- [ ] Historical records still attribute the correct people.
- [ ] Sensitive import report was deleted after credential delivery/reset.
- [ ] Coordinated backup and restore procedure was tested.
- [ ] Release ZIPs and backups were removed from public folders.
