Bỏ qua

Kiến Trúc Hệ Thống — GovData: Nền Tảng Quản Lý, Quản Trị Dữ Liệu Thành Phố

Phiên bản: 1.0 Ngày tạo: 2026-04-08 Trạng thái: Draft — Chờ Tech Lead xác nhận Nguồn: Phương Án Kỹ Thuật, ADRs, Business Understanding, TSD v1.3 (tham khảo)


Mục Lục

  1. Tổng Quan Kiến Trúc
  2. Sơ Đồ C4
  3. Mô Tả Thành Phần
  4. Luồng Dữ Liệu
  5. Failure Modes & Phục Hồi
  6. Kiến Trúc Bảo Mật
  7. Crosscutting Concerns
  8. Khả Năng Mở Rộng
  9. Triển Khai & Vận Hành
  10. Giám Sát & Observability
  11. Sao Lưu & Khắc Phục Sự Cố
  12. Mô Hình Chi Phí
  13. Sổ Rủi Ro
  14. Lộ Trình Phát Triển
  15. Giả Định & Ràng Buộc
  16. Kết Quả Validation Kiến Trúc

1. Tổng Quan Kiến Trúc

Mô Hình Kiến Trúc

Modular Monolith (ADR-002) — Một đơn vị deploy duy nhất (Spring Boot JAR) chứa các module có ranh giới rõ ràng. Matching Service (Python/FastAPI) là ngoại lệ duy nhất chạy như service riêng biệt.

Lý do: - Đội 2 Senior Fullstack — cần đơn giản, không quá nhiều service - On-premise, không có đội Ops riêng — Docker Compose đủ - Ranh giới module cho phép tách service ở GĐ2 nếu cần

Architecture Drivers (từ Phương Án Kỹ Thuật)

# Driver Ưu tiên Ảnh hưởng kiến trúc
D1 Bảo mật & Tuân thủ Thiết yếu Keycloak dual-mode, RBAC+ABAC, audit 100%, TLS
D2 Tính chính xác Thiết yếu Human-in-the-loop, DISPUTED guard, confident score
D3 Developer Experience Cao Modular Monolith, Spring Boot, Java 21 Virtual Threads
D4 Đơn giản vận hành Cao Docker Compose 2 VM, PostgreSQL thay ES, Redis thay RabbitMQ
D5 Độ tin cậy Cao PostgreSQL replication, health checks, retry patterns

Tổng Hợp Công Nghệ

Tầng Công nghệ Phiên bản ADR
Frontend Next.js (App Router) + shadcn/ui + Tailwind CSS 4 16.x ADR-006
Backend chính Java 21 + Spring Boot 4.0.5 (Virtual Threads) 4.0.5 ADR-002
Matching Service Python 3.12 + FastAPI 0.111.x ADR-010
Auth Server Keycloak 24 (dual-mode) 24.x ADR-001
Database PostgreSQL 18.3 (Primary + Replica) 18.3 ADR-004
Cache + Queue Redis 8.6.2 8.6.2 ADR-009
File Storage Local filesystem (Docker volume)
Reverse Proxy NGINX 1.25 1.25.x
Giám sát Prometheus + Grafana + Loki latest
CI/CD Jenkins latest
Container Docker + Docker Compose 25.x ADR-007

2. Sơ Đồ C4

2.1 System Context Diagram (Level 1)

Kroki

Mô tả: Hệ thống GovData là trung tâm — phục vụ 5 loại người dùng. Keycloak xử lý xác thực (dual-mode). SSO IdP là hệ thống bên ngoài tùy thuộc vào hồ sơ pháp lý. Nền tảng phân tích DL là downstream consumer.

2.2 Container Diagram (Level 2)

Kroki

Mô tả: NGINX là điểm vào duy nhất (port 443). Frontend (Next.js) phục vụ UI. Backend chính (Spring Boot) là Modular Monolith chứa 11 module. Matching Service (Python) chạy riêng biệt, giao tiếp qua REST nội bộ. PostgreSQL có Primary + Replica. Redis phục vụ cache và job queue.

2.3 Component Diagram (Level 3) — Backend Chính

Kroki

Mô tả: Backend chính gồm 11 module với ranh giới rõ ràng. Mỗi module chỉ expose API qua interface trong package api/. Giao tiếp cross-module qua Spring ApplicationEvents. Module-shared chứa domain models chung và audit logging.


3. Mô Tả Thành Phần

3.1 Frontend (Next.js)

  • Mục đích: Cung cấp giao diện web cho tất cả actors
  • Công nghệ: Next.js 16 (App Router) + shadcn/ui + Tailwind CSS 4 + TanStack Query
  • Trách nhiệm: SSR/SSG, routing, state management, gọi REST API
  • Phụ thuộc: Backend chính (REST API), Keycloak (PKCE auth flow)
  • Failure Impact: Nếu sập → user không truy cập được UI. Backend API vẫn hoạt động
  • Data Owned: Không — chỉ là presentation layer

