Skip to content

feat(crates/mdk-core): make NIP-70 protected tag optonal in key package creation for relay compatibility#173

Merged
jgmontoya merged 1 commit intomasterfrom
fix/optional-protected-tag
Feb 10, 2026
Merged

feat(crates/mdk-core): make NIP-70 protected tag optonal in key package creation for relay compatibility#173
jgmontoya merged 1 commit intomasterfrom
fix/optional-protected-tag

Conversation

@jgmontoya
Copy link
Contributor

@jgmontoya jgmontoya commented Feb 9, 2026

Addresses #168

This PR makes the NIP-70 "protected" tag optional when creating Nostr MLS key-package events to improve relay compatibility, defaulting to omitting the protected tag while providing an options-based API so callers can opt into it. It updates mdk-core internals and public API, adapts examples and tests, and exposes the options in UniFFI so external callers can request the protected tag when needed.

What changed:

  • create_key_package_for_event now omits the NIP-70 protected tag by default and delegates to a shared internal implementation that accepts a protected: bool flag (mdk-core).
  • Added create_key_package_for_event_with_options(public_key, relays, protected) to let callers include the protected tag when desired (mdk-core, mdk-uniffi).
  • Return type changed from (String, [Tag; 7]) to (String, Vec) to reflect optional protected tag and variable tag count (mdk-core; mdk-uniffi bindings updated).
  • Public APIs now accept relay inputs as IntoIterator<Item = RelayUrl> for flexibility (mdk-core).
  • Examples and test utilities updated to pass tags directly (EventBuilder::tags) and to demonstrate protected: true usage in the key_package_inspection example (mdk-core examples, test_util).
  • CHANGELOG entries updated in mdk-core and mdk-uniffi to document behavior and API changes.

Security impact:

  • No cryptographic algorithm, key derivation, nonce, or key storage behavior was changed; this is a behavioral/tagging change only.
  • Logging now includes the protected flag state in a debug message, which does not expose sensitive key material.

Protocol changes:

  • Nostr integration: NIP-70 protected tag (["-"]) is now optional and omitted by default for wider relay compatibility; callers can include it via the new options API (NIP-70).
  • No MLS protocol (RFC 9420) algorithmic changes.

API surface:

  • Breaking: create_key_package_for_event signature/return type changed to return Vec instead of fixed [Tag; 7], and it no longer includes the protected tag by default (mdk-core).
  • Breaking behavior: callers that relied on a guaranteed protected tag must migrate to create_key_package_for_event_with_options(..., protected: true).
  • New public API: create_key_package_for_event_with_options(public_key, relays, protected) (mdk-core) and corresponding UniFFI method create_key_package_for_event_with_options(public_key: String, relays: Vec, protected: bool) (mdk-uniffi).
  • UniFFI/FFI: tag conversion and KeyPackageResult mapping updated to account for Vec.

Testing:

  • Tests and examples updated to assert 6-tag output for default create_key_package_for_event and 7-tag output when protected: true is used; test utilities and examples adjusted accordingly.

@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

create_key_package_for_event now returns Vec<Tag> and omits the NIP‑70 protected tag by default; a new create_key_package_for_event_with_options(..., protected: bool) controls inclusion. Changes touch core logic, examples, tests, UniFFI bindings, and changelogs.

Changes

Cohort / File(s) Summary
Changelog docs
crates/mdk-core/CHANGELOG.md, crates/mdk-uniffi/CHANGELOG.md
Updated release notes documenting API break: fixed-size [Tag; 7] -> Vec<Tag>, protected tag made optional, and new options API.
Core key-package logic
crates/mdk-core/src/key_packages.rs
Changed public return type to Vec<Tag>; added create_key_package_for_event_with_options and create_key_package_for_event_internal; made NIP‑70 protected tag conditional; added generics for relay input, logging changes, and updated tests.
UniFFI bindings
crates/mdk-uniffi/src/lib.rs
Added UniFFI-exported create_key_package_for_event_with_options(..., protected: bool); adjusted tag conversion and updated docs for default behavior.
Examples & test utilities
crates/mdk-core/examples/key_package_inspection.rs, crates/mdk-core/examples/group_inspection.rs, crates/mdk-core/src/test_util.rs
Updated call sites to new API and to pass tag collections directly (removed .to_vec()); example shows protected: true.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

breaking-change, mls-protocol

Suggested reviewers

  • mubarakcoded
  • dannym-arx
  • erskingardner
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: making the NIP-70 protected tag optional in key package creation, which is reflected throughout the changeset with the new create_key_package_for_event_with_options function and updated return types.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
No Sensitive Identifier Leakage ✅ Passed PR contains no instances of sensitive identifiers being exposed through tracing, format, panic macros, or unredacted Debug implementations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/optional-protected-tag

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 9, 2026

