Skip to content

Conversation

@vitorpamplona
Copy link
Collaborator

@vitorpamplona vitorpamplona commented May 24, 2024

Adds a special event kinds for relays to allow for

  • Full deletion of an account to specific relays
  • Full deletion of an account to ALL relays

Read here

Co-authored-by: fiatjaf_ <[email protected]>
@fiatjaf
Copy link
Member

fiatjaf commented May 25, 2024

@arthurfranca
Copy link
Contributor

arthurfranca commented May 25, 2024

Starting over from scratch from one point in time onwards is a good feature.

Considering that an user could change their mind by using a kind:5 to delete the kind:62, scoping it to a relay is ok too. Or else user could be just punising themselves by forbidden backing up their old events on that one relay, forever.

@vitorpamplona have you considered merging the two kinds into a single parameterized replaceable event with the d tag set to "" if for all relays or to "<relay-url>" if for a specific relay? It feels like a good fit.

@vitorpamplona
Copy link
Collaborator Author

I am against the merge because the second event kind is much more dangerous than the first. Keeping things separate should avoid some mistakes but clients (like forgetting to set the relay or d tag)

@RandyMcMillan
Copy link
Contributor

RandyMcMillan commented May 25, 2024

Add a switch so that if tags is empty - delete all

if a tag list is included - delete only those tags associated with the pubkey.

Note: I understrand that the additional granularity is outside the "Right to Vanish" scope.

@sant0s12
Copy link
Contributor

sant0s12 commented May 25, 2024

I also like @arthurfranca's idea but instead of "" meaning all, have something like "ALL_RELAYS".
This is a harder mistake to make than using kind 63 instead of 62 and avoids having an extra kind.

Copy link
Collaborator

@mplorentz mplorentz left a comment

Choose a reason for hiding this comment

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

This is nice! Required, I think, for relays in the EU that want to be GDPR compliant. Also the Apple App Store has a rule that you must offer the user a way to delete their account, and this seems like a best-effort way to adhere to that rule, given that you can't force other people to delete your data.

@mplorentz
Copy link
Collaborator

CC @jb55 I think you publish some kind of account deletion event in Damus to comply with the Apple rules. Curious what you think of this.

@vitorpamplona
Copy link
Collaborator Author

Ok, unified the two kinds in one with the ALL_RELAYS tag as requested.

@arthurfranca
Copy link
Contributor

Ok, unified the two kinds in one with the ALL_RELAYS tag as requested

But it was supposed to be a d tag instead of relay one, a parameterized replaceable event (PRE).

A PRE fits nicely because the proposed event is unique per relay url.
Also, the fact that user events get deleted from the oldest one up until the proposed event's .created_at timestamp, makes it ok to overwrite the timestamp with a newer .created_at value from a PRE replacing an older version of itself.

@vitorpamplona
Copy link
Collaborator Author

But it was supposed to be a d tag instead of relay one, a parameterized replaceable event (PRE).

It can't. The event can have more than one target relay.

@arthurfranca
Copy link
Contributor

Relays MAY store the deletion request for bookkeeping and ensure past events are not re-broadcasted into the relay.

If I'm relay "A", references to relays "B", "C", ..., "Z" are bytes I don't want to store.

Contrary to what happens in most other use cases, this one benefits from splitting many references into individual events.

@vitorpamplona
Copy link
Collaborator Author

If I'm relay "A", references to relays "B", "C", ..., "Z" are bytes I don't want to store.

If that is the case, you probably also don't want to maintain an entry in the replaceable address index for this event in case the user sends a new one.

Deletion events should not be replaceable.

@arthurfranca
Copy link
Contributor

informs a specific relay to delete everything [...] until its .created_at

An event replacing the older one would effectively extend the "until" period. Isn't it desired?

@vitorpamplona
Copy link
Collaborator Author

An event replacing the older one would effectively extend the "until" period. Isn't it desired?

