NIP-XX --- Immutable Badges (Soft)
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119 (opens in a new tab).
draft
optional
depends:01
depends:58
mentions:33
1. Motivation
The purpose of this NIP is to provide immutable badge definitions that may not be changed once created.
2. Short Description
Badge Definition Events (opens in a new tab) are defined as having kind:30009
, ie. they're parameterized replaceable events (see NIP-33 (opens in a new tab)).
This can be seen as a feature, or a bug, depending on the use case and the ultimate purpose the end user will give to the whole badge lifecycle.
When seen as "living" awards that may change in time, a parameterized replaceable event is certainly the tool for the job. When seen as "static" achievements, being able to change the definition of a badge post-facto is certainly not desired.
Noting that NIP-58 (opens in a new tab) fails to assign a semantic meaning to the Badge Award Event (opens in a new tab)'s .content
field, we shall take advantage of that and use it to "freeze" the badge definition being awarded.
3. Overview
This document is organized as follows: we introduce the new Badge Award Event Content Semantic, finally we deal with Client Behavior. We close with a short FAQ section.
4. Badge Award Event Content Semantic
NIP-58 (opens in a new tab) gives no semantic to a Badge Award Event's .content
field.
We make use of this oversight by stipulating that a badge award event may come in one of two forms: it may either be "empty" or "binding".
Empty badge award events have the form:
{
...
"kind": 10,
...,
"tags": [
...,
["a", <BADGE_DEFINITION_EVENT_ID>], // kind:30009
...,
["p", <RECIPIENT_PUBKEY_1>],
...,
["p", <RECIPIENT_PUBKEY_2>],
...
],
...,
"content": "",
...
}
(note that this is exactly the same as the ones proposed in NIP-58 (opens in a new tab)); on the other hand, binding badge award events have the form:
{
...
"kind": 10,
...,
"tags": [
...,
["a", <BADGE_DEFINITION_EVENT_ID>], // kind:30009
...,
["p", <RECIPIENT_PUBKEY_1>],
...,
["p", <RECIPIENT_PUBKEY_2>],
...
],
...,
"content": <BADGE_DEFINITION_AWARD_EVENT>,
...
}
where the <BADGE_DEFINITION_AWARD_EVENT>
placeholder stands for the JSON string of the version of the event referred to by the "a"
tag being in effect awarded at this time.
The .kind
, .pubkey
, and "d"
tag of the serialized event in the .content
field MUST be compatible with the value of the "a"
tag in the event's tags.
5. Client Behavior
Conforming clients need to check the .content
field of a badge award event mentioned in the "e"
tags of a kind:30008
event with a "d"
tag with "profile_badges"
value.
If a non-empty .content
field is found, conforming clients MUST render the event encoded therein instead of looking for the referred element by "a"
tag.
6. FAQ
Why prevent badges from being modified? Can we not simply not modify them and leave it at that?
Users are still free to define badges with a kind:30009
event and simply not replace said event at all, this is not what this NIP addresses.
Rather, it prevents any modification whatsoever to the badge definition itself.
There's a difference between being able to change something and no doing it, and having a guarantee that it will not ever change. This NIP addresses the latter.