From fde278d5b55bf98b5cad16888b264cdc66020015 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 28 Feb 2025 11:15:42 +0000
Subject: [PATCH 1/5] Leverage electron-builder to build keytar rather than hak

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
 electron-builder.ts    |   3 +
 hak/keytar/build.ts    |  26 --------
 hak/keytar/check.ts    |  15 -----
 hak/keytar/hak.json    |  10 ---
 package.json           |   7 +-
 src/@types/keytar.d.ts |  54 ---------------
 src/electron-main.ts   |   1 -
 src/ipc.ts             |   2 +-
 src/keytar.ts          |  21 ------
 src/seshat.ts          |   2 +-
 yarn.lock              | 148 ++++++++++++++++++++++++++++++++++++++---
 11 files changed, 147 insertions(+), 142 deletions(-)
 delete mode 100644 hak/keytar/build.ts
 delete mode 100644 hak/keytar/check.ts
 delete mode 100644 hak/keytar/hak.json
 delete mode 100644 src/@types/keytar.d.ts
 delete mode 100644 src/keytar.ts

diff --git a/electron-builder.ts b/electron-builder.ts
index abf0ca63..660721d1 100644
--- a/electron-builder.ts
+++ b/electron-builder.ts
@@ -174,6 +174,9 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
             schemes: ["io.element.desktop", "element"],
         },
     ],
+    nativeRebuilder: "sequential",
+    nodeGypRebuild: false,
+    npmRebuild: true,
 };
 
 /**
diff --git a/hak/keytar/build.ts b/hak/keytar/build.ts
deleted file mode 100644
index b3495969..00000000
--- a/hak/keytar/build.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Copyright 2024 New Vector Ltd.
-Copyright 2020 The Matrix.org Foundation C.I.C.
-
-SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
-Please see LICENSE files in the repository root for full details.
-*/
-
-import path from "node:path";
-
-import type HakEnv from "../../scripts/hak/hakEnv.js";
-import type { DependencyInfo } from "../../scripts/hak/dep.js";
-
-export default async function buildKeytar(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
-    const env = hakEnv.makeGypEnv();
-
-    console.log("Running yarn with env", env);
-    await hakEnv.spawn(
-        path.join(moduleInfo.nodeModuleBinDir, "node-gyp"),
-        ["rebuild", "--arch", hakEnv.getTargetArch()],
-        {
-            cwd: moduleInfo.moduleBuildDir,
-            env,
-        },
-    );
-}
diff --git a/hak/keytar/check.ts b/hak/keytar/check.ts
deleted file mode 100644
index 3ced7f8a..00000000
--- a/hak/keytar/check.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-Copyright 2024 New Vector Ltd.
-Copyright 2020 The Matrix.org Foundation C.I.C.
-
-SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
-Please see LICENSE files in the repository root for full details.
-*/
-
-import type HakEnv from "../../scripts/hak/hakEnv.js";
-import type { DependencyInfo } from "../../scripts/hak/dep.js";
-
-export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
-    // node-gyp uses python for reasons beyond comprehension
-    await hakEnv.checkTools([["python", "--version"]]);
-}
diff --git a/hak/keytar/hak.json b/hak/keytar/hak.json
deleted file mode 100644
index 792d85d4..00000000
--- a/hak/keytar/hak.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "scripts": {
-        "check": "check.ts",
-        "build": "build.ts"
-    },
-    "copy": "build/Release/keytar.node",
-    "dependencies": {
-        "libsecret": "0.20.3"
-    }
-}
diff --git a/package.json b/package.json
index c40c2a74..5ba25ac2 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,8 @@
         "test": "playwright test",
         "test:open": "yarn test --ui",
         "test:screenshots:build": "docker build playwright -t element-desktop-playwright --platform linux/amd64",
