4.3 KiB
4.3 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. 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 |
Terminal upload 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 delivery/result/structured validation plus independent daily validation |
arr_ingestion.postgres |
Job lifecycle, artifact registration, atomic 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/loginand minimal/healthzreadiness are anonymous Web routes. The desktop portal redirects to login; generic business APIs, detailed health, uploads, traces and downloads return401without 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.
- 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 downloads are read from OSS and rechecked; monthly downloads resolve only registered active/superseded local artifacts and recheck path, size and SHA-256.
- 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.
Related Decisions
Last Updated
2026-08-03