#185 stage 2: gap detector must not report on the wrong environment #212

Closed
agent wants to merge 0 commits from worker/cb185-hostenvnames-2692b5-3 into main
Member

Implements stage 2 of fleetd issue #185.

When memberHerdrSocket: is configured, member panes run under a different OS user than fleetd's own process. HerdrPeerLauncher.hostEnvNames enumerates fleetd's OWN environment (there is no channel to read the member herdr's), so the CB-596 credential-gap detector (logCredentialGap) was reporting conclusions ('every member pane inherits them UNBLOCKED' / 'the scrub blanks them') that describe the wrong process once that config key is set.

Fix: logCredentialGap now checks memberHerdrSocketConfigured() first. When set, it logs a single WARN, once per launcher instance, naming the config key and stating the honest conclusion: the credential gap for member panes is UNKNOWN, not clean, and memberCredentials cannot be verified from this daemon. The one count it reports is scoped explicitly ('N of the M names in fleetd's own environment'). When the key is absent (today's only mode, the default), behaviour is byte-identical -- no log line on that path changed.

Tests added to HerdrPeerLauncherAllowListWiringTest:

  • gapConclusionsAreByteIdenticalWhenMemberHerdrSocketIsAbsent -- pins the exact pre-existing WARN/INFO text.
  • gapDetectorReportsUnknownInsteadOfAConclusionWhenMemberHerdrSocketIsConfigured -- the new WARN fires; the old conclusions do not.
  • theUnknownEnvironmentWarnFiresOnceNotOncePerSpawn -- fires once per launcher instance across two spawns.
  • theGapDetectorNeverLogsAnEnvVarValueOnlyItsName -- a canary VALUE resolvable for a credential-shaped NAME never reaches the log, only the NAME does.

Watched the two memberHerdrSocket-dependent tests fail red with the fix commented out, then restored and confirmed green (see PR description / worker report for the captured failure output).

mvn clean install from fleetd/: Tests run: 1065, Failures: 0, Errors: 0, Skipped: 0 -- BUILD SUCCESS.

Implements stage 2 of fleetd issue #185. When `memberHerdrSocket:` is configured, member panes run under a different OS user than fleetd's own process. `HerdrPeerLauncher.hostEnvNames` enumerates fleetd's OWN environment (there is no channel to read the member herdr's), so the CB-596 credential-gap detector (`logCredentialGap`) was reporting conclusions ('every member pane inherits them UNBLOCKED' / 'the scrub blanks them') that describe the wrong process once that config key is set. Fix: `logCredentialGap` now checks `memberHerdrSocketConfigured()` first. When set, it logs a single WARN, once per launcher instance, naming the config key and stating the honest conclusion: the credential gap for member panes is UNKNOWN, not clean, and `memberCredentials` cannot be verified from this daemon. The one count it reports is scoped explicitly ('N of the M names in fleetd's own environment'). When the key is absent (today's only mode, the default), behaviour is byte-identical -- no log line on that path changed. Tests added to `HerdrPeerLauncherAllowListWiringTest`: - `gapConclusionsAreByteIdenticalWhenMemberHerdrSocketIsAbsent` -- pins the exact pre-existing WARN/INFO text. - `gapDetectorReportsUnknownInsteadOfAConclusionWhenMemberHerdrSocketIsConfigured` -- the new WARN fires; the old conclusions do not. - `theUnknownEnvironmentWarnFiresOnceNotOncePerSpawn` -- fires once per launcher instance across two spawns. - `theGapDetectorNeverLogsAnEnvVarValueOnlyItsName` -- a canary VALUE resolvable for a credential-shaped NAME never reaches the log, only the NAME does. Watched the two memberHerdrSocket-dependent tests fail red with the fix commented out, then restored and confirmed green (see PR description / worker report for the captured failure output). `mvn clean install` from `fleetd/`: Tests run: 1065, Failures: 0, Errors: 0, Skipped: 0 -- BUILD SUCCESS.
agent added 1 commit 2026-08-31 17:13:32 +02:00
#185 stage 2: stop the credential-gap detector reporting on the wrong environment
CI / contract (pull_request) Successful in 54s
CI / build (pull_request) Successful in 1m39s
847e8bd3fa
When memberHerdrSocket: is configured, member panes run under a different OS
user than fleetd's own process, so hostEnvNames (fleetd's own environment)
no longer describes what a member pane inherits. logCredentialGap now checks
for that config key and, when set, logs a single WARN saying the gap is
UNKNOWN (not clean) and names the key, instead of printing the "inherits
them UNBLOCKED" / "the scrub blanks them" conclusions as fact. Behaviour is
byte-identical when memberHerdrSocket is absent (the default and only mode
this host runs).
Owner

