membership

package
v1.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2026 License: AGPL-3.0 Imports: 10 Imported by: 0

Documentation

Overview

Package membership implements the registry's network membership handlers: create, delete, rename, join, leave, invite, kick, promote, demote, transfer-ownership, role query, member-tags, task-exec, and list-networks. It is extracted from pkg/registry/server as part of the R4.1 registry decomposition.

Thread safety: all exported Handler* methods are safe for concurrent use. Locking is delegated to the server through mu (shared with Server) and callback functions that acquire whatever locks are needed internally.

Index

Constants

View Source
const (
	// MaxInviteInbox limits the number of pending invites per node.
	MaxInviteInbox = 100
	// InviteTTL is the maximum age of a pending invite.
	InviteTTL = 30 * 24 * time.Hour
)

Variables

This section is empty.

Functions

func ValidateNetworkName

func ValidateNetworkName(name string) error

ValidateNetworkName checks that a network name is valid.

Types

type Callbacks

type Callbacks struct {
	// Save triggers a debounced snapshot write.
	Save func()
	// Audit records an audit log entry.
	Audit func(action string, attrs ...any)
	// RecordWALNetworkCreate records a network-create WAL entry.
	RecordWALNetworkCreate func(netID uint16, name, joinRule, token, adminToken string, enterprise bool, creatorNodeID uint32, createdAt string)
	// RecordWALNetworkJoin records a network-join WAL entry.
	RecordWALNetworkJoin func(nodeID uint32, netID uint16)
	// RecordWALNetworkLeave records a network-leave WAL entry.
	RecordWALNetworkLeave func(nodeID uint32, netID uint16)
	// RecordWALNetworkDelete records a network-delete WAL entry.
	RecordWALNetworkDelete func(netID uint16)
	// InvalidateListNodesCache drops the per-network list_nodes cache.
	InvalidateListNodesCache func(netID uint16)
	// PublishMembershipChanged publishes a membership.changed bus event.
	PublishMembershipChanged func(netID uint16)
	// ApplyRBACPreAssignment checks and applies any pre-assigned roles.
	// Caller must hold the global write lock.
	ApplyRBACPreAssignment func(netID uint16, nodeID uint32)
	// RequireAdminToken validates the admin_token field in a message.
	RequireAdminToken func(msg map[string]interface{}) error
	// RequireNetworkRole checks RBAC role for network operations.
	RequireNetworkRole func(msg map[string]interface{}, netID uint16, roles ...Role) error
	// RequireEnterprise checks that the given network has the Enterprise flag.
	RequireEnterprise func(netID uint16) error
	// VerifyNodeSignature verifies an Ed25519 signature for a node write.
	// Takes pubKey and adminToken (already copied under RLock by caller).
	VerifyNodeSignature func(pubKey []byte, adminToken string, msg map[string]interface{}, challenge string) error
	// AdminToken returns the current admin token (caller must not hold write lock).
	AdminToken func() string
	// NodeExists returns true if nodeID is registered. Caller must hold mu.RLock
	// or mu.Lock before calling.
	NodeExists func(nodeID uint32) bool
	// GetNodeForRead returns node fields needed before write lock.
	// Returns (pubKey, ok). Caller must hold mu.RLock.
	GetNodePubKey func(nodeID uint32) (pubKey []byte, ok bool)
	// GetNode returns a node's key fields. Caller must hold mu (read or write).
	GetNode func(nodeID uint32) (pubKey []byte, networks []uint16, externalID string, ok bool)
	// NodeNetworks returns a copy of node.Networks. Caller must hold mu.
	NodeNetworks func(nodeID uint32) ([]uint16, bool)
	// AppendNodeNetwork appends netID to the node's Networks slice under its shard lock.
	// Caller must hold mu.Lock.
	AppendNodeNetwork func(nodeID uint32, netID uint16)
	// RemoveNodeNetwork removes netID from the node's Networks slice under its shard lock.
	// Caller must hold mu.Lock. Returns false if the node was not in the network.
	RemoveNodeNetwork func(nodeID uint32, netID uint16) bool
	// IncInvitesSent increments the invites_sent_total counter.
	IncInvitesSent func()
	// IncInvitesAccepted increments the invites_accepted_total counter.
	IncInvitesAccepted func()
	// IncInvitesRejected increments the invites_rejected_total counter.
	IncInvitesRejected func()
	// IncRbacOps increments the rbac_operations_total{op=label} counter.
	IncRbacOps func(op string)
}

Callbacks bundles the side-effect functions the Store calls on state changes. All functions must be safe for concurrent use.

type NetworkInfo

type NetworkInfo struct {
	ID           uint16
	Name         string
	JoinRule     string
	Token        string // for token-gated networks
	Members      []uint32
	MemberRoles  map[uint32]Role     // per-member RBAC roles
	MemberTags   map[uint32][]string // admin-assigned per-member tags (e.g. "service")
	AdminToken   string              // per-network admin token (optional)
	Policy       NetworkPolicy       // network policy (membership limits, port restrictions)
	Rules        *wire.NetworkRules  // managed network rules (nil = normal network)
	ExprPolicy   json.RawMessage     // programmable policy engine document (nil = none)
	Enterprise   bool                // enterprise network (gates Phase 2-5 features)
	Created      time.Time
	RequestCount atomic.Int64 // per-network request counter (dashboard stats)
}