Yes, but we don't need the infrastructure of replaceable events to do that. The regular 62 will delete past 62s as well.

@arthurfranca
Copy link
Contributor

Replaceable events infra is already in place (NIP-01), no extra lines of code for the replacement logic.

@vitorpamplona
Copy link
Collaborator Author

Replaceable events infra is already in place (NIP-01), no extra lines of code for the replacement logic.

My point is that we don't need to do replacement + deletion logics. Deletion logic is already enough.

Clients that don't implement replaceable events don't need to implement it.

@arthurfranca
Copy link
Contributor

Though.. a newer d-tag=ALL_RELAYS may replace an older d-tag=my-relay
And there is wss:// vs ws://, also trailing slash or not.

You have a point, the replacement logic can't rely solely on PRE flow.

@arthurfranca
Copy link
Contributor

Deletion logic is already enough.

Got it, if it replaces everything that came before, it replaces older 62. I was wrong.

@NfNitLoop
Copy link
Contributor

I don't really believe in a universal "right to vanish" for distributed protocols.

  1. Cache invalidation is a very complex problem. Throwing a "delete" event (be it kind 5, or this kind, or others) into the ether gives users a false sense of security. OK, you've said you want to delete some/all events, but do all the relays that store your events implement this NIP? Do they store the deletion request1 indefinitely so that things don't show up again? Did your message even make it to all the relays where your content was cached? If relays are free to not store deletion requests1 or not implement this NIP, you don't actually get a full "delete".

  2. Single/Mass deletion gives a false sense of security in the case of key compromise. If a user sees a post that they didn't post, and they delete it, they may think they've "dealt with" the issue, when in reality their key is still compromised.

  3. It's also an avenue for social abuse. Users can post awful content, then just delete it after the fact to avoid any consequences. Social media is social. If we have a conversation and you say awful things, you shouldn't get to just mind-wipe the internet of your actions.

  4. It can also introduce a potential for abuse. If relays DO store deletion events, now users can just fill relays with deletion events which they have to hold forever so that those events don't come back?


All that said, I suppose for those who do want to allow for deletion, or those that have to in order to comply with some laws, it's good to have a standard for this.

Some feedback:

I feel like "Delete Account" is a bad name for this. You're still going to have your pubkey, and all of your followers. And all of your content, on relays that aren't targeted. It's more like "Delete Content Before X From Server Y". And "Right To Vanish" is … just the same thing targeted at all relays. Maybe "Delete Content [From Relay]" and "Reset Account" are better terms for what these two cases accomplish?

If you want a real Delete Your Account, it should be an irrevocable revocation of the pubkey. Something like:

{
  "kind": whatever, // new kind # for pubkey revocation?
  "pubkey": pubkey,
  "content": seckey
}

Advantages:

  1. There's no coming back from this one. The secret key is out there, so anyone can now impersonate that account.
  2. The former user of the account gains plausible deniability for any old content. It could've been forged and backdated with their secret key, which is now in the public domain.
  3. Relay operators will want to store these kinds of revocations and delete other events, because they are possibly inauthentic, since the key is in the public domain.
  4. Key holders are less likely to abuse this than kind 5/62 deletion events, because the cost is losing their social network and truly starting over again from scratch.

Footnotes

  1. re: "Relays MAY store the deletion request for bookkeeping and ensure past events are not re-broadcasted into the relay." 2

@kehiy
Copy link
Contributor

kehiy commented Jan 17, 2025

@staab if you mean filter deletion, for relays who keep the filters, they can do the same thing as both nip 109 and 62.

without adding 2 more nip and a lot of complexity.

just send a nip-9 filter deletion with since and unitl set to minimum and maximum possible numbers. it would prevent future events to be written.

we may support freezing an account for a while using same model.

in relay side we would have different ways to support it.

here is an article explaining it:

