From b4c3e224ace4f3fc40eace7b6d13e93fc47eac83 Mon Sep 17 00:00:00 2001 From: Nick Downs Date: Tue, 13 Oct 2026 08:47:27 -0700 Subject: [PATCH] feat(session): support HUNK_RUNTIME_DIR override --- .changeset/tidy-rivers-smile.md | 5 +++++ docs/session-broker-sdk.md | 5 +++-- packages/hunk/src/session/broker/brokerLauncher.ts | 2 +- .../hunk/src/session/broker/credentials.test.ts | 14 ++++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 .changeset/tidy-rivers-smile.md diff --git a/.changeset/tidy-rivers-smile.md b/.changeset/tidy-rivers-smile.md new file mode 100644 index 000000000..357fe9fa0 --- /dev/null +++ b/.changeset/tidy-rivers-smile.md @@ -0,0 +1,5 @@ +--- +"hunkdiff": minor +--- + +Add `HUNK_RUNTIME_DIR` as an override for session runtime state and credentials, ahead of `XDG_RUNTIME_DIR`. diff --git a/docs/session-broker-sdk.md b/docs/session-broker-sdk.md index 9a16a648c..ed3c642a8 100644 --- a/docs/session-broker-sdk.md +++ b/docs/session-broker-sdk.md @@ -583,8 +583,9 @@ of becoming a second restart owner. Daemons too old to retire while idle, or hun require manual termination. Preservation means paths, selectors, outputs, and automatic credential discovery for upgraded clients—not interoperability with pre-authentication binaries. -Hunk's fixed-endpoint Phase-1 credential store uses a home-local `.hunk` parent when -`XDG_RUNTIME_DIR` is unavailable, rather than a predictable name in a shared temporary directory. +Hunk's fixed-endpoint Phase-1 credential store uses `HUNK_RUNTIME_DIR` when set, then +`XDG_RUNTIME_DIR`, and otherwise a home-local `.hunk` parent rather than a predictable name in a +shared temporary directory. It inherits the current user's ACL when it creates the `hunk-mcp/security-v1` directory on Windows and rejects symbolic-link redirection. Node does not provide a portable owner/DACL or general reparse-point inspection API, so this integration cannot diff --git a/packages/hunk/src/session/broker/brokerLauncher.ts b/packages/hunk/src/session/broker/brokerLauncher.ts index aabf50fc4..9a31cf5c9 100644 --- a/packages/hunk/src/session/broker/brokerLauncher.ts +++ b/packages/hunk/src/session/broker/brokerLauncher.ts @@ -85,7 +85,7 @@ function safeRuntimeToken(value: string) { } function resolveRuntimeBaseDir(env: NodeJS.ProcessEnv = process.env) { - const configured = env.XDG_RUNTIME_DIR?.trim(); + const configured = env.HUNK_RUNTIME_DIR?.trim() || env.XDG_RUNTIME_DIR?.trim(); if (configured) return configured; // Unix temporary directories are commonly shared across users. Keep the fallback beneath the // current home directory instead of a predictable shared-/tmp name another account can pre-own. diff --git a/packages/hunk/src/session/broker/credentials.test.ts b/packages/hunk/src/session/broker/credentials.test.ts index 62b48cfb9..36cde5e71 100644 --- a/packages/hunk/src/session/broker/credentials.test.ts +++ b/packages/hunk/src/session/broker/credentials.test.ts @@ -46,6 +46,20 @@ describe("Hunk session broker credential store", () => { expect(callerFile).not.toContain("hunk-review-capability"); }); + test("uses HUNK_RUNTIME_DIR ahead of XDG_RUNTIME_DIR for credentials", async () => { + const env = isolatedEnv(); + const override = mkdtempSync(join(tmpdir(), "hunk-runtime-override-")); + roots.push(override); + env.HUNK_RUNTIME_DIR = override; + + await loadOrCreateHunkSessionBrokerCredentials({ env }); + + expect(lstatSync(join(override, "hunk-mcp", "security-v1", "caller.json")).isFile()).toBe( + true, + ); + expect(() => lstatSync(join(env.XDG_RUNTIME_DIR!, "hunk-mcp"))).toThrow(); + }); + test("adopts one complete winner under concurrent first use", async () => { const env = isolatedEnv(); const results = await Promise.all(