From 31e690c6f4e36b4a39bf932e6feddade58f125ee Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 13:20:22 +0200 Subject: [PATCH 01/10] Stop the enrolment log message arriving with a gap in the middle The sentence was split across two source lines with a backslash continuation, which keeps the indentation inside the string - so what reached the log had a run of spaces in the middle of it. concat! joins the pieces with nothing between them and cannot do that whatever the surrounding formatting is. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01P4Pn5YzK5yErCEZkV47WmN --- src-tauri/src/e2ee_enrol.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/e2ee_enrol.rs b/src-tauri/src/e2ee_enrol.rs index 8699182..6cb04e4 100644 --- a/src-tauri/src/e2ee_enrol.rs +++ b/src-tauri/src/e2ee_enrol.rs @@ -180,8 +180,14 @@ pub async fn unlock_this_installation( // high). Dismissing that on a crypto path to keep a value a log file has // no use for is the wrong trade - the comparison happens in the interface. Ok(_fingerprint) => log::info!( - "Published this installation's key - approve it from an \ - installation that can already read your stashes" + // concat! rather than a `\` line continuation. The continuation left + // the indentation inside the string here, so the sentence reached the + // log with a run of spaces in the middle of it. concat! has no such + // ambiguity, whatever the cause was. + concat!( + "Published this installation's key - approve it from an ", + "installation that can already read your stashes", + ) ), // Not fatal: the recovery code still works, and the next start tries again. Err(e) => log::warn!("Could not publish this installation's key: {}", e), From 62477c7a3f1ddb21191abd186683e071472bf999 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 21:19:16 +0200 Subject: [PATCH 02/10] Approve another computer with a tick, and notice when you have been Three things about letting a second installation in, all of them in the way. The code had to be read off one screen and typed into the other before the approve button appeared. The eye had already done the comparing; the typing only added a chance to mistype sixteen characters and be told the codes did not match when they did. It is a checkbox now - the person either compared the two screens or decided not to, and that is their call to make either way. Nothing about the security changed with it. The fingerprint still travels to the backend, which recomputes it from the key it fetches at that moment, so a key swapped between the card being drawn and the button being pressed is still caught. That check was never the typing. The card itself now looks like the rest of the panel: the code sits in the same inset block the recovery code uses, large enough to read across a desk, the heading carries the shield the other headings do, and the action is a primary button with a spinner rather than an outline one that read as disabled. And the installation that was waiting now notices when it has been let in. It polled nothing, so it went on saying it was waiting until Settings was closed and reopened - which reads as the approval having failed. The panel already had a poll for the conversion sweep; it now also runs while this installation cannot open the key, and e2ee_status picks the key up opportunistically, so asking is also the act of unlocking. Waiting to be let in takes priority over watching the sweep, because an installation that cannot open the key can do nothing about the sweep anyway. The poll is quiet: it touches neither the busy flag nor the error line, so it cannot grey out a button under the cursor or wipe a message still being read. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01P4Pn5YzK5yErCEZkV47WmN --- CHANGELOG.md | 13 ++ src/lib/components/EncryptionPanel.svelte | 189 +++++++++++++++------- src/lib/i18n/locales/de.json | 7 +- src/lib/i18n/locales/en.json | 7 +- 4 files changed, 153 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ede6a4e..483a320 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,19 @@ popover, not for the person who wrote the commit. ## [Unreleased] +### Changed +- **Approving a new computer is a tick, not a retyped code.** You had to read the sixteen + characters off one screen and type them into the other before the approve button would + appear. Your eyes had already done the comparing; the typing only added a chance to + mistype it and be told the codes did not match when they did. The code is shown large + enough to read across a desk, and you confirm it matches with a checkbox + +### Fixed +- **A computer waiting to be let in notices when it has been.** After approving it from the + other machine, the one that was waiting went on saying it was waiting - the only way to + find out it had worked was to close the settings and open them again, which reads as the + approval having failed. It now picks the key up on its own, within a few seconds + ## [1.8.7] - 2026-09-24 ### Fixed diff --git a/src/lib/components/EncryptionPanel.svelte b/src/lib/components/EncryptionPanel.svelte index 8d19eb6..771b8da 100644 --- a/src/lib/components/EncryptionPanel.svelte +++ b/src/lib/components/EncryptionPanel.svelte @@ -38,6 +38,9 @@ See the GNU Affero General Public License for more details. const adapter = new DesktopStorageAdapter(); + /// What the panel is polling for, when it is polling at all. + type Waiting = "progress" | "approval" | null; + let status = $state(null); let busy = $state(false); let error = $state(""); @@ -70,17 +73,24 @@ See the GNU Affero General Public License for more details. const passphraseMode = $derived<"unset" | "locked">( keyStore === "locked" ? "locked" : "unset", ); - let progressTimer: ReturnType | null = null; + let pollTimer: ReturnType | null = null; + let pollingFor = $state(null); - const POLL_MS = 2000; + /// The progress count is a local database query, so it can be asked for often. The + /// approval check is a request to the server, so it is not. + const PROGRESS_POLL_MS = 2000; + const APPROVAL_POLL_MS = 4000; /// Records already through, for the bar. Clamped because `total` is counted fresh and /// a record deleted mid-sweep can otherwise make this exceed `total`. const done = $derived(Math.max(0, Math.min(total, total - remaining))); const percent = $derived(total > 0 ? Math.round((done / total) * 100) : 0); - let approving = $state(null); - let approvalFingerprint = $state(""); + /// The installation whose codes the user has ticked off as matching. + /// + /// One at a time: approving is a deliberate act per machine, and a tick that survived + /// from the previous card would be the wrong kind of convenience. + let confirmedDevice = $state(null); let recoveryInput = $state(""); const pending = $derived(status?.devices.filter((d) => d.status === "pending") ?? []); @@ -94,22 +104,46 @@ See the GNU Affero General Public License for more details. onDestroy(stopPolling); - /// Poll only while there is something to watch, and stop as soon as there is not: - /// an interval left running behind a closed settings page would query the database - /// every two seconds for the life of the process. - function syncPolling(state: string | undefined) { - if (state === "migrating" && !progressTimer) { - progressTimer = setInterval(readProgress, POLL_MS); - } else if (state !== "migrating") { - stopPolling(); + /// What the panel is waiting on, if anything. + /// + /// Both of these move somewhere the panel cannot see. The sweep is carried by ordinary + /// syncs, and approval happens on another machine entirely - so nothing tells this + /// panel when either has happened and it has to look. An installation that had just + /// been let in used to go on saying it was waiting until Settings was closed and + /// reopened, which reads as the approval not having worked. + /// Waiting to be let in comes first. An installation that cannot open the key can do + /// nothing about the sweep either, so polling its progress would watch the one number + /// that cannot change for it while missing the one that can. + function waitingOn(next: E2eeStatus | null): Waiting { + if (!next || next.state === "off") return null; + if (!next.unlocked) return "approval"; + if (next.state === "migrating") return "progress"; + return null; + } + + /// Poll only while there is something to watch, and stop as soon as there is not: an + /// interval left running behind a closed settings page would keep asking for the life + /// of the process. Re-entering with the same answer leaves the existing timer alone, + /// so a poll that refreshes cannot reset its own interval. + function syncPolling(next: Waiting) { + if (next === pollingFor) return; + stopPolling(); + pollingFor = next; + if (next === "progress") { + pollTimer = setInterval(readProgress, PROGRESS_POLL_MS); + } else if (next === "approval") { + // e2ee_status opens this installation's wrap if the server is holding one, so + // asking is also the act of picking the key up the moment it is granted. + pollTimer = setInterval(() => void refresh({ quiet: true }), APPROVAL_POLL_MS); } } function stopPolling() { - if (progressTimer) { - clearInterval(progressTimer); - progressTimer = null; + if (pollTimer) { + clearInterval(pollTimer); + pollTimer = null; } + pollingFor = null; } async function readProgress() { @@ -128,13 +162,21 @@ See the GNU Affero General Public License for more details. } } - async function refresh() { + /// Read the whole panel back. + /// + /// `quiet` is for the poll, and must touch neither `busy` nor `error`: flipping `busy` + /// every few seconds would grey out the buttons under the person's cursor, and + /// clearing `error` would wipe a message they are still reading. A failed poll says + /// nothing the next one will not say again. + async function refresh(options: { quiet?: boolean } = {}) { + const quiet = options.quiet === true; // Sets `busy` itself so the retry button below can disable while it runs; `run()` // calls this too, and setting the flag twice is harmless. - busy = true; + if (!quiet) busy = true; try { - status = await adapter.e2eeStatus(); - error = ""; + const next = await adapter.e2eeStatus(); + status = next; + if (!quiet) error = ""; try { keyStore = await adapter.localKeyStatus(); } catch { @@ -143,14 +185,14 @@ See the GNU Affero General Public License for more details. } // Read the count straight away rather than waiting a poll interval, so // reopening the page mid-sweep shows the real figure instead of a zero. - if (status.state === "migrating") { + if (next.state === "migrating") { await readProgress(); } - syncPolling(status.state); + syncPolling(waitingOn(next)); } catch (e) { - error = errorText(e); + if (!quiet) error = errorText(e); } finally { - busy = false; + if (!quiet) busy = false; } } @@ -260,7 +302,7 @@ See the GNU Affero General Public License for more details. {#if error} - {:else} - - {/if} + onchange={(e) => + (confirmedDevice = e.currentTarget.checked + ? device.deviceId + : null)} + class="mt-0.5" + /> + + {$_("encryption.confirmMatch")} + {$_("encryption.confirmMatchHint")} + + + + {/each} diff --git a/src/lib/i18n/locales/de.json b/src/lib/i18n/locales/de.json index 0d0da4b..d792213 100644 --- a/src/lib/i18n/locales/de.json +++ b/src/lib/i18n/locales/de.json @@ -303,9 +303,10 @@ "lockedApproveAlternative": "Oder gib diese Installation von einer frei, die sie schon lesen kann – dann brauchst du den Code nicht.", "useRecoveryCode": "Wiederherstellungscode verwenden", "pendingTitle": "Wartet auf Freigabe", - "compareInstruction": "Prüfe, ob das mit dem übereinstimmt, was die andere Installation anzeigt. Wenn nicht, gib sie nicht frei.", - "letItIn": "Freigeben", - "approve": "Die Codes stimmen überein, freigeben", + "compareInstruction": "Öffne auf dem anderen Rechner die Verschlüsselungs-Einstellungen und vergleiche den dort angezeigten Code mit diesem.", + "confirmMatch": "Ich habe beide Codes verglichen und sie sind identisch.", + "confirmMatchHint": "Wenn sie sich unterscheiden, gib nicht frei — dann versucht möglicherweise jemand anderes hereinzukommen.", + "approve": "Diese Installation freigeben", "thisInstallation": "Diese Installation", "activeCount": "{count} Installation(en) können deine Stashes lesen." }, diff --git a/src/lib/i18n/locales/en.json b/src/lib/i18n/locales/en.json index b6dbe0b..02802c2 100644 --- a/src/lib/i18n/locales/en.json +++ b/src/lib/i18n/locales/en.json @@ -303,9 +303,10 @@ "lockedApproveAlternative": "Or approve this installation from one that can already read them, without typing the code.", "useRecoveryCode": "Use recovery code", "pendingTitle": "Waiting to be let in", - "compareInstruction": "Check this matches what the other installation shows. If it does not, do not approve it.", - "letItIn": "Let it in", - "approve": "The codes match, approve", + "compareInstruction": "Open the encryption settings on the other computer and compare the code it shows with this one.", + "confirmMatch": "I have compared both codes and they are identical.", + "confirmMatchHint": "If they differ, do not approve — someone else may be trying to get in.", + "approve": "Approve this installation", "thisInstallation": "This installation", "activeCount": "{count} installation(s) can read your stashes." }, From 29307e2fef45b715a58f358feae199acdd2a511f Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 21:27:06 +0200 Subject: [PATCH 03/10] Drop two test scripts that have never run test:unit and test:integration both passed --testPathPattern, which is Jest's flag, not vitest's. Vitest takes file filters as positional arguments and its CLI parser rejects unknown options outright, so both died with `Unknown option --testPathPattern` before collecting a single file. They were introduced that way in f4b229e alongside vitest 4, which is the version that throws, so neither has ever run. Removed rather than repaired, because the split they describe does not exist. Every test file is named *.test.ts, so test:unit would match all fourteen and be a slower spelling of npm test, and test:integration would match none - the config only collects src/**/*.{test,spec}.{js,ts}, so an integration file would need a naming convention and an include change before a script could select it. CI never used either one: test.yml runs npm run test and npm run test:coverage, so nothing has been silently skipped. TESTING.md documented both and no longer does. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01P4Pn5YzK5yErCEZkV47WmN --- TESTING.md | 6 ------ package.json | 4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/TESTING.md b/TESTING.md index 1037485..c40a282 100644 --- a/TESTING.md +++ b/TESTING.md @@ -30,12 +30,6 @@ npm run test:ui # Run tests with coverage report npm run test:coverage - -# Run only unit tests -npm run test:unit - -# Run only integration tests -npm run test:integration ``` ### Backend Tests diff --git a/package.json b/package.json index 428873b..b677cec 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,7 @@ "test": "vitest run", "test:ui": "vitest --ui", "test:watch": "vitest", - "test:coverage": "vitest run --coverage", - "test:unit": "vitest run --testPathPattern=\\.test\\.", - "test:integration": "vitest run --testPathPattern=\\.integration\\." + "test:coverage": "vitest run --coverage" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^6.2.1", From aa9f1493b1d8362cd1bf5c6321e85aa96cdc3ab3 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 21:56:18 +0200 Subject: [PATCH 04/10] Fold long stashes in the queue behind Show more A plan filed through the MCP server, or a stash after AI enhancement, could run to several screens, and scrolling past one to reach the next item was most of the work of using the queue. A stash whose content is clearly taller than a fixed cap (not just a line or two over) now clamps to that height with a fade at the bottom, and a Show more / Show less button toggles it. Short stashes are unaffected. Collapsing a stash scrolled past its top brings the card back into view instead of leaving the reader stranded below it. Checked: svelte-check reports 0 errors, all 218 vitest tests pass, and I verified the clamp, toggle and no-accidental-copy behavior against the screenshot demo with a synthetic long stash (reverted after). Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 5 ++ src/lib/components/StashCard.svelte | 78 ++++++++++++++++++++++++++--- src/lib/i18n/locales/de.json | 2 + src/lib/i18n/locales/en.json | 2 + 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 483a320..5fb56d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ popover, not for the person who wrote the commit. appear. Your eyes had already done the comparing; the typing only added a chance to mistype it and be told the codes did not match when they did. The code is shown large enough to read across a desk, and you confirm it matches with a checkbox +- **Long stashes fold up in the queue.** A plan an agent filed through the MCP server, or a + stash after AI enhancement, could run to several screens, and scrolling past one to reach + the next item was most of the work of using the queue. A stash that is clearly taller + than the cap now stops at a fixed height with a fade, and Show more opens it, Show less + folds it back. Short stashes look exactly as before ### Fixed - **A computer waiting to be let in notices when it has been.** After approving it from the diff --git a/src/lib/components/StashCard.svelte b/src/lib/components/StashCard.svelte index 795a929..1ab438d 100644 --- a/src/lib/components/StashCard.svelte +++ b/src/lib/components/StashCard.svelte @@ -49,6 +49,8 @@ ArrowLeftRight, X, Tags, + ChevronDown, + ChevronUp, } from "lucide-svelte"; import Editor from "./Editor.svelte"; import FilePreviewTooltip from "./FilePreviewTooltip.svelte"; @@ -157,6 +159,35 @@ showEnhanced && hasEnhancedVersion ? item.enhancedContent! : item.content, ); + // Long stashes (agent plans, AI-enhanced text) are clamped to a maximum + // height so the queue stays navigable. A stash only collapses when it is + // clearly longer than the cap, so nobody expands a card to reveal one line. + const COLLAPSED_MAX_PX = 192; + const COLLAPSE_SLACK_PX = 48; + let contentRef = $state(); + let contentHeight = $state(0); + let expanded = $state(false); + let isLong = $derived(contentHeight > COLLAPSED_MAX_PX + COLLAPSE_SLACK_PX); + let isClamped = $derived(isLong && !expanded); + + $effect(() => { + if (!contentRef) return; + const el = contentRef; + const observer = new ResizeObserver(() => { + contentHeight = el.scrollHeight; + }); + observer.observe(el); + return () => observer.disconnect(); + }); + + function toggleExpanded() { + expanded = !expanded; + // Collapsing a stash read to its end would leave the reader far below it. + if (!expanded && cardRef && cardRef.getBoundingClientRect().top < 0) { + cardRef.scrollIntoView({ block: "start" }); + } + } + let stashData = $derived(extractTagsAndColors(item.content)); let stashTags = $derived(() => stashData.tags); let stashColors = $derived(() => stashData.colors); @@ -552,15 +583,48 @@ {/if} + {#if isLong} + + {/if} {:else}
{$_("stashCard.emptyStash")} diff --git a/src/lib/i18n/locales/de.json b/src/lib/i18n/locales/de.json index d792213..77e04cf 100644 --- a/src/lib/i18n/locales/de.json +++ b/src/lib/i18n/locales/de.json @@ -436,6 +436,8 @@ "stashAdded": "Stash hinzugefügt" }, "stashCard": { + "showMore": "Mehr anzeigen", + "showLess": "Weniger anzeigen", "emptyStash": "-- leer --", "copied": "Kopiert!", "attachment": "{count} Anhang ({size})", diff --git a/src/lib/i18n/locales/en.json b/src/lib/i18n/locales/en.json index 02802c2..0a1b2de 100644 --- a/src/lib/i18n/locales/en.json +++ b/src/lib/i18n/locales/en.json @@ -436,6 +436,8 @@ } }, "stashCard": { + "showMore": "Show more", + "showLess": "Show less", "emptyStash": "-- empty --", "attachment": "{count} attachment ({size})", "attachments": "{count} attachments ({size})", From 0097d009819a590d455e343ed887196d71542cc3 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 22:50:25 +0200 Subject: [PATCH 05/10] Try warming the cargo registry before CodeQL's rust extraction Measured one run: the rust matrix leg of codeql.yml took 6m36s against javascript-typescript's 1m1s and actions' 46s. Inside it, the extractor's own duration log breaks the 2m28s Extract phase down as LoadManifest (44.7s) and ExtractLibrary (46.0s) - resolving the dependency graph and its signatures for the 799 crates in src-tauri/Cargo.lock, the same crate count that made release.yml's own rust-cache entry worth adding. The remaining ~3m of the job is query evaluation shared across every query, security and diagnostic alike, and does not look reducible without shrinking the dependency graph itself or the query suite - out of scope here. Adding Swatinem/rust-cache before Initialize CodeQL, same as test.yml and release.yml already do, in case LoadManifest/ExtractLibrary are what it warms. Unverified: nothing in this run's log names a network fetch, so this may warm nothing the extractor reads. save-if mirrors release.yml's reasoning - this workflow's only run against main is the weekly schedule, so that is the only write, and everything else only restores. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/codeql.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b61b995..1ce2bba 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -64,6 +64,24 @@ jobs: - name: Checkout code uses: actions/checkout@v7 + # Buildless still touches disk: the extractor resolves the full dependency graph + # before it can read a single signature, against the same 799 crates in + # src-tauri/Cargo.lock that made release.yml's own rust-cache entry worth adding. + # Untested whether this actually warms anything the extractor reads rather than + # something it derives standalone - worth confirming against a run before trusting + # this comment over the numbers. + # + # `save-if` mirrors release.yml's for the same reason: a cache scoped to a PR or to + # develop is invisible to everything else and just spends the repository's shared + # 10 GB budget. This workflow's only run against main is the weekly schedule, so + # that is the only run that refreshes it. + - name: Cache Rust dependencies + if: matrix.language == 'rust' + uses: Swatinem/rust-cache@v2 + with: + workspaces: src-tauri -> target + save-if: ${{ github.ref == 'refs/heads/main' }} + - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: From cc39715fe445ba8aea52de585504bc67c5e72ce3 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 23:00:45 +0200 Subject: [PATCH 06/10] test: force-save the cache on develop to measure a warm run Temporary, to be reverted after: save-if is normally main-only, and this run's whole point is to populate the develop-scoped cache so a follow-up dispatch can measure a hit against the baseline already recorded. --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1ce2bba..58a5682 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -80,7 +80,7 @@ jobs: uses: Swatinem/rust-cache@v2 with: workspaces: src-tauri -> target - save-if: ${{ github.ref == 'refs/heads/main' }} + save-if: "true" - name: Initialize CodeQL uses: github/codeql-action/init@v4 From c3cf526c2a36a0826f6d067f5d4bdbbb3dda9c54 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 23:20:03 +0200 Subject: [PATCH 07/10] Take the cargo cache back out of CodeQL, measured to save nothing Two dispatched runs on develop, one cold and one on a full cache hit, 190 MB of ~/.cargo/registry restored in three seconds. The extractor's own timings barely moved: LoadManifest 58.2s to 50.6s, ExtractLibrary 57.2s to 55.1s, extraction as a whole 3m01s to 2m49s, and the rust job 8m37s to 8m16s. That is inside the spread between two uncached runs earlier the same evening (6m36s and 8m23s), so the cache is not what those phases are waiting on. It is not worth 190 MB of a 10 GB budget that release.yml and test.yml already fill to three quarters. This also undoes the temporary save-if override the measurement needed. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/codeql.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 58a5682..b61b995 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -64,24 +64,6 @@ jobs: - name: Checkout code uses: actions/checkout@v7 - # Buildless still touches disk: the extractor resolves the full dependency graph - # before it can read a single signature, against the same 799 crates in - # src-tauri/Cargo.lock that made release.yml's own rust-cache entry worth adding. - # Untested whether this actually warms anything the extractor reads rather than - # something it derives standalone - worth confirming against a run before trusting - # this comment over the numbers. - # - # `save-if` mirrors release.yml's for the same reason: a cache scoped to a PR or to - # develop is invisible to everything else and just spends the repository's shared - # 10 GB budget. This workflow's only run against main is the weekly schedule, so - # that is the only run that refreshes it. - - name: Cache Rust dependencies - if: matrix.language == 'rust' - uses: Swatinem/rust-cache@v2 - with: - workspaces: src-tauri -> target - save-if: "true" - - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: From 46c2650f5a640e92c7a80b747da70a2dc41da12d Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Thu, 24 Sep 2026 23:29:37 +0200 Subject: [PATCH 08/10] Skip CodeQL's rust analysis on pull requests that touch no Rust The rust leg is the whole length of codeql.yml - six to eight minutes, against about one each for actions and javascript-typescript - and almost none of it is this repository's code. The extractor spends it resolving the 799 crates in Cargo.lock, and the queries spend it on one shared pass over the database that builds, which is why all 37 finish within seconds of each other. Caching the cargo registry was measured and saved nothing, so the remaining lever is not running it when it cannot find anything new. A small job now asks the pull request's file list whether anything under src-tauri/, or this workflow itself, changed. When nothing did, the rust leg still runs as a job but skips its steps and says so in its summary, so the check reads as skipped rather than disappearing. Every doubt resolves to analysing: a failed lookup, an empty list, or a list at the endpoint's 3000-file cap. The weekly schedule and a manual dispatch always analyse everything, which keeps the Security tab's baseline for main complete. Checked the lookup against real pull requests: #16 and #18 (npm only) skip, #19 and #21 (cargo) analyse, #23 (develop) analyses, a missing PR analyses, and a scheduled run analyses. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/codeql.yml | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b61b995..6c711e6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,8 +28,52 @@ concurrency: cancel-in-progress: true jobs: + # The rust leg is the whole length of this workflow: six to eight minutes against about one + # for each of the other two, and caching the cargo registry was measured to save nothing. + # Almost none of that time is this repository's code. The extractor spends it resolving the + # 799 crates in Cargo.lock and reading their signatures, and the queries spend it on one + # shared pass over the database that builds - which is why all 37 finish together, and why + # dropping queries would not help. So a pull request that touches no Rust skips it. + # + # Only pull requests. The weekly schedule and a manual dispatch always analyse everything, + # which is what keeps the Security tab's baseline for main complete. A skipped PR shows a + # warning in the Code scanning check that the rust configuration was not found; that is the + # expected cost of skipping, not a failure. + rust-changes: + name: Rust changed? + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + pull-requests: read + outputs: + analyze: ${{ steps.check.outputs.analyze }} + steps: + - name: Look for changes the rust analysis would see + id: check + env: + GH_TOKEN: ${{ github.token }} + EVENT: ${{ github.event_name }} + PR: ${{ github.event.pull_request.number }} + run: | + analyze=true + # Every doubt resolves to analysing. A failed lookup reads as "no files", which + # would otherwise mean "no Rust" and skip the one thing this workflow is slow for. + if [ "$EVENT" = pull_request ] \ + && files=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR/files" --paginate --jq '.[].filename'); then + count=$(printf '%s\n' "$files" | grep -c . || true) + # The files endpoint stops at 3000. Past that the list is incomplete. + if [ "$count" -gt 0 ] && [ "$count" -lt 3000 ] \ + && ! printf '%s\n' "$files" | grep -qE '^(src-tauri/|\.github/workflows/codeql\.yml$)'; then + analyze=false + fi + echo "$count files changed; rust analysis: $analyze" + fi + echo "analyze=$analyze" >> "$GITHUB_OUTPUT" + analyze: name: Analyze (${{ matrix.language }}) + needs: rust-changes runs-on: ubuntu-latest timeout-minutes: 30 permissions: @@ -60,17 +104,30 @@ jobs: - language: rust build-mode: none + # Decided per step rather than per job, because a job-level `if` is evaluated before the + # matrix expands and cannot see `matrix.language`. The skipped rust leg still reports, as a + # green job with a note in its summary, rather than vanishing from the PR. + env: + SKIP: ${{ matrix.language == 'rust' && needs.rust-changes.outputs.analyze != 'true' }} + steps: + - name: Note the skip + if: env.SKIP == 'true' + run: echo "No Rust changed in this pull request, so the rust analysis was skipped. The weekly scheduled run still covers it." >> "$GITHUB_STEP_SUMMARY" + - name: Checkout code + if: env.SKIP != 'true' uses: actions/checkout@v7 - name: Initialize CodeQL + if: env.SKIP != 'true' uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - name: Analyze + if: env.SKIP != 'true' uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}" From 37a6a84d530e2510b98264e5cf7345359bb50f10 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Fri, 25 Sep 2026 01:04:48 +0200 Subject: [PATCH 09/10] Pick up the security fixes in Tauri and the crates under it Dependabot's 20 open alerts were all Rust, all in Cargo.lock and all shipping in the binary. Most were in crates the app only pulls in through other crates, which the grouped version-update PRs never touch. The cargo one fixed none of them. - tauri 2.10.2 -> 2.11.6 (floor raised to 2.11.1): is_local_url() let a remote origin pass as app:// on Windows/Android. Not reachable today, since the webview never leaves its bundle. @tauri-apps/api and cli follow to 2.11, which the build requires. - openssl 0.10.81, rustls-webpki 0.103.15, tar 0.4.46, serde_with 3.22.0, rand 0.8.8 / 0.9.5 Still open: glib 0.18 (gtk-rs 0.18 pins it until Tauri moves off it) and rand 0.7.3, which is build-time only (phf_codegen via tauri-utils). dependabot.yml drops the npm and cargo version updates: dependencies are now refreshed by hand before a release, and alerts stay on. cargo test 147 passed, vitest 218 passed, tsc clean. Co-Authored-By: Claude Sonnet 5 --- .github/dependabot.yml | 57 ++-- CHANGELOG.md | 8 + package-lock.json | 123 +++++---- package.json | 4 +- src-tauri/Cargo.lock | 581 +++++++++++++++++++++++++++++++---------- src-tauri/Cargo.toml | 2 +- 6 files changed, 546 insertions(+), 229 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6fa4147..955635d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,16 +1,28 @@ -# Version updates. Alerts and security updates are repository settings and need nothing -# here; this file is only the scheduled "bump things that are behind" pull requests. +# Version updates. Alerts are a repository setting and need nothing here; this file is only +# the scheduled "bump things that are behind" pull requests. # -# Two settings below are load-bearing rather than taste, and both are explained where they -# appear: `target-branch`, because the default would aim at the release branch, and the -# `groups` blocks, because an ungrouped cargo update is expensive in a way that is not -# obvious from the diff. +# Only the workflows are covered. npm and cargo were here once and were taken out on purpose, +# so do not add them back without reading why: +# +# - Version updates only move what package.json and Cargo.toml name directly. Every alert +# the repository actually had was in a transitive crate (openssl, rustls-webpki, tar...), +# which these pull requests never touch - the grouped cargo one fixed none of the 20 open +# alerts it sat next to. +# - Each major arrives as its own pull request that fails CI until someone does the +# migration, and each cargo one rewrites Cargo.lock, which busts the Rust cache and +# compiles all 799 crates cold on three operating systems. +# - Security updates would target the alerts, but they always aim at the default branch, +# `main`, where a merge is the release decision. `target-branch` does not apply to them, +# so they stay switched off in the repository settings. +# +# Instead, dependencies are refreshed by hand on `develop` before a release (`cargo update`, +# `npm update`, then check the open alerts). Alerts read the lockfiles on `main`, so they +# close when that release is promoted. version: 2 updates: - # The workflows themselves. This is the cheapest of the three and arguably the most - # useful: it is what would have flagged actions-rs/toolchain being archived in 2023, - # which test.yml had to notice by hand. + # The workflows themselves. This is cheap and useful: it is what would have flagged + # actions-rs/toolchain being archived in 2023, which test.yml had to notice by hand. - package-ecosystem: "github-actions" directory: "/" # Dependabot aims at the default branch unless told otherwise, and the default branch @@ -28,30 +40,3 @@ updates: # ones that need reading. actions-minor-and-patch: update-types: ["minor", "patch"] - - - package-ecosystem: "npm" - directory: "/" - target-branch: "develop" - schedule: - interval: "monthly" - open-pull-requests-limit: 3 - groups: - npm-minor-and-patch: - update-types: ["minor", "patch"] - - # The Rust crate. Grouping matters most here, and the reason is the Rust cache: its key - # includes a hash of Cargo.lock, so *any* crate bump is a cache miss, and the pull request - # then compiles all 799 crates cold on three operating systems. One grouped pull request a - # month pays that once; a pull request per crate would pay it over and over. - # - # The `drag` dependency is a git dependency (crabnebula-dev/drag-rs) and Dependabot does - # not update cargo git sources, so that one stays manual. - - package-ecosystem: "cargo" - directory: "/src-tauri" - target-branch: "develop" - schedule: - interval: "monthly" - open-pull-requests-limit: 3 - groups: - cargo-minor-and-patch: - update-types: ["minor", "patch"] diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb56d6..d361211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,14 @@ popover, not for the person who wrote the commit. find out it had worked was to close the settings and open them again, which reads as the approval having failed. It now picks the key up on its own, within a few seconds +### Security +- **The libraries built into the app are brought up to date with their security fixes.** This + covers the framework that hosts the app's window, the updater's archive unpacking, and the + TLS and certificate checks behind every connection to the sync server. None of the fixed + problems could be reached through anything Stashpad does today; this closes them before a + future change could make one reachable. The Linux build keeps one older GTK component with + a minor warning against it, until the framework moves off it + ## [1.8.7] - 2026-09-24 ### Fixed diff --git a/package-lock.json b/package-lock.json index 7a54bb1..16d17ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "stashpad", - "version": "1.6.10", + "version": "1.8.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "stashpad", - "version": "1.6.10", + "version": "1.8.7", "license": "AGPL-3.0", "dependencies": { "@tailwindcss/typography": "^0.5.19", @@ -34,8 +34,8 @@ "devDependencies": { "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/postcss": "^4.1.17", - "@tauri-apps/api": "^2.10.1", - "@tauri-apps/cli": "^2.10.0", + "@tauri-apps/api": "^2.11.1", + "@tauri-apps/cli": "^2.11.5", "@testing-library/jest-dom": "^6.9.1", "@testing-library/svelte": "^5.3.1", "@testing-library/user-event": "^14.6.1", @@ -1547,9 +1547,9 @@ } }, "node_modules/@tauri-apps/api": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz", - "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.1.tgz", + "integrity": "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==", "license": "Apache-2.0 OR MIT", "funding": { "type": "opencollective", @@ -1557,9 +1557,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.0.tgz", - "integrity": "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.5.tgz", + "integrity": "sha512-YbeJ6tctNoo40purO4u3Eeo3RVqmsjJr0NoKQRu+4pvO4gMLzkjta7x0k96SxSLmx+rQ+8um1ThOlw+HLpgFug==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -1573,23 +1573,23 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.10.0", - "@tauri-apps/cli-darwin-x64": "2.10.0", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0", - "@tauri-apps/cli-linux-arm64-gnu": "2.10.0", - "@tauri-apps/cli-linux-arm64-musl": "2.10.0", - "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0", - "@tauri-apps/cli-linux-x64-gnu": "2.10.0", - "@tauri-apps/cli-linux-x64-musl": "2.10.0", - "@tauri-apps/cli-win32-arm64-msvc": "2.10.0", - "@tauri-apps/cli-win32-ia32-msvc": "2.10.0", - "@tauri-apps/cli-win32-x64-msvc": "2.10.0" + "@tauri-apps/cli-darwin-arm64": "2.11.5", + "@tauri-apps/cli-darwin-x64": "2.11.5", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.5", + "@tauri-apps/cli-linux-arm64-gnu": "2.11.5", + "@tauri-apps/cli-linux-arm64-musl": "2.11.5", + "@tauri-apps/cli-linux-riscv64-gnu": "2.11.5", + "@tauri-apps/cli-linux-x64-gnu": "2.11.5", + "@tauri-apps/cli-linux-x64-musl": "2.11.5", + "@tauri-apps/cli-win32-arm64-msvc": "2.11.5", + "@tauri-apps/cli-win32-ia32-msvc": "2.11.5", + "@tauri-apps/cli-win32-x64-msvc": "2.11.5" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.0.tgz", - "integrity": "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.5.tgz", + "integrity": "sha512-tggOiVOohjIHdiElbjeBfB41s6cmfsq+ZQ0PX0fEtCdsDdZ9cCi54e5gNK7tdPbR6JbdDe7RA4kbQdyyBUUk/Q==", "cpu": [ "arm64" ], @@ -1604,9 +1604,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.0.tgz", - "integrity": "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.5.tgz", + "integrity": "sha512-SrO+KCbqvG1IvVPdlzQX4GEGZRQDISrmDY9bGcW68DLVFBCC06H+Loz6oyUZETUxsSMR6B4oDfvbQVgD4hxsqQ==", "cpu": [ "x64" ], @@ -1621,9 +1621,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.0.tgz", - "integrity": "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.5.tgz", + "integrity": "sha512-qLrOaCa8hLD5QVPQRjAgOXvhlTFKXmTliVF773GgvADYcWZSdmncnF5zBFAkdu1uQK8KfQbDlBUwqQYZqBfBRQ==", "cpu": [ "arm" ], @@ -1638,13 +1638,16 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.0.tgz", - "integrity": "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.5.tgz", + "integrity": "sha512-Tq32xpQjiQEdIrvwDq7lwHhXemn070CXWdbCvr9rdi9rsv9NFTbQ6izVSIfNE+59QaerxuwtUtZ5IxDNWaoYBw==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -1655,13 +1658,16 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.0.tgz", - "integrity": "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.5.tgz", + "integrity": "sha512-+OdWKj5Aq+C8HXypQ4t926V8cpVnc0ZcJIdhTXWjVAJHkaNuo8EuQR6KRZKHWIbJJgKdMPCDosvwzIFaBBqHKQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -1672,13 +1678,16 @@ } }, "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.0.tgz", - "integrity": "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.5.tgz", + "integrity": "sha512-Q0V2hjpllyDW8dWQZSsITuQDfcY9BpBZuhXkMa2T5AFLZAn+FJPXQSyvnxWNVxRowdQ59Xn0QVtGm6HEHNUEvw==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -1689,13 +1698,16 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.0.tgz", - "integrity": "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.5.tgz", + "integrity": "sha512-Xz1s87gFjZJZMQKAhLa77YeiCJM6yVog3f9OxDgVd/KxDIoB1dA5V2xOnMM+SRkOGk9juwIBqesVAjV0kUB0DA==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -1706,13 +1718,16 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.0.tgz", - "integrity": "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.5.tgz", + "integrity": "sha512-6A88wqAZXZHgMaBrGiy/Bpa4GgUnftXM7uquKOeOXCuK78/XdBxEECicK/1oHgrT179XBFOaA6lQEHysjRmGig==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -1723,9 +1738,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.0.tgz", - "integrity": "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.5.tgz", + "integrity": "sha512-sRGgF/ObRfLcS3PtUdyTbJtkGq3E+PNZTknvAURwMNUtHw9DU/BF6S5si43y9lS5yEO9bWJCA+GGYvnn6cphQw==", "cpu": [ "arm64" ], @@ -1740,9 +1755,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.0.tgz", - "integrity": "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.5.tgz", + "integrity": "sha512-bHOv/yxqfKpI7ioIFQi5wOfZ7jkbPzJD/UhXY52I/hrmE3qNh71cohIPyqZB5GQn3LZeJWdCUOqmIg/w6XX+Wg==", "cpu": [ "ia32" ], @@ -1757,9 +1772,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.0.tgz", - "integrity": "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.5.tgz", + "integrity": "sha512-vaaOmavqdCeS7oMib2banBZemgrC5v54tSkwoBV+bxrXQZhQZrOwE2EO2i4x+CHNtvQUM/6bSs3iymZMAsycWg==", "cpu": [ "x64" ], diff --git a/package.json b/package.json index b677cec..028d8b3 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "devDependencies": { "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/postcss": "^4.1.17", - "@tauri-apps/api": "^2.10.1", - "@tauri-apps/cli": "^2.10.0", + "@tauri-apps/api": "^2.11.1", + "@tauri-apps/cli": "^2.11.5", "@testing-library/jest-dom": "^6.9.1", "@testing-library/svelte": "^5.3.1", "@testing-library/user-event": "^14.6.1", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d572755..809f8d1 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -472,12 +472,27 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn 2.0.117", "which", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -613,6 +628,15 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -1029,6 +1053,19 @@ dependencies = [ "libc", ] +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "foreign-types 0.5.0", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.1.3" @@ -1118,6 +1155,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cssparser" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.13.1", + "smallvec", +] + [[package]] name = "cssparser-macros" version = "0.6.1" @@ -1130,14 +1180,20 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" dependencies = [ - "quote", - "syn 2.0.117", + "ctor-proc-macro", + "dtor", ] +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "ctr" version = "0.9.2" @@ -1175,9 +1231,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ "darling_core", "darling_macro", @@ -1185,11 +1241,10 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", "quote", @@ -1199,9 +1254,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", @@ -1243,6 +1298,37 @@ dependencies = [ "zeroize", ] +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.18", +] + [[package]] name = "deranged" version = "0.5.8" @@ -1277,6 +1363,27 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", +] + [[package]] name = "devtools-core" version = "0.3.6" @@ -1371,12 +1478,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - [[package]] name = "dispatch2" version = "0.3.1" @@ -1432,6 +1533,21 @@ dependencies = [ "const-random", ] +[[package]] +name = "dom_query" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" +dependencies = [ + "bit-set", + "cssparser 0.36.0", + "foldhash 0.2.0", + "html5ever 0.38.0", + "precomputed-hash", + "selectors 0.36.1", + "tendril 0.5.1", +] + [[package]] name = "dpi" version = "0.1.2" @@ -1475,6 +1591,21 @@ dependencies = [ "dtoa", ] +[[package]] +name = "dtor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dunce" version = "1.0.5" @@ -1734,6 +1865,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2326,7 +2463,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -2403,10 +2540,20 @@ checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.14.1", "match_token", ] +[[package]] +name = "html5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" +dependencies = [ + "log", + "markup5ever 0.38.0", +] + [[package]] name = "http" version = "0.2.12" @@ -2878,6 +3025,60 @@ dependencies = [ "system-deps", ] +[[package]] +name = "jiff" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link 0.2.1", +] + +[[package]] +name = "jiff-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" +dependencies = [ + "defmt", + "log", +] + +[[package]] +name = "jiff-static" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "jni" version = "0.21.1" @@ -2965,10 +3166,10 @@ version = "0.8.8-speedreader" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" dependencies = [ - "cssparser", - "html5ever", + "cssparser 0.29.6", + "html5ever 0.29.1", "indexmap 2.13.0", - "selectors", + "selectors 0.24.0", ] [[package]] @@ -3143,9 +3344,20 @@ dependencies = [ "log", "phf 0.11.3", "phf_codegen 0.11.3", - "string_cache", - "string_cache_codegen", - "tendril", + "string_cache 0.8.9", + "string_cache_codegen 0.5.4", + "tendril 0.4.3", +] + +[[package]] +name = "markup5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" +dependencies = [ + "log", + "tendril 0.5.1", + "web_atoms", ] [[package]] @@ -3256,9 +3468,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.17.1" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" dependencies = [ "crossbeam-channel", "dpi", @@ -3269,10 +3481,10 @@ dependencies = [ "objc2-core-foundation", "objc2-foundation 0.3.2", "once_cell", - "png 0.17.16", + "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3307,12 +3519,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - [[package]] name = "ndk-sys" version = "0.6.0+11769913" @@ -3559,17 +3765,10 @@ checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.11.0", "block2 0.6.2", - "libc", "objc2 0.6.4", - "objc2-cloud-kit", - "objc2-core-data 0.3.2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-core-image 0.3.2", - "objc2-core-text", - "objc2-core-video", "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", ] [[package]] @@ -3601,7 +3800,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "bitflags 2.11.0", "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -3653,28 +3851,25 @@ dependencies = [ ] [[package]] -name = "objc2-core-text" +name = "objc2-core-location" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" dependencies = [ - "bitflags 2.11.0", "objc2 0.6.4", - "objc2-core-foundation", - "objc2-core-graphics", + "objc2-foundation 0.3.2", ] [[package]] -name = "objc2-core-video" +name = "objc2-core-text" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ "bitflags 2.11.0", "objc2 0.6.4", "objc2-core-foundation", "objc2-core-graphics", - "objc2-io-surface", ] [[package]] @@ -3728,16 +3923,6 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "objc2-javascript-core" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586" -dependencies = [ - "objc2 0.6.4", - "objc2-core-foundation", -] - [[package]] name = "objc2-metal" version = "0.2.2" @@ -3788,25 +3973,33 @@ dependencies = [ ] [[package]] -name = "objc2-security" +name = "objc2-ui-kit" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.11.0", + "block2 0.6.2", "objc2 0.6.4", + "objc2-cloud-kit", + "objc2-core-data 0.3.2", "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", + "objc2-user-notifications", ] [[package]] -name = "objc2-ui-kit" +name = "objc2-user-notifications" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" dependencies = [ - "bitflags 2.11.0", "objc2 0.6.4", - "objc2-core-foundation", "objc2-foundation 0.3.2", ] @@ -3822,8 +4015,6 @@ dependencies = [ "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-foundation 0.3.2", - "objc2-javascript-core", - "objc2-security", ] [[package]] @@ -3852,15 +4043,14 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ "bitflags 2.11.0", "cfg-if", "foreign-types 0.3.2", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -3884,9 +4074,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -4053,10 +4243,20 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_macros 0.11.3", "phf_shared 0.11.3", ] +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros 0.13.1", + "phf_shared 0.13.1", + "serde", +] + [[package]] name = "phf_codegen" version = "0.8.0" @@ -4077,6 +4277,16 @@ dependencies = [ "phf_shared 0.11.3", ] +[[package]] +name = "phf_codegen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", +] + [[package]] name = "phf_generator" version = "0.8.0" @@ -4094,7 +4304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ "phf_shared 0.10.0", - "rand 0.8.5", + "rand 0.8.8", ] [[package]] @@ -4104,7 +4314,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared 0.11.3", - "rand 0.8.5", + "rand 0.8.8", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared 0.13.1", ] [[package]] @@ -4123,12 +4343,12 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", "syn 2.0.117", @@ -4161,6 +4381,15 @@ dependencies = [ "siphasher 1.0.2", ] +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher 1.0.2", +] + [[package]] name = "pin-project" version = "1.1.11" @@ -4534,9 +4763,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -4545,9 +4774,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -4923,7 +5152,7 @@ dependencies = [ "borsh", "bytes", "num-traits", - "rand 0.8.5", + "rand 0.8.8", "rkyv", "serde", "serde_json", @@ -4935,6 +5164,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -5034,9 +5269,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.9" +version = "0.103.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" dependencies = [ "ring", "rustls-pki-types", @@ -5149,7 +5384,7 @@ dependencies = [ "hkdf", "num", "once_cell", - "rand 0.8.5", + "rand 0.8.8", "serde", "sha2", "zbus 4.4.0", @@ -5198,14 +5433,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" dependencies = [ "bitflags 1.3.2", - "cssparser", - "derive_more", + "cssparser 0.29.6", + "derive_more 0.99.20", "fxhash", "log", "phf 0.8.0", "phf_codegen 0.8.0", "precomputed-hash", - "servo_arc", + "servo_arc 0.2.0", + "smallvec", +] + +[[package]] +name = "selectors" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" +dependencies = [ + "bitflags 2.11.0", + "cssparser 0.36.0", + "derive_more 2.1.1", + "log", + "new_debug_unreachable", + "phf 0.13.1", + "phf_codegen 0.13.1", + "precomputed-hash", + "rustc-hash 2.1.3", + "servo_arc 0.4.3", "smallvec", ] @@ -5328,15 +5582,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.17.0" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" +checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" dependencies = [ "base64 0.22.1", + "bs58", "chrono", "hex", "indexmap 1.9.3", "indexmap 2.13.0", + "jiff", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -5347,9 +5603,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.17.0" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" +checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" dependencies = [ "darling", "proc-macro2", @@ -5402,6 +5658,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "servo_arc" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha1" version = "0.10.6" @@ -5610,7 +5875,7 @@ dependencies = [ "keyring", "log", "mime_guess", - "rand 0.8.5", + "rand 0.8.8", "regex", "reqwest 0.12.28", "rusqlite", @@ -5663,6 +5928,18 @@ dependencies = [ "serde", ] +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.13.1", + "precomputed-hash", +] + [[package]] name = "string_cache_codegen" version = "0.5.4" @@ -5675,6 +5952,18 @@ dependencies = [ "quote", ] +[[package]] +name = "string_cache_codegen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", + "proc-macro2", + "quote", +] + [[package]] name = "strsim" version = "0.11.1" @@ -5782,35 +6071,35 @@ dependencies = [ [[package]] name = "tao" -version = "0.34.5" +version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a753bdc39c07b192151523a3f77cd0394aa75413802c883a0f6f6a0e5ee2e7" +checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ "bitflags 2.11.0", "block2 0.6.2", "core-foundation 0.10.1", - "core-graphics 0.24.0", + "core-graphics 0.25.0", "crossbeam-channel", - "dispatch", + "dbus", + "dispatch2", "dlopen2", "dpi", "gdkwayland-sys", "gdkx11-sys", "gtk", "jni", - "lazy_static", "libc", "log", "ndk", - "ndk-context", "ndk-sys", "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-foundation 0.3.2", + "objc2-ui-kit", "once_cell", "parking_lot", + "percent-encoding", "raw-window-handle", - "scopeguard", "tao-macros", "unicode-segmentation", "url", @@ -5839,9 +6128,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.44" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -5856,9 +6145,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.10.2" +version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463ae8677aa6d0f063a900b9c41ecd4ac2b7ca82f0b058cc4491540e55b20129" +checksum = "6fa5bacdb9bbad5954af3d1bd6cf6ae9192cab1b2e270f4a07f904610b9e85f4" dependencies = [ "anyhow", "bytes", @@ -5909,9 +6198,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.5.5" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca7bd893329425df750813e95bd2b643d5369d929438da96d5bbb7cc2c918f74" +checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632" dependencies = [ "anyhow", "cargo_toml", @@ -5925,15 +6214,14 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml 0.9.12+spec-1.1.0", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.5.4" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac423e5859d9f9ccdd32e3cf6a5866a15bedbf25aa6630bcb2acde9468f6ae3" +checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" dependencies = [ "base64 0.22.1", "brotli", @@ -5958,9 +6246,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.5.4" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a1bd2861ff0c8766b1d38b32a6a410f6dc6532d4ef534c47cfb2236092f59" +checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -6245,9 +6533,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b885ffeac82b00f1f6fd292b6e5aabfa7435d537cef57d11e38a489956535651" +checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8" dependencies = [ "cookie", "dpi", @@ -6270,9 +6558,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.10.0" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5204682391625e867d16584fedc83fc292fb998814c9f7918605c789cd876314" +checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" dependencies = [ "gtk", "http 1.4.0", @@ -6280,7 +6568,6 @@ dependencies = [ "log", "objc2 0.6.4", "objc2-app-kit 0.3.2", - "objc2-foundation 0.3.2", "once_cell", "percent-encoding", "raw-window-handle", @@ -6298,24 +6585,26 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.8.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd169fccdff05eff2c1033210b9b94acd07a47e6fa9a3431cf09cfd4f01c87e" +checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" dependencies = [ "anyhow", "brotli", "cargo_metadata", "ctor", + "dom_query", "dunce", "glob", - "html5ever", + "html5ever 0.29.1", "http 1.4.0", "infer", "json-patch", "kuchikiki", "log", "memchr", - "phf 0.11.3", + "phf 0.13.1", + "plist", "proc-macro2", "quote", "regex", @@ -6369,6 +6658,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tendril" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08" +dependencies = [ + "new_debug_unreachable", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -6760,7 +7058,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", + "rand 0.8.8", "slab", "tokio", "tokio-util", @@ -6896,9 +7194,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.21.3" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" +checksum = "045979e3f037cd18ad1cb2a419dfda133c5c29c9f3453370079f2255d46c257e" dependencies = [ "crossbeam-channel", "dirs 6.0.0", @@ -6910,10 +7208,10 @@ dependencies = [ "objc2-core-graphics", "objc2-foundation 0.3.2", "once_cell", - "png 0.17.16", + "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6934,7 +7232,7 @@ dependencies = [ "httparse", "log", "native-tls", - "rand 0.9.2", + "rand 0.9.5", "sha1", "thiserror 2.0.18", "utf-8", @@ -7326,6 +7624,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web_atoms" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8b815c1b593dc0baf78dd0f4fc8fdb2de53198fb1163738093e9a311c33fb3" +dependencies = [ + "phf 0.13.1", + "phf_codegen 0.13.1", + "string_cache 0.9.0", + "string_cache_codegen 0.6.1", +] + [[package]] name = "webkit2gtk" version = "2.0.2" @@ -8208,24 +8518,23 @@ checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wry" -version = "0.54.2" +version = "0.55.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb26159b420aa77684589a744ae9a9461a95395b848764ad12290a14d960a11a" +checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" dependencies = [ "base64 0.22.1", "block2 0.6.2", "cookie", "crossbeam-channel", "dirs 6.0.0", + "dom_query", "dpi", "dunce", "gdkx11", "gtk", - "html5ever", "http 1.4.0", "javascriptcore-rs", "jni", - "kuchikiki", "libc", "ndk", "objc2 0.6.4", @@ -8389,7 +8698,7 @@ dependencies = [ "hex", "nix", "ordered-stream", - "rand 0.8.5", + "rand 0.8.8", "serde", "serde_repr", "sha1", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2fb31be..c5af685 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -21,7 +21,7 @@ tauri-build = { version = "2.5.3", features = [] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } log = "0.4" -tauri = { version = "2.9.4", features = ["protocol-asset"] } +tauri = { version = "2.11.1", features = ["protocol-asset"] } tauri-plugin-log = "2" tauri-plugin-updater = "2" tauri-plugin-process = "2" From ad135fd16614ca183ca77ad5e07d88aa162587a1 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Fri, 25 Sep 2026 01:06:17 +0200 Subject: [PATCH 10/10] chore: bump version to v1.8.8 Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 2 ++ package.json | 2 +- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d361211..6413c39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ popover, not for the person who wrote the commit. ## [Unreleased] +## [1.8.8] - 2026-09-25 + ### Changed - **Approving a new computer is a tick, not a retyped code.** You had to read the sixteen characters off one screen and type them into the other before the approve button would diff --git a/package.json b/package.json index 028d8b3..e86bb4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stashpad", - "version": "1.8.7", + "version": "1.8.8", "description": "The staging area for your AI context.", "author": { "name": "Nico Wiedemann", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 809f8d1..d2f771b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -5858,7 +5858,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stashpad" -version = "1.8.7" +version = "1.8.8" dependencies = [ "active-win-pos-rs", "aes-gcm", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c5af685..4edfa68 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stashpad" -version = "1.8.7" +version = "1.8.8" description = "The staging area for your AI context." authors = ["Nico Wiedemann "] repository = "https://github.com/EarMaster/stashpad" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2b86ef8..f51f177 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "stashpad", - "version": "1.8.7", + "version": "1.8.8", "identifier": "org.stashpad", "build": { "frontendDist": "../dist",