Salta ai contenuti

@guestcraft/api

Questi contenuti non sono ancora disponibili nella tua lingua.

GuestCraft’s private, AGPL-3.0-only HTTP boundary: Hono routes, request/response schemas, authentication middleware, RFC 9457 problems and an OpenAPI 3.1 document. The package reads no environment and opens no connections. server/http wires the adapters; apps/web mounts the resulting app under /api. See ADR 0016 for HTTP conventions.

The package entry point exports:

Export Purpose
createApi(dependencies, options?) Build an app from ApiDependencies; call app.request() in tests or mount its handler in a runtime.
ApiDependencies, ApiOptions, ApiEnv and gateway types Describe injected use cases, authentication, request policy, discovery/device services, clock, randomness and logging.
openApiDocument() Generate the contract offline: it registers routes with refusing dependencies, skips createApi’s middleware, runs no use case and needs no database or credentials.
API_REVISION, SERVER_URL Contract revision and the composed /api/v1 base path.
PROBLEM_STATUS, PROBLEM_MEMBERS, FIELD_CODES, problemType and related types/constants Stable public problem codes, status mapping and allowed extension members.
REQUEST_ID_HEADER, DEFAULT_MAX_BODY_BYTES, SCALAR_SCRIPT, ReferenceScript Request-id, body-limit and self-hosted reference configuration.

This composition helper takes already-wired services and passes every dependency explicitly. ApiDependencies requires the tenancy, team, account-security, booking-import, history-import, booking-report, alert, messaging, ARI, enterprise-identity and guest data rights adapters along with the other use cases. Supply the runtime’s cookie-origin policy; it is required even when an embedding uses another authentication mechanism.

import { type ApiDependencies, createApi } from "@guestcraft/api";
export function buildApi(services: ApiDependencies) {
return createApi({
useCases: services.useCases,
properties: services.properties,
reservations: services.reservations,
folios: services.folios,
cashShifts: services.cashShifts,
rates: services.rates,
reports: services.reports,
receivables: services.receivables,
consolidatedReports: services.consolidatedReports,
exchangeRates: services.exchangeRates,
blocks: services.blocks,
housekeeping: services.housekeeping,
housekeepingPlanning: services.housekeepingPlanning,
housekeepingChecklists: services.housekeepingChecklists,
maintenance: services.maintenance,
nightAudits: services.nightAudits,
tenancy: services.tenancy,
team: services.team,
security: services.security,
enterpriseIdentity: services.enterpriseIdentity,
channex: services.channex,
bookingImport: services.bookingImport,
messages: services.messages,
payments: services.payments,
privacy: services.privacy,
ari: services.ari,
channexAlerts: services.channexAlerts,
bookingHistory: services.bookingHistory,
bookingReports: services.bookingReports,
apiKeys: services.apiKeys,
organizationTokens: services.organizationTokens,
clientSessions: services.clientSessions,
oauthApplications: services.oauthApplications,
webhooks: services.webhooks,
eventCatalog: services.eventCatalog,
events: services.events,
principals: services.principals,
auth: services.auth,
cookieRequestAllowed: services.cookieRequestAllowed,
actorNames: services.actorNames,
instance: services.instance,
devices: services.devices,
accounts: services.accounts,
clock: services.clock,
random: services.random,
logger: services.logger,
});
}

The generated API reference and committed OpenAPI document list every method, path, request, response, permission and security scheme. The resource groups below use those tag names; paths in the document are relative to /api/v1. The table uses the app’s own paths (/v1/...); apps/web serves them under /api, and the OpenAPI document lists them relative to its /api/v1 server.

Tags Resources and workflow contracts
system Health and instance discovery. GET /v1/health needs no credentials or database.
devices Device authorization and sessions.
organizations, workspaces Organization/workspace creation, settings, archival, organization Activity and accessible workspace directory.
properties Workspace property setup and reads.
roomTypes, units, guests, reservations, reservationRooms Inventory, guests, reservations, assignments, moves/splits, edge resizing, protected stays, version-checked Undo and stay lifecycle.
calendar, frontDesk, availability Bounded planning, front-desk and availability read models in the reservation contract.
blocks OOO/OOS room blocks.
housekeeping, maintenanceTickets Housekeeping settings, generated days and tasks; maintenance tickets, activity and photos.
rates Rate plans, nightly prices/restrictions and nonholding quotes.
policies Commercial policies, sold terms, no-shows, guarantees and prepayments.
reservations (ota_reports) Reports of an OTA booking’s no-show or invalid card to its channel through Channex.
folios, reservationFolios, folioExtras, folioTaxCategories, folioCreditsDue Reservation ledgers, split folios and transfers, manual settlement, extras, tax categories and credits due.
reports Performance, pickup and cash/folio revenue by service date, JSON and CSV.
consolidated_reports Performance consolidated across a workspace’s or an organization’s properties, JSON and CSV.
exchange_rates The organization’s stored exchange rates that convert consolidated reports (ADR 0014).
night_audits Business dates and audit automation.
cashShifts, cashShiftSettings Cash drawer settings, shifts and reports.
counterparties, receivables Counterparties, open items, receipts, allocations, write-offs, aging and statements.
team Members, invitations and audit, roles and property access, member sign-in locks.
channex Connection/mapping, booking intake and the import of existing bookings, ARI mapping, publication, recovery, drift repair and alerts.
privacy Guest data rights: retention periods with country-pack defaults, legal holds, erasure, access exports and their requests (ADR 0052). Browser sessions only.
messages Channex conversations, replies, attachments, outbox and templates.
api_keys, webhooks, events Workspace API keys with rotation and IP allow-lists, outbound endpoints, signing-secret rotation, tests, delivery history, replay and redelivery, and the events of the last 30 days.
organization_tokens, client_sessions Organization tokens across workspaces, and client sessions minted for front ends (ADR 0047).
authorized_applications The OAuth applications members authorized in the workspace, to list and revoke, browser-only.
enterprise_identity Verified domains, OIDC and SAML single sign-on connections, SCIM tokens and group access (ADR 0055).

