Skip to content

Commit bc06e18

Browse files
thymikeeclaude
andcommitted
fix(host): answer review of the platform host environment change
Redaction patterns come from the command host, the maestro child reads its own environment without a working-directory lookup, local ~ install sources expand against the host environment, and the runner launch resolves its host inside the try that closes its log descriptor. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
1 parent 57ba4cd commit bc06e18

7 files changed

Lines changed: 36 additions & 12 deletions

File tree

‎packages/capture-kit/src/recording/swift-cache.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ export function buildRecordingScriptPathCandidates(
4242

4343
/**
4444
* Resolves one recording helper script: checkout, built package, or working-directory fallback.
45-
* The caller names the project root it trusts, so this module stays free of host metadata lookup.
45+
* The caller names the project root it trusts, so this module stays free of host metadata lookup;
46+
* the working directory defaults to the command host's.
4647
*/
4748
export function resolveRecordingScriptPath(
4849
scriptName: string,

‎packages/daemon/src/server/http/http-server-proxy.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ test('proxy enforces public-only Maestro HTTP policy on a local daemon', async (
190190
headers: {},
191191
publicNetworkOnly: request.internal?.publicNetworkOnly === true,
192192
},
193-
process.env,
193+
env,
194194
),
195195
};
196196
},

‎packages/maestro/src/daemon-port/run-script-http-child.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { readFileSync } from 'node:fs';
22
import { pathToFileURL } from 'node:url';
3-
import { captureHostEnvironment } from '@agent-device/host-kit/process';
43
import type { RunScriptHttpRequest } from './run-script-http.ts';
54
import { executeRunScriptHttpRequest } from './run-script-http.ts';
65

76
export async function runScriptHttpChild(): Promise<void> {
87
const response = await executeRunScriptHttpRequest(
98
JSON.parse(readFileSync(0, 'utf8')) as RunScriptHttpRequest,
10-
captureHostEnvironment(process).env,
9+
process.env,
1110
);
1211
process.stdout.write(JSON.stringify(response));
1312
}

‎packages/platform-apple/src/runner/runner-process-launch.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ export function launchRunnerProcess(input: LaunchRunnerProcessInput): LaunchedRu
5959
} catch {}
6060
});
6161
const listenerReady = createRunnerListenerReadySignal();
62-
// The runner outlives this process, so it gets its environment and directory as plain values.
63-
const { env, cwd } = commandHostEnvironment();
6462
try {
63+
// The runner outlives this process, so it gets its environment and directory as plain values.
64+
const { env, cwd } = commandHostEnvironment();
6565
const launched = runCmdBackground(
6666
'xcodebuild',
6767
[

‎packages/provision-kit/src/install-source.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ export async function materializeInstallablePath(
8484
}
8585
}
8686

87-
function expandSourcePath(inputPath: string): string {
88-
return expandUserHomePath(inputPath);
87+
function expandSourcePath(inputPath: string, env: NodeJS.ProcessEnv): string {
88+
return expandUserHomePath(inputPath, { env });
8989
}
9090

9191
async function materializeLocalSource(
@@ -94,7 +94,7 @@ async function materializeLocalSource(
9494
): Promise<MaterializeLocalSourceResult> {
9595
if (source.kind === 'path') {
9696
return {
97-
localPath: expandSourcePath(source.path),
97+
localPath: expandSourcePath(source.path, options.environment),
9898
cleanup: async () => {},
9999
};
100100
}

‎src/platform-runtime-app-log-output.test.ts‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fs from 'node:fs';
22

33
import path from 'node:path';
4+
import { withCommandHost } from '@agent-device/host-kit/command';
45
import { afterEach, expect, test } from 'vitest';
56
import { openAppLogOutput, readAppLogOutputTail } from './platform-runtime-app-log-output.ts';
67
import { bindTestCommandHost, mkdtempForTestSync } from '@agent-device/test-kit';
@@ -94,3 +95,25 @@ function finalSymlinkFixture(label: string) {
9495
fs.symlinkSync(outsidePath, outputPath);
9596
return { sessionsDir, outputPath, outsidePath };
9697
}
98+
99+
test('redacts with the patterns of the command host, not the process', async () => {
100+
const root = mkdtempForTestSync('agent-device-app-log-redact-');
101+
roots.push(root);
102+
const sessionsDir = path.join(root, 'sessions');
103+
const outputPath = path.join(sessionsDir, 'one', 'app.log');
104+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
105+
106+
await withCommandHost(
107+
{
108+
host: { env: { AGENT_DEVICE_APP_LOG_REDACT_PATTERNS: 'secret-\\d+' }, cwd: root },
109+
requestEnv: undefined,
110+
},
111+
async () => {
112+
const sink = await openAppLogOutput(sessionsDir, outputPath);
113+
await sink.write('token secret-42 leaked\n');
114+
await sink[Symbol.asyncDispose]();
115+
},
116+
);
117+
118+
expect(fs.readFileSync(outputPath, 'utf8')).toBe('token [REDACTED] leaked\n');
119+
});

‎src/platform-runtime-app-log-output.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export async function openAppLogOutput(
2323
stream.on('error', (error) => {
2424
streamError ??= error;
2525
});
26-
const patterns = redactionPatterns();
26+
const { env } = commandHostEnvironment();
27+
const patterns = redactionPatterns(env);
2728
let pending = '';
2829
let writes = Promise.resolve();
2930
let disposal: Promise<void> | undefined;
@@ -90,8 +91,8 @@ function requireManagedOutputPath(sessionsDir: string, pathname: string): string
9091
});
9192
}
9293

93-
function redactionPatterns(): RegExp[] {
94-
return (process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS ?? '')
94+
function redactionPatterns(env: NodeJS.ProcessEnv): RegExp[] {
95+
return (env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS ?? '')
9596
.split(',')
9697
.map((part) => part.trim())
9798
.filter(Boolean)

0 commit comments

Comments
 (0)