⚠️ Coverage: 90.99% → 90.99% (0.00%)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/mdk-uniffi/CHANGELOG.md (1)

30-45: ⚠️ Potential issue | 🟠 Major

Add the required PR link to the new Unreleased entries.

Each new entry needs the PR link in the mandated format at the end; it currently only references the issue.

Proposed fix
- **`create_key_package_for_event` No Longer Adds Protected Tag**: The `create_key_package_for_event()` function no longer adds the NIP-70 protected tag by default. This is a behavioral change - existing code that relied on the protected tag being present will now produce key packages without it. Key packages can now be republished by third parties to any relay. For users who need the protected tag, use the new `create_key_package_for_event_with_options()` function with `protected: true`. (Related: [`#168`](https://github.com/marmot-protocol/mdk/issues/168))
+ **`create_key_package_for_event` No Longer Adds Protected Tag**: The `create_key_package_for_event()` function no longer adds the NIP-70 protected tag by default. This is a behavioral change - existing code that relied on the protected tag being present will now produce key packages without it. Key packages can now be republished by third parties to any relay. For users who need the protected tag, use the new `create_key_package_for_event_with_options()` function with `protected: true`. (Related: [`#168`](https://github.com/marmot-protocol/mdk/issues/168)) ([`#173`](https://github.com/marmot-protocol/mdk/pull/173))
@@
- **`create_key_package_for_event_with_options`**: New function that allows specifying whether to include the NIP-70 protected tag. Use this if you need to publish to relays that accept protected events. (Related: [`#168`](https://github.com/marmot-protocol/mdk/issues/168))
+ **`create_key_package_for_event_with_options`**: New function that allows specifying whether to include the NIP-70 protected tag. Use this if you need to publish to relays that accept protected events. (Related: [`#168`](https://github.com/marmot-protocol/mdk/issues/168)) ([`#173`](https://github.com/marmot-protocol/mdk/pull/173))

As per coding guidelines, "Always include a link to the PR at the end of each CHANGELOG entry using the format ([#123](https://github.com/marmot-protocol/mdk/pull/123)), using the PR number not the issue number".

crates/mdk-core/src/key_packages.rs (1)

98-161: ⚠️ Potential issue | 🟡 Minor

Use .to_string() for string conversion instead of .into().

The code uses "encoding".into() which violates the repo's string-conversion rule. Use .to_string() or .to_owned() instead.

Fix
-            TagKind::Custom("encoding".into()),
+            TagKind::Custom("encoding".to_string()),
🤖 Fix all issues with AI agents
In `@crates/mdk-core/CHANGELOG.md`:
- Around line 26-35: Update the Unreleased CHANGELOG entries to append the PR
link in the required format after the existing issue link for each bullet: for
the entries referencing create_key_package_for_event and
create_key_package_for_event_with_options, add the PR reference formatted like
([`#123`](https://github.com/marmot-protocol/mdk/pull/123)) using the actual PR
number (e.g., `#173`) so each bullet ends with both the issue and PR links.

@jgmontoya jgmontoya force-pushed the fix/optional-protected-tag branch from 1eced65 to c634cc4 Compare February 9, 2026 19:19
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/mdk-core/src/key_packages.rs`:
- Around line 157-161: Replace the implicit conversion using .into() with an
explicit .to_string() for the string literal passed to TagKind::Custom so the
calls like TagKind::Custom("encoding".into()) become
TagKind::Custom("encoding".to_string()); locate these occurrences in the Tag
construction sites (e.g. where tags.push(Tag::custom(TagKind::Custom(...),
[encoding.as_tag_value()])), and update the other similar TagKind::Custom(...)
uses in the file to use .to_string() instead of .into().

Copy link
Contributor

@dannym-arx dannym-arx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, looks good to me!

Copy link
Contributor

@mubarakcoded mubarakcoded left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@jgmontoya jgmontoya force-pushed the fix/optional-protected-tag branch from c634cc4 to 5d88b84 Compare February 10, 2026 15:02
@github-actions
Copy link

❌ Coverage: 90.99% → 90.95% (-0.04%)

…age creation for increased relay compatibility
@jgmontoya jgmontoya force-pushed the fix/optional-protected-tag branch from 5d88b84 to 2a9edfb Compare February 10, 2026 16:14
@github-actions
Copy link

❌ Coverage: 90.99% → 90.95% (-0.04%)

@jgmontoya jgmontoya merged commit 5952e36 into master Feb 10, 2026
13 of 15 checks passed
@jgmontoya jgmontoya deleted the fix/optional-protected-tag branch February 10, 2026 16:17
@jgmontoya jgmontoya mentioned this pull request Feb 10, 2026
@coderabbitai coderabbitai bot mentioned this pull request Mar 1, 2026
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.

4 participants