OViq Hotel ERP — Phase 6 executed verification record
Date: 2026-10-20
Environment: PHP 8.3.6, MySQL 8.0.46, Node.js, headless Chromium.
PHP target >=8.2. No claim is made that PHP8.2, Safari, Firefox, Windows,
production PHP-FPM/Nginx, actual OTA APIs or payment gateways were tested.

119 prior-phase regression assertions
60 Phase 6 service assertions (includes independent PHP/MySQL process races)
31 HTTP installation, route and migration checks
16 HTTP isolation, account revocation, 2FA fail-closed and throttle checks
23 real-browser workflow, responsive navigation and offline checks
10 actual archived Phase5 upgrade and backup/restore checks
Total: 259 reported assertions/checks across these layers (not 259 unique features).

Additional checks: PHP syntax lint for every shipped PHP file, Node.js syntax
validation for local JavaScript, fresh schema/seed import and ZIP integrity.
The optional GitHub workflow was supplied as code, not activated or executed.

Targeted race coverage:
- two independent workers contend for the same room/stay; exactly one booking
- two identical POS payment submissions; exactly one receipt persisted
- two workers close one business date; exactly one close and room-night charge
These are correctness races, NOT a sustained load or high-availability test.

Audit-trigger tests use a DBA-installed trigger fixture. Web installer deliberately
requires no SUPER privilege; operators must separately install audit guards and
run preflight before any live cutover. Read deployment notes and release status.
Preflight intentionally returns failure for missing guards and ownerless legacy
inventory. Those failing gates were tested as expected blockers, not ignored.

Browser workflow: local Bootstrap, room/type setup, guest registration, walk-in,
receipt and checkout, tape chart, CRM drag/drop and accessible movement, mobile
sidebar, static-only offline fallback and no uncaught JavaScript errors. A
browser screenshot in tests/previews is test-fixture data, not a live property.

Restore drill: CLI backup with a dedicated DBA fixture, SHA-256 reporting,
no-overwrite guard, restore into a separate database, table/record count and audit
trigger checks. Does not certify your production backup infrastructure.

Remaining functional and infrastructure gates are in RELEASE-STATUS.txt and
DEPLOYMENT.txt. A successful test run is not a production security certification.


