Backend-initiated broadcast notification plumbing — generic across consumers.
Builds a typed {method_name: (input) => Promise<void>} object from a list
of action specs. Each call validates input against the spec, wraps it in a
JSON-RPC notification, and either broadcasts to every connection or
fans out with a per-connection ACL predicate.
Counterpart to register_action_ws: that handles request-scoped dispatch
(frontend-initiated), this handles broadcast (backend-initiated). Together
they cover the two primitives fuz_app consumers share. Request-scoped
streaming (completion_progress, zap_apply events) stays on
ctx.notify inside a handler — it's socket-scoped, not broadcast.
Extracted from zzz's backend_actions_api.ts to stop the pattern from
drifting across consumers.