Files
BaronSSO/baron-sso/docs/works-only-user-recovery-2026-06-09.md

4.8 KiB

WORKS only 사용자 복구 보고서

관련 이슈: #1037

요약

  • 작업 시각: 2026-06-09 KST
  • 대상: WORKS 비교 결과에서 missing_in_baron으로 보이던 사용자 row
  • 최신 후보 수: 189명
  • 조치: Baron users.deleted_at soft-delete 해제
  • Kratos 조치: 직접 삽입/수정 없음. 189개 Kratos identity가 모두 현재 DB에 active 상태로 존재함을 확인함
  • 최종 결과: WORKS 사용자 비교의 missing_in_baron 0건

원인

이전 사용자 projection 동기화 코드가 Kratos ListIdentities() 결과를 전체 identity 목록으로 간주했습니다. 해당 API 결과는 제한된 페이지 결과였고, 그 목록에 없던 기존 사용자가 Baron users에서 soft-delete 처리되었습니다.

이로 인해 WORKS에는 사용자가 남아 있고 externalKey도 Baron 사용자 UUID를 가리키지만, Baron 비교 로직에서는 soft-deleted 사용자가 visible 사용자로 조회되지 않아 missing_in_baron으로 표시되었습니다.

대조 결과

복구 전 후보 189건 기준:

구분 현재 Baron 과거 Baron 백업 현재 Kratos 과거 Kratos 백업
후보 189 189 189 189
visible 사용자 0 189 - -
soft-delete 사용자 189 0 - -
누락 사용자 0 0 0 0
active identity - - 189 189
credential 보유 identity - - 189 189

확인한 백업:

  • backups/pre-saman-works-users-20260608-063605Z
  • backups/pre-works-only-user-recovery-20260609-083105KST

상세 리포트:

  • reports/works-only-user-recovery-20260609-0832/missing_in_baron_external_keys.csv
  • reports/works-only-user-recovery-20260609-0832/current_baron_candidate_status.csv
  • reports/works-only-user-recovery-20260609-0832/pre_saman_baron_candidate_status.csv
  • reports/works-only-user-recovery-20260609-0832/current_kratos_candidate_status.csv
  • reports/works-only-user-recovery-20260609-0832/pre_saman_kratos_candidate_status.csv
  • reports/works-only-user-recovery-20260609-0832/post_recovery_baron_candidate_status.csv

조치 내용

복구 전 DB 백업을 생성했습니다.

  • make dump DUMP_SERVICES=postgres,ory-postgres BACKUP=backups/pre-works-only-user-recovery-20260609-083105KST

이후 후보 189건에 대해 현재 Baron DB에서 다음 조건으로만 soft-delete를 해제했습니다.

  • WORKS missing_in_baron row의 externalKey가 UUID여야 함
  • 해당 UUID가 현재 Baron users.id에 존재해야 함
  • 해당 Baron row가 deleted_at IS NOT NULL이어야 함
  • 해당 UUID가 현재 Kratos identities.id에 active 상태로 존재해야 함

복구 결과:

  • 복구된 Baron 사용자: 189명
  • 전체 Baron users: 2114명
  • visible 사용자: 2106명
  • soft-delete 사용자: 8명
  • 후보 189명 중 Kratos active identity: 189명
  • 후보 189명 중 credential 보유 identity: 189명

최종 검증

실제 Kratos admin 세션으로 로컬 게이트웨이를 경유해 검증했습니다.

  • GET /api/v1/admin/users?limit=5000&offset=0
    • HTTP 200
    • total=2106
    • items=2106
  • GET /api/v1/admin/tenants/038326b6-954a-48a7-a85f-efd83f62b82a/worksmobile/comparison?includeMatched=true
    • HTTP 200
    • 사용자 비교 총 2110건
    • matched=2073
    • missing_in_baron=0
    • missing_in_worksmobile=30
    • needs_update=1
    • missing_external_key=6
    • 조직/그룹 비교 총 187건
    • 조직/그룹 missing_in_baron=1

테스트:

  • GOCACHE=/tmp/baron-sso-go-cache go test ./internal/service -run 'TestWorksmobileSyncServiceSkipsSoftDeletedUsersInComparison' -count=1
  • GOCACHE=/tmp/baron-sso-go-cache go test ./internal/handler ./internal/repository -run 'Test.*User|Test.*Projection|Test.*SoftDeleted|Test.*ListUsers' -count=1
  • BASE_URL=http://127.0.0.1:5173 npm --prefix adminfront test -- worksmobile.spec.ts --project=chromium

결과:

  • Go service 테스트 통과
  • Go handler/repository 테스트 통과
  • adminfront Worksmobile Playwright 4개 테스트 통과

재발 방지

이미 적용된 코드 변경으로 다음 조건을 방어합니다.

  • admin 사용자 목록은 Kratos 250개 제한 결과가 아니라 로컬 projection repository를 기준으로 조회합니다.
  • projection replace 동기화는 Kratos partial list에 없는 사용자를 삭제 처리하지 않습니다.
  • WORKS 비교 로직은 soft-deleted Baron 사용자를 visible 사용자로 취급하지 않습니다.
  • WORKS 비교 UI에는 필터링 후 표시 row와 전체 row 수를 함께 표시합니다.

남은 확인 항목:

  • 조직/그룹 비교의 missing_in_baron=1은 사용자 복구와 별개 항목입니다. 별도 이슈로 원인 확인이 필요합니다.
  • missing_external_key=6 사용자 row는 WORKS 측 externalKey가 없으므로 자동 복구 대상에서 제외했습니다.