(public) join_group accepts an optional organizationUid. When the device sends it, it becomes the group prefix directly and neither Redis nor MongoDB is consulted — the lookup only runs for clients that don't. No deployed client sends it yet; docs/organization-scoping.md has what core and front-display need to implement.
(internal) Redis read-through cache (redis_dsn, required) in front of the deviceUid → organizationUid lookup that scopes sync groups, so it no longer queries MongoDB on every join_group. 6 h ±10 % TTL, negative caching for devices the database doesn't know, and concurrent joins of the same device share a single query — a reconnect storm no longer becomes a query storm. See docs/organization-scoping.md.
(internal) Prometheus metrics for organization resolution (sos_applet_synchronizer_organization_*): un-namespaced joins, resolution failures by reason, cache hits/misses/errors, database queries and the ones shared between concurrent joins. Resolution fails open silently, so organization_unprefixed_resolutions_total is the signal that group scoping is degraded — alert on it.
(public) GET /alive (liveness) and GET /ready (readiness) probes. /ready answers 503 until the socket handlers are attached — until then the port accepts connections no handler would answer. Neither checks MongoDB or Redis: /ready reports their state in its body only, because the service synchronizes without them. /status is unchanged.
(public) Configuration option allowSlaveBroadcast to allow slave devices to broadcast values to all devices in a group via update_sync_config event.
(public) Observability endpoints GET /dashboard (+ /dashboard/view) and GET /metrics (Prometheus, sos_applet_synchronizer_ prefix) surfacing sync counters, barrier fill latency, connected peers/active groups and duplicate-deviceIdentification group collisions.
(public) A group whose last peers disconnect simultaneously no longer throws an uncaught TypeError from the barrier's master lookup (see public/CHANGELOG.md), which left stale pending requests behind and skipped the device_status update to the surviving peers.
(public) join_group is now always acknowledged, so a server-side failure can no longer leave a device waiting indefinitely for an answer that never comes.
(internal) A join is no longer rejected when the organization cannot be resolved. Previously a device missing from the database failed with Device not found, and a slow or unavailable MongoDB blocked the join. Resolution now fails open to an un-prefixed group, so synchronization keeps working when the databases don't — at the cost of groups not being namespaced by organization until they recover.
(internal) Startup no longer blocks on MongoDB or Redis being reachable (5 s bound, then it serves anyway and the clients reconnect in the background), and shutdown no longer closes either connection twice.
(public) Evict empty sync groups from memory so the dashboard, metrics and the periodic status tick do not accumulate dead groups.
(public) Emit device_status on device disconnect for organization-prefixed groups.
(public) Register a joining peer only when deviceIdentification is provided (the guard was always true before).
(public) Handle leave_group on the server so client leaveGroup() acks instead of hanging.
(public) Picking master device in the group based on deviceIdentification alphabetical order instead of the device creation date (keep the logic same with client - front-display).