VayuPress Docs

ADR-0124: VayuMail Outbound Reliability — Resend, Retry-Until-Sent & One-Click Dependency Updates

Status: Accepted
Date: 2026-07-08
Author: @johalputt
Relates to: ADR-0120 (HTMX console pattern), ADR-0064 (self-update), the VayuMail engine (internal/vayuos/mail)

Context

VayuMail's outbound queue (internal/vayuos/mail/queue.go, table vayumail_queue) is durable with exponential-backoff retry, but the Outbox tab was read-only: an operator could see "failed" but could not resend, retry, or clear a message, and the panel only refreshed on a full reload. Two concrete operator needs: (1) the Outbox should keep trying until a message sends, and give a one-click Resend when it eventually gives up; (2) a one-click way to apply dependency/security updates. This is the first slice of a broader VayuMail "enterprise-grade" overhaul.

Decision

1. Durable requeue operations (no data model change)

Add three operations to the existing queue: Requeue(id) (reset a message to state='pending', attempts=0, fresh max_attempts, next_attempt=now), RequeueAllFailed(), and Delete(id). Requeue works on both failed and pending rows, so a message that exhausted its retries during a transient outage can be sent again with one click. Engine wrappers (ResendQueued, RetryAllFailed, DeleteQueued) also kick an immediate off-request delivery pass (ProcessDue) so a Resend acts at once instead of waiting for the 30s worker tick.

2. Retry-until-sent (generous auto-retry, then one-click Resend)

Rather than literally-infinite retries (which would hammer a permanently-dead address and look like spam), the default QueueMaxAttempts is raised 12 → 20. With the existing backoff (2m doubling, capped at 6h) that auto-retries a transient failure for ~4+ days before marking it failed — at which point the operator gets a one-click Resend (and Retry all failed). This is the pragmatic, deliverability-safe reading of "keep trying until it sends".

3. Live Outbox via HTMX

The Outbox body is an HTMX fragment (GET /os/vayumail/outbox/fragment, hx-trigger="every 15s") that also re-renders in place after a Resend/Delete/ Retry-all (POST /os/vayumail/outbox/action → returns the refreshed body). Same CSP-safe pattern (self-hosted HTMX, nonce-gated glue, vp_csrf cookie mirrored to the header) already used by the Bot Shield console — no new JS, strict admin CSP intact.

4. Dependency updates are applied by installing a signed release

VayuPress is a single, statically-linked binary with its dependencies compiled in. There is therefore no server-side go get/rebuild to run, and the unprivileged web app must not attempt one. "Updating dependencies" = installing the latest signed release, which is built with the patched dependencies. The Security-updates tab now surfaces a one-click Update VayuPress action that routes to the existing verified self-updater (ADR-0064: SHA-256 + Ed25519, atomic swap, auto-rollback), and states this plainly. The secwatch monitor stays monitor-only.

Consequences

  • Outbound mail is operator-recoverable: nothing is stuck with no recourse, and ordinary transient failures self-heal for days without any action.
  • The Outbox is live and consistent with the rest of the modern VayuOS console.
  • Applying security patches is one click, with the full verified-update safety net, and honestly framed for a single-binary deployment.
  • Data model unchanged (same vayumail_queue table); the new operations are additive and covered by unit tests.

Not in this release (VayuMail overhaul roadmap)

Compose autosave + HTMX send, mailbox actions via HTMX (read/move/delete without reload), threaded conversations, richer search, server-side filters, and a design refresh across the mail tabs — to be delivered as the remaining screens are reviewed.