logiSA 2.0 / DOCS

Design baseline · 28 SEP 2026 · 11 / 23

TDD · UC-01 Cont/Seal

Current runtime: một task OPS đọc album và một child task CUSTOMER_SERVICE gửi kết quả trong cùng legacy workflow instance. Target: Process Definition chứa Workflow Cont/Seal nhiều task do Field Operations sở hữu, cùng Workflow gửi kết quả do Customer Service sở hữu.

Phân biệt hiện trạng / target. Phần execution dưới đây ghi lại vertical slice đang có trong code. Process Definition → role-owned Workflow → task graph là kiến trúc đích; chưa được triển khai bởi runtime Cont/Seal hiện tại.

Luồng Cont/Seal hiện tại

01Inbound eventZalo lưu event và media bền vững
02DispatcherKhớp tenant/session/group với flow đang bật
03OPS taskRECEIVE_CONTAINER_SEAL; idempotent theo source event
04Flow instancePin workflow revision và graph snapshot
05Skillextract_container_evidence → vision/OCR → quality gate/review
06Result taskCUSTOMER_SERVICE gửi qua outbox tới đích đã pin

Hiện tại chỉ có một task đọc/xử lý album; task gửi kết quả là một child task riêng chứ không phải bước thứ hai của AI đọc ảnh. Đây là current vertical slice, chưa theo hierarchy mới: mỗi inbound event đủ điều kiện tạo một legacy workflow instance với một OPS task/image job; image processor chạy code chuyên biệt, sau đó tạo CUSTOMER_SERVICE child task trong cùng instance để gửi report. Vì một instance đang chứa task của hai Role, đây là cấu trúc chuyển tiếp và không tuân thủ nguyên tắc target mỗi Workflow có đúng một Role owner. Role/task chưa được cấu hình qua UI.

Mapping sang kiến trúc đích

Trong Process Definition logistics shipment, Cont/Seal sẽ là một Workflow con có owner Role FIELD_OPERATIONS. Workflow này chứa các task đọc evidence, kiểm tra ISO/seal và xử lý review; task graph được phép fan-out/fan-in. Nếu cần xác nhận booking thuộc trách nhiệm Documentation, handoff sang Workflow con của Role đó. Gửi kết quả cho khách/nhà xe là Workflow con khác, owner CUSTOMER_SERVICE, được kích hoạt theo transition đã khai báo. Tên Process Definition và role catalog cần được owner nghiệp vụ chốt trước khi coi là contract.

UC-02–05 nằm ngoài vertical slice Cont/Seal hiện tại.

Envelope và version pinning

{
  "schemaVersion": "2.0",
  "taskId": "task_*",
  "taskType": "RECEIVE_CONTAINER_SEAL",
  "role": {"code": "OPS", "version": 1},
  "flow": {"id": "wf_*", "version": 4, "instanceId": "wfi_*"},
  "source": {"eventId": "evt_*", "channel": "zalo", "sessionId": "sess_*", "groupId": "group_*"},
  "evidence": [{"type": "image", "sourceEventId": "evt_*"}],
  "skill": {"code": "extract_container_evidence", "version": 1}
}

Tenant lấy từ event/session đã xác thực, không lấy từ payload. Legacy workflow instance lưu definition snapshot. Khi OPS hoàn tất, child task SEND_CONTAINER_SEAL_RESULT pin CUSTOMER_SERVICE role/skill và destination snapshot nhưng vẫn nằm trong cùng instance. Đây là hành vi hiện tại; target sẽ tách gửi kết quả thành Workflow con riêng do CUSTOMER_SERVICE sở hữu, được Process Orchestrator handoff trong cùng Process Instance. Job đang chạy không đọc destination từ config mới nhất.

State và lỗi

event: STORED → DISPATCHED | IGNORED
OPS task: PENDING → RUNNING → SUCCEEDED | WAITING_REVIEW | FAILED
flow: RUNNING → WAITING_DELIVERY → SUCCEEDED | UNKNOWN
result task: WAITING_DELIVERY → SUCCEEDED | UNKNOWN
UNKNOWN không tự gửi lại; cần đối soát receipt.

Test matrix theo acceptance

