TravelQ Hotel Admin — Kiến trúc microservice

Đề xuất self-host Holitech Linux · thiết kế only · 07/11/2026 (Asia/Saigon)

Mã tài liệuTravelQ-HotelAdmin-Kien-truc-Microservice-20261107
Đối tượnganh Long · đội kỹ thuật Holitech
Phạm viThiết kế kiến trúc · không mã ứng dụng · không deploy · không credential
Hạ tầng mục tiêuSelf-host Linux Holitech · không Cloudflare Pages/Functions/D1/TURN mint
Nguồn đối chiếuHợp đồng Spa/KT OFFLINE; audit Linux 07/11; manifest nguồn TEST t368 (250/250, aggregate c3ca7ab08ca8a17f) — đường dẫn tương đối trong kho tài liệu, không nhúng secret
Mọi mốc thời gian/công sức là ước lượng lập kế hoạch, không phải cam kết giao hàng hay chi phí. Không tuyên bố chứng nhận danh tính TQID/provider; gateway TQID là ranh giới ngoài kèm kiểm thử tích hợp hiện có. Tài liệu không nêu số liệu hồ sơ TQID hay khẳng định dữ liệu thật/giả của provider.
Giả định nguồn của bản này: đọc hợp đồng Spa/KT + đề xuất transport OFFLINE; audit khả thi Linux + provenance hash; đối chiếu nghiệp vụ từ cây nguồn TEST đã pin. Không đọc/chép secret. Bản này dùng sự thật đã có lúc soạn.

1. Mục tiêu điều hành và phạm vi

1.1 Mục tiêu

1.2 Trong / ngoài phạm vi

Trong phạm vi

Catalog ~14–16 miền; ma trận sở hữu dữ liệu; luồng bắt buộc; bảo mật; vận hành; lộ trình & rủi ro. Phân biệt UI bộ phận với backend miền — UI riêng không đồng nghĩa một microservice mỗi tab.

Ngoài phạm vi

Viết mã, migration chạy thật, deploy, provisioning, đọc secret, gửi tin ngoài. Chứng nhận cổng thanh toán / khuôn mặt / encoder / attestation (chưa nghiệm thu). App TravelQ ID trung tâm thuộc biên ngoài.

2. Hiện trạng đã xác minh vs đề xuất

Sự thật kỹ thuật từ audit 07/11/2026 (chỉ đọc). Đề xuất audit cũ Node + SQLite một máy phục vụ port monolith tối thiểu — bị thay bởi quyết định viết lại microservice; stack dưới chọn PostgreSQL per-service.

Hạng mụcHiện trạng đã kiểmĐề xuất microservice
Kiến trúcSPA + CF Pages Functions; D1 SQLite; chưa microserviceAPI Gateway/BFF + dịch vụ miền
API / schema4 tiền tố API; 10 bảng core; Friends DB tùy chọnOpenAPI theo dịch vụ; schema tách
KV / R2 / DO / Queues / TelegramKhông thấy phụ thuộc bắt buộc trong cây đã ràKhông giả định; kiểm kê nếu phát hiện thêm
Thanh toán / hoànChưa gateway verified; mô phỏng fail-closedLedger riêng + webhook; OFF đến khi có contract
Spa / KT least-privỨng viên OFFLINE đã review core; chưa live / GUI E2EUI riêng + Dept Exec + Attestation
Attestation QLChưa có endpoint / contract triển khaiDịch vụ Attestation; fail-closed trước đó
TQID / Face / EncoderProxy ngoài; face/encoder OFFGateway tối thiểu; thiết bị giữ OFF
TURNMint CloudflareTURN tự host (coturn / provider duyệt)
Frontend nghiệp vụCheck-in / booking / đơn / bảng bộ phận / báo cáo / cổng xuất: có theo hợp đồng nguồnKhông đồng nghĩa E2E production đã đạt

3. Sơ đồ kiến trúc đề xuất

