Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relationship status #761

Draft
wants to merge 32 commits into
base: master
Choose a base branch
from

Conversation

vitorpamplona
Copy link
Collaborator

@vitorpamplona vitorpamplona commented Sep 4, 2023

Uses unbound lists to create events that define the relationship between two pubkeys in a public or private manner.

Read here

@jb55
Copy link
Contributor

jb55 commented Sep 4, 2023

cc @Semisol

@alexgleason
Copy link
Member

Will this allow for Alex Gleason set their relationship status to "it's complicated" with X?

@arthurfranca
Copy link
Contributor

Previous discussion regarding contact list at #349
tldr: see "kind X follow (by @vitorpamplona)" section here

@fiatjaf
Copy link
Member

fiatjaf commented Sep 7, 2023

@alexgleason I think NIP-32 may be the best way to declare public relationship statuses.

@vitorpamplona
Copy link
Collaborator Author

There are so many jokes here that I don't know if this proposal has any legs 😅

@arthurfranca
Copy link
Contributor

Most "Relationship Status" lists will have few items so NIP-51 would be enough.
Hopefully I expect my unbounded list PR #784 to be at a good enough state to suggest holding some ever growing data like subscriber list.

@vitorpamplona Please take a look at this example I just added there:

nips/61.md

Lines 53 to 87 in 8ae2b5d

```js
{
"kind": 33118,
"tags": [
["d", "random6467362966154779"]
// this is enough to mark it as a "subscribers" unbounded list
["n", "subscribers"],
// This also adds this event to other unbounded list (e.g.: meant
// to hold all pubkeys who can access the
// 5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36 event)
// made of the "subscribers" unbounded list events
// and other events such as NIP-51 Categorized People lists
["n", "private:5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"],
],
"content": "<NIP-44 encrypted Stringified TAG-List([
["p", "91cf9..4e5ca", "wss://alicerelay.com/"]
])>",
...other fields
}
```
```js
{
"kind": 30000,
"tags": [
["d", "close_friends"]
["n", "private:5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"],
],
"content": "<NIP-44 encrypted Stringified TAG-List([
["p", "14aeb..8dad4", "wss://bobrelay.com/nostr"],
["p", "612ae..e610f", "ws://carolrelay.com/ws"]
])>",
...other fields
}
```

@vitorpamplona
Copy link
Collaborator Author

vitorpamplona commented Sep 21, 2023

So, the goal for Relationship Status is that most of us have over 10,000 contacts (not friends, not follows, just contacts). And a list with 10,000 people is quite a heavy list to be updated all the time. That was the reason to start this.

Like, an email client, for instance, can have a status group for every person that sent you an e-mail. Instead of updating the list in every new e-mail and blasting all relays with it, the client just adds a Relationship Status event.

@arthurfranca
Copy link
Contributor

arthurfranca commented Sep 21, 2023

So, with my unbounded list proposal (basically the n tag and the 33118 kind for "people") it could be like this:

{
  "kind": 33118,
  "tags": [
    ["d", "random6467362966154779"]
    ["n", "contacts"]
  ],
  "content": "<NIP-44 encrypted Stringified TAG-List([
    ["p", "91cf9..4e5ca", "wss://alicerelay.com/", "Alice"],
    ["status", `<Known Face, Contact, Following, Coworker,
      Friend, Partner, Family, Extended family, Trusted,
      Competitor, Traitor, Used to Know, Scammer, NSFW,
      Unkown, etc>`],
    ["summary", "<summary of the relationship>"],
    ["email", "[email protected]"]
  ])>",
  ...other fields
}

The difference is that you can later add the same entry simultaneously to another unbounded list editing it and adding a new n tag.

Want all contacts, search by the n tag and author.

Edit: the event is supposed to hold just one p tag (encrypted) so you add other stuff there like the email adress tag, or a separate summary tag. Edited the above example.

@arthurfranca
Copy link
Contributor

@vitorpamplona Added you as author and also the "contacts" example there at #784
Please check it out.

@vitorpamplona
Copy link
Collaborator Author

The difference is that you can later add the same entry simultaneously to another unbounded list editing it and adding a new n tag.

I am confused. What does it do? Why would I add the entry to another unbounded list?

@vitorpamplona
Copy link
Collaborator Author

vitorpamplona commented Sep 21, 2023

