# Simple document management

## Menu and everyday flow

**Documents** opens the paginated list. Navigation contains **All Documents**, **Add Documents**, and **Document Settings** for authorized company-wide settings/document administrators. Settings has **Document Types**, **Company Categories**, and **Storage & Security** tabs. Existing URLs and POST contracts remain available.

**Add Documents** selects Employee or Company once, then accepts up to 20 document cards. Employee lookup matches names/codes and shows their existing document types without overwriting any record. Employee profile links preselect that employee. Company ownership uses the current workspace, with a category on each card. Existing branch/legal-entity records keep their ownership and access restrictions.

Each card accepts a document type, number, issue date, expiry date and up to 10 ordered files. PDF, PNG and JPEG are content-validated against the effective platform/subscription limit. A PDF retains every page; several photos/PDFs share one upload group. Files can be removed or moved up/down. Camera capture remains available on phones. Custom names and encrypted notes are optional; the name defaults to the type. Expiry is required unless the user explicitly selects Does not expire, or the master type has no expiry. Types requiring expiry prohibit that option.

**Save All Documents** validates and saves each card independently. Successful cards lock and provide a document link; failed cards retain details and usable uploads. Correcting a failed card does not repeat successful saves or re-upload its staged files. No drafts are introduced. Mobile cards stack with a sticky Save bar; the desktop form uses compact field rows.

## Files and background protection

Staged files are authenticated-encrypted and scoped to company, uploading user and a per-card session UUID. Temporary bytes count toward storage limits; finalization transfers that accounting to permanent versions. Each card is atomic across its metadata and files. An attach/storage failure rolls back that card and cleans permanent objects, while other cards can still save. Consumed receipts remain for seven days, including retries after type deactivation. Abandoned files expire after 24 hours and use existing maintenance cleanup.

The new UI stages with `background=1` and numbered file slots; legacy front/back requests remain compatible. `upload_ids` defines the exact ordered set at finalization. New permanent versions record `file_position`; existing groups fall back to their original version order. No additional permanent file or draft tables are created.

Save does not wait for the scanner. The existing `ScanPendingDocuments` maintenance step checks encrypted quarantined files and retries service failures. Normal pages show **Saved - preparing secure access**, refresh availability automatically, and have no manual retry or ordinary verification step. Download, preview and OCR remain blocked until the relevant file passes scanning. Confirmed malware rejection remains separate. Settings shows counts of files pending more than five minutes and an authorized diagnostic action. Staging is not OCR and never starts text extraction automatically.

The list filters update after select/date changes or 300ms after search typing, with cancellation of stale responses. Filters reset pagination, stay in the URL and survive returning from details. Pagination works with or without JavaScript; mobile filters collapse above responsive document cards. Existing advanced history/compliance filters remain available.

Document Types offers Required/Optional/Does not expire, Active status and collapsed retention/compliance fields. Types referenced by any active or archived/deleted document cannot be deleted; deactivate instead. Unused types require deletion confirmation. Category rules remain equivalent. Both deletion checks keep tenant isolation and database foreign-key protection.

Secure server storage remains the default: private encrypted company folders outside public access. Company S3 storage uses the existing tested connection form and encrypted credentials. Changes affect new uploads; historical files keep their storage profiles. No keys are regenerated and no automatic storage migration is performed.

## Expiry, OCR and history

Saving confirms dates for ordinary expiry alerts, without a second review screen. Status uses the company calendar: **Expired** before today, **Expiring Soon** from today through 30 days ahead, and **Valid** after that. Explicitly non-expiring records show **Does not expire**; undated legacy records show **Expiry date needed**. Existing verified records are marked as date-confirmed during migration. No dates are guessed for other legacy records.

OCR remains off by default. A platform administrator enables the existing company setting under **Companies → company → Company security → OCR availability**. The existing Tesseract sandbox or configured isolated provider is reused. Selecting a file never starts OCR. **Read text from document** stages selected files and explicitly requests extraction after successful scanning. Results stay encrypted while staged. Users apply individual suggestions; typed values remain unchanged until then. Ambiguous or conflicting dates are omitted. OCR failure leaves files and manual fields available for Save. Browser OCR tests mock suggestion responses; backend tests exercise the existing provider interface with isolated HTTP fakes.

The list supports employee/company, owner name/code, category, type, status, expiry range, title/reference/filename search, sorting and pagination. File actions update after background checks. **Edit details & dates** also offers replacement files. Saved notes are encrypted. Details include uploaded/changed-by history and the original access audit. Legal holds, retention and renewal administration remain collapsed. Deletion requires confirmation and uses the existing archive service, preserving retention and legal holds.

Dashboard counts and reminders use confirmed dates even during scanner outages. Existing reminder schedules, email preferences and deduplication keys remain in force. Configured renewal workflows retain their separate verification requirements. Changing validity reconciles active renewal cases; replacement files clear compliance verification. Expiry alerts do not complete or approve renewals.

Company categories start with Legal, Finance, Insurance, Other and Company Vehicle Documents. Authorized company-wide document administrators can create, rename, deactivate or delete categories. A category referenced by an active or archived document cannot be deleted. Existing records may retain a deactivated category while their dates are edited. Employee-scoped administrators do not gain company-wide document/category access.

## Upgrade and diagnostics