==== Prior-phase regression assertions ====
PASS Authenticated property context resolves assigned property
PASS Super-admin permission gate succeeds
PASS Housekeeper denied CRM permission
PASS Forged CSRF token rejected
PASS Issued CSRF token accepted
PASS Lead created at version zero
PASS Lead stage persists
PASS Stale lead update rejected
PASS Unknown pipeline stage rejected
PASS Cross-property lead update denied
PASS Invalid calendar date rejected
PASS Blank lead title rejected
PASS Work assigned to technician
PASS Asset retirement blocked while work outstanding
PASS Work lifecycle reaches closed
PASS Closed work cannot advance
PASS Due maintenance produces one work order
PASS Repeated due generation creates no duplicate
PASS Retired assets cannot reactivate
PASS Event quote equals two hours times hall rate
PASS Overlapping event rejected
PASS Back-to-back hall booking accepted
PASS Hall capacity enforced
PASS Completed event cannot reopen
PASS Event cancellation persists
PASS Cross-property hall booking denied
PASS Pricing defaults disabled
PASS Disabled pricing engine rejects generation
PASS Pricing toggle persists
PASS Pricing generates two daily recommendations
PASS Regeneration uses unique date/type records
PASS No duplicate recommendations
PASS Approved recommendation stored as date override
PASS Reapplying recommendation rejected
PASS Base room-type rate unchanged
PASS High-occupancy pricing formula verified
PASS Low-occupancy pricing formula verified
PASS Audit and mutation transaction rolls back together
PASS Workflow audit records written
PASS Controller renders crm
PASS Controller renders maintenance
PASS Controller renders events
PASS Controller renders pricing
PASS Controller renders reports
PASS Date-rate API rejects missing inputs
PASS Date-rate API returns approved override
PASS Route handler exists /login
PASS Route handler exists /
PASS Route handler exists /dashboard
PASS Route handler exists /pms/calendar
PASS Route handler exists /pms/calendar-data
PASS Route handler exists /pms/available-rooms
PASS Route handler exists /pms/reservations
PASS Route handler exists /pms/reservations/create
PASS Route handler exists /pms/reservations/{id}
PASS Route handler exists /pms/rooms
PASS Route handler exists /pms/guests
PASS Route handler exists /pms/guests/{id}
PASS Route handler exists /pms/night-audit
PASS Route handler exists /front-office
PASS Route handler exists /pos
PASS Route handler exists /pos/orders/{id}
PASS Route handler exists /pos/kitchen
PASS Route handler exists /housekeeping
PASS Route handler exists /inventory
PASS Route handler exists /inventory/purchase-orders
PASS Route handler exists /inventory/purchase-orders/{id}
PASS Route handler exists /accounting
PASS Route handler exists /crm
PASS Route handler exists /maintenance
PASS Route handler exists /events
PASS Route handler exists /pricing
PASS Route handler exists /reports
PASS Route handler exists /reports/export
PASS Route handler exists /pms/date-rate
PASS Route handler exists /login
PASS Route handler exists /logout
PASS Route handler exists /pms/reservations
PASS Route handler exists /pms/reservations/{id}/checkin
PASS Route handler exists /pms/reservations/{id}/checkout
PASS Route handler exists /pms/reservations/{id}/transition/{action}
PASS Route handler exists /pms/reservations/{id}/charges
PASS Route handler exists /pms/reservations/{id}/payments
PASS Route handler exists /pms/room-types
PASS Route handler exists /pms/rooms
PASS Route handler exists /pms/rooms/{id}/status
PASS Route handler exists /pms/guests
PASS Route handler exists /pms/guests/{id}
PASS Route handler exists /pms/night-audit/run
PASS Route handler exists /front-office/wakeup
PASS Route handler exists /front-office/wakeup/{id}/complete
PASS Route handler exists /pos/outlets
PASS Route handler exists /pos/tables
PASS Route handler exists /pos/categories
PASS Route handler exists /pos/items
PASS Route handler exists /pos/orders
PASS Route handler exists /pos/orders/{id}/items
PASS Route handler exists /pos/orders/{id}/items/{item_id}/void
PASS Route handler exists /pos/orders/{id}/items/{item_id}/split
PASS Route handler exists /pos/orders/{id}/send-kitchen
PASS Route handler exists /pos/orders/{id}/pay
PASS Route handler exists /pos/orders/{id}/room-charge
PASS Route handler exists /pos/kitchen/{item_id}/advance
PASS Route handler exists /housekeeping/tasks
PASS Route handler exists /housekeeping/tasks/{id}/assign
PASS Route handler exists /housekeeping/tasks/{id}/advance
PASS Route handler exists /housekeeping/laundry
PASS Route handler exists /housekeeping/laundry/{id}/move
PASS Route handler exists /housekeeping/lost-found
PASS Route handler exists /housekeeping/lost-found/{id}/claim
PASS Route handler exists /inventory/items
PASS Route handler exists /inventory/stores
PASS Route handler exists /inventory/adjust
PASS Route handler exists /inventory/purchase-orders
PASS Route handler exists /inventory/purchase-orders/{id}/approve
PASS Route handler exists /inventory/purchase-orders/{id}/receive
PASS Route handler exists /accounting/journal
PASS Route handler exists /accounting/expenses
PASS Route handler exists /ops/{module}/{action}

TOTAL 119 assertions passed; 73 registered routes.


==== Phase 6 service and independent-process race assertions ====
PASS Property context established
PASS Decimal money addition uses exact minor units
PASS Fractional line rounds half up
PASS Negative monetary input rejected
PASS Excess decimal places rejected
PASS Cross-property guest rejected by reservation service
PASS Room maximum occupancy enforced
PASS Concurrent same-room booking: exactly one writer succeeds
PASS Concurrent booking creates only one reservation
PASS Unassigned reservations cannot oversell room-type inventory
PASS Dirty/cleaning room cannot be checked in
PASS Unpaid folio cannot check out
PASS Folio includes room tax and extra charges exactly once
PASS Identical folio payment replay is idempotent
PASS Payment key reuse with changed amount rejected
PASS Folio overpayment rejected
PASS Paid checkout sends room to cleaning
PASS Checkout generates one cleaning task
PASS Closed folio rejects charges
PASS Occupied restaurant table cannot be reopened
PASS Split tax totals use exact minor units
PASS POS partial-payment replay creates no duplicate
PASS Split payment cannot exceed remaining balance
PASS Cannot redistribute partially-paid lines
PASS Fully-paid split rejects additional payment
PASS All splits settled marks order paid
PASS Settled order frees table
PASS Settled order cannot be voided
PASS Concurrent identical payment requests both resolve successfully
PASS Concurrent payment replay persists only one receipt
PASS Still-open current business date cannot be closed
PASS Concurrent night audit closes date once
PASS Night audit posts exactly one room charge per business date
PASS Night audit does not double count quoted room amount
PASS Opening stock adjustment persists
PASS Negative inventory stock rejected
PASS Cross-property stock adjustment rejected
PASS Partial GRN advances PO state
PASS Cumulative GRN over-receipt rejected
PASS Weighted-average cost includes stock in both stores
PASS Receipt leaves other store quantity unchanged
PASS Receiving store gets exact received quantity
PASS Fully-received PO closes
PASS Double-entry journal balances exactly
PASS Journal uses property currency, not hardcoded USD
PASS Unbalanced journal rejected
PASS Expense cannot post to an asset account
PASS Rejected expense leaves no partial record
PASS Expense journal preserves expense date
PASS Database rejects audit update
PASS Database rejects audit deletion
PASS Login attempt bucket updated 1
PASS Login attempt bucket updated 2
PASS Login attempt bucket updated 3
PASS Login attempt bucket updated 4
PASS Login attempt bucket updated 5
PASS New session does not bypass database login throttle
PASS Native DI resolves typed dependencies
PASS Named routes encode path parameters
PASS Dynamic SQL identifiers validated
TOTAL 60 Phase 6 hardening assertions passed.


