Commit Graph

13 Commits

Author SHA1 Message Date
ttipo c5cc1a6705 docs: 11단계 대용량 첨부 — 계약 4절 · 디자인 보드 다섯 · README
일반 첨부 한도를 넘는 파일을 로그인 없이 받는 링크로 보내는 기능의 계약과 화면 원본이다.
계약 4절은 2026-10-30 확정한 한도(파일 2GB · 메일 10개 · 직원 10GB · 30일)와 조각 올리기 ·
악성 검사(ClamAV 실측 판정) · 공개 호스트 분리 · 받기 동시 연결 상한 · 운영 확인을 담는다.
리뷰에서 바꾼 것(경로 대소문자 · 공개 호스트 경로 해석 · 판정 대기 30분 + 1MB 마다 1초 ·
전체 상한을 공개 400 · 앱 안 200 으로 나눔)과 알려진 한계도 함께 적었다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:35:25 +09:00
ttipo fa6799d9f7 docs: 9단계(보내기 취소 · 예약 발송 · 외부 이미지 · 인쇄 · 보낸 사람 차단) 계약과 디자인
보내기 취소 · 예약 발송(엔진이 제출을 붙잡는다 — FUTURERELEASE), 외부 이미지 중계, 인쇄, 보낸 사람 차단, 보내기 · 읽기 설정의 계약(2절)을 정하고,
확정한 캔버스 보드 넷(MailReadTools · MailPrint · MailSendLater · SettingsSendRead)을 둔다. 디자인 README 에 구현하며 정한 보완을 적었다.
리뷰(화면 한 번 · 서버 두 번)로 정한 것도 함께 적었다 — 붙잡힌 메일은 취소로만 보낸편지함을 떠난다(MAIL_015 — 모든 옮기기 · 지우기 길, 확인하지 못하면 닫힌 쪽),
발송은 늘 envelope 을 직접 준다(엔진이 받지 않는 주소를 not-found 로 빼고 다시 제출 — 전에는 말없이 빠졌다), 다시 취소해도 200,
이미지 중계의 동시 수(서버 16 · 직원 6 — 받는 수가 적은 직원부터), 차단 주소는 dot-atom 만 · 다시 POST 하면 꺼진 규칙을 켠다.
엔진 사실(2026-10-29): envelope 의 거절은 제출 전체 · 첫 주소 하나, 내보내는 사본에서 Bcc 를 뗀다(개발의 Mailpit 이 보이는 Bcc 줄은 Mailpit 이 붙인다), 제출 조회의 정렬 이름은 sentAt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:07:45 +09:00
ttipo 7615329c32 docs: 8단계(주소록) 계약과 디자인
주소록(내 연락처 · 그룹 · 사내 목록)과 메일 연동의 계약(3절)을 정하고, 확정한 캔버스 보드 셋(Contacts · ContactsEdit · ContactsMail)을 둔다.
리뷰(서버 · 화면)로 정한 것도 함께 적었다 — 되돌리기는 서버가 원본을 5분 기억했다가 그대로 다시 만들고,
고치기는 PATCH(바꾼 칸만 · 칸 안의 남의 속성을 지킨다), 받는 사람 추천의 q 는 쓰기 화면과 같은 맞추기,
주소록 크기 한도 800만(캐시가 통째로 기억할 수 있게), excludeGroupId · 사내 항목 하나 · q 254자, 쓰기 화면 채우기는 연 직원에게 묶는다.
엔진이 한 요청의 destroy 에 같은 id 가 두 번 있으면 통째로 serverUnavailable 로 거절하는 것도 적었다(2026-10-29 확인).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 14:05:36 +09:00
ttipo 5ddc849c11 docs: 7단계(이미 받은 메일에 필터 적용) 계약과 디자인
필터를 저장할 때 받은편지함에 이미 있는 메일에도 그 필터 하나를 적용한다. 엔진의 Sieve 는 받을 때만
돌고 엔진 검색은 낱말 단위라, 서버가 받은편지함을 읽어 Sieve 와 같은 규칙으로 판정한다.

- 계약 2절 "이미 받은 메일에 적용"(POST /api/mail-filter-runs): 판정 규칙은 실엔진 배달로 맞췄다 —
  HTML 은 닫는 p · br 만 줄바꿈, style · script · head · template 은 글째 빼고, 속성이 붙은 태그는
  엔진처럼 알아보지 않는다. 머리글은 접힌 줄을 띄어쓰기 하나로, 인코딩된 글은 홀로 선 것만 푼다