https://njump.me/naddr1qq2nyv3ndf342d6ewcm52dny2d2rvc26w4452qg4waehxw309a4x2mrv09nxjumg9ekxzmny9upzpwkmmkjsw4et89u9ypyw5a8jauadj2c64sru848pmmqhf6xde932qvzqqqr4guth8yy5

ill update the article and add the freeze and delete account details (possible ways of implementation for both clients and relays) to it soon.

also you can find example implementation of immortal: https://github.com/dezh-tech/immortal

@staab
Copy link
Member

staab commented Jan 21, 2025

@kehiy I think the filter version is actually much more complex (it leaks metadata about deleted events, how is "search" interpreted, it's not easily indexable, it's going to be more computationally intensive for relays to implement), and isn't really justified by use case. The way I see it, we need the following types of deletes:

  • Delete this event. Bulk deletes are weird, if you published a bunch of events, just tag each one. It's still much lighter than the original payloads were. With one exception...
  • Delete everything on my pubkey until now. A "delete account" option. If this event uses the expiration tag, you could even (optionally) allow re-publishing old events after the delete expires.
  • Burn this pubkey. A permanent "delete account" option, for when a key is compromised.

Copy link
Contributor

@Semisol Semisol left a comment

Choose a reason for hiding this comment

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

There must be a "proof of freshness", to prevent dating events to in the future, and soft-bricking the npub.
A public key should not be able to be irreparably damaged due to a malicious or defective client (outside of full compromise of the nsec).

@staab
Copy link
Member

staab commented Jan 21, 2025

soft-bricking the npub

I think this is actually a desirable feature. I agree that it would suck to do this accidentally, but it's probably better to have it.

@kehiy
Copy link
Contributor

kehiy commented Jan 21, 2025

@kehiy I think the filter version is actually much more complex (it leaks metadata about deleted events, how is "search" interpreted, it's not easily indexable, it's going to be more computationally intensive for relays to implement), and isn't really justified by use case. The way I see it, we need the following types of deletes:

  • Delete this event. Bulk deletes are weird, if you published a bunch of events, just tag each one. It's still much lighter than the original payloads were. With one exception...
  • Delete everything on my pubkey until now. A "delete account" option. If this event uses the expiration tag, you could even (optionally) allow re-publishing old events after the delete expires.
  • Burn this pubkey. A permanent "delete account" option, for when a key is compromised.

i dont think if it's too complex. you can look at my implementation on immortal which currently performs the deletion of current events well. soon ill support keeping the deleted filter as well. i believe both of them at the same time won't be too complex. about performance, im using a mongo db with multiple database calls and it still performs well. soon ill refactor it to make on call and do the whole deletion which is much more efficient. and it would support all three cases you mentioned and more.

this article explains this filter tag better and answers your question about search and other fields on deletion filter:

https://njump.me/nostr:naddr1qq2nyv3ndf342d6ewcm52dny2d2rvc26w4452qghwaehxw309aex2mrp0yhxummnw3ezucnpdejz7q3qhtdamfg82u4nj7zjqj82wnew7wke9vd2cp7r6nsaast5arxujc4qxpqqqp65wvdt5af

@Semisol
Copy link
Contributor

Semisol commented Jan 21, 2025

I find it hard to see how relays will honor a feature that can be abused to hold anyone's npub by ransom just because your web client was able to sign an event. Most people blindly allow apps to sign all kinds of events, and most extensions don't even offer a per-kind option.

@kehiy
Copy link
Contributor

kehiy commented Jan 21, 2025

There must be a "proof of freshness", to prevent dating events to in the future, and soft-bricking the npub. A public key should not be able to be irreparably damaged due to a malicious or defective client (outside of full compromise of the nsec).

one of good approaches for this is @fiatjaf's idea which was using relay contact and asking them for a change. if someone accidentally freezed, deleted, limited their public-key.

the main idea was asking the relay operator for account deletion itself from fiatjaf on nsf meeting. but this would work for denial of a deletion or freeze. for deletion itself i like the filter model.

