Commit Graph

54 Commits

Author SHA1 Message Date
ttipo 468a4377ee feat(frontend): 전역 셸·로그인·세션 처리와 웹메일 화면
확정된 디자인(docs/design/webmail)을 기준으로 만든 웹메일 화면이다.

- 앞으로 붙일 사내 모듈(캘린더·파일·ERP 등)을 위한 전역 앱 레일과 셸,
  Pretendard 자체 호스팅, 바다 청록 브랜드 토큰과 콘텐츠 열 토큰
- 로그인과 세션 처리: 401 이면 한 번 갱신한 뒤 다시 보내고, 실패하면 세션 만료 대화상자를 띄운다.
  로그아웃은 다른 탭에도 알리고, 로그아웃 뒤에 늦게 온 갱신 결과는 버린다
- 메일함(분할·목록 보기), 읽기(외부 HTML 은 sandbox iframe 으로만 그린다),
  쓰기(발송 키 규칙, 첨부 형식·크기·합계·개수 사전 검사, 답장·전달 초안 길이 맞춤)
- 오류는 코드로만 분기하고, 문구는 생성된 에러 사전에서 가져온다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 01:31:59 +09:00
ttipo 71f2e01d83 feat(backend): 직원 인증(쿠키 JWT·DB 세션)과 웹메일 API(Stalwart JMAP 중계)
첫 사내 모듈인 웹메일의 백엔드다. 메일 엔진은 외부(Stalwart)에 두고 백엔드가 JMAP 으로 중계한다.

- 직원 로그인 = 메일 계정: 엔진으로 비밀번호를 확인한 뒤 HttpOnly 쿠키 JWT 를 발급한다.
  리프레시 세션은 DB 에 해시로 저장하고 1회용으로 회전한다 (이미 쓴 토큰이 오면 세션 폐기)
- 로그인 실패 한도는 엔진에 묻기 전에 원자적으로 차지하고, IPv6 는 /64 로 묶어 센다
- 상태를 바꾸는 요청은 출처(Sec-Fetch-Site·Origin)를 검사하고, 클라이언트 IP 는 TRUST_PROXY 로만 해석한다
- 메일함·목록·읽기·발송·첨부 API: 받은 HTML 은 정화해서 내보내고, 발송은 Idempotency-Key 로 중복을 막는다
- 메일 엔진 관리자 계정은 로그인·대리 접근 대상에서 막는다 (게이트웨이가 관리자까지 대리할 수 있다)
- 에러 코드 AUTH_004·MAIL_001~006 을 추가하고 클라이언트 에러 사전을 다시 생성했다

계약: docs/mail/api-contract.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 01:31:38 +09:00
ttipo 238d0ba838 chore(docker): 메일 엔진·네트워크 분리·같은 주소 배포와 Node 24 고정
웹메일 1단계를 개발 환경에서 띄우고 운영에 올리기 위한 인프라 구성이다.

- 메일 엔진 Stalwart(v0.16.27)와 개발용 Mailpit 을 compose profile `mail` 로 추가한다.
  초기 설정은 mail/scripts/setup.mjs 가 맡는다 — 여러 번 실행해도 안전하고,
  운영에서는 사전 검사가 실패하면 아무것도 바꾸지 않고 멈춘다
- 화면과 API 를 한 주소로 배포한다: 프론트 nginx 가 /api 를 백엔드로 넘기고,
  본문 한도·시간 제한·헤더 전달을 env 와 맞춘다. nginx 가 직접 내는 오류도 표준 실패 형식이다
- 인터넷을 향한 nginx 는 edge 네트워크로 백엔드에만 닿고, DB·메일 엔진은 app-network 에 둔다
  (메일 엔진의 신뢰 대역도 app-network 뿐)
- Node 24.22.1·npm 11.6.2·nginx 1.30.6 을 Dockerfile 과 CI 에 한 값으로 고정한다
- 개발 호스트 포트는 127.0.0.1 로 한정하고, data/ 는 클론 때부터 사용자 소유가 되게 .gitkeep 을 추적한다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 01:31:21 +09:00
ttipo 18f10cece4 Initial commit 2026-10-26 12:28:48 +09:00