feat(docker): 12단계 계정 보안 — 엔진 웹훅 · /api/internal 닫기 · 요청 대상 400

메일 프로그램(IMAP · SMTP) 로그인 기록을 엔진 웹훅으로 받는다.
- 루트 env MAIL_WEBHOOK_SECRET(setup · backend 공용, 운영 필수)과 backend 의 APP_NETWORK_SUBNET
- setup 이 엔진 웹훅을 맞추고(표시 머리글 — 소금 + 키 지문) 서명한 빈 묶음으로 받는 곳을 확인한다
  키를 바꾼 실행 · 게이트웨이 OTP · 테스트 직원의 402 를 따로 다룬다
- nginx 두 server 가 /api/internal/ 을 닫고, 요청 대상의 날 \(경로) · # · 0x80 이상은 location 전에 400
  Express 가 이런 대상을 다시 읽어 닫은 경로(/api/internal · /api/health)가 백엔드에서 열렸다(2026-10-31 리뷰)
- CI "닫는 경로 시험"(두 server × 세 경로의 변형) · 지시어만 세는 정적 검사
- mail/README: 웹훅 · 12단계 전부터 운영 중인 서버를 올리는 차례 · 휴대폰을 잃은 직원(관리 API 명령)
엔진 DNS 가 Custom(운영)이어도 웹훅은 backend 를 푼다 — 메일 컨테이너가 도커 DNS 를 쓴다(개발에서 확인).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 17:45:23 +09:00
parent c31442e639
commit d1ef0da488
11 changed files with 739 additions and 19 deletions
+6
View File
@@ -123,6 +123,12 @@ services:
# 사내 목록 계정 아이디 — mail setup 이 만든 비밀번호 없는 계정(<이 값>@MAIL_DOMAIN). 백엔드가 게이트웨이 대리 접근으로
# 엔진의 계정 목록(JMAP Principal)에서 직원 이름·주소만 읽는다 (docs/mail/api-contract.md 3절 "사내 목록" · mail/README.md)
- MAIL_DIRECTORY_LOCAL_PART=${MAIL_DIRECTORY_LOCAL_PART:-mail-directory}
# 엔진 웹훅(12단계 — 메일 프로그램 로그인 기록)의 서명 키 — 엔진이 보내는 묶음(POST /api/internal/mail-engine-events)의 HMAC-SHA256(X-Signature)을 이 값으로 본다.
# mail setup 이 같은 값으로 엔진 웹훅을 만든다. 운영 필수(shared/config/env.validation.ts). 바꾸면 setup 을 다시 실행하고 backend 를 다시 띄운다
# (docs/mail/api-contract.md 5절 "엔진 웹훅 받기" · mail/README.md "엔진 웹훅")
- MAIL_WEBHOOK_SECRET=${MAIL_WEBHOOK_SECRET:-}
# 앱 네트워크 대역 — 웹훅 받는 쪽이 접속 주소(소켓 — X-Forwarded-For 가 아니다)가 이 대역인지 본다. 아래 networks 의 app-network 서브넷과 같은 값이어야 한다
- APP_NETWORK_SUBNET=${APP_NETWORK_SUBNET:-172.16.71.0/24}
# 첨부 1개 최대 크기(MB). 앞단 리버스 프록시의 요청 본문 한도는 이보다 커야 한다
# (작으면 프록시가 먼저 413 을 내고 사용자에게는 FILE_002 로 보인다 — .claude/skills/docker/SKILL.md)
- MAIL_ATTACHMENT_MAX_SIZE_MB=${MAIL_ATTACHMENT_MAX_SIZE_MB:-20}