Sơ đồ kiến trúc microservice Hotel Admin self-host

Hình 1. Lớp UI riêng · Gateway/BFF · 16 miền dịch vụ · RabbitMQ outbox/inbox · Postgres per-service · ranh giới ngoài (TQID, cổng TT, thiết bị). SVG vector nhúng — không phụ thuộc Mermaid ngoài.

4. Catalog miền (~16) và sở hữu dữ liệu

Nguyên tắc: mỗi dịch vụ sở hữu schema, credential, backup riêng. Ban đầu có thể một cluster Postgres trên một máy nhưng cấm bảng dùng chung và cấm SQL join xuyên database. Giao tiếp liên miền bằng API phiên bản hóa + sự kiện.

#Dịch vụDB logicLệnh / sự kiệnTrách nhiệm chínhKhông làm
01Auth · Tenantauth_*Login, revoke, versionRBAC+ABAC hotel/dept; MFA adminPII khách; tiền
02TQID Gatewaytqid_*Resolve, proxy scopedPII tối thiểu; fail-closedLưu hồ sơ đầy đủ; chứng nhận provider
03Booking · Staystay_*CheckIn, Assign, CheckoutHolder policy; gọi cổng LegalCấp quỹ; thu tiền
04Inventoryinv_*AllocateOnPaidCấp phòng nguyên tử; chống oversellUser-hold; hoàn HV
05Pricing 4-mắtprice_*Propose / Approve / PublishHai tài khoản cá nhân độc lập, không tự duyệt; KS chỉ xemKS tự duyệt giá phòng
06Payments · Refundspay_*Intent, Verify, Refund1 tài khoản KS; mã động; ledgerMark hoàn sớm; áp hoàn DV lên HV
07Orders · Catalogorder_*Create, Cancel(cho), FeatSnapshot giá; tắt feat chỉ đơn mớiDispatch khi chưa paid_verified (prepaid)
08Dept Executiondept_*AdvanceStepBếp / HK / Spa / KT; expectedStep CASChốt attestation; thanh toán
09Attestationattest_*AttestCompletionĐề xuất: cổng hoàn tất dịch vụ (không xoá ledger paid)Bypass bằng login manager; không thay sổ cái tiền
10Notificationsnotify_*ReminderDueNhắc 15 phútTự bịa kênh Telegram (chưa có)
11Reportingreport_*ProjectFromEventsRead-model đối soátGhi đè ledger
12Legal · Residencelegal_*Upsert, AuthorizedExportPII mã hóa; audit xuấtFull PII trên UI thường
13Friends · Consentfriends_*OptIn / OutScope tùy chọnTrộn DB vận hành KS
14Mediamedia_* + MinIOPutObjectMetaUpload có phépLog body; lưu định danh thô không mã hóa
15Call Signalingcall_*Offer / Answer metaP2P + TURN tự hostMint Cloudflare
16Audit · Policyaudit_*Append, VerifyChainAppend-only; correlation-idUPDATE / DELETE audit

4.1 Biên nhất quán mạnh (không tách sai)

5. Stack đề xuất (self-host)

Thành phầnLựa chọnLý do
RuntimeNode.js LTS + TypeScriptGần logic JS hiện có; OpenAPI nhanh với đội nhỏ
APIREST + OpenAPI 3; gRPC nội bộ tùy chọngRPC chỉ khi đo được lợi ích latency/streaming
DBPostgreSQL per-serviceĐa instance / concurrency; PITR. Không SQLite cho microservice đa tiến trình. (Đề xuất SQLite audit = port monolith cũ — không áp dụng ở đây.)
BusRabbitMQ + Outbox / InboxHàng đợi bền, DLQ, pattern tài chính quen thuộc trên Compose; chọn thay NATS vì đội nhỏ ưu tiên độ chín saga tiền
CacheRedis tùy chọnEphemeral (rate-limit, cache); không chân lý tiền
ObjectMinIO (S3-compatible)Upload nội bộ DC Holitech
TLS / SecretNginx hoặc Caddy; Docker / K8s secretsKhông Cloudflare; không secret trong image / log / PDF
OrchestrationDocker Compose trước; K8s khi cần HA thậtMột host ≠ HA
Quan sátOpenTelemetry → Prometheus + Grafana + LokiCorrelation-id; redact PII
BackupPG PITR + MinIO mã hóa + restore drillMục tiêu đề xuất: RPO ≤ 15 phút · RTO ≤ 4 giờ — chưa đạt, chỉ mục tiêu

