Files
huntingclubroster/SECURITY-MIGRATION-2026-10-20.md

5.4 KiB

Development security/capacity migration — October 20, 2026

Completed against the approved development target, 192.168.1.190/huntingclubroster, using its previously approved non-TLS connection.

Backup and migration

  • Backup: .tools/backups/20261020-190128/huntingclubroster.sql.
  • Size: 53,033 bytes; 23 existing tables.
  • SHA-256: e7301cc5429f57bf93e9f1627b6c77afc9d8678ea0757a56a445e597417e0570.
  • Verified the completion marker and checksum, restored the backup to an isolated loopback database, and matched all 23 table row counts.
  • Applied bin/migrate-security-capacity.php and reran it to confirm repeatability. The database now has 26 tables, including user_mfa, mfa_recovery and club_resource_usage.
  • Compared every original table's row fingerprints before and after migration; existing values were preserved.

Persistent development MFA key

  • Generated a cryptographically random 32-byte key outside the project, in C:\Users\JamesRichie\AppData\Local\HuntingClubRoster\secrets\development-mfa.key.
  • Configured its path in ignored xml/settings.local.xml. Development servers can read this persistent key without inheriting a temporary shell variable. No key value is stored in the repository or this report.
  • The key has protected Windows permissions allowing only the current Windows account and SYSTEM. A protected recovery copy was saved under the same external secrets folder's recovery subdirectory. This is a local recovery copy, not an off-host backup.
  • Added a development-only key-file loader. It rejects missing, oversized, malformed and in-project key files. Production continues to require its explicitly injected environment key.
  • Eight key-configuration regression checks passed and are included in the test runner.

Development acceptance

All 68 development acceptance checks passed, using owned temporary clubs, accounts and records:

  • Super System Administrator and club administrator authenticator enrollment; administrator URLs and AJAX denied before MFA; valid authenticator acceptance; encrypted secrets; recovery-code consumption and rejection of reused codes.
  • Password login still requires the enrolled factor. Ordinary members keep their normal login flow. Sensitive changes require recent password/MFA confirmation.
  • Independent eight-hour absolute and 30-minute idle session expiration, tested by aging only private test sessions rather than changing server time or waiting.
  • Last-page access for members, seasons, dues, payments, corrections and invitations; paged ticket conversations; invalid page handling; personal counts and cross-club access denial.
  • Shared ticket, reply, invitation email and export budgets across different users, independent budgets for another club, and hourly-window reset.
  • Oversized CSV, Excel, PDF and financial exports rejected without truncation.

The verification servers temporarily used lower limits to exercise boundaries; normal development defaults were not changed. SMTP was redirected to an unused loopback port, so no real email was sent. The MFA key was loaded from the actual protected development key file, not a disposable test key.

All temporary accounts, factors, recovery codes, clubs, ledger rows, tickets, audits, counters and private sessions were removed. Row fingerprints for all 26 tables then matched their pre-test state. Real account passwords, roles, email verification and MFA enrollment were unchanged.

Detailed private evidence is retained beside the backup in security-migration-result.json, security-acceptance-result.json and security-cleanup-result.json.

The final development health check passed. Source validation passed for 61 PHP files, 57 application JavaScript files and 39 XSL stylesheets, including browser dependency integrity. The local backup-restoration copy was removed and its isolated database server stopped.

The existing Super System Administrator will be prompted to enroll an authenticator at the next sign-in; its owner must save the recovery codes. No real account was enrolled on the owner's behalf.

Actual development web-server follow-up

The browser application runs on ositsdevels under Rocky Linux Apache/PHP-FPM, not on the Windows workstation used for the original acceptance server. Its copied Windows key path caused login to fail before displaying MFA setup.

The owner ran the prepared administrator installer on that server. It installed the unchanged key at /etc/httpd/huntingclubroster/development-mfa.key, restricted its permissions to root and the Apache group, restored its SELinux context, and configured the application's FastCGI requests with HCR_MFA_KEY_FILE. This development-only override prevents workstation settings from replacing the server's key path. Nine key-configuration regression checks passed.

The installer also enabled the app's existing private-directory rules, validated Apache configuration and reloaded Apache. Its staged key was outside the web root in the server home directory and was removed after installation.

Verified through the actual Apache/PHP-FPM server after installation:

  • Configured MFA key is readable and can encrypt a secret.
  • Authenticator library can generate and verify a code entirely in memory.
  • Login page returns HTTP 200.
  • .tools/, local settings, classes and vendor endpoints return HTTP 403.
  • The staged key is removed. All temporary token-protected diagnostics were immediately removed, and no real account was enrolled or changed.