Kind Pure package
Name v0
Namespace nt / groups
Exported functions n/a — not supported for pure packages by the node (vm/qfuncs)
Module gno.land/p/nt/groups/v0
gno 0.9 doc.gno gno
⧉
1 // Package groups provides Groups containing a base address set plus named 2 // Roles, each with their own member set and metadata. 3 // 4 // A Group is the top-level container — one per DAO, one per permissions 5 // instance, etc. A Role is a named subset within a Group with arbitrary 6 // per-role metadata. 7 // not supported for pure packages by the node (vm/qfuncs)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
8 // The API separates three concerns explicitly, so each call site picks the
9 // right semantic:
10 //
11 // - base-only operations: Add, Remove, Has, Size, Iterate;
12 // - role registry operations: AddRole, GetRole, HasRole, RemoveRole,
13 // RoleCount, IterateRoles;
14 // - aggregated operations across base + all roles: HasAny, TotalSize,
15 // IterateAll, RolesContaining, RemoveFromAll.
16 //
17 // # Security model
18 //
19 // A Group, and the *Role values it hands out, are meant to be allocated and
20 // held by the consuming realm. Three rules apply at realm boundaries:
21 //
22 // 1. Do not ACCEPT a *Group or *Role from an external/untrusted caller —
23 // subsequent mutations would route to the allocating (attacker)
24 // realm's authority, and a poisoned Group could cause DoS or
25 // unexpected state.
26 //
27 // 2. Do not RETURN a *Group or *Role from any method or function callable
28 // by untrusted realms. Return *ReadonlyGroup or *ReadonlyRole instead.
29 // Exposing a mutable handle is exactly as dangerous as accepting one.
30 //
31 // 3. Do not TRUST a *ReadonlyGroup or *ReadonlyRole received from an
32 // untrusted caller. A readonly view is a live handle over its creator's
33 // data, not a snapshot: the sender controls the contents and can mutate
34 // them between reads. Base authorization and accounting decisions only
35 // on views derived from a Group you allocated yourself.
36 //
37 // The Readonly() views are the only safe handles to cross a realm boundary —
38 // safe to hand out, per rule 3 not blindly safe to consume.
39 //
40 // # Metadata: do not store mutable pointers
41 //
42 // Each Role has a free-form "meta any" slot. Meta() returns the stored
43 // value as-is, so a pointer stored in meta can be retrieved by an untrusted
44 // reader holding a Readonly() view. A direct field write through that
45 // pointer is still blocked by the realm-ownership
46 // gate, but invoking a MUTATOR METHOD on it (or passing it into a function
47 // that mutates by argument) runs under whatever realm allocated it (borrow
48 // rule #2) and commits the write. This includes common /p/ types such as
49 // *addrset.Set and *avl.Tree — they are mutable pointers, not "just data".
50 // Therefore store only:
51 //
52 // - value types (ints, strings, value structs/slices with NO internal
53 // pointer reaching a mutator-bearing type), or
54 // - a wrapper whose only exported methods are read-only and which holds no
55 // externally-mutable pointer.
56 //
57 // # Readonly views
58 //
59 // Group and Role each expose a Readonly() method returning a typed
60 // read-only view (ReadonlyGroup, ReadonlyRole; role member sets surface as
61 // *addrset.ReadonlySet). The views are concrete structs with unexported
62 // fields and only read-side exported methods, so cross-package callers
63 // cannot mutate through them.
64 package groups
65