2025-11-13 - 2026-11-13
Overview
142 Pull requests merged by 1 user
Merged
#431 feat(contacts): drive contacts sync from stored CardDAV accounts
Merged
#430 fix(dav): parse multistatus with namespaces, not substrings
Merged
#429 fix(store): survive one corrupt body on bulk read paths
Merged
#428 fix(cal): refuse phrases the scheduler cannot resolve exactly
Merged
#427 refactor(cli): drop the runner's dead ephemeral store
Merged
#425 fix: fail honestly on unreadable TLS modes and mis-sized mail
Merged
#424 fix(daemon): bound nunciod's own keyring reads
Merged
#423 fix(test): close the store pool before salvaging its database
Merged
#420 fix(cli): let the CLI take its gRPC token from the environment
Merged
#418 perf(grpc): batch ListMessages placements; fix JMAP parse folder
Merged
#417 feat(mail): mutation RPCs, typed conflicts, and the placement set
Merged
#416 feat(imap): key messages by their server object id
Merged
#415 docs: chart the shortest route to a hand-drivable daemon
Merged
#414 feat(jmap): enumerate changes so deleted mail stops haunting the store
Merged
#413 chore: placement model follow-ups (reap on repoint, claim lifetime, sync naming)
Merged
#399 fix(filter): make filter execution single-owner per account, default off
Merged
#385 docs(adr): record the convergent multi-engine sync model
Merged
#398 feat(mail): capture Message-ID and a content hash at ingest
Merged
#405 feat(store): split message identity from mailbox placements
Merged
#403 feat(mail): report what a mutation proved, not that it was accepted
Merged
#400 feat(store): gate the identity schema and tag sync tokens with their scheme
Merged
#402 feat(sync): enumerate IMAP changes over a four-rung capability ladder
Merged
#401 feat(mail): add a raw IMAP layer for ENABLE, tagged codes, and VANISHED
Merged
#384 test(mail): stateful IMAP mock harness + fix a flaky webhook capture test
Merged
#411 fix(test): install one global capture subscriber; delete schema migrations
Merged
#378 feat(core): redaction policy, Redacted<T>, and no-secrets-in-logs canary
Merged
#377 feat(cli): wire verbosity flags and render typed daemon errors
Merged
#376 feat(proto): real GetStatus health/readiness surface
Merged
#374 feat(mail): instrument protocol syncs and log destructive IMAP ops
Merged
#373 fix(cal): surface dropped VEVENTs; instrument DAV syncs + store lifecycle; redact DAV config Debug
Merged
#372 feat(nunciod): domain + lifecycle log coverage (OBS-3)
Merged
#371 feat(nunciod): per-RPC tracing span with request-id correlation and auth logging
Merged
#369 fix(filter): surface rule-eval timeouts and instrument engine + webhook egress
Merged
#367 refactor(proto): model account transport as a oneof
Merged
#368 feat(nunciod): layered tracing subscriber with EnvFilter, rotating file, and JSON
Merged
#366 feat(nunciod): bounded-concurrency sync dispatcher with per-account timeout
Merged
#356 feat(proto): enum hygiene for rule export format and account TLS
Merged
#355 feat(nunciod): bound gRPC server concurrency/streams/timeout/message size
Merged
#354 feat(store): implement contact search over contacts_fts
Merged
#353 feat(proto): enforce id-naming law and return full config from AddAccount
Merged
#352 feat(mail): bound IMAP fetch by batch count and per-message size
Merged
#350 feat(proto): keyset pagination for all list/search RPCs (AIP-158)
Merged
#349 feat(nunciod): bound outbox per-item execution with a timeout
Merged
#348 feat(proto): unify time fields on Timestamp/Duration
Merged
#346 feat(nunciod): single-instance advisory lock on the DB path
Merged
#345 feat(cal): add CalendarEvent::to_ical serializer
Merged
#344 refactor(core): remove dead EventBus ReloadFilters/unread_count arms
Merged
#343 fix(filter): pin webhook dispatch to the checked IP to close DNS-rebind TOCTOU
Merged
#342 feat(proto): typed errors (ErrorInfo/ErrorReason) via Status details
Merged
#341 perf(sync): batch new-message detection to remove the is_new_message N+1
Merged
#337 fix(store): deterministic message surrogate identity (C1)
Merged
#340 feat(nunciod): graceful shutdown with WAL-checkpointing close
Merged
#335 fix(core): reject cleartext Plain TLS to non-loopback hosts
Merged
#336 fix(cli): render clean error messages instead of raw tonic::Status
Merged
#272 feat: production-wire Calendar sync via first-class CalDAV accounts
Merged
#270 fix(store): preserve audit tables and real TLS modes during salvage
Merged
#269 fix(store): surface unparseable filter rules instead of dropping them
Merged
#268 fix(store): fail export when its WORM audit write fails
Merged
#267 fix(filter): use unique rule ids to prevent silent overwrite
Merged
#266 fix(store): make WORM/ledger appends atomic
Merged
#264 fix(store): fail closed on decrypt failure in decrypt_text_at_rest
Merged
#263 feat: build the outbox remote-mutation executor (filters made live)
Merged
#241 deps(cargo): bump rustls from 0.23.42 to 0.23.43
Merged
#262 refactor(mail): remove fake/dead protocol code
Merged
#261 refactor(core): remove fabricated e2ee/ai/plugin modules
Merged
#243 fix(filter): enforce real IP/CIDR SSRF checks on webhook targets
Merged
#242 M6: Fail closed on missing/unfetchable SHA256SUMS in the auto-updater
Merged
#240 M6: Reject non-loopback gRPC bind addresses; consolidated auth-coverage canary
Merged
#239 fix(store): validate WORM/ledger key length from the vault
Merged
#238 feat(security): zeroize long-lived engine key material on drop
Merged
#236 fix(store): fail closed on encryption failure in save_email
Merged
#235 Promote to main: M5 (Mail lifecycle + incremental sync)
Merged
#234 docs: mark M5 complete, set M6 as next
Merged
#232 feat(mail): select an explicit account for SendMessage
Merged
#231 feat(sync): incremental IMAP sync with progress + per-item FETCH timeout
Merged
#230 M5: Account lifecycle over gRPC (edit/delete/test) + persist TLS mode
Merged
#229 fix(accounts): roll back orphaned keyring secret on add_account failure
Merged
#228 Promote to main: M3 (JMAP) + M4 (Filters made live)
Merged
#227 docs: mark M1-M4 complete, set M5 as next milestone
Merged
#226 feat(filter): add streaming Filters.Triage RPC for retroactive rescan
Merged
#224 feat(filter): move edit/export/import/logs onto Filters gRPC service
Merged
#223 fix(filter): correct account-field evaluation and reject header conditions
Merged
#222 M4: Wire FilterEngine into live sync so matched rules actually fire
Merged
#221 feat(mail): wire a real JMAP client into the mail sync path
Merged
#220 Promote dev -> main: M1 Calendar + M2 Contacts verticals
Merged
#218 feat(contacts): add Contacts gRPC vertical (proto, daemon, CLI, E2E)
Merged
#217 feat(contacts): build a real CardDAV engine, replacing the fabricated client
Merged
#215 M1: Wire RRULE recurrence expansion into calendar event queries
Merged
#214 feat(calendar): add Calendar gRPC vertical (proto, daemon, CLI, E2E)
Merged
#213 chore: sync rc to reconstructed dev (engine + CI + rc gating)
Merged
#210 deps(cargo): bump icalendar from 0.15.8 to 0.17.13
Merged
#212 fix(build): remove broken cargo verify alias; ci: gate rc branch
Merged
#211 Promote dev → main: green CI + workflow/security cleanup
Merged
#166 Promote rebuilt engine-first foundation (dev -> main)
Merged
#123 deps(cargo): bump zip from 4.6.1 to 8.6.0
Merged
#121 build(deps): bump hmac from 0.12.1 to 0.13.0
Merged
#120 deps(npm): bump @types/react from 18.3.31 to 19.2.17 in /crates/nuncio-gui/ui
Merged
#119 deps(npm): bump react from 18.3.1 to 19.2.8 in /crates/nuncio-gui/ui
Merged
#116 deps(npm): bump @vitejs/plugin-react from 4.7.0 to 6.0.4 in /crates/nuncio-gui/ui
Merged
#115 build(deps): bump quick-xml from 0.36.2 to 0.41.0
Merged
#114 build(deps): bump async-imap from 0.9.7 to 0.11.3
Merged
#83 build(deps): bump actions/checkout from 4 to 7
Merged
#84 build(deps): bump softprops/action-gh-release from 2 to 3
Merged
#85 build(deps): bump actions/setup-node from 4 to 7
Merged
#86 build(deps): bump tauri-apps/tauri-action from 0 to 1
Merged
#87 build(deps): bump sha2 from 0.10.9 to 0.11.0
Merged
#88 build(deps): bump rustls-pki-types from 1.15.0 to 1.15.1
Merged
#90 build(deps): bump age from 0.10.1 to 0.12.1
Merged
#91 build(deps-dev): bump vite from 5.4.21 to 8.1.5 in /crates/nuncio-gui/ui in the npm_and_yarn group across 1 directory
Merged
#92 build(deps): bump webpki-roots from 0.26.11 to 1.0.9
Merged
#93 build(deps): bump zip from 2.4.2 to 4.6.1
Merged
#94 build(deps): bump chrono-tz from 0.9.0 to 0.10.4
Merged
#95 build(deps): bump html2text from 0.12.5 to 0.17.1
Merged
#96 build(deps): bump mail-parser from 0.9.4 to 0.11.5
Merged
#61 feat(ci): enhance release.yml workflow with SHA256 checksum generation (GH-32)
Merged
#60 test(integration): add ephemeral_harness test for multi-account lifecycle (GH-31)
Merged
#59 test(integration): add full offline end-to-end integration test matrix (GH-30)
Merged
#58 feat(gui): add GuiViewState three-panel split view model (GH-29)
Merged
#57 feat(gui): add HtmlSanitizer and nuncio-mail:// scheme asset protocol (GH-28)
Merged
#56 feat(gui): add Tauri v2 IPC bridge and state event loop handlers (GH-27)
Merged
#55 feat(tui): add TuiApp event loop integrating watch state streams and broadcast events (GH-26)
Merged
#54 feat(tui): add HtmlRenderer for HTML-to-ANSI terminal text conversion (GH-25)
Merged
#53 feat(tui): add KeybindingEngine for Vim navigation and action shortcuts (GH-24)
Merged
#52 feat(tui): add AppLayout for 3-pane responsive terminal view (GH-23)
Merged
#51 feat(cli): add HeadlessRunner integrating EventBus and DatabaseEngine (GH-22)
Merged
#50 feat(cli): add JsonResponse machine output formatter and pipeline helpers (GH-21)
Merged
#49 feat(cli): add Clap subcommand hierarchy and global argument flags (GH-20)
Merged
#48 feat(cal): add MockCalendarBackend and wiremock CalDAV server test harness (GH-19)
Merged
#47 feat(cal): add CalDavClient for WebDAV REPORT calendar queries (GH-18)
Merged
#46 feat(cal): add RecurrenceEngine for RFC 5545 RRULE expansion (GH-17)
Merged
#45 feat(cal): add IcalParserAdapter and CalendarEvent domain models (GH-16)
Merged
#44 feat(mail): add MockMailBackend and wiremock protocol server mock infrastructure (GH-15)
Merged
#43 feat(mail): add ImapDualSocketManager and ImapEngine for IDLE push streams (GH-14)
Merged
#42 feat(mail): add MailBackend trait and JmapEngine protocol client (GH-13)
Merged
#41 feat(mail): add SmtpTransportEngine using lettre async Tokio client (GH-12)
Merged
#40 feat(mail): add MimeParserAdapter using mail-parser and bytes::Bytes (GH-11)
Merged
#39 feat(store): add PayloadCipher for AES-256-GCM and age attachment streaming encryption (GH-10)
Merged
#38 feat(store): add SecretManager and MockKeyring OS vault integration (GH-9)
Merged
#37 feat(store): add SQLite FTS5 trigram search engine and sync triggers (GH-8)
Merged
#36 feat(store): implement DatabaseEngine with SQLite WAL pragmas and schema migrations (GH-7)
Merged
#35 feat(core): add AccountConfig model and validation schema (GH-6)
Merged
#34 feat(core): implement EventBus channels for commands, state streams, and events (GH-5)
12 Pull requests proposed by 1 user
Proposed
#379 deps(actions): bump github/codeql-action from 3 to 4.37.4
Proposed
#382 deps(cargo): bump lettre from 0.11.22 to 0.11.23
Proposed
#383 deps(cargo): bump clap from 4.6.4 to 4.6.6
Proposed
#404 deps(cargo): bump async-trait from 0.1.91 to 0.1.92
Proposed
#432 deps(cargo): bump futures from 0.3.33 to 0.3.34
Proposed
#434 deps(cargo): bump aes-gcm from 0.10.3 to 0.11.1
Proposed
#435 deps(cargo): bump quick-xml from 0.41.0 to 0.42.0
Proposed
#436 deps(cargo): bump mail-parser from 0.9.4 to 0.11.8
Proposed
#437 deps(cargo): bump flate2 from 1.1.9 to 1.1.10
Proposed
#438 deps(cargo): bump keyring from 2.3.3 to 4.2.0
Proposed
#439 deps(cargo): bump tokio-rustls from 0.26.4 to 0.26.5
Proposed
#440 Qualify central Gitea Gradle and Rust CI
144 Issues closed from 1 user
Closed
#255 M6.5 [P1]: Production-wire Contacts sync (per-account CardDAV config + real client)
Closed
#257 M6.5 [P2]: DAV clients need real namespace-aware XML parsing (stop substring split + silent drops)
Closed
#265 M6.5 [P2]: Graceful bulk-path handling when one stored body is corrupted
Closed
#258 M6.5 [P2]: NaturalLanguageScheduler silently returns wrong times - parse genuinely or delete
Closed
#256 M6.5 [P2]: Filter size field is wrong for HTML-only mail
Closed
#271 M6.5 [P2]: tls_mode_from_db silently falls back to ImplicitTls on the normal read path
Closed
#421 nunciod hangs at startup if its keyring read blocks
Closed
#422 Flaky: salvage returns SQLITE_IOERR_SHORT_READ when the fixture pool is not closed
Closed
#419 nuncio-cli hangs forever reading the gRPC token in non-interactive sessions
Closed
#339 JMAP parse_email_get_response hardcodes folder_id='inbox' (mislabels non-inbox mailboxes)
Closed
#395 proto: mutation RPCs, durable conflicts, and DAV conditional write-back
Closed
#407 sync: IMAP and JMAP derive disjoint message keys, so engines do not converge across types
Closed
#375 Convert nuncio-filter hand-rolled test subscriber to tracing-test (flaky callsite-Interest race)
Closed
#408 jmap: implement Email/changes so JMAP accounts stop accumulating ghost messages
Closed
#410 mail: housekeeping left by the placement split (naming, mbox header, UID guard)
Closed
#409 filter: decide the reaping policy for the filter_fired claim ledger
Closed
#406 store: repointing a placement orphans its message row and strands plaintext in FTS
Closed
#363 OBS-7 Redaction policy + Redacted<T> newtype + no-secrets-in-logs canary
Closed
#365 OBS-9 CLI observability: wire -v/-vv + typed ErrorInfo rendering + RUNNING.md log docs
Closed
#330 WS-F10 [PROTO] Ops: System.GetHealth RPC + system health CLI (de-dup with WS-C8)
Closed
#364 OBS-8 [PROTO] Real GetStatus health surface (uptime/sync_state/outbox_depth/last_error + counters)
Closed
#361 OBS-5 Mail protocol instrumentation + destructive-op pre-logging
Closed
#362 OBS-6 Cal/Contacts/Store instrumentation + VEVENT-drop FIX + DAV Debug redaction
Closed
#359 OBS-3 Daemon handler + lifecycle log coverage
Closed
#358 OBS-2 Per-RPC span + request_id correlation + auth accept/reject logging
Closed
#360 OBS-4 Filter engine instrumentation + silent eval-timeout FIX
Closed
#278 WS-A6 [PROTO] AccountConfig oneof transport { ImapSmtp | Jmap | Dav }
Closed
#357 OBS-1 Subscriber foundation: layered Registry + EnvFilter + rotating file + JSON
Closed
#292 WS-C4 Bounded-concurrency sync dispatcher + per-account timeout (fixes serialized head-of-line)
Closed
#326 WS-F6 Ops: structured, leveled, secret-safe logging in nunciod
Closed
#277 WS-A5 [PROTO] Enum hygiene: RuleExportFormat enum; drop redundant use_tls
Closed
#304 WS-D8 gRPC server concurrency/stream/timeout limits
Closed
#318 WS-E10 SearchEngine::search_contacts (contacts_fts table + triggers already exist, unused)
Closed
#276 WS-A4 [PROTO] Id conventions: opaque ids, id vs <noun>_id naming, AddAccountResponse returns full config
Closed
#301 WS-D5 Bounded/paged IMAP fetch with per-message + per-batch size caps (use RFC822.SIZE)
Closed
#275 WS-A3 [PROTO] Keyset pagination on every list/search (AIP-158 page_size/page_token/next_page_token)
Closed
#290 WS-C2 Outbox per-item timeout (hung mutation -> Retry, cannot freeze all accounts)
Closed
#274 WS-A2 [PROTO] Timestamps: all wall-clock -> google.protobuf.Timestamp, durations -> Duration
Closed
#291 WS-C3 Single-instance advisory lock keyed on DB path
Closed
#310 WS-E2 CalendarEvent::to_ical() serializer + round-trip (the one missing serializer)
Closed
#324 WS-F4 Hygiene: EventBus dead-arm cleanup (unread_count nothing reads, ReloadFilters no-op)
Closed
#306 WS-D10 Pin resolved IP for webhook dispatch to close the DNS-rebind TOCTOU
Closed
#273 WS-A1 [PROTO] Typed errors: ErrorInfo message + frozen ErrorReason enum via Status details
Closed
#325 WS-F5 Hygiene: kill is_new_message N+1 SELECT-per-message in sync
Closed
#281 WS-B1 Message identity: deterministic surrogate id + remote_id/uid_validity columns (C1 fix) [GATE]
Closed
#289 WS-C1 Graceful shutdown: signal -> serve_with_shutdown -> drain -> db.close() WAL checkpoint
Closed
#297 WS-D1 Reject TlsMode::Plain to non-loopback hosts (quick win, ship first)
Closed
#321 WS-F1 CLI: render Status.message() not the raw tonic::Status Debug dump (~28 sites)
Closed
#254 M6.5 [P1]: Production-wire Calendar sync (per-account CalDAV config + real client)
Closed
#248 M6 [P1]: Salvage recovers audit/ledger tables + stops silently downgrading TLS mode
Closed
#247 M6 [P1]: Filter-rule load must not silently drop unparseable rules
Closed
#246 M6 [P1]: Export must not report success when its WORM audit write fails
Closed
#249 M6 [P1]: Prevent deterministic rule-ID collisions (silent overwrite on CreateRule)
Closed
#245 M6 [P1]: WORM/ledger append is non-atomic — serialize the hash-chain writes
Closed
#237 decrypt_text_at_rest silently returns empty string on decrypt/decode failure (read path)
Closed
#252 M6.5 [P0]: Build the outbox remote-mutation executor (filters made fully live)
Closed
#253 M6.5 [P0]: Remove fake/dead protocol code (orphaned dup CardDAV; credential-less fake-data mail paths)
Closed
#244 M6 [P0]: Delete fabricated e2ee/ai/plugin modules (fake crypto verification)
Closed
#203 M6: Replace webhook SSRF substring blocklist with real IP/CIDR + DNS-resolution checks
Closed
#202 M6: Fail closed on missing/unfetchable SHA256SUMS in the auto-updater
Closed
#201 M6: Reject non-loopback gRPC bind addresses; add a consolidated auth-coverage canary test
Closed
#200 M6: Validate WORM/ledger key length from the vault, fail closed on mismatch
Closed
#199 M6: Zeroize long-lived engine key material on drop
Closed
#198 M6: Fail closed on encryption failure in PayloadCipher::encrypt_text_at_rest
Closed
#196 M5: SendMessage selects an explicit account instead of the first configured
Closed
#195 M5: Incremental IMAP sync with progress reporting and per-item FETCH timeout
Closed
#194 M5: Account lifecycle over gRPC (edit/delete/test) + persist TLS mode
Closed
#197 M5: Roll back orphaned keyring secret when AddAccount fails to persist
Closed
#193 M4 [PROTO]: Re-expose bulk filter triage as a streaming Filters RPC
Closed
#192 M4 [PROTO]: Move filter edit/export/import/logs onto the Filters gRPC service
Closed
#191 M4: Fix filter header-field and account-field evaluation bugs
Closed
#190 M4: Wire FilterEngine into live sync so matched rules actually fire
Closed
#189 M3: Real JMAP client wired into the existing Mail sync path
Closed
#188 M2: Add Contacts API vertical (proto, daemon, CLI, E2E)
Closed
#187 M2: Build a real Contacts (CardDAV) engine, replacing the fabricated client
Closed
#186 M1: Wire RRULE recurrence expansion into calendar event queries
Closed
#185 M1: Add Calendar API vertical (proto, daemon, CLI, E2E)
Closed
#143 0.C.3 Replace the 100% coverage gate
Closed
#165 gRPC hardening: warn/validate on non-loopback bind; guard future services with interceptor
Closed
#164 Validate WORM/ledger key length loaded from vault
Closed
#163 Zeroize engine key material on drop
Closed
#162 cipher: encrypt_text_at_rest silently stores empty ciphertext on failure (data loss)
Closed
#169 AddAccount: avoid orphaned keyring entry if save_account fails after set_secret
Closed
#170 Mail.SendMessage: select account explicitly (currently uses first configured)
Closed
#184 ImapEngine ignores since_state: every sync is a full historical re-fetch, not incremental
Closed
#181 filter: WHERE 'account =' condition matches folder_id, not account_id
Closed
#176 Re-expose bulk filter triage over gRPC (lost with the JSON-RPC IPC)
Closed
#175 Move filter edit/export/import/logs to gRPC (Filters service)
Closed
#180 3.D Real JMAP HTTP client + camelCase fix
Closed
#179 3.C Real CardDAV sync + vCard round-trip
Closed
#178 3.B Real CalDAV transport + TZID fix + rrule recurrence
Closed
#177 3.A Filter-engine correctness (scoping, ON ACCOUNT, non-ASCII offsets, NOT IN)
Closed
#174 2.D Publish proto contract + SDK stubs + contract tests
Closed
#173 2.C Retire the legacy hand-rolled JSON-RPC IPC
Closed
#172 2.B Export + WORM audit gRPC services
Closed
#171 2.A Filters gRPC service (migrate filter.* off JSON-RPC)
Closed
#161 1.C.6 Mock protocol server harness
Closed
#168 Account model: carry a separate SMTP endpoint (host/port)
Closed
#160 1.C.5 Real SMTP send via outbox
Closed
#159 1.C.4 Read path over gRPC
Closed
#158 1.C.3 Real IMAP fetch to store loop
Closed
#157 1.C.2 Account setup + credentials in keyring
Closed
#156 1.C.1 Persistent DB path
Closed
#155 1.B.4 Transient error is not corruption
Closed
#154 1.B.3 Fix salvage schema mismatch
Closed
#153 1.B.2 FTS backfill at migration
Closed
#152 1.B.1 FTS-vs-encryption strategy
Closed
#151 1.A.4 Events server-streaming RPC
Closed
#150 1.A.3 CLI becomes a gRPC client
Closed
#149 1.A.2 Authenticated gRPC daemon server
Closed
#148 1.A.1 Proto skeleton + tonic build
Closed
#145 0.D.2 Move UI crates to _reference/
Closed
#144 0.D.1 Extract API-surface draft from MCP tools
Closed
#142 0.C.2 Align CI to the local gate
Closed
#140 0.B.2 Disable fail-open auto-updater
Closed
#147 0.E.2 Implement real OS keyring vault
Closed
#146 0.E.1 Purge hardcoded crypto keys
Closed
#141 0.C.1 Clear the clippy backlog / adopt green baseline
Closed
#139 0.B.1 Mark public releases pre-alpha
Closed
#138 0.A.3 Rewrite README to honest pre-alpha
Closed
#137 0.A.2 Rewrite CLAUDE.md to reality
Closed
#136 0.A.1 Remove fabricated docs
Closed
#4 Phase 4: Native Desktop GUI Shell & Cross-Platform Packaging
Closed
#3 Phase 3: Terminal User Interface (Ratatui TUI Shell)
Closed
#2 Phase 2: Protocol Engine Libraries (IMAP IDLE, JMAP, CalDAV)
Closed
#1 Phase 1: Core Engine & SQLite FTS5 Local Storage
Closed
#22 M4.3: Headless CLI E2E Integration Suite
Closed
#21 M4.2: JSON Pipeline Output Formatting (--json)
Closed
#20 M4.1: CLI Subcommand Parser (clap v4)
Closed
#19 M3.4: CalDAV Server Mocks (wiremock)
Closed
#18 M3.3: CalDAV REPORT Client (reqwest + quick-xml)
Closed
#17 M3.2: Recurrence Expansion Engine (rrule finite window math)
Closed
#16 M3.1: iCal/vCard to JSCalendar Parser (calcard)
Closed
#15 M2.5: Protocol Server Mocks (wiremock & MockMailBackend)
Closed
#14 M2.4: IMAP IDLE Dual-Socket Manager (async-imap IDLE push stream)
Closed
#13 M2.3: JMAP Client Protocol Engine (jmap-client Email/changes)
Closed
#12 M2.2: Outbound SMTP Transport (lettre async Tokio client)
Closed
#11 M2.1: Zero-Copy MIME Parser (mail-parser & bytes::Bytes)
Closed
#10 M1.6: Attachment Blob Encryption (age & AES-GCM)
Closed
#9 M1.5: OS Vault Integration (keyring) & Fallback
Closed
#8 M1.4: SQLite FTS5 Trigram Indexing & Triggers
Closed
#7 M1.3: SQLite Engine & WAL Migrations (sqlx)
Closed
#6 M1.2: Account & Configuration Schema (AccountConfig)
Closed
#5 M1.1: Event Bus Channels (CoreCommand, CoreEvent, mpsc, watch)
217 Issues created by 1 user
Opened
#1 Phase 1: Core Engine & SQLite FTS5 Local Storage
Opened
#2 Phase 2: Protocol Engine Libraries (IMAP IDLE, JMAP, CalDAV)
Opened
#3 Phase 3: Terminal User Interface (Ratatui TUI Shell)
Opened
#4 Phase 4: Native Desktop GUI Shell & Cross-Platform Packaging
Opened
#5 M1.1: Event Bus Channels (CoreCommand, CoreEvent, mpsc, watch)
Opened
#6 M1.2: Account & Configuration Schema (AccountConfig)
Opened
#7 M1.3: SQLite Engine & WAL Migrations (sqlx)
Opened
#8 M1.4: SQLite FTS5 Trigram Indexing & Triggers
Opened
#9 M1.5: OS Vault Integration (keyring) & Fallback
Opened
#10 M1.6: Attachment Blob Encryption (age & AES-GCM)
Opened
#11 M2.1: Zero-Copy MIME Parser (mail-parser & bytes::Bytes)
Opened
#12 M2.2: Outbound SMTP Transport (lettre async Tokio client)
Opened
#13 M2.3: JMAP Client Protocol Engine (jmap-client Email/changes)
Opened
#14 M2.4: IMAP IDLE Dual-Socket Manager (async-imap IDLE push stream)
Opened
#15 M2.5: Protocol Server Mocks (wiremock & MockMailBackend)
Opened
#16 M3.1: iCal/vCard to JSCalendar Parser (calcard)
Opened
#17 M3.2: Recurrence Expansion Engine (rrule finite window math)
Opened
#18 M3.3: CalDAV REPORT Client (reqwest + quick-xml)
Opened
#19 M3.4: CalDAV Server Mocks (wiremock)
Opened
#20 M4.1: CLI Subcommand Parser (clap v4)
Opened
#21 M4.2: JSON Pipeline Output Formatting (--json)
Opened
#22 M4.3: Headless CLI E2E Integration Suite
Opened
#79 Epic: OpenPGP (RFC 3156) & S/MIME (RFC 8551) End-to-End Encryption
Opened
#80 Epic: WASM & QuickJS Sandboxed Plugin Runtime Engine
Opened
#81 Epic: Autonomous Local LLM Email Summarization & Action Triage Engine
Opened
#136 0.A.1 Remove fabricated docs
Opened
#137 0.A.2 Rewrite CLAUDE.md to reality
Opened
#138 0.A.3 Rewrite README to honest pre-alpha
Opened
#139 0.B.1 Mark public releases pre-alpha
Opened
#140 0.B.2 Disable fail-open auto-updater
Opened
#141 0.C.1 Clear the clippy backlog / adopt green baseline
Opened
#142 0.C.2 Align CI to the local gate
Opened
#143 0.C.3 Replace the 100% coverage gate
Opened
#144 0.D.1 Extract API-surface draft from MCP tools
Opened
#145 0.D.2 Move UI crates to _reference/
Opened
#146 0.E.1 Purge hardcoded crypto keys
Opened
#147 0.E.2 Implement real OS keyring vault
Opened
#148 1.A.1 Proto skeleton + tonic build
Opened
#149 1.A.2 Authenticated gRPC daemon server
Opened
#150 1.A.3 CLI becomes a gRPC client
Opened
#151 1.A.4 Events server-streaming RPC
Opened
#152 1.B.1 FTS-vs-encryption strategy
Opened
#153 1.B.2 FTS backfill at migration
Opened
#154 1.B.3 Fix salvage schema mismatch
Opened
#155 1.B.4 Transient error is not corruption
Opened
#156 1.C.1 Persistent DB path
Opened
#157 1.C.2 Account setup + credentials in keyring
Opened
#158 1.C.3 Real IMAP fetch to store loop
Opened
#159 1.C.4 Read path over gRPC
Opened
#160 1.C.5 Real SMTP send via outbox
Opened
#161 1.C.6 Mock protocol server harness
Opened
#162 cipher: encrypt_text_at_rest silently stores empty ciphertext on failure (data loss)
Opened
#163 Zeroize engine key material on drop
Opened
#164 Validate WORM/ledger key length loaded from vault
Opened
#165 gRPC hardening: warn/validate on non-loopback bind; guard future services with interceptor
Opened
#168 Account model: carry a separate SMTP endpoint (host/port)
Opened
#169 AddAccount: avoid orphaned keyring entry if save_account fails after set_secret
Opened
#170 Mail.SendMessage: select account explicitly (currently uses first configured)
Opened
#171 2.A Filters gRPC service (migrate filter.* off JSON-RPC)
Opened
#172 2.B Export + WORM audit gRPC services
Opened
#173 2.C Retire the legacy hand-rolled JSON-RPC IPC
Opened
#174 2.D Publish proto contract + SDK stubs + contract tests
Opened
#175 Move filter edit/export/import/logs to gRPC (Filters service)
Opened
#176 Re-expose bulk filter triage over gRPC (lost with the JSON-RPC IPC)
Opened
#177 3.A Filter-engine correctness (scoping, ON ACCOUNT, non-ASCII offsets, NOT IN)
Opened
#178 3.B Real CalDAV transport + TZID fix + rrule recurrence
Opened
#179 3.C Real CardDAV sync + vCard round-trip
Opened
#180 3.D Real JMAP HTTP client + camelCase fix
Opened
#181 filter: WHERE 'account =' condition matches folder_id, not account_id
Opened
#184 ImapEngine ignores since_state: every sync is a full historical re-fetch, not incremental
Opened
#185 M1: Add Calendar API vertical (proto, daemon, CLI, E2E)
Opened
#186 M1: Wire RRULE recurrence expansion into calendar event queries
Opened
#187 M2: Build a real Contacts (CardDAV) engine, replacing the fabricated client
Opened
#188 M2: Add Contacts API vertical (proto, daemon, CLI, E2E)
Opened
#189 M3: Real JMAP client wired into the existing Mail sync path
Opened
#190 M4: Wire FilterEngine into live sync so matched rules actually fire
Opened
#191 M4: Fix filter header-field and account-field evaluation bugs
Opened
#192 M4 [PROTO]: Move filter edit/export/import/logs onto the Filters gRPC service
Opened
#193 M4 [PROTO]: Re-expose bulk filter triage as a streaming Filters RPC
Opened
#194 M5: Account lifecycle over gRPC (edit/delete/test) + persist TLS mode
Opened
#195 M5: Incremental IMAP sync with progress reporting and per-item FETCH timeout
Opened
#196 M5: SendMessage selects an explicit account instead of the first configured
Opened
#197 M5: Roll back orphaned keyring secret when AddAccount fails to persist
Opened
#198 M6: Fail closed on encryption failure in PayloadCipher::encrypt_text_at_rest
Opened
#199 M6: Zeroize long-lived engine key material on drop
Opened
#200 M6: Validate WORM/ledger key length from the vault, fail closed on mismatch
Opened
#201 M6: Reject non-loopback gRPC bind addresses; add a consolidated auth-coverage canary test
Opened
#202 M6: Fail closed on missing/unfetchable SHA256SUMS in the auto-updater
Opened
#203 M6: Replace webhook SSRF substring blocklist with real IP/CIDR + DNS-resolution checks
Opened
#204 M6: Sanitize inbound HTML email bodies before they leave the engine
Opened
#205 M7: Enforce full-surface contract coverage and an additive-only v1 policy in nuncio-proto
Opened
#206 M7: Verified Swift/C#/TypeScript codegen with minimal connect+GetStatus examples
Opened
#207 M7: CLI RPC coverage matrix — prove every nuncio.v1 RPC has an offline CLI-driven E2E
Opened
#208 M7: Replace the informational coverage job with an engine-crate gate + a required E2E CI job
Opened
#209 M7: Fix the broken release pipelines and tag an honest pre-alpha backend release
Opened
#216 calendar: recurrence overlap-windowing + unify is-recurring predicate (low)
Opened
#219 contacts: low-severity follow-ups from M2-S2 review (guards, id uniqueness, CLI wording)
Opened
#225 filter edit silently re-enables disabled rules and resets created_at
Opened
#233 M5 review follow-ups: sync/SMTP robustness polish
Opened
#237 decrypt_text_at_rest silently returns empty string on decrypt/decode failure (read path)
Opened
#244 M6 [P0]: Delete fabricated e2ee/ai/plugin modules (fake crypto verification)
Opened
#245 M6 [P1]: WORM/ledger append is non-atomic — serialize the hash-chain writes
Opened
#246 M6 [P1]: Export must not report success when its WORM audit write fails
Opened
#247 M6 [P1]: Filter-rule load must not silently drop unparseable rules
Opened
#248 M6 [P1]: Salvage recovers audit/ledger tables + stops silently downgrading TLS mode
Opened
#249 M6 [P1]: Prevent deterministic rule-ID collisions (silent overwrite on CreateRule)
Opened
#250 M6 [P2]: CodeQL scans JS/actions only — add Rust static analysis and require it on main
Opened
#251 M6 [P2]: Remove test theater (assertion-free backend tests; serve-result-swallowing test)
Opened
#252 M6.5 [P0]: Build the outbox remote-mutation executor (filters made fully live)
Opened
#253 M6.5 [P0]: Remove fake/dead protocol code (orphaned dup CardDAV; credential-less fake-data mail paths)
Opened
#254 M6.5 [P1]: Production-wire Calendar sync (per-account CalDAV config + real client)
Opened
#255 M6.5 [P1]: Production-wire Contacts sync (per-account CardDAV config + real client)
Opened
#256 M6.5 [P2]: Filter size field is wrong for HTML-only mail
Opened
#257 M6.5 [P2]: DAV clients need real namespace-aware XML parsing (stop substring split + silent drops)
Opened
#258 M6.5 [P2]: NaturalLanguageScheduler silently returns wrong times - parse genuinely or delete
Opened
#259 M6.5 [P2]: CLI polish - dead ephemeral DB, missing commands, self-update exception
Opened
#260 M6.5 [P2]: Audit minor cleanups (dead code, no-op command, weak UUIDs, non-atomic provision)
Opened
#265 M6.5 [P2]: Graceful bulk-path handling when one stored body is corrupted
Opened
#271 M6.5 [P2]: tls_mode_from_db silently falls back to ImplicitTls on the normal read path
Opened
#273 WS-A1 [PROTO] Typed errors: ErrorInfo message + frozen ErrorReason enum via Status details
Opened
#274 WS-A2 [PROTO] Timestamps: all wall-clock -> google.protobuf.Timestamp, durations -> Duration
Opened
#275 WS-A3 [PROTO] Keyset pagination on every list/search (AIP-158 page_size/page_token/next_page_token)
Opened
#276 WS-A4 [PROTO] Id conventions: opaque ids, id vs <noun>_id naming, AddAccountResponse returns full config
Opened
#277 WS-A5 [PROTO] Enum hygiene: RuleExportFormat enum; drop redundant use_tls
Opened
#278 WS-A6 [PROTO] AccountConfig oneof transport { ImapSmtp | Jmap | Dav }
Opened
#279 WS-A7 Error-code correctness pass (internal -> failed_precondition/unavailable/unimplemented; Triage rule_id -> UNIMPLEMENTED)
Opened
#280 WS-A8 Freeze-policy + CRUD-roadmap docs (additive-only-after-freeze, golden guards full surface)
Opened
#281 WS-B1 Message identity: deterministic surrogate id + remote_id/uid_validity columns (C1 fix) [GATE]
Opened
#282 WS-B2 [PROTO] Multi-recipient model: EmailAddress from/to/cc/bcc/reply_to (parser->store->proto->send)
Opened
#283 WS-B3 [PROTO] Message flags: MessageFlag set + Mail.SetFlags (replaces read bool / MarkRead)
Opened
#284 WS-B4 [PROTO] Threading: parse+store message_id/in_reply_to/references + thread_id; reply headers on send
Opened
#285 WS-B5 [PROTO] Client mailbox mutations: Mail.MoveMessage/CopyMessage/DeleteMessage via outbox
Opened
#286 WS-B6 [PROTO] Folder management: Mail.CreateFolder/RenameFolder/DeleteFolder/Subscribe
Opened
#287 WS-B7 [PROTO] Drafts: save/list/get/delete/send (local-first; server APPEND staged)
Opened
#288 WS-B8 [PROTO] Attachments on receive: persist+encrypt + attachment_id/size_bytes + streaming GetAttachment
Opened
#289 WS-C1 Graceful shutdown: signal -> serve_with_shutdown -> drain -> db.close() WAL checkpoint
Opened
#290 WS-C2 Outbox per-item timeout (hung mutation -> Retry, cannot freeze all accounts)
Opened
#291 WS-C3 Single-instance advisory lock keyed on DB path
Opened
#292 WS-C4 Bounded-concurrency sync dispatcher + per-account timeout (fixes serialized head-of-line)
Opened
#293 WS-C5 Autonomous per-account sync scheduler honoring sync_interval_secs (jitter, hot add/remove)
Opened
#294 WS-C6 [PROTO] Reliable resumable event stream: seq + bounded replay ring + ResyncRequired + NewMailArrived + forward SyncProgress + Subscribe(from_seq)
Opened
#295 WS-C7 IMAP IDLE real-time integration (wire the existing unused listen_idle into the scheduler)
Opened
#296 WS-C8 [PROTO] Health surface: System.GetHealth (outbox pending/failed, per-account last-sync outcome, WAL size)
Opened
#297 WS-D1 Reject TlsMode::Plain to non-loopback hosts (quick win, ship first)
Opened
#298 WS-D2 SPIKE: SQLCipher-through-sqlx feasibility (bundled-sqlcipher-vendored-openssl vs migrate to rusqlite)
Opened
#299 WS-D3 Whole-DB at-rest encryption (SQLCipher) + migration + 'stolen DB reveals nothing' test [HEADLINE]
Opened
#300 WS-D4 Signed updates: minisign detached signature + pinned key + decompression-bomb guards + safe apply/rollback
Opened
#301 WS-D5 Bounded/paged IMAP fetch with per-message + per-batch size caps (use RFC822.SIZE)
Opened
#302 WS-D6 [PROTO] Untrusted-content: engine-side HTML sanitization (ammonia) + html_is_untrusted marker + parser/zip/path hardening
Opened
#303 WS-D7 [PROTO] Bearer token rotation/revocation + per-client scoping
Opened
#304 WS-D8 gRPC server concurrency/stream/timeout limits
Opened
#305 WS-D9 OS-permissioned IPC: UDS 0600 / Windows named pipe + peer-UID check (replace loopback TCP)
Opened
#306 WS-D10 Pin resolved IP for webhook dispatch to close the DNS-rebind TOCTOU
Opened
#307 WS-D11 Remove/wire the dead age attachment cipher (superseded by WS-B8 attachment persistence)
Opened
#308 WS-D12 Document the same-user-malware non-goal (do not over-claim local isolation)
Opened
#309 WS-E1 [PROTO] Persist DAV href/etag/uid (extend #254/#255 read-sync to capture them) [prereq for write-back]
Opened
#310 WS-E2 CalendarEvent::to_ical() serializer + round-trip (the one missing serializer)
Opened
#311 WS-E3 CalDavWriteClient: conditional PUT/DELETE (If-None-Match/If-Match, 412 -> re-GET + aborted, never clobber)
Opened
#312 WS-E4 [PROTO] Calendar.CreateEvent/UpdateEvent/DeleteEvent write-through
Opened
#313 WS-E5 [PROTO] Calendar.ListCalendars + PROPFIND collection discovery
Opened
#314 WS-E6 [PROTO] Recurrence editing (series + single-instance RECURRENCE-ID; this-and-future staged)
Opened
#315 WS-E7 CardDavWriteClient: conditional PUT/DELETE
Opened
#316 WS-E8 [PROTO] Contacts.UpdateContact/DeleteContact + wire CreateContact to real CardDAV write-back
Opened
#317 WS-E9 [PROTO] Contact groups (ContactGroup type exists but never persisted; CardDAV KIND:group)
Opened
#318 WS-E10 SearchEngine::search_contacts (contacts_fts table + triggers already exist, unused)
Opened
#319 WS-E11 [PROTO] Structured scoped paginated multi-entity Search service (supersedes Mail.SearchMessages)
Opened
#320 WS-E12 Field-scoped operator query builder (from:/subject:/org:...) replacing the strip-everything sanitizer
Opened
#321 WS-F1 CLI: render Status.message() not the raw tonic::Status Debug dump (~28 sites)
Opened
#322 WS-F2 CLI: surface interactive password prompt + daemon prerequisite in --help
Opened
#323 WS-F3 Docs: expand RUNNING.md to the full command surface + install->add-account->sync walkthrough + troubleshooting
Opened
#324 WS-F4 Hygiene: EventBus dead-arm cleanup (unread_count nothing reads, ReloadFilters no-op)
Opened
#325 WS-F5 Hygiene: kill is_new_message N+1 SELECT-per-message in sync
Opened
#326 WS-F6 Ops: structured, leveled, secret-safe logging in nunciod
Opened
#327 WS-F7 CLI: wire --verbose; wire-or-remove the dead --account global flag
Opened
#328 WS-F8 CLI: standardize --account scoping across mail/cal/contact + show which account synced
Opened
#329 WS-F9 CLI: add cal get, contact get, system watch (Subscribe consumer)
Opened
#330 WS-F10 [PROTO] Ops: System.GetHealth RPC + system health CLI (de-dup with WS-C8)
Opened
#331 WS-F11 [PROTO] Ops: System.Backup RPC (online VACUUM INTO) + system backup + documented offline restore
Opened
#332 WS-F12 CLI: typed-error hints from ErrorInfo (extends WS-F1)
Opened
#333 WS-F13 Refactor: decompose grpc.rs (~6.1k) into grpc/{system,accounts,mail,filters,calendar,contacts,export,audit,auth,serve}.rs [behavior-preserving]
Opened
#334 WS-F14 Refactor: decompose DatabaseEngine (~3.8k/47 methods) into per-domain stores over one pool [behavior-preserving]
Opened
#338 WS-B follow-up: reap orphaned legacy message rows after identity migration
Opened
#339 JMAP parse_email_get_response hardcodes folder_id='inbox' (mislabels non-inbox mailboxes)
Opened
#347 Flaky test: mail_and_folder_report_honest_errors_when_daemon_unreachable (port-reuse race)
Opened
#351 WS-A3 pre-freeze hardening: Audit reserve, cross-list token tag, boundary tests
Opened
#357 OBS-1 Subscriber foundation: layered Registry + EnvFilter + rotating file + JSON
Opened
#359 OBS-3 Daemon handler + lifecycle log coverage
Opened
#358 OBS-2 Per-RPC span + request_id correlation + auth accept/reject logging
Opened
#360 OBS-4 Filter engine instrumentation + silent eval-timeout FIX
Opened
#361 OBS-5 Mail protocol instrumentation + destructive-op pre-logging
Opened
#362 OBS-6 Cal/Contacts/Store instrumentation + VEVENT-drop FIX + DAV Debug redaction
Opened
#363 OBS-7 Redaction policy + Redacted<T> newtype + no-secrets-in-logs canary
Opened
#364 OBS-8 [PROTO] Real GetStatus health surface (uptime/sync_state/outbox_depth/last_error + counters)
Opened
#365 OBS-9 CLI observability: wire -v/-vv + typed ErrorInfo rendering + RUNNING.md log docs
Opened
#370 Wire evaluate_with_timeout into the production sync filter path (ReDoS guard unused)
Opened
#375 Convert nuncio-filter hand-rolled test subscriber to tracing-test (flaky callsite-Interest race)
Opened
#386 sync: capture Message-ID and a content hash at ingest
Opened
#387 sync: add PRAGMA user_version gating and scheme-tagged sync tokens
Opened
#388 mail: raw IMAP command layer for ENABLE, tagged response codes, and VANISHED
Opened
#389 filter: add per-account filters_enabled, default off
Opened
#390 sync: IMAP change enumeration with a four-rung, per-mailbox capability ladder
Opened
#391 mail: conditional mutations with three outcomes (Applied/Conflict/Unknown)
Opened
#392 dav: href/ETag remote identity for calendar and contacts
Opened
#393 dav: sync-collection change enumeration for CalDAV and CardDAV
Opened
#394 store: split message identity from placements
Opened
#395 proto: mutation RPCs, durable conflicts, and DAV conditional write-back
Opened
#396 sync: per-account scheduler, session pooling, rate limiting, and jittered backoff
Opened
#397 test: multi-engine convergence harness with side-effect counting
Opened
#406 store: repointing a placement orphans its message row and strands plaintext in FTS
Opened
#407 sync: IMAP and JMAP derive disjoint message keys, so engines do not converge across types
Opened
#408 jmap: implement Email/changes so JMAP accounts stop accumulating ghost messages
Opened
#409 filter: decide the reaping policy for the filter_fired claim ledger
Opened
#410 mail: housekeeping left by the placement split (naming, mbox header, UID guard)
Opened
#419 nuncio-cli hangs forever reading the gRPC token in non-interactive sessions
Opened
#421 nunciod hangs at startup if its keyring read blocks
Opened
#422 Flaky: salvage returns SQLITE_IOERR_SHORT_READ when the fixture pool is not closed
Opened
#426 store: unparseable stored account protocol silently coerces to ImapSmtp