Skip to content

03 Domain and Workflow

hywznn edited this page Jul 22, 2026 · 6 revisions

도메인과 Workflow

FOWOCO의 핵심 Domain은 “누가 어떤 근로자의 어떤 업무를, 어떤 조건으로 다음 단계로 옮겼는가”입니다. 단순 CRUD보다 상태 전이와 증빙·승인이 중요합니다.

주요 객체

객체 쉬운 설명 핵심 관계
Company FOWOCO를 사용하는 사업장 모든 업무 데이터의 tenant
User HR·관리자·조회자 Company에 속하고 Role을 가짐
Worker 업무 대상 외국인근로자 Company에 속하고 Task·Document를 가짐
WorkerDocument 문서 유형·상태·만료일 metadata Worker에 속하고 FileReference를 선택적으로 가짐
Task HR이 실제로 처리할 업무카드 Worker, TaskType, 상태, version, 담당자
ChecklistItem 완료해야 할 필수 단계 pinned Workflow Catalog에서 생성된 snapshot
Approval 특정 Task version에 대한 사람의 결정 승인 후 핵심값 수정 시 무효화
Evidence 완료를 증명하는 참조 Document, File, 외부 제출번호 등
WorkerLink 근로자용 만료 URL 승인된 특정 Task와 허용 action만 노출
AiRun AI 요청의 영속 실행 단위 여러 TaskCandidate를 가질 수 있음
AiAttempt 같은 AiRun 안의 1회 실행 시도 오류·시각·version을 수정하지 않고 보존
TaskCandidate AI가 제안한 업무카드 후보 HR이 각각 확정·폐기
AuditEvent 누가 무엇을 했는지 남긴 기록 append-only

세 가지 Workflow를 구분합니다

  1. Knowledge Workflow Catalog: 업무 유형별 필수정보·체크리스트·승인·완료 기준. knowledge 저장소가 versioned bundle로 배포합니다.
  2. AI Agent Pipeline: 자연어를 Intent·Slot·후보로 해석합니다. ai 저장소가 소유합니다.
  3. Server Task Workflow: 실제 Task의 상태 변경, 권한, 승인, 증빙을 강제합니다. server 저장소가 소유합니다.

Server는 Catalog의 정확한 version을 읽어 Task 생성 시 snapshot을 남기지만 Catalog 원문을 임의 수정하지 않습니다.

Task 상태

stateDiagram-v2
  [*] --> DRAFT
  DRAFT --> NEEDS_INFO: 필수정보 부족
  DRAFT --> READY_FOR_REVIEW: 필수정보 충족
  NEEDS_INFO --> READY_FOR_REVIEW: 정보 보완
  READY_FOR_REVIEW --> APPROVED: HR 승인
  READY_FOR_REVIEW --> DRAFT: 반려·수정 필요
  APPROVED --> WAITING_WORKER: 근로자 행동 필요
  APPROVED --> WAITING_EXTERNAL: 외부기관 처리 대기
  APPROVED --> COMPLETED: 즉시 완료 조건 충족
  WAITING_WORKER --> READY_FOR_REVIEW: 응답 후 재검토 필요
  WAITING_WORKER --> WAITING_EXTERNAL: 제출 뒤 외부 대기
  WAITING_WORKER --> COMPLETED: 증빙·조건 충족
  WAITING_EXTERNAL --> READY_FOR_REVIEW: 보완 필요
  WAITING_EXTERNAL --> COMPLETED: 외부 처리·증빙 완료
  DRAFT --> CANCELLED
  NEEDS_INFO --> CANCELLED
  READY_FOR_REVIEW --> CANCELLED
  APPROVED --> CANCELLED
  WAITING_WORKER --> CANCELLED
  WAITING_EXTERNAL --> CANCELLED
Loading
상태 초보자를 위한 의미 대표 다음 행동
DRAFT 막 만든 초안 담당자·대상·기한 확인
NEEDS_INFO 필수값이 부족함 누락정보 입력 또는 요청
READY_FOR_REVIEW 사람이 검토할 준비 완료 편집·승인 요청
APPROVED 특정 version을 HR이 승인 근로자 전달·외부 제출
WAITING_WORKER 근로자 확인·응답·파일을 기다림 Worker Link 상태 확인
WAITING_EXTERNAL 출입국 등 외부기관 결과를 기다림 제출 reference·기한 관리
COMPLETED 증빙과 완료 조건 충족 수정 대신 후속 Task 생성
CANCELLED 사유와 함께 중단 재개 대신 새 Task 검토

IN_PROGRESS, FAILED는 Task 상태로 쓰지 않습니다. 진행 중이라는 모호한 상태 대신 무엇을 기다리는지 표현하고, 기술 실패는 AiRun/Event 상태로 관리합니다.

상태 전이는 Command입니다

범용 PATCH status=...로 상태를 덮어쓰지 않습니다.

