1. 10 Feb, 2026 5 commits
  2. 09 Feb, 2026 3 commits
    • Steven's avatar
      fix(tests): update PAT tests to accept both custom and SQL errors · 2b19d8a9
      Steven authored
      The PostgreSQL implementation returns 'PAT not found' when no rows match,
      while SQLite/MySQL return 'sql: no rows in result set' from QueryRowContext.
      
      Both behaviors are correct - the key fix is that PostgreSQL no longer
      throws JSONB errors on missing/malformed data.
      
      Changes:
      - Update test assertions to accept either error type
      - Fix comment punctuation for godot linter
      - Maintain backward compatibility across all database drivers
      2b19d8a9
    • Steven's avatar
      fix(postgres): handle missing PAT data gracefully and add comprehensive tests · d9e8387d
      Steven authored
      Fixes #5612, #5611
      
      Root cause: PostgreSQL's jsonb_array_elements() throws errors when the
      'tokens' key is missing or malformed, while SQLite/MySQL return NULL
      gracefully. This caused:
      - 502 errors when creating admin after v0.25.3 → v0.26.0 upgrade
      - Settings not persisting and users unable to stay logged in
      
      Changes to store/db/postgres/user_setting.go:
      - Remove strict JSONB operations from GetUserByPATHash query
      - Fetch all PERSONAL_ACCESS_TOKENS rows and filter in Go
      - Skip malformed/invalid JSON rows with continue (error recovery)
      - Match SQLite/MySQL's forgiving error handling
      
      New integration tests (store/test/user_setting_test.go):
      - TestUserSettingGetUserByPATHashNoTokensKey
      - TestUserSettingGetUserByPATHashEmptyTokensArray
      - TestUserSettingGetUserByPATHashWithOtherUsers
      
      New PostgreSQL-specific tests (store/db/postgres/user_setting_test.go):
      - TestGetUserByPATHashWithMissingData (comprehensive edge cases)
      - TestGetUserByPATHashPerformance (100+ users)
      - TestUpsertUserSetting (basic upsert)
      
      Test coverage:
       Missing PERSONAL_ACCESS_TOKENS key
       Empty/malformed JSON data
       Multiple users with mixed valid/invalid data
       Performance with 100+ users
       Error recovery without crashes
      
      Benefits:
      - No database migration required (TEXT column works fine)
      - Backward compatible with v0.25.3 upgrades
      - Handles missing/corrupt data gracefully
      - Consistent behavior across all database drivers
      d9e8387d
    • MuLingQwQ's avatar
  3. 08 Feb, 2026 6 commits
  4. 07 Feb, 2026 1 commit
  5. 05 Feb, 2026 2 commits
    • Steven's avatar
      fix: prevent 401 errors on window focus when token expires · 81ef53b3
      Steven authored
      Fixes #5589
      
      When the page returns from background to foreground after the JWT
      token expires (~15 min), React Query's automatic refetch-on-focus
      triggers multiple API calls simultaneously. These all fail with 401
      Unauthorized, leaving the user with empty content.
      
      Solution:
      - Add useTokenRefreshOnFocus hook that listens to visibilitychange
      - Proactively refresh token BEFORE React Query refetches
      - Uses 2-minute buffer to catch expiring tokens early
      - Graceful error handling - logs error but doesn't block
      
      Changes:
      - Created web/src/hooks/useTokenRefreshOnFocus.ts
      - Updated isTokenExpired() to accept optional buffer parameter
      - Exported refreshAccessToken() for use by the hook
      - Integrated hook into AppInitializer (only when user authenticated)
      81ef53b3
    • Steven's avatar
      chore: tweak security report email · 86f780d1
      Steven authored
      86f780d1
  6. 04 Feb, 2026 4 commits
    • Steven's avatar
      refactor: remove hide-scrollbar utility · cf65f086
      Steven authored
      Removed the hide-scrollbar CSS class and all its usages throughout the
      codebase. Hiding scrollbars can hurt UX by making it unclear when
      content is scrollable.
      
      Changes:
      - Removed hide-scrollbar CSS definition from index.css
      - Removed hide-scrollbar class from Navigation component (2 instances)
      - Removed hide-scrollbar class from MemoDetailSidebar (2 instances)
      - Removed hide-scrollbar class from TagsSection
      - Removed hide-scrollbar class from ShortcutsSection
      
      Components now use standard browser scrollbar behavior, which provides
      better visual feedback to users about scrollable content. Modern
      browsers already handle scrollbar appearance elegantly.
      cf65f086
    • Steven's avatar
      perf: disable tooltips in year calendar to fix lag · 74b63b27
      Steven authored
      Fixed issue #5579 where the calendar selection dialog was very laggy.
      
      The root cause was rendering ~365 individual Tooltip components when
      opening the year calendar view (one per day with activity). This created
      a huge number of DOM nodes and event listeners that caused significant
      performance issues.
      
      Changes:
      - Added disableTooltips prop to MonthCalendar and CalendarCell components
      - Disabled tooltips in YearCalendar's small month views
      - Removed unnecessary TooltipProvider wrapper in YearCalendar
      - Tooltips remain enabled in the default month calendar view
      
      Performance improvements:
      - Eliminates ~365 tooltip instances when dialog opens
      - Reduces initial render time significantly
      - Makes dialog interactions smooth and responsive
      
      Users can still click on dates to drill down for details if needed.
      74b63b27
    • Steven's avatar
      fix: shortcut edit button opens create dialog instead of edit dialog · e7605d90
      Steven authored
      Fixed issue #5576 where clicking the edit button on a shortcut would
      incorrectly open a create dialog instead of an edit dialog.
      
      The root cause was an incorrect useEffect that was watching the shortcut
      state itself instead of the initialShortcut prop. When the dialog was
      opened for editing, the state wasn't properly reinitializing with the
      existing shortcut data.
      
      Changed the useEffect to:
      - Watch initialShortcut as the dependency
      - Reinitialize the shortcut state when initialShortcut changes
      - Properly distinguishes between create (initialShortcut undefined) and
        edit (initialShortcut has data) modes
      e7605d90
    • memory_clear's avatar
  7. 03 Feb, 2026 2 commits
    • Steven's avatar
      fix: prevent CTRL+Enter save while editor is loading content (#5581) · 6bb383a4
      Steven authored
      - Add validation check for loading state before allowing save
      - Prevents false "Content, attachment, or file required" error
      - Occurs when user presses CTRL+Enter immediately after opening edit mode
      - Editor state may still be loading when keyboard shortcut fires
      
      Closes #5581
      6bb383a4
    • Steven's avatar
      fix: nested task list display and checkbox interaction (#5575) · b4fea8c6
      Steven authored
      - Fix nested task lists not showing proper indentation
      - Use simple CSS cascade with [&_ul.contains-task-list]:ml-6
      - Fix checkbox clicks toggling wrong tasks in nested lists
      - Search from memo root container for global task indexing
      - Remove complex selectors in favor of standard approach
      - Match behavior of GitHub, Notion, and other platforms
      
      Closes #5575
      b4fea8c6
  8. 02 Feb, 2026 12 commits
    • Steven's avatar
      fix(auth): make PKCE optional for OAuth sign-in (#5570) · cf0a285e
      Steven authored
      Fixes issue where OAuth sign-in fails with 'Cannot read properties of
      undefined (reading 'digest')' when accessing Memos over HTTP.
      
      The crypto.subtle API is only available in secure contexts (HTTPS or
      localhost), but PKCE (RFC 7636) is optional per OAuth 2.0 standards.
      
      Changes:
      - Make PKCE generation optional with graceful fallback
      - Use PKCE when crypto.subtle available (HTTPS/localhost)
      - Fall back to standard OAuth flow when unavailable (HTTP)
      - Log warning to console when PKCE unavailable
      - Only include code_challenge in auth URL when PKCE enabled
      
      The backend already supports optional PKCE (empty codeVerifier), so no
      backend changes needed. This fix aligns frontend behavior with backend.
      
      Benefits:
      - OAuth sign-in works on HTTP deployments (reverse proxy scenarios)
      - Enhanced security (PKCE) still used when HTTPS available
      - Backward compatible with OAuth providers that don't support PKCE
      
      Fixes #5570
      cf0a285e
    • Steven's avatar
      refactor: improve GitHub Actions workflows structure and maintainability · 7465fbb4
      Steven authored
      - Add build-binaries workflow for multi-platform binary releases
      - Rename workflows for conciseness:
        - demo-render-deploy.yml → demo-deploy.yml
        - build-and-push-canary-image.yml → build-canary-image.yml
        - build-and-push-stable-image.yml → build-stable-image.yml
      - Centralize version config with env variables (GO_VERSION, NODE_VERSION, PNPM_VERSION)
      - Standardize step names across all workflows
      - Add concurrency controls to prevent redundant runs
      - Update Node.js (20→22) and pnpm (9→10) versions to match build-binaries
      - Improve job names with descriptive labels
      - Add consistent comments and formatting
      - Set artifact retention to 60 days for binary builds
      7465fbb4
    • Steven's avatar
      feat: add build binaries workflow for multi-platform releases · 4033f64b
      Steven authored
      - Add workflow_dispatch trigger for manual binary builds
      - Build for linux (amd64, arm64, arm/v7), darwin (amd64, arm64), windows (amd64)
      - Package as tar.gz (Unix) and zip (Windows)
      - Generate build summary with artifact sizes
      4033f64b
    • Steven's avatar
      refactor: simplify NSFW implementation by inlining logic · 29412f46
      Steven authored
      - Remove unused showNsfwContent prop (was only used in MemoDetail to pre-reveal NSFW, which defeats the purpose)
      - Inline useNsfwContent hook logic directly into MemoView.tsx (only 3 lines, no reusability benefit)
      - Delete web/src/components/MemoView/hooks/useNsfwContent.ts
      - NSFW content now consistently starts hidden across all pages
      - Maintains same user experience: click to reveal, no toggle back
      
      This removes unnecessary indirection and prop threading while preserving functionality.
      29412f46
    • Steven's avatar
      fix: prevent private memos from disappearing during token refresh (#5565) · 6db58fae
      Steven authored
      Root cause: enabled={isInitialized && !!user} prevented displaying cached
      data when user auth state transitioned during token refresh.
      
      Changes:
      - Remove !!user check from Home page enabled condition
      - Add clearAccessToken() in redirectOnAuthFailure for clean logout
      
      Fixes #5565
      6db58fae
    • Steven's avatar
      fix: add Unicode case-insensitive search for SQLite (#5559) · 8770b186
      Steven authored
      Add custom memos_unicode_lower() SQLite function to enable proper
      case-insensitive text search for non-English languages (Cyrillic,
      Greek, CJK, etc.).
      
      Previously, SQLite's LOWER() only worked for ASCII characters due to
      modernc.org/sqlite lacking ICU extension. This caused searches for
      non-English text to be case-sensitive (e.g., searching 'блины' wouldn't
      find 'Блины').
      
      Changes:
      - Add store/db/sqlite/functions.go with Unicode case folding function
      - Register custom function using golang.org/x/text/cases.Fold()
      - Update filter renderer to use custom function for SQLite dialect
      - Add test for Unicode case-insensitive search
      - Make golang.org/x/text a direct dependency
      
      Fixes #5559
      8770b186
    • Damian Jankowski's avatar
      chore: view memo URL updated (#5569) · c14843fa
      Damian Jankowski authored
      c14843fa
    • Steven's avatar
      fix: handle pasted files in memo editor · 2db57b13
      Steven authored
      Fixes #5568
      2db57b13
    • Steven's avatar
      fix: restore access token creation flow · 0dbc35a2
      Steven authored
      Fixes #5563
      0dbc35a2
    • Steven's avatar
      fix: preserve tag case when extracting markdown tags · e1c8101d
      Steven authored
      Fixes #5566
      e1c8101d
    • Steven's avatar
      chore: fix update user request name in member dialog · 34c341c8
      Steven authored
      Fixed #5564
      34c341c8
    • Steven's avatar
      chore: fix OAuth callback double-run state error · b8029c70
      Steven authored
      b8029c70
  9. 01 Feb, 2026 1 commit
    • Johnny's avatar
      fix: auto-fix permission issues when upgrading from 0.25.3 to 0.26.0 · d14cfa1c
      Johnny authored
      Fixes #5551
      
      The Docker image now runs as non-root (UID 10001) for security, but this
      breaks upgrades from 0.25.3 where data files were owned by root.
      
      Changes:
      - Dockerfile: Keep USER as root, install su-exec
      - entrypoint.sh: Fix ownership of /var/opt/memos, then drop to non-root
      - Supports custom MEMOS_UID/MEMOS_GID env vars for flexibility
      
      This allows seamless upgrades without manual chown on the host.
      d14cfa1c
  10. 31 Jan, 2026 4 commits
    • Johnny's avatar
      fix: add nil check for currentUser in DeleteUser · 1696c6c4
      Johnny authored
      Defense-in-depth fix: Add missing nil check before accessing
      currentUser.ID and currentUser.Role in DeleteUser function.
      
      While the auth interceptor should block unauthenticated requests,
      this check prevents potential nil pointer panic if fetchCurrentUser
      returns (nil, nil).
      1696c6c4
    • Johnny's avatar
      fix: add access control checks for attachments, comments, and reactions · c7b48b80
      Johnny authored
      Security fixes for multiple authorization bypass vulnerabilities:
      
      - GetAttachment: Add visibility check via checkAttachmentAccess helper
      - UpdateAttachment: Add ownership check (creator or admin only)
      - Fileserver: Require creator/admin auth for unlinked attachments
      - ListMemoAttachments: Add memo visibility check
      - CreateMemoComment: Add memo visibility check for target memo
      - ListMemoReactions: Add memo visibility check
      - UpsertMemoReaction: Add memo visibility check
      
      All checks follow the existing pattern used in GetMemo for consistency.
      c7b48b80
    • Johnny's avatar
      fix(fileserver): use streaming for video/audio to prevent memory exhaustion · 86fab0cf
      Johnny authored
      - Add serveMediaStream() to stream video/audio without loading into memory
      - Use http.ServeFile for local files (zero-copy, handles range requests)
      - Redirect to S3 presigned URLs for S3-stored media files
      - Refactor for better maintainability:
        - Extract constants and pre-compile lookup maps
        - Consolidate duplicated S3 client creation logic
        - Split authentication into focused helper methods
        - Group code by responsibility with section comments
        - Add setSecurityHeaders() and setMediaHeaders() helpers
      86fab0cf
    • Ganesh M's avatar
      fix(ui): math render (#5549) · 27de96d4
      Ganesh M authored
      27de96d4