Role-Based Access Control for Relays #192

Closed
opened 2026-04-11 16:45:12 +00:00 by hodlbod · 8 comments
Owner
  • Open PR to NIP 43
  • Implement in Zooid
  • Implement in Flotilla

Mirror the same schema concepts in NIP 29 at relay scope:

  • Add relay roles event kind (role catalog)
  • Add relay admins event kind (admins + assigned roles)
  • Add role names to relay members listing (compatible extension)
  • Reuse the same tag grammar where possible:
    role
    role-label
    role-color (hue)
    role-order
    role-permission
    role-access (if relay wants relay-level access semantics)

This keeps 29/43 conceptually consistent.

Validation behavior (minimal but strict)

Relay SHOULD reject:

Role assignments containing unknown roles.
Moderation actions (mostly via nip 86) if the sender has no role-permission granting that kind.
- [ ] Open PR to NIP 43 - [ ] Implement in Zooid - [ ] Implement in Flotilla Mirror the same schema concepts in [NIP 29](https://gitea.coracle.social/coracle/flotilla/issues/47) at relay scope: - Add relay roles event kind (role catalog) - Add relay admins event kind (admins + assigned roles) - Add role names to relay members listing (compatible extension) - Reuse the same tag grammar where possible: role role-label role-color (hue) role-order role-permission role-access (if relay wants relay-level access semantics) This keeps 29/43 conceptually consistent. # Validation behavior (minimal but strict) Relay SHOULD reject: Role assignments containing unknown roles. Moderation actions (mostly via nip 86) if the sender has no role-permission granting that kind.
hodlbod added the idea label 2026-04-11 16:45:19 +00:00
hodlbod added this to the Current milestone 2026-04-11 16:45:21 +00:00
Khushvendra was assigned by hodlbod 2026-04-11 16:45:25 +00:00
Khushvendra was unassigned by hodlbod 2026-04-11 16:45:32 +00:00
Contributor

@hodlbod By zooid are you referencing caravel repo?

@hodlbod By zooid are you referencing caravel repo?
Contributor

@hodlbod Posting a concrete plan here so #192 is ready once the NIP-29 work is accepted and implemented.

NIP-43 Follow-up Plan (after NIP-29)

Gating condition

Start this only after:

  1. NIP-29 role/permission schema is merged in NIPs
  2. Relay/client implementation for that schema is live and validated

Goal

Mirror the NIP-29 RBAC model at relay scope, with consistent tag grammar and minimal ambiguity.

Scope for #192

  1. Relay-level role catalog event kind
  2. Relay-level admins event kind (admins + assigned roles)
  3. Relay members list extensions with optional role names
  4. Shared tag grammar consistency with NIP-29:
    • role
    • role-label
    • role-color (hue 0-255)
    • role-order (UI only)
    • role-permission (explicit capabilities)
    • role-access (if relay-level access policy is exposed)

Validation/behavior expectations

Relay SHOULD reject:

  1. Unknown-role assignments
  2. Moderation actions when sender lacks role-permission for that action

Also keep explicit language that role-order does not imply privilege.

PR strategy (granular)

NIP-43 PR 1: New relay role/admin/member schema

  1. Add relay role catalog event kind
  2. Add relay admins event kind
  3. Extend relay members listing format with optional role names

NIP-43 PR 2: Interop + migration notes

  1. Clarify relation to NIP-29 room-level schema
  2. Clarify how relays project/resolve relay roles for room-level behavior
  3. Add compatibility guidance for older clients

Implementation sequence (Zooid + Flotilla)

  1. Implement relay events and validation in Zooid
  2. Add client parsing/rendering in Flotilla
  3. Add compatibility tests for:
    • old clients + new relay
    • new clients + old relay
    • mixed role assignment scenarios

If this structure looks good, I’ll keep #192 as the execution tracker and begin with NIP-43 PR 1 only after the NIP-29 PR is accepted so that the scope is fixed for this issue after comparing with #47.

Also imo 2 PR's would be more appropriate for this issue due to the the topics it touches upon. Lmk your thoughts.

@hodlbod Posting a concrete plan here so #192 is ready once the NIP-29 work is accepted and implemented. ## NIP-43 Follow-up Plan (after NIP-29) ### Gating condition Start this only after: 1. NIP-29 role/permission schema is merged in NIPs 2. Relay/client implementation for that schema is live and validated ## Goal Mirror the NIP-29 RBAC model at relay scope, with consistent tag grammar and minimal ambiguity. ## Scope for #192 1. Relay-level role catalog event kind 2. Relay-level admins event kind (admins + assigned roles) 3. Relay members list extensions with optional role names 4. Shared tag grammar consistency with NIP-29: - role - role-label - role-color (hue 0-255) - role-order (UI only) - role-permission (explicit capabilities) - role-access (if relay-level access policy is exposed) ## Validation/behavior expectations Relay SHOULD reject: 1. Unknown-role assignments 2. Moderation actions when sender lacks role-permission for that action Also keep explicit language that role-order does not imply privilege. ## PR strategy (granular) ### NIP-43 PR 1: New relay role/admin/member schema 1. Add relay role catalog event kind 2. Add relay admins event kind 3. Extend relay members listing format with optional role names ### NIP-43 PR 2: Interop + migration notes 1. Clarify relation to NIP-29 room-level schema 2. Clarify how relays project/resolve relay roles for room-level behavior 3. Add compatibility guidance for older clients ## Implementation sequence (Zooid + Flotilla) 1. Implement relay events and validation in Zooid 2. Add client parsing/rendering in Flotilla 3. Add compatibility tests for: - old clients + new relay - new clients + old relay - mixed role assignment scenarios --- If this structure looks good, I’ll keep #192 as the execution tracker and begin with NIP-43 PR 1 only after the NIP-29 PR is accepted so that the scope is fixed for this issue after comparing with #47. Also imo 2 PR's would be more appropriate for this issue due to the the topics it touches upon. Lmk your thoughts.
hodlbod modified the milestone from Current to Future 2026-04-13 19:07:14 +00:00
hodlbod modified the milestone from Future to Next 2026-04-13 19:07:16 +00:00
Khushvendra was assigned by hodlbod 2026-04-13 19:07:24 +00:00
Author
Owner

Zooid is a relay implementation tailored to multi-tenant and compatibility with flotilla: https://gitea.coracle.social/coracle/zooid

Zooid is a relay implementation tailored to multi-tenant and compatibility with flotilla: https://gitea.coracle.social/coracle/zooid
Contributor

@hodlbod Had a few doubts:

  • NIP-29 uses 9000–9009 as the permission kinds. For relay-level permissions, should role-permission reference NIP-43 kinds (8000, 8001) instead? Or should we define new permission identifiers?
  • The plan proposes 13535 (relay roles) and 13536 (relay admins) as new kinds adjacent to the existing 13534 (relay members). These are in the same addressable range. Should we use different numbers?
  • The existing deriveSupportedMethods + ManagementMethod based admin check should remain as fallback, but should we also add new NIP-86 methods (e.g. listRelayRoles, setRelayUserRoles) as a convenience API in this PR?
@hodlbod Had a few doubts: - NIP-29 uses `9000–9009` as the permission kinds. For relay-level permissions, should role-permission reference NIP-43 kinds (`8000, 8001`) instead? Or should we define new permission identifiers? - The plan proposes 13535 (relay roles) and 13536 (relay admins) as new kinds adjacent to the existing 13534 (relay members). These are in the same addressable range. Should we use different numbers? - The existing `deriveSupportedMethods` + `ManagementMethod` based admin check should remain as fallback, but should we also add new NIP-86 methods (e.g. `listRelayRoles`, `setRelayUserRoles`) as a convenience API in this PR?
Author
Owner
  • NIP 43 should probably reference nip 86 methods rather than kind numbers
  • Those numbers should be ok, any particular reason not to use them?
  • It's hard to say what should be nip 86 and what shouldn't. Reads should probably be events to be consistent with nip 43 and writes should probably be methods to be consistent with nip 86.
- NIP 43 should probably reference nip 86 methods rather than kind numbers - Those numbers should be ok, any particular reason not to use them? - It's hard to say what should be nip 86 and what shouldn't. Reads should probably be events to be consistent with nip 43 and writes should probably be methods to be consistent with nip 86.
Contributor

Those numbers should be ok, any particular reason not to use them?

No really, just wanted to be consistent with the numbering and in case there was a protocol that i was not aware of being followed for the naming.

> Those numbers should be ok, any particular reason not to use them? No really, just wanted to be consistent with the numbering and in case there was a protocol that i was not aware of being followed for the naming.
Contributor

@hodlbod ill start working on this as soon as #220 is satisfactory. Does that work?

@hodlbod ill start working on this as soon as #220 is satisfactory. Does that work?
Khushvendra was unassigned by hodlbod 2026-05-06 16:35:33 +00:00
Author
Owner

Ok, I was thinking through this and we need to take a different approach due to the divergence between nip 29 roles and relay-level roles. I think it's better that roles get defined at the relay level and referenced by groups (groups can still create their own specific roles). However, at the relay level we need to avoid the RPC style management stuff nip 29 has.

First pass implemented in cd28085d11

Ok, I was thinking through this and we need to take a different approach due to the divergence between nip 29 roles and relay-level roles. I think it's better that roles get defined at the relay level and referenced by groups (groups can still create their own specific roles). However, at the relay level we need to avoid the RPC style management stuff nip 29 has. - [Add a nip86 method to publish an event using the relay's self key](https://github.com/nostr-protocol/nips/pull/2389) - [Publish roles to relay as self with `d` tag and allow for assignment](https://github.com/nostr-protocol/nips/pull/2390) First pass implemented in cd28085d11a42955a38865beece242de768e0306
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: coracle/flotilla#192