- 시작한 때 받은편지함에 있던 메일만 보고(위 경계), 마지막으로 남긴 메일이 빠지면 그 초부터 다시 읽는다.
  본문 값은 한 통 1MiB 까지 — 바깥 메일 한 통으로 서버가 메모리를 크게 쓰지 않게
- 부재중 응답에 isActive(엔진에서 우리 규칙이 꺼졌는지), 엔진의 임시 업로드 한도, 바깥 주소 자동 전달은
  허용하지 않는다는 정책(2026-10-29 결정)
- 디자인 캔버스 확정본 MailFilterApply · MailFilterApplyStates 와 README "7단계"(구현하며 정한 보완 포함)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:03:42 +09:00
ttipo 41b5fdbe22 docs: 6단계(메일 필터) 계약과 디자인 · JSON 본문 모양 한도
메일 필터(GET·PUT /api/mail-filters)와, 부재중 자동 응답의 저장 자리를 엔진의 Sieve
스크립트 하나로 옮기는 계약을 적는다. 확정한 캔버스 보드(SettingsFilter · MailFilterStates)와
구현하며 정한 보완도 함께 둔다.

- 엔진(Stalwart 0.16.27)은 계정마다 켜진 스크립트가 하나뿐이다. 엔진의 부재중도 스크립트라
  따로 두면 하나를 켤 때 다른 하나가 꺼진다. 그래서 한 스크립트에 함께 둔다
- 스팸 막기는 엔진의 분류 표시(X-Spam-Score)로 한다. spamtest 는 점수를 정수로 내린 값이라
  10 으로 막으면 5~10점 스팸을 놓친다(실엔진에서 확인)
- 모든 JSON 본문에 모양 한도(배열 1,000 · 값 10,000 · 깊이 32)를 걸고 UTF-8 만 받는다.
  DTO 의 개수 한도로는 본문 검증 DoS 를 막지 못했다(리뷰 측정)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:58:51 +09:00
ttipo ac418e3aa9 docs: 발송의 받는 사람별 결과 · 부재중 길이 한도 (6단계 앞 수정)
- 계약 2절 "받는 사람별 결과" — 엔진이 제출 때 거절한 받는 사람(deliveryStatus)을 201 의 rejectedRecipients 로 알리고,
  모두 거절이면 보내지 않은 것으로 다룬다(보낸 사본을 지우고 MAIL_010 · MAIL_011). 같은 키 재시도 · 분류 규칙 · 알려진 한계 · 로그
- 부재중 자동 응답 — 켤 때 제목 150 · 내용 600. 엔진이 UTF-8 511 · 2,047바이트로 막아 4단계의 200 · 4,000 은 한글로 저장되지 않았다.
  꺼 둔 채로는 4단계 한도까지 받는다(켜진 옛 긴 글도 끌 수 있게)
- 엔진의 받는 쪽 한도는 로그인한 직원의 발송에 걸지 않는다(mail setup)
- 디자인 README — 일부 거절 알림 · MAIL_010 안내 띠 · 부재중 길이

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:11:13 +09:00
ttipo e27e9feb0b docs: 5단계(실시간 새 메일 · 바탕화면 알림) 계약과 디자인
- 계약 2절 "실시간 알림": GET /api/mail-events(SSE) — state(+inboxUnread) · new-mail · ping(upstream) · end 이벤트,
  직원마다 엔진 연결 하나 · 연결 5개 · 25초 ping · 토큰 만료 30초 전 end, 새 메일 판단(10분 넘게 앞선 메일 제외) · 5분 안전판,
  클라이언트 규칙(브라우저마다 연결 하나 · fetch 로 읽기 · 다시 잇기 · 1분 확인과의 관계 · 바탕화면 알림 조건)
- 엔진 확인 사실(Stalwart 0.16.27): EventSource 는 대리 접근으로 열린다, ping 은 30초보다 짧지 않다, EmailDelivery 는 초안에도 바뀐다,
  스트림은 동시 요청 한도에 들지 않는다, 해석 못 하는 sinceState 는 400 notRequest
- 디자인 캔버스 5단계 보드(SettingsNotify · MailRealtime)와 README "5단계" · "5단계 구현하며 정한 보완"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:31:38 +09:00
ttipo cbfccaa499 docs: 4단계(계정 · 메일 설정) 계약과 디자인
- 계약 1절: PUT /api/auth/password — 지금 비밀번호 틀림은 400 AUTH_005(401 이면 클라이언트가 갱신 · 재시도한다),
  로그인과 같은 실패 한도, 바뀌면 이 세션만 남기고 다른 로그인을 끊는다(결과를 모를 때도)