@Semisol
Copy link
Contributor

Semisol commented Jan 21, 2025

Asking relay operators to undo it doesn't scale though.

@kehiy
Copy link
Contributor

kehiy commented Jan 21, 2025

I find it hard to see how relays will honor a feature that can be abused to hold anyone's npub by ransom just because your web client was able to sign an event. Most people blindly allow apps to sign all kinds of events, and most extensions don't even offer a per-kind option.

if you mean in case of filter deletion, relay can set a min pow for deletion request or ask for payments. to prevent huge checks and resources usage.

@kehiy
Copy link
Contributor

kehiy commented Jan 21, 2025

Asking relay operators to undo it doesn't scale though.

i agree.

@Semisol
Copy link
Contributor

Semisol commented Jan 21, 2025

if you mean in case of filter deletion, relay can set a min pow for deletion request or ask for payments. to prevent huge checks and resources usage.

I think you misunderstood, I was referring to a malicious web client signing a delete everything event on behalf on someone that is dated to in the future, and holding their identity for ransom. Most people allow apps to sign any event kind.

@vitorpamplona
Copy link
Collaborator Author

I was referring to a malicious web client signing a delete everything event on behalf of someone that is dated to in the future, and holding their identity for ransom

I am not sure how proof of freshness solves this. If there is such a client, they can do the same with the past events. They can sign and wait to use in the future as well. The same client can start posting stuff the user didn't approve. If the issue is ransom from a malicious client and that client has the key, I don't think there is anything we can do to protect the user. They can literally do whatever they want with the account.

@kehiy
Copy link
Contributor

kehiy commented Jan 21, 2025

@Semisol if your signer/client publishs unexpected deletions on your behalf, then it would do more as well.

check the code, use a safe signer, restrict writing levels to be safe from this. we already have people who loose their follow lists. ive got my profile cleaned multiple time juts because some old web clients considered my old pubkey kind 0 as their base to create new one.

@mikedilger
Copy link
Contributor

Implemented in chorus.

Copy link
Contributor

@kehiy kehiy left a comment

Choose a reason for hiding this comment

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

implemented on dezh-tech/immortal#119

@staab
Copy link
Member

staab commented Feb 15, 2025

This is implemented in flotilla.social

@mikedilger
Copy link
Contributor

@vitorpamplona can you fix merge conflicts? This is implemented in at least 2 places and has 5 approvals, I think it should be merged.

@vitorpamplona
Copy link
Collaborator Author

Good to go!

@staab staab merged commit 619e3be into nostr-protocol:master Feb 19, 2025
@quentintaranpino
Copy link

This will be implemented in the nostrcheck-server relay module.

@cypherhoodlum
Copy link
Contributor

This will be implemented on Nestr github-like client

@dtonon
Copy link
Contributor

dtonon commented Feb 19, 2025

It seems a quite dangerous NIP, a bugged or malicious client can definitively nuke your profile just using a remote signer. Scary.
I would at least add a delay to the final action (e.g. 24h window) and a mechanism to undo the request.

@staab
Copy link
Member

staab commented Feb 20, 2025

I would at least add a delay to the final action (e.g. 24h window) and a mechanism to undo the request.

I agree. I also don't think the "undelete" part of the NIP makes sense, because this NIP is not a defense against a leaked key. But I don't feel strongly enough to open a PR.

@vitorpamplona
Copy link
Collaborator Author

I would at least add a delay to the final action (e.g. 24h window) and a mechanism to undo the request.

I think that is a relay operator's decision to offer or not the 24h window.

@mikedilger
Copy link
Contributor

If we had master keys and sub-keys, this could require the (more secure) master key to avoid the danger since clients wouldn't be given the master key. But we still have no movement towards a master-key sub-key system. So currently irrelevant.

RandyMcMillan pushed a commit to gnostr-org/gnostr-nips that referenced this pull request Apr 5, 2025
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.