Merged to main in 457dc03. Full suite on merged main: 1065 tests, 0 failures, BUILD SUCCESS.

Reviewed the diff and it does what the brief asked: the new branch is an early return gated on memberHerdrSocketConfigured(), so the default path (memberHerdrSocket: absent — the only mode this host runs) is untouched, and that is pinned char-for-char by gapConclusionsAreByteIdenticalWhenMemberHerdrSocketIsAbsent. The WARN names the config key, states "unknown, not clean", and scopes its count explicitly to fleetd's own environment.

Both judgement calls in the report were right:

  • Firing the WARN regardless of whether fleetd's own env happens to show a local gap. "Unknown" is true either way, and staying silent when the local gap is empty would be the misleading case.
  • Leaving logAllowListCoverage alone. It is a different log site and already carries its own denominator.

The out-of-scope finding was the valuable part of this delivery, so thank you for noting it rather than fixing it. I checked it and it is real, plus a second independent problem in the same method — filed as #213. In short: applyEnvironmentAllowListPolicy reads fleetd's own $SHELL to decide whether the ZDOTDIR scrub can run, and generates that scrub into fleetd's own java.io.tmpdir, which on macOS is a per-user 0700 directory another uid cannot even traverse. So in two-user mode the zsh branch can be taken while nothing scrubs and no sentinel overlay is applied either — the control reports success and does nothing. Not live (no memberHerdrSocket: on this host), but a blocker for the stage 4 rollout.

Merged to `main` in `457dc03`. Full suite on merged main: 1065 tests, 0 failures, BUILD SUCCESS. Reviewed the diff and it does what the brief asked: the new branch is an early return gated on `memberHerdrSocketConfigured()`, so the default path (`memberHerdrSocket:` absent — the only mode this host runs) is untouched, and that is pinned char-for-char by `gapConclusionsAreByteIdenticalWhenMemberHerdrSocketIsAbsent`. The WARN names the config key, states "unknown, not clean", and scopes its count explicitly to fleetd's own environment. Both judgement calls in the report were right: - Firing the WARN regardless of whether fleetd's own env happens to show a local gap. "Unknown" is true either way, and staying silent when the local gap is empty would be the misleading case. - Leaving `logAllowListCoverage` alone. It is a different log site and already carries its own denominator. The out-of-scope finding was the valuable part of this delivery, so thank you for noting it rather than fixing it. I checked it and it is real, plus a second independent problem in the same method — filed as **#213**. In short: `applyEnvironmentAllowListPolicy` reads fleetd's own `$SHELL` to decide whether the ZDOTDIR scrub can run, and generates that scrub into fleetd's own `java.io.tmpdir`, which on macOS is a per-user `0700` directory another uid cannot even traverse. So in two-user mode the zsh branch can be taken while nothing scrubs and no sentinel overlay is applied either — the control reports success and does nothing. Not live (no `memberHerdrSocket:` on this host), but a blocker for the stage 4 rollout.
ltms closed this pull request 2026-08-31 17:19:56 +02:00
Some checks are pending
CI / contract (pull_request) Successful in 54s
CI / build (pull_request) Successful in 1m39s

Pull request closed

Sign in to join this conversation.