forked from baron/baron-sso
custom claim 권한체크 확인
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
# 사용자 projection 가시성 감사 보고서
|
||||
# 사용자 가시성 감사 보고서
|
||||
|
||||
작성 시각: 2026-06-08 16:55 KST
|
||||
|
||||
관련 이슈:
|
||||
- #1035: adminfront 사용자 레지스트리 total이 Kratos 250건 제한으로 잘못 표시됨
|
||||
- #1036: 사용자 projection 가시성 영향 범위 검증 및 WORKS 비교 표 row count 표시
|
||||
- #1036: 사용자 가시성 영향 범위 검증 및 WORKS 비교 표 row count 표시
|
||||
|
||||
## 결론
|
||||
|
||||
`총 250명` 표시는 단순 UI 문제가 아니라, Kratos partial list를 full snapshot처럼 처리한 projection 동기화 버그였습니다.
|
||||
`총 250명` 표시는 단순 UI 문제가 아니라, Kratos partial list를 full snapshot처럼 처리한 legacy sync 버그였습니다.
|
||||
|
||||
현재 로컬 DB와 API는 다음 상태입니다.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
| --- | ---: | --- |
|
||||
| users 전체 | 2,114 | `deleted_at` 포함 전체 row |
|
||||
| visible users | 1,917 | `deleted_at IS NULL`, adminfront/orgfront 사용자 목록 기준 |
|
||||
| soft-deleted users | 197 | 사용자 삭제 또는 과거 projection 문제로 숨겨진 row |
|
||||
| soft-deleted users | 197 | 사용자 삭제 또는 과거 legacy sync 문제로 숨겨진 row |
|
||||
| CSV 원본 줄 수 | 1,887 | 헤더 포함 |
|
||||
| CSV 실제 데이터 행 | 1,886 | 헤더 제외 |
|
||||
| 이번 import 사용자 | 1,886 | 모두 DB 매칭, 모두 visible |
|
||||
@@ -33,8 +33,8 @@
|
||||
|
||||
보고 파일 위치:
|
||||
|
||||
- `reports/user-projection-visibility-audit-20260608-1645/existing_users_not_in_saman_import.csv`
|
||||
- `reports/user-projection-visibility-audit-20260608-1645/imported_users_missing_or_soft_deleted.csv`
|
||||
- `reports/user-visibility-audit-20260608-1645/existing_users_not_in_saman_import.csv`
|
||||
- `reports/user-visibility-audit-20260608-1645/imported_users_missing_or_soft_deleted.csv`
|
||||
|
||||
파일 내용:
|
||||
|
||||
@@ -100,9 +100,9 @@ soft-deleted 기존 사용자 197명과 WORKS comparison `baronId`를 대조한
|
||||
|
||||
이번 문제는 단일 UI 카운트 문제가 아니라 다음 경계가 한꺼번에 얽힌 문제였습니다.
|
||||
|
||||
1. Kratos identity list는 partial list인데 backend projection sync가 full snapshot으로 처리했습니다.
|
||||
2. projection sync가 local DB soft-delete까지 수행해 사용자 가시성 자체를 손상시켰습니다.
|
||||
3. adminfront 사용자 목록, orgfront 조직도, WORKS comparison이 모두 사용자 projection을 다른 방식으로 소비하고 있었습니다.
|
||||
1. Kratos identity list는 partial list인데 legacy backend sync가 full snapshot으로 처리했습니다.
|
||||
2. legacy sync가 Backend DB soft-delete까지 수행해 사용자 가시성 자체를 손상시켰습니다.
|
||||
3. adminfront 사용자 목록, orgfront 조직도, WORKS comparison이 모두 사용자 데이터를 다른 방식으로 소비하고 있었습니다.
|
||||
4. WORKS comparison은 사용자 목록이 아니라 Baron/WORKS 양쪽 차이를 보여주는 비교 화면이라 total 의미가 달랐습니다.
|
||||
5. 운영자가 partial data인지 바로 볼 수 있도록 WORKS 표 row count가 필요했습니다.
|
||||
|
||||
@@ -110,14 +110,14 @@ soft-deleted 기존 사용자 197명과 WORKS comparison `baronId`를 대조한
|
||||
|
||||
현재 구조는 다음과 같습니다.
|
||||
|
||||
- Ory/Kratos -> backend projection sync: 현재 `ListIdentities()` partial 조회입니다. offset/cursor 전체 순회가 아닙니다.
|
||||
- backend projection -> adminfront 사용자 목록: `cursor`가 있으면 cursor pagination, 없으면 offset pagination을 받습니다. adminfront는 infinite query로 `nextCursor`를 사용합니다.
|
||||
- backend projection -> orgfront 조직도/picker: 현재 `limit=5000&offset=0` 단일 offset 조회입니다.
|
||||
- Ory/Kratos -> Backend identity mirror warmup: `ListIdentities()` partial 조회를 전체 snapshot으로 취급하면 안 됩니다. 전체 수집은 pagination을 끝까지 따라가야 합니다.
|
||||
- Backend -> adminfront 사용자 목록: `cursor`가 있으면 cursor pagination, 없으면 offset pagination을 받습니다. adminfront는 infinite query로 `nextCursor`를 사용합니다.
|
||||
- Backend -> orgfront 조직도/picker: Redis orgchart snapshot 또는 Backend cursor API를 사용해야 하며 `limit=5000&offset=0` 단일 offset 조회는 금지합니다.
|
||||
- WORKS comparison: backend가 비교 결과 배열을 만들어 내려주고, adminfront가 검색/필터 후 화면 row를 표시합니다.
|
||||
|
||||
## 재발 방지 조치
|
||||
|
||||
- 사용자 목록 API는 Kratos가 아니라 local projection DB를 primary source로 사용합니다.
|
||||
- Kratos partial list에 없는 사용자를 projection sync에서 삭제하지 않도록 수정했습니다.
|
||||
- 사용자 목록 API는 Backend가 Ory-warmed Redis cache와 허용된 read model을 조합해 cursor로 제공합니다.
|
||||
- Kratos partial list에 없는 사용자를 legacy sync에서 삭제하지 않도록 수정했습니다.
|
||||
- WORKS comparison에서 soft-deleted local user가 들어와도 comparison row로 노출되지 않도록 방어 테스트와 로직을 추가했습니다.
|
||||
- WORKS comparison 표에 `표시 N / 전체 M` row count를 표시했습니다.
|
||||
|
||||
Reference in New Issue
Block a user