I would separate the status example from a people list example. Otherwise, you have to link each status tag with each p tag (since you can have multiple p-tags in kind: 33118

So, an unbound list allows a client to search for multiple n tags in the same kind, while here you would get the "unbound" list by just getting everything with kind:30382.

You could turn the status into the unbound event's n tag. Then you can group people into one or more unbound status lists while still being able to get a single person's status by filtering by kind:30382, p tag and pubkey.

Wouldn't that be the right way to do this?

@arthurfranca
Copy link
Contributor

arthurfranca commented Sep 21, 2023

you can have multiple p-tags in kind: 33118

A kind 33118 event was meant to have a single p tag (I have recently edited the description pointing that out), because an unbounded people list (with a specific n tag) is made of one to many of these events.
There is another example there with two p tags but it is the NIP-51 kind 30000 with an n tag.

You could turn the status into the unbound event's n tag... to get a single person's status by filtering by kind:30382, p tag and pubkey.

Hmm got it you want to have kind 30382 with a p tag unencrypted (to able to use on filter). I encrypted the n tag content
to hide the info there (edit: so you would have to encrypt "known_face" before using on filter).

{
  "kind": 30382, // can fetch all contacts
  "tags": [
    ["d", "91cf9..4e5ca"]
    ["n", <NIP-44 encrypted("known_face")>], // can fetch all "known_face"s but no one knows the status
    ["relay", "<recommended relay>"],
  ],
  "content": "<NIP-44 encrypted Stringified TAG-List([
    ["nickname", "<My buddy>"],
    ["summary", "<summary of the relationship>"],
    ["email", "[email protected]"]
  ])>",
  ...other fields
}

Is this it?

@arthurfranca
Copy link
Contributor

arthurfranca commented Sep 21, 2023

If the above ["n", <NIP-44 encrypted("known_face")>] is a good idea, maybe you should standardize a NIP-51 list
holding all used n statuses?

I encrypted it because someone may get mad if it discovers his friend labeled him as a "scammer" or something worse =o

@vitorpamplona
Copy link
Collaborator Author

ohh interesting.. i didn't know the 33118 was supposed to be for just one person. I thought it would be a list of lists of people. Which is probably useful in some use cases.

["n", <NIP-44 encrypted("known_face")>]

Maybe using status for n is not a good idea. I am not sure if the encryption is deterministic to make sure all known_faces map to the same base64.

@arthurfranca
Copy link
Contributor

Maybe using status for n is not a good idea. I am not sure if the encryption is deterministic to make sure all known_faces map to the same base64.

