{"numFailedTestSuites":0,"numFailedTests":0,"numPassedTestSuites":16,"numPassedTests":214,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":16,"numTotalTests":214,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1792572862135,"success":true,"testResults":[{"assertionResults":[{"ancestorTitles":["범위 감시 함수"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 목록 조건은 범위 키를 절 목록으로 싣는다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"목록 조건은 범위 키를 절 목록으로 싣는다"},{"ancestorTitles":["범위 감시 함수"],"duration":15,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 범위 키가 없으면 목록 조건을 만들지 않고 던진다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 키가 없으면 목록 조건을 만들지 않고 던진다"},{"ancestorTitles":["범위 감시 함수"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 목록 조건도 종류의 필수 키가 빠지면 던진다 (기업 경계 키 누락)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"목록 조건도 종류의 필수 키가 빠지면 던진다 (기업 경계 키 누락)"},{"ancestorTitles":["범위 감시 함수"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 단건 판정은 원천이 같으면 allow 다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"단건 판정은 원천이 같으면 allow 다"},{"ancestorTitles":["범위 감시 함수"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 단건 판정은 원천이 다르면 deny 다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"단건 판정은 원천이 다르면 deny 다"},{"ancestorTitles":["범위 감시 함수"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 ORG 신원에 orgPath 가 없으면 deny 다 (orgPath 누락 거부)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"ORG 신원에 orgPath 가 없으면 deny 다 (orgPath 누락 거부)"},{"ancestorTitles":["범위 감시 함수"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 자동 칸 행은 판정하지 않고 undeclared 다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"자동 칸 행은 판정하지 않고 undeclared 다"},{"ancestorTitles":["범위 감시 함수 · 조직 경로 (구분자 경계)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 조직 경로 (구분자 경계) 구분자 경계: 실제 ULID 세 단계 경로의 상위 조회는 하위 행을 허용한다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"구분자 경계: 실제 ULID 세 단계 경로의 상위 조회는 하위 행을 허용한다"},{"ancestorTitles":["범위 감시 함수 · 조직 경로 (구분자 경계)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 조직 경로 (구분자 경계) 구분자 경계: 형제 세그먼트 (/A/B/ 대 /A/BC/) 는 차단한다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"구분자 경계: 형제 세그먼트 (/A/B/ 대 /A/BC/) 는 차단한다"},{"ancestorTitles":["범위 감시 함수 · 조직 경로 (구분자 경계)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 조직 경로 (구분자 경계) 구분자 경계: 1/2 는 1/23 과 다르다 (1/23 행은 차단한다)","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"구분자 경계: 1/2 는 1/23 과 다르다 (1/23 행은 차단한다)"},{"ancestorTitles":["범위 감시 함수 · 조직 경로 (구분자 경계)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 조직 경로 (구분자 경계) 빈 orgPath 와 루트 / 는 정규화 뒤에도 던진다","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"status":"passed","title":"빈 orgPath 와 루트 / 는 정규화 뒤에도 던진다"},{"ancestorTitles":["범위 감시 함수 · 조직 경로 (구분자 경계)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 조직 경로 (구분자 경계) 행의 orgPath 가 형식에 맞지 않으면 deny 다 (LIKE 와일드카드 행을 허용하지 않는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"행의 orgPath 가 형식에 맞지 않으면 deny 다 (LIKE 와일드카드 행을 허용하지 않는다)"},{"ancestorTitles":["범위 감시 함수 · 단건 3의미 (합치지 않는다)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 단건 3의미 (합치지 않는다) memId 동일: 소유 회원이 같을 때만 allow, 관리자도 이 의미로는 allow 하지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"memId 동일: 소유 회원이 같을 때만 allow, 관리자도 이 의미로는 allow 하지 않는다"},{"ancestorTitles":["범위 감시 함수 · 단건 3의미 (합치지 않는다)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 단건 3의미 (합치지 않는다) 주문 소유자만: 소유 회원 일치만 allow, 관리자 신원은 주문 판정을 열지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"주문 소유자만: 소유 회원 일치만 allow, 관리자 신원은 주문 판정을 열지 않는다"},{"ancestorTitles":["범위 감시 함수 · 단건 3의미 (합치지 않는다)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 단건 3의미 (합치지 않는다) 소유자 또는 관리자 열람: 관리자는 allow, 그 밖은 소유 회원 일치","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"소유자 또는 관리자 열람: 관리자는 allow, 그 밖은 소유 회원 일치"},{"ancestorTitles":["범위 감시 함수 · 단건 3의미 (합치지 않는다)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 단건 3의미 (합치지 않는다) 자동 칸 행은 단건 3의미 모두 undeclared 다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"자동 칸 행은 단건 3의미 모두 undeclared 다"},{"ancestorTitles":["범위 감시 함수 · ORG 쌍 키"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · ORG 쌍 키 ORG 신원은 자동 칸이어도 orgPath 누락을 먼저 거부한다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"ORG 신원은 자동 칸이어도 orgPath 누락을 먼저 거부한다"},{"ancestorTitles":["범위 감시 함수 · ORG 쌍 키"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · ORG 쌍 키 ORG 판정은 agcId · orgPath 쌍 키가 없으면 던진다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"ORG 판정은 agcId · orgPath 쌍 키가 없으면 던진다"},{"ancestorTitles":["범위 감시 함수 · 범위 키 누락 (R2)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 범위 키 누락 (R2) 범위 키 목록이 비면 단건 판정도 던진다 (allow 를 내지 않는다)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 키 목록이 비면 단건 판정도 던진다 (allow 를 내지 않는다)"},{"ancestorTitles":["범위 감시 함수 · 범위 키 누락 (R2)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 범위 키 누락 (R2) 종류의 필수 키가 빠진 호출은 던진다 (고른 키만 비교하지 않는다)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"종류의 필수 키가 빠진 호출은 던진다 (고른 키만 비교하지 않는다)"},{"ancestorTitles":["범위 감시 함수 · 범위 키 누락 (R2)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 감시 함수 · 범위 키 누락 (R2) 필수 키를 다 넘기면 추가 키가 있어도 판정한다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"필수 키를 다 넘기면 추가 키가 있어도 판정한다"}],"endTime":1792572862810,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-control/scope-monitor.spec.ts","startTime":1792572862504,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["권한 평가기 evaluate"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 판정 불가 ≠ 거부 — 표가 없으면 deny 가 아니라 unknown 이다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"판정 불가 ≠ 거부 — 표가 없으면 deny 가 아니라 unknown 이다"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 표 부재 1146 은 unknown (table-absent)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"표 부재 1146 은 unknown (table-absent)"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 칸 없음 1054 는 unknown (column-absent)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"칸 없음 1054 는 unknown (column-absent)"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 오류 사슬의 cause 를 본다 (드라이버 래퍼)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"오류 사슬의 cause 를 본다 (드라이버 래퍼)"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate granted 코드는 allow 이고 최고관리자를 부르지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"granted 코드는 allow 이고 최고관리자를 부르지 않는다"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate NULL 신원의 최고관리자는 allow","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"NULL 신원의 최고관리자는 allow"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate NULL 신원 비최고관리자는 deny (null-athid)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"NULL 신원 비최고관리자는 deny (null-athid)"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 최고관리자 판정 불가 시 일반 코드도 unknown","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"최고관리자 판정 불가 시 일반 코드도 unknown"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 최고관리자 판정 불가 시 최고관리자 전용 코드는 unknown","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"최고관리자 판정 불가 시 최고관리자 전용 코드는 unknown"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 미등록 코드는 역할과 무관하게 unknown (unknown-code)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"미등록 코드는 역할과 무관하게 unknown (unknown-code)"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 비최고관리자는 최고관리자 전용 코드를 집합에 있어도 거부된다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"비최고관리자는 최고관리자 전용 코드를 집합에 있어도 거부된다"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 관리자가 아닌 신원의 미등록 코드는 unknown-code 다 (호출자 오타가 unmapped 에 숨지 않는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"관리자가 아닌 신원의 미등록 코드는 unknown-code 다 (호출자 오타가 unmapped 에 숨지 않는다)"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 관리자가 아닌 신원은 unmapped 다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"관리자가 아닌 신원은 unmapped 다"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 최고관리자 조회는 거부일 때만 한 번 불린다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"최고관리자 조회는 거부일 때만 한 번 불린다"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 행이 없으면 거부 (no-binding), 집합에 없는 코드는 거부 (not-granted)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"행이 없으면 거부 (no-binding), 집합에 없는 코드는 거부 (not-granted)"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 카탈로그에 rbac.manage 가 있고 최고관리자 전용 집합에도 든다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"카탈로그에 rbac.manage 가 있고 최고관리자 전용 집합에도 든다"},{"ancestorTitles":["권한 평가기 evaluate"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 평가기 evaluate 열람 토큰 신원은 권한이 있어도 unmapped 다 (관리자 판정 대상이 아니다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"열람 토큰 신원은 권한이 있어도 unmapped 다 (관리자 판정 대상이 아니다)"}],"endTime":1792572862853,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/permission/evaluate.spec.ts","startTime":1792572862815,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["권한 거부 403 (E0607)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"권한 거부 403 (E0607) code 상수는 E0607 이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"code 상수는 E0607 이다"},{"ancestorTitles":["권한 거부 403 (E0607)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 거부 403 (E0607) 본문은 code · message · reason 세 키이고 예외 타입은 ForbiddenException 이다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"본문은 code · message · reason 세 키이고 예외 타입은 ForbiddenException 이다"},{"ancestorTitles":["권한 거부 403 (E0607)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 거부 403 (E0607) 메시지는 호출하는 곳의 문구를 그대로 보존한다 (상수 하나로 덮지 않는다)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"메시지는 호출하는 곳의 문구를 그대로 보존한다 (상수 하나로 덮지 않는다)"},{"ancestorTitles":["권한 거부 403 (E0607)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 거부 403 (E0607) 사유 3종 (permission · super-only · scope) 이 본문에 그대로 실린다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"사유 3종 (permission · super-only · scope) 이 본문에 그대로 실린다"}],"endTime":1792572862907,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/admin/permission-denied.spec.ts","startTime":1792572862536,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["감시용 신원 해석"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 관리자 쿠키가 검증되면 관리자 신원과 admId 를 준다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"관리자 쿠키가 검증되면 관리자 신원과 admId 를 준다"},{"ancestorTitles":["감시용 신원 해석"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 관리자 쿠키가 검증에 실패해도 던지지 않고 신원 없음을 준다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"관리자 쿠키가 검증에 실패해도 던지지 않고 신원 없음을 준다"},{"ancestorTitles":["감시용 신원 해석"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 영업 형상의 관리자 쿠키는 관리자 종류를 그대로 준다 (판정 대상은 admin 뿐이다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"영업 형상의 관리자 쿠키는 관리자 종류를 그대로 준다 (판정 대상은 admin 뿐이다)"},{"ancestorTitles":["감시용 신원 해석"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 회원 쿠키는 회원 신원이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"회원 쿠키는 회원 신원이다"},{"ancestorTitles":["감시용 신원 해석"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 열람 토큰 헤더는 존재만 보고 열람 토큰 표지다 (검증하지 않는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"열람 토큰 헤더는 존재만 보고 열람 토큰 표지다 (검증하지 않는다)"},{"ancestorTitles":["감시용 신원 해석"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 외부 Basic 은 PrincipalKind 가 아닌 표지다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"외부 Basic 은 PrincipalKind 가 아닌 표지다"},{"ancestorTitles":["감시용 신원 해석"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 중복 제시: 관리자 쿠키와 회원 쿠키가 같이 오면 관리자가 이긴다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"중복 제시: 관리자 쿠키와 회원 쿠키가 같이 오면 관리자가 이긴다"},{"ancestorTitles":["감시용 신원 해석"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 검증된 회원 후보가 없는 refresh 형상만 있으면 형상 불일치 표지다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"검증된 회원 후보가 없는 refresh 형상만 있으면 형상 불일치 표지다"},{"ancestorTitles":["감시용 신원 해석"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 아무 신원도 없으면 none 이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"아무 신원도 없으면 none 이다"},{"ancestorTitles":["감시용 신원 해석"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"감시용 신원 해석 관리자 형상이 정수가 아닌 admId 를 주면 admId 를 비우고 판정 대상에서 뺀다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"관리자 형상이 정수가 아닌 admId 를 주면 admId 를 비우고 판정 대상에서 뺀다"}],"endTime":1792572862941,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-control/access-identity.spec.ts","startTime":1792572862911,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["(u) 상승 쓰기의 이행기 분류 (리뷰 R1 HIGH)"],"duration":6,"failureDetails":[],"failureMessages":[],"fullName":"(u) 상승 쓰기의 이행기 분류 (리뷰 R1 HIGH) (u) 표 부재 1146 은 상승을 생략하고 warn 을 한 줄 남기며 쓰기를 살린다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"(u) 표 부재 1146 은 상승을 생략하고 warn 을 한 줄 남기며 쓰기를 살린다"},{"ancestorTitles":["(u) 상승 쓰기의 이행기 분류 (리뷰 R1 HIGH)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"(u) 상승 쓰기의 이행기 분류 (리뷰 R1 HIGH) (u) 칸 부재 1054 perm_version 도 상승을 생략하고 warn 을 남긴다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"(u) 칸 부재 1054 perm_version 도 상승을 생략하고 warn 을 남긴다"},{"ancestorTitles":["(u) 상승 쓰기의 이행기 분류 (리뷰 R1 HIGH)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"(u) 상승 쓰기의 이행기 분류 (리뷰 R1 HIGH) (u) 이름이 다른 1146 과 그 밖의 오류는 그대로 던진다 (상승을 조용히 빼지 않는다)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"(u) 이름이 다른 1146 과 그 밖의 오류는 그대로 던진다 (상승을 조용히 빼지 않는다)"},{"ancestorTitles":["(v) 판정 불가의 원인은 로그에 남는다 (리뷰 R1 MEDIUM)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"(v) 판정 불가의 원인은 로그에 남는다 (리뷰 R1 MEDIUM) (v) 읽기의 그 밖의 오류는 원인 메시지를 error 로그에 싣고 판정 불가로 던진다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"(v) 읽기의 그 밖의 오류는 원인 메시지를 error 로그에 싣고 판정 불가로 던진다"},{"ancestorTitles":["(v) 판정 불가의 원인은 로그에 남는다 (리뷰 R1 MEDIUM)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"(v) 판정 불가의 원인은 로그에 남는다 (리뷰 R1 MEDIUM) (v) 표 부재 1146 은 이행기라 error 로그를 남기지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"(v) 표 부재 1146 은 이행기라 error 로그를 남기지 않는다"}],"endTime":1792572862950,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/permission/permission-version.spec.ts","startTime":1792572862535,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["범위 절 어댑터 · 실제 SQL"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"범위 절 어댑터 · 실제 SQL eq: 담당 영업 열을 값과 같다고 묶는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"eq: 담당 영업 열을 값과 같다고 묶는다"},{"ancestorTitles":["범위 절 어댑터 · 실제 SQL"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 절 어댑터 · 실제 SQL prefix: 경계 접두 LIKE 는 자신과 하위만 잡는 값 /A/B/% 를 넘긴다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"prefix: 경계 접두 LIKE 는 자신과 하위만 잡는 값 /A/B/% 를 넘긴다"},{"ancestorTitles":["범위 절 어댑터 · 실제 SQL"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"범위 절 어댑터 · 실제 SQL 두 절은 AND 로 묶인다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"두 절은 AND 로 묶인다"},{"ancestorTitles":["범위 절 어댑터 · 실제 SQL"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"범위 절 어댑터 · 실제 SQL 빈 절 목록은 조건 없음 (undefined) 을 돌려주지 않고 던진다 (전건 노출 차단)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"빈 절 목록은 조건 없음 (undefined) 을 돌려주지 않고 던진다 (전건 노출 차단)"},{"ancestorTitles":["범위 절 어댑터 · 실제 SQL"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"범위 절 어댑터 · 실제 SQL 음성: 와일드카드가 든 접두 값은 LIKE 로 넘기지 않고 던진다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"음성: 와일드카드가 든 접두 값은 LIKE 로 넘기지 않고 던진다"}],"endTime":1792572862953,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-control/scope-condition.spec.ts","startTime":1792572862856,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["권한 집합 조회 어댑터"],"duration":7,"failureDetails":[],"failureMessages":[],"fullName":"권한 집합 조회 어댑터 권한 집합 조회는 표지 코드 두 개를 거른다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"권한 집합 조회는 표지 코드 두 개를 거른다"},{"ancestorTitles":["권한 집합 조회 어댑터"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 집합 조회 어댑터 바인딩 조회는 관리자 행의 athId 를 준다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"바인딩 조회는 관리자 행의 athId 를 준다"},{"ancestorTitles":["권한 집합 조회 어댑터"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 집합 조회 어댑터 바인딩 행이 없으면 null 이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"바인딩 행이 없으면 null 이다"}],"endTime":1792572862980,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/permission/permission-adapter.spec.ts","startTime":1792572862520,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["관리자 감시 가드"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 관리자 쿠키가 있으면 판정 입력을 붙이고 통과시킨다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"관리자 쿠키가 있으면 판정 입력을 붙이고 통과시킨다"},{"ancestorTitles":["관리자 감시 가드"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 HEAD 요청도 GET 행과 같은 코드로 판정한다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"HEAD 요청도 GET 행과 같은 코드로 판정한다"},{"ancestorTitles":["관리자 감시 가드"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 경로 맵에 없는 라우트는 code 가 null 인 입력으로 넘긴다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"경로 맵에 없는 라우트는 code 가 null 인 입력으로 넘긴다"},{"ancestorTitles":["관리자 감시 가드"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 영업 등 관리자 계열 다른 종류는 판정하지 않고 종류 칸으로만 남긴다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"영업 등 관리자 계열 다른 종류는 판정하지 않고 종류 칸으로만 남긴다"},{"ancestorTitles":["관리자 감시 가드"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 위조된 관리자 쿠키는 invalid 칸으로 남고 판정하지 않는다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"위조된 관리자 쿠키는 invalid 칸으로 남고 판정하지 않는다"},{"ancestorTitles":["관리자 감시 가드"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 관리자 쿠키가 없으면 아무것도 붙이지 않는다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"관리자 쿠키가 없으면 아무것도 붙이지 않는다"},{"ancestorTitles":["관리자 감시 가드"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 열람 토큰 헤더만 있으면 검증 없이 view-token 칸으로 남긴다 (R1)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"열람 토큰 헤더만 있으면 검증 없이 view-token 칸으로 남긴다 (R1)"},{"ancestorTitles":["관리자 감시 가드"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 판정 준비가 던져도 통과시키고 guard-error 칸으로 남긴다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"판정 준비가 던져도 통과시키고 guard-error 칸으로 남긴다"},{"ancestorTitles":["관리자 감시 가드"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 가드 요청 객체가 비정상이어도 던지지 않고 true 다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"요청 객체가 비정상이어도 던지지 않고 true 다"},{"ancestorTitles":["판정하지 않는 신원 칸 (R2 타입)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"판정하지 않는 신원 칸 (R2 타입) 계수 칸 이름은 닫힌 집합이다 (오타 칸은 컴파일되지 않는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"계수 칸 이름은 닫힌 집합이다 (오타 칸은 컴파일되지 않는다)"}],"endTime":1792572862989,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-control/access-control.guard.spec.ts","startTime":1792572862577,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 미지 코드는 거부된다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"미지 코드는 거부된다"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 비최고관리자는 최고관리자 전용 코드를 쓰면 거부된다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"비최고관리자는 최고관리자 전용 코드를 쓰면 거부된다"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 비최고관리자는 최고관리자 전용 코드를 가진 역할을 회수하지 못한다 (잠금 아래 이전 집합으로 판정)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"비최고관리자는 최고관리자 전용 코드를 가진 역할을 회수하지 못한다 (잠금 아래 이전 집합으로 판정)"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 최고관리자 판정 조회가 실패하면 쓰지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"최고관리자 판정 조회가 실패하면 쓰지 않는다"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService DI 가 두 의존성을 실제 클래스로 찾는다 (Nest 가 읽는 design:paramtypes)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"DI 가 두 의존성을 실제 클래스로 찾는다 (Nest 가 읽는 design:paramtypes)"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":5,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 버전 sentinel 행이 없으면 던진다 (잠금 단계에서 중단하고 쓰지 않는다)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"버전 sentinel 행이 없으면 던진다 (잠금 단계에서 중단하고 쓰지 않는다)"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 쓰기 트랜잭션은 sentinel 잠금 → 역할 잠금 → 이전 집합 읽기 순서다 (잠금 전 읽기는 낡는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"쓰기 트랜잭션은 sentinel 잠금 → 역할 잠금 → 이전 집합 읽기 순서다 (잠금 전 읽기는 낡는다)"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 권한 쓰기는 같은 트랜잭션에서 버전을 올린다 (행 교체 뒤 · 감사 앞, 인라인 상승)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"권한 쓰기는 같은 트랜잭션에서 버전을 올린다 (행 교체 뒤 · 감사 앞, 인라인 상승)"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 잠금 아래에서 역할이 없으면 쓰지 않는다 (바깥 확인과 쓰기 사이의 삭제)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"잠금 아래에서 역할이 없으면 쓰지 않는다 (바깥 확인과 쓰기 사이의 삭제)"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 감사 행의 aud_changes 는 추가·삭제된 코드 목록을 싣는다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"감사 행의 aud_changes 는 추가·삭제된 코드 목록을 싣는다"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService aud_changes 가 1KB 를 넘으면 개수와 고위험 변경만 남기고 절단을 표시한다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"aud_changes 가 1KB 를 넘으면 개수와 고위험 변경만 남기고 절단을 표시한다"},{"ancestorTitles":["권한 쓰기 서비스 PermissionAdminService"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 서비스 PermissionAdminService 시드 스크립트의 감사 줄 버전은 감사 모듈과 같다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"시드 스크립트의 감사 줄 버전은 감사 모듈과 같다"}],"endTime":1792572863131,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/permission/permission-admin.service.spec.ts","startTime":1792572862551,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["권한 쓰기 컨트롤러 배선"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 컨트롤러 배선 가드 순서는 인증 · 역할 · 최고관리자 판정이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"가드 순서는 인증 · 역할 · 최고관리자 판정이다"},{"ancestorTitles":["권한 쓰기 컨트롤러 배선"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 컨트롤러 배선 역할 메타데이터는 admin 이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"역할 메타데이터는 admin 이다"},{"ancestorTitles":["권한 쓰기 컨트롤러 입력"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 컨트롤러 입력 codes 가 없으면 400 이고 서비스를 부르지 않는다 (전 권한 삭제로 해석하지 않는다)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"codes 가 없으면 400 이고 서비스를 부르지 않는다 (전 권한 삭제로 해석하지 않는다)"},{"ancestorTitles":["권한 쓰기 컨트롤러 입력"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 컨트롤러 입력 codes 가 문자열 배열이 아니면 400 이다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"codes 가 문자열 배열이 아니면 400 이다"},{"ancestorTitles":["권한 쓰기 컨트롤러 입력"],"duration":7,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 컨트롤러 입력 카탈로그 크기를 넘는 배열이나 64자를 넘는 코드는 400 이고 서비스를 부르지 않는다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"카탈로그 크기를 넘는 배열이나 64자를 넘는 코드는 400 이고 서비스를 부르지 않는다"},{"ancestorTitles":["권한 쓰기 컨트롤러 입력"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"권한 쓰기 컨트롤러 입력 명시적 빈 배열은 허용되고, 문자열 배열은 서비스로 넘어간다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"명시적 빈 배열은 허용되고, 문자열 배열은 서비스로 넘어간다"}],"endTime":1792572863159,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/permission/permission-admin.controller.spec.ts","startTime":1792572862521,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["최고관리자 판정 엔드포인트"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"최고관리자 판정 엔드포인트 permission: 최고관리자에게 isSuper 참을 낸다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"permission: 최고관리자에게 isSuper 참을 낸다"},{"ancestorTitles":["최고관리자 판정 엔드포인트"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"최고관리자 판정 엔드포인트 permission: 최고관리자가 아닌 내부 관리자에게 isSuper 거짓을 200 으로 낸다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"permission: 최고관리자가 아닌 내부 관리자에게 isSuper 거짓을 200 으로 낸다"},{"ancestorTitles":["최고관리자 판정 엔드포인트"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"최고관리자 판정 엔드포인트 permission: 판정을 내지 못하면 던져 비-200 이 된다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"permission: 판정을 내지 못하면 던져 비-200 이 된다"},{"ancestorTitles":["최고관리자 판정 엔드포인트"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"최고관리자 판정 엔드포인트 permission: 컨트롤러에 인증·역할 가드만 있고 최고관리자 가드가 없다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"permission: 컨트롤러에 인증·역할 가드만 있고 최고관리자 가드가 없다"}],"endTime":1792572863188,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/admin/super-admin-permission.controller.spec.ts","startTime":1792572862564,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":12,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B01) 관리자 갱신: 업무 갱신 → 상승 → 감사 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B01) 관리자 갱신: 업무 갱신 → 상승 → 감사 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B02) 관리자 삭제: 업무 삭제 → 상승 → 감사 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B02) 관리자 삭제: 업무 삭제 → 상승 → 감사 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B03) 기업 갱신: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B03) 기업 갱신: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B04) 기업 삭제: 업무 삭제 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B04) 기업 삭제: 업무 삭제 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B05) 조직 삭제 · 소속 해제: 회원 해제 → 상승 → 계약 · 조직 쓰기 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B05) 조직 삭제 · 소속 해제: 회원 해제 → 상승 → 계약 · 조직 쓰기 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B06) 권한 그룹 삭제: 그룹 · 권한 행 삭제 → 상승 → 감사 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B06) 권한 그룹 삭제: 그룹 · 권한 행 삭제 → 상승 → 감사 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B07) 회원 갱신 (소속 쓰기): 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B07) 회원 갱신 (소속 쓰기): 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B08) 퇴사: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B08) 퇴사: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":6,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B09) 회원 삭제: 업무 삭제 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B09) 회원 삭제: 업무 삭제 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B10) 소속 이동: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"status":"passed","title":"(B10) 소속 이동: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B11) 조직관리자 지정: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"status":"passed","title":"(B11) 조직관리자 지정: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B12) 자격 상실: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B12) 자격 상실: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"},{"ancestorTitles":["상승 행별 spec (M8b · 쓰기 대응표 13행)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"상승 행별 spec (M8b · 쓰기 대응표 13행) (B13) 자격 복귀: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"(B13) 자격 복귀: 업무 갱신 → 상승 순서이고 상승 실패면 거절 · 커밋 없음"}],"endTime":1792572863305,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/permission/permission-bump-sites.spec.ts","startTime":1792572862519,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 일괄 전건 거부: 영업 범위 밖 회원이 하나라도 있으면 403 이고 쓰기 0회다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"일괄 전건 거부: 영업 범위 밖 회원이 하나라도 있으면 403 이고 쓰기 0회다"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 일괄 전건 거부: 조직관리자 지정도 범위 밖 회원이 섞이면 쓰기 0회다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"일괄 전건 거부: 조직관리자 지정도 범위 밖 회원이 섞이면 쓰기 0회다"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 정상 경로: 담당 범위 회원만이면 같은 트랜잭션 tx 로 잠그고 판정하고 바꾼다","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"status":"passed","title":"정상 경로: 담당 범위 회원만이면 같은 트랜잭션 tx 로 잠그고 판정하고 바꾼다"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 잠금 순서: 회원 → 담당 기업 → 회원 현재 소속 조직 → 목적지 조직 (판정 전에 끝난다)","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"잠금 순서: 회원 → 담당 기업 → 회원 현재 소속 조직 → 목적지 조직 (판정 전에 끝난다)"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 음성: 범위 인자를 빼면 (담당 sagId 없음) 판정 대상 수가 어긋나 거부한다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"음성: 범위 인자를 빼면 (담당 sagId 없음) 판정 대상 수가 어긋나 거부한다"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 사전 판정: 범위 밖이면 트랜잭션을 열기 전에 거부한다 (잠금 0회)","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"사전 판정: 범위 밖이면 트랜잭션을 열기 전에 거부한다 (잠금 0회)"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 연결 1개: 영업 배정의 판정 조회 (목적지 조직 · 회원 기업) 는 모두 같은 tx 를 받는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"연결 1개: 영업 배정의 판정 조회 (목적지 조직 · 회원 기업) 는 모두 같은 tx 를 받는다"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 연결 1개: 기업 배정의 현행 판정 (회원 기업 · 목적지 조직) 도 같은 tx 를 받는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"연결 1개: 기업 배정의 현행 판정 (회원 기업 · 목적지 조직) 도 같은 tx 를 받는다"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 사전 판정 (corp): 담당 기업 밖 회원이 섞이면 트랜잭션도 잠금도 열기 전에 거부한다","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"status":"passed","title":"사전 판정 (corp): 담당 기업 밖 회원이 섞이면 트랜잭션도 잠금도 열기 전에 거부한다"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 신원 없음: 판정 신원이 없으면 판정 없이 통과하지 않고 거부한다 (쓰기 0회)","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"신원 없음: 판정 신원이 없으면 판정 없이 통과하지 않고 거부한다 (쓰기 0회)"},{"ancestorTitles":["강제 ON · 소속 쓰기 (영업 범위)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"강제 ON · 소속 쓰기 (영업 범위) 숫자가 아닌 sagId: 판정 조회 (SQL) 전에 403 이다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"숫자가 아닌 sagId: 판정 조회 (SQL) 전에 403 이다"}],"endTime":1792572863733,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-control/scope-enforce.spec.ts","startTime":1792572862559,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["핸들러 범위 절 · 목록 (I1 · I4)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 목록 (I1 · I4) ON: 영업 전 기업 목록(I1)은 담당 sagId 절을 저장소에 넘긴다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"ON: 영업 전 기업 목록(I1)은 담당 sagId 절을 저장소에 넘긴다"},{"ancestorTitles":["핸들러 범위 절 · 목록 (I1 · I4)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 목록 (I1 · I4) OFF: 같은 요청도 저장소 인자는 현행과 같이 비어 있다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"OFF: 같은 요청도 저장소 인자는 현행과 같이 비어 있다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 목록 (I1 · I4)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 목록 (I1 · I4) OFF: 구독 실패 목록(I4)도 저장소 인자가 null 이다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"OFF: 구독 실패 목록(I4)도 저장소 인자가 null 이다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 목록 (I1 · I4)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 목록 (I1 · I4) ON: 담당 영업 키가 없는 영업 신원은 500 이 아니라 403 으로 거부된다 (목록 호출 0회)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"ON: 담당 영업 키가 없는 영업 신원은 500 이 아니라 403 으로 거부된다 (목록 호출 0회)"},{"ancestorTitles":["핸들러 범위 절 · 목록 (I1 · I4)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 목록 (I1 · I4) ON: 구독 실패 목록(I4)은 절을 서비스에 넘기고, 목록과 count 는 같은 범위 조건을 쓴다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"ON: 구독 실패 목록(I4)은 절을 서비스에 넘기고, 목록과 count 는 같은 범위 조건을 쓴다"},{"ancestorTitles":["핸들러 범위 절 · 목록 (I1 · I4)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 목록 (I1 · I4) 범위 절 생성기는 같은 입력에 같은 절 목록을 돌려준다 (집계·내보내기 경로는 이 시험이 보지 않는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"범위 절 생성기는 같은 입력에 같은 절 목록을 돌려준다 (집계·내보내기 경로는 이 시험이 보지 않는다)"},{"ancestorTitles":["단건 3의미 (분리 함수)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"단건 3의미 (분리 함수) 3의미는 이름별 함수로 나뉘고 같은 입력에 서로 다른 의미를 합치지 않는다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"3의미는 이름별 함수로 나뉘고 같은 입력에 서로 다른 의미를 합치지 않는다"},{"ancestorTitles":["핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀) ON: 영업 머니 내역 목록은 담당 sagId 절을 서비스에 넘긴다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"ON: 영업 머니 내역 목록은 담당 sagId 절을 서비스에 넘긴다"},{"ancestorTitles":["핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀) 범위 인자 동일: 머니 내역 목록과 count 는 같은 범위 절 객체를 저장소에 넘긴다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 인자 동일: 머니 내역 목록과 count 는 같은 범위 절 객체를 저장소에 넘긴다"},{"ancestorTitles":["핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀) 범위 인자 동일: 결제 목록과 count 도 같은 범위 절을 받는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 인자 동일: 결제 목록과 count 도 같은 범위 절을 받는다"},{"ancestorTitles":["핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀) OFF: 머니 내역 목록의 저장소 인자는 null 이다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"OFF: 머니 내역 목록의 저장소 인자는 null 이다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 목록 (I5 · I6 목록 · 엑셀) ON: 담당 영업 키가 없는 영업 신원은 머니 목록에서 403 이고 서비스를 부르지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"ON: 담당 영업 키가 없는 영업 신원은 머니 목록에서 403 이고 서비스를 부르지 않는다"},{"ancestorTitles":["핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록) 범위 인자 동일: 적립 목록과 count 는 같은 범위 절 객체를 저장소에 넘긴다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 인자 동일: 적립 목록과 count 는 같은 범위 절 객체를 저장소에 넘긴다"},{"ancestorTitles":["핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록) ON: 영업 적립 목록 컨트롤러는 담당 sagId 절을 서비스에 넘긴다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"ON: 영업 적립 목록 컨트롤러는 담당 sagId 절을 서비스에 넘긴다"},{"ancestorTitles":["핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록) OFF: 적립 목록의 범위 인자는 null 이다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"OFF: 적립 목록의 범위 인자는 null 이다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록) 타 기업 누출 0: 담당이 아닌 기업의 기업머니 내역은 403 이고 이력 · 요약을 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"타 기업 누출 0: 담당이 아닌 기업의 기업머니 내역은 403 이고 이력 · 요약을 읽지 않는다"},{"ancestorTitles":["핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록) 범위 인자 동일: 담당 기업의 이력 목록과 count 는 같은 범위 절을 받는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 인자 동일: 담당 기업의 이력 목록과 count 는 같은 범위 절을 받는다"},{"ancestorTitles":["핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록) OFF: 기업머니 내역은 범위 검사 없이 저장소 인자 null 이다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"OFF: 기업머니 내역은 범위 검사 없이 저장소 인자 null 이다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 적립 · 기업 이력 (I7 · I5 목록) 타 기업 누출 0 (질의 형상): 영업 담당 조건은 그 영업의 sagId 만 인자로 갖는다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"타 기업 누출 0 (질의 형상): 영업 담당 조건은 그 영업의 sagId 만 인자로 갖는다"},{"ancestorTitles":["핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7) 담당 기업의 다른 회원 허용: 회원 기업의 담당 영업이 요청 영업이면 회원 내역을 서비스가 준다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"담당 기업의 다른 회원 허용: 회원 기업의 담당 영업이 요청 영업이면 회원 내역을 서비스가 준다"},{"ancestorTitles":["핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7) 타 기업 거부: 회원 기업의 담당 영업이 다르면 403 이고 회원 내역을 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"타 기업 거부: 회원 기업의 담당 영업이 다르면 403 이고 회원 내역을 읽지 않는다"},{"ancestorTitles":["핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7) 미선언 403: 담당 영업 키가 없는 영업 신원은 소유 기업이 맞아도 적립 단건에서 403 이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"미선언 403: 담당 영업 키가 없는 영업 신원은 소유 기업이 맞아도 적립 단건에서 403 이다"},{"ancestorTitles":["핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7) 타 기업 거부 (적립 단건): 담당이 아닌 기업의 지급건은 403 이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"타 기업 거부 (적립 단건): 담당이 아닌 기업의 지급건은 403 이다"},{"ancestorTitles":["핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7) 타 기업 거부 (결제 단건): 결제 회원 기업의 담당 영업이 다르면 상세와 이용내역 모두 403 이다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"타 기업 거부 (결제 단건): 결제 회원 기업의 담당 영업이 다르면 상세와 이용내역 모두 403 이다"},{"ancestorTitles":["핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7) OFF: 회원 내역 단건은 소유 기업 조회 (getMemberAgcId · getSagIdOfAgc) 를 하지 않는다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"OFF: 회원 내역 단건은 소유 기업 조회 (getMemberAgcId · getSagIdOfAgc) 를 하지 않는다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 머니 단건 · 조직 단건 (I2 · I5 · I6 · I7) 범위 밖 조직 거부: 영업 신원이 담당이 아닌 기업의 조직 상세를 보면 403 이고 상세를 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 밖 조직 거부: 영업 신원이 담당이 아닌 기업의 조직 상세를 보면 403 이고 상세를 읽지 않는다"},{"ancestorTitles":["핸들러 범위 절 · 분석 상세 단건 (I8)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 분석 상세 단건 (I8) 타 기업 거부 (분석 상세): 분석 행의 소유 기업이 담당 영업 것이 아니면 403 이고 상세를 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"타 기업 거부 (분석 상세): 분석 행의 소유 기업이 담당 영업 것이 아니면 403 이고 상세를 읽지 않는다"},{"ancestorTitles":["핸들러 범위 절 · 분석 상세 단건 (I8)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 분석 상세 단건 (I8) 담당 기업의 분석 상세는 허용되고 서비스가 상세를 준다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"담당 기업의 분석 상세는 허용되고 서비스가 상세를 준다"},{"ancestorTitles":["핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완) 타 기업 거부 (집계 · 내보내기): 분석 원장의 소유 기업이 담당 영업 것이 아니면 403 이고 집계 · 원자료를 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"타 기업 거부 (집계 · 내보내기): 분석 원장의 소유 기업이 담당 영업 것이 아니면 403 이고 집계 · 원자료를 읽지 않는다"},{"ancestorTitles":["핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완) 타 기업 거부 (기본 · 처방): 분석 원장의 소유 기업이 담당 영업 것이 아니면 403 이고 기본 · 처방을 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"타 기업 거부 (기본 · 처방): 분석 원장의 소유 기업이 담당 영업 것이 아니면 403 이고 기본 · 처방을 읽지 않는다"},{"ancestorTitles":["핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완) 담당 기업의 기본 · 처방은 허용되고 서비스가 준다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"담당 기업의 기본 · 처방은 허용되고 서비스가 준다"},{"ancestorTitles":["핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완) 담당 기업의 집계 · 내보내기는 허용되고 서비스가 준다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"담당 기업의 집계 · 내보내기는 허용되고 서비스가 준다"},{"ancestorTitles":["핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 분석 집계 · 내보내기 (I8, M6b 보완) OFF: 집계 · 내보내기는 소유 조회를 하지 않는다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"OFF: 집계 · 내보내기는 소유 조회를 하지 않는다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완) 타 기업 거부 (기업 지급 · 개별 지급): 대상 기업의 담당 영업이 다르면 403 이고 지급 서비스를 부르지 않는다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"타 기업 거부 (기업 지급 · 개별 지급): 대상 기업의 담당 영업이 다르면 403 이고 지급 서비스를 부르지 않는다"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완) 타 기업 거부 (기업 엑셀 지급 · 기업 충전): 대상 기업이 다르면 403 이고 서비스를 부르지 않는다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"타 기업 거부 (기업 엑셀 지급 · 기업 충전): 대상 기업이 다르면 403 이고 서비스를 부르지 않는다"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완) 타 기업 거부 (결제 취소): 결제 회원 기업의 담당 영업이 다르면 403 이고 취소를 부르지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"타 기업 거부 (결제 취소): 결제 회원 기업의 담당 영업이 다르면 403 이고 취소를 부르지 않는다"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완) 담당 기업의 지급은 허용되고 서비스가 받는다 (정상 경로)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"담당 기업의 지급은 허용되고 서비스가 받는다 (정상 경로)"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 (기업 지정 지급 · 충전 · 결제 취소, M6b 보완) OFF: 기업 지급은 대상 기업 소유 조회를 하지 않는다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"OFF: 기업 지급은 대상 기업 소유 조회를 하지 않는다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2) ON: 영업 환불 목록은 담당 sagId 절을 서비스에 넘긴다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"ON: 영업 환불 목록은 담당 sagId 절을 서비스에 넘긴다"},{"ancestorTitles":["핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2) OFF: 환불 목록은 범위 인자가 null 이다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"OFF: 환불 목록은 범위 인자가 null 이다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2) 범위 인자 동일: 환불 목록과 count 는 같은 범위 절 객체를 저장소에 넘긴다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 인자 동일: 환불 목록과 count 는 같은 범위 절 객체를 저장소에 넘긴다"},{"ancestorTitles":["핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2) 타 기업 거부 (환불 단건): 환불 회원 기업의 담당 영업이 다르면 403 이고 환불을 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"타 기업 거부 (환불 단건): 환불 회원 기업의 담당 영업이 다르면 403 이고 환불을 읽지 않는다"},{"ancestorTitles":["핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 절 · 환불 목록 · 단건 (M6b 보완 · R2) 담당 기업의 환불 단건은 허용되고 서비스가 준다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"담당 기업의 환불 단건은 허용되고 서비스가 준다"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1) 잠금 뒤 판정 인자: 담당 영업의 쓰기 4종은 담당 번호를 서비스에 넘긴다 (충전 · 지급 · 개별 · 엑셀)","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"잠금 뒤 판정 인자: 담당 영업의 쓰기 4종은 담당 번호를 서비스에 넘긴다 (충전 · 지급 · 개별 · 엑셀)"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1) 잠금 뒤 판정 인자: 상수 OFF 면 판정 인자가 undefined 다 (응답 불변)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"잠금 뒤 판정 인자: 상수 OFF 면 판정 인자가 undefined 다 (응답 불변)"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1) 잠금 뒤 판정: 잠근 기업의 담당이 신원과 다르면 (사전 판정 뒤 재배정 경합) 403 으로 되돌린다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"잠금 뒤 판정: 잠근 기업의 담당이 신원과 다르면 (사전 판정 뒤 재배정 경합) 403 으로 되돌린다"},{"ancestorTitles":["핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"핸들러 범위 판정 · 머니 쓰기 잠금 뒤 판정 (M6b 보완 R1) 잠금 뒤 판정: 담당이 같으면 통과하고, 판정 인자가 없으면 저장소를 읽지 않는다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"잠금 뒤 판정: 담당이 같으면 통과하고, 판정 인자가 없으면 저장소를 읽지 않는다"}],"endTime":1792572863874,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-control/scope-handlers.spec.ts","startTime":1792572862555,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["관리자 감시 인터셉터"],"duration":23,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 판정 예외는 unknown 으로 접힌다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"판정 예외는 unknown 으로 접힌다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":352,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 풀 포화 때 업무 요청이 시간 상한 안에 끝난다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"풀 포화 때 업무 요청이 시간 상한 안에 끝난다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":20,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 정지한 DB 작업이 있어도 동시 실행은 상한을 넘지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"정지한 DB 작업이 있어도 동시 실행은 상한을 넘지 않는다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":356,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 시간 상한이 지나면 멈춘 판정의 슬롯을 돌려준다 (풀 연결은 여전히 쥐어 있다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"시간 상한이 지나면 멈춘 판정의 슬롯을 돌려준다 (풀 연결은 여전히 쥐어 있다)"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 감시 풀은 연결 2 · 대기 없음 · 큐 0 이다 (DB 쪽 동시 상한은 이 값이다)","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"감시 풀은 연결 2 · 대기 없음 · 큐 0 이다 (DB 쪽 동시 상한은 이 값이다)"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":21,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 최고관리자 판정 조회는 감시 연결로 간다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"최고관리자 판정 조회는 감시 연결로 간다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 판정 결과 unmapped 는 허용으로 세지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"판정 결과 unmapped 는 허용으로 세지 않는다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":6,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 요청 처리 중 감시 코드가 던져도 업무 요청은 끊기지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"요청 처리 중 감시 코드가 던져도 업무 요청은 끊기지 않는다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":31,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 기록 단계가 던져도 처리되지 않은 거부가 생기지 않는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"기록 단계가 던져도 처리되지 않은 거부가 생기지 않는다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 감시 연결마다 질의 시간 상한을 건다 (정지한 질의를 서버가 끊는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"감시 연결마다 질의 시간 상한을 건다 (정지한 질의를 서버가 끊는다)"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 SET 이 실패한 감시 연결은 버리고 경고를 남긴다 (R2)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"SET 이 실패한 감시 연결은 버리고 경고를 남긴다 (R2)"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 미배정 관리자 요청은 판정하지 않고 집계한다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"미배정 관리자 요청은 판정하지 않고 집계한다"},{"ancestorTitles":["관리자 감시 인터셉터"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"관리자 감시 인터셉터 판정 입력이 없으면 아무것도 세지 않는다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"판정 입력이 없으면 아무것도 세지 않는다"}],"endTime":1792572863912,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-control/access-control.spec.ts","startTime":1792572862512,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["접근 계약 부팅 단언 판정"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 부팅 단언 판정 레지스트리와 런타임 집합이 같으면 위반이 없다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"레지스트리와 런타임 집합이 같으면 위반이 없다"},{"ancestorTitles":["접근 계약 부팅 단언 판정"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 부팅 단언 판정 음성: 행 하나를 뺀 레지스트리면 선언 없음 위반이 1이다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"음성: 행 하나를 뺀 레지스트리면 선언 없음 위반이 1이다"},{"ancestorTitles":["접근 계약 부팅 단언 판정"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 부팅 단언 판정 음성: 레지스트리에 없는 경로가 런타임에 있으면 미지 경로 위반이 1이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: 레지스트리에 없는 경로가 런타임에 있으면 미지 경로 위반이 1이다"},{"ancestorTitles":["접근 계약 부팅 단언 판정"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 부팅 단언 판정 레지스트리에만 있는 행은 런타임 부재 위반이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"레지스트리에만 있는 행은 런타임 부재 위반이다"},{"ancestorTitles":["접근 계약 부팅 단언 판정"],"duration":4,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 부팅 단언 판정 음성: 예외 경로가 런타임 집합에 없어도 위반이 0이다 (예외가 누락 검사를 덮는다)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"음성: 예외 경로가 런타임 집합에 없어도 위반이 0이다 (예외가 누락 검사를 덮는다)"},{"ancestorTitles":["접근 계약 예외표 · 접두 경계"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 예외표 · 접두 경계 예외 경로 7개와 접두 /swagger/ 아래 경로는 위반이 아니다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"예외 경로 7개와 접두 /swagger/ 아래 경로는 위반이 아니다"},{"ancestorTitles":["접근 계약 예외표 · 접두 경계"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 예외표 · 접두 경계 음성: /swagger-admin 과 /swagger-admin/x 는 예외가 아니라 미지 경로 위반이다 (접두 경계)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: /swagger-admin 과 /swagger-admin/x 는 예외가 아니라 미지 경로 위반이다 (접두 경계)"},{"ancestorTitles":["접근 계약 예외표 · 접두 경계"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 예외표 · 접두 경계 음성: 예외 경로의 다른 메서드(DELETE /health · POST /live)는 예외가 아니라 미지 경로 위반이다 (메서드 경계)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: 예외 경로의 다른 메서드(DELETE /health · POST /live)는 예외가 아니라 미지 경로 위반이다 (메서드 경계)"},{"ancestorTitles":["접근 계약 모드 · 단언 불능"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 모드 · 단언 불능 warn 은 던지지 않고 Logger.warn 을 한 번 부른다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"warn 은 던지지 않고 Logger.warn 을 한 번 부른다"},{"ancestorTitles":["접근 계약 모드 · 단언 불능"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 모드 · 단언 불능 음성(리뷰 R1): warn 에서 위반 0건이면 Logger.log 한 줄로 모드와 대조 행 수를 남기고 warn 은 부르지 않는다","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"status":"passed","title":"음성(리뷰 R1): warn 에서 위반 0건이면 Logger.log 한 줄로 모드와 대조 행 수를 남기고 warn 은 부르지 않는다"},{"ancestorTitles":["접근 계약 모드 · 단언 불능"],"duration":11,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 모드 · 단언 불능 fail 은 던진다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"fail 은 던진다"},{"ancestorTitles":["접근 계약 모드 · 단언 불능"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 모드 · 단언 불능 음성: 라우터 스택 없음 입력과 수집 0건 입력은 단언 불능 위반 1건이다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"음성: 라우터 스택 없음 입력과 수집 0건 입력은 단언 불능 위반 1건이다"},{"ancestorTitles":["접근 계약 모드 · 단언 불능"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 모드 · 단언 불능 음성: 단언 불능은 warn 에서 던지지 않고 fail 에서 던진다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"음성: 단언 불능은 warn 에서 던지지 않고 fail 에서 던진다"},{"ancestorTitles":["접근 계약 모드 · 단언 불능"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 모드 · 단언 불능 음성: 라우터 스택이 없는 Express 앱은 단언 불능으로 세고 부팅을 멈추지 않는다 (warn)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"음성: 라우터 스택이 없는 Express 앱은 단언 불능으로 세고 부팅을 멈추지 않는다 (warn)"},{"ancestorTitles":["접근 계약 모드 · 단언 불능"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 모드 · 단언 불능 음성: fail 모드에서 라우터 스택이 없는 앱은 단언 불능으로 던진다 (fail-open 금지)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: fail 모드에서 라우터 스택이 없는 앱은 단언 불능으로 던진다 (fail-open 금지)"},{"ancestorTitles":["접근 계약 실제 라우터 수집"],"duration":92,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 실제 라우터 수집 실제 라우터: 최소 Nest 모듈의 GET /zz-probe 를 수집하고 빈 레지스트리에서 미지 경로 1건이다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"실제 라우터: 최소 Nest 모듈의 GET /zz-probe 를 수집하고 빈 레지스트리에서 미지 경로 1건이다"},{"ancestorTitles":["접근 계약 실제 라우터 수집"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 실제 라우터 수집 음성: 목록 밖 와일드카드 핸들러(/zz-export/*)는 수집에서 빠지지 않고 미지 경로 위반이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: 목록 밖 와일드카드 핸들러(/zz-export/*)는 수집에서 빠지지 않고 미지 경로 위반이다"},{"ancestorTitles":["접근 계약 실제 라우터 수집"],"duration":5,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 실제 라우터 수집 실제 Swagger 경로: setupSwagger 가 만든 문서 경로(-json · -yaml · 접두)는 예외표로 덮여 위반이 없다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"실제 Swagger 경로: setupSwagger 가 만든 문서 경로(-json · -yaml · 접두)는 예외표로 덮여 위반이 없다"},{"ancestorTitles":["접근 계약 와일드카드 등록 (미들웨어 층 대 핸들러)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 와일드카드 등록 (미들웨어 층 대 핸들러) 미들웨어 2층 + @Get(*) 핸들러 = 핸들러 GET /* 1건만 위반이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"미들웨어 2층 + @Get(*) 핸들러 = 핸들러 GET /* 1건만 위반이다"},{"ancestorTitles":["접근 계약 와일드카드 등록 (미들웨어 층 대 핸들러)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 와일드카드 등록 (미들웨어 층 대 핸들러) 음성: 미들웨어 층 없이 @Get(*) 핸들러만 있으면 GET /* 가 위반이다 (기준 개수로 가리지 않는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: 미들웨어 층 없이 @Get(*) 핸들러만 있으면 GET /* 가 위반이다 (기준 개수로 가리지 않는다)"},{"ancestorTitles":["접근 계약 와일드카드 등록 (미들웨어 층 대 핸들러)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 와일드카드 등록 (미들웨어 층 대 핸들러) 음성: 미들웨어 층이 1개로 줄고 핸들러가 남으면 위반이 숨지 않는다 (슬롯 빌림 금지)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: 미들웨어 층이 1개로 줄고 핸들러가 남으면 위반이 숨지 않는다 (슬롯 빌림 금지)"},{"ancestorTitles":["접근 계약 와일드카드 등록 (M4 · 1509 반례)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 와일드카드 등록 (M4 · 1509 반례) 미선언 와일드카드 핸들러는 위반으로 잡힌다 (미들웨어 2층은 빼고 핸들러 층은 남긴다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"미선언 와일드카드 핸들러는 위반으로 잡힌다 (미들웨어 2층은 빼고 핸들러 층은 남긴다)"},{"ancestorTitles":["접근 계약 와일드카드 등록 (@All 핸들러의 모양은 미들웨어와 같다)"],"duration":2,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 와일드카드 등록 (@All 핸들러의 모양은 미들웨어와 같다) 음성(리뷰 R1 codex): 미들웨어 1층 + 미선언 @All(*) 면 핸들러 층 ACL 이 위반으로 남는다 (층 수 2 로 가리지 않는다)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성(리뷰 R1 codex): 미들웨어 1층 + 미선언 @All(*) 면 핸들러 층 ACL 이 위반으로 남는다 (층 수 2 로 가리지 않는다)"},{"ancestorTitles":["접근 계약 와일드카드 등록 (@All 핸들러의 모양은 미들웨어와 같다)"],"duration":3,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 와일드카드 등록 (@All 핸들러의 모양은 미들웨어와 같다) 미들웨어 2층 + 미선언 @All(*): 미들웨어 두 층은 빠지고 핸들러 층의 GET /* 가 1건 위반으로 남는다","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"미들웨어 2층 + 미선언 @All(*): 미들웨어 두 층은 빠지고 핸들러 층의 GET /* 가 1건 위반으로 남는다"},{"ancestorTitles":["접근 계약 main.ts 배선"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 main.ts 배선 main.ts 는 listen 앞에서 비주석 부팅 단언 호출을 정확히 한 번 한다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"main.ts 는 listen 앞에서 비주석 부팅 단언 호출을 정확히 한 번 한다"},{"ancestorTitles":["접근 계약 main.ts 배선"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 main.ts 배선 음성: 호출을 주석 처리하면 호출 0건이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: 호출을 주석 처리하면 호출 0건이다"},{"ancestorTitles":["접근 계약 main.ts 배선"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 main.ts 배선 음성: 호출을 listen 뒤로 옮기면 before 가 거짓이다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"음성: 호출을 listen 뒤로 옮기면 before 가 거짓이다"},{"ancestorTitles":["접근 계약 실제 AppModule 대조"],"duration":1709,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 실제 AppModule 대조 실제 AppModule: setupSwagger 를 붙인 앱이 fail 단언을 통과하고 미선언 핸들러가 없다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"실제 AppModule: setupSwagger 를 붙인 앱이 fail 단언을 통과하고 미선언 핸들러가 없다"},{"ancestorTitles":["접근 계약 범위 선언 (M6b Task 5)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 범위 선언 (M6b Task 5) 현재 레지스트리는 범위 선언 누락 위반이 0건이다 (골든 목록 대조)","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"현재 레지스트리는 범위 선언 누락 위반이 0건이다 (골든 목록 대조)"},{"ancestorTitles":["접근 계약 범위 선언 (M6b Task 5)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 범위 선언 (M6b Task 5) 범위 선언 누락 1건: 신규 영업 자동 칸 행 하나를 더한 사본은 위반이 1이다","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"status":"passed","title":"범위 선언 누락 1건: 신규 영업 자동 칸 행 하나를 더한 사본은 위반이 1이다"},{"ancestorTitles":["접근 계약 범위 선언 (M6b Task 5)"],"duration":1,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 범위 선언 (M6b Task 5) 범위 선언 누락 1건: 저자 선언(author) 이면 신규 행도 위반이 아니다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"범위 선언 누락 1건: 저자 선언(author) 이면 신규 행도 위반이 아니다"},{"ancestorTitles":["접근 계약 범위 선언 (M6b Task 5)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 범위 선언 (M6b Task 5) 범위 필드가 없는 행은 조용히 통과하지 않고 단언 불능으로 센다 (fail-closed)","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"status":"passed","title":"범위 필드가 없는 행은 조용히 통과하지 않고 단언 불능으로 센다 (fail-closed)"},{"ancestorTitles":["접근 계약 범위 선언 (M6b Task 5)"],"duration":0,"failureDetails":[],"failureMessages":[],"fullName":"접근 계약 범위 선언 (M6b Task 5) fail 모드는 던진다: 범위 선언 누락 위반이 있으면 부팅 단언이 멈춘다","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"status":"passed","title":"fail 모드는 던진다: 범위 선언 누락 위반이 있으면 부팅 단언이 멈춘다"}],"endTime":1792572864930,"message":"","name":"/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac/insuniverse-server/apps/api/src/modules/auth/access-contract/access-contract.spec.ts","startTime":1792572862517,"status":"passed","summary":""}],"wasInterrupted":false}