Outbox ghi cùng transaction miền; consumer Inbox theo idempotency key — chống double-pay / double-allocate. Tên biến môi trường (names-only, không giá trị): ví dụ AUTH_DATABASE_URL, PAY_DATABASE_URL, RABBITMQ_URL, MINIO_ENDPOINT — Holitech chọn sau khi chốt runtime. Docker/Compose chưa cài trên máy audit hiện tại — cần môi trường riêng khi triển khai sau này.

6. Luồng nghiệp vụ bắt buộc (sơ đồ)

Luồng mua phòng và đơn dịch vụ prepaid

Hình 2. Luồng A (mua phòng) và Luồng B (đơn prepaid → ledger paid → attestation hoàn tất). HV tuyệt đối không hoàn/huỷ.

6.1 Mua phòng — không user-hold

  1. Khởi tạo thanh toán → mã động TTL 60 giây, không hold quỹ theo phiên user.
  2. Hết hạn → intent expired; provider đến muộn → quarantine + reconcile; không tự coi đã bán.
  3. Chỉ PaymentVerified (chữ ký webhook, đúng merchant KS, đúng amount/order, chống replay) → Inventory Allocate nguyên tử.
  4. Verified-paid mới đếm quỹ đã bán. Paid nhưng hết phòng → quarantine; xử lý theo policy TA/dịch vụ nếu được phép — tuyệt đối không hoàn/huỷ HV. Đây là design question mở, không “lặng hoàn”.

HV: không hoàn, không huỷ. TA: ngoại lệ chỉ highest TravelQ admin (không manager/LT). Quy tắc hoàn dịch vụ không áp blanket lên HV.

6.2 Đơn → tiền (ledger) → LT → bộ phận → attestation hoàn tất → báo cáo

  1. Tạo đơn (snapshot giá server).
  2. Prepaid (Bếp đồ ăn/uống; Spa): paid_verified trước LT dispatch. HK: đồ dùng miễn phí; giặt là trả phí theo rule.
  3. LT dispatch → Dept Advance + expectedStep; non-terminal. LT không đánh dấu hoàn tất bộ phận. Nhắc sau 15 phút.
  4. Đề xuất: Attestation QL là cổng hoàn tất dịch vụ — không xoá / không thay sổ cái đã paid_verified. Hiện chưa có contract → fail-closed cho bước hoàn tất.
  5. Dịch vụ đã trả bị từ chối: RefundRequested → gọi provider → RefundSettled chỉ khi verified; retry idempotent; không mark sớm; không double-count.
  6. Báo cáo / đối soát tách: paid · completed · refund_pending · settled. Ghi nhận kế toán doanh thu cần xác nhận tài chính.

Mọi khoản về một tài khoản nhận tiền đích KS. Không cash / nợ phòng / manual-paid. Mỗi giao dịch: mã động hotel / order / amount. KS bật/tắt nhóm đơn: chỉ đơn mới; giữ lịch sử. KS VIEW giá; TravelQ maker/checker = hai tài khoản cá nhân độc lập, không tự duyệt (mật khẩu dùng chung ≠ hai tài khoản độc lập).

6.3 Hiển thị danh tính & xuất pháp lý

7. Bảo mật (đề xuất)

8. Vận hành · quan sát · sao lưu

9. Lộ trình · ước lượng · rủi ro

