# Channex staging test runbook
## Environment and activation safety
Set `CHANNEX_ENVIRONMENT=staging` with the staging host/key. Production must use
`CHANNEX_ENVIRONMENT=production`, `https://app.channex.io/api/v1`, and a separate
production key. The runtime refuses a mismatched environment/host combination.
Each venue has independent staging and production mappings. Complete property,
room type, rate plan, initial ARI, and webhook setup before pressing **Activate**.
Production also requires recorded Channex approval. **Pause** stops outbound ARI;
the account-wide booking feed remains active to avoid losing reservations.
**Safe disconnect** first sends zero inventory and stop-sell for the 500-day
horizon, then disables the property webhook.
Set `CHANNEX_ALERT_EMAIL` to receive deduplicated health failures and one recovery
notification. Run `php artisan channex:health` to verify this path.
## One-time deployment setup
1. Rotate the API key that was shared during development and set the replacement only in the deployment secret store.
2. Configure:
```dotenv
CHANNEX_ENABLED=true
CHANNEX_BASE_URL=https://staging.channex.io/api/v1
CHANNEX_API_KEY=<rotated-staging-key>
CHANNEX_WEBHOOK_SECRET=<at-least-32-random-characters>
APP_URL=https://<public-zapazime-host>
QUEUE_CONNECTION=database
```
3. Deploy and run:
```bash
php artisan migrate --force
php artisan optimize:clear
php artisan channex:doctor --live
php artisan channex:health
```
4. Keep these processes running under Supervisor, systemd, or the hosting control panel:
```bash
php artisan queue:work --queue=channex,default --tries=5 --timeout=300
php artisan schedule:work
```
In production, a once-per-minute cron entry calling `php artisan schedule:run` can replace `schedule:work`.
## Property onboarding order
Open **Company Admin → Venues → Channex** and, for one test property only:
1. Run **Test Channex connection**.
2. Open the property and complete every readiness item.
3. Click **Prepare mappings**.
4. Click **Sync property**.
5. Click **Sync room types** and verify pooled room counts.
6. Click **Sync rate plans** and verify occupancy, currency, and prices.
7. Open **Preview initial ARI**, inspect the date range and minimum availability, then send it.
8. Click **Register booking webhook**.
Do not connect a live OTA until the staging checks below pass.
## Outbound tests
For the formal self-certification, open the venue's **Certification workspace**.
Assign Twin/Double room roles and the four BAR/Breakfast rate-plan roles, then run
scenarios 1–10 from that screen. Execution is hard-locked to
`staging.channex.io`; every exact request, response, error, and returned Channex
task ID is retained for the submission form. Scenarios 3–8 are each deliberately
sent as one batched request, as required by Channex.
1. Create a future local booking. Within roughly 30–60 seconds, the Channex availability for its room type must decrease for `[check-in, check-out)` only.
2. Modify the booking dates. Both the old and new ranges must reconcile.
3. Cancel the booking. Availability must return.
4. Add and remove a room block. Availability must change without altering `count_of_rooms`.
5. Change a base rate, season, weekday modifier, or restriction. The queued restrictions update must appear in Channex.
6. Mark a physical room out of order. Pooled availability must decrease, while the room-type identity remains unchanged.
Use the property **Delivery health** panel to inspect pending and failed ARI work. Failed records can be replayed without recreating mappings.
## Inbound booking tests
### Official Booking.com staging accounts
List the currently supported test hotel IDs, currencies, and booking URLs:
```bash
php artisan channex:test-booking --accounts
```
Use a hotel whose currency exactly matches every mapped Channex rate plan. Prefer
the EUR hotel `4372137`, GBP hotels `5868189` / `6519420`, JPY hotel `10484818`,
or USD hotel `10485037`. Do not automate hotel `12152494`: Channex documents that
it requires a real payment card. These accounts are shared; if Channex reports
"Channel Already Exists", select another ID or ask Channex support to release it.
Create and map a Booking.com channel in the Channex staging UI, map both rooms and
rates, and activate it. A room-only mapping will not activate. Then create a test
reservation through the URL printed by the command. Booking.com's checkout remains
an intentional human step so CI cannot place an external reservation accidentally.
After checkout, copy the Channex booking `unique_id` and run:
```bash
php artisan channex:test-booking <unique_id> --expect=new --wait=300
```
Modify the same reservation and then cancel it, running these assertions after each
operation:
```bash
php artisan channex:test-booking <unique_id> --expect=modified --wait=300
php artisan channex:test-booking <unique_id> --expect=cancelled --wait=300
```
The verifier polls the authoritative account-wide revision feed while it waits and
passes only when the expected revision has produced a local Zapazime booking. The
queue worker must be running; a received-but-failed or unmapped revision fails with
its delivery error.
1. Create a test booking through a Channex staging channel.
2. Confirm the webhook returns HTTP 200 quickly and a booking revision appears in Delivery health.
3. Confirm one local physical room from the mapped pool is assigned.
4. Confirm the revision becomes `acknowledged` only after the local booking exists.
5. Modify dates or guest details in the channel and verify the same local booking is updated.
6. Cancel it and verify the local booking becomes cancelled and inventory is restored.
7. Temporarily stop the webhook, create another booking, then run `php artisan channex:poll-bookings`; the account-wide fallback must recover it.
8. Test an unmapped room type. It must remain unacknowledged with a visible error instead of creating an unsafe booking.
Guarantee/card data is intentionally discarded. Do not enable card retrieval without a separate PCI-reviewed design with Channex.
## Scheduled operations
- Booking revision recovery: every 15 minutes, once per Channex account.
- Incremental ARI: event-driven, coalesced per property for 30 seconds.
- Full 500-day reconciliation: nightly at 02:30, serialized per property.
- Multi-property full reconciliations are isolated into queue jobs and staggered by
ten seconds, so one property failure cannot abort the account-wide run.
- ARI is proactively limited to 10 availability and 10 restriction requests per
property per minute. A remote 429 or 5xx response pauses that property for one
minute before queue retry.
- Channex rate-limit and server errors use queue retries and backoff.
## Go-live gate
Before production, require all of the following:
- Channex PMS certification scenarios pass.
- The API key has been rotated after staging.
- HTTPS webhook secret validation is active.
- Queue worker and scheduler are supervised and monitored.
- No failed/unacknowledged revision is older than 15 minutes.
- Full-sync payloads remain below the enforced 9.5 MB safety limit.
- Property, room-type, rate-plan, and OTA mappings were manually verified.