9d5cf7100e
Rig config enabling the pull-only hub on the docker cluster (central pair hosts, site-a pair follows; site-b and site-c deliberately left off so the default-OFF posture is proven side by side), plus the gate record. Checks 1-3 PASS. A central write reaches both site-a nodes in 5 s with a byte-identical ciphertext row and decrypts correctly on both; a site pair boots and serves its full last-known-good store with the entire central pair stopped, warning once per interval without crashing, and resumes convergence unaided when central returns; a tombstone propagates in under 9 s and survives a pair restart with central up and sweeping, without resurrecting. Check 4 FAILS one clause of three. Both auth negatives - absent bearer and wrong bearer - are denied with a byte-identical Unauthenticated status and detail, and a fleet-wide grep of all eight nodes' docker logs and on-disk Serilog files finds ZERO occurrences of the dev token, the dev KEK or either plaintext. But the criterion also asks for a server-side WARNING on denial, and there is none: the only record is one Information line per call from Grpc.AspNetCore.Server, because SecretsHubAuthInterceptor deliberately logs nothing on a denial and warns only when no token is configured at all. That is a property of the 0.4.0 library, not of this branch, and it is not patched here - a host-side interceptor would contradict a documented library decision at the wrong layer and put an unbounded log write on an unauthenticated endpoint. The merge condition is 4/4, so this branch is NOT merged. The library's denial logging is the only thing between this result and a merge. Two residuals worth carrying: the hub client dials a single endpoint and does not fail over (observed live, and contrasted against CentralGrpcEndpoints failing over on the same node in the same minute), and the central pair does not converge with itself - central-b answered an authenticated GetManifest with an empty manifest for the whole run while central-a held both secrets. Together those make "which central node is authoritative for secrets" one question, not two. Rig config notes: Secrets__SqlitePath points at /app/data because the appsettings default resolves to /app inside the image's writable layer, so the central pair gained the per-node data volume the site pairs already had. All values are dev-only and committed under the same exception the mesh PSKs already use. Also recorded: a gate-METHOD defect. Seeding the bind-mounted store from the macOS host is not coherent with the running container - the row was visible to the host and to a fresh container but never to the node, and was lost outright on restart. Every store access was redone from a throwaway container. The failure mode is a convincing false negative that looks exactly like a broken hub. Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1