핵심 내용
- 각 레스토랑의 데이터는 앱에서만이 아니라 데이터베이스 자체 안에서 분리됩니다.
- 비밀번호는 scrypt로 해시 처리되며, 실패가 반복되면 계정이 15분 동안 잠깁니다.
- 세션은 갱신할 때마다 교체되며, 이미 사용된 세션이 다시 쓰이면 로그인 체인 전체가 종료됩니다.
- 주문, 현금, 포인트, 감사 기록은 추가만 가능합니다.
레스토랑마다 독립된 공간
모든 레스토랑이 하나의 플랫폼에서 운영되지만, 분리는 데이터베이스가 강제합니다. 모든 레스토랑 테이블에는 행 수준 보안(RLS)이 켜져 있고 강제 적용되며, 모든 요청은 하나의 레스토랑으로 설정된 트랜잭션 안에서 실행됩니다. 애플리케이션이 사용하는 계정은 이 규칙을 우회할 수 없습니다.
제한된 작업을 위해 이 규칙을 통과할 수 있는 내부 역할은 두 가지입니다. 하나는 백그라운드 작업자로, 활성 레스토랑 목록만 조회한 뒤 레스토랑별로 작업을 수행할 수 있습니다. 다른 하나는 SCALE 팀의 관리 센터로, 고객 주소, 주문 위치, 비밀번호 해시, 레스토랑 자체 감사 로그에는 접근할 수 없습니다.
로그인과 비밀번호
- 비밀번호는 8자에서 128자이며, 무작위 솔트와 함께 scrypt 해시로 저장되고, 일정한 시간 안에 비교됩니다.
- 비밀번호를 5회 잘못 입력하면 계정이 15분 동안 잠깁니다. 존재하지 않는 계정으로 로그인해도 같은 시간이 걸리므로, 어떤 계정이 존재하는지 드러나지 않습니다.
- 로그인 시도는 15분 동안 주소별로도 제한됩니다. 직원은 10회, 고객은 60회, 신규 고객 가입은 5회입니다. 이 횟수는 모든 서버가 공유합니다.
- 인증 코드는 6자리이며, 10분 후 만료되고 시도 횟수가 제한됩니다.
- 로그인과 주문하기에 Cloudflare 봇 차단을 켤 수 있습니다.
재사용할 수 없는 세션
로그인하면 수명이 짧은 액세스 토큰(기본값 15분)과 갱신 토큰이 발급됩니다. 갱신할 때마다 갱신 토큰이 새 토큰으로 교체됩니다. 이전 토큰이 다시 사용되면 세션 체인 전체가 종료되므로, 탈취된 토큰을 오래 사용할 수 없습니다.
각 요청은 세션이 아직 활성 상태인지도 확인하므로, 직원을 삭제하거나, 비밀번호를 변경하거나, 역할을 축소하면 모든 곳에서 즉시 로그아웃됩니다. 콘솔 쿠키는 페이지 스크립트가 읽을 수 없으며 다른 사이트에서 전송되지 않습니다.
최소 권한 역할
접근 권한은 주문 조회부터 현금 확인, 직원 관리까지 29가지 권한으로 구성됩니다. 소유자는 이 권한을 자유롭게 조합해 역할을 만들 수 있으며, 직원을 하나의 지점으로 제한할 수 있습니다. 누구도 자신이 가지지 않은 권한을 부여할 수 없고, 기본 제공 역할은 수정할 수 없으며, 마지막 활성 소유자는 삭제할 수 없습니다.
콘솔은 역할이 사용할 수 없는 기능을 숨기지만, 이는 화면을 명확하게 하기 위한 것일 뿐입니다. 서버는 모든 작업에서 권한, 지점, 소속을 확인합니다.
다시 쓸 수 없는 기록
주문 상태 변경, 포인트 원장, 재고 이동, 가격 이력, 감사 로그는 추가만 가능합니다. 데이터베이스가 모든 수정과 삭제를 거부하므로, 정정은 눈에 보이는 새 항목을 추가하는 방식으로 이루어집니다.
고객 데이터 존중
- 주문 위치는 앱이 열려 있는 동안 동의를 받은 경우에만 수집되며, 180일 후 삭제됩니다.
- 고객은 웹사이트나 앱에서 계정을 삭제할 수 있습니다. 주소, 위치, 기기, 알림, 비밀번호가 삭제되고 프로필은 익명화됩니다.
- 같은 사람이 신규 고객 혜택을 다시 받는 것을 막기 위해, 전화번호와 이메일은 보호된 지문 형태로만 보관됩니다.