-        "test:screenshots:run": "docker run --rm --network host -v $(pwd):/work/element-desktop -v /var/run/docker.sock:/var/run/docker.sock --platform linux/amd64 -it element-desktop-playwright"
+        "test:screenshots:run": "docker run --rm --network host -v $(pwd):/work/element-desktop -v /var/run/docker.sock:/var/run/docker.sock --platform linux/amd64 -it element-desktop-playwright",
+        "postinstall": "electron-builder install-app-deps"
     },
     "dependencies": {
         "@sentry/electron": "^5.0.0",
@@ -62,6 +63,7 @@
         "counterpart": "^0.18.6",
         "electron-store": "^10.0.0",
         "electron-window-state": "^5.0.3",
+        "keytar": "^7.9.0",
         "minimist": "^1.2.6",
         "png-to-ico": "^2.1.1",
         "uuid": "^11.0.0"
@@ -111,8 +113,7 @@
         "typescript": "5.7.3"
     },
     "hakDependencies": {
-        "matrix-seshat": "^4.0.1",
-        "keytar": "^7.9.0"
+        "matrix-seshat": "^4.0.1"
     },
     "resolutions": {
         "@types/node": "18.19.76",
diff --git a/src/@types/keytar.d.ts b/src/@types/keytar.d.ts
deleted file mode 100644
index ba396b51..00000000
--- a/src/@types/keytar.d.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-// Based on https://github.com/atom/node-keytar/blob/master/keytar.d.ts because keytar is a hak-dependency and not a normal one
-// Definitions by: Milan Burda <https://github.com/miniak>, Brendan Forster <https://github.com/shiftkey>, Hari Juturu <https://github.com/juturu>
-// Adapted from DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/keytar/index.d.ts
-
-declare module "keytar" {
-    /**
-     * Get the stored password for the service and account.
-     *
-     * @param service The string service name.
-     * @param account The string account name.
-     *
-     * @returns A promise for the password string.
-     */
-    export function getPassword(service: string, account: string): Promise<string | null>;
-
-    /**
-     * Add the password for the service and account to the keychain.
-     *
-     * @param service The string service name.
-     * @param account The string account name.
-     * @param password The string password.
-     *
-     * @returns A promise for the set password completion.
-     */
-    export function setPassword(service: string, account: string, password: string): Promise<void>;
-
-    /**
-     * Delete the stored password for the service and account.
-     *
-     * @param service The string service name.
-     * @param account The string account name.
-     *
-     * @returns A promise for the deletion status. True on success.
-     */
-    export function deletePassword(service: string, account: string): Promise<boolean>;
-
-    /**
-     * Find a password for the service in the keychain.
-     *
-     * @param service The string service name.
-     *
-     * @returns A promise for the password string.
-     */
-    export function findPassword(service: string): Promise<string | null>;
-
-    /**
-     * Find all accounts and passwords for `service` in the keychain.
-     *
-     * @param service The string service name.
-     *
-     * @returns A promise for the array of found credentials.
-     */
-    export function findCredentials(service: string): Promise<Array<{ account: string; password: string }>>;
-}
diff --git a/src/electron-main.ts b/src/electron-main.ts
index 470effbc..16134924 100644
--- a/src/electron-main.ts
+++ b/src/electron-main.ts
@@ -22,7 +22,6 @@ import { URL, fileURLToPath } from "node:url";
 import minimist from "minimist";
 
 import "./ipc.js";
-import "./keytar.js";
 import "./seshat.js";
 import "./settings.js";
 import * as tray from "./tray.js";
diff --git a/src/ipc.ts b/src/ipc.ts
index 66dbf975..cd761055 100644
--- a/src/ipc.ts
+++ b/src/ipc.ts
@@ -7,12 +7,12 @@ Please see LICENSE files in the repository root for full details.
 
 import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron";
 import { relaunchApp } from "@standardnotes/electron-clear-data";
+import * as keytar from "keytar";
 
 import IpcMainEvent = Electron.IpcMainEvent;
 import { recordSSOSession } from "./protocol.js";
 import { randomArray } from "./utils.js";
 import { Settings } from "./settings.js";
-import { keytar } from "./keytar.js";
 import { getDisplayMediaCallback, setDisplayMediaCallback } from "./displayMediaCallback.js";
 
 ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void {
diff --git a/src/keytar.ts b/src/keytar.ts
deleted file mode 100644
index fdcddfde..00000000
--- a/src/keytar.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-Copyright 2022-2024 New Vector Ltd.
-
-SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
-Please see LICENSE files in the repository root for full details.
-*/
-
-import type * as Keytar from "keytar"; // Hak dependency type
-
-let keytar: typeof Keytar | undefined;
-try {
-    ({ default: keytar } = await import("keytar"));
-} catch (e) {
-    if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
-        console.log("Keytar isn't installed; secure key storage is disabled.");
-    } else {
-        console.warn("Keytar unexpected error:", e);
-    }
-}
-
-export { keytar };
diff --git a/src/seshat.ts b/src/seshat.ts
index cea557c7..eacc38e9 100644
--- a/src/seshat.ts
+++ b/src/seshat.ts
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
 import { app, ipcMain } from "electron";
 import { promises as afs } from "node:fs";
 import path from "node:path";
+import * as keytar from "keytar";
 
 import type {
     Seshat as SeshatType,
@@ -16,7 +17,6 @@ import type {
 } from "matrix-seshat"; // Hak dependency type
 import IpcMainEvent = Electron.IpcMainEvent;
 import { randomArray } from "./utils.js";
-import { keytar } from "./keytar.js";
 
 let seshatSupported = false;
 let Seshat: typeof SeshatType;
diff --git a/yarn.lock b/yarn.lock
index 9186868c..0f154711 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2726,7 +2726,7 @@ base64-js@^1.3.1, base64-js@^1.5.1:
   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
   integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
 
-bl@^4.1.0:
+bl@^4.0.3, bl@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
   integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
@@ -2977,6 +2977,11 @@ chokidar@^4.0.0:
   dependencies:
     readdirp "^4.0.1"
 
+chownr@^1.1.1:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
+  integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
+
 chownr@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
@@ -3285,6 +3290,11 @@ decompress-response@^6.0.0:
   dependencies:
     mimic-response "^3.1.0"
 
+deep-extend@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+  integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
 deep-is@^0.1.3:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
@@ -3550,7 +3560,7 @@ encoding@^0.1.13:
   dependencies:
     iconv-lite "^0.6.2"
 
-end-of-stream@^1.1.0:
+end-of-stream@^1.1.0, end-of-stream@^1.4.1:
   version "1.4.4"
   resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
   integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
@@ -3984,6 +3994,11 @@ execa@^8.0.1:
     signal-exit "^4.1.0"
     strip-final-newline "^3.0.0"
 
+expand-template@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
+  integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
+
 exponential-backoff@^3.1.1:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91"
@@ -4140,6 +4155,11 @@ forwarded-parse@2.1.2:
   resolved "https://registry.yarnpkg.com/forwarded-parse/-/forwarded-parse-2.1.2.tgz#08511eddaaa2ddfd56ba11138eee7df117a09325"
   integrity sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==
 
+fs-constants@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
+  integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
+
 fs-extra@^10.0.0, fs-extra@^10.1.0:
   version "10.1.0"
   resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
@@ -4313,6 +4333,11 @@ get-tsconfig@^4.7.5, get-tsconfig@^4.8.1:
   dependencies:
     resolve-pkg-maps "^1.0.0"
 
+github-from-package@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
+  integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==
+
 glob-parent@^5.1.2:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
@@ -4701,6 +4726,11 @@ ini@^5.0.0:
   resolved "https://registry.yarnpkg.com/ini/-/ini-5.0.0.tgz#a7a4615339843d9a8ccc2d85c9d81cf93ffbc638"
   integrity sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==
 
+ini@~1.3.0:
+  version "1.3.8"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+  integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
 internal-slot@^1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802"
@@ -5093,6 +5123,14 @@ jszip@^3.1.0:
     readable-stream "~2.3.6"
     setimmediate "^1.0.5"
 
+keytar@^7.9.0:
+  version "7.9.0"
+  resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb"
+  integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==
+  dependencies:
+    node-addon-api "^4.3.0"
+    prebuild-install "^7.0.1"
+
 keyv@^4.0.0, keyv@^4.5.3:
   version "4.5.4"
   resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
@@ -5435,7 +5473,7 @@ minimatch@^9.0.0, minimatch@^9.0.3, minimatch@^9.0.4, minimatch@^9.0.5:
   dependencies:
     brace-expansion "^2.0.1"
 
-minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8:
+minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8:
   version "1.2.8"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
   integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
@@ -5541,6 +5579,11 @@ minizlib@^3.0.1:
     minipass "^7.0.4"
     rimraf "^5.0.5"
 
+mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
+  integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
+
 mkdirp@^0.5.1:
   version "0.5.6"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
@@ -5568,6 +5611,11 @@ ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
   integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
 
+napi-build-utils@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e"
+  integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==
+
 natural-compare@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -5583,7 +5631,7 @@ negotiator@^1.0.0:
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a"
   integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==
 
-node-abi@^3.45.0:
+node-abi@^3.3.0, node-abi@^3.45.0:
   version "3.74.0"
   resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.74.0.tgz#5bfb4424264eaeb91432d2adb9da23c63a301ed0"
   integrity sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==
@@ -5595,6 +5643,11 @@ node-addon-api@^1.6.3:
   resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d"
   integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==
 
+node-addon-api@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f"
+  integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==
+
 node-api-version@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/node-api-version/-/node-api-version-0.2.0.tgz#5177441da2b1046a4d4547ab9e0972eed7b1ac1d"
@@ -6200,6 +6253,24 @@ postject@^1.0.0-alpha.6:
   dependencies:
     commander "^9.4.0"
 
+prebuild-install@^7.0.1:
+  version "7.1.3"
+  resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec"
+  integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==
+  dependencies:
+    detect-libc "^2.0.0"
+    expand-template "^2.0.3"
+    github-from-package "0.0.0"
+    minimist "^1.2.3"
+    mkdirp-classic "^0.5.3"
+    napi-build-utils "^2.0.0"
+    node-abi "^3.3.0"
+    pump "^3.0.0"
+    rc "^1.2.7"
+    simple-get "^4.0.0"
+    tar-fs "^2.0.0"
+    tunnel-agent "^0.6.0"
+
 prelude-ls@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -6278,6 +6349,16 @@ quick-lru@^5.1.1:
   resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
   integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
 
+rc@^1.2.7:
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+  integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
+  dependencies:
+    deep-extend "^0.6.0"
+    ini "~1.3.0"
+    minimist "^1.2.0"
+    strip-json-comments "~2.0.1"
+
 read-binary-file-arch@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz#959c4637daa932280a9b911b1a6766a7e44288fc"
@@ -6304,7 +6385,7 @@ read-pkg@^5.2.0:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-readable-stream@^3.4.0:
+readable-stream@^3.1.1, readable-stream@^3.4.0:
   version "3.6.2"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
   integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
@@ -6556,16 +6637,16 @@ safe-array-concat@^1.1.2:
     has-symbols "^1.0.3"
     isarray "^2.0.5"
 
+safe-buffer@^5.0.1, safe-buffer@~5.2.0:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
 safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
   integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
 
-safe-buffer@~5.2.0:
-  version "5.2.1"
-  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
-  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-
 safe-regex-test@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377"
@@ -6700,6 +6781,20 @@ sigstore@^3.0.0:
     "@sigstore/tuf" "^3.0.0"
     "@sigstore/verify" "^2.0.0"
 
+simple-concat@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
+  integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
+
+simple-get@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543"
+  integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==
+  dependencies:
+    decompress-response "^6.0.0"
+    once "^1.3.1"
+    simple-concat "^1.0.0"
+
 simple-update-notifier@2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb"
@@ -6969,6 +7064,11 @@ strip-json-comments@^3.1.1:
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
   integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
 
+strip-json-comments@~2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+  integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
+
 stubborn-fs@^1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/stubborn-fs/-/stubborn-fs-1.2.5.tgz#e5e244223166921ddf66ed5e062b6b3bf285bfd2"
@@ -7010,6 +7110,27 @@ tapable@^2.2.0:
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
   integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
 
+tar-fs@^2.0.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.2.tgz#425f154f3404cb16cb8ff6e671d45ab2ed9596c5"
+  integrity sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==
+  dependencies:
+    chownr "^1.1.1"
+    mkdirp-classic "^0.5.2"
+    pump "^3.0.0"
+    tar-stream "^2.1.4"
+
+tar-stream@^2.1.4:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
+  integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
+  dependencies:
+    bl "^4.0.3"
+    end-of-stream "^1.4.1"
+    fs-constants "^1.0.0"
+    inherits "^2.0.3"
+    readable-stream "^3.1.1"
+
 tar@^6.0.5, tar@^6.1.11, tar@^6.1.12, tar@^6.2.1:
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
@@ -7127,6 +7248,13 @@ tuf-js@^3.0.1:
     debug "^4.3.6"
     make-fetch-happen "^14.0.1"
 
+tunnel-agent@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+  integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==
+  dependencies:
+    safe-buffer "^5.0.1"
+
 type-check@^0.4.0, type-check@~0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"

From bce251b35b3d6cecf0c6d409eb9060dccd8d1c35 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 28 Feb 2025 11:17:07 +0000
Subject: [PATCH 2/5] Update node engines, 23.x is broken too

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index c40c2a74..b071c094 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
     "type": "module",
     "files": [],
     "engines": {
-        "node": ">=18.0.0 <=22.13.1 || >22"
+        "node": ">=18.0.0 <=22.13.1"
     },
     "scripts": {
         "i18n": "matrix-gen-i18n && yarn i18n:sort && yarn i18n:lint",

From ff7f53fb35675694b3961a77c97557765d4cedd4 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 28 Feb 2025 11:39:31 +0000
Subject: [PATCH 3/5] Use modern Dockerfile env format to silence warnings
 (#2171)

---
 dockerbuild/Dockerfile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/dockerbuild/Dockerfile b/dockerbuild/Dockerfile
index 0c4c0b3c..ecd61fc5 100644
--- a/dockerbuild/Dockerfile
+++ b/dockerbuild/Dockerfile
@@ -2,7 +2,7 @@
 # with broader compatibility, down to Debian bullseye & Ubuntu focal.
 FROM rust:bullseye
 
-ENV DEBIAN_FRONTEND noninteractive
+ENV DEBIAN_FRONTEND=noninteractive
 
 RUN curl --proto "=https" -L https://yarnpkg.com/latest.tar.gz | tar xvz && mv yarn-* /yarn && ln -s /yarn/bin/yarn /usr/bin/yarn
 RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
@@ -16,8 +16,8 @@ RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
   apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/*
 RUN ln -s /usr/bin/python3 /usr/bin/python & ln -s /usr/bin/pip3 /usr/bin/pip
 
-ENV DEBUG_COLORS true
-ENV FORCE_COLOR true
+ENV DEBUG_COLORS=true
+ENV FORCE_COLOR=true
 
 WORKDIR /project
 

From 5ee122cdae80f392b7c826f6ac40a0c3c5cec0cc Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 28 Feb 2025 12:14:10 +0000
Subject: [PATCH 4/5] Add logging

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
 src/ipc.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/ipc.ts b/src/ipc.ts
index cd761055..feda1cfd 100644
--- a/src/ipc.ts
+++ b/src/ipc.ts
@@ -161,7 +161,8 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
                 // rather than sending them a pickle key we did not store on their behalf.
                 await keytar!.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
                 ret = pickleKey;
-            } catch {
+            } catch (e) {
+                console.error("Failed to create pickle key", e);
                 ret = null;
             }
             break;

From e4dac2a2107536e2adb0cdc6e4387b8ff0ce326d Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 28 Feb 2025 12:33:47 +0000
Subject: [PATCH 5/5] Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
 src/ipc.ts    | 10 +++++-----
 src/seshat.ts |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/ipc.ts b/src/ipc.ts
index feda1cfd..9bbeb4e9 100644
--- a/src/ipc.ts
+++ b/src/ipc.ts
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
 
 import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron";
 import { relaunchApp } from "@standardnotes/electron-clear-data";
-import * as keytar from "keytar";
+import keytar from "keytar";
 
 import IpcMainEvent = Electron.IpcMainEvent;
 import { recordSSOSession } from "./protocol.js";
@@ -141,11 +141,11 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
 
         case "getPickleKey":
             try {
-                ret = await keytar?.getPassword("element.io", `${args[0]}|${args[1]}`);
+                ret = await keytar.getPassword("element.io", `${args[0]}|${args[1]}`);
                 // migrate from riot.im (remove once we think there will no longer be
                 // logins from the time of riot.im)
                 if (ret === null) {
-                    ret = await keytar?.getPassword("riot.im", `${args[0]}|${args[1]}`);
+                    ret = await keytar.getPassword("riot.im", `${args[0]}|${args[1]}`);
                 }
             } catch {
                 // if an error is thrown (e.g. keytar can't connect to the keychain),
@@ -169,10 +169,10 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
 
         case "destroyPickleKey":
             try {
-                await keytar?.deletePassword("element.io", `${args[0]}|${args[1]}`);
+                await keytar.deletePassword("element.io", `${args[0]}|${args[1]}`);
                 // migrate from riot.im (remove once we think there will no longer be
                 // logins from the time of riot.im)
-                await keytar?.deletePassword("riot.im", `${args[0]}|${args[1]}`);
+                await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`);
             } catch {}
             break;
         case "getDesktopCapturerSources":
diff --git a/src/seshat.ts b/src/seshat.ts
index eacc38e9..ac467cd6 100644
--- a/src/seshat.ts
+++ b/src/seshat.ts
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
 import { app, ipcMain } from "electron";
 import { promises as afs } from "node:fs";
 import path from "node:path";
-import * as keytar from "keytar";
+import keytar from "keytar";
 
 import type {
     Seshat as SeshatType,