M6.5 [P0]: Build the outbox remote-mutation executor (filters made fully live) #252

Closed
opened 2026-07-31 14:42:45 +00:00 by KofTwentyTwo · 1 comment
KofTwentyTwo commented 2026-07-31 14:42:45 +00:00 (Migrated from github.com)

The headline half-gap. Filter remote actions MOVE/COPY/FLAG/UNFLAG/DELETE/FORWARD/CALL WEBHOOK parse, validate, match, log, and enqueue to the outbox, but NOTHING executes them. The outbox worker (nunciod/src/main.rs:101-135) only bumps the retry counter and leaves items pending (it honestly refuses to mark completed, so no fabrication, but the action never happens). WebhookDispatcher (SSRF-hardened in #203) is unreachable from the daemon. Only MarkRead/MarkUnread take effect today.

Goal: build a real outbox executor that drains pending mutations and applies each against the correct backend (IMAP/JMAP for MOVE/COPY/FLAG/UNFLAG/DELETE per the message account; the SSRF-hardened WebhookDispatcher for CALL WEBHOOK; a real forward for FORWARD TO), marking completed ONLY on genuine success and retrying/failing honestly otherwise. Offline E2E (mock backends) proving each action type executes end-to-end and the ledger reflects reality. This makes M4 filters truly live.

Source: full-tree audit 2026-07-30 (scratchpad/audit/AUDIT-SUMMARY.md). Follow docs/STORY-WORKFLOW.md: engine+proto(if surface)+CLI+offline E2E, mock-only tests, no fabricated data, comment convention, PR to dev, PO reviews before close.

The headline half-gap. Filter remote actions MOVE/COPY/FLAG/UNFLAG/DELETE/FORWARD/CALL WEBHOOK parse, validate, match, log, and enqueue to the outbox, but NOTHING executes them. The outbox worker (nunciod/src/main.rs:101-135) only bumps the retry counter and leaves items pending (it honestly refuses to mark completed, so no fabrication, but the action never happens). WebhookDispatcher (SSRF-hardened in #203) is unreachable from the daemon. Only MarkRead/MarkUnread take effect today. Goal: build a real outbox executor that drains pending mutations and applies each against the correct backend (IMAP/JMAP for MOVE/COPY/FLAG/UNFLAG/DELETE per the message account; the SSRF-hardened WebhookDispatcher for CALL WEBHOOK; a real forward for FORWARD TO), marking completed ONLY on genuine success and retrying/failing honestly otherwise. Offline E2E (mock backends) proving each action type executes end-to-end and the ledger reflects reality. This makes M4 filters truly live. Source: full-tree audit 2026-07-30 (scratchpad/audit/AUDIT-SUMMARY.md). Follow docs/STORY-WORKFLOW.md: engine+proto(if surface)+CLI+offline E2E, mock-only tests, no fabricated data, comment convention, PR to dev, PO reviews before close.
KofTwentyTwo commented 2026-07-31 15:55:24 +00:00 (Migrated from github.com)

Delivered via PR #263 (squash-merged to dev). The outbox worker now GENUINELY executes remote filter mutations: MailBackend::apply_mutation with real IMAP (UID-addressed, UIDVALIDITY-guarded) + JMAP (Email/set) ops; the daemon executor resolves message->account->backend and dispatches MOVE/COPY/FLAG/UNFLAG/DELETE to the backend, CALL WEBHOOK to the SSRF-hardened dispatcher, FORWARD via MessageSender — marking completed ONLY on real success, retry/fail honestly otherwise. Opus adversarial review verified the whole destructive surface fail-closed + no fake completion; caught+fixed a CRITICAL data-loss bug (bare EXPUNGE -> now UID-scoped UID EXPUNGE, fail-closed without UIDPLUS) + its test theater, plus lazy webhook-key provisioning. M4 'filters made live' is now truly live.

Delivered via PR #263 (squash-merged to dev). The outbox worker now GENUINELY executes remote filter mutations: MailBackend::apply_mutation with real IMAP (UID-addressed, UIDVALIDITY-guarded) + JMAP (Email/set) ops; the daemon executor resolves message->account->backend and dispatches MOVE/COPY/FLAG/UNFLAG/DELETE to the backend, CALL WEBHOOK to the SSRF-hardened dispatcher, FORWARD via MessageSender — marking completed ONLY on real success, retry/fail honestly otherwise. Opus adversarial review verified the whole destructive surface fail-closed + no fake completion; caught+fixed a CRITICAL data-loss bug (bare EXPUNGE -> now UID-scoped UID EXPUNGE, fail-closed without UIDPLUS) + its test theater, plus lazy webhook-key provisioning. M4 'filters made live' is now truly live.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: KofTwentyTwo/nuncio#252