nips
nips copied to clipboard
docs: add nip-58 badge event and profile badges
Adds event kind 8 meaning Badge and event kind 30008 parameterized replaceable event meaning Profile Badge.
Looks good.
For image
and thumbs
that are used to display images from a URL, should the minted badge include the SHA-256 hash of the image as well? I'm guessing we don't want the image host or badge issuer to be able to change the badge images based on time-of-day, or client IP without the client being able to notice something has changed.
Oh, another thing related to the URLs in this NIP. Are the image and thumbnail URLs supposed to be HTTP or HTTPS only? Or are other schemes valid as well? Like data URLs, ipfs://
URLs, Bittorrent magnet URLs etc.
Oh, another thing related to the URLs in this NIP. Are the image and thumbnail URLs supposed to be HTTP or HTTPS only? Or are other schemes valid as well? Like data URLs,
ipfs://
URLs, Bittorrent magnet URLs etc.
URL so it can be located anywhere.
I like this idea, just one question: What is the purpose of having ["d", "profile_badges"] in the tags? Is this not already known through the kind 30008?
I like this idea, just one question: What is the purpose of having ["d", "profile_badges"] in the tags? Is this not already known through the kind 30008?
This prevents another kind 30008 event from replacing it unless that event is also for the key profile_badges
.
These are parameterized replaceable events, so the kind isn't super important. You could use kind 30008 for another purpose, and if you used a different d
tag things wouldn't overwrite each other.
This prevents another kind 30008 event from replacing it unless that event is also for the key profile_badges. These are parameterized replaceable events, so the kind isn't super important. You could use kind 30008 for another purpose, and if you used a different d tag things wouldn't overwrite each other.
I am not happy with this answer. This feels like introducing two ways of doing the same thing.
Why not just define kind 10003
as meaning "profile badges" and put all badges there?
The answer above says "the kind isn't super important". To me if it isn't important it shouldn't be defined or used.
Do you also think kind 0
events should be a parameterized replaceable event and have a d
tag that says "metadata"?
I am not happy with this answer. This feels like introducing two ways of doing the same thing.
To clarify, I didn't write this NIP so my answer might not reflect that of the author.
Why not just define kind
10003
as meaning "profile badges" and put all badges there?
Makes sense to me.
The answer above says "the kind isn't super important". To me if it isn't important it shouldn't be defined or used.
Kind isn't an optional field, so it needs to be used.
You can't query filter by d
tags unless the relay implements the generic tag query NIP, but you can fall back to a kind query to find this event.
Do you also think kind
0
events should be a parameterized replaceable event and have ad
tag that says "metadata"?
Yes.
I also think setting aside arbitrary ranges for replaceable/ephemeral/parameterized replaceable was dumb, should have been tags or another field that determines that. Why should a relay hardcode that kind=0 is a replaceable event, instead of the event specifying that in can be replaced.
The person sending the event already knows if it should be replaced or not, or ephemeral or not, or if it should be replaced with pubkey + kind
, or pubkey + kind + replacement key
, there is no need to use ranges for this.
you can fall back to a kind
This is not good. If the kind is enough we should use just the kind.
Yes.
Has that been working bad so far such that it would be improved by having a d
tag? The best you'll achieve with that is to just replace the entire concept of kinds with that of d
tags, which essentially become named kinds.
Why should a relay hardcode that kind=0 is a replaceable event
The event specifies that by being in a kind range that is replaceable. No need to transfer an additional useless property called "replaceable", no need to parse that every single time. Ideally we wouldn't have these ranges and everything would be hardcoded, but that's not feasible, so the ranges are a nice solution.
I know programmers like to parse things at runtime and have the program dynamically handle everything, but that's not a good idea for open protocols. Some things must always be hardcoded. And the more things you can manage to hardcode the better.
Or maybe you wanted, for example, that each event had a JSON schema attached to itself specifying what fields it contains. It would also have to specify a hashing algorithm in itself, hashing function, curve and signature algorithm, because it would be dumb to have these things hardcoded! Not to mention the hardcoding of the JSON spec, why not allow events to have any encoding they want, they just specify that in their leading byte, we don't want to be dumb and hardcode the JSON format! And then you also need relays to advertise what protocols they accept for connections, because it would be dumb to hardcode that they all use websockets!
I think all these properties should be moved to tags and content should be an optional human-readable string describing the context of that specific badge award.
"tags": [
["p", "deadbeef"],
["r", "bravery"], // this is so one can query how many of any given tags a public key has issued
["name", "Bravery"], // optional
["description", "Given to people who shows signs of bravery"], // optional
["image", "https://..."], // optional
["thumb", "https://..."], // optional
["image_sha256sum", "..."] // optional
],
"content": "bob won this badge because his actions on field"
This prevents another kind 30008 event from replacing it unless that event is also for the key profile_badges.
These are parameterized replaceable events, so the kind isn't super important. You could use kind 30008 for another purpose, and if you used a different d tag things wouldn't overwrite each other.
I am not happy with this answer. This feels like introducing two ways of doing the same thing.
Why not just define kind
10003
as meaning "profile badges" and put all badges there?The answer above says "the kind isn't super important". To me if it isn't important it shouldn't be defined or used.
Do you also think kind
0
events should be a parameterized replaceable event and have ad
tag that says "metadata"?
I was hoping to introduce more badge lists like on NIP-51 Lists: archived, awards, etc. If we make it a kind 10008 we won't be able to do this.
I am not happy with this answer. This feels like introducing two ways of doing the same thing.
To clarify, I didn't write this NIP so my answer might not reflect that of the author.
Why not just define kind
10003
as meaning "profile badges" and put all badges there?Makes sense to me.
The answer above says "the kind isn't super important". To me if it isn't important it shouldn't be defined or used.
Kind isn't an optional field, so it needs to be used.
You can't query filter by
d
tags unless the relay implements the generic tag query NIP, but you can fall back to a kind query to find this event.Do you also think kind
0
events should be a parameterized replaceable event and have ad
tag that says "metadata"?Yes.
I also think setting aside arbitrary ranges for replaceable/ephemeral/parameterized replaceable was dumb, should have been tags or another field that determines that. Why should a relay hardcode that kind=0 is a replaceable event, instead of the event specifying that in can be replaced.
The person sending the event already knows if it should be replaced or not, or ephemeral or not, or if it should be replaced with
pubkey + kind
, orpubkey + kind + replacement key
, there is no need to use ranges for this.
It wasn't dumb, Nostream recognizes these ranges and uses indexes to maintain the uniqueness of replaceable events. But yeah maybe we could have done the same without the ranges? The good thing about ranges is that the relays already support many kinds as special events without the need to make changes to the relay.
I was hoping to introduce more badge lists like on NIP-51 Lists: archived, awards, etc. If we make it a kind 10008 we won't be able to do this.
With this in mind I think is worth allowing for future extensibility with kind 30008
.
Also think is better to put badge data in tags intead of a JSON string in the content as @fiatjaf suggests, and image + thumbnail should be enough to display these in clients, no need to overcomplicate with lots of resolutions.
May argue for the need of a time-to-live (TTL) attribute for badge events?
Here's my use case: Personhood-based sybil resitance. The Encointer protocol (as does IDENA and others) requires persons to attend regular concurrent key signing gatherings. In order to get a unique personhood proof, such a proof of attendance has to be ephemeral and reputation is only valid for 10days after which badges need renewal.
Motivation for nostr: Persons can only maintain one nostr profile with high reputation (because they can not be in more than one place at the same time of the gatherings), which can be useful for a variety of use cases
Our badges would mean sth like "has attended 4 of the past 5 Encointer personhood cycles"
@brenzi you could just say "this person attended a meeting on day x" and then people browsing that knew what Encointer was would realize that the last meeting they attended was 5 years ago so that doesn't mean anything.
This NIP works better if badges don't have metadata in them.
If I am issuing the same badge to a bunch of people it doesn't make sense for me to write the description and image in all these badges. And worse: as time passes I may want to change the description and images of badges I've given in the past, which is desirable.
I think this works better if I do
-
kind:30009
: "define badge", an event with description, images, can be replaced to be updated -
kind:8
: "badge award", an event in which I give a badge to people, contains ana
tag (see https://nips.be/33) referencing the badge -
kind:30008
: "profile badges", event users can use to decide what badges they "accept" and want to display, contains multiplea
ande
tags referencing the pairs ofkind:8
andkind:30009
above
@brenzi you could just say "this person attended a meeting on day x" and then people browsing that knew what Encointer was would realize that the last meeting they attended was 5 years ago so that doesn't mean anything.
Agreed, this can be solved client side. My preference would still be that the badge somehow can be marked as perishable with a TTL because the cycle period could change and clients would have to look up the lifetime of those badges dynamically, which I think is unnecessary overhead. No doubt we can find a workaround for our use case though.
@brenzi there is a NIP for generalized event expiration already. That can be used for badges too.
I assume there's no way to revoke an awarded badge, like with a replaceable event, since the awarding is kind:8
?
The use-case I'm thinking of is badges for membership levels, like Premium Supporter, Platinum Member, etc. These can be contingent on regular payment (badge re-issued every month), or on good behavior in a community (badge issued once, but may be revoked at any point in the future if necessary).
there is a NIP for generalized event expiration already. That can be used for badges too.
General event TTL expiration wouldn't work for that, you'd have to decide in advance how long this badge will live. Even so, it's impractical because each time it's renewed (re-awarded), the recipient has to update or re-issue the kind:3008
Profile Badge event to point to the new award.
Or am I missing something? Is there a simpler, more robust way to revoke badges?
I assume there's no way to revoke an awarded badge, like with a replaceable event, since the awarding is
kind:8
?The use-case I'm thinking of is badges for membership levels, like Premium Supporter, Platinum Member, etc. These can be contingent on regular payment (badge re-issued every month), or on good behavior in a community (badge issued once, but may be revoked at any point in the future if necessary).
there is a NIP for generalized event expiration already. That can be used for badges too.
General event TTL expiration wouldn't work for that, you'd have to decide in advance how long this badge will live. Even so, it's impractical because each time it's renewed (re-awarded), the recipient has to update or re-issue the
kind:3008
Profile Badge event to point to the new award.Or am I missing something? Is there a simpler, more robust way to revoke badges?
Deletion events. Ask clients to honor them because none of them care. (except Snort)
Do not bother about expiration time, just make badges with dates in them and write in them that they are valid only for a month. Then issue a new badge every month.
@ok300 If you feel this is still a problem, perhaps it's best to create a new issue to discuss since this PR is already merged.