==== HTTP installer and route regression ====
PASS Uninstalled application routes to public installer
PASS Installer rejects missing CSRF
PASS Installer database configuration succeeds
PASS Installer builds all tables and seeds identity catalog
PASS Installer creates administrator and completes lock step
PASS Installation lock written
PASS Installed wizard cannot be reopened
PASS Login rejects missing CSRF
PASS Login authenticates and dashboard renders
PASS Authenticated route /crm renders
PASS Authenticated route /maintenance renders
PASS Authenticated route /events renders
PASS Authenticated route /pricing renders
PASS Authenticated route /reports renders
PASS Authenticated route /pms/calendar renders
PASS Authenticated route /pms/rooms renders
PASS Authenticated route /pos renders
PASS Authenticated route /accounting renders
PASS Nested-page base URL anchored at application root
PASS CRM mutation rejects missing CSRF
PASS Lead creation escapes stored HTML when rendered
PASS AJAX lead movement persists
PASS AJAX stale version returns conflict
PASS Invalid report date returns 422
PASS Report CSV export responds
PASS Unregistered route returns 404 without fatal error
PASS Service worker excludes authenticated page persistence
PASS CLI migration runner handles fresh install and rerun
PASS Phase 4-style database receives Phase 5 additions
PASS Non-CRM role denied CRM page
PASS Housekeeper denied pricing page
TOTAL 31 HTTP/deployment checks passed.


==== Cross-property/session/throttle HTTP checks ====
PASS Foreign guest detail denied
PASS Foreign reservation detail denied
PASS Foreign POS order detail denied
PASS Foreign outlet detail denied
PASS Property-isolated collection /pms/guests
PASS Property-isolated collection /pms/reservations
PASS Property-isolated collection /pms/reservations/create
PASS Property-isolated collection /inventory
PASS Property-isolated collection /front-office
PASS Property-isolated collection /dashboard
PASS Cross-property checkout denied before mutation
PASS Foreign inventory input cannot cross resource boundary
PASS Unsupported JSON mutation fails closed
PASS Disabled account loses existing session access
PASS 2FA-marked account cannot silently bypass unsupported second factor
PASS HTTP login throttle survives six fresh cookie jars
TOTAL 16 security HTTP checks passed.


==== Chromium end-to-end and offline checks ====
PASS Desktop sidebar renders
PASS Room type setup submits successfully
PASS Room setup creates clean room tile
PASS Guest registration reaches profile
PASS Walk-in guest checked in through real browser form
PASS Folio receipt records through idempotent payment form
PASS Paid browser checkout succeeds
PASS Tape chart JavaScript renders fourteen-day grid
PASS Drag-and-drop CRM movement persists after reload
PASS Accessible CRM selector persists stage change
PASS Browser route renders /maintenance
PASS Browser route renders /events
PASS Browser route renders /pricing
PASS Browser route renders /reports
PASS Browser route renders /accounting
PASS Browser route renders /housekeeping
PASS Browser route renders /pos
PASS Mobile sidebar toggle works at 390px
PASS Mobile dashboard avoids document-level horizontal overflow
PASS Browser cache contains no authenticated HTML pages
PASS Offline navigation displays static fallback, not guest data
PASS No uncaught browser JavaScript errors
PASS No external asset requests needed for application rendering
TOTAL 23 browser checks passed.


==== Real archived upgrade and backup restore checks ====
PASS Archived Phase5 database upgrades through Phase6
PASS Actual upgrade migration rerun is idempotent
PASS Unknown legacy inventory ownership is preserved for manual reconciliation
PASS Preflight blocks unresolved legacy inventory
PASS Preflight reports missing DBA audit guards
PASS DBA audit-guard installer succeeds and can be rerun
PASS CLI backup produces a checksum-verified SQL dump
PASS Backup tool refuses to overwrite an existing file
PASS Backup restores matching table and fixture record counts into another database
PASS Restore includes both append-only audit triggers
TOTAL 10 upgrade/backup checks passed.

