Files
wyndham-ARR/.project-docs/20-architecture/system-overview.md
2026-08-06 22:40:18 +08:00

5.2 KiB

System Overview

Current Architecture

ARR2.0 accepts Opera XML plus a separate Booking Tour Code/โรงแรม workbook and owns both deterministic processing lifecycles. It writes immutable private objects, runs the frozen processor locally, independently validates the complete artifacts, and atomically commits accepted facts to PostgreSQL. A pure PRICE_UNMATCHED result instead enters an authenticated, auditable manual-price review state and cannot create Finance facts until the original XML is replayed with a frozen canonical manifest. Downstream analytics and report programs read committed facts. Successful daily commits also create a durable outbox event. A separate worker derives the affected month and watermark from committed ARRIVAL facts, publishes a validated workbook, and records metadata-only report state in PostgreSQL.

Main Components

Component Responsibility
arr_web.auth / authenticated SessionLedger Environment-owned operator credentials, bounded login attempts, random server-side sessions, CSRF and logout revocation
arr_web.programmatic XML upload plus synchronous frozen-review final replay orchestration and safe public error mapping
arr_processing.local / arr_processing.policy Isolated frozen processor execution and approved version/rule identity
arr_storage Immutable staged/committed OSS workflow; all object ACLs private
arr_ingestion.validation Strict v3/v4 delivery/result/structured validation plus independent daily/review-manifest replay
arr_ingestion.postgres Job/review lifecycle, artifact registration, atomic final Finance version commit and outbox
booking_ingestion.excel Bounded Tour Code/โรงแรม extraction, latest-row/cancellation semantics and room-item normalization
booking_ingestion.excel_review_postgres Durable editable draft state and zero-pending atomic current-source activation
arr_web.booking_uploads Private Booking workbook upload, draft review orchestration and privacy-minimized source summaries
arr_web.job_trace Read-only programmatic trace from persisted run/attempt/delivery/version/outbox facts
monthly_reports.worker Dedicated leased outbox consumer with retry/dead-letter behavior
monthly_reports.repository / reporting schema ARRIVAL-derived snapshots, report versions, lineage, manifests and artifact identities
monthly_reports, channel_analytics, company_reports Deterministic downstream consumers of committed facts; company reports build official XLSX files in Python/openpyxl inside Web
Web + Caddy Compose Web-owned login/session boundary behind Caddy HTTPS; no browser-native Basic Auth and no MCP service

Important Boundaries

  • The uploaded source is re-materialized from committed object storage before processing.
  • Login documents/assets, the H5 read-only page/assets, purpose-built public H5 aggregate endpoints, POST /api/login and minimal /healthz readiness are anonymous Web routes. The desktop portal redirects to login; generic business APIs, detailed health, uploads, traces and downloads return 401 without an authenticated server-side session.
  • Operator credentials come only from runtime ARR_WEB_USERNAME / ARR_WEB_PASSWORD; the application fails closed when either is absent. Authenticated mutations also require the per-session CSRF token.
  • Processor exit code and JSON status must agree; output paths are confined to an isolated temporary directory.
  • Validation completes before the database transaction; any transaction failure leaves no partial active version.
  • review_required is valid only for a non-empty error set entirely composed of PRICE_UNMATCHED. It records neither a Finance version nor an arr.processing_failed/monthly event; a final manual value is limited to the verified missing key and is entered as a non-negative integer (including 0) before exact .00 storage/manifest normalization.
  • All review mutations use the authenticated session plus CSRF protection and optimistic revision checks. Finalization is idempotent; infrastructure failures retain the frozen manifest for retry, while deterministic replay failures close the case and job as failed.
  • Booking uploads create review drafts first. Only an explicit activation with no retained pending items can atomically create immutable Booking facts and switch booking.current_source_batch; an open draft blocks company-report creation.
  • Only recognized transient PostgreSQL concurrency errors receive bounded transaction retries.
  • PostgreSQL state, not HTTP/console output, is authoritative for success.
  • Daily and new report downloads are read from OSS and rechecked; historical local report artifacts remain readable through the controlled project-root fallback with the same size and SHA-256 checks.
  • Fresh uploads are new jobs/versions; exact delivery replay is idempotent.
  • Monthly success is acknowledged only after both artifacts are registered and the publication is active; replay of the same snapshot returns the existing report.

Last Updated

2026-08-06