Domain Command Authenticated API 대표 전이
requestReview(taskId, expectedVersion) POST /api/v1/tasks/{taskId}/approval-requests DRAFT/NEEDS_INFO → READY_FOR_REVIEW
approve(taskId, expectedVersion) POST /api/v1/tasks/{taskId}/approve READY_FOR_REVIEW → APPROVED
reject(taskId, expectedVersion, reason) POST /api/v1/tasks/{taskId}/reject READY_FOR_REVIEW → DRAFT
issueWorkerLink(taskId, expectedVersion) POST /api/v1/tasks/{taskId}/worker-link APPROVED → WAITING_WORKER
recordExternalSubmission(taskId, expectedVersion, reference) POST /api/v1/tasks/{taskId}/external-submissions APPROVED/WAITING_WORKER → WAITING_EXTERNAL
complete(taskId, expectedVersion, evidenceIds) POST /api/v1/tasks/{taskId}/complete APPROVED 또는 허용 대기상태 → COMPLETED
cancel(taskId, expectedVersion, reason) POST /api/v1/tasks/{taskId}/cancel 비종료 상태 → CANCELLED

각 Command는 현재 상태, Actor Role, company, 필수정보, 증빙, optimistic lock version을 검사하고 Activity·Audit을 남깁니다.

반려하면 현재 승인 요청을 종료하고 사유를 Audit에 남긴 뒤 DRAFT로 돌아갑니다. 담당자가 수정하고 다시 승인 요청해야 합니다.

AiRun 실행 상태

stateDiagram-v2
  [*] --> QUEUED
  QUEUED --> RUNNING
  RUNNING --> SUCCEEDED
  RUNNING --> RETRYING: 일시 오류
  RETRYING --> RUNNING
  RUNNING --> FAILED: 영구 오류 또는 retry 소진
  RETRYING --> FAILED
  FAILED --> RETRYING: HR 수동 retry
Loading
상태 의미
QUEUED 요청과 실행 event가 DB에 저장됨
RUNNING AI Runtime 호출 또는 응답 검증 중
RETRYING 제한적 backoff 뒤 재실행 예정
SUCCEEDED 내부 호출과 계약 검증이 끝남
FAILED 자동 진행이 불가능한 기술 실패

AI의 업무 판정인 NEEDS_INFO, REVIEW_REQUIRED는 AiRun 상태가 아니라 outcome입니다.

POST /api/v1/ai-runs/{aiRunId}/retry는 실패한 Run 안에 새 AiAttempt를 추가하고 FAILED → RETRYING으로 전이합니다. 이전 attempt의 오류·시각·version은 그대로 보존하며 202 + 같은 aiRunId를 반환합니다. 같은 idempotency key로 retry를 반복해도 새 attempt가 중복 생성되지 않습니다.

복합 요청과 후보 결정

입력 예시:

“응웬반A 체류연장 준비하고 여권 사본도 요청해줘”

AI Runtime은 EXPIRY_RENEWAL, DOCUMENT_REQUEST 후보를 각각 반환할 수 있습니다. Server는 두 후보를 저장하되 실제 Task로 자동 등록하지 않습니다.

POST /api/v1/ai-runs/{aiRunId}/candidate-decisions
{
  "decisions": [
    {"candidateId": "candidate-1", "decision": "ACCEPT"},
    {"candidateId": "candidate-2", "decision": "DISCARD", "reason": "이미 제출됨"}
  ]
}
  • ACCEPT: 현재 후보 snapshot으로 Task를 한 번만 생성합니다.
  • DISCARD: 업무에는 등록하지 않고 폐기 사유와 Actor를 Audit에 남깁니다.
  • 같은 idempotency key나 같은 후보 확정이 반복돼도 Task가 중복 생성되면 안 됩니다.

TaskType과 Catalog

MVP 대표 유형:

  • EXPIRY_RENEWAL
  • DOCUMENT_REQUEST
  • PAYROLL_EXPLANATION
  • EMPLOYMENT_CHANGE
  • WORK_NOTICE

각 Task는 생성 시 사용한 workflow_catalog_version과 체크리스트 snapshot을 저장합니다. 나중에 Knowledge bundle이 바뀌어도 진행 중인 Task의 조건이 몰래 바뀌지 않습니다. 정책상 migration이 필요하면 별도의 명시적 Command와 Audit을 사용합니다.

승인 불변식

  • AI 후보는 승인할 수 있는 상태가 아니라 검토 대상입니다.
  • 승인자는 해당 Company와 Role을 가져야 합니다.
  • 승인은 task_id + task_version + 승인 snapshot에 묶입니다.
  • 대상자, 기한, 금액, 문서 종류, 안내문처럼 중요한 값을 수정하면 승인을 무효화합니다.
  • 승인되지 않은 Task는 Worker Link 발급과 전달이 불가능합니다.
  • 완료 조건이 있는 Task는 Evidence 없이 COMPLETED가 될 수 없습니다.

동시성과 중복

  • Task와 중요한 aggregate에 @Version을 사용합니다.
  • Command에는 expectedVersion을 전달합니다.
  • API command는 필요한 곳에 Idempotency-Key를 사용합니다.
  • Event consumer는 at-least-once 전달을 전제로 멱등하게 처리합니다.
  • 충돌 시 최신 상태를 덮지 말고 CONCURRENT_MODIFICATION을 반환합니다.

최소 테스트

  • 허용/금지 상태 전이
  • Role 부족과 타 사업장 접근
  • 필수정보 부족과 NEEDS_INFO
  • 승인 후 핵심값 변경 시 승인 무효화
  • 승인 전 Worker Link 발급 차단
  • Evidence 없는 완료 차단
  • 후보 확정 동시 요청에도 Task 하나
  • 오래된 expectedVersion 거부
  • Catalog version 변경 뒤 기존 Task snapshot 유지

Clone this wiki locally