fix(grpc): keep the RpcException off the failover warning so no sink can render Status.Detail

Review follow-ups: the warning now carries only the two endpoint URIs and the
status code — attaching the exception object would let any real sink render
its ToString(), which for RpcException includes server-authored Status.Detail.
The leak pin test now also asserts no exception rides on the warning, via a
new WarningExceptions capture on RecordingLogger. Plus two cosmetic nits:
unified ThrowIfNull idiom, documented that FallbackEndpoints mutation after
Validate is unsupported.

Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1
This commit is contained in:
Joseph Doherty
2026-08-07 09:49:45 -04:00
parent 0d4978953f
commit 7a2980e2f1
4 changed files with 29 additions and 8 deletions
@@ -175,6 +175,12 @@ public sealed class FailoverSecretsHubReaderTests
}
Assert.Equal(1, _logger.WarningCount);
// The exception object must not ride along either: sinks render an attached exception's
// ToString(), which for RpcException includes Status.Detail — the very text the message
// template deliberately excludes. A clean message with the exception attached would still
// leak in production, so the warning must carry NO exception at all.
Assert.All(_logger.WarningExceptions, Assert.Null);
}
[Fact]