Skip to content

Commit 6a2d419

Browse files
theoephraimclaude
andcommitted
fix varlock() prompt write-back and daemon spawn race conditions
- Fix regex in writeBackEncryptedValue to match any varlock() call, not just varlock(prompt), so prompt=1 works when a value already exists - Use singleton DaemonClient in prompt path to avoid redundant spawn attempts - Handle cross-process daemon spawn race by retrying connect on spawn failure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 04484dd commit 6a2d419

3 files changed

Lines changed: 12 additions & 5 deletions

File tree

packages/varlock/src/lib/local-encrypt/builtin-resolver.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type VarlockResolverState = {
2929
function writeBackEncryptedValue(itemKey: string, ciphertext: string, sourceFilePath: string | undefined) {
3030
if (!sourceFilePath) return;
3131
const currentContents = fs.readFileSync(sourceFilePath, 'utf-8');
32-
const pattern = new RegExp(`^(${escapeRegExp(itemKey)}\\s*=\\s*)varlock\\(prompt(?:=\\S*)?\\)`, 'm');
32+
const pattern = new RegExp(`^(${escapeRegExp(itemKey)}\\s*=\\s*)varlock\\([^)]*\\)`, 'm');
3333
const prefixedCiphertext = `${LOCAL_PREFIX}${ciphertext}`;
3434
const updatedContents = currentContents.replace(pattern, `$1varlock("${prefixedCiphertext}")`);
3535
if (updatedContents !== currentContents) {
@@ -105,8 +105,7 @@ export const VarlockResolver: typeof Resolver = createResolver<VarlockResolverSt
105105

106106
// Use daemon's native dialog on macOS Secure Enclave
107107
if (backend.type === 'secure-enclave' && backend.biometricAvailable) {
108-
const { DaemonClient } = await import('./daemon-client');
109-
const client = new DaemonClient();
108+
const client = localEncrypt.getDaemonClient();
110109
const ciphertext = await client.promptSecret({
111110
itemKey,
112111
message: `Enter the secret value for ${itemKey}:`,

packages/varlock/src/lib/local-encrypt/daemon-client.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,15 @@ export class DaemonClient {
8484
// Daemon not running, spawn it
8585
}
8686

87-
await this.spawnDaemon();
87+
try {
88+
await this.spawnDaemon();
89+
} catch {
90+
// Another process may have won the race to spawn the daemon.
91+
// Wait briefly for it to be ready, then try connecting.
92+
await new Promise<void>((r) => {
93+
setTimeout(r, 1000);
94+
});
95+
}
8896
await this.connectToSocket(socketPath);
8997
}
9098

packages/varlock/src/lib/local-encrypt/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export function getBackendInfo(): BackendInfo {
157157

158158
let daemonClient: DaemonClient | undefined;
159159

160-
function getDaemonClient(): DaemonClient {
160+
export function getDaemonClient(): DaemonClient {
161161
daemonClient ||= new DaemonClient();
162162
return daemonClient;
163163
}

0 commit comments

Comments
 (0)