목록을 보호해도 드롭다운이 다른 사용자의 값을 읽을 수 있다

보이스 목록에서 다른 사용자의 클론을 제외해도, 언어·억양 필터가 별도로 전체 보이스의 distinct 값을 조회하면 그 사용자의 메타데이터가 옵션에 남는다. 항목 이름을 보여주지 않아도, 남의 데이터에서 나온 값이라는 접근 범위 문제는 그대로다.

AI Commons에서 수정 전에는 여섯 필터 조회가 삭제 여부만 확인했다. 변경에서는 컨트롤러가 로그인 사용자 ID를 서비스에 넘기고, 각 distinct 조회에 다음 공통 조건을 적용했다.

const baseWhere = {
  deletedAt: null,
  OR: [{ kind: "BUILTIN" }, { kind: "CLONED", userId }],
};

공용 보이스와 현재 사용자 소유 클론만 옵션의 재료로 삼는 조건이다. 현재 화면의 한 페이지에서 옵션을 계산하면 다른 페이지의 유효한 값을 놓친다. 별도 조회를 유지하면서 그 조회에도 의도한 접근 범위를 주는 편이 이 요구에 맞는다.

보조 조회는 목록의 권한을 자동으로 물려받지 않는다

수정 뒤에도 distinct 쿼리는 여섯 번이다. 이 변화의 효과는 조회 횟수 감소가 아니라 데이터 범위 제한이다. 검색 제안, 개수, 필터 옵션처럼 목록 주변에서 따로 읽는 값도 각각의 조회 조건을 확인해야 한다.

테스트 코드는 결과 키, null 제거, 빈 배열을 검사하며 사용자 ID를 인자로 넘기도록 바뀌었다. where 조건 자체나 다른 사용자의 클론 제외를 검사하지는 않는다. 접근 범위를 제한하는 쿼리 조건과, 그 제한을 직접 검사하는 테스트는 구분해야 한다. 이후 협업 소유자 선택과 나이·성별 옵션의 공용 보이스 전용 조회가 추가됐으므로, 이 조건을 현재 모든 목록과 옵션이 완전히 같은 정책을 쓴다는 설명으로 확대할 수는 없다.