On this page
Static vs capability authority๏
๐ Advanced ยท Lesson 11
WHAT THE ROOM KIND ACTUALLY CHANGES.
StaticRiftSpace and CapabilityRiftSpace override exactly TWO properties of RiftSpace, and they are the two that matter:
command_system StaticCommandSystem / CapabilityCommandSystem frame_viewer StaticFrameViewer / FrameViewer
THE DOING ONE AND THE SEEING ONE. workstation, event_system and memory_system are inherited unchanged, so the room's storage and signalling are constant while its AUTHORITY and its VISIBILITY both narrow together.
That pairing is the design. A room you may not mutate is also a room that shows you less - and melder does it the same way twice, by handing you a different class rather than guarding a shared one.
AND HERE IS THE DESIGN DECISION WORTH LEARNING FROM.
The static room does not REFUSE meld(). It does not raise PermissionError, it does not check a flag, it does not consult an ACL at call time. IT SIMPLY DOES NOT HAVE THE METHOD.
melder's own note on StaticCommandSystem says it outright:
"Does not expose topology mutation or direct meld(...) because those methods now live on the capability surface INSTEAD OF BEING DENIED AFTER INHERITANCE."
That is the opposite of the usual pattern, where a subclass inherits everything and then overrides the dangerous half to raise. Melder builds authority UP by class membership instead of tearing it DOWN by guard.
WHY THAT IS BETTER, CONCRETELY: - There is no refusal path, so there is no refusal path to test, no error message to get subtly wrong, and no gap between "the guard is there" and "the guard is correct". - Capability becomes STATICALLY ENUMERABLE. You can answer "what may this room do" without executing anything and without triggering a single refusal. - hasattr becomes an honest question again. In a deny-after- inherit design it lies - the attribute is there and calling it explodes.
THE AIX SURFACE Both kinds expose list_supported_command_methods(). A room will tell you what it can do. For an agent that is the difference between probing a surface by trying things and reading it.
WHAT MOVES BETWEEN THEM static - reads, spell status, and meld_existing_spell (REUSE of something already created; no creation, no topology) capability - all of that PLUS direct meld(), link/sever_link, create_lesser_conduit, and the cluster verbs (create/delete/join/leave/list)
Before you run๏
Use the Advanced guide for prerequisite concepts. Run from a checkout with Melder installed and Python 3.14 free-threading selected. The collection download includes the level's local helper modules.
Run the saved script๏
python UX_and_AIX_experiences/03_advanced/11_static_vs_capability_authority.py
py -3.14t UX_and_AIX_experiences/03_advanced/11_static_vs_capability_authority.py
Public surface๏
StaticCommandSystem vs CapabilityCommandSystem via room.command_system, list_supported_command_methods
Code๏
1"""
2TIER: advanced (11)
3GOAL: WHAT THE ROOM KIND ACTUALLY CHANGES.
4
5 StaticRiftSpace and CapabilityRiftSpace override exactly TWO
6 properties of RiftSpace, and they are the two that matter:
7
8 command_system StaticCommandSystem / CapabilityCommandSystem
9 frame_viewer StaticFrameViewer / FrameViewer
10
11 THE DOING ONE AND THE SEEING ONE. workstation, event_system and
12 memory_system are inherited unchanged, so the room's storage and
13 signalling are constant while its AUTHORITY and its VISIBILITY both
14 narrow together.
15
16 That pairing is the design. A room you may not mutate is also a
17 room that shows you less - and melder does it the same way twice,
18 by handing you a different class rather than guarding a shared one.
19
20 AND HERE IS THE DESIGN DECISION WORTH LEARNING FROM.
21
22 The static room does not REFUSE meld(). It does not raise
23 PermissionError, it does not check a flag, it does not consult an
24 ACL at call time. IT SIMPLY DOES NOT HAVE THE METHOD.
25
26 melder's own note on StaticCommandSystem says it outright:
27
28 "Does not expose topology mutation or direct meld(...) because
29 those methods now live on the capability surface INSTEAD OF
30 BEING DENIED AFTER INHERITANCE."
31
32 That is the opposite of the usual pattern, where a subclass inherits
33 everything and then overrides the dangerous half to raise. Melder
34 builds authority UP by class membership instead of tearing it DOWN
35 by guard.
36
37 WHY THAT IS BETTER, CONCRETELY:
38 - There is no refusal path, so there is no refusal path to test,
39 no error message to get subtly wrong, and no gap between "the
40 guard is there" and "the guard is correct".
41 - Capability becomes STATICALLY ENUMERABLE. You can answer "what
42 may this room do" without executing anything and without
43 triggering a single refusal.
44 - hasattr becomes an honest question again. In a deny-after-
45 inherit design it lies - the attribute is there and calling it
46 explodes.
47
48 THE AIX SURFACE
49 Both kinds expose list_supported_command_methods(). A room will tell
50 you what it can do. For an agent that is the difference between
51 probing a surface by trying things and reading it.
52
53 WHAT MOVES BETWEEN THEM
54 static - reads, spell status, and meld_existing_spell (REUSE of
55 something already created; no creation, no topology)
56 capability - all of that PLUS direct meld(), link/sever_link,
57 create_lesser_conduit, and the cluster verbs
58 (create/delete/join/leave/list)
59SURFACE EXERCISED: StaticCommandSystem vs CapabilityCommandSystem via
60 room.command_system, list_supported_command_methods
61VERIFY: rides the owner's 3.14t run; asserts are the contract.
62"""
63import melder as md
64
65
66def _room(nexus, space_type, name):
67 config = nexus.create_rift_configuration()
68 config.with_space_type(space_type)
69 rift = nexus.create_rift(configuration=config, rift_name=name)
70 rift.mark_active()
71 return rift.space
72
73
74def main() -> None:
75 nexus = md.Nexus()
76 system_config = nexus.create_configuration()
77 system_config.with_rift_creation_enabled(True)
78 nexus.activate(system_config)
79
80 static_room = _room(nexus, "static", "ops-static")
81 capability_room = _room(nexus, "capability", "ops-capability")
82
83 # The rooms themselves are different classes...
84 print("static room: ", type(static_room).__name__)
85 print("capability room:", type(capability_room).__name__)
86 assert type(static_room) is not type(capability_room)
87
88 # TWO fixtures differ - and they are the DOING one and the SEEING one.
89 static_commands = static_room.command_system
90 capability_commands = capability_room.command_system
91 print("static commands: ", type(static_commands).__name__)
92 print("capability commands:", type(capability_commands).__name__)
93 assert type(static_commands) is not type(capability_commands)
94
95 print("static viewer: ", type(static_room.frame_viewer).__name__)
96 print("capability viewer: ", type(capability_room.frame_viewer).__name__)
97 assert type(static_room.frame_viewer) is not type(
98 capability_room.frame_viewer)
99
100 # Everything else is the same class on both - inherited, untouched.
101 for fixture in ("workstation", "event_system", "memory_system"):
102 static_kind = type(getattr(static_room, fixture)).__name__
103 capability_kind = type(getattr(capability_room, fixture)).__name__
104 assert static_kind == capability_kind, fixture
105 print(f" {fixture:16s} same on both: {static_kind}")
106
107 # AUTHORITY BY ABSENCE. These are not refusals you catch - they are
108 # methods that were never put on the class.
109 mutating = ("meld", "link", "sever_link", "create_lesser_conduit",
110 "create_cluster", "delete_cluster", "join_cluster",
111 "leave_cluster")
112 print()
113 print("verb static capability")
114 for verb in mutating:
115 on_static = hasattr(static_commands, verb)
116 on_capability = hasattr(capability_commands, verb)
117 print(f" {verb:22s} {str(on_static):6s} {on_capability}")
118 assert on_static is False, f"static must not carry {verb}"
119 assert on_capability is True, f"capability must carry {verb}"
120
121 # REUSE IS NOT CREATION. The static room can meld something that
122 # already exists - it just cannot bring anything new into being.
123 assert hasattr(static_commands, "meld_existing_spell") is True
124 assert hasattr(capability_commands, "meld_existing_spell") is True
125 print()
126 print("meld_existing_spell on both: reuse is not creation")
127
128 # The shared read surface lives on the base and is present either way.
129 for shared in ("find_spell_id", "get_spell_permissions", "snapshot_state",
130 "describe_spells_in_conduit", "get_conduit_by_name"):
131 assert hasattr(static_commands, shared), shared
132 assert hasattr(capability_commands, shared), shared
133 print("shared read surface present on both")
134
135 # THE AIX DOOR. Ask the room what it can do rather than probing it.
136 static_verbs = static_commands.list_supported_command_methods()
137 capability_verbs = capability_commands.list_supported_command_methods()
138 print()
139 print("static supports ", len(static_verbs), "command methods")
140 print("capability supports", len(capability_verbs), "command methods")
141 assert len(capability_verbs) > len(static_verbs), (
142 "capability is the broader surface by construction"
143 )
144
145 print()
146 print("one property differs: command_system. that IS the room kind.")
147 print("authority is granted by class membership, never denied by guard")
148
149
150if __name__ == "__main__":
151 main()
Check the outcome๏
The script contains its own assertions or demonstrated refusal paths. Run it to evaluate those checks against your installed version. The code above is taken directly from the saved file; no run output is invented here.