Design baseline · 28 SEP 2026 · 05 / 23
Contracts & API
Contract-first · schemaVersion 2.0 · stable identifiers
DESIGN DIAGRAMS · TARGET ARCHITECTURE 2.0
Contract map · Producer → Consumer
Các message được validate ở từng boundary. Chi tiết fields và schemaVersion nằm trong JSON Schema tải về.
Envelope chung
Mọi message có schemaVersion, tenantId, traceId. UUID cho identity nội bộ; provider IDs là opaque string. Thời gian RFC3339 UTC. Tenant được backend resolve từ session/authenticated identity; đối chiếu tenant trong message. Public request không dùng tenantId để tự cấp quyền.
{
"schemaVersion": "2.0",
"tenantId": "00000000-0000-4000-8000-000000000001",
"traceId": "trace-demo-001",
"taskId": "00000000-0000-4000-8000-000000000002",
"taskType": "RECEIVE_CONTAINER_SEAL",
"roleCode": "OPS",
"roleVersion": 1,
"shipmentId": null,
"sourceEventIds": [
"00000000-0000-4000-8000-000000000003"
],
"evidenceIds": [
"00000000-0000-4000-8000-000000000004"
],
"idempotencyKey": "event-demo:RECEIVE_CONTAINER_SEAL:0",
"input": {
"submissionId": "demo-album"
},
"parentTaskId": null
}
Ranh giới message
| Contract | Producer → Consumer | Ý nghĩa |
|---|---|---|
| InboundEvent | Gateway → Intake | eventId, providerEventId, sessionId, channel, thread/sender, text, evidenceIds, albumId, occurredAt, direction. ACK event đã durable. |
| ProcessRoutingDecision | Intake → Process Orchestrator | decisionId, eventId, action, reason, processInstanceId, workflow targets hoặc task attach. Server validate tenant, correlation và Process/Workflow references. |
| TaskEnvelope | Workflow Runtime → Task Executor | taskId,type,workflowInstanceId, inherited ownerRole/version,input,businessCase?,events,evidence,idempotency,parent. Role ownership lấy từ Workflow, không assign tùy ý từng task. |
| ContextBundle | Context Builder → Role/Skill | taskId, snapshotVersion, facts[], references[], missingFields[], budget. Mỗi fact có source và observedAt. |
| WorkflowExecutionPlan | Workflow Runtime → Task Executor | workflowInstanceId,taskInstanceId,nodeId,executor kind/version,input. Runtime điều khiển task graph; Role không chọn Flow/Workflow tùy ý. |
| ToolCall / ToolResult | Skill ↔ Tool broker | executionId, callId, toolCode/version, arguments, idempotencyKey; status,data,error,receipt. Permission check trước mỗi call. |
| TaskResult | Role/Skill → Validator | resultId,taskId,executionId,status,data,evidenceIds,proposedEvent,errors. Kết quả đề xuất chưa phải state committed. |
| ValidationDecision | Validator → Orchestrator | resultId,verdict ACCEPT/REVIEW/REJECT,ruleVersion,violations[],acceptedData; chỉ acceptedData được commit. |
| WorkflowEvent | Process / Workflow Runtime → durable queue | eventId,processInstanceId,workflowInstanceId,aggregateVersion,eventType,causationId,data. Consumer dedupe theo eventId. |
| OutboundCommand / DeliveryReceipt | Orchestrator ↔ Gateway | commandId stable, destination pin, text/evidence; receipt SENT/UNKNOWN/FAILED,providerMessageIds. SENT cần provider evidence. |
| ReviewDecision | Operator BFF → Orchestrator | reviewId,expectedVersion,decision,correctedData,reason. actor lấy từ auth, audit immutable. |
API surface đích
| API | Input / response | Semantics |
|---|---|---|
| POST /internal/v2/events | InboundEvent → 202 {eventId,status:ACCEPTED}; duplicate 200 | Service auth + session scope; eventId stable, mismatch payload 409. |
| GET /api/v2/{roles,skills,task-types,process-definitions,workflows} | cursor,limit≤100 → {items,nextCursor} | BFF tenant-scoped; archived mặc định bị ẩn. |
| POST /api/v2/{roles,skills,process-definitions,workflows} | {code,name,definition} → 201 {id,version:1} | Validate schema và references trước save. |
| PUT /api/v2/{roles,skills,process-definitions,workflows}/{id}/versions | {expectedVersion,definition} → 201 {id,version} | Mỗi lần lưu tạo bản mới; stale → 409. |
| POST /api/v2/workflows/{id}/publish | {version,expectedVersion} → 200 | Task graph hợp lệ; đúng một Role owner và các task/executor references tồn tại; CAS active version. |
| GET /api/v2/channel-groups | sessionId,cursor → {items:[{id,name}],nextCursor} | Lấy từ gateway đúng session; UI load mọi trang để dropdown đủ nhóm. |
| GET /api/v2/tasks[/{id}] | Filter state,type,trace,shipment + cursor → list/detail | Detail gồm plan, executions, evidence, reviews và delivery. |
| POST /api/v2/tasks/{id}/{cancel,retry} | {expectedVersion,reason} → 202 | Retry tạo attempt/task follow-up phù hợp; không replay side effect UNKNOWN. |
| POST /api/v2/reviews/{id}/decisions | ReviewDecision → 200 {reviewId,version,state} | Server actor; stale/đã quyết định → 409. |
| POST /internal/v2/results | TaskResult → 202 {resultId,status:RECORDED} | Chỉ worker có scope và lease hợp lệ; không đồng nghĩa đã ACCEPT. |
| POST /internal/v2/outbound | OutboundCommand → 202 {commandId,status:ACCEPTED} | Gateway durable queue trước ACK; tra receipt bằng GET cùng commandId. |
| GET /internal/v2/outbound/{commandId} | → DeliveryReceipt | 404 chưa biết; SENT terminal; UNKNOWN cần đối soát, không tự resend. |
Errors, retries và tương thích
{
"error": {
"code": "VERSION_CONFLICT",
"message": "Expected version is stale",
"retryable": false,
"details": [
{
"path": "expectedVersion",
"code": "STALE"
}
]
},
"traceId": "trace-demo-001"
}
400 malformed; 401 unauthenticated; 403 denied capability; 404 absent hoặc ngoài tenant; 409 version/idempotency/state conflict; 422 schema/graph/business validation; 429 budget/rate; 503 dependency unavailable. Worker retry chỉ lỗi transient theo policy bounded exponential backoff + jitter. Tôn trọng Retry-After. Timeout side effect không chắc chắn → UNKNOWN.
POST mutation yêu cầu Idempotency-Key (trừ event/command dùng ID ổn định). Cùng scope/key/payload trả kết quả cũ; khác hash trả 409. Contract schemas strict: thêm field cần cập nhật consumer trước producer hoặc tăng schemaVersion; breaking change tăng major. Giữ adapters v1 khi rollout v2, không đổi payload v1 âm thầm.
Configuration schemas
RoleConfig và SkillConfig chốt prompt, quyền, executor và limits. WorkflowConfig chứa task graph, đúng một ownerRole và settingsSchemaRef + settings theo workflow; settings được validate thêm bằng schema tham chiếu. ContSealWorkflowSettings yêu cầu session, danh sách nhóm nguồn, nhóm kết quả và integration refs. Flow nghiệp vụ khác không bị buộc có nhóm Zalo.
Task-specific schemas
Envelope input/data là object mở tại biên generic. Trước execution/commit phải validate lần hai bằng schema của task/skill version đã pin. Cookbook cung cấp schema ContSealInput/ContSealData làm mẫu; Booking, EIR và Customs phải có schema + acceptance riêng trước khi enable.