체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

체류기간 만료 경과 긴급 확인 흐름 구현 - #198

Merged
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay
Aug 16, 2026
Merged

체류기간 만료 경과 긴급 확인 흐름 구현#198
hywznn merged 1 commit into
mainfrom
feat/184-expired-stay

Conversation

@hywznn

Copy link
Copy Markdown
Member

왜 필요한가요?

기록상 체류기간이 지났다는 사실만으로 근로자를 퇴사 처리하거나 적법 체류 여부를 판단하면 안 됩니다. 담당자가 공식 결과를 확인할 수 있도록 긴급 확인 Case를 만들고, 확인 전에는 고용상태를 그대로 유지해야 합니다.

Depends on fowoco/knowledge#54
Closes#184

무엇이 바뀌나요?

  • stay_expiry_date < todayACTIVE·ON_LEAVE 근로자를 매일 또는 수동으로 스캔합니다.
  • (company_id, worker_id, source_stay_expiry_date)로 중복 Case를 차단합니다.
  • APPROVED / APPLICATION_PENDING / UNKNOWN / NOT_APPLIED / EMPLOYMENT_ENDED 상태와 증빙·재확인일을 별도 저장합니다.
  • 승인 결과가 확인된 경우에만 Worker의 새 체류만료일을 갱신합니다.
  • 고용 종료는 HR 확인 시각과 공식 메모가 있어야 하며 WF-CHG-001을 자동 실행하지 않고 후보로만 반환합니다.
  • PostgreSQL RLS 환경의 일일 스캔은 최소 후보만 반환하는 SECURITY DEFINER bootstrap을 사용하고, 실제 저장은 사업장별 독립 transaction에서 수행합니다.
  • Knowledge projection을 0.3.1로 맞추고 일반 체류연장과 만료 경과 예외 Workflow의 생성 경계를 분리합니다.

API

  • POST /api/v1/stay-verifications/scan
  • GET /api/v1/stay-verifications
  • PATCH /api/v1/stay-verifications/{stayVerificationId}

안전장치

  • 날짜 경과만으로 Worker.work_status 변경 금지
  • 승인 결과 또는 공식 확인 메모 없는 확정 상태 거부
  • expected_version 동시성 검증
  • 증빙 서류의 worker·company 소유권 검증
  • actor·시각·이전/변경 상태 감사로그 기록
  • test profile의 스케줄러 비활성화로 공유 Fixture 오염 방지

Migration

  • V54__create_stay_verification_case.sql
  • V55__prepare_expired_stay_scan.sql (PostgreSQL)

다음 Server Migration은 V56부터 사용합니다.

검증

  • ./gradlew clean test — 658 tests, 성공
  • StayVerificationIntegrationTest — 멱등 스캔·tenant 격리·증빙·승인·고용 종료 분기 성공
  • PostgreSQL 16 임시 DB에서 PostgreSqlMigrationTests 성공
  • git diff --check 성공

후속 연동

  • Client #346에서 긴급 확인 목록과 상태 입력 UI를 이 API에 연결합니다.
  • AI #50은 WF-STY-EXC-001의 설명·질문 보조만 담당하며 법적 결론과 자동 퇴사 판단을 하지 않습니다.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stay): 체류기간 만료 예외 Case 생성과 상태 분기

1 participant

@hywznn