- 계약 2절: 메일함 관리(만들기 · 이름 바꾸기 · 지우기 · 모두 읽음 · 비우기 — 500통씩 · 한 요청 25초, 같은 메일함은 하나씩),
  부재중 자동 응답(JMAP VacationResponse), 스팸 표시(isJunk) · 원문(.eml)
- 디자인 캔버스 4단계 보드(SettingsAccount · SettingsVacation · MailboxManage · MailActions4)와 README "4단계" · "4단계 구현하며 정한 보완"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 03:41:45 +09:00
ttipo 7585b3bfac docs: 3단계(새 메일·검색·여러 통 처리) 계약과 디자인
캔버스 버전 21 로 확정한 3단계 화면(Search · BulkSelect · ListStates)과 계약 2절의 새 절(새 메일 확인 · 검색 · 여러 통 한꺼번에).
개발 엔진(Stalwart 0.16.27)에서 직접 확인한 검색 한계 — 낱말이 통째로 같을 때만 맞고 제목 맨 앞 말머리는 색인 밖이다 — 와
그 보완(조사 붙인 형태를 함께 찾기), 휴지통 전용 영구 삭제의 조건(ifInState)을 함께 적었다.
웹 화면은 DELETE /api/messages/{id} 를 쓰지 않는다 — 다른 창이 휴지통에 넣은 메일을 확인 없이 영구 삭제하지 않게.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:56:09 +09:00
ttipo 1868665592 docs: 2단계(임시 저장·서명·받는 사람 추천) 계약과 디자인
캔버스 19 에서 확정한 2단계 화면(Settings · ComposeAssist)을 저장소에 두고,
계약 2절에 임시 저장 · 서명 · 받는 사람 추천 절과 서식 본문의 서명 그림 예외를 더한다.

구현과 리뷰에서 정한 것도 함께 적는다:
- 엔진의 destroy 는 되돌릴 수 없어, 사용자 메일을 지우는 경로는 확인한 상태 그대로일 때만(ifInState) 지운다
- 본문에 그림으로 보인 부분은 첨부 목록·클립에서 뺀다(isInline · hasAttachment) — 서명 그림이 매번 첨부로 보이지 않게
- 서명 그림 한도(서명 3장 · 보관 10장 · 300KB · 4096px), 사내 추천은 최근 90일 로그인
- 저장하지 않는 경우(찾지 못한 첨부 · 본문 한도 초과)와 남의 저장본 원본 보존, 알려진 한계

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 19:21:52 +09:00
ttipo 0282b6b7bd docs: 본문 길이 초과 코드·본문 잘림 표시·나가기 확인 계약과 디자인
- 계약 2절: MAIL_007 과 그 경우들, MessageDetail 의 isHtmlBodyOmitted·isBodyTruncated, 보여 줄 본문 규칙,
  보내는 서식 본문의 보이지 않는 서식 하한(8px·알파 0.3 — 바탕과 같은 색은 막지 않는다)
- 디자인: 나가기 전 확인(문구·단추·묻지 않는 경우·보내는 중·알려진 한계), 읽기 화면 본문 안내,
  내 메일 답장의 받는 사람, 인용할 원문 고르기, 본문 길이 띠의 MAIL_007 문구

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 13:00:09 +09:00
ttipo d807cb4441 docs: 서식 본문 계약과 메일 쓰기 편집기 디자인
- 계약 2절: 서식 본문(bodyHtml)의 허용 목록·값 형식·한도(VAL_001)·지문, 읽기 한도와 정화 전 검사(htmlBody null),
  답장·전달 초안 길이 맞춤, 발송 JSON 4MB, 서식 본문 지문의 알려진 한계
- 디자인: 쓰기 화면 입력칸 포커스 규칙, 편집기 툴바·메뉴·단축키·좁은 폭 순서·팔레트, 원문 인용, 본문 이미지 → 첨부
  (캔버스 Compose·ComposeEditor 보드와 구현하며 정한 것)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 07:49:40 +09:00
ttipo a5afbc040e docs(design): 웹메일 디자인 원본과 브랜드 로고 추가
사용자가 확정한 디자인 캔버스(버전 11)의 원본이다. 화면 구현의 기준으로 쓴다.

- 로그인·메일함(분할·목록 보기)·읽기·쓰기·상태 화면의 캔버스 원본과 자산 대응표
- 디자인 원칙(뱃지 없음·높은 밀도·콘텐츠 열 규칙·밀도 예외)과 구현하며 정한 보완
- 흰 로고 원본 (어두운 브랜드 바탕 전용)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 01:32:09 +09:00