c8e90daafb
Extends the existing build-and-resolve wiring suite rather than asserting over ServiceDescriptors, for the reason that file already documents: a registration can look correct as a descriptor list and still fail on first resolve. Role separation is pinned in both directions — central registers the hub's fail-closed interceptor and NOT the sweep, a site registers the sweep and NOT the hub — because only one of those is a security failure and testing the happy half would not catch it. The sweep is asserted by resolving IHostedService, which builds its whole graph (reader, keyed channel, local store) and is where a forgotten AddZbSecrets would surface; GrpcSecretSyncService is internal to the package, so it is matched by assembly + type name the way the SqlServer replicator's services already are. SqlServer mode gets regression pins with the mode key both unset and named explicitly, plus one asserting it stays role-agnostic — both nodes sync bidirectionally against the same database, and the role parameter added for the hub must not have quietly changed that. The mapping tests assert over the app's real endpoint data sources, on the WIRE route (/zb.mom.ww.secrets.hub.v1.SecretsHub/...) rather than the C# type, since the route is what a follower addresses. One of them pins exactly the two READ methods: pull-only is a property of the contract, and this is where a future package version growing a write RPC would become visible instead of silently opening a path for a site to overwrite central. Numeric mode values get their own test. Enum.TryParse accepts any integer, including ones outside the enum, so "7" would otherwise select a mode that does not exist and fall through to the SqlServer branch. Verified red-first by mutation on the finished implementation: swapping the two role branches reds 8 (both role pins, both fail-closed pins, both mapping pins); deleting the UsesGrpcHub check in the map extension reds exactly the two "maps no hub endpoint" cases — the unauthenticated-hub scenario; dropping Enum.IsDefined and letting UsesGrpcHub ignore Enabled reds the out-of-range value and the flag-off-with-full-hub-config cases. 31/31 green restored. Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1