You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(lists): kind 30005 writes prose into .content, which NIP-51 reserves for private items #7588
CuratedListService publishing a public curated list writes the description into .content (mobile/lib/services/curated_list_service.dart:1191-1193):
if (list.isPublic) {
content = list.description ??'Curated video list: ${list.name}';
tags =CuratedListConverter.toEventTags(list);
}
NIP-51 puts a set's description in a tag — "sets can optionally have a title, an image and a description tags" — and reserves .content for the NIP-44-encrypted private-item array. The converter already emits that tag (mobile/packages/curated_list_repository/lib/src/curated_list_converter.dart:190-191), so the prose in .content is both redundant and protocol-wrong.
This is the same defect PR #6966 fixed for kind 10003, where .content had been the literal "Divine global bookmarks".
Data-loss path
NIP-51 allows one list to carry public and private items simultaneously — the spec's own mute-list example does. For a kind-30005 with public e/a tags and another client's ciphertext in .content, unsealItemTags short-circuits before decrypting (mobile/lib/services/curated_list_relay_gateway.dart:484):
if (event.content.isEmpty ||_hasPublicItemTags(event.tags)) {
returnconstUnsealedItemTags.notSealed();
}
Divine then treats the list as public, and the next edit overwrites .content with the description — destroying private items it never read. Kind 30005 is addressable/replaceable, so the overwrite is total.
Suggested fix
Publish a public list with content: '' and rely on the existing description tag. Carry any existing .content through verbatim when the private items are not what is being changed, mirroring how BookmarkService handles kind 10003 (mobile/lib/services/bookmark_service.dart:722-728).
Note curated_list_converter.dart:107 currently falls back to event.content as the description when reading a non-private list, so the read path needs to keep tolerating legacy events that still carry prose there.
Not measured
The incidence of mixed public+private kind-30005 lists in the wild has not been measured, so the data-loss path is demonstrated from the code rather than from an observed occurrence.
Activity