3.2 Backend Chính (Spring Boot Modular Monolith)

  • Mục đích: Xử lý toàn bộ business logic, expose REST API
  • Công nghệ: Java 21 (Virtual Threads) + Spring Boot 4.0.5 + Spring Data JPA + Hibernate
  • Trách nhiệm: 11 module (xem Level 3 diagram), audit logging, event publishing
  • Phụ thuộc: PostgreSQL, Redis, Keycloak, Matching Service
  • Failure Impact: Nếu sập → toàn bộ nghiệp vụ dừng. Frontend hiển thị lỗi kết nối
  • Data Owned: Toàn bộ business data (metadata, mappings, workflows, audit)
  • API Surface: /api/v1/* — RESTful, JWT auth, pagination, response wrapper

3.3 Matching Service (Python/FastAPI)

  • Mục đích: Scoring engine cho AI matching — đối chiếu fields với Anchored Data
  • Công nghệ: Python 3.12 + FastAPI + psycopg3
  • Trách nhiệm: Rule-based scoring (synonym + trigram + levenshtein), data type compatibility check
  • Phụ thuộc: PostgreSQL (read-only Anchored Data)
  • Failure Impact: Nếu sập → matching không khả dụng. Các chức năng khác vẫn hoạt động bình thường
  • Data Owned: Không — scoring results lưu qua Backend chính
  • API Surface: POST /match — nhận danh sách fields, trả kết quả scored

3.4 Keycloak

  • Mục đích: Auth Server tập trung — dual-mode (local + SSO)
  • Công nghệ: Keycloak 24 + PostgreSQL riêng
  • Trách nhiệm: Xác thực user, phát hành JWT, quản lý realm, Protocol Mappers (org_id, unit_id)
  • Phụ thuộc: PostgreSQL (DB riêng cho Keycloak), SSO IdP (khi sẵn sàng)
  • Failure Impact: Nếu sập → không đăng nhập được. JWT hiện có vẫn hợp lệ đến khi hết hạn
  • Data Owned: User credentials, realm configuration, SSO federation config

3.5 PostgreSQL (Primary + Replica)

  • Mục đích: Single source of truth cho toàn bộ business data
  • Công nghệ: PostgreSQL 18.3 + streaming replication + pg_trgm + fuzzystrmatch
  • Trách nhiệm: Lưu trữ metadata, mappings, audit log, workflow state
  • Failure Impact:
  • Primary sập → không ghi được. Failover thủ công sang Replica (RTO < 4h)
  • Replica sập → báo cáo chậm hơn (fallback sang Primary)
  • Data Owned: Toàn bộ persistent data

3.6 Redis

  • Mục đích: Cache + job queue
  • Công nghệ: Redis 8.6.2
  • Trách nhiệm: Session cache, lookup cache (cây tổ chức, Domain tree), matching job queue
  • Failure Impact: Nếu sập → cache miss, phản hồi chậm hơn. Fallback DB trực tiếp. Không mất dữ liệu
  • Data Owned: Không — chỉ là cache layer

3.7 File Storage (Local Filesystem)

  • Mục đích: Lưu trữ file upload (CSV, DDL)
  • Công nghệ: Local filesystem, Docker volume mount (/data/uploads/)
  • Trách nhiệm: Lưu file gốc Discovery
  • Failure Impact: Nếu disk đầy → không upload file mới. File đã parse vào DB không ảnh hưởng
  • Data Owned: File gốc đã upload

4. Luồng Dữ Liệu

4.1 Luồng Xác Thực (Happy Path)

Kroki

4.2 Luồng Xác Thực (Error Path)

Kroki

4.3 Luồng Discovery + Matching (Happy Path)

Kroki

4.4 Luồng Discovery (Error Path)

Kroki


5. Failure Modes & Phục Hồi

5.1 Phân Tích Failure Mode

Thành phần Loại lỗi Ảnh hưởng Phát hiện Phản ứng Thời gian phục hồi
PostgreSQL Primary Sập node Không ghi được Health check 5s Failover thủ công sang Replica; promote Replica < 4 giờ (RTO)
PostgreSQL Replica Replication lag > 15 phút Dữ liệu đọc cũ cho báo cáo Prometheus metric Alert → DBA kiểm tra Tự động khi lag giảm
PostgreSQL Replica Sập node Báo cáo chậm hơn Health check 5s Route tất cả read sang Primary < 1 giờ (restart)
Matching Service Crash/timeout Matching không khả dụng Health check + timeout 60s Retry 3 lần, Circuit Breaker, queue retry < 5 phút (restart)
Matching Service Scoring sai Gợi ý không chính xác Human review phát hiện 100% human review là safety net Không downtime
Redis Sập node Cache miss, matching queue mất Health check 5s Fallback DB trực tiếp; re-enqueue jobs < 5 phút (restart)
File storage (disk) Disk đầy / lỗi I/O Upload file thất bại Disk monitoring Dọn dẹp / mở rộng disk < 1 giờ
Keycloak Sập node Không đăng nhập mới Health check 5s JWT hiện có vẫn hợp lệ; restart Keycloak < 15 phút
NGINX Sập node Toàn bộ hệ thống không truy cập External monitoring Restart NGINX; nếu VM sập → khắc phục VM < 30 phút
Frontend (Next.js) Sập node UI không khả dụng Health check Restart; API vẫn hoạt động < 5 phút

5.2 Resilience Patterns

Pattern Áp dụng cho Cấu hình
Retry with Backoff Matching Service Tối đa 3 lần, exponential backoff (2s, 4s, 8s)
Circuit Breaker Matching Service Threshold: 3 failures liên tiếp, timeout 30s, half-open sau 60s
Idempotency Guard Matching worker WHERE suggested_de_id IS NULL — an toàn khi re-trigger
Per-item Error Handling Parse file, scoring Lỗi 1 field → log WARN, tiếp tục field tiếp theo
Timeout Tất cả external calls Matching: 60s; Keycloak: 5s
Append-only Audit Tất cả write operations REVOKE UPDATE, DELETE ON audit_log
Streaming Replication PostgreSQL Primary → Replica Async replication, lag < 15 phút
Connection Pool PostgreSQL, Redis HikariCP max 20 connections; Jedis pool max 10

5.3 Chiến Lược Graceful Degradation

Phụ thuộc sập Tính năng ảnh hưởng Hành vi degradation Ảnh hưởng user
Matching Service Matching mới Queue job, retry sau. Các tính năng khác bình thường Trung bình — matching chậm
Redis Cache, matching queue Fallback truy vấn DB trực tiếp; jobs mất cần re-trigger Nhẹ — chậm hơn
PostgreSQL Replica Báo cáo, tra cứu Route sang Primary Nhẹ — latency tăng nhẹ
Disk đầy Upload file Báo lỗi, dọn dẹp disk Nhẹ — upload tạm dừng
Keycloak Đăng nhập mới JWT hiện có vẫn dùng được; đăng nhập mới chờ Trung bình — user mới chờ

6. Kiến Trúc Bảo Mật

6.1 Xác Thực

Keycloak Dual-mode (ADR-001):

Luồng Khi nào dùng Chi tiết
Local (username/password) GĐ0 demo, triển khai sớm, SSO chưa sẵn sàng User → Keycloak form → Xác thực local realm → JWT
SSO (SAML 2.0) Khi hồ sơ pháp lý được phê duyệt User → "Đăng nhập SSO" → SAML redirect → IdP xác thực → JWT

JWT Claims structure:

{
  "sub": "user-uuid",
  "email": "owner@soyte.gov.vn",
  "realm_access": { "roles": ["DATA_OWNER"] },
  "org_id": "uuid-so-y-te",
  "unit_id": "uuid-phong-nghiep-vu-y",
  "exp": 1711234567
}

Custom claims org_id, unit_id được thêm qua Keycloak Protocol Mapper — hoạt động cả hai luồng.

6.2 Phân Quyền — PBAC (Policy-Based Access Control)

Hệ thống sử dụng PBAC — mỗi action được đánh giá bằng policy kết hợp nhiều yếu tố, không chỉ role mà còn data ownership, entity state, và business rules.

4 yếu tố đánh giá quyền:

Yếu tố Loại Mô tả Ví dụ
Role RBAC Loại action được phép theo vai trò Manager được chạy matching; Staff chỉ tra cứu
Data Ownership ABAC Quyền phụ thuộc vào quan hệ sở hữu user ↔ dữ liệu Data Owner chỉ xác nhận ô Bảng C thuộc org_id mình
Entity State State Guard Quyền phụ thuộc trạng thái entity Approver chỉ phê duyệt Bảng C khi >70% confirmed AND 0 DISPUTED
Business Rules Policy Quy tắc nghiệp vụ đặc thù Đề xuất mở rộng chỉ trong Domain đã tồn tại; Admin không tự xóa

Ví dụ policy phức hợp:

Policy: "Data Owner xác nhận ô Bảng C"
  ALLOW IF:
    user.role = DATA_OWNER                           -- Role
    AND source_mapping.org_id = user.org_id          -- Data Ownership
    AND source_mapping.current_state IN              -- State Guard
        ('AI_SUGGESTED', 'AI_HIGH_CONFIDENCE', 'DATABASE')
  DENY OTHERWISE → 403
Policy: "Approver phê duyệt Bảng C tổng thể"
  ALLOW IF:
    user.role = APPROVER                             -- Role
    AND confirmed_orgs_percent > 70%                 -- Business Rule (aggregate)
    AND disputed_count = 0                           -- State Guard (aggregate)
  DENY OTHERWISE → 422 (precondition failed)

Luồng đánh giá (Defense in Depth — 5 lớp):

Request → [1] JWT Validation → [2] Role Check → [3] Data Ownership Check
                                  [5] Default Deny ← [4] State Guard + Business Rules
Lớp Kiểm tra Kết quả khi fail
1. JWT Validation Chữ ký + thời hạn JWT 401 Unauthorized
2. Role Check Vai trò có quyền thực hiện loại action này? 403 Forbidden
3. Data Ownership org_id/unit_id user khớp với resource? 403 Forbidden
4. State Guard + Business Rules Entity ở trạng thái cho phép? Điều kiện nghiệp vụ thỏa mãn? 422 Unprocessable Entity
5. Default Deny Không match policy nào 403 Forbidden

Implementation: Spring Security (lớp 1-2) + custom PolicyEvaluator ở Service layer (lớp 3-5). Không cần policy engine bên ngoài (OPA) cho GĐ1.

Ma trận vai trò × action (tóm tắt):

Action Manager Data Owner Approver Staff Admin
CRUD Domain/SubDomain/DE
Upload Discovery
Chạy Matching
Xem Bảng C (toàn bộ)
Xem Bảng C (đơn vị mình)
Xác nhận/từ chối hiện trạng
Đánh dấu DISPUTED
Giải quyết DISPUTED
Phê duyệt Bảng C
Chốt chủ quản (Bảng D)
Ban hành Từ điển
Tra cứu Từ điển
Quản lý user/vai trò
Quản lý cây tổ chức

6.3 Bảo Mật Mạng

Lớp Biện pháp Chi tiết
Edge NGINX reverse proxy Port 443 duy nhất expose, TLS 1.2+
Mạng Segmentation VM-App và VM-DB trên private network, không expose ra internet
Truyền tải TLS Tất cả traffic mã hóa TLS 1.2+
Service-to-service Private network Backend → Matching, Backend → DB qua internal IP
Rate limiting NGINX Giới hạn request/phút cho auth endpoints

6.4 Bảo Vệ Dữ Liệu

Loại dữ liệu Phân loại Mã hóa lưu trữ Mã hóa truyền tải Kiểm soát truy cập
User credentials Bí mật Keycloak bcrypt hash TLS 1.2+ Keycloak only
Metadata nghiệp vụ Nội bộ Ổ đĩa mã hóa (OS-level) TLS 1.2+ RBAC theo vai trò
Audit logs Tuân thủ Append-only, ổ đĩa mã hóa TLS 1.2+ Read-only cho Admin
Discovery credentials Tạm thời Không lưu — chỉ dùng runtime TLS 1.2+ Xóa ngay sau sử dụng
File upload (CSV/DDL) Nội bộ Ổ đĩa mã hóa (OS-level) TLS 1.2+ Manager only

6.5 Quản Lý Bí Mật

Loại bí mật Lưu trữ Xoay vòng Truy cập
DB credentials Docker Secrets (GĐ1) / Vault (GĐ2) Thủ công / Tự động Environment variable
Keycloak admin Docker Secrets Thủ công Environment variable
JWT signing key Keycloak quản lý Tự động (Keycloak) Keycloak internal
AES key (GĐ2) Docker Secrets / Vault 90 ngày /run/secrets/ mount
SMTP credentials Docker Secrets Thủ công Environment variable

6.6 Threat Model (STRIDE)

Mối đe dọa Mô tả Xác suất Ảnh hưởng Biện pháp Trạng thái
Spoofing Giả mạo danh tính Trung bình Cao Keycloak SSO/local auth, JWT validation Đã giảm thiểu
Tampering Chỉnh sửa dữ liệu trái phép Thấp Cao Input validation, audit log bất biến, RBAC Đã giảm thiểu
Repudiation Phủ nhận hành động Trung bình Trung bình Audit log 100% write operations, append-only Đã giảm thiểu
Information Disclosure Rò rỉ dữ liệu Trung bình Cao Org-scoped access, TLS, không lưu credentials Đã giảm thiểu
Denial of Service Quá tải hệ thống Thấp Cao Rate limiting NGINX, connection pool limits Giảm thiểu một phần
Elevation of Privilege Truy cập trái phép Thấp Thiết yếu Least privilege, RBAC+ABAC, Default Deny Đã giảm thiểu

6.7 Checklist Kiểm Soát Bảo Mật

  • [x] Tất cả endpoint yêu cầu xác thực (trừ public portal rõ ràng)
  • [x] RBAC thực thi ở API level
  • [x] Input validation trên mọi user input
  • [x] Phòng chống SQL injection (parameterized queries — JPA/Hibernate)
  • [x] Phòng chống XSS (output encoding — React tự xử lý)
  • [x] CSRF protection (stateless JWT — không cần CSRF token)
  • [x] Rate limiting trên auth endpoints (NGINX)
  • [x] Bí mật không trong code hay file config (Docker Secrets)
  • [x] Audit trail cho mọi data mutation
  • [x] Quét lỗ hổng dependency trong CI (Trivy + OWASP ZAP)
  • [x] Network segmentation (private subnets cho DB/Cache)

6.8 Kiểm Toán & Tuân Thủ

Audit Log Format:

{
  "id": "uuid",
  "action": "CONFIRM_SOURCE_MAPPING",
  "entity_type": "SOURCE_MAPPING",
  "entity_id": "uuid",
  "user_id": "uuid",
  "org_id": "uuid",
  "before": {"current_state": "AI_SUGGESTED"},
  "after": {"current_state": "CONFIRMED"},
  "ip_address": "192.168.1.50",
  "timestamp": "2026-04-08T14:30:00+07:00"
}
  • Lưu trữ: Bảng audit_log trong PostgreSQL
  • Bảo vệ: REVOKE UPDATE, DELETE ON audit_log FROM app_user ở DB level
  • Retention: 5 năm (tuân thủ Luật DL 60/2024)
  • Ghi: Trong cùng @Transactional với business operation — đảm bảo consistency

7. Crosscutting Concerns

7.1 Xử Lý Lỗi

Tầng Chiến lược Ví dụ
API Gateway (NGINX) HTTP error codes chuẩn 502 Bad Gateway khi backend sập
Controller Validation errors → 400/422 Thiếu field bắt buộc → 422
Service Layer Domain exceptions → HTTP mapping BusinessRuleViolation → 422, NotFoundException → 404
Repository DB exceptions → Domain exceptions UniqueConstraintViolation → DuplicateEntityError
External Calls Circuit Breaker + Retry Matching Service timeout → retry 3 lần → Circuit Breaker
Background Jobs Per-item error handling Lỗi 1 field → log WARN, tiếp tục field tiếp theo

API Error Response Format:

{
  "success": false,
  "error": {
    "code": "DISPUTED_NOTE_TOO_SHORT",
    "message": "Ghi chú tranh chấp phải ≥ 20 ký tự",
    "field": "dispute_note"
  },
  "timestamp": "2026-04-08T14:30:00+07:00",
  "traceId": "abc123"
}

7.2 Logging & Observability

Khía cạnh Công cụ Chi tiết
Structured Logging Logback + JSON format Mỗi log entry có traceId, userId, orgId
Log Aggregation Loki Thu thập từ Docker containers, Grafana query
Metrics Prometheus + Spring Actuator Request rate, latency histogram, error rate, JVM metrics
Dashboards Grafana System overview, business metrics, infrastructure
Log Levels Chuẩn ERROR (sự cố), WARN (cần chú ý), INFO (business events), DEBUG (chi tiết kỹ thuật)
Retention 30 ngày (info), 90 ngày (error/warn) Loki retention policy

Correlation ID: Mỗi request nhận traceId duy nhất tại NGINX → propagate qua Backend → Matching Service → response. Giúp trace toàn bộ luồng xử lý.

7.3 Quản Lý Cấu Hình

Loại cấu hình Lưu trữ Ví dụ
Application config Environment variables (Docker Compose) DATABASE_URL, REDIS_URL, KEYCLOAK_URL
Business rules Database (bảng config) Matching threshold (0.60), DISPUTED min chars (20)
Feature flags Database Enable/disable email notifications, auto-accept matching
Secrets Docker Secrets (GĐ1) / Vault (GĐ2) DB password, SMTP password, AES key

7.4 Chiến Lược Kiểm Thử

Cấp độ Mục tiêu Công cụ Phạm vi
Unit Tests > 95% JUnit 5, Mockito (Java); Pytest (Python) Business logic, scoring, parsers
Integration Tests Luồng chính Spring Boot Test + Testcontainers API endpoints, DB queries, module interactions
Contract Tests API contracts OpenAPI validation Frontend ↔ Backend contract
E2E Tests Luồng quan trọng Playwright Đăng nhập, Discovery, Matching, Xác nhận
Security Tests CI pipeline Trivy (container), OWASP ZAP (DAST) 0 Critical, < 5 High
Module Boundary 100% ArchUnit Không cross-module internal imports
Load Tests Peak scenarios Gatling > 200 req/s, P95 < 2s

8. Khả Năng Mở Rộng

Chiến Lược Mở Rộng

Thành phần GĐ1 GĐ2+ (khi cần)
Backend 1 instance 2+ instances sau NGINX load balancer
Matching Service 1 instance Scale riêng theo matching queue depth
PostgreSQL Primary + 1 Replica Thêm Replica cho báo cáo nặng
Redis 1 instance Redis Sentinel cho HA
Frontend 1 instance Nhiều instances sau NGINX

Caching

Cache Layer Dữ liệu TTL Invalidation
Redis — lookup Cây tổ chức, Domain tree 1 giờ Event-driven khi CRUD
Redis — session JWT session metadata Theo JWT expiry Tự hết hạn
Redis — search Kết quả search phổ biến 5 phút Time-based
PostgreSQL — Materialized View Báo cáo tổng hợp Refresh hàng giờ Scheduled refresh

Capacity Planning

Tài nguyên GĐ1 Peak Tốc độ tăng Trigger hành động
Database < 5 GB 10 GB ~1 GB/năm Scale ổ đĩa khi đạt 70%
File storage < 10 GB 50 GB Theo số Sở tham gia Mở rộng disk VM-App
User đồng thời 200 500 Theo phase triển khai Thêm backend instance khi P95 > 3s

9. Triển Khai & Vận Hành

9.1 Môi Trường

Môi trường Mục đích Hạ tầng Dữ liệu
Development Phát triển tính năng Docker Compose local Seed data
Staging Kiểm thử trước production VM riêng hoặc chia sẻ Dữ liệu ẩn danh từ production
Production Hệ thống thực 2 VM (VM-App + VM-DB) Dữ liệu thực

9.2 CI/CD Pipeline

Kroki

Quality Gates

Gate Kiểm tra Hành động khi fail
Build Compilation, linting Block merge
Unit Test JUnit + Pytest (> 95% coverage) Block merge
Integration Test API + DB tests Block merge
Security Scan Trivy (container) + OWASP ZAP Block deploy nếu Critical
Module Boundary ArchUnit tests Block merge
Manual QA Kiểm thử trên Staging Block deploy production

9.3 Chiến Lược Release

Rolling restart (đơn giản cho Docker Compose):

# Deploy production
docker compose pull
docker compose up -d --no-deps backend    # Backend trước
docker compose up -d --no-deps matching   # Matching Service
docker compose up -d --no-deps frontend   # Frontend cuối

Downtime dự kiến: < 30 giây mỗi service restart. Chấp nhận được cho hệ thống nội bộ.

9.4 Runbooks

Runbook Trigger Tóm tắt bước
Xử lý sự cố Alert Grafana Phân loại → Điều tra (xem Loki logs) → Giảm thiểu → Khắc phục → RCA (trong 48h)
Rollback Deploy lỗi docker compose up -d --no-deps {service} với image tag cũ
Scale backend P95 > 3s kéo dài Thêm backend instance, cập nhật NGINX upstream
DB Failover PostgreSQL Primary sập Promote Replica → cập nhật connection string → restart backend
DB Restore Mất dữ liệu Restore từ backup gần nhất → apply WAL → verify data
Keycloak Recovery Keycloak sập Restart container; nếu DB corrupt → restore Keycloak DB
Redis Recovery Redis sập Restart container; cache tự rebuild; re-enqueue matching jobs nếu cần

9.5 Quy Trình Sự Cố

Alert → Phân loại (5 phút) → Điều tra (15 phút) → Giảm thiểu → Khắc phục → RCA (trong 48h)
Mức nghiêm trọng Ví dụ Phản hồi
P1 — Thiết yếu Hệ thống sập hoàn toàn Xử lý ngay, thông báo stakeholders
P2 — Cao Matching Service sập Xử lý trong 1 giờ, các tính năng khác vẫn hoạt động
P3 — Trung bình Báo cáo chậm Xử lý trong ngày làm việc
P4 — Thấp UI glitch Fix trong sprint tiếp theo

10. Giám Sát & Observability

10.1 SLI/SLO Framework

Service SLI (đo gì) SLO (mục tiêu) Error Budget
NGINX (tổng thể) Tỷ lệ request thành công 99.5% / tháng 3.65 giờ / tháng
Search API Latency P95 < 2 giây N/A
Write API Latency P95 < 500ms N/A
Matching Worker Tỷ lệ job hoàn thành 99.5% 3.65 giờ / tháng
Matching Worker Thời gian mỗi field < 500ms N/A

10.2 Dashboards

Dashboard Đối tượng Metrics chính
Tổng quan hệ thống Ops / Tech Lead Request rate, error rate, latency P95/P99, uptime
Nghiệp vụ PM / Approver Số DE, sessions Discovery, % Sở đã xác nhận, DISPUTED count
Hạ tầng Ops CPU, RAM, disk, network, DB connections, replication lag
Matching Tech Lead Jobs/giờ, accuracy (manual override rate), avg confidence score

10.3 Alerting

Alert Điều kiện Mức Thông báo Escalation
Error rate cao > 5% 5xx trong 5 phút P1 Grafana → Email Tech Lead ngay lập tức
Latency cao P95 > 3s trong 10 phút P2 Grafana → Email Review trong ngày
DB replication lag > 15 phút P2 Grafana → Email DBA review
DB connection pool > 80% utilized P3 Grafana Review trong ngày
Matching session quá lâu > 60 giây P3 Loki log WARN Review trong ngày
Disk space > 80% P2 Grafana → Email Dọn dẹp / mở rộng
Keycloak sập Health check fail 3 lần P1 Grafana → Email Restart ngay

10.4 Health Checks

Endpoint Kiểm tra Tần suất Ngưỡng alert
/actuator/health/liveness Backend đang chạy 10s 3 lần fail liên tiếp
/actuator/health/readiness Backend sẵn sàng (DB + Redis OK) 30s 1 lần fail
/api/v1/health Backend + dependencies 60s 2 lần fail liên tiếp
Matching: /health Matching Service đang chạy 30s 3 lần fail liên tiếp
Keycloak: /health Auth Server đang chạy 30s 1 lần fail

11. Sao Lưu & Khắc Phục Sự Cố

Chiến Lược Sao Lưu

Dữ liệu Phương pháp Tần suất Retention Lưu trữ
PostgreSQL (business DB) pg_dump -Fc -Z 6 Hàng ngày 01:00 30 ngày VM-DB /backup/
PostgreSQL (WAL) Streaming replication Liên tục 7 ngày Replica
Keycloak DB pg_dump riêng Hàng ngày 01:30 30 ngày VM-DB /backup/
Upload files rsync /data/uploads/ Hàng ngày 02:00 30 ngày VM-DB /backup/
Docker Compose config Git Mỗi thay đổi Vĩnh viễn Git repo

Khắc Phục Sự Cố (Disaster Recovery)

Chỉ số Mục tiêu Chiến lược
RTO (Recovery Time Objective) < 4 giờ Failover thủ công: promote Replica → cập nhật config → restart
RPO (Recovery Point Objective) < 15 phút WAL streaming replication lag < 15 phút

Quy Trình DR

1. Phát hiện sự cố (monitoring alert)
2. Đánh giá mức độ: VM-App sập / VM-DB sập / cả hai
3. VM-App sập:
   a. Khắc phục VM hoặc provision VM mới
   b. Pull Docker images
   c. docker compose up -d
   d. Verify health checks
4. VM-DB sập:
   a. Nếu Replica còn: promote Replica thành Primary
   b. Cập nhật connection string trong Docker Compose
   c. Restart backend
   d. Thiết lập Replica mới từ Primary mới
5. Cả hai sập:
   a. Provision VM mới
   b. Restore PostgreSQL từ backup gần nhất
   c. Restore upload files từ backup
   d. Deploy applications
   e. Verify toàn bộ health checks
6. Thông báo stakeholders
7. RCA trong 48 giờ

Lịch Diễn Tập

  • Hàng tháng: Test restore PostgreSQL từ backup
  • Hàng quý: Test DR procedure đầy đủ (simulate VM sập)

12. Mô Hình Chi Phí

Khoản chi Chi tiết Ước tính GĐ1 Yếu tố scale
VM-App 8 vCPU, 16GB RAM, 100GB SSD Phần cứng on-premise Thêm VM khi cần
VM-DB 4 vCPU, 32GB RAM, 500GB SSD Phần cứng on-premise Tăng disk khi cần
Software Toàn bộ open-source $0
Mạng Mạng chính phủ hiện có $0
Nhân sự 2 Senior Fullstack Chi phí chính Thêm người khi scale
Bảo trì Docker Compose, minimal Thấp

Chiến Lược Tối Ưu Chi Phí

  • Open-source toàn bộ — không có license fee
  • On-premise — không có cloud monthly cost
  • Modular Monolith — 1 backend service, ít container, ít tài nguyên
  • PostgreSQL thay Elasticsearch — bớt 1 JVM cluster
  • Redis đa năng — cache + queue, bớt RabbitMQ

13. Sổ Rủi Ro

# Rủi ro Ảnh hưởng Xác suất Biện pháp Trạng thái Chịu TN
R1 SSO pháp lý bị trễ > 6 tháng Thấp Rất cao Keycloak dual-mode Đã giải quyết Tech Lead
R2 AI matching accuracy thấp cho tiếng Việt Cao Trung bình Human review 100% + feedback log Chấp nhận Tech Lead
R3 Sở không xác nhận Bảng C đúng hạn Cao Cao Auto-reminder + Approver chốt đơn phương Đã giải quyết PM
R4 DISPUTED không giải quyết Cao Trung bình Hard guard + escalation Đã giải quyết PM
R5 PostgreSQL Primary sập Cao Thấp Streaming replication + backup hàng ngày Đã giảm thiểu Ops
R6 Team 2 người quá tải Cao Trung bình Ưu tiên MVP, defer non-essential Theo dõi PM
R7 Full-text search chậm ở quy mô lớn Thấp Thấp GIN indexes đủ < 50K; Elasticsearch option GĐ2 Chấp nhận Tech Lead

Technical Debt Log

# Nợ kỹ thuật Ảnh hưởng Ưu tiên Kế hoạch Xem lại khi
TD1 Elasticsearch cho search Nếu P95 > 3s Thấp Thêm ES, sync qua Change Data Capture DE > 10K
TD2 Kubernetes Nếu cần auto-scaling Thấp Migrate Docker Compose → K3s > 3 VM
TD3 Automated HA failover RTO hiện tại thủ công < 4h Thấp PostgreSQL Patroni Uptime > 99.9%
TD4 ML matching models Rule-based có thể thiếu chính xác Trung bình Train trên ai_feedback_log Đủ training data
TD5 Email notifications Chưa có, chỉ in-app (backlog) Trung bình SMTP integration GĐ1 nếu kịp

14. Lộ Trình Phát Triển

Lộ Trình Kiến Trúc

Phase Thay đổi kiến trúc Trigger
GĐ0 MVP Modular Monolith + Matching Service, Keycloak local, Docker Compose
GĐ1 Đầy đủ + SSO federation, + báo cáo nâng cao, + DISPUTED workflow SSO pháp lý sẵn sàng
GĐ1.5 + Read replicas cho báo cáo, + caching nâng cao Performance metrics cho thấy cần
GĐ2 + LDOP/PostgreSQL Direct Discovery, + ML matching, + Workflow Engine Scale requirements
GĐ3 + NDOP sync, + Elasticsearch (nếu cần), + K8s (nếu cần) > 30 Sở, > 10K DE

Dễ Thay Đổi

  • UI components (shadcn/ui composable)
  • Matching scoring algorithm (đóng gói trong Matching Service)
  • Query báo cáo và layout dashboard
  • Discovery parsers (thêm format mới)
  • Caching strategy

Khó Thay Đổi

  • PostgreSQL schema (migration cost)
  • Keycloak realm configuration (user data migration)
  • Modular Monolith → Microservices (refactoring lớn)
  • Mã Data Element format (bất biến sau khi tạo)
  • Audit log schema (append-only by design)

15. Giả Định & Ràng Buộc

Giả Định Kỹ Thuật

# Giả định Ảnh hưởng nếu sai
TA1 PostgreSQL GIN đủ cho search < 50K records Cần Elasticsearch GĐ2
TA2 Rule-based scoring đủ chính xác GĐ1 Cần ML sớm hơn
TA3 2 VM đủ cho GĐ1 Cần thêm VM
TA4 Redis Queue đủ cho matching jobs Cần RabbitMQ
TA5 Docker Compose đủ cho vận hành Cần K8s

Ràng Buộc

# Ràng buộc Nguồn
C1 On-premise — không cloud Chính sách chính phủ
C2 Đội 2 Senior Fullstack Nguồn lực
C3 Tuân thủ Luật DL 60/2024, NĐ 13/2023 Pháp lý
C4 Hỗ trợ tiếng Việt đầy đủ Nghiệp vụ
C5 SSO pháp lý có thể chưa sẵn sàng Quy trình hành chính

16. Kết Quả Validation Kiến Trúc

Scenario Walkthrough

Scenario 1: Manager upload CSV và chạy matching

Path: Manager → Frontend → NGINX → Backend (module-discovery) → Local FS → Backend (module-matching) → Redis Queue → Worker → Matching Service → PostgreSQL → Frontend (SSE)

Happy path: 1. Manager upload file CSV → NGINX proxy → Backend parse file → Lưu local FS + DB ✅ 2. Manager kích hoạt matching → Enqueue Redis → Worker dequeue ✅ 3. Worker gọi Matching Service → Scoring → Trả kết quả ✅ 4. Worker lưu results vào DB → SSE thông báo Frontend ✅

Failure scenarios: - File CSV sai format → Parse fail → Trả lỗi rõ ràng cho user ✅ - Matching Service timeout → Retry 3 lần → Circuit Breaker → Trả lỗi ✅ - Scoring lỗi 1 field → Skip field, tiếp tục field tiếp → Log WARN ✅

Kết quả: ✅ PASS

Scenario 2: Data Owner xác nhận hiện trạng

Path: Data Owner → Frontend → Backend (module-confirm) → PostgreSQL → Audit Log

Happy path: 1. Data Owner đăng nhập → Keycloak JWT → Backend extract org_id ✅ 2. GET Bảng C → Filter theo org_id (chỉ thấy đơn vị mình) ✅ 3. Xác nhận → UPDATE source_mapping state = CONFIRMED → Audit log ✅

Failure scenarios: - Data Owner cố xem đơn vị khác → RBAC org_id check → 403 Forbidden ✅ - JWT hết hạn → Refresh token → Retry request ✅

Kết quả: ✅ PASS

Scenario 3: Approver phê duyệt Bảng C

Path: Approver → Frontend → Backend (module-confirm) → PostgreSQL

Happy path: 1. Approver xem tổng hợp → GET Bảng C toàn bộ ✅ 2. Phê duyệt → Guard check: > 70% Sở xác nhận VÀ 0 DISPUTED ✅ 3. Nếu pass guard → Chốt Bảng C → Audit log ✅

Failure scenarios: - Còn DISPUTED → Hard guard block → Trả lỗi rõ ràng ✅ - < 70% Sở xác nhận → Hard guard block → Hiển thị % hiện tại ✅

Kết quả: ✅ PASS

Load & Capacity Sanity Check

Chỉ số Mục tiêu Hỗ trợ kiến trúc Gap
User đồng thời peak 500 Spring Boot Virtual Threads + NGINX Không
Throughput > 200 req/s Virtual Threads, HikariCP pool 20, Redis cache Không
Lưu trữ DB (1 năm) < 10 GB 500GB SSD provisioned Không
Search P95 < 2s GIN index + pg_trgm + Redis cache Không
Matching 300 fields < 30s Batch processing, per-field 500ms Không

Security Review

  • [x] Tất cả endpoint yêu cầu xác thực
  • [x] RBAC + ABAC thực thi ở API level
  • [x] Input validation (JPA/Hibernate parameterized queries)
  • [x] Mã hóa truyền tải (TLS 1.2+)
  • [x] Mã hóa lưu trữ (OS-level disk encryption)
  • [x] Bí mật trong Docker Secrets
  • [x] Audit logging cho mọi data mutation
  • [x] Rate limiting trên auth endpoints
  • [x] Network segmentation (private subnets)
  • [x] Quét lỗ hổng trong CI (Trivy + OWASP ZAP)
  • [x] Threat model STRIDE hoàn thành

Operational Readiness

  • [x] Monitoring dashboards định nghĩa (4 dashboards)
  • [x] SLI/SLO targets đặt và đo lường được
  • [x] Alerting rules định nghĩa với escalation path
  • [x] Health check endpoints thiết kế
  • [x] Runbooks có (7 runbooks)
  • [x] Chiến lược sao lưu với quy trình restore
  • [x] DR plan với RTO/RPO targets
  • [x] CI/CD pipeline với quality gates
  • [x] Log aggregation và retention policy

Tóm Tắt Validation

Kiểm tra Trạng thái Ghi chú
Scenario Walkthrough (3 journeys) ✅ PASS Tất cả happy + error paths covered
Load & Capacity ✅ PASS Kiến trúc đáp ứng mọi target
Security Review ✅ PASS 11/11 checks passed
Cost Review ✅ PASS Open-source, on-premise, chi phí thấp
Operational Readiness ✅ PASS 9/9 checks passed

Hạng Mục Mở Từ Validation

# Hạng mục Mức Chịu TN Kế hoạch
V1 Automated HA failover chưa có (RTO thủ công) Thấp Ops Chấp nhận GĐ1; xem xét Patroni ở GĐ2
V2 Email notification chưa triển khai Trung bình Dev Backlog GĐ1
V3 Load test thực tế chưa chạy Trung bình Dev Chạy trước go-live

Cập nhật lần cuối: 2026-04-08