StaticdefaultStaticemitEmit payload for name. Permission gate fires synchronously
(a denied caller throws SecurityError immediately). Listeners
fire on the next microtask in a fresh EventDispatch frame
each. Pre-bootstrap emits are silently dropped.
StaticemittableBuild an access-check function for an event property. Two checks:
setProp/getProp on the registry must have come
via EventApi. Even if a caller gets the registry instance and
tries to call setProp directly, this rejects the bypass.Set (emit), the originating caller's class
must be in allowed. Get (subscribe) is open by default
because a subscriber has no privilege to leak; tighten with
EventApi.eventPolicy({ emit, subscribe }) if a specific
event needs it.Stack-walks so intervening frames (e.g. PropertiedMixin's own
checkAccess proxy mediation) don't break the check.
StaticeventCompanion to emittableBy for events that want to gate subscribe
(Get) too. Composes both checks; pass null for either side to
leave it open.
StaticfireStatichistoryRecent emitted payloads for name, newest last. Bounded ring
buffer; older entries roll off after HISTORY_LIMIT emits.
Optionallimit: numberStaticonRegister a listener for name. Returns a Subscription whose
unsubscribe() removes it from the side-table.
Optionalopts: SubscribeOptions<BusEvent<PayloadOf<E>>>Register a listener for name. Returns a Subscription whose
unsubscribe() removes it from the side-table.
Optionalopts: SubscribeOptions<T>StaticonceStaticrestrictRestrict the receive (subscribe) side of an event to an allowlist
of consumer classes — the first use of the EventRegistry prop-access
apparatus's Get half. Emit stays open (emit: []); only the listed
classes may EventApi.on(name, …). Everyone else's subscribe throws.
For sensitive activity taps whose payload carries a per-actor id
(comm.received, reaction.fired, command.dispatched): broadcasting
those on the open-subscribe bus would let any mudlib subscriber snoop a
player's command/utterance cadence. Locking subscribe to the single
blessed consumer closes that side-channel while keeping the bus's
producer-ignorant decoupling.
Call from the consumer's tap-install (with the consumer's own class) so the policy is in place before the first subscribe, and re-asserts after a hot-reload (the reloaded install passes the reloaded class). Ownership is tracked by class name: a same-named reload re-asserts; a different class is refused (no hijacking another consumer's tap).
Resolve the default policy for an event name. Falls back to a permissive (no-allowlist)
emittableBy()for unknown names so a custom event registered ad-hoc still gets the EventApi-mediated defense without requiring the well-known map to be edited.The policy table is lazily initialised on first call so we don't run
emittableBy(...)at module-top:api/eventparticipates in a cycle withlib/events(the event vocabulary) andapi/stuff(the StuffApi binding the policy references). Deferring the table construction to first-call avoids resolving partial modules.