From 582a256ef346b3be8f7e81ff9e2722eae5831ba0 Mon Sep 17 00:00:00 2001 From: David McFadzean Date: Mon, 16 Mar 2026 14:26:57 -0400 Subject: [PATCH 1/2] fix: Persist passphrase and state in chrome.storage.session Move passphrase and extensionState from in-memory variables to chrome.storage.session so they survive MV3 service worker restarts. Session storage is automatically cleared when the browser closes, maintaining the same security model as before. Closes #221 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/background/background.ts | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/apps/browser-extension/src/background/background.ts b/apps/browser-extension/src/background/background.ts index 753bdbb0..b0e80aaa 100644 --- a/apps/browser-extension/src/background/background.ts +++ b/apps/browser-extension/src/background/background.ts @@ -11,8 +11,27 @@ interface PendingNostrRequest { const pendingNostrRequests = new Map(); -let passphrase: string | null = null; -const extensionState: Record = {}; +async function getPassphrase(): Promise { + const result = await chrome.storage.session.get("passphrase"); + return (result.passphrase as string) ?? null; +} + +async function setPassphrase(value: string | null): Promise { + if (value === null) { + await chrome.storage.session.remove("passphrase"); + } else { + await chrome.storage.session.set({ passphrase: value }); + } +} + +async function getExtensionState(): Promise> { + const result = await chrome.storage.session.get("extensionState"); + return (result.extensionState as Record) ?? {}; +} + +async function setExtensionState(state: Record): Promise { + await chrome.storage.session.set({ extensionState: state }); +} async function getApprovedNostrOrigins(): Promise { const { approvedNostrOrigins = [] } = await chrome.storage.session.get("approvedNostrOrigins"); @@ -122,26 +141,25 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { sendResponse({ error: "Request not found" }); } } else if (message.action === "STORE_PASSPHRASE") { - passphrase = message.passphrase; - sendResponse({ success: true }); + setPassphrase(message.passphrase).then(() => sendResponse({ success: true })); } else if (message.action === "GET_PASSPHRASE") { - sendResponse({ passphrase }); + getPassphrase().then((passphrase) => sendResponse({ passphrase })); } else if (message.action === "CLEAR_PASSPHRASE") { - passphrase = null; - sendResponse({ success: true }); + setPassphrase(null).then(() => sendResponse({ success: true })); } else if (message.action === "STORE_STATE") { - extensionState[message.key] = message.value; - sendResponse({ success: true }); + getExtensionState().then((state) => { + state[message.key] = message.value; + setExtensionState(state).then(() => sendResponse({ success: true })); + }); } else if (message.action === "GET_ALL_STATE") { - sendResponse({ extensionState }); + getExtensionState().then((extensionState) => sendResponse({ extensionState })); } else if (message.action === "CLEAR_ALL_STATE") { - for (const key in extensionState) { - delete extensionState[key]; - } - sendResponse({ success: true }); + setExtensionState({}).then(() => sendResponse({ success: true })); } else if (message.action === "CLEAR_STATE") { - delete extensionState[message.key]; - sendResponse({ success: true }); + getExtensionState().then((state) => { + delete state[message.key]; + setExtensionState(state).then(() => sendResponse({ success: true })); + }); } return true; From 87f871369e691f7fabd99aaf095c7fccc2245871 Mon Sep 17 00:00:00 2001 From: David McFadzean Date: Mon, 16 Mar 2026 20:04:19 -0400 Subject: [PATCH 2/2] fix: Expose Tor SOCKS proxy port to host Add port mapping for the Tor SOCKS proxy (9050) so it can be used from the host for testing onion connectivity. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.drawbridge.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.drawbridge.yml b/docker-compose.drawbridge.yml index 0c9b3ae4..4d89f8bc 100644 --- a/docker-compose.drawbridge.yml +++ b/docker-compose.drawbridge.yml @@ -56,6 +56,8 @@ services: tor: image: goldy/tor-hidden-service:latest + ports: + - "${ARCHON_TOR_SOCKS_PORT:-9050}:9050" environment: DRAWBRIDGE_TOR_SERVICE_HOSTS: '4222:drawbridge:4222' DRAWBRIDGE_TOR_SERVICE_VERSION: '3'