f10f4c3754
TelemetryStreamAuthInterceptor, ConfigServeAuthInterceptor and LocalDbSyncAuthInterceptor all decided "is a key configured?" with string.IsNullOrEmpty. A whitespace-only configured value therefore passed that guard and fell through to the constant-time comparison — where it is satisfied by a whitespace-only bearer token. The gate would be open to anyone who guessed a blank credential. This backports the check the two NEW mesh interceptors already use: MeshCommandAuthInterceptor (and its central-side clone) validate with string.IsNullOrWhiteSpace, so the four/five planes now answer the same way to the same misconfiguration. Nothing else changes — the denial status codes (PermissionDenied / Unauthenticated / PermissionDenied respectively) and every denial message are untouched, and no key material is logged. No deployment configures a whitespace key: the docker-dev rig and production both set real keys, so this is a fail-closed hardening of an unreachable-today misconfiguration rather than a live exposure. Tests: each of the three test files gains a ..._WithBlankKeyConfigured_IsDenied fact mirroring MeshCommandAuthInterceptorTests.ExecuteMethod_WithBlankPskConfigured_IsDenied (configured key " ", presented "Bearer "), verified red before the fix. ConfigServeAuthInterceptor and LocalDbSyncAuthInterceptor also gain the HasExactlyOnePublicConstructor pin their two siblings already had — Grpc.AspNetCore silently stops invoking an interceptor with more than one public constructor, which would disable auth without failing anything. Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1