IDGiven / WhenThen
UC01-T01 · AC1/5OPS mở Workflows với tenant/session được phépĐúng config; save tạo revision; optimistic conflict không ghi đè.
UC01-T02 · AC2/3/4Tải Zalo inventory; chọn nhiều nhóm nhà xe và resultTên thật, giữ channel/session/group ID; không có phân loại theo từng nhóm; reject ID ngoài inventory, trùng hoặc source=result.
UC01-T03 · AC5Bật flow thiếu source/result hoặc graph saiLỗi cụ thể; không tạo revision.
UC01-T04 · AC6Một album từ group đã chọnMột OPS task/flow instance; attachment theo thứ tự; ảnh sai nguồn không gọi vision.
UC01-T05 · AC6Vision trả hợp lệ, sai ISO, thiếu cont, confidence thấp hoặc outageQuality gate quyết VERIFIED/NEEDS_REVIEW; outage không làm mất ảnh hoặc tự xác minh.
UC01-T06 · AC7OPS đang xử lý khi admin đổi result groupChild task gửi tới group trong snapshot cũ; report mở đầu bằng tên nhóm nguồn, kèm kết quả và media nguồn, không gửi ghi chú trích xuất.
UC01-T07 · AC7/8Gateway trả receipt hoặc timeoutReceipt accepted → SENT; timeout → UNKNOWN; không tạo vòng lặp inbound.
UC01-T08 · AC8Inbound replay, worker restart, duplicate outbox claimUnique event/task/command ngăn gửi trùng; lease hết hạn không tự retry side effect mơ hồ.
UC01-T09 · isolationHai tenant có ID hội thoại giống nhauKhông đọc workflow, evidence, task hoặc destination của tenant kia.

Definition of done

  1. Test config/API/validator xanh; migration chạy trên DB mới và DB đã có V1–V21.
  2. Kiểm tra task có role/version, task type, skill/version, workflow snapshot; result tạo CUSTOMER_SERVICE child task và outbox đúng destination.
  3. Kiểm tra ảnh từ group chưa cấu hình không sinh task; đổi config trong lúc chạy không đổi destination.
  4. Operational acceptance cần session Zalo kết nối, quyền đọc/gửi group, model credential, media URL hợp lệ và gateway receipt; unit test đơn lẻ chưa đủ để xác nhận “dùng được”.

Historical verification record · 25 Sep 2026

CheckResultCoverage boundary
bun run app:typecheckPASSDashboard TypeScript, including workflow BFF.
bun run app:testPASS · 39/39Current workflow config, role-assignment removal, toast layout, and 9Router BFF tests; not live provider inference.
bun test gateway/tests/*.test.tsPASS · 31/31 · 24 SepSession/QR, tenant-scoped secrets, image album, inbound/outbound contract mocks; not rerun for this UI/core change and not a real Zalo room.
mvn testPASS · 106/106Current core APIs, Cont/Seal report formatting and carrier-only source filtering, graph validator, Sheet MCP client and vision adapter.
PostgreSQL V1–V22 migration checkPASSDisposable database with one existing enabled Cont/Seal workflow and queued image; V22 backfilled ASSIGN → OPS / RECEIVE_CONTAINER_SEAL and linked its flow version.
Inbound runtime smokePASSDisposable DB + Quarkus: configured source album → ASSIGN/OPS task; replay → duplicate; unconfigured group → IGNORE. Image processing was disabled in this smoke, so it made no model or outbound call.
Live image preview · no side effectPASSPreviewed one retained photo from the configured Zalo source group through the selected vision route; detected both container and seal, confidence 0.98, quality status PASSES_CHECKS.
UC-01 full-flow integration · disposable DBPASSSame real image source → ASSIGN / OPS / RECEIVE_CONTAINER_SEAL → image job DONE → CUSTOMER_SERVICE child task → report SENT to a mock gateway receipt → child and flow SUCCEEDED. Destination matched the pinned result group. No real Zalo send.

The selected Zalo session is connected and its workflow is enabled with a source group and result group. The real model has read a retained group photo, and the complete delivery state machine has passed against a mock gateway. A newly submitted album is still the final live-room check for the post-V22 deployment; no test report was sent to the real result group.

logiSA 2.0 · Public development cookbook · Design target; implementation status in Delivery.