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

Download this collection ยท Source on GitHub

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.

More advanced examples ยท Level guide