Skip to content

Click-to-read deletes message from inbox list (cross-node, kept_for rebuild miss) #113

@iduartgomez

Description

@iduartgomez

Repro

FREENET_LIVE_E2E_SEND=1 cargo make test-e2e-real-node

Test 3 (live-node.spec.ts:343 — multi-round + read + archive across nodes) fails at line 478:

Error: round one stays visible after click-to-read
Locator: locator('iframe#app').contentFrame().getByText(/round one/i)
Expected: visible
Timeout: 10000ms
Error: element(s) not found

Flow that fails

  1. alice@gw → bob@peer: 'round one' (delivered, asserted visible)
  2. bob clicks the row → opens detail (asserted visible via fm-detail-time)
  3. bob navigates back to inbox list
  4. Expected: row still visible, read=true
  5. Actual: row gone

Suspected root cause

ui/src/app.rs:1191-1214 rebuilds the inbox list by merging contract messages with local_state::kept_for(&alias) (rows the contract evicted but the user has read). On click-to-read:

  • local_mark_read (local_state.rs:445) bumps the local-state delegate.
  • The contract's copy of the message gets evicted from the live emails list (read-window scrubbing in inbox contract).
  • kept_for should resurface it as a kept row (read=true).

Either:

  • local_mark_read isn't producing a KeptMessage entry in SNAPSHOT before the rebuild fires, OR
  • The rebuild reads SNAPSHOT before the delegate's echo lands, OR
  • Cross-node specific: contract eviction races the local-state delegate write so the row falls out of both sets.

Single-node manual flow (offline example-data,no-sync) doesn't exercise this — Playwright email-app.spec.ts doesn't click-to-read.

Why it matters for #81

Issue #81 wants FREENET_LIVE_E2E_SEND gate flipped off so cross-node delivery is a release blocker. The alice → bob test passes (modulo a separate too-greedy log regex — see #81 followup). Multi-round test 3 fails on this real product bug. Gate cannot flip until this is fixed, otherwise tag releases break.

Proposal

  1. Trace the kept_for rebuild race: log when local_mark_read writes the kept entry vs when the rebuild reads it.
  2. Likely fix: make mark_read synchronously add to SNAPSHOT (optimistic write) before awaiting the delegate echo, the way drafts are handled.
  3. Add a unit test on the offline path (mock contract evicting a read message) that pins kept_for resurrection.

Out of scope

alice → bob log-grep regex over-matches webapp re-publish noise. Fix in #81.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions