Symptom

Feature, not a bug: users need to stop a server from auto-joining the swarm. Building it surfaced a latent defect — the server’s beacon listener could not actually be stopped.

Root cause

ServerMetaData.beaconsEnabled (SDK 0.0.52) gives the setting a home, but the JVM Multicast.receiveBeacons launched its receive loop in a detached SupervisorJob scope. Cancelling the supervisor’s listener job never reached that scope, so the socket stayed bound and kept responding — there was no way to “shut down all beacon processes.” Separately, ServerServerProcessor started beacons unconditionally at startup and nothing reacted to a live beaconsEnabled edit (meta-only CRUD updates don’t wake processors).

Fix

Prevention

A background loop that owns an OS resource (socket, file handle) must run structured under a cancellable job — never a detached SupervisorJob — or it can never be torn down. New env-dependent server units (ServerServerProcessor, BeaconSettingsTask) take a selfId: () -> String seam instead of calling installId(), so they are unit-testable without the real ~/.krill/install_id. Socket-level behavior stays out of unit tests (the port-bind/network ban); it is covered by the supervisor job-lifecycle test plus QA on real hardware.