NetworkInfo holds the in-memory state for a single network.

type NetworkInvite

type NetworkInvite struct {
	NetworkID uint16    `json:"network_id"`
	InviterID uint32    `json:"inviter_id"`
	Timestamp time.Time `json:"timestamp"`
}

NetworkInvite is a pending network invitation stored in the invite inbox.

type NetworkPolicy

type NetworkPolicy struct {
	MaxMembers   int      `json:"max_members"`
	AllowedPorts []uint16 `json:"allowed_ports"`
	Description  string   `json:"description"`
}

NetworkPolicy defines constraints and metadata for a network.

type Role

type Role string

Role represents a member's permission level within a network.

const (
	RoleOwner  Role = "owner"  // created the network, full control
	RoleAdmin  Role = "admin"  // can invite, remove members, change settings
	RoleMember Role = "member" // can communicate, cannot manage
)

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store holds membership handler logic. The actual data maps (networks, inviteInbox, nextNet) are owned by the parent server and shared via the mu pointer. This is intentional for the R4.1 phase — locking semantics are preserved by using the same mutex as the server.

func NewStore

func NewStore(
	mu *sync.RWMutex,
	networks map[uint16]*NetworkInfo,
	inviteInbox map[uint32][]*NetworkInvite,
	nextNet *uint16,
	cb Callbacks,
	now func() time.Time,
) *Store

NewStore creates a ready-to-use membership Store. All pointer parameters are shared with the parent server and must not be nil.

func (*Store) HandleCreateNetwork

func (st *Store) HandleCreateNetwork(msg map[string]interface{}) (map[string]interface{}, error)

HandleCreateNetwork implements the "create_network" protocol command.

func (*Store) HandleDeleteNetwork

func (st *Store) HandleDeleteNetwork(msg map[string]interface{}) (map[string]interface{}, error)

HandleDeleteNetwork implements the "delete_network" protocol command.

func (*Store) HandleDemoteMember

func (st *Store) HandleDemoteMember(msg map[string]interface{}) (map[string]interface{}, error)

HandleDemoteMember implements the "demote_member" protocol command.

func (*Store) HandleGetMemberRole

func (st *Store) HandleGetMemberRole(msg map[string]interface{}) (map[string]interface{}, error)

HandleGetMemberRole implements the "get_member_role" protocol command.

func (*Store) HandleGetMemberTags

func (st *Store) HandleGetMemberTags(msg map[string]interface{}) (map[string]interface{}, error)

HandleGetMemberTags implements the "get_member_tags" protocol command.

func (*Store) HandleInviteToNetwork

func (st *Store) HandleInviteToNetwork(msg map[string]interface{}) (map[string]interface{}, error)

HandleInviteToNetwork implements the "invite_to_network" protocol command.

func (*Store) HandleJoinNetwork

func (st *Store) HandleJoinNetwork(msg map[string]interface{}) (map[string]interface{}, error)

HandleJoinNetwork implements the "join_network" protocol command.

func (*Store) HandleKickMember

func (st *Store) HandleKickMember(msg map[string]interface{}) (map[string]interface{}, error)

HandleKickMember implements the "kick_member" protocol command.

func (*Store) HandleLeaveNetwork

func (st *Store) HandleLeaveNetwork(msg map[string]interface{}) (map[string]interface{}, error)

HandleLeaveNetwork implements the "leave_network" protocol command.

func (*Store) HandleListNetworks

func (st *Store) HandleListNetworks(msg map[string]interface{}) (map[string]interface{}, error)

HandleListNetworks implements the "list_networks" protocol command.

func (*Store) HandlePollInvites

func (st *Store) HandlePollInvites(msg map[string]interface{}) (map[string]interface{}, error)

HandlePollInvites implements the "poll_invites" protocol command.

func (*Store) HandlePromoteMember

func (st *Store) HandlePromoteMember(msg map[string]interface{}) (map[string]interface{}, error)

HandlePromoteMember implements the "promote_member" protocol command.

func (*Store) HandleRenameNetwork

func (st *Store) HandleRenameNetwork(msg map[string]interface{}) (map[string]interface{}, error)

HandleRenameNetwork implements the "rename_network" protocol command.

func (*Store) HandleRespondInvite

func (st *Store) HandleRespondInvite(msg map[string]interface{}) (map[string]interface{}, error)

HandleRespondInvite implements the "respond_invite" protocol command.

func (*Store) HandleSetMemberTags

func (st *Store) HandleSetMemberTags(msg map[string]interface{}) (map[string]interface{}, error)

HandleSetMemberTags implements the "set_member_tags" protocol command.

func (*Store) HandleSetNetworkEnterprise

func (st *Store) HandleSetNetworkEnterprise(msg map[string]interface{}) (map[string]interface{}, error)

HandleSetNetworkEnterprise implements the "set_network_enterprise" command.

func (*Store) HandleTransferOwnership

func (st *Store) HandleTransferOwnership(msg map[string]interface{}) (map[string]interface{}, error)

HandleTransferOwnership implements the "transfer_ownership" protocol command.

func (*Store) ReplaceState

func (st *Store) ReplaceState(networks map[uint16]*NetworkInfo, inviteInbox map[uint32][]*NetworkInvite)

ReplaceState atomically swaps the membership store's network and invite maps with replacement values. Called by the server after applying a replication snapshot so the store's internal map pointers stay current. Must be called with s.mu held (Lock).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL