Commit graph

1045 commits

Author SHA1 Message Date
boojack
88ac3ec31e feat(stats): support filtered all-user stats
- Add state and filter inputs to ListAllUserStats and reuse it for explore/archive sidebar stats.
- Reduce duplicate home initialization requests by sharing stats/settings data paths.
- Include memo paragraph regression coverage from the current working tree.
2026-05-09 09:11:04 +08:00
boojack
c49e75f91f chore: avoid copying memo protobuf locks 2026-05-09 08:32:00 +08:00
boojack
4a1e401bd9 fix(memo): enforce parent visibility for comments 2026-05-08 23:22:56 +08:00
boojack
02096836c3 test: stabilize backend tests in CI
- Avoid requiring built frontend assets in cache header tests.
- Skip Testcontainers-backed store tests when Docker is unavailable.
2026-05-08 22:24:54 +08:00
boojack
084f40bc9e fix(frontend): correct static cache headers 2026-05-08 21:25:05 +08:00
boojack
5ccba98adc
refactor: split STT and Audio-LLM into separate interfaces (#5928) 2026-05-03 00:21:58 +08:00
boojack
238f27dea1
feat(transcription): explicit STT settings with provider, model, prompt (#5926) 2026-05-02 19:35:18 +08:00
Steven
8daef1dc89 feat(activity-calendar): aggregate by ViewContext.timeBasis
Fixes the inconsistency where switching the memo list to update_time
left the activity heatmap aggregating by created_time. The heatmap
now follows the same time basis as the list it sits next to.

Backend
- UserStats gains memo_updated_timestamps (additive proto field, tag 8).
- GetUserStats and ListAllUserStats populate it alongside the existing
  memo_created_timestamps. No DB migration; memo.updated_ts already
  exists on every row.

Frontend
- useFilteredMemoStats reads timeBasis from ViewContext and selects
  the matching timestamp source.
- StatisticsView and MonthNavigator forward timeBasis through to
  MonthCalendar / YearCalendar so tooltip text matches the basis
  ("X memos in DATE" vs "X memos updated on DATE").
- Falls back to memoCreatedTimestamps when an old server returns an
  empty memoUpdatedTimestamps array (detected by length divergence,
  since protobuf-es deserializes missing repeated fields as []).

Tests
- Backend: TestGetUserStats_MemoUpdatedTimestamps verifies the field
  is populated and reflects post-creation updates.
- Frontend: filtered-memo-stats covers create/update source switching
  and the old-server fallback path; activity-calendar-tooltip covers
  basis-aware label selection.

Spec and implementation plan committed under docs/superpowers/.
2026-05-02 00:26:53 +08:00
Steven
ea0625da45 feat(stats): admin instance resource statistics 2026-05-01 23:15:56 +08:00
Steven
cd4f28ae10 feat(notification): add smtp email settings
- Add admin notification email settings UI and test-email RPC
- Dispatch privacy-first comment and mention emails through server notification layer
- Keep SMTP secrets write-only and require passwords when SMTP identity changes
2026-05-01 18:48:21 +08:00
Steven
35bf761b8c fix(security): enforce attachment ownership on memo updates 2026-05-01 18:23:53 +08:00
Tokenicrat 词元
603781f792
fix(frontend): use correct url path for memos in sitemap.xml (#5921) 2026-05-01 16:08:31 +08:00
boojack
1df3fe7955
fix(user): omit internal settings from list responses (#5917) 2026-04-30 08:49:03 +08:00
boojack
9c5c604944 feat: add link metadata endpoints 2026-04-29 22:38:08 +08:00
memoclaw
c7242324a1 fix(fileserver): preserve HDR image metadata in thumbnails 2026-04-29 21:32:10 +08:00
boojack
94ce1e5347 chore(settings): show build commit in version info 2026-04-27 08:51:11 +08:00
boojack
c268551a16
feat(memos): choose created or updated time for memos (#5894) 2026-04-26 11:50:26 +08:00
boojack
0fb83a745d
fix(auth): harden authorization and username validation (#5890) 2026-04-25 21:24:16 +08:00
boojack
ee1799851e
feat: redesign account and SSO management (#5886) 2026-04-24 09:08:58 +08:00
boojack
30c0611a82
fix: fix legacy username auth flows (#5885) 2026-04-23 22:35:38 +08:00
boojack
d688914b28
feat(auth): add SSO user identity linkage (#5883) 2026-04-23 08:51:45 +08:00
boojack
50638040f6
fix: reduce list memo query overhead (#5880) 2026-04-22 09:31:48 +08:00
George Wu
bbded584ce
fix: user resource names can be uuidv4 from idp sub claim (#5856) 2026-04-19 13:05:08 +08:00
boojack
01be01f4b7
fix: mixed-case user resource names (#5853) 2026-04-19 10:44:25 +08:00
boojack
583c3d24f4
feat(mcp): harden tool exposure and side effects (#5850) 2026-04-18 22:28:35 +08:00
wndnjs0
0fc1dab28b
fix: add unix socket file permission setting (755 -> 660) (#5849) 2026-04-18 13:21:03 +08:00
boojack
ff6389a5ef fix(api): appease image size lint 2026-04-16 23:21:07 +08:00
boojack
c45663761d fix(api): reduce memory pressure in backend paths 2026-04-16 23:08:48 +08:00
boojack
8479e1d5a3 test: close SSE response body explicitly 2026-04-16 22:57:31 +08:00
boojack
a5ddd5adaf fix(server): close SSE clients during shutdown
Close long-lived SSE streams before HTTP shutdown so graceful shutdown is not held until the deadline. Also wait for background runners before closing the store to make shutdown ordering explicit.
2026-04-16 22:49:10 +08:00
boojack
a7fd1dacc9
refactor(ai): use official provider SDKs (#5845) 2026-04-16 22:27:57 +08:00
boojack
101704c8ea
feat(ai): add BYOK audio transcription (#5832) 2026-04-13 22:09:24 +08:00
boojack
0ad0fec8d4 feat(ai): add Anthropic provider option 2026-04-12 21:42:17 +08:00
memoclaw
d87539a1e1
feat: add Gemini transcription provider (#5830)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-12 21:12:03 +08:00
memoclaw
83ed32f119
feat(ai): add instance AI providers and transcription (#5829)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-12 19:23:34 +08:00
boojack
40fd700fb8 fix(fileserver): render SVG attachment previews 2026-04-12 10:41:38 +08:00
boojack
fee7fcd660 fix(frontend): restore sitemap and robots routes 2026-04-10 22:23:00 +08:00
memoclaw
24fc8ab8ca
feat(mentions): add memo mention parsing, notifications, and rendering (#5811)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-06 22:16:53 +08:00
boojack
c3e7e2c316 fix: normalize attachment MIME types before validation 2026-04-06 14:05:24 +08:00
boojack
10a955fd62 refactor: move plugin packages under internal 2026-04-06 11:10:32 +08:00
boojack
4b4e719470
feat(attachments): add Live Photo and Motion Photo support (#5810) 2026-04-06 10:47:01 +08:00
boojack
25feef3aad
fix(api): tolerate missing related users in memo conversions (#5809) 2026-04-06 08:23:18 +08:00
memoclaw
1921b57662
fix(tags): allow blur-only tag metadata (#5800)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-31 21:38:55 +08:00
boojack
0e89407ee9 fix(filter): enforce CEL syntax semantics
Reject non-standard truthy numeric expressions in filters and document the parser as a supported subset of standard CEL syntax.

- remove legacy filter rewrites
- support standard equality in tag exists predicates
- add regression coverage for accepted and rejected expressions
2026-03-31 08:10:49 +08:00
boojack
d3f6e8ee31 chore: harden MCP access control and origin validation 2026-03-31 00:12:28 +08:00
boojack
7c708ee27e
chore: add migration upgrade coverage (#5796) 2026-03-30 23:51:57 +08:00
memoclaw
acbc914dea
fix(webhooks): trigger memo updates for attachment and relation changes (#5795)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-30 20:01:16 +08:00
memoclaw
9610ed8fc8
fix(lint): correct goimports struct literal alignment after removing write-only credential fields (#5794)
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-29 20:31:09 +08:00
memoclaw
9d3a74bccc fix(api): make credentials write-only and restrict sensitive settings to admins
Security fixes for credential leakage across three resources:

- NOTIFICATION setting: restrict GetInstanceSetting to admin-only
  (was publicly accessible, exposing SMTP credentials)
- SMTP password: never return SmtpPassword in API responses (write-only)
- S3 secret: never return AccessKeySecret in API responses (write-only)
- OAuth2 ClientSecret: never return in API responses for any role
  (was previously returned to admins); remove redactIdentityProviderResponse
  in favor of omitting the field at the conversion layer
- Preserve-on-empty: when updating settings with an empty credential
  field, preserve the existing stored value instead of overwriting
  (applies to SmtpPassword, AccessKeySecret, and ClientSecret)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 07:34:00 +08:00
memoclaw
c53677fcba fix(api): improve SSE hub design and fix double-broadcast on comments
- Fix duplicate SSE event on comment creation: CreateMemoComment now
  suppresses the redundant memo.created broadcast from the inner
  CreateMemo call, emitting only memo.comment.created
- Extract reaction event-building IIFEs into buildMemoReactionSSEEvent
  helper, removing duplicated inline DB-fetch logic
- Promote resolveSSEAudienceCreatorID from method to free function
  (resolveSSECreatorID) since it never used the receiver
- Add userID to SSE connect/disconnect log lines for traceability
- Change canReceive default from permissive (return true) to
  deny-with-warning for unknown visibility types
- Add comprehensive tests covering all new helpers, visibility edge
  cases, slow-client drop behavior, and the double-broadcast fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 07:33:40 +08:00
memoclaw
4add9b04ad fix: prevent local attachment uploads from overwriting files 2026-03-26 21:46:51 +08:00
memoclaw
a24d420922
fix(api): restrict user email exposure to self and admins (#5784)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-25 22:02:08 +08:00
memoclaw
acddef1f3d
fix(api): switch user resource names to usernames (#5779)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-25 09:11:17 +08:00
memoclaw
45b21530d9
feat: add blur_content attribute to tag metadata settings (#5767)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-23 19:42:27 +08:00
memoclaw
9e04049632
feat: treat tag setting keys as anchored regex patterns (#5759)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-22 08:07:45 +08:00
google-labs-jules[bot]
e0cc247823
chore: optimize multi-user RSS feed generation by fixing N+1 query (#5749)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-03-20 18:09:24 +08:00
memoclaw
6f1f3d81c5
chore: remove disallow_public_visibility setting (#5743)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-20 00:00:51 +08:00
memoclaw
3f3133d6e2
feat(memo): add share links for private memos (#5742)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-19 23:47:22 +08:00
memoclaw
f759b416af
refactor(inbox): store memo comment payloads without activity records (#5741)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-19 19:33:25 +08:00
memoclaw
a249d06e2e
feat(instance): add notification transport setting (#5737)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-19 09:18:28 +08:00
boojack
65d14fbb63
feat(instance): add canonical tag metadata setting (#5736) 2026-03-19 08:54:43 +08:00
boojack
330291d4d9
feat(user): add per-user tag metadata settings (#5735) 2026-03-18 23:15:14 +08:00
boojack
04f239a2fc
fix(api): remove public activity service (#5734) 2026-03-18 22:42:57 +08:00
memoclaw
12e2205cb6
chore(backend): update Go toolchain and dependencies (#5730) 2026-03-16 21:07:52 +08:00
memoclaw
1e688b2a5d
feat: extract title from first H1 heading into memo property (#5726)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:05:03 +08:00
memoclaw
b8e9ee2b26
feat(mcp): enhance MCP server with full capabilities and new tools (#5720)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:15:52 +08:00
memoclaw
f4154d090b
fix: restrict archived memo access to creator only (#5707)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:15:08 +08:00
memoclaw
8f43e8075b
fix: correct typos in comments, error messages, and identifiers (#5704)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:40:17 +08:00
memoclaw
1e82714a52
perf: batch load memo relations when listing memos (#5692)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:19:19 +08:00
memoclaw
92d937b1aa
feat: replace auto-increment ID with UID for identity provider resource names (#5687)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 21:01:22 +08:00
Biplav Barua
def123232a
feat: implement ListActivities pagination (#5468) 2026-03-04 19:08:47 +08:00
Steven
0cf8805184 refactor(sse): move status indicator to avatar badge
Replace the standalone SSE dot above UserMenu with a small badge
overlaid on the bottom-right of the user avatar. Only visible when
status is connecting (yellow) or disconnected (red) — invisible in the
normal connected state, removing constant visual noise.
2026-03-03 23:25:01 +08:00
milvasic
ea0892a8b2
feat: add live refresh via Server-Sent Events (SSE) with visual indicator (#5638)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: milvasic <milvasic@users.noreply.github.com>
2026-03-03 22:56:12 +08:00
Johnny
803d488a5f feat(mcp): refactor MCP server to standard protocol structure
- Replace PAT-only auth with optional auth supporting both PAT and JWT
  via auth.Authenticator.Authenticate(); unauthenticated requests see
  only public memos, matching REST API visibility semantics
- Inline auth middleware into mcp.go following fileserver pattern;
  remove auth_middleware.go
- Introduce memoJSON response type that correctly serialises store.Memo
  (including Payload.Tags and Payload.Property) without proto marshalling
- Add tools: list_memo_comments, create_memo_comment, list_tags
- Extend list_memos with state (NORMAL/ARCHIVED), order_by_pinned, and
  page parameters
- Extend update_memo with pinned and state parameters
- Extract #tags from content on create/update via regex to pre-populate
  Payload.Tags without requiring a full markdown service rebuild
- Add MCP Resources: memo://memos/{uid} template returns memo as
  Markdown with YAML frontmatter, allowing clients to read memos by URI
- Add MCP Prompts: capture (save a thought) and review (search + summarise)
2026-03-01 23:10:23 +08:00
Johnny
7c1defba01 feat(webhook): dispatch webhook on memo comment creation 2026-03-01 20:11:23 +08:00
Steven
26d10212c6 refactor: consolidate duplicated auth logic into auth package
Add ApplyToContext and AuthenticateToUser helpers to the auth package,
then remove the duplicated auth code spread across the MCP middleware,
file server, Connect interceptor, and gRPC-Gateway middleware.

- auth.ApplyToContext: single place to set claims/user into context after Authenticate()
- auth.AuthenticateToUser: resolves any credential (bearer token or refresh cookie) to a *store.User
- MCP middleware: replaced manual PAT DB lookup + expiry check with Authenticator.AuthenticateByPAT
- File server: replaced authenticateByBearerToken/authenticateByRefreshToken with AuthenticateToUser
- Connect interceptor + Gateway middleware: replaced duplicated context-setting block with ApplyToContext
- MCPService now accepts secret to construct its own Authenticator
2026-02-24 23:08:16 +08:00
Steven
47d9414702 feat: add MCP server with PAT authentication
Embeds a Model Context Protocol (MCP) server into the Memos HTTP
process, exposing memo operations as MCP tools at POST/GET /mcp using
Streamable HTTP transport.

Authentication is PAT-only — requests without a valid personal access
token receive HTTP 401. Six tools are exposed: list_memos, get_memo,
create_memo, update_memo, delete_memo, and search_memos, all scoped to the authenticated user.
2026-02-24 22:54:51 +08:00
Steven
704503e556 fix(store): allow memo/attachment deletion when local file is missing
Fixes two bugs reported in #5603:

1. store/attachment.go: ignore os.ErrNotExist when removing a local
   attachment file so that a missing file on disk (broken state from
   failed uploads) no longer blocks deletion of the DB record, allowing
   memos referencing corrupt attachments to be deleted normally.

2. memo_attachment_service.go: add nil guard on GetAttachment result
   before dereferencing it in SetMemoAttachments, preventing a nil
   pointer panic when an attachment UID no longer exists in the DB.
2026-02-23 10:26:40 +08:00
Steven
150371d211 fix(webhook): remediate SSRF vulnerability in webhook dispatcher
- Add plugin/webhook/validate.go as single source of truth for SSRF
  protection: reserved CIDR list parsed once at init(), isReservedIP(),
  and exported ValidateURL() used at registration/update time
- Replace unguarded http.Client in webhook.go with safeClient whose
  Transport uses a custom DialContext that re-resolves hostnames at
  dial time, defeating DNS rebinding attacks
- Call webhook.ValidateURL() in CreateUserWebhook and both
  UpdateUserWebhook paths to reject non-http/https schemes and
  reserved/private IP targets before persisting
- Strip internal service response body from non-2xx error log messages
  to prevent data leakage via application logs
2026-02-23 10:14:24 +08:00
Steven
71e8a06463 chore: upgrade Echo v4 to v5.0.3 2026-02-10 09:15:27 +08:00
Johnny
b623162d37 chore: fix static check linter warnings 2026-02-08 21:37:02 +08:00
Johnny
984d9b461b fix: gracefully handle deleted memos in activity service to prevent inbox crashes 2026-02-08 21:26:18 +08:00
Johnny
d9dc5be200 fix: replace echo.NewHTTPError with status.Errorf 2026-02-08 19:23:34 +08:00
Johnny
1696c6c414 fix: add nil check for currentUser in DeleteUser
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).
2026-01-31 23:08:09 +08:00
Johnny
c7b48b800f fix: add access control checks for attachments, comments, and reactions
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.
2026-01-31 23:02:30 +08:00
Johnny
86fab0cf4c fix(fileserver): use streaming for video/audio to prevent memory exhaustion
- 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
2026-01-31 22:01:28 +08:00
Steven
b32cba35c6 fix: add nil check for AnyResponse in WrapUnary method to prevent caching issues 2026-01-29 21:32:54 +08:00
Steven
b0558824c4 feat: update instance profile to use admin user instead of initialized flag
- Changed InstanceProfile to include admin user field
- Updated GetInstanceProfile method to retrieve admin user
- Modified related tests to reflect changes in admin user retrieval
- Removed owner cache logic and tests, introducing new admin cache tests
2026-01-28 23:27:53 +08:00
Johnny
a7b0d71f6e feat: implement EXIF metadata stripping for image uploads 2026-01-26 22:18:44 +08:00
Steven
501e8f1eae chore: implement read-write lock for owner cache 2026-01-22 22:11:47 +08:00
Steven
edcddf3c95 chore: fix tests 2026-01-22 21:59:23 +08:00
Steven
fd29a98c90 chore: fix linter 2026-01-22 21:03:05 +08:00
Steven
ba099b72ed feat: update InstanceProfile to include initialization status
- Removed the owner field from InstanceProfile as it is no longer needed.
- Added an initialized field to InstanceProfile to indicate if the instance has completed first-time setup.
- Updated GetInstanceProfile method to set initialized based on the existence of an admin user.
- Modified tests to reflect changes in InstanceProfile and ensure correct behavior regarding instance initialization.
- Adjusted frontend logic to redirect users based on the initialized status instead of the owner field.
2026-01-22 20:59:40 +08:00
Steven
956ae0ebc5 fix: prevent browser caching of API responses in MetadataInterceptor 2026-01-21 08:12:23 +08:00
Johnny
0f3c9a467d refactor: migrate HOST roles to ADMIN
- Updated the isSuperUser function to only check for ADMIN role.
- Added SQL migration scripts for MySQL, PostgreSQL, and SQLite to change user roles from HOST to ADMIN.
- Created a new SQLite migration to alter the user table structure and ensure data integrity during the migration process.
2026-01-20 23:38:30 +08:00
Johnny
47ebb04dc3 refactor: remove mode flag and introduce explicit demo flag 2026-01-20 22:58:33 +08:00
Johnny
dc7ec8a8ad feat: allow setting custom timestamps when creating memos and comments
Allow API users to set custom create_time, update_time, and display_time
when creating memos and comments. This enables importing historical data
with accurate timestamps.

Changes:
- Update proto definitions: change create_time and update_time from
  OUTPUT_ONLY to OPTIONAL to allow setting on creation
- Modify CreateMemo service to handle custom timestamps from request
- Update database drivers (SQLite, MySQL, PostgreSQL) to support
  inserting custom timestamps when provided
- Add comprehensive test coverage for custom timestamp functionality
- Maintain backward compatibility: auto-generated timestamps still
  work when custom values are not provided
- Fix golangci-lint issues in plugin/filter (godot and revive)

Fixes #5483
2026-01-17 12:56:03 +08:00
Steven
61dbca8dc2 fix: prevent browser cache from serving stale memo data (#5470)
This fixes a critical data loss issue where users editing the same memo
on multiple devices would overwrite each other's changes due to aggressive
browser caching, particularly in Chromium-based browsers and PWAs.

Changes:
- Backend: Add Cache-Control headers to all API responses to prevent
  browser HTTP caching
- Frontend: Force fresh fetch from server when opening memo editor by
  invalidating React Query cache
- Frontend: Reduce memo query staleTime from 60s to 10s for better
  collaborative editing support

Fixes #5470
2026-01-13 20:55:21 +08:00
Johnny
f58533003b fix: clean up memo_relation and attachments when deleting memo
Fixes #5472

Move cleanup logic to store.DeleteMemo to ensure data consistency:
- Delete memo_relation records where memo is source (MemoID) or target (RelatedMemoID)
- Delete attachments linked to the memo (including S3/local files)

This prevents stale COMMENT records in memo_relation after deleting
a memo that has comments.
2026-01-12 23:18:04 +08:00
Johnny
7053edae27 fix: allow guests to view public memo comments
Add ListMemoComments to public endpoints whitelist so unauthenticated
users can see public comments. The service layer already filters
comments by visibility (only PUBLIC for guests).

Fixes #5471
2026-01-11 22:35:12 +08:00