feat/email-ingest-inbox #18
Open
hyungi
wants to merge 4 commits from
feat/email-ingest-inbox into main
pull from: feat/email-ingest-inbox
merge into: hyungi:main
hyungi:main
hyungi:feat/board-two-node
hyungi:feat/two-node-endpoints
hyungi:feat/presegment-pr2
hyungi:feat/theory-study
hyungi:feat/ds-clients-sync
hyungi:fix/stability-review-2026-06-29
hyungi:refactor/ask-orchestrator
hyungi:fix/ds-review-bugs
hyungi:fix/migration-validator-inline-comment
hyungi:chore/dead-code-cleanup
hyungi:refactor/aiclient-gate
hyungi:fix/aiclient-sampling
hyungi:feat/presegment-llm
hyungi:feat/presegment
hyungi:feat/mineru-extraction
hyungi:chore/phase2a-code-teardown
hyungi:chore/remove-ai-gateway
hyungi:fix/section-view-image-flash
hyungi:fix/section-view-md-render-d8
hyungi:feat/asme-item-decomp-d1
hyungi:feat/backend-audit-r3
hyungi:feat/section-view-md-render
hyungi:feat/md-image-prerender
hyungi:feat/auto-review-pending
hyungi:feat/ds-app-macos-finish
hyungi:feat/memo-to-document
hyungi:fix/md-render-katex-tldr
hyungi:feat/background-jobs-observability
hyungi:feat/safety-library-b3-p2
hyungi:feat/safety-library-b3
hyungi:feat/docpage-open-as-default
hyungi:feat/safety-library-a1
hyungi:feat/ds-docpage-d3
hyungi:feat/ds-board-merged
hyungi:feat/ds-board-engines
hyungi:feat/eid-chat
hyungi:feat/ds-processing-board
hyungi:feat/ds-macbook-offload
hyungi:feat/crawl-24x7-c
hyungi:feat/crawl-24x7-b
hyungi:feat/crawl-24x7-a
hyungi:fix/hwp-pyhwp-conversion
hyungi:feat/documents-outline-rail
hyungi:feat/outline-anchor
hyungi:feat/documents-viewer-unify
hyungi:fix/md-status-completed-compat
hyungi:fix/md-status-chip
hyungi:feat/email-pkm-folder
hyungi:feat/jwt-invalidation
hyungi:feat/phase2-backfill
hyungi:backup/rollout-orig-96d5778
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
41e99cb8e2 |
feat(frontend): show email source icon on memo card
- lucide-svelte Mail icon import 추가 - 배지 영역 조건에 source_channel === email 추가 - voice 배지 다음에 email 배지 분기 (sky 색조, title=email_subject) PR-2B/2C 의 기존 배지 영역 (voice / ai_event_kind / _last_promoted) 그대로. 사용자가 한 화면에서 텍스트/음성/이메일 메모를 source 시각 식별. plan: ~/.claude/plans/document-enchanted-candy.md |
||
|
|
52dd7129a3 |
feat(memos): include source_channel=email in memo inbox list
list 쿼리 확장: - 기존 source_channel IN (memo, voice) → OR (source_channel = email AND source_external_id IS NOT NULL) - mailplus_archive 의 INBOX root archive row (source_external_id=NULL) 는 자동 제외 - inbox_ingest 가 만든 email memo 만 /memos UI 에 노출 MemoResponse 확장: - source_external_id: Message-ID 또는 imap UID fallback - email_subject: email_metadata.subject (UI 부제/툴팁) _to_memo_response 가 email_metadata JSONB 에서 subject 추출. ingest 가 만든 row 가 UI 에 보이는 게 PR-2B 의 분류 배지/4 버튼/promote flow 자산 재사용의 전제. plan: ~/.claude/plans/document-enchanted-candy.md |
||
|
|
f4eef9e6e0 |
feat(email): IMAP ingest service for inbox@hyungi.net
신규 워커 app/workers/inbox_ingest.py (337줄):
- 5분 APScheduler cron (mailplus_archive 와 분리 — INBOX root archive vs DocumentServer/Ingest folder)
- UID SEARCH SINCE 14일 (UNSEEN 단독 의존 X, 사용자가 MailPlus UI 에서 먼저 읽어도 누락 회피)
- Message-ID 정규화 또는 imap:{folder}:{uidvalidity}:{uid} fallback → source_external_id always non-null
- ON CONFLICT DO NOTHING (DB unique 진실원장)
- 신규 row 만 BODY parse: snippet + HTML stripping + attachment metadata (binary 저장 X)
- enqueue_stage(doc.id, classify) 로 기존 classify pipeline 진입
- HC.io heartbeat (옵션, INBOX_INGEST_HC_URL)
- parse 실패 분기: row 생성 전 (logger.error + HC fail) / 후 (email_metadata.parse_error 기록)
env (credentials.env.example):
- INBOX_INGEST_ENABLED=false (기본 dormant, 사용자가 alias/folder 셋업 후 true)
- INBOX_INGEST_FOLDER=DocumentServer/Ingest
- INBOX_INGEST_DAYS=14
- INBOX_INGEST_HC_URL=
main.py:
- inbox_ingest_run import + scheduler.add_job interval 5m
email_ingest 정책 (사용자 라운드 2026-05-12):
- 직접 events row 생성 X
- 이메일은 universal inbox item, source_channel=email memo 로 저장
- classify_worker 가 ai_event_kind 채움 (별 PR 의 4B robustness fix 선결)
- 사용자 1-click promote 만이 events row 생성 path
plan: ~/.claude/plans/document-enchanted-candy.md
|
||
|
|
c49047bf2a |
feat(email): schema for email source_external_id + metadata
migrations 259~261: - documents.source_external_id TEXT NULL (email 에선 always non-null, ingest 책임) - documents.email_metadata JSONB NULL (from/to/cc/subject/folder/uidvalidity/uid/received_at/attachments) - partial unique on (source_external_id) WHERE source_channel = email AND source_external_id IS NOT NULL ORM: - Document.source_external_id / email_metadata mapped_column 추가 dedup 진실원장 = DB unique index. server-side IMAP \\Seen flag 는 best-effort. mailplus_archive 의 INBOX root archive row 는 source_external_id=NULL 이라 unique 에서 자연 제외. plan: ~/.claude/plans/document-enchanted-candy.md |