상담원 화면 문구를 「원문 표시 · 저장 시 마스킹」 정책에 맞춘다 — 잠금 아이콘 「민감정보가 마스킹되었습니다」

장민석이 넘긴 일이다(2026-10-06). 서버·콜 미디에이터 쪽은 w8-screen-plain-storage-encrypt(장민석)에서 바꿨고, 프론트는 고치지 않았다(사용자 지시 — 프론트는 조서희 전담). 근거: _project/decisions/326(비공개).

무엇이 바뀌었나

콜 미디에이터 0.2.14 부터 /ws 의 transcript.text 가 원문이다. masked 구간은 그대로 오고, MaskedText 가 그 자리 글자를 <mark> 로 그리므로 화면은 「원문 + 개인정보 자리 강조」가 된다(코드 수정 없이 동작). DB 저장 쪽은 지금처럼 마스킹본이다 — 지난 통화 보기(GET /hub/calls/{id}/transcript)는 여전히 마스킹본을 준다.

정할 것 — 문구가 옛 정책 그대로다

2026-10-08 — 정성윤이 넘겨받아 했다

담당을 조서희 → 정성윤으로 옮겼다(CLAUDE.md §4 — 넘겨받았으면 적는다). apps/ 는 조서희 전담이지만 PM 지시로 가져왔다(§0 — 사용자 지시가 우선). 문구를 어떻게 쓸지는 프론트 판단이라 되돌리거나 다시 쓰셔도 된다.

들여다보니 문구만의 문제가 아니었다

실서버에서 실제로 무엇이 그려지는지 코드로 따라가 보니 두 가지가 갈렸다.

자리 실서버에서 판정
자물쇠 아이콘 「민감정보가 마스킹되었습니다」 안 뜬다 — piiMatches 는 !isCoreApiConfigured() 일 때만 찬다(mock 전용) 문구만 고침
「⚠ 경고」 배지 뜬다 — hasAlert = item.masked.length > 0 이라 개인정보 구간이 있으면 무조건 실제 문제
.masked-span 빨간 강조 원문을 감싼다 — ***** 를 덮던 색인데 이제 번호 위에 얹힌다 실제 문제

뒤의 둘이 시연 영상 검토(2026-10-02) 지적 ③ 「⚠ 경고 배지가 고객의 개인정보 발화에 붙는다」의 정체다. 상담원 위반과 같은 빨간 배지가 고객이 번호를 불렀을 뿐인 줄에 붙고, 빨간 강조가 번호로 눈을 끌었다.

고친 것

  1. 「⚠ 경고」 → 「저장 시 가림」(.alert-pill.is-mask, 중립 회색). title 「저장·전송할 때 이 부분은 가려집니다」
  2. .masked-span 기본색을 중립 회색 + 점선 밑줄로 — 「저장할 때 가려질 자리」라는 뜻만 전한다. ⚠ mock 의 .is-pii·.is-abuse 는 「이미 가려진 자리」라 그대로 뒀다
  3. 자물쇠 title·aria-label → 「저장할 때 가려지는 부분입니다」
  4. MaskedText.tsx 주석 — 「실서버는 원문을 절대 주지 않는다」가 거짓이 됐다. SEC-1 이 왜 그대로 성립하는지로 다시 썼다
  5. maskSensitiveText.ts 에 「mock 전용」 한 줄
  6. .claude/rules/call.md §2 — 옛 문장은 긋고 새 규칙을 적었다(절대 원칙 8)

검증

tsc --noEmit 통과 · npm test 92건 통과(기존 87 + 새 5). 새 테스트 test/plainScreenCopy.test.tsx 는 소스를 직접 읽어 옛 문구가 되살아나는지 본다 — 손으로 적은 목록끼리 맞추면 또 갈라지기 때문이다(ai 쪽에서 09-22 에 실제로 겪었다).

⚠ 운영 화면에서 눈으로 보지는 않았다 — 배포 뒤 확인이 남는다.