GET /v1/openapi.json serves the contract with a five-minute cache. GET /v1/docs serves Scalar using the runtime’s local bundle, a script nonce and a restrictive Content Security Policy. It gives Scalar the copy of the committed document that the web build has processed for that bundle, so that Scalar renders it without processing it first (ADR 0016); its download links to openapi.json. ApiOptions.reference can select a different script, which then processes the document itself, or disable the page; the JSON contract remains available. /auth/* delegates to the injected auth handler in its own format.

  • Browser sessions, device bearer tokens and the integrations’ credentials (workspace API keys, organization tokens and client sessions) are separate credentials. Each operation declares which it accepts. Administration of tenancy, teams, Channex, API keys, organization tokens and webhooks requires a browser session; only an API key or an organization token mints client sessions. Invitation acceptance uses a single-use invitation token. A key or token is constrained by its creator’s live permissions, and a client session by its minting credential’s; the key-management/delivery rules are in the linked integration contract. A client session limited to one reservation, one guest or one property’s public booking reaches only the operations that routes/client-session-scope.ts lists for its scope, with path parameters naming its own objects; authenticate answers any other auth.forbidden and reports it for the audit.
  • crossOrigin answers the CORS preflight of every /v1 operation for any origin, never with credentials, and lets a page read only the answers of requests with a client session’s token (ADR 0047).
  • GuestCraft-Workspace-Id selects accessible workspace context; it grants no permission. Property operations enforce their concrete property scope. Resource writes that require strong ETag/If-Match document the precondition in OpenAPI.
  • The cookie request policy runs before body parsing and authentication. Refusals return request.untrusted_origin (403). Raw encoded paths pass through the middleware; control characters are rejected.
  • Every response has a validated or generated Request-Id. Access logs exclude query strings, cap the encoded path at 2 KB and identify API-key callers by key ID, never the secret.
  • API responses default to Cache-Control: no-store and X-Content-Type-Options: nosniff; a maintenance photo is answered as its bytes with Cache-Control: private, max-age=300, and a guest data export as its ZIP archive, an attachment that stays no-store. The default body limit is 1 MiB, 4 MiB for rates restore and 3 MiB for message attachments and maintenance photo uploads; maxBodyBytes overrides all of them. Limits also apply without Content-Length.
  • Body operations expect supported JSON media types. Send Content-Type: application/json; an unsupported type is 415. An empty JSON body is request.malformed (400). Omitting a required body is request.invalid (400), including schemas whose fields are all optional: send {} for those operations. Optional bodies may be omitted.

API errors use application/problem+json (RFC 9457) with stable type, code and status, a request_id, and only the extension members allowed by PROBLEM_MEMBERS. Clients branch on codes rather than parsing detail. Auth handler responses retain their own format.

Problem titles/details come from the English catalog. Content-Language identifies the chosen language and Vary: Accept-Language marks negotiation; the application ships English only. Unexpected failures answer server.internal (500) without internal error details. Retryable infrastructure failures answer server.unavailable (503), with Retry-After when known. Admission refusals of API keys and device tokens answer auth.rate_limited (429) with Retry-After.

A new problem needs a status in PROBLEM_STATUS, an explicit member list in PROBLEM_MEMBERS (even when empty), and described title/detail entries in packages/i18n/catalogs/en.json. Run pnpm i18n:catalogs; tests check code coverage by the problem catalog and allowed placeholders.

Terminal window
pnpm --filter @guestcraft/api test
pnpm --filter @guestcraft/api typecheck
pnpm --filter @guestcraft/api openapi
pnpm --filter @guestcraft/scripts test:integration test/integration/readme-examples.integration.test.ts

Tests exercise app.request(), middleware and route contracts using injected services and in-memory fakes. The OpenAPI test compares the offline export with the committed artifact; exporting needs no database or credentials. The documentation example check compiles the actual README fences with the package’s strict TypeScript settings. Persistence and isolation are verified separately by database/server integration tests.

Public contract changes flow from these route schemas to OpenAPI, then the generated SDK and React factories; do not edit generated outputs by hand. Contract decisions are recorded in the ADRs; each workflow guide names the revision that introduced it.

Guest duplicate review, two-version merge, consent evidence and owning-property reassignment use the guests tag. See the guest workflow for permission scope, survivor pointers and preserved history.

Guest OTA contact review returns only eligible fields, newest snapshot first. Operators can apply selected fields through ordinary guest replacement or keep a field with PUT /guests/{id}/contact_notice_dismissals/{reservation_id}/{field} using the guest ETag, snapshot revision and expected value. Dismissed values remain suppressed for that identity and field across later snapshots; the field decision is audited without contact values. See the API changelog for problems and recovery.

Night audit settings, configured no-shows and expired tentative options share the durable property-date audit workflow. Cash drawer shifts provide currency-aware opening float, server-linked cash activity and versioned counted closure. See the night audit contract and cash shift contract for public operations, permissions, recovery, persistence and request-woken Vercel scheduling with the daily cron safety net.