role.gno
2.10 Kb · 64 lines
1package groups
2
3import "gno.land/p/moul/addrset"
4
5// Role is a named bucket of addresses with optional metadata.
6//
7// A Role is always owned by a parent Group; the only way to obtain a *Role
8// is Group.AddRole or Group.GetRole. See the Group doc for the realm-
9// boundary rules that govern passing *Role values around.
10type Role struct {
11 name string
12 members *addrset.Set
13 meta any
14}
15
16// newRole constructs a new empty role with the given name. Unexported: the
17// only valid path to a *Role is via Group.AddRole, which registers it in
18// the parent Group's role registry. A detached Role has no useful API.
19func newRole(name string) *Role {
20 return &Role{
21 name: name,
22 members: &addrset.Set{},
23 }
24}
25
26// Name returns the role's registry name.
27func (r *Role) Name() string {
28 return r.name
29}
30
31// Members returns a mutable reference to the role's member set; mutations
32// through the returned pointer affect the role.
33//
34// SECURITY: the returned *addrset.Set is mutable. Do not expose it to
35// untrusted callers — use Role.Readonly().Members() for a
36// cross-realm-safe view.
37func (r *Role) Members() *addrset.Set {
38 return r.members
39}
40
41// Meta returns the role's metadata slot. See the package doc for the rule
42// against storing mutable pointers in meta.
43func (r *Role) Meta() any {
44 return r.meta
45}
46
47// SetMeta sets the role's metadata slot. Passing nil clears it.
48//
49// SECURITY: do NOT store a pointer whose type has a mutator method (this
50// includes common /p/ types like *addrset.Set or *avl.Tree) if untrusted
51// realms may hold a Readonly() view of this Group. Meta() returns the stored
52// value as-is, so a foreign reader can invoke that method and borrow rule #2
53// commits the write under this (the allocating) realm's authority. A direct
54// field write through the pointer is still blocked by the realm-ownership
55// gate — the leak is specifically mutator-method dispatch. Prefer value types
56// with no internal pointers. See the package doc.
57func (r *Role) SetMeta(meta any) {
58 r.meta = meta
59}
60
61// Readonly returns a read-only view of the role.
62func (r *Role) Readonly() *ReadonlyRole {
63 return &ReadonlyRole{role: r}
64}