4.8 KiB
4.8 KiB
WORKS only 사용자 복구 보고서
관련 이슈: #1037
요약
- 작업 시각: 2026-06-09 KST
- 대상: WORKS 비교 결과에서
missing_in_baron으로 보이던 사용자 row - 최신 후보 수: 189명
- 조치: Baron
users.deleted_atsoft-delete 해제 - Kratos 조치: 직접 삽입/수정 없음. 189개 Kratos identity가 모두 현재 DB에 active 상태로 존재함을 확인함
- 최종 결과: WORKS 사용자 비교의
missing_in_baron0건
원인
이전 사용자 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-063605Zbackups/pre-works-only-user-recovery-20260609-083105KST
상세 리포트:
reports/works-only-user-recovery-20260609-0832/missing_in_baron_external_keys.csvreports/works-only-user-recovery-20260609-0832/current_baron_candidate_status.csvreports/works-only-user-recovery-20260609-0832/pre_saman_baron_candidate_status.csvreports/works-only-user-recovery-20260609-0832/current_kratos_candidate_status.csvreports/works-only-user-recovery-20260609-0832/pre_saman_kratos_candidate_status.csvreports/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_baronrow의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=2106items=2106
GET /api/v1/admin/tenants/038326b6-954a-48a7-a85f-efd83f62b82a/worksmobile/comparison?includeMatched=true- HTTP 200
- 사용자 비교 총 2110건
matched=2073missing_in_baron=0missing_in_worksmobile=30needs_update=1missing_external_key=6- 조직/그룹 비교 총 187건
- 조직/그룹
missing_in_baron=1
테스트:
GOCACHE=/tmp/baron-sso-go-cache go test ./internal/service -run 'TestWorksmobileSyncServiceSkipsSoftDeletedUsersInComparison' -count=1GOCACHE=/tmp/baron-sso-go-cache go test ./internal/handler ./internal/repository -run 'Test.*User|Test.*Projection|Test.*SoftDeleted|Test.*ListUsers' -count=1BASE_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가 없으므로 자동 복구 대상에서 제외했습니다.