다크모드
계정 보안·패스워드 변경 — BE 참고 매뉴얼
인증 계약
패스워드의 정본은 Supabase Auth의 auth.users.encrypted_password다. 애플리케이션 테이블, 브라우저 저장소, 감사 로그에는 현재·새 패스워드 또는 해시를 저장하지 않는다.
계정 일반과 개인·Company·빌링 프로필의 인라인 편집은 현재 Prototype 로컬 상태로 UX만 검증한다. 운영 API로 연결할 때 관리코드·로그인 아이디·생성 일시·등록번호는 변경 불가이며, 이름·약칭·연락처·주소·담당자처럼 허용된 필드만 allowlist 업데이트한다. 읽기 카드와 편집 폼이 같은 페이지에 있다는 사실은 인가 경계를 바꾸지 않는다. 이메일·휴대전화가 변경되면 기존 인증 상태를 승계하지 말고 재인증 상태로 전환한다.
변경 순서는 다음과 같다.
- 현재 access token으로
auth.getUser()를 호출해 로그인 사용자를 확인한다. - 반환된 Auth 이메일과 사용자가 입력한 현재 패스워드로
signInWithPassword()를 호출해 재인증한다. 직원의 내부 Auth 이메일은 UI에 노출하지 않는다. - 재인증 성공 후
auth.updateUser({ password })로 새 패스워드를 저장한다. - 성공 시 기본 global scope의
auth.signOut()으로 모든 refresh token을 폐기하고 재로그인을 요구한다.
조직 계정과 워크스페이스 계정은 같은 패스워드 변경 계약을 쓰며 로그인 식별자만 다릅니다. 공개 로그인 ID와 내부 Auth 식별자는 분리하고, 실제 패스워드 검증은 credential provider가 담당합니다.
로그인 화면의 조직 | 워크스페이스는 인증 문맥 선택이고 role 선택이 아닙니다. 로그인 문구나 route에서 role을 파생하지 않으며 membership과 role assignment를 별도로 판정합니다.
보호 경로의 미인증 fallback과 계정 종류가 불명확한 일반 로그아웃은 /auth/workspace로 보냅니다. 조직 이메일 확인·패스워드 재설정처럼 계정 문맥이 확정된 callback은 /auth/organization을 사용합니다. 과거 /auth/staff와 /auth/signin은 링크 호환 alias일 뿐 신규 계약에 사용하지 않습니다.
검증과 오류
- 새 패스워드 최소 길이: 8자
- 현재 패스워드와 같은 새 패스워드: 거부
- 현재 패스워드 오류:
current-password-invalid - 세션·사용자 조회 실패:
session-unavailable - Auth 변경 실패:
password-update-failed
오류 응답과 UI에는 내부 이메일, 사용자 존재 여부, Supabase 원문 오류를 노출하지 않는다. 패스워드 값은 로깅하거나 분석 이벤트 payload에 포함하지 않는다.
패스워드 표시/숨김은 브라우저 입력 type=password|text만 전환하는 FE 동작이다. API payload, 인증 순서, 저장 계약은 바뀌지 않으며 표시 상태도 저장하지 않는다.
후속
조직 이메일 계정은 검증된 이메일 recovery를 사용합니다. 조직·워크스페이스 로그인 ID 계정은 관리자의 본인 확인과 임시 패스워드 발급·최초 변경 강제를 별도 상태머신으로 구현해야 합니다. must_change_password는 그 후속 흐름에서 사용합니다.