feat(mail): capture and surface IMAP \Seen read state (unread) - #946
Conversation
The mail experience had no read/unread signal: ingestion fetched only "(RFC822)" and discarded IMAP flags, the Email model had no read field, and the API/UI could not show unread mail — so mockup_19's unread indicator was unbacked. This is the first backed slice toward the mail folder/label/LNB the design specifies. - Email.is_read column (default read; migration 0011 server_default true so existing/file-imported mail is not surfaced as unread). - imap_worker fetches "(RFC822 FLAGS)" and threads the \Seen flag through to process_fetched_email via flags_indicate_seen() — a pure, unit-tested parser that defaults to unread on a parse miss (never silently marks mail read). - /api/emails EmailListItem exposes is_read (coalescing unflushed None -> read). - EmailList renders an '안 읽음' badge from is_read === false. Verified: backend 53 passed (emails + imap + threading + pop3), new flags_indicate_seen unit test, frontend EmailList 5 passed, tsc + eslint clean, migration parses and chains from 0009. Follow-ups (same defect, design-backed): multi-folder ingestion (select beyond INBOX) + folder column, labels, then the left folder-LNB per mockup_19. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RkKdtHRLG4wSLh6PVsp8J
OpenCode Review Overview
Pull request overviewOpenCode reviewed the current-head bounded evidence and found no blocking issues. FindingsNo blocking findings. SummaryApproval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (5 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (5 files)"]
R1 --> V1["backend tests"]
Evidence --> S2["Frontend (2 files)"]
S2 --> I2["browser runtime and bundle"]
I2 --> R2["Review risk: Frontend (2 files)"]
R2 --> V2["frontend tests"]
|
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found no blocking issues.
Findings
No blocking findings.
Summary
Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including backend/alembic/versions/0011_email_read_state.py, backend/api/emails.py, backend/db/models.py, backend/services/imap_worker.py, backend/tests/test_imap_worker.py, and 2 more.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects backend/alembic/versions/0011_email_read_state.py to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source checks are delegated to configured OpenCode web_search/Context7/DeepWiki sources when applicable; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: Playwright visual, DOM locator, ARIA snapshot, console, and responsive evidence were checked when a web UI surface was present; for non-web surfaces, API/CLI/log/docs/workflow interaction evidence was reviewed instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.
- Result: APPROVE
- Reason: PR adds IMAP read state tracking with comprehensive backend and frontend changes, tests pass
- Head SHA:
69097f94e9fb74f017ffe260ad0fbde8957d16b2 - Workflow run: 29151620257
- Workflow attempt: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (5 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (5 files)"]
R1 --> V1["backend tests"]
Evidence --> S2["Frontend (2 files)"]
S2 --> I2["browser runtime and bundle"]
I2 --> R2["Review risk: Frontend (2 files)"]
R2 --> V2["frontend tests"]
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found no blocking issues.
Findings
No blocking findings.
Summary
Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including backend/alembic/versions/0011_email_read_state.py, backend/api/emails.py, backend/db/models.py, backend/services/imap_worker.py, backend/tests/test_imap_worker.py, and 2 more.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects backend/alembic/versions/0011_email_read_state.py to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source checks are delegated to configured OpenCode web_search/Context7/DeepWiki sources when applicable; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: Playwright visual, DOM locator, ARIA snapshot, console, and responsive evidence were checked when a web UI surface was present; for non-web surfaces, API/CLI/log/docs/workflow interaction evidence was reviewed instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.
- Result: APPROVE
- Reason: No blocking issues found in the current-head evidence.
- Head SHA:
4b721d38d2f95d1dd1530a88535bf294ee590527 - Workflow run: 29165683384
- Workflow attempt: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (5 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (5 files)"]
R1 --> V1["backend tests"]
Evidence --> S2["Frontend (2 files)"]
S2 --> I2["browser runtime and bundle"]
I2 --> R2["Review risk: Frontend (2 files)"]
R2 --> V2["frontend tests"]
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found no blocking issues.
Findings
No blocking findings.
Summary
Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including backend/alembic/versions/0011_email_read_state.py, backend/api/emails.py, backend/db/models.py, backend/services/imap_worker.py, backend/tests/test_imap_worker.py, and 2 more.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects backend/alembic/versions/0011_email_read_state.py to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source checks are delegated to configured OpenCode web_search/Context7/DeepWiki sources when applicable; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: Playwright visual, DOM locator, ARIA snapshot, console, and responsive evidence were checked when a web UI surface was present; for non-web surfaces, API/CLI/log/docs/workflow interaction evidence was reviewed instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.
- Result: APPROVE
- Reason: No blocking issues found in the current-head bounded evidence.
- Head SHA:
cb826b6a23b5667a7344ef9163b2f9e8f18572e6 - Workflow run: 29168431995
- Workflow attempt: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (5 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (5 files)"]
R1 --> V1["backend tests"]
Evidence --> S2["Frontend (2 files)"]
S2 --> I2["browser runtime and bundle"]
I2 --> R2["Review risk: Frontend (2 files)"]
R2 --> V2["frontend tests"]
Why
The mail experience had no read/unread signal: ingestion fetched only
(RFC822)and discarded IMAP flags,Emailhad no read field, and the API/UI couldn't show unread mail — somockup_19's unread indicator was unbacked. Per the reframe that this missing capability is itself a defect (not a reason to defer the mail LNB), this is the first backed slice toward the design's mail folder/label/LNB.What
Email.is_readcolumn (defaults read; migration0011server_default trueso existing/file-imported mail isn't surfaced as unread).imap_workernow fetches(RFC822 FLAGS)and threads the\Seenflag throughprocess_fetched_emailviaflags_indicate_seen()— a pure, unit-tested parser that defaults to unread on a parse miss (never silently marks mail read)./api/emailsEmailListItemexposesis_read(coalescing unflushedNone→ read).EmailListrenders an '안 읽음' badge fromis_read === false.Verification (local)
flags_indicate_seenunit test.EmailList.test.tsx5 passed;tsc+eslintclean.0009.Follow-ups (same defect, design-backed)
Multi-folder ingestion (
selectbeyond INBOX) +foldercolumn → labels → the left folder-LNB permockup_19.🤖 Generated with Claude Code