one sudo call for both agent-status answers, not two

host's finding on 6b7aad91. claudeLoginState ran two `runAs` probes in parallel,
and each is a `sudo -n setpriv` fork/exec that writes a line to
/var/log/auth.log. It is reached from /agent-status, which sits on a grant every
role holds by default, so a polling UI would have cost two sudo spawns and two
auth-log lines per poll per member — cheap individually, unbounded in aggregate,
and the auth log is where a real sudo event has to stay visible.

One call answering both questions with markers instead of two exit codes. Did
not take his second suggestion of caching `installed`: one call per request is
cheap enough that a second mechanism with its own invalidation is the worse
trade, and that judgement is recorded in COMMS so a polling UI can revisit it.

Also carries the verify list he asked for, including the pertento host key I
accepted on first use so git could reach his remote — he can compare it against
the server, which I cannot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 22:14:21 +00:00
co-authored by Claude Opus 5
parent f4dc46d67a
commit 288679af09
2 changed files with 92 additions and 4 deletions
+16 -4
View File
@@ -111,9 +111,21 @@ export type ClaudeLoginState = {
* saying nothing about whether the account that needs it can see it.
*/
export async function claudeLoginState(params: { email: string; osUser: string }): Promise<ClaudeLoginState> {
const [installed, loggedIn] = await Promise.all([
asMember(params.osUser, ['test', '-x', claudeBinPath(params.email)]),
asMember(params.osUser, ['test', '-s', credentialsPath(params.email)]),
// One `runAs` for both answers, not two. Each is a `sudo -n setpriv` fork/exec that writes a line to
// `/var/log/auth.log`, and this is reached from `/agent-status`, which sits on a grant every role has by
// default — so a UI that polls it would otherwise cost two sudo spawns and two auth-log lines per poll, per
// member. Individually cheap, unbounded in aggregate, and the auth log is where a real sudo event has to
// stay visible.
//
// Markers rather than an exit code because one call now answers two questions. `-x` follows symlinks, which
// is what the installer produces: a link into a versioned directory, not a file.
const probe = await asMember(params.osUser, [
'sh',
'-c',
'test -x "$1" && printf bin; test -s "$2" && printf cred',
'_',
claudeBinPath(params.email),
credentialsPath(params.email),
]);
return { installed: installed.ok, loggedIn: loggedIn.ok };
return { installed: probe.out.includes('bin'), loggedIn: probe.out.includes('cred') };
}