Salta ai contenuti

@guestcraft/channex

Questi contenuti non sono ancora disponibili nella tua lingua.

GuestCraft’s AGPL adapters from the portable Channex client to the ports of @guestcraft/core/channex. server composes these factories with credentials and ownership checks. Core owns permissions, transactions, recovery and publication policy; this package owns bounded HTTP calls and safe boundary conversion (ADRs 0002 and 0022).

Every port call takes a ChannexKey: the API key and the Channex environment that verified it (staging for a sandbox workspace, production otherwise; ADR 0050). All factories build their clients through channexClient (src/client.ts), which sends the key to its own environment’s base URL and nowhere else. Factories accept an optional injected fetch; simulator calls require that transport injection, and no factory exposes a base-URL override. Message attachment links are kept only on the key’s own host.

Factory Port responsibilities
channexRemote(fetch?) Validate a key (channex.key_refused with its environment for a 401, 403 or 404), list property summaries, scan required properties; no partial complete-list result
bookingImportRemote(fetch?) Revision feed/history/current reads, a property’s revision history 100 per page, room discovery, acknowledgements and property booking-webhook registration/removal
ariRemote(fetch?) Settings/plan discovery, absolute availability/restriction writes, task outcomes, a property’s recent tasks, read-back of current values and safe pacing/warning metadata
messageRemote(fetch?) Messages installation, property feed, request events, conversations, sends, attachments, no-reply status and webhook registration/cleanup
cardTokenizationRemote(fetch?) Core’s CardTokenizationRemote (ADR 0054): the Stripe payment method of an OTA booking’s card, the Stripe Tokenization App’s one documented operation (the operator installs the app in Channex’s interface)
bookingReportRemote(fetch?) One Booking Reporting call per report (no-show, invalid card, cancel due to invalid card): sent, a definite refusal (not_supported, invalid_arguments, booking_not_found, access_refused), or ChannexUpstreamError with retry facts; an unreadable success, a 408 or 5xx, or a lost answer is an unknown outcome

channexRemote uses five-second attempts and one GET retry, with a 15-second validation deadline and 20-second property discovery/scan deadlines. bookingImportRemote uses four-second attempts without retries, except acknowledgements and 100-revision history pages allow ten seconds. messageRemote uses five-second attempts and one GET retry with its wait capped at one second; cardTokenizationRemote uses five-second attempts and never retries its write. ariRemote uses four-second reads without retries and payload-size-based write timeouts of 6–16 seconds. bookingReportRemote uses one ten-second attempt per report, never retried.

Connection validation reads one property and retains only the total. Complete account property discovery is bounded to 50 pages of 100. Shared-account summary discovery reads individually selected properties. The domain fences ownership before revision reads, acknowledgements and webhook deletion; see ADR 0028’s shared-account rules for recovery scope.

Booking normalization handles offset-less provider timestamps and passes the OTA guest language through raw; core canonicalizes it during projection. It passes payment_collect, payment_type and the client’s reduced guarantee (card type, last four digits, expiry, virtual flag and virtual-card details) to core; the card number, security code, holder’s name and token never reach this package. Rejected revisions contain safe identity metadata only; unreadable entries retain at most an outer ID. Core decides durable quarantine, projection and acknowledgement. Rejected upstream bodies and card data are discarded. Optional customer data may be absent or null; projection sanitization belongs to core.

Connection failures return safe domain results. Booking operations translate client failures to ChannexUpstreamError; local normalization runs outside that translation. For client failures, connection, booking and ARI ports omit provider error bodies and transport causes. cardTokenizationRemote returns only a failure kind: forbidden (403: the app is not installed on the booking’s property, or not allowed), not_found, rejected (another refusal Channex explained), unavailable (nothing happened) or unknown (a payment method whose answer was lost, timed out, was a 408/5xx or unusable may have been made). Messages translates client failures to MessageRemoteError with a reason, retryability and unknown-outcome flags, but retains the entire ChannexError as cause, including provider error fields and any transport cause. ARI reads turn a client failure into ChannexUpstreamError with the client’s retry facts (a refused key or an invalid response is not retryable; a 429/5xx keeps Retry-After), let local bugs pass unchanged, and report an unsupported property currency as channex.currency_unsupported (ADR 0008, ADR 0034). ARI writes return pacing and outcome information; a lost or malformed write response cannot be reported as confirmed synchronization. ARI read-back turns core’s half-open nights into Channex’s inclusive date range and answers one value per target and night. A restriction’s stop_sell is Channex’s stop_sell_manual, the explicit closure, because Channex’s stop_sell also reports zero availability or rate; fields Channex does not return are left out, and a property the key cannot reach reads as no values. Channex documents one read-back rate per plan and night, also for a per-person plan whose writes carry per-occupancy rates; core treats it as the main option’s rate, an unverified assumption. Plan discovery returns each plan’s rate mode, occupancy options (main option, and whether Channex derives the option’s rate) and child and infant fees as decimal strings; an integer fee is read as minor units of the plan’s currency (unverified). Settings carry agePolicy, the ages of the property’s hotel policy (infantMaxAge, childrenMaxAge, each nullable), or null when the property has none; a failed policy read fails the settings read rather than guess.

Import, mapping, recovery, unlink cleanup, outbound ARI and messaging depend on the composed core/db/server/API/UI workflow. These factories do not start workers or persist anything. Current supported behavior and remaining operational limits are documented in booking import, ARI publication and Messages. Simulator evidence is not provider certification or proof of live channel delivery.

Terminal window
pnpm --filter @guestcraft/channex test
pnpm --filter @guestcraft/channex typecheck

Adapter tests inject the independent simulator or a scripted transport; no account is needed. Server integration suites under packages/server/test/integration cover the composed Channex, booking-import and Messages paths with real PostgreSQL/PgBouncer. Run those suites one at a time. Built-app Channex browser scripts and their setup are documented in the web README.