Migration `2026_10_21_000032_order_document_files` adds nullable file ordering to existing versions. Issue and expiry dates are directly visible on each card. Only custom name, note and manual OCR are under More details. Mobile employee results have 52px minimum touch targets.

Migration `2026_10_21_000031_simplify_document_management` creates `document_categories` and `document_uploads` and adds the nullable category/note/confirmation fields plus the non-expiring flag to `documents`. It follows migration 30 for front/back grouping and migration 29 for storage profiles. Existing identifiers, keys, encrypted files, ownership and audit history are preserved. No new Composer or npm packages are required. The matching compiled assets are tracked in Git for cPanel.

Back up the database, private storage and original document key using the existing deployment procedure. From the HRMS application directory, after the release is available on the server:

```bash
set -e
php artisan down --retry=60
git pull --ff-only origin main
php artisan config:clear
php artisan migrate --force
php artisan view:clear
php artisan config:cache
php artisan view:cache
php artisan queue:restart
php artisan up
php artisan zentrik:documents:diagnose YOUR_COMPANY_SLUG --document=DOCUMENT_ID
```

Use the same PHP 8.3+ binary as the site. Stop if a migration or cache build fails. Confirm the existing maintenance cron runs every minute; do not generate new application/document keys, reset the database, or run fresh-install commands. The diagnostic exits nonzero on a failure; running it after `up` keeps an existing scanner outage from blocking date-entry availability. A site with missing dependencies needs its existing Composer deployment procedure as well.

The diagnostic separately reports schema readiness, private storage read/write, existing-file reads, authenticated decryption and scanner protocol/connectivity. It never changes file scan states or keys. Full exception details remain in the private application log. It tests harmless text, not a malware sample.

The supplied HRMS log established an earlier missing `document_storage_profiles` table. It did not establish the current live scanner cause. Run the new diagnostic on the live host and inspect the newest matching HRMS error. Scanner failures require the configured scanning service; decryption failures require the original key/integrity investigation; storage failures require permissions or connection repair. Do not bypass scanning.

## Verification on 21 October 2026

- SQLite: 74 document/register/scope/renewal/legacy cases, 559 assertions; the opt-in installed-OCR case was run separately and passed with 9 assertions. The OCR date-parser unit check passed with 6 assertions.
- MySQL: the 22 document/register cases were exercised against `zentrikhrms_codex_test`. The corrected scoped-user fixture and updated scanner-outage reminder scenario passed a targeted rerun (2 cases, 42 assertions).
- Browser: employee upload/edit/delete on mobile and dark mode; company categories, inline types, explicit OCR suggestions/failure and filters; employee/legacy compliance workflow; PWA install controls; camera selection and offline upload. All five workflows passed across the main run and corrected company-filter rerun.
- The real installed Tesseract sandbox passed extraction and encrypted-result/manual-expiry checks. Browser OCR suggestions use explicit mocks; this does not establish live-host OCR availability.
- Full Pint check, UTF-8 check, whitespace check and production asset build passed.
- The local application database was backed up privately before migration 31. The new diagnostic passed schema, storage read/write, existing-file read, decryption and scanner checks for local document 8. The live host has not been changed or diagnosed by this implementation.
- Usability follow-up: all 19 document-storage feature tests passed (288 assertions), including blank/default/custom names. Signed-in local browser checks saved company document 14 with an automatic name and employee document 15 using the mobile employee picker; both synthetic PDFs passed scanning. Editing document 15's expiry preserved its existing file and custom name. The 390px layout had no horizontal overflow. These test records remain in the demo workspace for inspection.
- The optional-name regression also passed against the isolated MySQL database (1 case, 15 assertions).
- Final browser rerun: all three document-storage and employee/compliance workflows passed with a 180-second per-test limit. Checks include automatic names, custom-name preservation during inline type creation, mobile result selection, keyboard selection and the employee no-match state. Production build, full Pint, UTF-8 and staged whitespace checks passed.

## Multi-document release verification

- SQLite: the 80-case document/register/scope/renewal/legacy selection finished with 78 passing cases, one outdated label assertion and one opt-in installed-OCR skip. After correcting that literal assertion, the complete PhaseTwo suite passed (32 cases, 158 assertions; one installed-OCR skip). No application failures remain in that selection.
- MySQL: all four new batch cases passed (77 assertions) against `zentrikhrms_codex_test`, including independent transactions, ordered files, retry receipts after type deactivation, type-deletion restrictions and scanner failures.
- Browser: all five updated workflows passed across the four-workflow run and final company/settings rerun. Coverage includes server-rejected cards without duplicate uploads, file ordering, mobile date editing, category/type masters, manual OCR success/failure, live filters/back navigation, legacy legal holds/renewals, PWA behavior and offline camera uploads.
- Signed-in local checks saved synthetic documents 16 and 17 independently in one employee batch, then edited document 16's expiry on mobile without another file. The local operator diagnostic passed schema, storage read/write, stored-file read, decryption and scanner checks. The normal background scanner made both files Ready; the downloaded PDF matched the original SHA-256 exactly. Live search narrowed the document list to one matching record. Desktop 1440px and mobile 390px forms were inspected; mobile had no horizontal overflow.
- Migration 32 was applied only to the local demo after an encrypted database backup. Full Pint, UTF-8, whitespace checks and the production asset build passed. No live-host deployment or storage/scanner configuration changes were performed.