Just tested it. It is not deterministic =(

nip44.encrypt(hexToBytes(sk1), 'scammer') // 'AU9OCx1Rn7PAA5TxDqgi5Up7bK+cNAgI2bU5/BhQmg0='
nip44.encrypt(hexToBytes(sk1), 'scammer') // 'AfCaDG/6jzFvQKEAVkaKzlgKIsPddNWXaynDPPNb/64='

@arthurfranca
Copy link
Contributor

maybe you should standardize a NIP-51 list holding all used n statuses?

If searching by the status at n tag was a must have feature, it could still be done if such NIP-51 list (holding all used n statuses) had tags like this:

[
  ["status", "<status 1>", "random string 1"],
  ["status", "Big Time Scammer", "6064460175057025"]
]

Then the n tag would be "6064460175057025"

@vitorpamplona
Copy link
Collaborator Author

@arthurfranca I am back to this, changed it to a private status (hash of the key as d-tag) and changed it to your unbound list idea.

I will be using this to document a list of Patients a doctor is taking care of. People can count how many patients a doctor has, but the relationship between them should be fully private.

81.md Outdated Show resolved Hide resolved
81.md Outdated Show resolved Hide resolved
81.md Outdated Show resolved Hide resolved
vicariousdrama pushed a commit to vicariousdrama/cornychat that referenced this pull request May 6, 2024
- Petnames implemented following Vitor's NIP-81 proposal in nostr-protocol/nips#761
- Documented use of 30311 and 30382 kinds in data types page
- Added more known supporters to about page
- Set volume of some doorbell sounds to half
- Added doorbell preview
81.md Outdated Show resolved Hide resolved
81.md Outdated Show resolved Hide resolved
81.md Outdated Show resolved Hide resolved
@vicariousdrama
Copy link
Contributor

I'm in favor of this NIP.

Corny Chat implemented basic support for NIP-81, kind 30382 on 2024-05-06 for petnames. This is an exceptionally useful feature so that users can actually start giving personal names to pubkeys which helps resolve who's who amongst the Dans, and acts as a defence against impersonation. NIP-44 encryption is used for those whose extensions support it. Otherwise it falls back to plain text.

@vitorpamplona
Copy link
Collaborator Author

@alexgleason did you add 30382 based on this NIP?

@vicariousdrama @alexgleason can you check if the NIP text matches your implementations? If not, I can change the text.

@alexgleason
Copy link
Member

@vitorpamplona You can run nak req -k 30382 -a db0e60d10b9555a39050c258d460c5c461f6d18f467aa9f62de1a728b8a891a4 wss://gleasonator.dev/relay to see my events.

I am using custom n values, none of which are described here. Example:

{
  "kind": 30382,
  "id": "3a7f95cb6b72a2ebdac6c3f1410e33685efb2644ae18e7be1f5f8933a8f4d59b",
  "pubkey": "db0e60d10b9555a39050c258d460c5c461f6d18f467aa9f62de1a728b8a891a4",
  "created_at": 1718215730,
  "tags": [
    ["d", "932614571afcbad4d17a191ee281e39eebbb41b93fac8fd87829622aeb112f4d"],
    ["n", "admin"],
    ["n", "suggest"],
    ["n", "suggested"]
  ],
  "content": "",
  "sig": "ca77c7313785f39434c1b944865fcce73f1053947e69ef6667e7c76a2ef8af70af6d1d37cd6cc8e530907868ffeec85412d0e6e9c7f973b29a5de6b2cc3be2b7"
}
  • admin - the user is granted admin permission of the ditto server, since this event is signed by the Ditto nsec
  • suggested - the user is globally suggested in the UI
  • suggest (deprecated) - I decided to go with suggested (even though it doesn't match the tense of follow) and forgot to remove the tag from existing events.

I am using this in a slightly unconventional way, but it all makes sense. I intend for regular users to also create kind 30382 events for things like private notes about users, and for users to suggest other users in future updates.

@vitorpamplona
Copy link
Collaborator Author

Nice!

I am not sure if the ns should be defined here. I am just making sure the rest of it is like we described. :)

@arthurfranca
Copy link
Contributor

Fixing kind numbers

👍

README.md Outdated
| `30402` | Classified Listing | [99](99.md) |
| `30403` | Draft Classified Listing | [99](99.md) |
| `30617` | Repository announcements | [34](34.md) |
| `30818` | Wiki article | [54](54.md) |
| `31382` | Private Relationship Status| [81](81.md) |
Copy link
Contributor

Choose a reason for hiding this comment

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

31383

Copy link
Collaborator Author

@vitorpamplona vitorpamplona Jun 20, 2024

Choose a reason for hiding this comment

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

No that's for the event, according to the old version of #784, 31382 is for private relationship between public keys

Copy link
Contributor

Choose a reason for hiding this comment

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

but there is no reference to 31383 in this PR, so then it shouldn't be in the README either unless it is explained.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am confused, 31383 is not in the readme.

Public 30382
Private 31382

@vicariousdrama
Copy link
Contributor

@alexgleason did you add 30382 based on this NIP?

@vicariousdrama @alexgleason can you check if the NIP text matches your implementations? If not, I can change the text.

I've checked how I've implemented this in Corny Chat, and only use kind 30382. The petname tag is used, as a tag, or in encrypted content via nip44 if the client signer supports it. This appears to match how your nip is written

@Giszmo
Copy link
Member

Giszmo commented Aug 17, 2024

ACK. Looks good to me.

@SilberWitch
Copy link
Contributor

Is there a reason why the d tag is used to reference an npub, in kind 30382? Shouldn't that be a p tag, since it's a reference to another user, and we generally use d tags as an identifier for long-form notes?

@vitorpamplona
Copy link
Collaborator Author

Is there a reason why the d tag is used to reference an npub, in kind 30382?

It's so that you can only have one 30382 per key.

@SilberWitch
Copy link
Contributor

Ah. I see. 🤔
I thought it was a typo.

That makes sense, since they're replaceable events, but a bit confusing.

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.