Giả định đội: 2–3 engineer full-stack + 0.5 ops quen Node/Postgres; song song với xác nhận nghiệp vụ từ anh Long. Đơn vị: person-week (pw). Không hứa ngày calendar / chi phí tiền. Không bịa số liệu test/CI hiện tại.

Giai đoạnDeliverableAcceptance (không %)Ước lượng
G0 ChốtBiên dịch vụ + quyết định race HV + app con ngày 1Biên bản xác nhận viết1–2 pw
G1 NềnCompose, Gateway, Auth, Audit, OTelHealth + login fail-closed + audit append3–5 pw
G2 Phòng & tiềnInventory + Payments ledger (adapter lab kiểm soát)Không oversell test đua; HV không hoàn5–8 pw
G3 Ở & đơnBooking/Stay + Orders + Dept + NotifyPrepaid + reminder 15p + CAS5–8 pw
G4 Giá & BCPricing 4-mắt + ReportingHai tài khoản độc lập, không tự duyệt; KS view-only2–4 pw
G5 PII & ngoàiLegal cổng; TQID gateway; TURN tự hostExport có audit; TQID fail-closed3–5 pw
G6 Cứng hóaAttestation (cổng hoàn tất); chaos/idempotency; restore drillHoàn tất dịch vụ có attest khi bật; ledger paid độc lập; restore đạt mục tiêu giấy3–5 pw

Tổng thô: ~22–37 pw (ước lượng lập kế hoạch). Với giả định đội 2–3 engineer, quy đổi thô ~8–19 tuần trước các trễ bên ngoài (gateway/TQID/pháp lý/onboarding) — không phải cam kết ngày giao.

9.1 Rủi ro chính

  1. Onboarding cổng thanh toán / merchant từng KS.
  2. Contract TQID & thay TURN khỏi Cloudflare.
  3. Khuôn mặt / encoder — giữ OFF đến khi có hardware + contract.
  4. Xuất pháp lý & retention PII.
  5. Race inventory ↔ payment (đặc biệt HV).
  6. Migration JSON-state monolith → DB tách / nhất quán phân tán.
  7. Ops single-host (backup / restore / disk / secrets).

9.2 Phải xác nhận nghiệp vụ trước khi code

10. Thuật ngữ

Thuật ngữNghĩa trong tài liệu
MicroserviceDịch vụ deploy độc lập, sở hữu DB logic riêng, giao tiếp API / sự kiện
Outbox / InboxGhi sự kiện cùng transaction; consumer khử trùng idempotent
paid_verifiedThanh toán đã xác minh bởi provider / webhook — không phải tự khai UI
ABACKiểm soát truy cập theo thuộc tính (hotel, dept, account-version)
4-mắtMaker và checker phải là hai tài khoản cá nhân độc lập; không tự duyệt
HV / TAHạng quỹ phòng theo nghiệp vụ TravelQ; HV không hoàn / huỷ
RPO / RTOMục tiêu mất dữ liệu tối đa / thời gian phục hồi tối đa (chưa đạt)
Fail-closedThiếu contract / secret / provider → từ chối, không mock production
QuarantineTrạng thái giữ kết quả tiền/phòng chưa quyết — chờ reconcile, không tự bán / tự hoàn HV

11. Kết luận

Đây là bản thiết kế đề xuất để Holitech self-host theo hướng microservice, kế thừa hợp đồng nghiệp vụ đã biết từ nguồn Hotel Admin hiện có, đồng thời không tuyên bố đã triển khai, đã nghiệm thu cổng thanh toán, khuôn mặt, encoder, attestation, hay chứng nhận danh tính TQID. Sự thật đã kiểm (monolith CF+D1, 4 API, 10 bảng core, không KV/R2 bắt buộc trong phạm vi rà, payment/face/encoder/attestation chưa xong) được tách rõ khỏi phần đề xuất.

Bước tiếp theo: anh Long và Holitech chốt các câu hỏi mục §9.2, rồi mới mở giai đoạn G0 / G1.