5.6 KiB
Data Flow
Web Access Boundary
- An anonymous browser requesting
/is redirected to/loginwith an allowlisted return target./h5and its H5 assets are public; anonymous access is limited to/api/public/h5/months,/api/public/h5/analyticsand the no-detail/healthzsignal. Other anonymous API/download requests receive JSON401 AUTH_REQUIRED. POST /api/loginaccepts strict same-origin JSON, verifies runtime-owned credentials under a bounded per-client attempt ledger and issues a random server-side session plus CSRF token in anHttpOnly,SameSite=Strictcookie.- Every desktop portal page, detailed health response, generic read API, upload/mutation, task trace and artifact download validates the authenticated session. Public H5 endpoints return only sanitized aggregate dashboard data; mutations additionally validate the session CSRF token.
POST /api/logoutvalidates CSRF, revokes the server-side session and expires the cookie./healthzremains a no-detail anonymous readiness signal for container orchestration.GET /api/history-monthsis an authenticated read-only discovery path. It combines daily processing/monthly publication counts from PostgreSQL with durable company-job counts; each desktop history then reads its selected month through the existing paged list endpoint.
Primary XML Flow
| Step | Source | Destination | Gate |
|---|---|---|---|
| 1 | Browser XML upload | Uploaded-basename task provenance + private canonical source object + queued DB job | Filename/content/size and immutable object identity |
| 2 | Committed source object | Isolated processor input | Materialization rechecks stored bytes |
| 3 | Fixed process_daily.py |
Daily/result/structured or failure artifacts | Timeout, confined paths, exit/JSON agreement |
| 4 | Local artifacts | Private committed OSS objects | Role, MIME, size and SHA-256 |
| 5 | Canonical DeliveryEnvelope |
DeliveryValidator |
Strict Schema, reconciliation, source/artifact hashes and independent validation |
| 6 | Verified delivery | PostgreSQL Finance facts | Serializable atomic commit/version activation |
| 7 | Accepted/failed run | Task trace and outbox | Persisted state is authoritative |
| 8 | arr.daily_version_committed |
Dedicated monthly worker | Lease, SKIP LOCKED, bounded retry/dead-letter |
| 9 | Retained Finance ARRIVAL facts |
Monthly snapshot request | Affected month from event version; “更新至” is max included ARRIVAL |
| 10 | Monthly snapshot | XLSX/result + reporting metadata |
Formula reopen-validation, current-pin recheck, atomic activation |
| 11 | Registered active report | Web list/download + outbox acknowledgement | Real report ID; visible monthly tab polls automatically; path/size/SHA-256 recheck before download |
State Ownership
- PostgreSQL owns job/attempt/delivery state, Finance facts, current version and outbox.
- PostgreSQL
reportingowns monthly publication versions, daily-version lineage, channel manifest and artifact identities; it does not duplicate monthly business rows. - OSS owns immutable source/output bytes; ARR stores only controlled object identities in the database.
processing_runs.uploaded_filenameowns the user-facing browser basename; the source artifact remains canonically namedsource.xmlfor processing and validation.- Temporary processor/validator paths are deleted after each request.
- Monthly XLSX/result bytes live in immutable local archive paths on the current shared output volume; generated report artifacts are derived outputs, not an alternative business fact source.
Booking Source And Company-Report Flow
| Step | Source | Destination | Gate |
|---|---|---|---|
| 1 | Authenticated Booking XLSX upload | Bounded parser 2.0 | Requires Tour Code + exact โรงแรม, latest-row/cancellation semantics and room-item extraction/review |
| 2 | Parsed raw items | Private artifact + extraction draft | Live migration 015 preserves source coordinates, confirmed/pending/deleted item state and extracted values |
| 3 | Human review | Draft item updates | Confirm/edit or atomically soft-delete 1-50 unique selected items while canonical current Booking source remains unchanged |
| 4 | Fully reviewed draft | Accepted canonical batch + booking.current_source_batch |
Live 014/015 plus repository zero-pending/atomic activation; real PostgreSQL transaction-only vertical slice passes |
| 5 | Current Finance facts | Company-report stay segments | Finance supplies company/channel/dates/pricing; normalized Group Code is the Booking lookup key; open draft blocks new job |
| 6 | Current Booking room summary | Booking Room output |
Sum by Group Code + room type; missing or unmatched Group Code leaves Booking Room blank |
Migrations 014/015 are formally applied: batch 1 is the current source and the draft tables are empty. The source contains a PostgreSQL draft repository, backend routes, browser editor and GET/POST/PATCH/DELETE transport coverage. A real-PostgreSQL transaction-only probe created a draft, confirmed its pending item, activated immutable facts and then rolled everything back, preserving the current source and leaving no synthetic residue. First activation of an actual operator workbook remains a controlled business action.
Monthly Derivation Boundary
The worker never infers a date from an XML filename or the current clock. It treats the event's daily_version_id only
as a lookup key, derives scope from retained Finance ARRIVAL, and verifies that the generated report's maximum arrival
equals its persisted as_of_date. Every data-row TOTAL PRICE cell is =R[row]*C[row]*G[row].
Last Updated
2026-07-31