Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/mdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- `create_group` and `update_group_data` now reject `Some(0)` (or `Some(Some(0))` on updates) with `Error::Group`. Callers must use `None` (or `Some(None)` on updates) to disable. Part 2 of #253. ([#306](https://github.com/marmot-protocol/mdk/pull/306))
- Outer kind:445 wrappers built by `build_message_event` (messages, proposals, commits) automatically carry a NIP-40 `expiration` tag when the group has a `disappearing_message_secs` set. If the caller also supplies an expiration tag, the earliest of the two is used — the caller can request a shorter ephemeral lifetime but never extend the group's setting. The event's `created_at` is pinned to the same snapshot used for the expiration math. Part 2 of #253. ([#306](https://github.com/marmot-protocol/mdk/pull/306))
- Added `KeyPackageOptions::existing_d_tag: Option<String>` so callers can supply a previously stored `d` tag value when rotating a KeyPackage. When `Some`, the value is validated (non-empty, exactly 64 ASCII hex digits per MIP-00) and used directly for both the kind:30443 `Tag::identifier(...)` and the returned `KeyPackageEventData::d_tag`; no random `d` is generated. When `None`, the existing random 32-byte hex behavior is preserved. Validation matches the MIP-00 constraint enforced by `parse_key_package`, so caller-supplied values round-trip through publication and re-parsing. The `mdk_core::key_packages::validate_existing_d_tag` helper is also re-exported as `pub` so consumers (and the UniFFI binding) can pre-validate before calling. Closes the ergonomics gap that previously forced consumers (e.g. whitenoise-rs) to post-edit the tag list to keep their NIP-33 addressable slot stable across rotations. ([#303](https://github.com/marmot-protocol/mdk/pull/303))
- Added `delete_message`, `delete_messages_before_timestamp`, and `delete_processed_messages_for_group` public methods on `MDK` for granular message deletion supporting disappearing-message cleanup by the client. Part 3 of #253. ([#315](https://github.com/marmot-protocol/mdk/pull/315))

### Fixed

Expand Down
50 changes: 50 additions & 0 deletions crates/mdk-core/src/groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2099,6 +2099,56 @@ where
.map_err(|e| Error::Group(e.to_string()))
}

/// Delete a single message by event ID within a group.
///
/// Removes the decrypted message content from storage. Does not affect
/// processed message records.
///
/// Returns `Ok(true)` if the message was found and deleted, `Ok(false)`
/// if no message with the given event ID exists in the group.
///
/// This is a local-only operation — no MLS proposals or Nostr events
/// are published.
pub fn delete_message(&self, group_id: &GroupId, event_id: &EventId) -> Result<bool, Error> {
self.storage()
.delete_message(group_id, event_id)
.map_err(|e| Error::Group(e.to_string()))
}

/// Delete all messages in a group created before the given timestamp.
///
/// Intended for disappearing-message cleanup: compute
/// `now - disappearing_message_secs` and pass it as `before`.
///
/// Returns the number of messages deleted.
///
/// This is a local-only operation — no MLS proposals or Nostr events
/// are published.
pub fn delete_messages_before_timestamp(
&self,
group_id: &GroupId,
before: Timestamp,
) -> Result<usize, Error> {
self.storage()
.delete_messages_before_timestamp(group_id, before)
.map_err(|e| Error::Group(e.to_string()))
}

/// Delete all processed message records for a group.
///
/// Removes tracking metadata from local storage. Previously-seen events
/// may be reprocessed if encountered again.
///
/// Returns the number of records deleted.
///
/// This is a local-only operation — no MLS proposals or Nostr events
/// are published.
pub fn delete_processed_messages_for_group(&self, group_id: &GroupId) -> Result<usize, Error> {
self.storage()
.delete_processed_messages_for_group(group_id)
.map_err(|e| Error::Group(e.to_string()))
}

/// Delete all local state for a group.
///
/// Removes everything MDK stores for this group: messages, processed
Expand Down
2 changes: 2 additions & 0 deletions crates/mdk-memory-storage/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

### Added

- Implemented `delete_message`, `delete_messages_before_timestamp`, and `delete_processed_messages_for_group` for per-message and bulk expiry-based deletion. `delete_message` and `delete_messages_before_timestamp` scope `messages_cache` eviction to the owning group so a coincident `EventId` in another group cannot be evicted by accident. Part 3 of #253. ([#315](https://github.com/marmot-protocol/mdk/pull/315))

### Fixed

- Fixed `MdkMemoryStorage::save_welcome` to reject oversized welcome group metadata and serialized event JSON before caching welcomes, matching SQLite backend payload bounds. ([#276](https://github.com/marmot-protocol/mdk/pull/276))
Expand Down
Loading
Loading