Skip to content

feat(xmtp_db): add IntentState::Superseded for abandoned guarded intents - #4019

Merged
tylerhawkes merged 1 commit into
mainfrom
tyler/appdata-cb-db
Aug 19, 2026
Merged

tylerhawkes merged 1 commit into
mainfrom
tyler/appdata-cb-db

Conversation

@tylerhawkes

@tylerhawkes tylerhawkes commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

Stack

Merge bottom-up — each PR is based on its parent below.
Android is the priority path: #4019 → #4011 → #4012 → #4016.

Already merged: #4018 (proto regen). Related follow-up, independent of this stack: #4020.


Adds IntentState::Superseded, a terminal state for an intent abandoned before publishing because its compare-and-swap guard no longer matched the committed value.

Why a new state rather than reusing Error

sync_until_intent_resolved maps IntentState::Error to a generic GroupError::Sync. A caller cannot tell "another member changed the field first, re-derive and retry" from "the network is down" — and those want opposite reactions. Immediately republishing is right for the first and wrong for the second.

Processed is equally unusable: it reads as success, so the caller would be told a write landed that never did.

So the state has to be distinct. Superseded is terminal, carries no error semantics, and update_app_data translates it into a typed AppDataSuperseded error in the next PR.

Compatibility

New variant, value 6. The column is a plain integer and nothing migrates, but note this is one-way for local databases: a client old enough not to know the variant fails to deserialize an intent row written as Superseded. That is the same constraint every prior IntentState addition carried.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AdY7WKkNbJmdzpmUWvW1my

Note

Add IntentState::Superseded for intents abandoned due to CAS guard mismatch

  • Adds a new terminal IntentState::Superseded (value 6) to represent group intents abandoned when a compare-and-swap guard fails during publish.
  • Adds set_group_intent_superseded to QueryGroupIntent, which transitions an intent to Superseded only from ToPublish state; returns NotFound::IntentForToPublish otherwise.
  • Extends FromSql deserialization to map integer 6 to Superseded instead of erroring.
  • In mls_sync, a Superseded outcome from process_own_message now logs an error and takes no further action.

Macroscope summarized 43d1402.

@tylerhawkes
tylerhawkes requested a review from a team as a code owner August 19, 2026 18:51
@claude

claude Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

Claude finished @tylerhawkes's task —— View job


PR Review - August 19, 2026 19:35 UTC

Overview

This PR adds IntentState::Superseded to handle abandoned compare-and-swap guarded intents. The implementation is straightforward and follows existing state transition patterns.

Code Quality & Design

Positive:

  • Clean state machine design with terminal Superseded state distinct from Error
  • Consistent implementation following existing IntentState patterns
  • Proper documentation explaining the CAS guard semantics
  • Mock trait updated appropriately

Critical Issue (already flagged by Macroscope):
The set_group_intent_superseded implementation at crates/xmtp_db/src/encrypted_store/group_intent.rs:517-534 lacks state guards. Unlike other state transitions (set_group_intent_published, set_group_intent_committed, set_group_intent_to_publish), it doesn't filter on .filter(dsl::state.eq(IntentState::ToPublish)). This allows superseding intents in any state, which could race with successful publishing/committing.

Fix needed:

// Line 524 should add:
.filter(dsl::state.eq(IntentState::ToPublish))

Test Coverage Concerns

Missing tests (0% patch coverage per codecov):

  1. No test for set_group_intent_superseded function itself
  2. No test verifying state transition guard (ToPublish → Superseded only)
  3. No test for invalid state transition attempts
  4. No test for the mls_sync.rs warning path (lines 2448-2455)

Recommendation: Add a test similar to test_invalid_state_transition (lines 1144-1177) but for the Superseded state:

  • Verify successful transition from ToPublish
  • Verify failure when attempting to supersede Published/Committed intents
  • Verify error type matches expectations

Minor Observations

  1. mls_sync.rs:2448-2455 - The error case handling is defensive but unreachable per the comment. Consider whether this should be an assertion instead of just logging.

  2. Consistency - The Display impl (line 117) and FromSql impl (line 762) correctly handle the new variant, maintaining consistency with existing code.

Security & Performance

No security concerns identified. Performance impact is negligible (one additional enum variant).


Summary: The implementation is clean but requires the state guard fix and test coverage before merging. The core design decision (separate Superseded state) is sound.

Comment thread crates/xmtp_db/src/encrypted_store/group_intent.rs
@macroscopeapp

macroscopeapp Bot commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — Adds a new terminal IntentState::Superseded variant with proper state transition guards (only allows transition from ToPublish). The unresolved High severity comment is a false positive—the code at line 524 already includes the .filter(dsl::state.eq(IntentState::ToPublish)) guard it suggests. Author owns all modified files.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@codecov

codecov Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.90%. Comparing base (e3f9c62) to head (43d1402).

Files with missing lines Patch % Lines
crates/xmtp_db/src/encrypted_store/group_intent.rs 0.00% 17 Missing ⚠️
crates/xmtp_mls/src/groups/mls_sync.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4019      +/-   ##
==========================================
- Coverage   85.93%   85.90%   -0.03%     
==========================================
  Files         417      417              
  Lines       68170    68188      +18     
==========================================
- Hits        58579    58577       -2     
- Misses       9591     9611      +20     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Base automatically changed from tyler/appdata-cb-proto to main August 19, 2026 19:45
@tylerhawkes
tylerhawkes merged commit a5b1013 into main Aug 19, 2026
45 of 47 checks passed
@tylerhawkes
tylerhawkes deleted the tyler/appdata-cb-db branch August 19, 2026 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants