add NIP-86: Relay Management API
https://github.com/nostr-protocol/nips/blob/relay-management-api/86.md
Based on discussions at https://t.me/+BBS3jWGU9C1lYTRh
A few more rpc ideas:
- change relay name
- kind whitelist
- kind blacklist
- turning on or off pay to relay
- supported nips for the relay doc
- auto approve invites
If a relay keeps events in a moderation queue then there are three states:
- needs moderation
- approved
- banned
This would require the following additional methods:
- listeventsneedingmoderation
- approveevent
In order to undo mistakes
- unbanevent
- unbanpubkey
For IP management
- blockip
- unblockip
- listblockedips
I know engineers LOVE to Request/Response everything, but I would strongly encourage supporters of this to opt for a Configuration/Rection model, where the user simply changes the state and the relay follows suit.
In a Configuration/Rection, there is no need for individual success/error responses back to the client. The Client has the full state and upload new states as it sees fit. Errors should be handled by error states/logs the client can also get.
Configuration/Rection models work better in Nostr.
@vitorpamplona interesting idea, but that forces relays to adhere to a standardized config state schema, right? So it doesn't work, for example, for pyramid.fiatjaf.com, which keeps track of a tree of users, not a simple list -- and other such cases.
And then it assumes relays have only "full-power" admins that can edit everything, while the RPC model would easily support multiple admins with different sets of permissions and other weird constructs.
What do you think?
The list commands will have scaling issues when there are thousands of results unless there's some kind of pagination.
I am using kind 30382 events with ["n", "disabled"] (published by the relay's authorized nsec) to ban users, check:
nak req -k 30382 --tag n=disabled -a b9396834822fcb1c7f15dc171ce441ef8ab7d3b82ff3d147de15e4961f00e1f9 wss://gleasonator.dev/relay
@vitorpamplona interesting idea, but that forces relays to adhere to a standardized config state schema, right?
Correct. And that would be great for interoperability. Let's force Relays to come together like we do with Clients in Nostr. They gotta come up with a basic setup everyone uses and define new events for each of the specialties they might offer. We do this for Clients, so why can't Relays do the same?
JSON RPC inside Nostr looks like DIDs to me. It starts giving a lot of freedom to each implementer and ends up with 175 different ways to do the same thing and Clients now have to navigate all of the options to render things properly for the User.
Correct. And that would be great for interoperability. Let's force Relays to come together like we do with Clients in Nostr.
You're misunderstanding this. Relays must be different. If all relays are the same then there is no point in even working on new relay implementations and it is impossible for anyone to work on any new way to manage relays, everybody will be forced to work with whatever standard schema we define here. And of course people won't, they will just create different relays that don't adhere to this standard and this will be a useless standard.
We do this for Clients, so why can't Relays do the same?
Relays already adhere to the same core principles of Nostr that clients do: the WebSocket interface for events, the query language, the event format. We don't have to make them all be the same in all other aspects too.
JSON RPC inside Nostr looks like DIDs to me.
This is not "inside Nostr", it's an HTTP interface between a relay owner and its own machine. There is no need to deal with signed events for this use case.
The list commands will have scaling issues when there are thousands of results unless there's some kind of pagination.
I find it hard to imagine thousands of results, but it's not that bad either. These will not be commands you'll be running a million times per second. If we reach that point then we can make a new RPC kind that is paginated or do a custom proprietary solution or whatever.
I am using kind 30382 events with ["n", "disabled"] (published by the relay's authorized nsec) to ban users
This is good, but some relays may not want to make these things public.
You're misunderstanding this. Relays must be different.
They can be different. They can just code each state separately. There is a basic one for everyone to kick start their relays and then separate states (as if each one became a separate NIP) to setup their unique behaviors.
This is not "inside Nostr", it's an HTTP interface between a relay owner and its own machine. There is no need to deal with signed events for this use case.
Definitely disagree. Relays should setup an example and use the protocol as well. By working inside of Nostr, Relays might create an ecosystem of Relay-controlling Nostr Clients that might flourish by themselves. Relay Operators should be able to use all the benefits of Nostr for themselves instead of relying on the old unverifiable Web to do their operations.
Why do we need this? Why not have relays just host an interface for admins to manage them with? Clients that want users to be able to manage relays (I have vague plans to do this with coracle's groups) could just redirect users to the relay's admin page. I agree with @fiatjaf that relays should not be required to structure things in a particular ways, we've barely begun to explore what it means for relays to be weird and shouldn't hamper that.
@staab One example is that it takes the burden off of relay developers to program admin pages and moderation tools, these functionalities can be abstracted away and implemented by other tools like https://github.com/nodetec/relaywizard for instance.
As long as a relay implements a standard rpc for moderation or configuration you could for instance run relaywiz ban <pubkey> or relaywiz kind whitelist <kind>.
If you'd rather use a webui, engineers more specialized in web design can create webuis that relay operators can choose from to install on their server to do the moderation/configuration. So if one relay dev or frontend engineer makes a solid management client all relay operators that implement this nip benefit from that client. Regardless of the underlying relay implementation.
@mikedilger don't you think allowpubkey should work the same as unbanpubkey, and approveevent be the same as unbanevent and so on?
I find it hard to imagine thousands of results
I can... can't we just add a limit and offset? Then I won't bitch about this until the end of time like kind 3's :joy:
I know engineers LOVE to Request/Response everything, but I would strongly encourage supporters of this to opt for a Configuration/Rection model, where the user simply changes the state and the relay follows suit.
This isn't about configuration. This isn't AWS cloudformation. We aren't specifying a relay configuration state. We are manipulating the data. Look at the commands.
Definitely disagree. Relays should setup an example and use the protocol as well.
I disagree here. Removing somebody's post (censorship) is highly controversial and some people will want to retaliate if they know you did this. So it's better not to create a digitally signed record that is proof that you did it, even if correct code would never leak that record.
Why do we need this? Why not have relays just host an interface for admins to manage them with?
I was hoping somebody else would write a relay management website and I could just use it and not be bothered. But that probably won't happen if it is just for chorus.
@mikedilger don't you think
allowpubkeyshould work the same asunbanpubkey, andapproveeventbe the same asunbaneventand so on?
If a user is allowed, future events are automatically approved and don't await moderation. If they are banned, future events are banned and also don't wait moderation. There is a neutral state of being neither, where the events await moderation. So I need extra commands to handle that tristate situation.
This isn't about configuration. This isn't AWS cloudformation. We aren't specifying a relay configuration state. We are manipulating the data. Look at the commands.
Are you kidding?
Here are the states based on the commands:
- RelayMetadata { name: "", description: "", icon: "", }
- BannedPubKeys: List
- AllowedPubKeys: List
- EventsNeedingModeration: List
- AllowedEvents: List
- BannedEvents: List
- AllowedKinds: List
- DisallowedKinds: List
- BlockedIPs: List
EVERY COMMAND in this NIP is just manipulating a state. There is nothing else. It's state all the way down.
Removing somebody's post (censorship) is highly controversial and some people will want to retaliate if they know you did this.
So, the goal here is to find the sneakiest way to censor people without letting them know. Got it.
@vitorpamplona There is nothing wrong with censoring someone on an individual relay, they can just move to another relay, or even spin up there own. And as a relay operator I don't have to announce to the world everyone I ban. Which could be and very likely will be a lot of users, for most public relays publicly publishing every ban will just be double the spam.
Also we could just create a kind for publishing a relays ban list if the operator wants to share that information.
Maybe one use case of publishing bans could be that if other relays trust the pubkey that publishes the ban then they could automatically ban that event/pubkey as well.
There is nothing wrong with censoring someone on an individual relay, they can just move to another relay, or even spin up there own.
If there is nothing wrong, why are people so afraid of disclosing who they ban?
The relay is yours. You can ban whoever you want. But not telling users is a HUGE red flag for EVERYONE.
Be upfront and you will gain people's trust. Hide it and you are just operating a ticking time bomb.
If there is nothing wrong, why are people so afraid of disclosing who they ban?
The relay is yours. You can ban whoever you want. But not telling users is a HUGE red flag for EVERYONE.
Be upfront and you will gain people's trust. Hide it and you are just operating a ticking time bomb.
If we enforce full transparency at the level of this NIP that will just cause people to not use this NIP.
At the end of the day if someone is sufficiently motivated to privately ban someone they can put that in a config file on their server.
What do we really gain from not standardizing the process?
If we enforce full transparency at the level of this NIP that will just cause people to not use this NIP.
No need to force it. Just spec it to allow transparency. Relay operators can always remove their own events from a REQ. If they want to hide it, they always can... regardless of what we do here. But that should not be incentivized.
Are you kidding? [...] EVERY COMMAND in this NIP is just manipulating a state. There is nothing else. It's state all the way down.
"State" is not what differentiates. Of course it is all state.
But why should I upload an entire database of state, every moderation decision ever made on all users and all notes just because I want to change the logo icon? Sorry, but that is nutty.
Events are state. Should I upload every event on my relay every time I want to change a config parameter?
A lot of your decisions have had zero consideration for performance and/or traffic, like publishing a draft for every keystroke. This is just another in a long line of ideas that will burn nostr into a cinder.
The relay is yours. You can ban whoever you want. But not telling users is a HUGE red flag for EVERYONE.
I think it is a good policy to be up front and tell people when you ban them. BUT I don't think it is a good policy for us NIP developers for force all relay operators to adopt that good policy, because we couldn't even if we wanted to.
But why should I upload an entire database of state, every moderation decision ever made on all users and all notes just because I want to change the logo icon? Sorry, but that is nutty.
Should I upload every event on my relay every time I want to change a config parameter?
Are you thinking that I am proposing a single Replaceable Event to host all these lists and states? No. The state for the relay metadata could use one event kind just for it. Other states can use other new kinds. Approval and rejection of moderation can use single events for each, or lists, depending on your needs.
I don't think it is a good policy for us NIP developers for force all relay operators to adopt that good policy
Like I said before, this is not forcing anything. Just spec it to allow for transparency. Relay operators can always remove their own events from a REQ. If they want to hide it, they always can... regardless of what we do here. But bad behavior should not be incentivized.
Am I the only one who has already implemented relay moderation using events? I'm with Vitor on this one, ideally it's public. I'm not sure who these imaginary relay moderation implementers are.
I've already implemented relay moderation without using events. I'm just trying to create an API to it so that generic moderation tools that other people build will work with chorus.
A lot of people on nostr are anonymous. Why? Because they don't want nutters to come after them (including government nutters). Relay operators doing moderation are deleting events of people who are far more likely to be nutters than average. Even normal people turn into raving lunatics when they get censored. That is why I think the case for anonymity and the case for not digitally signing your actions isn't insignificant. If some revolutionary posts something illegal in my jurisdiction and I remove it and tell him why (that would be honest and nice) he may come to my house at night with an ~~axe~~ guillotine and off me. I'm the kind of guy who likes to survive.
So you guys can go ahead and hammer everything into the shape of a nostr event. Nobody is stopping you. I think this NIP is about doing it a different way. We could have two NIPs, one using events, one using HTTP REST.
There is not a lot of relay operators out there to begin with @alexgleason. We all agree that you can do the stuff this nip covers anyway but in a proprietary fashion so I see no good reason to gatekeep these features. If you want to have public moderation you can have it, if you want to privately moderate/configure your relay you can do that as well. Especially in the case that you are operating a private/exclusive relay to begin with.
Just create a standard and allow relay operators to choose, there is nothing wrong with a relay operator moderating their relay however they see fit. The standard is just going to make their lives easier.
A simple command line relay manager is here: https://github.com/mikedilger/relay-manager
- You need to store your Encrypted Private Key in your dotfiles (e.g. ~/.config/relay-manager/epk)
- It will prompt for your password every time you run it (which is very annoying, but it works for now), and it zeroes the memory afterwards
- Still I recommend managing relays with a keypair different from your normal nostr user
- I wrote it so I could test the server side code with it, not to be really useful. So I won't be extending it much if at all.
Example:
$ relay-manager ws://localhost:8080/ allowevent fb19b9b9ee1c57c5a52519986cc8d6068d8897a8ba0a5b25bc9db63a89278a39
CMD: {"method":"allowevent","params":["fb19b9b9ee1c57c5a52519986cc8d6068d8897a8ba0a5b25bc9db63a89278a39"]}
Password:
Error: Error { inner: ServerError(501, "{\"error\":\"The Management API is not yet implemented\",\"result\":{}}"), location: Location { file: "src/web.rs", line: 55, col: 67 } }
As you can see, my local chorus server cannot yet handle this command.
I've implemented a thing on Khatru, but it's not tested and no one should use it yet. I'll now proceed to write some tests and to use it on Pyramid to see if it works: https://github.com/fiatjaf/khatru/blob/91c652ef485272e6b2dc9f5ff1c6e8fad74600fe/nip86.go
I should probably write a book to document all these things.
Can we merge this? It's implemented in multiple places apparently. Any changes we should make?