v2026.3
Changes
chore(deps): Bump the frontend-dependencies group across 1 directory with 11 updates -
@dependabot[bot] in #118
Bumps the frontend-dependencies group with 11 updates in the /frontend directory:
| Package | From | To |
|---|---|---|
| @fontsource/familjen-grotesk | 5.2.8 |
5.3.0 |
| @fontsource/spline-sans-mono | 5.2.8 |
5.3.0 |
| @tabler/icons-svelte | 3.44.0 |
3.45.0 |
| @tiptap/core | 3.27.3 |
3.28.0 |
| @tiptap/extension-link | 3.27.3 |
3.28.0 |
| @tiptap/pm | 3.27.3 |
3.28.0 |
| @tiptap/starter-kit | 3.27.3 |
3.28.0 |
| marked | 18.0.6 |
18.0.7 |
| svelte | 5.56.4 |
5.56.7 |
| svelte-check | 4.7.2 |
4.7.3 |
| vite | 8.1.4 |
8.1.5 |
Updates @fontsource/familjen-grotesk from 5.2.8 to 5.3.0
Commits
- See full diff in compare view
Updates @fontsource/spline-sans-mono from 5.2.8 to 5.3.0
Commits
- See full diff in compare view
Updates @tabler/icons-svelte from 3.44.0 to 3.45.0
Release notes
Sourced from @tabler/icons-svelte's releases.
Release 3.45.0
20 new icons:
filled/brand-signaloutline/app-window-bottom-leftoutline/app-window-bottom-rightoutline/app-window-bottomoutline/app-window-centeroutline/arrow-fork-tripleoutline/brand-signaloutline/device-vision-pro-wifioutline/device-workstationoutline/dragonoutline/italic-offoutline/tab-closeoutline/text-outlineoutline/text-regex-asteriskoutline/text-regex-endoutline/text-regex-plusoutline/text-regex-questionoutline/text-regex-startoutline/underline-offoutline/virtual-spaceNew features
- New package:
@tabler/icons-astro— Astro support- Added
sideEffects: falsefor better tree-shaking in Vue package- Spelling fixes: corrected misspelled icon names
Fixed icons:
outline/flip-horizontal,outline/flip-verticalRenamed icons:
filled/mood-confuzedrenamed tofilled/mood-confusedoutline/brand-adobe-after-effectrenamed tooutline/brand-adobe-after-effectsoutline/brand-kako-talkrenamed tooutline/brand-kakao-talkoutline/currency-rubelrenamed tooutline/currency-rubleoutline/foodstepsrenamed tooutline/footstepsoutline/gender-trasvestirenamed tooutline/gender-travestioutline/ikosaedrrenamed tooutline/icosahedronoutline/mood-confuzedrenamed tooutline/mood-confusedoutline/physotherapistrenamed tooutline/physiotherapistoutline/sport-billardrenamed tooutline/sport-billiard
Commits
975920fRelease 3.45.04a4b287Add Astro support for Tabler Icons (#1559)- See full diff in compare view
Updates @tiptap/core from 3.27.3 to 3.28.0
Release notes
Sourced from @tiptap/core's releases.
v3.28.0
@tiptap/extension-detailsPatch Changes
- 8614730: Fix the cursor moving to the details summary after typing in content at the start of a document.
@tiptap/core@3.28.0
@tiptap/extension-listPatch Changes
- 8614730: Fix markdown parsing a line like
(216) 555-1234as an ordered list. A number followed by)mid-line is no longer treated as a list marker.@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/reactPatch Changes
- 8614730: Batch React node view portal store notifications that happen in the same microtask to avoid nested update depth warnings when many node views mount together.
- 8614730: Bind onMount and onUnmount event handlers when initializing an Editor with useEditor hook.
@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaboration-caretPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaborationPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-drag-handlePatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version- Updated dependencies [8614730]
@tiptap/extension-collaboration@3.28.0
... (truncated)
Changelog
Sourced from @tiptap/core's changelog.
3.28.0
Patch Changes
@tiptap/pm@3.28.03.27.4
Patch Changes
@tiptap/pm@3.27.4
Commits
c5f4b57chore(release): release new stable release (#8038)24263ecchore(release): publish a new stable version- See full diff in compare view
Updates @tiptap/extension-link from 3.27.3 to 3.28.0
Release notes
Sourced from @tiptap/extension-link's releases.
v3.28.0
@tiptap/extension-detailsPatch Changes
- 8614730: Fix the cursor moving to the details summary after typing in content at the start of a document.
@tiptap/core@3.28.0
@tiptap/extension-listPatch Changes
- 8614730: Fix markdown parsing a line like
(216) 555-1234as an ordered list. A number followed by)mid-line is no longer treated as a list marker.@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/reactPatch Changes
- 8614730: Batch React node view portal store notifications that happen in the same microtask to avoid nested update depth warnings when many node views mount together.
- 8614730: Bind onMount and onUnmount event handlers when initializing an Editor with useEditor hook.
@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaboration-caretPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaborationPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-drag-handlePatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version- Updated dependencies [8614730]
@tiptap/extension-collaboration@3.28.0
... (truncated)
Changelog
Sourced from @tiptap/extension-link's changelog.
3.28.0
Patch Changes
3.27.4
Patch Changes
Commits
c5f4b57chore(release): release new stable release (#8038)24263ecchore(release): publish a new stable version- See full diff in compare view
Updates @tiptap/pm from 3.27.3 to 3.28.0
Release notes
Sourced from @tiptap/pm's releases.
v3.28.0
@tiptap/extension-detailsPatch Changes
- 8614730: Fix the cursor moving to the details summary after typing in content at the start of a document.
@tiptap/core@3.28.0
@tiptap/extension-listPatch Changes
- 8614730: Fix markdown parsing a line like
(216) 555-1234as an ordered list. A number followed by)mid-line is no longer treated as a list marker.@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/reactPatch Changes
- 8614730: Batch React node view portal store notifications that happen in the same microtask to avoid nested update depth warnings when many node views mount together.
- 8614730: Bind onMount and onUnmount event handlers when initializing an Editor with useEditor hook.
@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaboration-caretPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaborationPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-drag-handlePatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version- Updated dependencies [8614730]
@tiptap/extension-collaboration@3.28.0
... (truncated)
Commits
c5f4b57chore(release): release new stable release (#8038)24263ecchore(release): publish a new stable version- See full diff in compare view
Updates @tiptap/starter-kit from 3.27.3 to 3.28.0
Release notes
Sourced from @tiptap/starter-kit's releases.
v3.28.0
@tiptap/extension-detailsPatch Changes
- 8614730: Fix the cursor moving to the details summary after typing in content at the start of a document.
@tiptap/core@3.28.0
@tiptap/extension-listPatch Changes
- 8614730: Fix markdown parsing a line like
(216) 555-1234as an ordered list. A number followed by)mid-line is no longer treated as a list marker.@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/reactPatch Changes
- 8614730: Batch React node view portal store notifications that happen in the same microtask to avoid nested update depth warnings when many node views mount together.
- 8614730: Bind onMount and onUnmount event handlers when initializing an Editor with useEditor hook.
@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaboration-caretPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-collaborationPatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version@tiptap/core@3.28.0
@tiptap/pm@3.28.0
@tiptap/extension-drag-handlePatch Changes
- 8614730: Bump
@tiptap/y-tiptapversion to ensure users use latest version- Updated dependencies [8614730]
@tiptap/extension-collaboration@3.28.0
... (truncated)
Changelog
Sourced from @tiptap/starter-kit's changelog.
3.28.0
Patch Changes
- Updated dependencies [c1254c1]
@tiptap/extension-list@3.28.0@tiptap/extension-list-item@3.28.0@tiptap/extension-list-keymap@3.28.0@tiptap/extension-bullet-list@3.28.0@tiptap/extension-ordered-list@3.28.0@tiptap/extension-dropcursor@3.28.0@tiptap/extension-gapcursor@3.28.0@tiptap/core@3.28.0@tiptap/extension-blockquote@3.28.0@tiptap/extension-bold@3.28.0@tiptap/extension-code@3.28.0@tiptap/extension-code-block@3.28.0@tiptap/extension-document@3.28.0@tiptap/extension-hard-break@3.28.0@tiptap/extension-heading@3.28.0@tiptap/extension-horizontal-rule@3.28.0@tiptap/extension-italic@3.28.0@tiptap/extension-link@3.28.0@tiptap/extension-paragraph@3.28.0@tiptap/extension-strike@3.28.0@tiptap/extension-text@3.28.0@tiptap/extension-underline@3.28.0@tiptap/extensions@3.28.0@tiptap/pm@3.28.03.27.4
Patch Changes
- Updated dependencies [d2983cd]
- Updated dependencies [53f8e57]
- Updated dependencies [6238a3c]
- Updated dependencies [c28d888]
@tiptap/extensions@3.27.4@tiptap/extension-blockquote@3.27.4@tiptap/extension-list@3.27.4@tiptap/extension-dropcursor@3.27.4@tiptap/extension-gapcursor@3.27.4@tiptap/extension-list-item@3.27.4@tiptap/extension-list-keymap@3.27.4@tiptap/extension-bullet-list@3.27.4@tiptap/extension-ordered-list@3.27.4@tiptap/core@3.27.4@tiptap/extension-bold@3.27.4@tiptap/extension-code@3.27.4
... (truncated)
Commits
c5f4b57chore(release): release new stable release (#8038)24263ecchore(release): publish a new stable version- See full diff in compare view
Updates marked from 18.0.6 to 18.0.7
Release notes
Sourced from marked's releases.
v18.0.7
18.0.7 (2026-07-21)
Bug Fixes
- Avoid O(n^2) backtracking in HTML block close and tilde interrupt regexes (#4014) (f945fc5), closes #3991
- Avoid O(n^2) masked source rebuild in inline tokenizer (#4017) (9154f8f)
- keep empty list after blockquote as a sibling block (#4004) (3f144a0)
- preserve code spans adjacent to tildes (#4012) (0de7188)
- Recognize setext headings whose first line starts with # (#4015) (f056437), closes #1
- treat a line of only tabs as a blank line between paragraphs (#4007) (bc2f121)
Commits
a8971a1chore(release): 18.0.7 [skip ci]d899c2echore(deps): bump actions/setup-node from 6 to 7 (#4025)7fbf82echore(deps-dev): bump semantic-release from 25.0.7 to 25.0.8 (#4026)738edf2chore(deps-dev): bump brace-expansion from 5.0.2 to 5.0.6 (#4027)9154f8ffix: Avoid O(n^2) masked source rebuild in inline tokenizer (#4017)f945fc5fix: Avoid O(n^2) backtracking in HTML block close and tilde interrupt regexe...3f144a0fix: keep empty list after blockquote as a sibling block (#4004)0de7188fix: preserve code spans adjacent to tildes (#4012)f056437fix: Recognize setext headings whose first line starts with # (#4015)12bfa94chore(deps-dev): bump semantic-release from 25.0.5 to 25.0.7 (#4020)- Additional commits viewable in compare view
Updates svelte from 5.56.4 to 5.56.7
Release notes
Sourced from svelte's releases.
svelte@5.56.7
Patch Changes
- chore: provide
indentoption forsvelte@5.56.6
Patch Changes
perf: skip unnecessary blocker analysis when compiling components without top-level await (#18548)
fix: rerun derived that had an abort controller on reconnection (#18551)
svelte@5.56.5
Patch Changes
chore: drop dead code that make TSGO fail (#18496)
fix: don't (re)connect deriveds when read inside branch/root effects (#18527)
fix: skip unnecessary derived effect in earlier batch (#18525)
fix: avoid declaration tag warning in event handlers (#18500)
fix: abort deriveds own AbortSignal when it disconnects (#18400)
fix: ensure
$state.eager()is correctly transormed for SSR output (#18530)fix: correctly transform declaration tags during SSR (#18492)
fix: transform computed keys in keyed
{#each}destructuring patterns (#18521)fix: chain preprocessor sourcemaps with an empty
sources[0]instead of dropping them (#18518)fix: clear previous_task reference after abort in Tween to prevent memory leak on interrupted tweens (#18541)
fix: don't treat declaration tags as parts inside each blocks (#18507)
Changelog
Sourced from svelte's changelog.
5.56.7
Patch Changes
- chore: provide
indentoption for5.56.6
Patch Changes
perf: skip unnecessary blocker analysis when compiling components without top-level await (#18548)
fix: rerun derived that had an abort controller on reconnection (#18551)
5.56.5
Patch Changes
chore: drop dead code that make TSGO fail (#18496)
fix: don't (re)connect deriveds when read inside branch/root effects (#18527)
fix: skip unnecessary derived effect in earlier batch (#18525)
fix: avoid declaration tag warning in event handlers (#18500)
fix: abort deriveds own AbortSignal when it disconnects (#18400)
fix: ensure
$state.eager()is correctly transormed for SSR output (#18530)fix: correctly transform declaration tags during SSR (#18492)
fix: transform computed keys in keyed
{#each}destructuring patterns (#18521)fix: chain preprocessor sourcemaps with an empty
sources[0]instead of dropping them (#18518)fix: clear previous_task reference after abort in Tween to prevent memory leak on interrupted tweens (#18541)
fix: don't treat declaration tags as parts inside each blocks (#18507)
Commits
b29d700Version Packages (#18560)b791cacchore: provideindentoption forprint(#18474)4a6a85bVersion Packages (#18552)d0dbe1aperf: skip quadratic blocker analysis when no top-level await (#18548)22e0adbfix: rerun derived that had an abort controller on reconnection (#18551)602a873Version Packages (#18497)a4fd67efix: $state.eager() is sometimes incorrect in SSR (#18530)199ffebfix: clear previous_task reference after abort in Tween (#18541)edeef1fchore: add some failing tests (#18528)a91b068fix: abort deriveds own AbortSignal when it disconnects (#18400)- Additional commits viewable in compare view
Updates svelte-check from 4.7.2 to 4.7.3
Release notes
Sourced from svelte-check's releases.
svelte-check@4.7.3
Patch Changes
- feat: zero-config
+error.svelteprops (#3076)
Commits
6a7012cVersion Packages (#3077)d653640feat: zero-config+error.svelteprops (#3076)- See full diff in compare view
Updates vite from 8.1.4 to 8.1.5
Changelog
Sourced from vite's changelog.
8.1.5 (2026-07-16)
Bug Fixes
- bundled-dev: avoid duplicated
buildEnd(#22931) (8100320)- client: overlay error message format align rolldown (#22869) (5a72b87)
- deps: update all non-major dependencies (#22921) (fef682d)
- deps: update rolldown-related dependencies (#22922) (3c345e4)
- module-runner: don't crash stack-trace source mapping when globalThis.Buffer is absent (#22945) (f8b38e3)
- optimizer: respect importer module format for dynamic import interop with CJS deps (#22951) (6c08c39)
- ssr: scope switch-case declarations to the switch, not the function (#22893) (b59a73f)
Documentation
- build: fix incorrect
@defaultfor build.cssMinify (#22948) (c88c236)- build: fix incorrect
@defaultfor build.lib.formats (#22911) (369ed60)Tests
Commits
5e7fe12release: v8.1.56c08c39fix(optimizer): respect importer module format for dynamic import interop wit...5a72b87fix(client): overlay error message format align rolldown (#22869)f8b38e3fix(module-runner): don't crash stack-trace source mapping when globalThis.Bu...8100320fix(bundled-dev): avoid duplicatedbuildEnd(#22931)c88c236docs(build): fix incorrect@defaultfor build.cssMinify (#22948)b59a73ffix(ssr): scope switch-case declarations to the switch, not the function (#22...fef682dfix(deps): update all non-major dependencies (#22921)3c345e4fix(deps): update rolldown-related dependencies (#22922)369ed60docs(build): fix incorrect@defaultfor build.lib.formats (#22911)- Additional commits viewable in compare view
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore <dependency name> major versionwill close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)@dependabot ignore <dependency name> minor versionwill close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)@dependabot ignore <dependency name>will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)@dependabot unignore <dependency name>will remove all of the ignore conditions of the specified dependency@dependabot unignore <dependency name> <ignore condition>will remove the ignore condition of the specified dependency and ignore conditions
chore(deps): Bump the go-dependencies group across 1 directory with 4 updates -
@dependabot[bot] in #114
Bumps the go-dependencies group with 3 updates in the / directory: github.com/yuin/goldmark, golang.org/x/crypto and modernc.org/sqlite.
Updates github.com/yuin/goldmark from 1.8.2 to 1.8.4
Release notes
Sourced from github.com/yuin/goldmark's releases.
v1.8.4
fix: disable svg in data:image urls
v1.8.3
Full Changelog: yuin/goldmark@v1.8.2...v1.8.3
- fix: #556
Commits
50ba9fcfix: disable svg in data:image urls2326684fix: #556- See full diff in compare view
Updates golang.org/x/crypto from 0.52.0 to 0.54.0
Commits
cdce021go.mod: update golang.org/x dependenciesd9474ccopenpgp: make the deprecation message more explicit7626c50ssh: verify declared key type matches decoded key in authorized_keys0471e79ssh/agent: enforce strict limits on DSA key parameters6435c37ssh: sanitize client disconnect messages7d695dassh/agent: drain channel stderr in agent forwarders5b7f841acme/autocert: fix data race in Manager.createCert0b316e7argon2: update RFC 9106 parameter recommendations55aec0ax509roots/fallback: update bundle5f2de1ainternal: remove wycheproof tests- Additional commits viewable in compare view
Updates golang.org/x/net from 0.55.0 to 0.56.0
Commits
9e7fdbfinternal/http3: fix wrong argument being given when validating header valueb686e5finternal/http3: add gzip support to transport8a34885go.mod: update golang.org/x dependencies72eaf98dns/dnsmessage: correctly validate SVCB record parameter order82e7868dns/dnsmessage: avoid panic when parsing SVCB record with truncated datab64f1fainternal/http3: add server support for "Trailer:" magic prefix2707ee2internal/http3: implement HTTP/3 clientConn methods31358ccinternal/http3: snapshot response headers at WriteHeader time8ecbaa9html: don't adjust xml:base8ae811ahtml: properly handle end script tag in fragment mode- Additional commits viewable in compare view
Updates modernc.org/sqlite from 1.53.0 to 1.54.0
Changelog
Sourced from modernc.org/sqlite's changelog.
Changelog
2026-07-20 v1.55.0:
- Add
github.com/mattn/go-sqlite3-compatible shorthand DSN query parameters to ease migration from that driver:_busy_timeout/_timeout,_foreign_keys/_fk,_journal_mode/_journal,_synchronous/_sync,_auto_vacuum/_vacuum, and_query_only, each setting the correspondingly named PRAGMA. Values are validated against the same setmattn/go-sqlite3accepts (case-insensitive) and an unrecognized value fails the connection with an error, so a typo such as_synchronous=fu1lor_foreign_keys=yes_pleaseis reported rather than silently downgrading durability or dropping foreign-key enforcement. The keys are applied in a fixed order independent of their order in the DSN —_busy_timeoutand_auto_vacuumbefore any_pragmavalues (auto_vacuummust be set before the database is first written), the rest after, and_query_onlylast — and where a key and its alias are both supplied the alias wins, matchingmattn/go-sqlite3; selection is by presence rather than by value, so supplying the alias empty (_foreign_keys=on&_fk=) suppresses the PRAGMA rather than deferring to the primary key, again matching that driver. Behavior change to note: prior releases ignored these keys entirely, so a DSN carried over from amattn/go-sqlite3setup changes in two ways. A recognized key that previously did nothing now takes effect —_foreign_keys=onbegins enforcing constraints against data that may already violate them,_journal_mode=walpersistently converts the database file, and_query_only=1makes the connection read-only. And a value outside the accepted set now fails the connection with an error where the same DSN previously opened successfully — for example a duration-style_busy_timeout=5sor_timeout=5000ms, neither of which is the integer that key requires. Review such DSNs before upgrading._pragmais unchanged and no pre-existing parameter changes meaning, though see the following entry for a change in when all of them are validated.- See [GitLab merge request #134](https://gitlab.com/cznic/sqlite/-/merge_requests/134), thanks Toni Spets (
@beeper-hifi) and Ian Chechin!- Validate every DSN query parameter before applying any of them. Parameters were previously checked as each was reached, so a DSN whose later parameter was rejected had already executed the PRAGMAs ahead of it. Because
PRAGMA journal_modeandPRAGMA auto_vacuumare persistent changes to the database file, a DSN such asfile:x.db?_journal_mode=wal&_synchronous=bogusfailed the connection and yet leftx.dbconverted to WAL. A failedOpennow leaves the database as it found it. This covers the pre-existing_txlock,_timezone,_time_format,_time_integer_format,_inttotimeand_texttotimeparameters as well as the shorthand keys above: all of them were validated only after the_pragmalist had already run, so the same DSN shape — a valid_pragma=journal_mode=walalongside a misspelled_txlock— converted the file before reporting the error. Only the values accepted for each parameter are unchanged; a DSN that opened successfully before still opens, and one that failed still fails with the same error._pragmaremains the sole exception, since its values are executed verbatim and cannot be checked in advance: a malformed_pragmais still rejected by SQLite as it runs, after any earlier_pragmain the list has taken effect.2026-07-15 v1.54.0:
- Upgrade to SQLite 3.53.3. This also bumps the pinned
modernc.org/libcto v1.74.1; as always, downstream modules must pin the exact samemodernc.org/libcversion this module'sgo.modpins (see [GitLab issue #177](https://gitlab.com/cznic/sqlite/-/issues/177)).- Under the opt-in
_texttotimeDSN parameter, best-effort parse date-shaped TEXT values from columns SQLite reports with an empty declared type — aggregates and expressions over a date column (MAX(d),COALESCE(d, ...),upper(d),d || ''), subqueries, and typeless real columns (CREATE TABLE t(x)) — intotime.Time, instead of delivering them as a raw string thatScancannot store into a*time.Time. The existing declaredDATE/DATETIME/TIME/TIMESTAMPpath is unchanged; this only adds the empty-decltype case. The conversion is strictly best-effort: a value that does not parse as a time falls through to the original string, so noScanthat worked before can newly fail.ColumnTypeScanTypecontinues to reportstringfor empty-decltype columns, since the declared type cannot prove the column is temporal. Without_texttotimethe behavior is byte-for-byte unchanged. Resolves [GitLab issue #248](https://gitlab.com/cznic/sqlite/-/issues/248).- See [GitLab merge request #133](https://gitlab.com/cznic/sqlite/-/merge_requests/133), thanks Ian Chechin!
2026-06-21 v1.53.0:
- Add experimental
netbsd/amd64support, resolving the long-standing build break in [GitLab issue #246](https://gitlab.com/cznic/sqlite/-/issues/246). This target is intentionally not yet listed among the supported platforms in the package documentation: the port had been broken for years and is only now revived, and there is as yet no real-world experience running it under production workloads. Green CI is not the same as battle-tested — so while the full test suite (including thepcacheandvecpackages and the-raceconcurrency test) passes on NetBSD 10.1 / Go 1.26.3, and the entire upstream toolchain (libc,cc,ccgo,libz,libtcl8.6,libsqlite3,libsqlite_vec) is green on the NetBSD CI builder, the target is offered for evaluation only. If you run NetBSD, please exercise it with your own workloads and report back via #246; the intent is to promote it to a fully supported platform after a period of broader real-world testing (on the order of a month) elapses without surprises.- Implementation notes: the previously shipped
lib/sqlite_netbsd_amd64.gowas a stale old-generator transpile that no longer compiled (themu.enter/mu.leavebreak in #246); it is replaced by a fresh new-generator transpile consistent with every other platform, andmodernc.org/sqlite/vec(sqlite-vec) is vendored and auto-registers on netbsd. Correct operation requires the matching pinnedmodernc.org/libc, which carries two NetBSD-specific fixes found during this work: themmap(2)PAD-argument ABI (without it, concurrent WAL access faults with SIGBUS in the WAL-index shared memory) and a workingabort(3)(the prior stub left SQLite's crash-recoverywritecrashtest unable to terminate by signal). As usual, downstream modules must pin the exactmodernc.org/libcversion this module'sgo.modpins.- See [GitLab merge request #82](https://gitlab.com/cznic/sqlite/-/merge_requests/82), thanks Leonardo Taccari (
@iamleot) and Thomas Klausner (@wiz)!- Add experimental
freebsd/386andfreebsd/armsupport. As with thenetbsd/amd64target above, these two 32-bit FreeBSD ports are intentionally not yet listed among the supported platforms in the package documentation:freebsd/386previously shipped a stale, effectively untested SQLite 3.41 transpile, andfreebsd/armis entirely new, so neither has real-world production mileage yet. Both are now freshly transpiled at SQLite 3.53.2 consistent with every other platform, build cleanly, and pass the full test suite (core, WAL/concurrency, and thevecpackage) on the FreeBSD CI builders; they are offered for evaluation only. If you run 32-bit FreeBSD, please exercise these targets with your own workloads and report back — the intent is to promotefreebsd/386,freebsd/arm, andnetbsd/amd64to fully supported platforms in a future release cycle, once a period of broader real-world testing elapses without surprises.- Implementation notes: correct operation on
freebsd/armrequires the matching pinnedmodernc.org/libc(v1.73.4), which fixes the per-archmmap(2)off_tencoding for 32-bit FreeBSD; without it the WAL shared-memory mapping faults with SIGBUS under concurrent access, the same class of bug found on the netbsd port. As usual, downstream modules must pin the exactmodernc.org/libcversion this module'sgo.modpins.- See [GitLab merge request #119](https://gitlab.com/cznic/sqlite/-/merge_requests/119), thanks Olivier Cochard-Labbé (
@ocochard)!- Add a Go-facing wrapper for
SQLITE_CONFIG_PCACHE2.PageCacheis the factory andCachethe per-database instance, both idiomatic Go interfaces;Pageexposes the rawBufandExtrapointers that SQLite reads through the C pcache contract.RegisterPageCacheandMustRegisterPageCacheinstall the module process-globally before the firstsql.Open; subsequent Open calls are gated through a one-shotXsqlite3_config(SQLITE_CONFIG_PCACHE2)so a too-late Register returnsErrPageCacheTooLaterather than silently falling through to the built-in pcache1. The binding owns thesqlite3_pcache_pagestub and re-consults the implementation on every Fetch, reusing the stub only when the returnedPagevalue is unchanged, which keeps a bounded/evicting purgeable cache safe by construction.- See [GitLab merge request #126](https://gitlab.com/cznic/sqlite/-/merge_requests/126), thanks Ian Chechin!
- Add
modernc.org/sqlite/pcache, the reference page-cache implementation that accompanies the #126SQLITE_CONFIG_PCACHE2wrapper.pcache.Newreturns a*Poolsatisfying thePageCacheinterface; register it once withsqlite.MustRegisterPageCache(pcache.New())and every connection opened afterwards draws its pages from it. EachPool.Createmints a fresh per-databaseCache: a bounded, LRU-evicting page store that honours thePRAGMA cache_sizesoft cap and releases the least-recently-unpinned page when it must make room. Page memory — theBufandExtrabuffers SQLite reads through — is allocated withlibc.Xmalloc/libc.Xcallocand therefore lives off the Go heap, which keeps SQLite's interior pointer arithmetic on the page extras from tripping the race detector's checkptr enforcement.Pool.Statsreports aggregate lifetime counters (hits, misses, allocs, evictions, rekeys, truncates, caches) across every cache a Pool has created, so hit/miss/eviction behaviour is observable without instrumenting individual caches. Cross-connection page sharing is out of scope for now; eachCreatereturns an independent per-database cache.- Validated end-to-end against the #126 stress workload (
cache_size=16, 4000 BLOB rows with DELETE andincremental_vacuum,integrity_checkclean under-race) and benchmarked for the memory-utilization goal tracked in [GitLab issue #204](https://gitlab.com/cznic/sqlite/-/issues/204).- See [GitLab merge request #127](https://gitlab.com/cznic/sqlite/-/merge_requests/127), thanks Ian Chechin!
- Tighten the
modernc.org/sqlite/pcachereference implementation per cznic's !127 review follow-ups. AddsStats.EasyRefusals, a per-Pool counter for the cases whereFetchCreateEasyreturns nil at cap; SQLite reacts to a refusal by spilling dirty pages and retrying withFetchCreateForce, so the new field is a direct proxy for the I/O pressure the strict Easy contract imposes vs pcache1's recycle-without-spill behavior.BenchmarkPoolEvictionChurnwas reworked to drive a rotating-residue DELETE (k % 3 = i % 3) and re-insert a matching batch each cycle so the spill pressure recurs andeasy-refusals/opscales withb.Ninstead of capping at the seed's one-time first-cycle cost; both existing benchmarks now reporteasy-refusals/opalongside the page-allocs/evictions metrics.Stats.Evictionsdocumentation was tightened to match the actual behavior (counts LRU eviction,Unpin(discard=true),Shrinkreleases, andUnpin(discard=false)trimming back to target after aFetchCreateForceovercommit; bulk frees fromTruncate,Rekeycollisions, andDestroyare not counted). TheTestPoolRoundTripIntegritycomment claiming the workload exercisesxRekey~15 times has been corrected; the SQL surface does not reliably emit xRekey here, and that codepath is covered by the unit tests instead.- See [GitLab merge request #130](https://gitlab.com/cznic/sqlite/-/merge_requests/130), thanks Ian Chechin!
- Make
modernc.org/sqlite/pcache-race-clean under SQLite'scache=sharedmode. The pool already runs correctly under shared-cache because every callback into a givenCacheis serialised internally by SQLite'ssqlite3BtreeEnteron theBtSharedmutex; verified empirically with a lock-free in-flight probe (max-in-flight = 1 on the canonical two-connection workload, 4 on a positive control with goroutines hitting the cache directly). However the Go race detector does not recognise SQLite's libc mutex as a happens-before edge and reports false-positive races onFetchvsUnpinreads/writes of the per-cache state, which surfaces asDATA RACEfailures for any user who registers the pool and runs their suite under-race. Async.Mutexon thecachetype is now taken on every public method (SetSize,PageCount,Fetch,Unpin,Rekey,Truncate,Destroy,Shrink), always. On the common non-shared-cache path the lock is uncontended (one atomic CAS per Lock/Unlock pair, negligible next to the SQLite work it bookends); on the shared-cache path it just rubber-stamps the order SQLite'sBtSharedmutex already established. A newe2e_test.goTestSharedCacheTwoConns_Integritydrives twosql.Connagainst the samecache=sharedURI with concurrent writers and assertsPRAGMA integrity_check = okunder-race; passes cleanly with the lock, would surface the false-positive without it. Design notes live inpcache/sharing.go.- See [GitLab merge request #131](https://gitlab.com/cznic/sqlite/-/merge_requests/131), thanks Ian Chechin!
- Add a Go wrapper for
sqlite3_db_status, the per-connection runtime counters (cache hit/miss/write/spill rates, schema and prepared-statement memory, lookaside usage, deferred foreign keys).DBStatusis an interface implemented by the driver connection and reached through thedatabase/sqlescape hatch(*sql.Conn).Raw(), mirroring the existingFileControlsurface;DBStatusOpis a distinct typed enum of theSQLITE_DBSTATUS_*verbs so a counter from a different op family will not compile in its place.Status(op, reset)returns the(current, high)pair and optionally resets the counter. This also letsmodernc.org/sqlite/pcachemeasure real I/O instead of theEasyRefusalsproxy: the newBenchmarkPoolSpillIOreads the pager-levelSQLITE_DBSTATUS_CACHE_SPILL/_CACHE_WRITEcounters, which the pager maintains identically for pcache1 and the pool, making the pcache1-vs-pool comparison cznic raised on the !127 review a genuine apples-to-apples measurement. On the rotating-residue eviction-churn workload atcache_size=16the pool spills ~3.5x more than pcache1 (cache-spill/op 31.96 vs 8.96) for ~3% more page writes (cache-write/op 450 vs 436) at identical hit/miss, quantifying the I/O cost of the strict Easy contract thatEasyRefusalsonly proxied.- See [GitLab merge request #132](https://gitlab.com/cznic/sqlite/-/merge_requests/132), thanks Ian Chechin!
- Add an opt-in
_dqsDSN query parameter that disables SQLite's double-quoted string literal compatibility quirk on a per-connection basis. When_dqs=0(or anystrconv.ParseBoolfalse value) is supplied, the driver callssqlite3_db_configwithSQLITE_DBCONFIG_DQS_DDLandSQLITE_DBCONFIG_DQS_DMLset to off before any statement is prepared, so a double-quoted identifier that fails to resolve raises a parse error instead of silently falling back to a string literal. Absence of the parameter, or_dqs=1, leaves SQLite's default behavior unchanged; existing DSNs continue to work byte-for-byte. Resolves [GitLab issue #61](https://gitlab.com/cznic/sqlite/-/issues/61).- See [GitLab merge request #128](https://gitlab.com/cznic/sqlite/-/merge_requests/128), thanks Ian Chechin!
- Add an opt-in
_error_rcDSN query parameter for clearer error reporting on open-time failures. When_error_rc=1(or anystrconv.ParseBooltrue value) is supplied, error strings synthesised from a(rc, db)pair only appendsqlite3_errmsg(db)whensqlite3_extended_errcode(db)is consistent with the operation rc (full match first, primary code&0xffas fallback). On mismatch the canonicalsqlite3_errstr(rc)is used alone, so an open-timeSQLITE_CANTOPENno longer carries the temporary handle's stale "out of memory" errmsg. Absence of the parameter, or_error_rc=0, preserves the legacy "errstr: errmsg" form byte-for-byte; existing callers that parse error strings are unaffected. The driver's*Error.Code()returns the same SQLite result code in both modes. Parsed beforesqlite3_open_v2so open-time errors are covered. Resolves [GitLab issue #230](https://gitlab.com/cznic/sqlite/-/issues/230).- See [GitLab merge request #129](https://gitlab.com/cznic/sqlite/-/merge_requests/129), thanks Ian Chechin!
2026-06-06 v1.52.0:
- Upgrade to SQLite 3.53.2.
- Add
Backup.RemainingandBackup.PageCount, thin wrappers around the existingsqlite3_backup_remainingandsqlite3_backup_pagecountC symbols. Together they expose the per-Stepprogress counters that the underlying backup object already maintains, enabling progress reporting during online backups without dropping tomodernc.org/sqlite/libdirectly.- See [GitLab merge request #122](https://gitlab.com/cznic/sqlite/-/merge_requests/122), thanks Ian Chechin!
- Drop the redundant second copy in
(*conn).columnText, the path that backs everyRows.Scaninto a Gostringfor a TEXT column. The value's bytes are still copied once out of SQLite-owned memory into a fresh Go buffer; that buffer is then reinterpreted as the result string withunsafe.Stringrather than copied a second time by the implicitstring([]byte)conversion. This removes one allocation per TEXT value per row and roughly halves the bytes allocated on that path; on the newBenchmarkColumnTextScancases it is ~13–20% faster for payloads of 256 B and larger, with no measurable change for very short strings. Purely internal: no API or behavioral change, and the returned string never aliases SQLite's buffer.- See [GitLab merge request #123](https://gitlab.com/cznic/sqlite/-/merge_requests/123), thanks Ian Chechin!
- Cache each result column's declared type once per result set in
newRowsinstead of recomputing it on every row. The TEXT branch ofRows.NextcallsColumnTypeDatabaseTypeNamefor every TEXT column on every row (independent of any DSN flag), which previously did alibc.GoString+strings.ToUppereach time; that lookup is now a single index into a cached, pre-uppercased[]string, andColumnTypeScanTypereads the same cache and drops its per-callstrings.ToLower. The declared type is fixed for the lifetime of a prepared statement, so the C round-trip is paid once per column rather than once per column per row, removing exactly 1 alloc + 8 B per TEXT column per row from theNexthot path. The newBenchmarkTextToTimeScancases show ~7% faster on a 1000-row DATETIME SELECT under_texttotime=1. Purely internal:ColumnTypeDatabaseTypeNameandColumnTypeScanTypereturn identical values, no API or behavioral change.- See [GitLab merge request #124](https://gitlab.com/cznic/sqlite/-/merge_requests/124), thanks Ian Chechin!
- Cache, per result column, the
parseTimeFormatsindex that first parsed a TEXT-stored DATE/DATETIME/TIMESTAMP value, and try that format first on later rows instead of re-walking the list from the top.(*conn).parseTimepreviously rantime.Parsedown the format list on every such row; for the canonical SQLite TEXT datetime format every row paid two failedtime.Parseattempts — each allocating a*time.ParseError— before the match. On a 1000-row DATETIME TEXT SELECT this cuts ~50% of allocs/op and ~57% of B/op and is ~37% faster. The fall-through chain is preserved exactly: the seven formats are mutually exclusive, so the cached hint can never select a different match than the in-order scan, and the parseddriver.Valueis identical to before. Purely internal: no API or behavioral change.- See [GitLab merge request #125](https://gitlab.com/cznic/sqlite/-/merge_requests/125), thanks Ian Chechin!
2026-05-28 v1.51.0:
- Pool the
[]driver.Valueslice passed to scalar/aggregate UDF callbacks and to vtabFilter/Insert/Updatecallbacks, eliminating the dominant per-row allocation on UDF-heavy queries. Benchmarks on a 1000-row, 3-arg noop scalar UDF show ~40% fewer bytes/op and ~15% fewer allocs/op.- Document the matching "arguments are not valid past return" contract on
vtab.Cursor.Filterandvtab.Updater.Insert/Update, consistent with the existing rule forFunctionImpl.Scalar/AggregateFunction.Step/WindowInverse.- Resolves [GitLab issue #226](https://gitlab.com/cznic/sqlite/-/issues/226). See [GitLab merge request #114](https://gitlab.com/cznic/sqlite/-/merge_requests/114), thanks Ian Chechin!
... (truncated)
Commits
feat: browse themes button in settings -
@TRC-Loop in #122
Closes #121
Adds a "Browse themes" button to the Themes settings category, between "Import theme..." and "Open folder". It opens https://themes.pelton.app in the user's browser via BrowserOpenURL, the same way About opens links.
Nothing is fetched into the webview, so no third-party content reaches the app. Downloads come back in through the existing import flow.
2 new i18n keys in all five locales.
feat: choose which parts of a theme to import -
@TRC-Loop in #120
Closes #106
When a .peltontheme carries both colors and custom CSS, the import modal now asks which parts to bring in. Both are checked by default, so a plain import is still one click.
Behavior
- The choice only appears when the theme actually has both parts. A colors-only or CSS-only theme has nothing to choose, so nothing is shown.
- Deselecting CSS also hides the remote-reference warning, since no stylesheet is being installed.
- Install is disabled if both are unchecked.
Implementation
themepack.SelectParts(keepTokens, keepCSS)drops the deselected part's files from the container and rewritesmanifest.json, so the copy written into the themes folder is exactly what was picked. Nothing is filtered at apply time.ConfirmThemeImporttakes the two flags and applies the selection beforeWriteContainer.PreviewThemeImportreportstokenCountso the modal knows whether the theme defines colors at all.- Wails bindings hand-edited to match.
Tests
internal/themepack/parts_test.go covers all three selections through a write/read round trip: dropping CSS keeps tokens and icons, dropping tokens keeps CSS, keeping both changes nothing.
6 new i18n keys in all five locales.
feat: customizable in-app menu bar -
@TRC-Loop in #117
Closes #73.
Lets users customize the in-app menu bar directly on the bar, via an in-place editor mode entered from Settings > Interface.
What
- Editor mode on the bar: Settings has an Edit menu bar button that flips the live bar into an editor (and closes settings so you edit in place). A Done button exits.
- Reorder top-level menus (drag the chips) and items (drag within a menu), show/hide anything, and delete custom pieces. Built-ins are never destroyed, so Reset always restores them.
- + to add a top-level menu on the bar; + inside a menu to add an item, a submenu, or a separator.
- Submenus (one level deep) render as hover flyouts in the normal bar.
- Custom entries: click a custom item or submenu to edit its label, action (from the catalog) and icon inline. Icon picker shows theme icons first, then a searchable Tabler picker over the full set.
- Choose how items shipped by future updates join a saved layout: shown immediately (default) or hidden until added.
How
- Layout persists as one JSON setting (
menu_bar_layout), so it rides the existing config export/import with no backend changes. resolveBar()drives the normal bar (incl. submenu flyouts); the editor renders the raw layout and writes straight to the store, so edits preview live. A merge step folds in newly shipped built-ins and drops removed ones.- Drag-and-drop via svelte-dnd-action (menus, items, and per-submenu item zones).
- Tabler geometry (~2 MB) is a Vite-aliased lazy chunk, loaded only when the icon picker opens; a chosen icon's geometry is stored on the item so the always-on bar renders it without that dataset. macOS-only items stay valid across installs and are filtered per platform.
- New deps:
svelte-dnd-action,@tabler/icons(icon node data). i18n added to all 5 locales.
svelte-check and vite build pass. The drag/click GUI interaction still wants a manual make run smoke test.
feat: offer to set Pelton as the default mail client -
@TRC-Loop in #146
Closes #119 (the default-mail-client half; the mailto: handling half is #145).
Lets Pelton register as the system's default mailto: handler, offered quietly: one skippable onboarding step, and a passive line in the About section. Nothing nags.
What changed
Backend (internal/desktop/defaultclient*.go) — a small cross-platform surface (DefaultMailClientStatus, SetDefaultMailClient) over per-OS implementations:
- macOS (
_darwin.go, cgo/CoreServices): detect withLSCopyDefaultHandlerForURLScheme, set withLSSetDefaultHandlerForURLScheme(which shows the system's own confirmation sheet). Compares against the bundle idsh.arne.pelton. - Linux (
_linux.go):xdg-settings get/set default-url-scheme-handler mailto pelton.desktop. - Windows (
_windows.go): opensms-settings:defaultapps(Windows does not allow setting it programmatically); detection returns "unknown" until the installer registers a ProgId, so the About line stays hidden rather than guessing wrong. - Other (
_other.go): reports unknown / unsupported.
Detection returns a known flag; where a platform cannot answer reliably the UI shows nothing.
Frontend:
- Onboarding: a new
defaultmailstep with a single "Set as default" action, skippable via the nav and the global skip. It is dropped from the flow entirely when Pelton is already the default (or the platform can't say), so it never shows a pointless offer. - About section: a low-key line + "Set as default" button, shown only when
known && !isDefault. No banner, no modal, no repeat prompting. - New strings across all five locales (en/de/fr/es/nl).
Notes
- The macOS build already links cgo (Wails/WebKit), so the CoreServices code adds no new build requirement; the deprecated
LS*calls remain the only supported non-private way to read/set a scheme handler. - The OS integration (the macOS sheet, xdg association, Windows settings page, and default detection) needs manual verification from a packaged build per platform; the binding surface, onboarding flow and About line are typechecked and the backend builds/vets/tests clean on darwin plus linux/windows cross-compiles.
Verified: go build ./..., go vet, go test ./internal/desktop/, linux+windows cross-compiles all pass; svelte-check clean; all 5 locales at key parity; go.mod/go.sum unchanged after wails generate module.
feat: open mailto: links in a prefilled compose -
@TRC-Loop in #145
Part of #119 (the mailto: handling half). Clicking a mailto: link anywhere on the machine now opens a Pelton compose window with the recipient, subject and body prefilled.
This is the first of two PRs for #119. The default mail client half (onboarding step + passive About line + per-platform set/detect) is a separate change and will follow; #119 stays open until then.
What changed
- RFC 6068 parser (
internal/desktop/mailto.go) forto(path + query),cc,bcc,subject,body, with additionaltovalues merged. Unknown headers are ignored; a malformed URL yields an empty draft (blank compose) rather than an error. Percent-decoding usesPathUnescape, so+is a literal plus per the spec (not a space) and%0D%0Ain the body is preserved. Fully unit-tested (mailto_test.go). - Single instance (
SingleInstanceLock): a second launch (e.g. anothermailto:click) hands its argv to the running app and surfaces its window instead of spawning a second Pelton. The dev build (PELTON_DEV) uses a separate lock id so it never collides with an installed Pelton. - Per-platform delivery:
- Linux/Windows: the URL arrives as argv (the
.desktopfile already declaresMimeType=x-scheme-handler/mailto;andExec=pelton %u); it is stashed at launch and picked up on first mount, or handed over via the single-instance path when already running. - macOS:
mac.Options.OnUrlOpen(the URL arrives as an Apple event, not argv).wails.jsonnow declares themailtoprotocol soInfo.plistrendersCFBundleURLTypes.
- Linux/Windows: the URL arrives as argv (the
- Frontend:
consumePendingMailto()picks up a launch draft after the sidebar loads;onMailtoComposehandles links opened while running. Both route throughopenComposeWith, which prefills the compose and reveals the cc/bcc rows only when they carry a value. - Onboarding-first: if a
mailto:arrives before any mailbox exists, the draft is held and opened once onboarding finishes or a mailbox is added, rather than dropped.
Notes / not in this PR
- No new user-facing strings, so no locale changes here.
- Windows registry registration (
SOFTWARE\Clients\Mail,Capabilities\URLAssociations) is installer work per the issue and is not part of this change. - The native OS wiring (macOS Apple event, single-instance handoff, Linux
.desktopassociation) needs manual verification from a packaged build; the parser and the delivery/onboarding logic are covered by tests and typecheck.
Verified: go build ./..., go vet, go test (mailto suite) all pass; cross-compiles for linux and windows succeed; svelte-check clean; go.mod confirmed unchanged after wails generate module.
feat: read-only MCP server for AI agents -
@TRC-Loop in #131
Closes #77
A read-only Model Context Protocol server so external AI agents can browse, read and search Pelton's cached mail. Off by default.
Design decisions (agreed in waves)
- Transport: streamable HTTP bound to
127.0.0.1only. Pelton runs continuously, so an agent connects to a URL rather than spawning it. ArequireLoopbackguard makes binding to a routable interface impossible. - Library: the official
github.com/modelcontextprotocol/go-sdk. - Scope: read-only. Tools:
list_accounts,list_folders,list_messages,get_message,search_messages.get_messagereturns headers, message metadata (Message-ID, size), the plain-text body, the HTML body when present (most mail has one), and attachment metadata (name, type, size) but never attachment bytes. No tool sends, moves, flags or deletes; that guarantee rests on theMailboxinterface having no mutating method. Write actions are tracked in #127. - Auth: a bearer token Pelton generates. Every request is checked with a constant-time comparison before it reaches the MCP handler, so an unauthorized caller cannot even enumerate the tools.
- Settings home: a new External category (the shared home for external-service integrations; VirusTotal #129 will live here too), with an enable toggle, editable port, the token with copy + regenerate, and a ready-to-paste client config snippet.
Backend
internal/mcpserver holds the protocol plumbing behind the narrow Mailbox interface; internal/desktop/bind_mcp.go adapts the store and search index to it and owns the lifecycle. The server starts at boot when enabled, and any settings change (enable, port, token) stops and restarts it under one lock. Settings persist as mcp_enabled / mcp_port / mcp_token.
Tests
internal/mcpserver/mcpserver_test.go: every tool round-trips over an in-memory transport and returns its data (including that list_messages honours the limit and search params are forwarded); typed output is exposed as structured content, not only JSON text; the bearer middleware rejects missing/wrong/prefix-less tokens and admits the correct one; Start refuses to run without a token; requireLoopback accepts loopback and rejects routable addresses.
Verification
go build ./..., full go test ./internal/..., go vet, gofmt clean; svelte-check 0 errors, frontend build clean. New i18n keys added to all five locales.
Summary
- Added an optional, disabled-by-default, read-only MCP server for browsing, reading, and searching cached mail.
- Exposed the server over loopback-only streamable HTTP with bearer-token authentication.
- Added MCP tools for accounts, folders, messages, message details, and search, including body and attachment metadata.
- Added External settings UI with enablement, port configuration, token regeneration, connection details, and localized translations.
- Integrated persistent settings, startup, shutdown, and lifecycle restart handling.
- Added adapters for Pelton’s mailbox store and search index.
- Added tests covering tool behavior, JSON results, authentication, token requirements, and loopback validation.
AI usage
The change appears Very Likely to have used AI assistance, based on the provided AI-generated file summaries and highly structured implementation. There is no evidence here that it was fully agentic or used 100%; AI was likely used to help with implementation and documentation.
feat: theme creator color picker, metadata and advanced section -
@TRC-Loop in #124
Closes #107
All three parts of the issue.
Color picker
Replaces the native <input type="color"> well with ColorPicker.svelte: a saturation/value area, hue and alpha sliders, and typed hex plus R/G/B fields. The color model lives in frontend/src/theme/color.ts and parses #rgb, #rgba, #rrggbb, #rrggbbaa, rgb() and rgba(), in comma or space form.
- Alpha is a first-class control, since the built-in border tokens are
rgba(...). Output is hex while opaque andrgba()once it is not, matching how the built-in palettes are written. - Values the model cannot parse (
color-mix(), named colors) still round-trip: the text field stays authoritative and the picker only overwrites the token once you actually pick something. - The popover is fixed-positioned and flips above the well near the bottom of the screen, because the modal body scrolls and would clip an absolutely positioned panel.
Editable metadata
Author and version join name in the editor and are written into manifest.json, so exported .peltontheme files carry correct data. Editing an existing theme now loads through a new GetThemeDraft binding, which returns the theme in editor form rather than apply form.
Advanced section
A collapsed <details> holding:
- Raw tokens: the rest of the themeable surface (accent, link, selection, radii, fonts, type scale, elevation), labelled by token name, since this is the raw view. The derived
-bgpartners of the status colors stay out, as the save computes those. - Custom CSS: a textarea applied on top of the tokens, previewing live like every other field.
CSS is stored as one file the editor owns (css/custom.css), so editing a theme that already ships stylesheets adds to them instead of overwriting the author's work. Remote references are stripped on save: CSS typed or pasted into the editor is held to the same no-network rule as an import, and unlike an import there is no author to ask. Capped at 256 KB with a clear error, well under the container's own limit.
Tests
internal/desktop/bind_theme_editor_test.go covers the stylesheet handling: appended once and never duplicated, remote references and @import stripped, clearing removes both the file and the manifest entry while leaving the theme's own stylesheets alone, oversized input rejected.
11 new i18n keys in all five locales.
feat: verbose sync shows current mailbox in status line -
@TRC-Loop in #144
Closes #128.
Adds an opt-in verbose sync mode so a running sync says which mailbox it is working on instead of a plain "Syncing", which made large or slow syncs look stuck.
What changed
- New
verbose_syncpreference (off by default), wired throughUIPrefsDTO, the prefs store, andSettingKeys. - The frontend now subscribes to the
sync:progressevents the backend already emitted (folder name + done/total). A newsyncFolderstore holds the mailbox currently being synced; it clears on the trailing progress event and when the sync ends. - The status line renders "Syncing {mailbox}…" when verbose sync is on and a folder is in progress, falling back to the plain label otherwise.
- Toggle added to the Power settings section, next to the auto-sync interval.
Notes
- No new backend event was needed, the per-folder progress was already being emitted from
syncFolders, it just had no consumer. - i18n keys added to all five locales (en/de/fr/es/nl).
feat: views (preset searches) -
@TRC-Loop in #135
What
Adds Views (preset searches): user-defined saved searches surfaced as their own entries, per the decisions on the issue.
A View = name + icon + color + a filter (free text, from/to/subject, relative date window, and scope: unread-only / flagged-only / has-attachment / account or all).
Behaviour
- Eager-run for all views: message bodies are already fully cached at sync time, so there is no per-view prefetch. Instead every view's query runs on startup, after each sync, and after local read/flag/delete changes, in the background, feeding a live count badge and instant open.
- Placement (hidden by default): a setting under Sidebar chooses how Views appear:
Hidden(feature off),In sidebar(a group above the account trees), orSeparate tab(a Mail/Views toggle that swaps the sidebar body). - Creation: a "Save as view" button in the search bar (promotes the current query) and a dedicated New view builder. Views are reorderable by drag.
- Reachability: sidebar rows, a
New viewaction in the customizable menu bar, and assignable keyboard shortcuts (new-view,next-view,prev-view).
Backend
viewstable (migration 0011) + CRUD + reorder (internal/storage/views.go).- View execution engine (
internal/desktop/bind_views.go): text criteria go through the full-text index, pure-scope views read the store, then scope/date/hygiene filters apply in Go. Results cap at 500 newest-first. Bound methodsListViews/SaveView/DeleteView/ReorderViews;ListMessagesgains asavedViewkind.views:changedevent drives badge refresh.
Frontend
- Types, api, a
viewsstore (+ global editor state), sidebarSavedViewsgroup and tab toggle,ViewEditorModal, curated icon/color palette,viewsPlacementpreference, and the menu/shortcut wiring. - i18n across all five locales.
Tests / checks
internal/storageview CRUD + reorder tests; go build + desktop/storage/imap suites pass.- svelte-check: 0 errors / 0 warnings; vite build succeeds.
Notes
- Command palette (the powerful fuzzy reachability) is tracked separately in #134.
- Curated view icon set (not the full tabler dataset) keeps the feature light.
Closes #103
feat: VIP senders with native new-mail notifications -
@TRC-Loop in #142
Adds VIP senders and native OS new-mail notifications (#126).
What it does
- Mark any sender as a VIP: a star toggle in the reading-pane header and a context-menu action on any message row. VIPs are managed in Settings > Notifications (add by address, remove).
- New mail from a VIP raises a native OS notification (macOS Notification Center, Windows toast, Linux dbus, via beeep) even when general new-mail notifications are off, so important senders cut through.
- A separate general "Notify on new mail" toggle (off by default) notifies for all new inbox mail.
- VIP senders show a star next to the sender in the list, reading pane and search results. The star updates live the moment a sender is marked, backed by a client-side store.
- Notifications fire only for INBOX (a full sync of Sent/Archive never notifies) and skip already-seen mail.
Matching
Exact address only. Stored lowercased; a changing display name never breaks the match (bareAddress helper on both sides).
How it's built
- Sync engine now surfaces the storage ids of freshly fetched messages (FolderSyncResult.NewIDs); the desktop layer loads them and decides what to notify.
- New notification layer (notify.go) with a Go-side locale table, mirroring the native-menu i18n approach since notifications are built before the webview and beeep takes plain strings.
- VIP storage/logic (bind_vip.go) with unit tests; general toggle in UIPrefs; senderVip on the message summary DTO.
- Frontend: vip store, VIPSendersModal, star surfaces, settings section; i18n across all five locales.
Known limitation
beeep has no per-notification click callback, so clicking a notification does not open that exact message. Exact click-to-open would need platform-specific code and is worth a separate issue.
Closes #126
fix: rename settings category Network to Proxy -
@TRC-Loop in #137
Renames the user-facing settings category label from Network to Proxy in all five locales, since the category only holds proxy settings. Internal category id and the network.proxy.* key namespace are unchanged.
Closes #116
fix: resync off the idle connection so new mail arrives promptly -
@TRC-Loop in #133
What
New mail was fetched over the connection that was still parked in IMAP IDLE, so the fetch could not run until IDLE stopped, which only happened on go-imap's 28-minute idle restart (or app shutdown). New mail therefore took minutes to appear instead of seconds.
Fix
internal/imap: addIdleUntil(ctx)which parks on IDLE, blocks until the server pushes an update / ctx is cancelled / the connection drops, and always stops IDLE before returning so the connection is free to FETCH. Removed the now-unusedUpdates()accessor and the oldIdle()that held IDLE open for the whole session (exposing it invited exactly this misuse).internal/desktop:idleSessionis now a single-goroutine loop:IdleUntil-> on update takesyncMu, resync INBOX, release, idle again. No concurrent FETCH on the idling connection;syncMuis held only for the brief resync, so manual/background syncs no longer stall behind it.cmd/imaptest: updated to the new loop API.
Tests
TestStopIdle(close/wait error reaping) andTestDrainUpdatesininternal/imap.- Existing imap + desktop suites pass.
Closes #125
fix: stop reading pane jitter on fractional display scaling -
@TRC-Loop in #141
The reading pane iframe is sized to its content height via a ResizeObserver that writes each measured body height back onto the iframe. On fractional display scaling (125%/150%, common on Fedora's WebKitGTK) the applied height snaps to a device pixel differently from how getBoundingClientRect measures it back, so the body flips between two adjacent pixel heights forever. That continuous 1px oscillation is the visible shaking that makes mail unreadable.
Fix: add hysteresis in measure() so a new reading only takes effect when it differs from the applied height by more than a pixel. This settles the feedback loop while still tracking real content growth and shrink. No behavior change on integer scaling, where diffs were already 0.
Closes #123
Full Changelog: v1.0.9...v2026.3