Rinda 권한 에러 근본원인 분석
TL;DR
- 가장 많은
agent/missions등 403 tier-blocked = 체험 만료(expired) 워크스페이스의 백그라운드 폴링 → null 티어 → 전부 차단. 정상 동작인데 ERROR로 알림돼 채널을 도배. - 실제 정책 버그 1건: beta
trial티어에execute액션 누락 (alpha엔 존재) → 활성 체험 유저의 온보딩이 beta에서만 깨짐. alpha↔beta drift. sequences/:id500은 권한과 무관한 별개 코드 버그(어드민X-Workspace-Id: all미방어).
권한 모델 (확인됨)
티어 정책 = allow-list + default-deny. getWorkspaceTier()는 expired/canceled 구독을 제외하므로 만료 시 tier = null. null 티어는 billing read/list/create/update만 허용하고 나머지 전부 deny.
checkPermissionDetailed → ① role 체크 통과 → ② getWorkspaceTier(ws)
expired 체험 → tier=null → getTierAllowedPermissions(null) = billing 4종만 allow
→ ai:chatbot||list 등 not in set → 403 TIER_BLOCKED
expired 체험 → tier=null → getTierAllowedPermissions(null) = billing 4종만 allow
→ ai:chatbot||list 등 not in set → 403 TIER_BLOCKED
근거 경로: iam.service.ts:603-630(getWorkspaceTier) · iam.service.ts:1387-1429(getTierAllowedPermissions) · auth.macro.iam-check.ts:62(tier-blocked 로깅)
근본 원인 분류
| # | 에러 | 실제 원인 | 판정 | 비중 |
|---|---|---|---|---|
| A | agent/missions(ai:chatbot‖list), customer-groups, gtm claim 403 | 6개 WS가 expired 체험 → tier=null → 정상 차단. FE가 만료 후에도 계속 폴링 | 정상 알림 노이즈 | 최대 |
| B | onboarding/analyze-company-file 403 (settings:workspace‖execute) | beta trial 정책에 execute 누락 (alpha엔 존재). 활성 체험 유저 온보딩 차단 | 정책 drift | 1건+ |
| C | upload/campaign-image 403 (settings:workspace‖create) | trial은 alpha/beta 둘 다 create 없음 → 라우트 권한 과다(annotation 부적절) | 검토 | 1건 |
| D | sequences/:id 계열 500 (workspace_id="all") | 어드민 X-Workspace-Id: all → assertConcreteWorkspace 미적용, "all"이 그대로 UUID 쿼리로 → 22P02 | 코드 버그 | 5건(동시) |
| E | workspaces/:id/* 403 workspace-not-member | user 531f90a0는 706da031 owner, 1619cc1d 비멤버 → 정상 차단(FE stale context 추정) | 정상 | 1버스트 |
| F | email-replies/drafts 500 AITimeout | gpt-5-mini 30s 타임아웃, 1회성 | 일시 | 1건 |
alpha vs beta drift (핵심)
| 티어 | settings 허용 액션 (alpha) | settings 허용 액션 (beta) |
|---|---|---|
| trial | read, update, delete, execute | read, update, delete (execute 없음) |
→ beta iam_tier_boundaries의 trial 정책이 stale. alpha는 이미 execute 추가됨. 원인 B는 beta 정책을 alpha와 동기화하면 해소.
대상 워크스페이스 구독 상태 (beta)
| workspace_id | 구독 상태 | 티어(상품) | 결과 |
|---|---|---|---|
019eb009…3e82 | trialing 활성 | trial | 온보딩 execute 차단(원인 B) |
7ca7c0c0…7dd5 | expired | trial(만료) | tier=null 전면 차단(원인 A) |
1a06bcdc…3146 | expired | trial(만료) | 원인 A |
d32ccf96…442c | expired | trial(만료) | 원인 A |
506859f7…5338 | expired | trial(만료) | 원인 A |
a20faf7c…37aa | expired | trial(만료) | 원인 A |
019e00b2…3ec1 | expired | trial(만료) | 원인 A |
권장 조치 (우선순위)
P1 · 원인 B — beta
iam_tier_boundaries trial 정책에 execute 추가(alpha 동기화). 활성 체험 유저 온보딩 funnel 복구. seed 코드와 일치 여부도 점검.P2 · 원인 A — expected tier-blocked 거부를 ERROR 알림에서 제외(로그 레벨 강등) + FE가 만료 후 폴링 중단/업그레이드 월. 채널 노이즈 대폭 감소.
P3 · 원인 D —
GET /sequences/:id 계열 5개에 assertConcreteWorkspace 가드 추가("all" → 400). 어드민 500 제거.P4 · 원인 C/E/F — campaign-image 권한 annotation 재검토 · workspace-not-member FE stale context · AI timeout. 개별 이슈로 등록만.