# Legacy Account Migration Guide

The migration keeps each application’s business records and local IDs while moving passwords, account status, levels, app access and function permissions to the Unified User Portal.

## Safety model

The importer is CLI-only and dry-run by default. It:

- normalises usernames case-insensitively;
- creates one central identity for matching usernames across applications;
- maps the highest legacy role to a central level, never Super Administrator;
- enables only source applications where the legacy profile is active;
- preserves a usable legacy password hash where possible and forces a password change;
- generates a strong temporary password when no usable hash exists;
- writes `central_user_id` back to local compatibility profiles;
- replaces linked local password hashes with `!central-authentication!`;
- refuses blocking identity/link conflicts;
- preserves local business records, local primary keys and historical attribution.

## 1. Maintenance window and coordinated backups

Restrict all three applications. Back up:

- Staff Compliance `data/users.json`, all JSON data and document folders;
- Price Label `storage/app.sqlite` and `uploads/`;
- Store Audit database, `config.php` and `storage/`;
- central database and private config if already installed;
- currently deployed code.

Confirm the backups can be restored before continuing.

## 2. Install central login and upgrade local schemas

1. Install the Unified User Portal at its final HTTPS URL.
2. Complete mandatory Super Administrator two-factor setup.
3. Upload the unified versions of all applications while preserving business data.
4. Run Store Audit `upgrade.php` with `audit.manage_settings`.
5. Open Price Label Maker through its setup/application flow so its non-destructive schema migration adds `central_user_id` where needed.
6. Initialise missing Staff Compliance files with `setup.php` if necessary.

Do not reopen the applications to ordinary users yet.

## 3. Run a dry run

From cPanel Terminal, adapt this command:

```bash
php /home/CPANEL_USER/public_html/user-portal/tools/import_legacy_users.php \
  --config=/home/CPANEL_USER/unified-auth-config.php \
  --staff=/home/CPANEL_USER/public_html/staff-compliance/data/users.json \
  --labels=/home/CPANEL_USER/public_html/price-labels/storage/app.sqlite \
  --audit-config=/home/CPANEL_USER/public_html/store-audit/config.php \
  --report=/home/CPANEL_USER/unified-import-report.txt
```

Omit a source option only when that application genuinely has no legacy users to import. The command makes no changes without `--apply`.

## 4. Resolve the report

Review every account and resolve:

- the same case-insensitive username used by different people;
- one local profile already linked to another central user;
- duplicate local profiles;
- conflicting legacy password hashes;
- unexpected level mapping or inactive status;
- stale accounts that should not receive an app grant.

Legacy role mapping is:

| Source | Legacy role | Central level |
|---|---|---|
| Staff Compliance | employee/user | Employee |
| Staff Compliance | supervisor | Supervisor |
| Staff Compliance | assistant manager | Assistant Manager |
| Staff Compliance | manager/store manager | Store Manager |
| Staff Compliance | administrator/admin | Administrator |
| Store Audit | auditor/supervisor | Supervisor |
| Store Audit | assistant manager | Assistant Manager |
| Store Audit | manager/store manager | Store Manager |
| Store Audit | administrator/admin | Administrator |
| Price Label Maker | user | Employee |
| Price Label Maker | admin/administrator | Administrator |

When one person appears in multiple apps, the highest mapped level is selected. Review the result rather than assuming legacy role names had identical meaning.

## 5. Apply

After resolving all blocking conflicts and taking a fresh coordinated backup, rerun the same command with `--apply`.

A private `--report` path is mandatory when a temporary password must be generated. The report is created with restrictive permissions where supported and may contain secrets. Keep it outside `public_html`.

The importer is designed to be rerunnable. It links existing central accounts instead of replacing them and does not remove an existing application grant on a later run.

## 6. Review every central account

For each imported user:

1. Confirm display name, username, active status and level.
2. Confirm exact application grants.
3. Review inherited functions and add explicit Allow/Deny only where required.
4. Reset questionable temporary/legacy credentials centrally.
5. Confirm the first login forces a password change.
6. Ensure Administrator accounts complete mandatory two-factor setup.

Usernames become immutable central identity keys. Correct a mistaken identity before production use rather than creating ambiguous duplicates.

## 7. Review local assignments

Central permissions do not replace business assignments:

- Staff Compliance: manager, branch and archive state;
- Store Audit: local compatibility profile, branch assignment, schedule/audit ownership eligibility;
- Price Label Maker: branch assignment.

Review these inside the relevant application after central migration.

## 8. Acceptance and reopening

Use `ACCEPTANCE_CHECKLIST.md`. Test representative accounts and confirm historical records still display the correct people. Test explicit denied routes by entering their URLs directly. Confirm one logout ends access in all applications.

Delete the private import report after temporary passwords are securely delivered or reset. Keep only the protected coordinated backup required by your retention policy.

## Rollback

Restore central and all affected local data from the same pre-migration backup point. Do not restore only the central database or only one application after `central_user_id` links have been applied.
