abc58e6394fcec9e610784a97616b31cc8a17704
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f6c3f7c593 |
test(secrets): live gate 4/4 — check 4 re-run and PASSES on 0.4.1
Second pass on the 0.4.1 image, from a clean start with zero denial warnings on central-a. Both auth negatives are still refused with a byte-identical Unauthenticated status and detail - 0.4.1 changed what the server writes down, not what a caller sees - and the no-bearer call now produces a WRN in the same second it is refused, with the cause attributed. No interval has to elapse for the first denial to be visible, which is the whole point: a follower with a mis-rotated token is refused on every sweep, and central now says so immediately. The rate limit was proven to DEFER rather than drop, not assumed to. The wrong-bearer call one second later fell inside the 60 s window and produced no line of its own; the window was waited out and one further wrong-bearer call issued, whose summary reported TWO wrong-credential denials - the deferred one plus the new one. Summing the two lines gives exactly the three negatives issued, correctly attributed by cause. N is a per-window delta, so a reader must sum the lines rather than quote the last one; that is recorded as a follow-up because it is the kind of thing an alert gets wrong. Log hygiene re-run fleet-wide and widened: all eight nodes' docker logs and every on-disk Serilog file were grepped for the dev token, the dev KEK, all three secret plaintexts AND both wrong tokens the negatives presented. Zero hits everywhere. The presented-credential check is deliberate - echoing a rejected credential back into a log is its own leak and a free oracle, and the new warning counts denials by cause without carrying any credential material. Checks 2 and 3 were not repeated: 0.4.1 touches the hub's denial logging and nothing else - no wire change, no store change, no sweep change. Convergence was re-smoked instead so the new image is not merely assumed to replicate: a fresh secret reached both followers in 17 s, byte-identical and decrypt-verified on both, and the first pass's live secret and tombstone survived the image swap unchanged on all three nodes. The first-pass FAIL evidence is kept intact rather than overwritten. The fix only means anything against the failure it answers, and a gate doc that shows only the green run cannot be audited. Residuals stand as recorded: the hub client dials a single endpoint with no failover, and the central pair does not converge with itself - central-b answered an authenticated GetManifest with an empty manifest for the whole run. Those are one question, not two. 4/4. Merging. Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1 |
||
|
|
9d5cf7100e |
test(secrets): live gate for the gRPC secrets hub — 3/4 PASS, not merged
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 |