> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tuturuuu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Task notification email freshness

> Current due-date eligibility for immediate and digest task emails.

Task notification emails are skipped when the current task due date is strictly
more than 24 hours before the delivery check. Exactly 24 hours overdue, future due
dates and tasks without a due date remain eligible under the existing recipient,
notification-age and preference checks. This is an instant-based cutoff, not a
calendar-day or workspace-timezone comparison.

The dispatcher loads the current task through its task list and workspace board,
binding both the notification task ID and workspace ID. It does not use the
queued due-date snapshot for eligibility. A task rescheduled into the future is
therefore not skipped because its notification contains an older due date.

Immediate and digest dispatchers recheck every email item before rendering.
Mixed digests omit overdue items and build their subject and content from the
remaining items. An all-overdue batch completes with skipped delivery logs and
makes no email provider request. The skip reason is
`skipped: task_due_older_than_1_day`.

A tenant-scoped lookup that succeeds with an explicitly null task row is a known
unavailable task (for example, deleted or moved). It is skipped with
`skipped: task_unavailable`, so other eligible items in a mixed batch can proceed.
Undefined or malformed lookup results remain unknown and fail closed.

Skip and settlement writes must succeed before the dispatcher continues. If an
email provider was already attempted, a later settlement error remains an unknown
outcome for reconciliation; the digest is not marked retryable or automatically
resent. A provider `success: false` result can represent a transport timeout and
does not prove rejection. Existing explicit suppression reasons still settle as
skipped; other unsuccessful or thrown provider outcomes require reconciliation.
The same settlement protection applies to push delivery because the write helpers
are shared: accepted or ambiguous push attempts remain in processing for
reconciliation. Only zero deliveries with every device rejected as invalid proves
no push was accepted. Push freshness eligibility is unchanged.

Missing task/workspace bindings, conflicting payload task IDs, tenant mismatch,
lookup errors and invalid current due dates fail before delivery. They are not
recorded as a proven overdue skip. Existing delivery-attempt and ambiguous
provider-result handling remain in place; freshness is not reevaluated after a
provider attempt. Push and non-task notifications retain their existing checks.

For source validation, run the focused notification freshness and dispatcher
tests, then `bun check` and a real web app build through the resource queue.
The digest route is first-class under `apps/web/src/app/api/cron/`; after route
registration changes, run `node scripts/tanstack-migration-manifest.js generate`
followed by `node scripts/tanstack-migration-manifest.js check` and
`bun web:api-routes:check`. The package command `bun migration:tanstack:manifest`
remains disabled while the alternate runtime is paused; source inventory
generation does not resume that runtime. Rust route parity remains backlog and does
not mean production traffic has moved.

Source checks do not prove production activation or delivered email. No migration
or manual notification replay is required by this change.

## Retained batch reconciliation

The digest persists `delivery_in_flight` in the processing batch before calling
a provider. The write must return the exact processing batch ID; zero updated
rows or database errors prevent provider contact. A settlement or ambiguous attempt error writes the fixed
`reconciliation_required` marker while keeping status `processing`. If that write
fails, the cron returns an error; the earlier in-flight marker remains the durable
unknown-outcome signal. Neither marker is a provider acceptance receipt.

Each authorized digest cron also performs a bounded read-only inspection of up to
50 marked processing batches in the root workspace, with a separate two-second
discovery budget capped by the overall processing deadline. The budget is checked
before each query; an in-flight query may exceed it. It reports `reconciliation`
entries with batch IDs, persisted log counts and `terminal_log_snapshot`. At most
1001 logs are read per batch; empty, oversized, pending, failed, missing-date or
ambiguous-error snapshots never qualify. Null-workspace batches and older
unmarked processing rows require separate tenant-bound operator inspection.

This inspection never sends a notification, updates logs, resets a batch or
automatically marks a batch sent. A true snapshot only means every observed log
is already `sent` with a valid settlement timestamp and either no error or an
explicit `skipped: ` reason. It is not provider acceptance or inbox arrival proof,
and it cannot exclude a concurrently started queue insert.

For an authorized reconciliation, first select the exact processing batch by ID
and its marker through an authenticated, tenant-bound read-only client. Capture
all attached delivery log IDs, statuses, timestamps and skip reasons. Resolve
any active queue/dispatcher ownership before treating the snapshot as complete.
Only when every log is already terminal sent/skipped, the complete batch membership
is settled, and the corresponding outcome is known may an explicitly authorized
operator prepare a separately reviewed batch-only status update, guarded by
its ID, current processing status and unchanged marker. Use the complete log
count; do not change delivery logs or contact a provider during that operation.
The current helper has no conditional reconciliation guard; do not call it as
a reconciliation shortcut. The cron does not provide that mutation capability.

Pending logs after an attempted provider call require correlated provider outcome
receipts and a separately reviewed settlement operation. Unknown/accepted outcomes
remain held: do not use Retry, mark failed/pending, clear the marker, or resend.
If receipts or complete membership are unavailable, retain processing and record
the unresolved batch ID. This change adds no automatic unknown-outcome recovery,
new schema or production migration.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.