From b3efb2514bdd160f1b41d55f01e73461d4626968 Mon Sep 17 00:00:00 2001
From: =AhmedAshraf <=ahmedashrafelgendy25@gmail.com>
Date: Sun, 22 Mar 2026 17:57:16 +0200
Subject: [PATCH 1/9] i fixed the conflicts feat: add memo color customization
---
.dockerignore | 24 +-
.github/FUNDING.yml | 2 +-
.github/ISSUE_TEMPLATE/bug_report.yml | 198 +-
.github/ISSUE_TEMPLATE/config.yml | 16 +-
.github/ISSUE_TEMPLATE/feature_request.yml | 156 +-
.github/workflows/backend-tests.yml | 182 +-
.github/workflows/build-canary-image.yml | 332 +-
.github/workflows/demo-deploy.yml | 34 +-
.github/workflows/frontend-tests.yml | 144 +-
.github/workflows/proto-linter.yml | 80 +-
.github/workflows/release.yml | 704 +-
.github/workflows/stale.yml | 48 +-
.gitignore | 58 +-
.golangci.yaml | 202 +-
AGENTS.md | 204 +-
CLAUDE.md | 10 +-
CODEOWNERS | 4 +-
LICENSE | 42 +-
README.md | 240 +-
SECURITY.md | 92 +-
cmd/memos/main.go | 382 +-
go.mod | 282 +-
go.sum | 710 +-
internal/base/resource_name.go | 14 +-
internal/base/resource_name_test.go | 70 +-
internal/profile/profile.go | 214 +-
internal/util/util.go | 146 +-
internal/util/util_test.go | 62 +-
internal/version/version.go | 108 +-
internal/version/version_test.go | 212 +-
memos_prod.db | Bin 0 -> 4096 bytes
memos_prod.db-shm | Bin 0 -> 32768 bytes
memos_prod.db-wal | Bin 0 -> 453232 bytes
node_modules/.modules.yaml | 36 +
node_modules/.pnpm-workspace-state-v1.json | 26 +
node_modules/.pnpm/lock.yaml | 49 +
node_modules/.pnpm/node_modules/react | 1 +
node_modules/.pnpm/node_modules/react-dom | 1 +
node_modules/.pnpm/node_modules/scheduler | 1 +
.../node_modules/react | 1 +
.../react-colorful/ACKNOWLEDGMENTS | 5 +
.../node_modules/react-colorful/CHANGELOG.md | 257 +
.../node_modules/react-colorful/LICENSE | 21 +
.../node_modules/react-colorful/README.md | 343 +
.../node_modules/react-colorful/package.json | 200 +
.../node_modules/react-dom | 1 +
.../node_modules/react | 1 +
.../node_modules/react-dom/LICENSE | 21 +
.../node_modules/react-dom/README.md | 60 +
.../cjs/react-dom-client.development.js | 28121 +++++++++++++++
.../cjs/react-dom-client.production.js | 16049 +++++++++
.../cjs/react-dom-profiling.development.js | 28503 ++++++++++++++++
.../cjs/react-dom-profiling.profiling.js | 18068 ++++++++++
...t-dom-server-legacy.browser.development.js | 9877 ++++++
...ct-dom-server-legacy.browser.production.js | 6603 ++++
...eact-dom-server-legacy.node.development.js | 9877 ++++++
...react-dom-server-legacy.node.production.js | 6692 ++++
.../react-dom-server.browser.development.js | 10601 ++++++
.../react-dom-server.browser.production.js | 7410 ++++
.../cjs/react-dom-server.bun.development.js | 9605 ++++++
.../cjs/react-dom-server.bun.production.js | 6745 ++++
.../cjs/react-dom-server.edge.development.js | 10620 ++++++
.../cjs/react-dom-server.edge.production.js | 7512 ++++
.../cjs/react-dom-server.node.development.js | 10802 ++++++
.../cjs/react-dom-server.node.production.js | 7707 +++++
.../cjs/react-dom-test-utils.development.js | 24 +
.../cjs/react-dom-test-utils.production.js | 21 +
.../react-dom/cjs/react-dom.development.js | 424 +
.../react-dom/cjs/react-dom.production.js | 210 +
.../cjs/react-dom.react-server.development.js | 340 +
.../cjs/react-dom.react-server.production.js | 152 +
.../node_modules/react-dom/client.js | 38 +
.../react-dom/client.react-server.js | 5 +
.../node_modules/react-dom/index.js | 38 +
.../node_modules/react-dom/package.json | 117 +
.../node_modules/react-dom/profiling.js | 38 +
.../react-dom/profiling.react-server.js | 5 +
.../react-dom/react-dom.react-server.js | 7 +
.../node_modules/react-dom/server.browser.js | 16 +
.../node_modules/react-dom/server.bun.js | 17 +
.../node_modules/react-dom/server.edge.js | 17 +
.../node_modules/react-dom/server.js | 3 +
.../node_modules/react-dom/server.node.js | 18 +
.../react-dom/server.react-server.js | 5 +
.../node_modules/react-dom/static.browser.js | 12 +
.../node_modules/react-dom/static.edge.js | 12 +
.../node_modules/react-dom/static.js | 3 +
.../node_modules/react-dom/static.node.js | 14 +
.../react-dom/static.react-server.js | 5 +
.../node_modules/react-dom/test-utils.js | 7 +
.../node_modules/scheduler | 1 +
.../react@19.2.4/node_modules/react/LICENSE | 21 +
.../react@19.2.4/node_modules/react/README.md | 37 +
.../cjs/react-compiler-runtime.development.js | 24 +
.../cjs/react-compiler-runtime.production.js | 16 +
.../cjs/react-compiler-runtime.profiling.js | 16 +
.../cjs/react-jsx-dev-runtime.development.js | 338 +
.../cjs/react-jsx-dev-runtime.production.js | 14 +
.../cjs/react-jsx-dev-runtime.profiling.js | 14 +
...sx-dev-runtime.react-server.development.js | 370 +
...jsx-dev-runtime.react-server.production.js | 40 +
.../cjs/react-jsx-runtime.development.js | 352 +
.../react/cjs/react-jsx-runtime.production.js | 34 +
.../react/cjs/react-jsx-runtime.profiling.js | 34 +
...ct-jsx-runtime.react-server.development.js | 370 +
...act-jsx-runtime.react-server.production.js | 40 +
.../react/cjs/react.development.js | 1284 +
.../react/cjs/react.production.js | 542 +
.../cjs/react.react-server.development.js | 848 +
.../cjs/react.react-server.production.js | 423 +
.../node_modules/react/compiler-runtime.js | 14 +
.../react@19.2.4/node_modules/react/index.js | 7 +
.../node_modules/react/jsx-dev-runtime.js | 7 +
.../react/jsx-dev-runtime.react-server.js | 7 +
.../node_modules/react/jsx-runtime.js | 7 +
.../react/jsx-runtime.react-server.js | 7 +
.../node_modules/react/package.json | 51 +
.../node_modules/react/react.react-server.js | 7 +
.../node_modules/scheduler/LICENSE | 21 +
.../node_modules/scheduler/README.md | 9 +
.../scheduler-unstable_mock.development.js | 414 +
.../cjs/scheduler-unstable_mock.production.js | 406 +
...cheduler-unstable_post_task.development.js | 150 +
...scheduler-unstable_post_task.production.js | 140 +
.../scheduler/cjs/scheduler.development.js | 364 +
.../cjs/scheduler.native.development.js | 350 +
.../cjs/scheduler.native.production.js | 330 +
.../scheduler/cjs/scheduler.production.js | 340 +
.../node_modules/scheduler/index.js | 7 +
.../node_modules/scheduler/index.native.js | 7 +
.../node_modules/scheduler/package.json | 27 +
.../node_modules/scheduler/unstable_mock.js | 7 +
.../scheduler/unstable_post_task.js | 7 +
node_modules/react-colorful | 1 +
plugin/cron/README.md | 2 +-
plugin/cron/chain.go | 192 +-
plugin/cron/chain_test.go | 504 +-
plugin/cron/constantdelay.go | 54 +-
plugin/cron/constantdelay_test.go | 110 +-
plugin/cron/cron.go | 698 +-
plugin/cron/cron_test.go | 1410 +-
plugin/cron/logger.go | 172 +-
plugin/cron/option.go | 90 +-
plugin/cron/option_test.go | 86 +-
plugin/cron/parser.go | 892 +-
plugin/cron/parser_test.go | 768 +-
plugin/cron/spec.go | 376 +-
plugin/cron/spec_test.go | 602 +-
plugin/email/README.md | 1014 +-
plugin/email/client.go | 286 +-
plugin/email/client_test.go | 242 +-
plugin/email/config.go | 94 +-
plugin/email/config_test.go | 160 +-
plugin/email/doc.go | 196 +-
plugin/email/email.go | 86 +-
plugin/email/email_test.go | 254 +-
plugin/email/message.go | 182 +-
plugin/email/message_test.go | 362 +-
plugin/filter/MAINTENANCE.md | 100 +-
plugin/filter/README.md | 126 +-
plugin/filter/engine.go | 382 +-
plugin/filter/helpers.go | 50 +-
plugin/filter/ir.go | 318 +-
plugin/filter/parser.go | 1172 +-
plugin/filter/render.go | 1496 +-
plugin/filter/schema.go | 638 +-
plugin/httpgetter/html_meta.go | 332 +-
plugin/httpgetter/html_meta_test.go | 64 +-
plugin/httpgetter/http_getter.go | 2 +-
plugin/httpgetter/image.go | 90 +-
plugin/httpgetter/util.go | 30 +-
plugin/idp/idp.go | 16 +-
plugin/idp/oauth2/oauth2.go | 268 +-
plugin/idp/oauth2/oauth2_test.go | 328 +-
plugin/markdown/ast/tag.go | 56 +-
plugin/markdown/extensions/tag.go | 48 +-
plugin/markdown/markdown.go | 910 +-
plugin/markdown/markdown_test.go | 1188 +-
plugin/markdown/parser/tag.go | 300 +-
plugin/markdown/parser/tag_test.go | 526 +-
plugin/markdown/renderer/markdown_renderer.go | 532 +-
.../renderer/markdown_renderer_test.go | 352 +-
plugin/scheduler/README.md | 734 +-
plugin/scheduler/doc.go | 70 +-
plugin/scheduler/example_test.go | 330 +-
plugin/scheduler/integration_test.go | 786 +-
plugin/scheduler/job.go | 116 +-
plugin/scheduler/job_test.go | 180 +-
plugin/scheduler/middleware.go | 240 +-
plugin/scheduler/middleware_test.go | 292 +-
plugin/scheduler/parser.go | 458 +-
plugin/scheduler/parser_test.go | 254 +-
plugin/scheduler/scheduler.go | 404 +-
plugin/scheduler/scheduler_test.go | 330 +-
plugin/storage/s3/s3.go | 226 +-
plugin/webhook/validate.go | 166 +-
plugin/webhook/webhook.go | 240 +-
plugin/webhook/webhook_test.go | 2 +-
pnpm-lock.yaml | 49 +
proto/README.md | 34 +-
proto/api/v1/README.md | 6 +-
proto/api/v1/attachment_service.proto | 300 +-
proto/api/v1/auth_service.proto | 230 +-
proto/api/v1/common.proto | 46 +-
proto/api/v1/idp_service.proto | 294 +-
proto/api/v1/instance_service.proto | 2 -
proto/api/v1/memo_service.proto | 1194 +-
proto/api/v1/shortcut_service.proto | 248 +-
proto/api/v1/user_service.proto | 1368 +-
proto/buf.gen.yaml | 60 +-
proto/buf.lock | 12 +-
proto/buf.yaml | 38 +-
.../attachment_service.connect.go | 472 +-
.../v1/apiv1connect/auth_service.connect.go | 434 +-
.../v1/apiv1connect/idp_service.connect.go | 474 +-
.../apiv1connect/instance_service.connect.go | 346 +-
.../v1/apiv1connect/memo_service.connect.go | 1272 +-
.../apiv1connect/shortcut_service.connect.go | 472 +-
.../v1/apiv1connect/user_service.connect.go | 1412 +-
proto/gen/api/v1/attachment_service.pb.go | 1224 +-
proto/gen/api/v1/attachment_service.pb.gw.go | 1042 +-
.../gen/api/v1/attachment_service_grpc.pb.go | 568 +-
proto/gen/api/v1/auth_service.pb.go | 1256 +-
proto/gen/api/v1/auth_service.pb.gw.go | 686 +-
proto/gen/api/v1/auth_service_grpc.pb.go | 516 +-
proto/gen/api/v1/common.pb.go | 488 +-
proto/gen/api/v1/idp_service.pb.go | 1610 +-
proto/gen/api/v1/idp_service.pb.gw.go | 1014 +-
proto/gen/api/v1/idp_service_grpc.pb.go | 570 +-
proto/gen/api/v1/instance_service.pb.go | 26 +-
proto/gen/api/v1/instance_service.pb.gw.go | 698 +-
proto/gen/api/v1/instance_service_grpc.pb.go | 406 +-
proto/gen/api/v1/memo_service.pb.go | 4954 +--
proto/gen/api/v1/memo_service.pb.gw.go | 3298 +-
proto/gen/api/v1/memo_service_grpc.pb.go | 1612 +-
proto/gen/api/v1/shortcut_service.pb.go | 992 +-
proto/gen/api/v1/shortcut_service.pb.gw.go | 1086 +-
proto/gen/api/v1/shortcut_service_grpc.pb.go | 568 +-
proto/gen/api/v1/user_service.pb.go | 5984 ++--
proto/gen/api/v1/user_service.pb.gw.go | 3762 +-
proto/gen/api/v1/user_service_grpc.pb.go | 1788 +-
proto/gen/openapi.yaml | 8 -
proto/gen/store/attachment.pb.go | 574 +-
proto/gen/store/idp.pb.go | 952 +-
proto/gen/store/inbox.pb.go | 542 +-
proto/gen/store/instance_setting.pb.go | 24 +-
proto/gen/store/memo.pb.go | 586 +-
proto/gen/store/user_setting.pb.go | 2010 +-
proto/store/attachment.proto | 66 +-
proto/store/idp.proto | 84 +-
proto/store/inbox.proto | 48 +-
proto/store/instance_setting.proto | 2 -
proto/store/memo.proto | 58 +-
proto/store/user_setting.proto | 226 +-
scripts/Dockerfile | 112 +-
scripts/build.sh | 64 +-
scripts/compose.yaml | 16 +-
scripts/entrypoint.sh | 90 +-
scripts/entrypoint_test.sh | 262 +-
scripts/install.sh | 592 +-
server/auth/authenticator.go | 398 +-
server/auth/context.go | 198 +-
server/auth/extract.go | 66 +-
server/auth/token.go | 498 +-
server/auth/token_test.go | 612 +-
server/router/api/v1/acl_config.go | 90 +-
server/router/api/v1/acl_config_test.go | 172 +-
server/router/api/v1/attachment_exif_test.go | 382 +-
server/router/api/v1/attachment_service.go | 1308 +-
server/router/api/v1/auth_service.go | 1232 +-
.../api/v1/auth_service_client_info_test.go | 358 +-
server/router/api/v1/common.go | 136 +-
server/router/api/v1/connect_handler.go | 158 +-
server/router/api/v1/connect_interceptors.go | 474 +-
server/router/api/v1/connect_services.go | 1008 +-
server/router/api/v1/header_carrier.go | 248 +-
server/router/api/v1/health_service.go | 50 +-
server/router/api/v1/idp_service.go | 506 +-
server/router/api/v1/instance_service.go | 2 -
.../router/api/v1/memo_attachment_service.go | 272 +-
server/router/api/v1/memo_relation_service.go | 362 +-
server/router/api/v1/memo_service.go | 1820 +-
.../router/api/v1/memo_service_converter.go | 486 +-
server/router/api/v1/memo_service_filter.go | 2 +-
server/router/api/v1/memo_share_service.go | 444 +-
server/router/api/v1/reaction_service.go | 330 +-
server/router/api/v1/resource_name.go | 320 +-
server/router/api/v1/shortcut_service.go | 692 +-
server/router/api/v1/sse_handler.go | 186 +-
server/router/api/v1/sse_hub.go | 198 +-
server/router/api/v1/sse_hub_test.go | 140 +-
.../api/v1/test/attachment_service_test.go | 118 +-
server/router/api/v1/test/auth_test.go | 1310 +-
server/router/api/v1/test/idp_service_test.go | 1104 +-
.../api/v1/test/instance_admin_cache_test.go | 108 +-
.../api/v1/test/instance_service_test.go | 676 +-
.../v1/test/memo_attachment_service_test.go | 332 +-
.../api/v1/test/memo_relation_service_test.go | 338 +-
.../router/api/v1/test/memo_service_test.go | 738 +-
.../api/v1/test/memo_share_service_test.go | 218 +-
.../api/v1/test/reaction_service_test.go | 388 +-
.../api/v1/test/shortcut_service_test.go | 1638 +-
server/router/api/v1/test/sse_handler_test.go | 156 +-
server/router/api/v1/test/test_helper.go | 178 +-
.../api/v1/test/user_notification_test.go | 286 +-
.../v1/test/user_service_registration_test.go | 346 +-
.../api/v1/test/user_service_stats_test.go | 210 +-
server/router/api/v1/user_service.go | 2978 +-
server/router/api/v1/user_service_stats.go | 472 +-
server/router/api/v1/v1.go | 300 +-
server/router/fileserver/README.md | 614 +-
server/router/fileserver/fileserver.go | 1204 +-
server/router/fileserver/fileserver_test.go | 336 +-
server/router/frontend/dist/index.html | 39 +-
server/router/frontend/frontend.go | 136 +-
server/router/mcp/README.md | 252 +-
server/router/mcp/mcp.go | 130 +-
server/router/mcp/prompts.go | 384 +-
server/router/mcp/resources_memo.go | 170 +-
server/router/mcp/tools_attachment.go | 544 +-
server/router/mcp/tools_memo.go | 1198 +-
server/router/mcp/tools_reaction.go | 342 +-
server/router/mcp/tools_relation.go | 422 +-
server/router/mcp/tools_tag.go | 156 +-
server/router/rss/rss.go | 858 +-
server/runner/memopayload/runner.go | 176 +-
server/runner/s3presign/runner.go | 268 +-
server/server.go | 376 +-
store/attachment.go | 344 +-
store/cache.go | 18 +-
store/cache/cache.go | 654 +-
store/cache/cache_test.go | 418 +-
store/common.go | 48 +-
store/db/db.go | 64 +-
store/db/mysql/attachment.go | 482 +-
store/db/mysql/common.go | 20 +-
store/db/mysql/idp.go | 260 +-
store/db/mysql/inbox.go | 300 +-
store/db/mysql/instance_setting.go | 130 +-
store/db/mysql/memo.go | 538 +-
store/db/mysql/memo_relation.go | 244 +-
store/db/mysql/memo_share.go | 236 +-
store/db/mysql/mysql.go | 136 +-
store/db/mysql/reaction.go | 226 +-
store/db/mysql/user.go | 358 +-
store/db/mysql/user_setting.go | 186 +-
store/db/postgres/attachment.go | 442 +-
store/db/postgres/common.go | 52 +-
store/db/postgres/idp.go | 246 +-
store/db/postgres/inbox.go | 302 +-
store/db/postgres/instance_setting.go | 144 +-
store/db/postgres/memo.go | 508 +-
store/db/postgres/memo_relation.go | 296 +-
store/db/postgres/memo_share.go | 272 +-
store/db/postgres/postgres.go | 114 +-
store/db/postgres/reaction.go | 202 +-
store/db/postgres/user.go | 360 +-
store/db/postgres/user_setting.go | 242 +-
store/db/postgres/user_setting_test.go | 580 +-
store/db/sqlite/attachment.go | 442 +-
store/db/sqlite/common.go | 18 +-
store/db/sqlite/functions.go | 88 +-
store/db/sqlite/idp.go | 246 +-
store/db/sqlite/inbox.go | 282 +-
store/db/sqlite/instance_setting.go | 144 +-
store/db/sqlite/memo.go | 494 +-
store/db/sqlite/memo_relation.go | 270 +-
store/db/sqlite/memo_share.go | 276 +-
store/db/sqlite/reaction.go | 272 +-
store/db/sqlite/sqlite.go | 150 +-
store/db/sqlite/user.go | 378 +-
store/db/sqlite/user_setting.go | 218 +-
store/driver.go | 144 +-
store/idp.go | 372 +-
store/inbox.go | 150 +-
store/instance_setting.go | 598 +-
store/memo.go | 318 +-
store/memo_relation.go | 94 +-
store/memo_share.go | 92 +-
store/migration/mysql/0.17/00__inbox.sql | 18 +-
.../mysql/0.17/01__delete_activity.sql | 2 +-
.../migration/mysql/0.18/00__extend_text.sql | 6 +-
store/migration/mysql/0.18/01__webhook.sql | 20 +-
.../migration/mysql/0.18/02__user_setting.sql | 8 +-
.../mysql/0.19/00__add_resource_name.sql | 30 +-
store/migration/mysql/0.20/00__reaction.sql | 18 +-
.../mysql/0.21/00__user_description.sql | 2 +-
store/migration/mysql/0.21/01__rename_uid.sql | 6 +-
.../mysql/0.22/00__resource_storage_type.sql | 22 +-
store/migration/mysql/0.22/01__memo_tags.sql | 6 +-
.../migration/mysql/0.22/02__memo_payload.sql | 6 +-
store/migration/mysql/0.22/03__drop_tag.sql | 2 +-
store/migration/mysql/0.23/00__reactions.sql | 24 +-
store/migration/mysql/0.24/00__memo.sql | 2 +-
.../migration/mysql/0.24/01__memo_pinned.sql | 16 +-
.../mysql/0.24/02__s3_reference_length.sql | 4 +-
.../mysql/0.25/00__remove_webhook.sql | 2 +-
.../00__rename_resource_to_attachment.sql | 2 +-
.../mysql/0.26/01__drop_memo_organizer.sql | 2 +-
.../mysql/0.26/02__migrate_host_to_admin.sql | 2 +-
.../0.27/00__migrate_storage_setting.sql | 12 +-
.../migration/mysql/0.27/01__add_idp_uid.sql | 16 +-
.../02__migrate_inbox_message_payload.sql | 28 +-
.../mysql/0.27/03__drop_activity.sql | 2 +-
store/migration/mysql/0.27/04__memo_share.sql | 28 +-
store/migration/mysql/LATEST.sql | 222 +-
.../postgres/0.19/00__add_resource_name.sql | 30 +-
.../migration/postgres/0.20/00__reaction.sql | 18 +-
.../postgres/0.21/00__user_description.sql | 2 +-
.../postgres/0.21/01__rename_uid.sql | 6 +-
.../0.22/00__resource_storage_type.sql | 22 +-
.../migration/postgres/0.22/01__memo_tags.sql | 2 +-
.../postgres/0.22/02__memo_payload.sql | 2 +-
.../migration/postgres/0.22/03__drop_tag.sql | 2 +-
.../migration/postgres/0.23/00__reactions.sql | 24 +-
store/migration/postgres/0.24/00__memo.sql | 2 +-
.../postgres/0.24/01__memo_pinned.sql | 14 +-
.../postgres/0.25/00__remove_webhook.sql | 2 +-
.../00__rename_resource_to_attachment.sql | 2 +-
.../postgres/0.26/01__drop_memo_organizer.sql | 2 +-
.../0.26/02__migrate_host_to_admin.sql | 2 +-
.../0.27/00__migrate_storage_setting.sql | 10 +-
.../postgres/0.27/01__add_idp_uid.sql | 16 +-
.../02__migrate_inbox_message_payload.sql | 26 +-
.../postgres/0.27/03__drop_activity.sql | 2 +-
.../postgres/0.27/04__memo_share.sql | 28 +-
store/migration/postgres/LATEST.sql | 222 +-
store/migration/sqlite/0.10/00__activity.sql | 16 +-
.../migration/sqlite/0.11/00__user_avatar.sql | 6 +-
store/migration/sqlite/0.11/01__idp.sql | 14 +-
store/migration/sqlite/0.11/02__storage.sql | 12 +-
.../sqlite/0.12/00__user_setting.sql | 10 +-
.../sqlite/0.12/01__system_setting.sql | 136 +-
.../0.12/03__resource_internal_path.sql | 6 +-
.../sqlite/0.12/04__resource_public_id.sql | 34 +-
.../sqlite/0.13/00__memo_relation.sql | 12 +-
.../0.13/01__remove_memo_organizer_id.sql | 42 +-
.../0.14/00__drop_resource_public_id.sql | 50 +-
.../sqlite/0.14/01__create_indexes.sql | 10 +-
.../sqlite/0.15/00__drop_user_open_id.sql | 50 +-
.../0.16/00__add_memo_id_to_resource.sql | 26 +-
.../sqlite/0.16/01__drop_shortcut_table.sql | 2 +-
store/migration/sqlite/0.17/00__inbox.sql | 18 +-
.../sqlite/0.17/01__delete_activities.sql | 2 +-
store/migration/sqlite/0.18/00__webhook.sql | 24 +-
.../sqlite/0.18/01__user_setting.sql | 8 +-
.../sqlite/0.19/00__add_resource_name.sql | 22 +-
store/migration/sqlite/0.2/00__user_role.sql | 118 +-
.../sqlite/0.2/01__memo_visibility.sql | 6 +-
store/migration/sqlite/0.20/00__reaction.sql | 18 +-
.../sqlite/0.21/00__user_description.sql | 2 +-
.../migration/sqlite/0.21/01__rename_uid.sql | 6 +-
.../sqlite/0.22/00__resource_storage_type.sql | 34 +-
store/migration/sqlite/0.22/01__memo_tags.sql | 6 +-
.../sqlite/0.22/02__memo_payload.sql | 2 +-
store/migration/sqlite/0.23/00__reactions.sql | 24 +-
store/migration/sqlite/0.24/00__memo.sql | 12 +-
.../migration/sqlite/0.24/01__memo_pinned.sql | 22 +-
.../sqlite/0.25/00__remove_webhook.sql | 2 +-
.../00__rename_resource_to_attachment.sql | 10 +-
.../sqlite/0.26/01__drop_memo_organizer.sql | 2 +-
.../sqlite/0.26/02__drop_indexes.sql | 8 +-
.../sqlite/0.26/03__alter_user_role.sql | 48 +-
.../sqlite/0.26/04__migrate_host_to_admin.sql | 2 +-
.../0.27/00__migrate_storage_setting.sql | 10 +-
.../migration/sqlite/0.27/01__add_idp_uid.sql | 16 +-
.../02__migrate_inbox_message_payload.sql | 50 +-
.../sqlite/0.27/03__drop_activity.sql | 2 +-
.../migration/sqlite/0.27/04__memo_share.sql | 28 +-
.../0.3/00__memo_visibility_protected.sql | 84 +-
.../migration/sqlite/0.4/00__user_setting.sql | 16 +-
.../0.5/00__regenerate_foreign_keys.sql | 432 +-
.../sqlite/0.5/01__memo_resource.sql | 18 +-
.../sqlite/0.5/02__system_setting.sql | 12 +-
.../sqlite/0.5/03__resource_extermal_link.sql | 6 +-
.../sqlite/0.6/00__recreate_triggers.sql | 116 +-
store/migration/sqlite/0.7/00__remove_fk.sql | 380 +-
.../sqlite/0.7/01__remove_triggers.sql | 12 +-
.../sqlite/0.8/00__migration_history.sql | 8 +-
.../sqlite/0.8/01__user_username.sql | 98 +-
store/migration/sqlite/0.9/00__tag.sql | 10 +-
store/migration/sqlite/LATEST.sql | 224 +-
store/migrator.go | 810 +-
store/reaction.go | 82 +-
store/seed/DEMO_DATA_GUIDE.md | 410 +-
store/seed/sqlite/01__dump.sql | 106 +-
store/store.go | 114 +-
store/test/README.md | 26 +-
store/test/attachment_filter_test.go | 750 +-
store/test/attachment_test.go | 494 +-
store/test/containers.go | 636 +-
store/test/filter_helpers_test.go | 580 +-
store/test/idp_test.go | 936 +-
store/test/inbox_test.go | 1226 +-
store/test/instance_setting_test.go | 772 +-
store/test/main_test.go | 100 +-
store/test/memo_filter_test.go | 1878 +-
store/test/memo_relation_test.go | 1892 +-
store/test/memo_test.go | 956 +-
store/test/migrator_test.go | 400 +-
store/test/reaction_test.go | 378 +-
store/test/store.go | 222 +-
store/test/user_setting_test.go | 1986 +-
store/test/user_test.go | 572 +-
store/user.go | 318 +-
store/user_setting.go | 972 +-
web/.gitignore | 14 +-
web/biome.json | 402 +-
web/components.json | 40 +-
web/docs/auth-architecture.md | 110 +-
web/index.html | 48 +-
web/public/site.webmanifest | 28 +-
web/src/App.tsx | 132 +-
web/src/auth-state.ts | 256 +-
.../ActivityCalendar/CalendarCell.tsx | 164 +-
.../ActivityCalendar/MonthCalendar.tsx | 152 +-
.../ActivityCalendar/YearCalendar.tsx | 232 +-
.../components/ActivityCalendar/constants.ts | 70 +-
web/src/components/ActivityCalendar/hooks.ts | 46 +-
web/src/components/ActivityCalendar/index.ts | 8 +-
web/src/components/ActivityCalendar/types.ts | 78 +-
.../ActivityCalendar/useCalendar.ts | 188 +-
web/src/components/ActivityCalendar/utils.ts | 144 +-
web/src/components/AttachmentIcon.tsx | 216 +-
web/src/components/AuthFooter.tsx | 70 +-
.../components/ChangeMemberPasswordDialog.tsx | 228 +-
web/src/components/ConfirmDialog/README.md | 262 +-
web/src/components/ConfirmDialog/index.tsx | 118 +-
.../components/CreateAccessTokenDialog.tsx | 366 +-
.../CreateIdentityProviderDialog.tsx | 1064 +-
web/src/components/CreateShortcutDialog.tsx | 316 +-
web/src/components/CreateUserDialog.tsx | 300 +-
web/src/components/CreateWebhookDialog.tsx | 332 +-
web/src/components/DateTimeInput.tsx | 86 +-
web/src/components/Empty.tsx | 22 +-
web/src/components/ErrorBoundary.tsx | 206 +-
.../components/Inbox/MemoCommentMessage.tsx | 452 +-
web/src/components/LearnMore.tsx | 62 +-
web/src/components/LocaleSelect.tsx | 82 +-
.../MemoActionMenu/MemoActionMenu.tsx | 270 +-
web/src/components/MemoActionMenu/hooks.ts | 252 +-
web/src/components/MemoActionMenu/index.ts | 6 +-
web/src/components/MemoActionMenu/types.ts | 40 +-
web/src/components/MemoContent/CodeBlock.tsx | 312 +-
.../MemoContent/ConditionalComponent.tsx | 72 +-
.../components/MemoContent/MermaidBlock.tsx | 176 +-
web/src/components/MemoContent/Table.tsx | 152 +-
web/src/components/MemoContent/Tag.tsx | 4 +-
.../components/MemoContent/TaskListItem.tsx | 140 +-
web/src/components/MemoContent/constants.ts | 160 +-
web/src/components/MemoContent/hooks.ts | 56 +-
web/src/components/MemoContent/index.tsx | 67 +-
.../MemoContent/markdown/Blockquote.tsx | 34 +-
.../MemoContent/markdown/Heading.tsx | 5 +-
.../MemoContent/markdown/HorizontalRule.tsx | 22 +-
.../components/MemoContent/markdown/Image.tsx | 38 +-
.../MemoContent/markdown/InlineCode.tsx | 34 +-
.../components/MemoContent/markdown/Link.tsx | 54 +-
.../components/MemoContent/markdown/List.tsx | 142 +-
.../MemoContent/markdown/Paragraph.tsx | 34 +-
.../components/MemoContent/markdown/README.md | 194 +-
.../components/MemoContent/markdown/index.ts | 16 +-
.../components/MemoContent/markdown/types.ts | 18 +-
web/src/components/MemoContent/types.ts | 24 +-
web/src/components/MemoContent/utils.ts | 50 +-
.../MemoDetailSidebar/MemoDetailSidebar.tsx | 140 +-
.../MemoDetailSidebarDrawer.tsx | 5 +-
.../MemoDetailSidebar/MemoSharePanel.tsx | 316 +-
web/src/components/MemoDetailSidebar/index.ts | 8 +-
web/src/components/MemoDisplaySettingMenu.tsx | 98 +-
.../MemoEditor/Editor/SlashCommands.tsx | 90 +-
.../MemoEditor/Editor/SuggestionsPopup.tsx | 98 +-
.../MemoEditor/Editor/TagSuggestions.tsx | 100 +-
.../components/MemoEditor/Editor/commands.ts | 56 +-
.../components/MemoEditor/Editor/index.tsx | 436 +-
.../components/MemoEditor/Editor/shortcuts.ts | 140 +-
.../MemoEditor/Editor/useListCompletion.ts | 164 +-
.../MemoEditor/Editor/useSuggestions.ts | 316 +-
web/src/components/MemoEditor/README.md | 146 +-
.../MemoEditor/Toolbar/InsertMenu.tsx | 432 +-
.../MemoEditor/Toolbar/VisibilitySelector.tsx | 84 +-
.../components/MemoEditor/Toolbar/index.ts | 6 +-
.../MemoEditor/components/EditorContent.tsx | 150 +-
.../MemoEditor/components/EditorMetadata.tsx | 58 +-
.../MemoEditor/components/EditorToolbar.tsx | 112 +-
.../components/FocusModeOverlay.tsx | 40 +-
.../components/TimestampPopover.tsx | 178 +-
.../components/MemoEditor/components/index.ts | 14 +-
web/src/components/MemoEditor/constants.ts | 28 +-
web/src/components/MemoEditor/hooks/index.ts | 20 +-
.../MemoEditor/hooks/useAutoSave.ts | 18 +-
.../MemoEditor/hooks/useBlobUrls.ts | 56 +-
.../MemoEditor/hooks/useDragAndDrop.ts | 42 +-
.../MemoEditor/hooks/useFileUpload.ts | 68 +-
.../MemoEditor/hooks/useFocusMode.ts | 20 +-
.../MemoEditor/hooks/useKeyboard.ts | 64 +-
.../MemoEditor/hooks/useLinkMemo.ts | 170 +-
.../MemoEditor/hooks/useLocation.ts | 174 +-
.../MemoEditor/hooks/useMemoInit.ts | 80 +-
web/src/components/MemoEditor/index.tsx | 320 +-
.../MemoEditor/services/cacheService.ts | 50 +-
.../MemoEditor/services/errorService.ts | 28 +-
.../components/MemoEditor/services/index.ts | 10 +-
.../MemoEditor/services/memoService.ts | 294 +-
.../MemoEditor/services/uploadService.ts | 56 +-
.../MemoEditor/services/validationService.ts | 64 +-
.../components/MemoEditor/state/actions.ts | 156 +-
.../components/MemoEditor/state/context.tsx | 80 +-
web/src/components/MemoEditor/state/index.ts | 8 +-
.../components/MemoEditor/state/reducer.ts | 260 +-
web/src/components/MemoEditor/state/types.ts | 142 +-
.../components/MemoEditor/types/attachment.ts | 162 +-
.../components/MemoEditor/types/components.ts | 154 +-
web/src/components/MemoEditor/types/index.ts | 32 +-
.../MemoEditor/types/insert-menu.ts | 16 +-
.../components/MemoExplorer/MemoExplorer.tsx | 174 +-
.../MemoExplorer/MemoExplorerDrawer.tsx | 84 +-
.../MemoExplorer/ShortcutsSection.tsx | 270 +-
.../components/MemoExplorer/TagsSection.tsx | 200 +-
web/src/components/MemoExplorer/index.ts | 10 +-
web/src/components/MemoFilters.tsx | 212 +-
.../Attachment/AttachmentCard.tsx | 76 +-
.../Attachment/AttachmentListEditor.tsx | 334 +-
.../Attachment/AttachmentListView.tsx | 346 +-
.../MemoMetadata/Attachment/index.ts | 6 +-
.../MemoMetadata/Location/LocationDialog.tsx | 226 +-
.../Location/LocationDisplayEditor.tsx | 96 +-
.../Location/LocationDisplayView.tsx | 104 +-
.../components/MemoMetadata/Location/index.ts | 6 +-
.../MemoMetadata/Relation/LinkMemoDialog.tsx | 184 +-
.../MemoMetadata/Relation/RelationCard.tsx | 32 +-
.../Relation/RelationListEditor.tsx | 188 +-
.../Relation/RelationListView.tsx | 168 +-
.../components/MemoMetadata/Relation/index.ts | 8 +-
.../components/MemoMetadata/SectionHeader.tsx | 96 +-
web/src/components/MemoMetadata/index.ts | 12 +-
.../components/MemoPreview/MemoPreview.tsx | 87 +-
web/src/components/MemoPreview/index.ts | 2 +-
.../MemoReactionListView.tsx | 68 +-
.../MemoReactionListView/ReactionSelector.tsx | 126 +-
.../MemoReactionListView/ReactionView.tsx | 116 +-
.../components/MemoReactionListView/hooks.ts | 164 +-
.../components/MemoReactionListView/index.ts | 6 +-
.../MemoRelationForceGraph.tsx | 62 +
.../MemoRelationForceGraph/index.ts | 5 +
.../MemoRelationForceGraph/types.ts | 10 +
.../MemoRelationForceGraph/utils.ts | 36 +
web/src/components/MemoView/MemoView.tsx | 311 +-
.../components/MemoView/MemoViewContext.tsx | 8 +-
.../MemoView/components/MemoBody.tsx | 10 +-
.../components/MemoCommentListView.tsx | 25 +-
.../components/MemoCustomizeColor.tsx | 286 +
.../MemoView/components/MemoHeader.tsx | 292 +-
.../MemoView/components/MemoSnippetLink.tsx | 68 +-
.../components/MemoView/components/index.ts | 6 +-
web/src/components/MemoView/constants.ts | 8 +-
web/src/components/MemoView/hooks/index.ts | 6 +-
.../MemoView/hooks/useImagePreview.ts | 54 +-
.../MemoView/hooks/useMemoActions.ts | 26 +-
.../MemoView/hooks/useMemoHandlers.ts | 78 +-
web/src/components/MemoView/index.ts | 4 +-
web/src/components/MemoView/types.ts | 46 +-
web/src/components/MemosLogo.tsx | 52 +-
web/src/components/MobileHeader.tsx | 66 +-
web/src/components/Navigation.tsx | 250 +-
web/src/components/NavigationDrawer.tsx | 76 +-
.../PagedMemoList/PagedMemoList.tsx | 437 +-
web/src/components/PagedMemoList/index.ts | 6 +-
web/src/components/PasswordSignInForm.tsx | 240 +-
web/src/components/PreviewImageDialog.tsx | 202 +-
web/src/components/RequiredBadge.tsx | 22 +-
web/src/components/SearchBar.tsx | 102 +-
.../Settings/AccessTokenSection.tsx | 290 +-
.../components/Settings/InstanceSection.tsx | 360 +-
web/src/components/Settings/MemberSection.tsx | 418 +-
.../Settings/MemoRelatedSettings.tsx | 272 +-
.../components/Settings/MyAccountSection.tsx | 128 +-
.../Settings/PreferencesSection.tsx | 214 +-
web/src/components/Settings/SSOSection.tsx | 298 +-
.../components/Settings/SectionMenuItem.tsx | 50 +-
web/src/components/Settings/SettingGroup.tsx | 60 +-
web/src/components/Settings/SettingRow.tsx | 82 +-
.../components/Settings/SettingSection.tsx | 62 +-
web/src/components/Settings/SettingTable.tsx | 142 +-
.../components/Settings/StorageSection.tsx | 472 +-
web/src/components/Settings/TagsSection.tsx | 72 +-
.../components/Settings/WebhookSection.tsx | 242 +-
web/src/components/Skeleton.tsx | 102 +-
.../StatisticsView/MonthNavigator.tsx | 180 +-
.../StatisticsView/StatisticsView.tsx | 68 +-
web/src/components/StatisticsView/index.ts | 2 +-
web/src/components/TagTree.tsx | 320 +-
web/src/components/ThemeSelect.tsx | 102 +-
web/src/components/UpdateAccountDialog.tsx | 446 +-
.../UpdateCustomizedProfileDialog.tsx | 308 +-
web/src/components/UserAvatar.tsx | 46 +-
.../components/UserMemoMap/UserMemoMap.tsx | 246 +-
web/src/components/UserMemoMap/index.ts | 2 +-
web/src/components/UserMenu.tsx | 356 +-
web/src/components/VisibilityIcon.tsx | 56 +-
web/src/components/kit/OverflowTip.tsx | 80 +-
web/src/components/kit/SquareDiv.tsx | 90 +-
web/src/components/map/LocationPicker.tsx | 486 +-
web/src/components/map/index.ts | 6 +-
web/src/components/map/map-utils.tsx | 72 +-
web/src/components/map/useReverseGeocoding.ts | 78 +-
web/src/components/ui/badge.tsx | 68 +-
web/src/components/ui/button.tsx | 90 +-
web/src/components/ui/checkbox.tsx | 56 +-
web/src/components/ui/dialog.tsx | 244 +-
web/src/components/ui/dropdown-menu.tsx | 546 +-
web/src/components/ui/input.tsx | 36 +-
web/src/components/ui/label.tsx | 36 +-
web/src/components/ui/popover.tsx | 104 +-
web/src/components/ui/radio-group.tsx | 54 +-
web/src/components/ui/select.tsx | 296 +-
web/src/components/ui/separator.tsx | 50 +-
web/src/components/ui/sheet.tsx | 256 +-
web/src/components/ui/switch.tsx | 50 +-
web/src/components/ui/textarea.tsx | 34 +-
web/src/components/ui/tooltip.tsx | 118 +-
web/src/components/ui/visually-hidden.tsx | 38 +-
web/src/connect.ts | 402 +-
web/src/contexts/AuthContext.tsx | 366 +-
web/src/contexts/InstanceContext.tsx | 322 +-
web/src/contexts/MemoFilterContext.tsx | 320 +-
web/src/contexts/ViewContext.tsx | 128 +-
web/src/helpers/consts.ts | 10 +-
web/src/helpers/resource-names.ts | 112 +-
web/src/helpers/utils.ts | 78 +-
web/src/hooks/index.ts | 22 +-
web/src/hooks/useAsyncEffect.ts | 18 +-
web/src/hooks/useAttachmentQueries.ts | 114 +-
web/src/hooks/useCurrentUser.ts | 16 +-
web/src/hooks/useDateFilterNavigation.ts | 38 +-
web/src/hooks/useDialog.ts | 150 +-
web/src/hooks/useFilteredMemoStats.ts | 174 +-
web/src/hooks/useInstanceQueries.ts | 160 +-
web/src/hooks/useLiveMemoRefresh.ts | 422 +-
web/src/hooks/useLoading.ts | 70 +-
web/src/hooks/useMediaQuery.ts | 68 +-
web/src/hooks/useMemoFilters.ts | 200 +-
web/src/hooks/useMemoQueries.ts | 317 +-
web/src/hooks/useMemoShareQueries.ts | 9 -
web/src/hooks/useMemoSorting.ts | 96 +-
web/src/hooks/useNavigateTo.ts | 48 +-
web/src/hooks/useTokenRefreshOnFocus.ts | 98 +-
web/src/hooks/useUserLocale.ts | 70 +-
web/src/hooks/useUserQueries.ts | 492 +-
web/src/hooks/useUserTheme.ts | 74 +-
web/src/i18n.ts | 172 +-
web/src/index.css | 104 +-
web/src/layouts/MainLayout.tsx | 188 +-
web/src/layouts/RootLayout.tsx | 120 +-
web/src/lib/calendar-utils.ts | 46 +-
web/src/lib/color.ts | 42 +-
web/src/lib/error.ts | 76 +-
web/src/lib/query-client.ts | 58 +-
web/src/lib/tag.ts | 128 +-
web/src/lib/utils.ts | 12 +-
web/src/locales/ar.json | 6 +-
web/src/locales/ca.json | 6 +-
web/src/locales/cs.json | 6 +-
web/src/locales/de.json | 6 +-
web/src/locales/en-GB.json | 38 +-
web/src/locales/en.json | 8 +-
web/src/locales/es.json | 6 +-
web/src/locales/fa.json | 6 +-
web/src/locales/fr.json | 6 +-
web/src/locales/gl.json | 6 +-
web/src/locales/hi.json | 6 +-
web/src/locales/hr.json | 6 +-
web/src/locales/hu.json | 6 +-
web/src/locales/id.json | 6 +-
web/src/locales/it.json | 6 +-
web/src/locales/ja.json | 6 +-
web/src/locales/ka-GE.json | 6 +-
web/src/locales/ko.json | 6 +-
web/src/locales/mr.json | 6 +-
web/src/locales/nb.json | 6 +-
web/src/locales/nl.json | 6 +-
web/src/locales/pl.json | 6 +-
web/src/locales/pt-BR.json | 6 +-
web/src/locales/pt-PT.json | 6 +-
web/src/locales/ru.json | 6 +-
web/src/locales/sl.json | 6 +-
web/src/locales/sv.json | 6 +-
web/src/locales/th.json | 6 +-
web/src/locales/tr.json | 6 +-
web/src/locales/uk.json | 6 +-
web/src/locales/vi.json | 6 +-
web/src/locales/zh-Hans.json | 6 +-
web/src/locales/zh-Hant.json | 6 +-
web/src/main.tsx | 164 +-
web/src/pages/AdminSignIn.tsx | 46 +-
web/src/pages/Archived.tsx | 70 +-
web/src/pages/Attachments.tsx | 584 +-
web/src/pages/AuthCallback.tsx | 252 +-
web/src/pages/Explore.tsx | 82 +-
web/src/pages/Home.tsx | 74 +-
web/src/pages/Inboxes.tsx | 244 +-
web/src/pages/MemoDetail.tsx | 304 +-
web/src/pages/NotFound.tsx | 30 +-
web/src/pages/PermissionDenied.tsx | 30 +-
web/src/pages/Setting.tsx | 324 +-
web/src/pages/SharedMemo.tsx | 85 +
web/src/pages/SignIn.tsx | 270 +-
web/src/pages/SignUp.tsx | 324 +-
web/src/pages/UserProfile.tsx | 312 +-
web/src/router/index.tsx | 4 +-
web/src/router/routes.ts | 26 +-
web/src/themes/COLOR_GUIDE.md | 598 +-
web/src/themes/default-dark.css | 86 +-
web/src/themes/default.css | 166 +-
web/src/themes/paper.css | 64 +-
web/src/types/common.d.ts | 2 +-
web/src/types/common.ts | 26 +-
web/src/types/i18n.d.ts | 2 +-
web/src/types/markdown.ts | 88 +-
web/src/types/modules/setting.d.ts | 2 +-
.../proto/api/v1/attachment_service_pb.ts | 644 +-
web/src/types/proto/api/v1/auth_service_pb.ts | 600 +-
web/src/types/proto/api/v1/common_pb.ts | 180 +-
web/src/types/proto/api/v1/idp_service_pb.ts | 752 +-
.../types/proto/api/v1/instance_service_pb.ts | 14 +-
web/src/types/proto/api/v1/memo_service_pb.ts | 2646 +-
.../types/proto/api/v1/shortcut_service_pb.ts | 500 +-
web/src/types/proto/api/v1/user_service_pb.ts | 3124 +-
.../types/proto/google/api/annotations_pb.ts | 78 +-
web/src/types/proto/google/api/client_pb.ts | 1906 +-
.../proto/google/api/field_behavior_pb.ts | 314 +-
web/src/types/proto/google/api/http_pb.ts | 948 +-
.../types/proto/google/api/launch_stage_pb.ts | 236 +-
web/src/types/proto/google/api/resource_pb.ts | 708 +-
web/src/types/proto/google/type/color_pb.ts | 408 +-
web/src/types/statistics.ts | 26 +-
web/src/types/view.d.ts | 10 +-
web/src/utils/attachment.ts | 108 +-
web/src/utils/auth-redirect.ts | 150 +-
web/src/utils/format.ts | 150 +-
web/src/utils/i18n.ts | 248 +-
web/src/utils/markdown-list-detection.ts | 134 +-
web/src/utils/memo.ts | 54 +-
web/src/utils/oauth.ts | 296 +-
.../remark-plugins/remark-disable-setext.ts | 28 +-
.../remark-plugins/remark-preserve-type.ts | 44 +-
web/src/utils/remark-plugins/remark-tag.ts | 224 +-
web/src/utils/theme.ts | 498 +-
web/src/utils/user.ts | 10 +-
web/src/utils/uuid.ts | 10 +-
web/tsconfig.json | 3 +-
web/vite.config.mts | 110 +-
852 files changed, 303670 insertions(+), 98297 deletions(-)
create mode 100644 memos_prod.db
create mode 100644 memos_prod.db-shm
create mode 100644 memos_prod.db-wal
create mode 100644 node_modules/.modules.yaml
create mode 100644 node_modules/.pnpm-workspace-state-v1.json
create mode 100644 node_modules/.pnpm/lock.yaml
create mode 120000 node_modules/.pnpm/node_modules/react
create mode 120000 node_modules/.pnpm/node_modules/react-dom
create mode 120000 node_modules/.pnpm/node_modules/scheduler
create mode 120000 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react
create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS
create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md
create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/LICENSE
create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/README.md
create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/package.json
create mode 120000 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-dom
create mode 120000 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/LICENSE
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/README.md
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-client.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-client.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-profiling.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-profiling.profiling.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.browser.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.browser.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.bun.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.bun.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.edge.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.edge.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.node.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.node.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-test-utils.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-test-utils.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.react-server.development.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.react-server.production.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/client.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/client.react-server.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/index.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/package.json
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/profiling.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/profiling.react-server.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/react-dom.react-server.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.browser.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.bun.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.edge.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.node.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.react-server.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.browser.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.edge.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.node.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.react-server.js
create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/test-utils.js
create mode 120000 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/scheduler
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/LICENSE
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/README.md
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-compiler-runtime.development.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-compiler-runtime.production.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-compiler-runtime.profiling.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.development.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.production.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.profiling.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.react-server.development.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.react-server.production.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.development.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.production.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.profiling.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.react-server.development.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.react-server.production.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.development.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.production.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.react-server.development.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.react-server.production.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/compiler-runtime.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/index.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-dev-runtime.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-dev-runtime.react-server.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-runtime.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-runtime.react-server.js
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/package.json
create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/react.react-server.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/LICENSE
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/README.md
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_mock.development.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_mock.production.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_post_task.development.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_post_task.production.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.development.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.native.development.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.native.production.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.production.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/index.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/index.native.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/package.json
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/unstable_mock.js
create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/unstable_post_task.js
create mode 120000 node_modules/react-colorful
create mode 100644 pnpm-lock.yaml
create mode 100644 web/src/components/MemoRelationForceGraph/MemoRelationForceGraph.tsx
create mode 100644 web/src/components/MemoRelationForceGraph/index.ts
create mode 100644 web/src/components/MemoRelationForceGraph/types.ts
create mode 100644 web/src/components/MemoRelationForceGraph/utils.ts
create mode 100644 web/src/components/MemoView/components/MemoCustomizeColor.tsx
create mode 100644 web/src/pages/SharedMemo.tsx
diff --git a/.dockerignore b/.dockerignore
index d465134d4..944184ae7 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,13 +1,13 @@
-web/node_modules
-web/dist
-.git
-.github
-build/
-tmp/
-memos
-*.md
-.gitignore
-.golangci.yaml
-.dockerignore
-docs/
+web/node_modules
+web/dist
+.git
+.github
+build/
+tmp/
+memos
+*.md
+.gitignore
+.golangci.yaml
+.dockerignore
+docs/
.DS_Store
\ No newline at end of file
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index f9af2381b..e4a2c915f 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1 +1 @@
-github: usememos
+github: usememos
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 75f0b5850..e034c8d1b 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,99 +1,99 @@
-name: Bug Report
-description: Something isn't working as expected
-type: Bug
-body:
- - type: markdown
- attributes:
- value: |
- Thanks for reporting a bug! Please fill out the form below so we can reproduce and fix the issue.
-
- **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues) to avoid duplicates.
-
- - type: checkboxes
- id: pre-check
- attributes:
- label: Pre-submission Checklist
- options:
- - label: I have searched existing issues and confirmed this bug has not been reported
- required: true
- - label: I can reproduce this bug on the latest version or the [demo site](https://demo.usememos.com)
- required: true
- - label: This is a bug, not a question (use [Discussions](https://github.com/usememos/memos/discussions) for questions)
- required: true
-
- - type: input
- id: version
- attributes:
- label: Memos Version
- description: Find this in **Settings > System > About** or via the `--version` flag
- placeholder: "v0.25.2"
- validations:
- required: true
-
- - type: dropdown
- id: deployment
- attributes:
- label: Deployment Method
- options:
- - Docker
- - Pre-built binary
- - Built from source
- validations:
- required: true
-
- - type: dropdown
- id: database
- attributes:
- label: Database
- options:
- - SQLite
- - PostgreSQL
- - MySQL
- validations:
- required: true
-
- - type: input
- id: browser-os
- attributes:
- label: Browser & OS
- description: e.g. Chrome 120 on macOS 15, Firefox 130 on Ubuntu 24.04
- placeholder: "Chrome 120 on macOS 15"
- validations:
- required: false
-
- - type: textarea
- id: bug-description
- attributes:
- label: Bug Description
- description: A clear and concise description of what the bug is
- placeholder: When I try to..., the application...
- validations:
- required: true
-
- - type: textarea
- id: reproduction-steps
- attributes:
- label: Steps to Reproduce
- description: Minimal steps to reliably reproduce the issue
- placeholder: |
- 1. Go to '...'
- 2. Click on '...'
- 3. See error
- validations:
- required: true
-
- - type: textarea
- id: expected-behavior
- attributes:
- label: Expected Behavior
- description: What did you expect to happen instead?
- placeholder: I expected...
- validations:
- required: true
-
- - type: textarea
- id: additional-context
- attributes:
- label: Screenshots, Logs & Additional Context
- description: Attach screenshots, browser console errors, or server logs if available
- placeholder: Drag and drop images here, or paste error logs...
+name: Bug Report
+description: Something isn't working as expected
+type: Bug
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for reporting a bug! Please fill out the form below so we can reproduce and fix the issue.
+
+ **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues) to avoid duplicates.
+
+ - type: checkboxes
+ id: pre-check
+ attributes:
+ label: Pre-submission Checklist
+ options:
+ - label: I have searched existing issues and confirmed this bug has not been reported
+ required: true
+ - label: I can reproduce this bug on the latest version or the [demo site](https://demo.usememos.com)
+ required: true
+ - label: This is a bug, not a question (use [Discussions](https://github.com/usememos/memos/discussions) for questions)
+ required: true
+
+ - type: input
+ id: version
+ attributes:
+ label: Memos Version
+ description: Find this in **Settings > System > About** or via the `--version` flag
+ placeholder: "v0.25.2"
+ validations:
+ required: true
+
+ - type: dropdown
+ id: deployment
+ attributes:
+ label: Deployment Method
+ options:
+ - Docker
+ - Pre-built binary
+ - Built from source
+ validations:
+ required: true
+
+ - type: dropdown
+ id: database
+ attributes:
+ label: Database
+ options:
+ - SQLite
+ - PostgreSQL
+ - MySQL
+ validations:
+ required: true
+
+ - type: input
+ id: browser-os
+ attributes:
+ label: Browser & OS
+ description: e.g. Chrome 120 on macOS 15, Firefox 130 on Ubuntu 24.04
+ placeholder: "Chrome 120 on macOS 15"
+ validations:
+ required: false
+
+ - type: textarea
+ id: bug-description
+ attributes:
+ label: Bug Description
+ description: A clear and concise description of what the bug is
+ placeholder: When I try to..., the application...
+ validations:
+ required: true
+
+ - type: textarea
+ id: reproduction-steps
+ attributes:
+ label: Steps to Reproduce
+ description: Minimal steps to reliably reproduce the issue
+ placeholder: |
+ 1. Go to '...'
+ 2. Click on '...'
+ 3. See error
+ validations:
+ required: true
+
+ - type: textarea
+ id: expected-behavior
+ attributes:
+ label: Expected Behavior
+ description: What did you expect to happen instead?
+ placeholder: I expected...
+ validations:
+ required: true
+
+ - type: textarea
+ id: additional-context
+ attributes:
+ label: Screenshots, Logs & Additional Context
+ description: Attach screenshots, browser console errors, or server logs if available
+ placeholder: Drag and drop images here, or paste error logs...
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 99c57ecd1..7b50bcfc4 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,8 +1,8 @@
-blank_issues_enabled: false
-contact_links:
- - name: Questions & Support
- url: https://github.com/usememos/memos/discussions
- about: Ask questions or get help in GitHub Discussions — please don't open issues for questions
- - name: Documentation
- url: https://www.usememos.com/docs
- about: Check the documentation before opening an issue
+blank_issues_enabled: false
+contact_links:
+ - name: Questions & Support
+ url: https://github.com/usememos/memos/discussions
+ about: Ask questions or get help in GitHub Discussions — please don't open issues for questions
+ - name: Documentation
+ url: https://www.usememos.com/docs
+ about: Check the documentation before opening an issue
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index ec1ff0cfe..9f113a370 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -1,78 +1,78 @@
-name: Feature Request
-description: Suggest a new feature or improvement
-type: Feature
-body:
- - type: markdown
- attributes:
- value: |
- Thanks for suggesting a feature! Please fill out the form below so we can understand your idea.
-
- **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues?q=label%3Aenhancement) to avoid duplicates.
-
- - type: checkboxes
- id: pre-check
- attributes:
- label: Pre-submission Checklist
- options:
- - label: I have searched existing issues and confirmed this feature has not been requested
- required: true
- - label: This is a feature request, not a bug report or question
- required: true
-
- - type: dropdown
- id: feature-type
- attributes:
- label: Feature Area
- options:
- - User Interface (UI)
- - User Experience (UX)
- - API / Backend
- - Integrations / Plugins
- - Security / Privacy
- - Performance
- - Other
- validations:
- required: true
-
- - type: textarea
- id: problem-statement
- attributes:
- label: Problem or Use Case
- description: What problem does this feature solve? Why do you need it?
- placeholder: |
- I often need to... but currently there's no way to...
- validations:
- required: true
-
- - type: textarea
- id: proposed-solution
- attributes:
- label: Proposed Solution
- description: Describe what you'd like to happen
- placeholder: |
- It would be great if Memos could...
- validations:
- required: true
-
- - type: textarea
- id: alternatives
- attributes:
- label: Alternatives Considered
- description: Have you considered any workarounds or alternative approaches?
- placeholder: |
- I've tried... but it doesn't work well because...
-
- - type: textarea
- id: additional-context
- attributes:
- label: Additional Context
- description: Mockups, screenshots, examples from other apps, or any other context
- placeholder: Drag and drop images here...
-
- - type: checkboxes
- id: contribution
- attributes:
- label: Contribution
- description: Would you be willing to help implement this feature?
- options:
- - label: I'm willing to submit a pull request for this feature
+name: Feature Request
+description: Suggest a new feature or improvement
+type: Feature
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for suggesting a feature! Please fill out the form below so we can understand your idea.
+
+ **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues?q=label%3Aenhancement) to avoid duplicates.
+
+ - type: checkboxes
+ id: pre-check
+ attributes:
+ label: Pre-submission Checklist
+ options:
+ - label: I have searched existing issues and confirmed this feature has not been requested
+ required: true
+ - label: This is a feature request, not a bug report or question
+ required: true
+
+ - type: dropdown
+ id: feature-type
+ attributes:
+ label: Feature Area
+ options:
+ - User Interface (UI)
+ - User Experience (UX)
+ - API / Backend
+ - Integrations / Plugins
+ - Security / Privacy
+ - Performance
+ - Other
+ validations:
+ required: true
+
+ - type: textarea
+ id: problem-statement
+ attributes:
+ label: Problem or Use Case
+ description: What problem does this feature solve? Why do you need it?
+ placeholder: |
+ I often need to... but currently there's no way to...
+ validations:
+ required: true
+
+ - type: textarea
+ id: proposed-solution
+ attributes:
+ label: Proposed Solution
+ description: Describe what you'd like to happen
+ placeholder: |
+ It would be great if Memos could...
+ validations:
+ required: true
+
+ - type: textarea
+ id: alternatives
+ attributes:
+ label: Alternatives Considered
+ description: Have you considered any workarounds or alternative approaches?
+ placeholder: |
+ I've tried... but it doesn't work well because...
+
+ - type: textarea
+ id: additional-context
+ attributes:
+ label: Additional Context
+ description: Mockups, screenshots, examples from other apps, or any other context
+ placeholder: Drag and drop images here...
+
+ - type: checkboxes
+ id: contribution
+ attributes:
+ label: Contribution
+ description: Would you be willing to help implement this feature?
+ options:
+ - label: I'm willing to submit a pull request for this feature
diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml
index dfdd5ac1f..7384f5d60 100644
--- a/.github/workflows/backend-tests.yml
+++ b/.github/workflows/backend-tests.yml
@@ -1,91 +1,91 @@
-name: Backend Tests
-
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
- paths:
- - "go.mod"
- - "go.sum"
- - "**.go"
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- GO_VERSION: "1.26.1"
-
-jobs:
- static-checks:
- name: Static Checks
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup Go
- uses: actions/setup-go@v6
- with:
- go-version: ${{ env.GO_VERSION }}
- cache: true
- cache-dependency-path: go.sum
-
- - name: Verify go.mod is tidy
- run: |
- go mod tidy -go=${{ env.GO_VERSION }}
- git diff --exit-code
-
- - name: Run golangci-lint
- uses: golangci/golangci-lint-action@v9
- with:
- version: v2.11.3
- args: --timeout=3m
-
- tests:
- name: Tests (${{ matrix.test-group }})
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- test-group: [store, server, plugin, other]
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup Go
- uses: actions/setup-go@v6
- with:
- go-version: ${{ env.GO_VERSION }}
- cache: true
- cache-dependency-path: go.sum
-
- - name: Run tests
- run: |
- case "${{ matrix.test-group }}" in
- store)
- # Run store tests for all drivers (sqlite, mysql, postgres)
- go test -v -coverprofile=coverage.out -covermode=atomic ./store/...
- ;;
- server)
- go test -v -race -coverprofile=coverage.out -covermode=atomic ./server/...
- ;;
- plugin)
- go test -v -race -coverprofile=coverage.out -covermode=atomic ./plugin/...
- ;;
- other)
- go test -v -race -coverprofile=coverage.out -covermode=atomic \
- ./cmd/... ./internal/... ./proto/...
- ;;
- esac
- env:
- DRIVER: ${{ matrix.test-group == 'store' && '' || 'sqlite' }}
-
- - name: Upload coverage
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- uses: codecov/codecov-action@v5
- with:
- files: ./coverage.out
- flags: ${{ matrix.test-group }}
- fail_ci_if_error: false
+name: Backend Tests
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ paths:
+ - "go.mod"
+ - "go.sum"
+ - "**.go"
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ GO_VERSION: "1.26.1"
+
+jobs:
+ static-checks:
+ name: Static Checks
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup Go
+ uses: actions/setup-go@v6
+ with:
+ go-version: ${{ env.GO_VERSION }}
+ cache: true
+ cache-dependency-path: go.sum
+
+ - name: Verify go.mod is tidy
+ run: |
+ go mod tidy -go=${{ env.GO_VERSION }}
+ git diff --exit-code
+
+ - name: Run golangci-lint
+ uses: golangci/golangci-lint-action@v9
+ with:
+ version: v2.11.3
+ args: --timeout=3m
+
+ tests:
+ name: Tests (${{ matrix.test-group }})
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ test-group: [store, server, plugin, other]
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup Go
+ uses: actions/setup-go@v6
+ with:
+ go-version: ${{ env.GO_VERSION }}
+ cache: true
+ cache-dependency-path: go.sum
+
+ - name: Run tests
+ run: |
+ case "${{ matrix.test-group }}" in
+ store)
+ # Run store tests for all drivers (sqlite, mysql, postgres)
+ go test -v -coverprofile=coverage.out -covermode=atomic ./store/...
+ ;;
+ server)
+ go test -v -race -coverprofile=coverage.out -covermode=atomic ./server/...
+ ;;
+ plugin)
+ go test -v -race -coverprofile=coverage.out -covermode=atomic ./plugin/...
+ ;;
+ other)
+ go test -v -race -coverprofile=coverage.out -covermode=atomic \
+ ./cmd/... ./internal/... ./proto/...
+ ;;
+ esac
+ env:
+ DRIVER: ${{ matrix.test-group == 'store' && '' || 'sqlite' }}
+
+ - name: Upload coverage
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
+ uses: codecov/codecov-action@v5
+ with:
+ files: ./coverage.out
+ flags: ${{ matrix.test-group }}
+ fail_ci_if_error: false
diff --git a/.github/workflows/build-canary-image.yml b/.github/workflows/build-canary-image.yml
index de8f5919a..eceaa8d32 100644
--- a/.github/workflows/build-canary-image.yml
+++ b/.github/workflows/build-canary-image.yml
@@ -1,166 +1,166 @@
-name: Build Canary Image
-
-on:
- push:
- branches: [main]
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.repository }}
- cancel-in-progress: true
-
-jobs:
- build-frontend:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v6
-
- - uses: pnpm/action-setup@v4.2.0
- with:
- version: 10
- - uses: actions/setup-node@v6
- with:
- node-version: "24"
- cache: pnpm
- cache-dependency-path: "web/pnpm-lock.yaml"
- - name: Get pnpm store directory
- id: pnpm-cache
- shell: bash
- run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- - name: Setup pnpm cache
- uses: actions/cache@v5
- with:
- path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
- key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
- restore-keys: ${{ runner.os }}-pnpm-store-
- - run: pnpm install --frozen-lockfile
- working-directory: web
- - name: Run frontend build
- run: pnpm release
- working-directory: web
-
- - name: Upload frontend artifacts
- uses: actions/upload-artifact@v6
- with:
- name: frontend-dist
- path: server/router/frontend/dist
- retention-days: 1
-
- build-push:
- needs: build-frontend
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- strategy:
- fail-fast: false
- matrix:
- platform:
- - linux/amd64
- - linux/arm64
- steps:
- - uses: actions/checkout@v6
-
- - name: Download frontend artifacts
- uses: actions/download-artifact@v7
- with:
- name: frontend-dist
- path: server/router/frontend/dist
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_HUB_USERNAME }}
- password: ${{ secrets.DOCKER_HUB_TOKEN }}
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ github.token }}
-
- - name: Build and push by digest
- id: build
- uses: docker/build-push-action@v6
- with:
- context: .
- file: ./scripts/Dockerfile
- platforms: ${{ matrix.platform }}
- cache-from: type=gha,scope=build-${{ matrix.platform }}
- cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
- outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
-
- - name: Export digest
- run: |
- mkdir -p /tmp/digests
- digest="${{ steps.build.outputs.digest }}"
- touch "/tmp/digests/${digest#sha256:}"
-
- - name: Upload digest
- uses: actions/upload-artifact@v6
- with:
- name: digests-${{ strategy.job-index }}
- path: /tmp/digests/*
- if-no-files-found: error
- retention-days: 1
-
- merge:
- needs: build-push
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- steps:
- - name: Download digests
- uses: actions/download-artifact@v7
- with:
- pattern: digests-*
- merge-multiple: true
- path: /tmp/digests
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: |
- neosmemo/memos
- ghcr.io/usememos/memos
- flavor: |
- latest=false
- tags: |
- type=raw,value=canary
-
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_HUB_USERNAME }}
- password: ${{ secrets.DOCKER_HUB_TOKEN }}
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ github.token }}
-
- - name: Create manifest list and push
- working-directory: /tmp/digests
- run: |
- docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
- $(printf 'neosmemo/memos@sha256:%s ' *)
- env:
- DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
-
- - name: Inspect images
- run: |
- docker buildx imagetools inspect neosmemo/memos:canary
- docker buildx imagetools inspect ghcr.io/usememos/memos:canary
+name: Build Canary Image
+
+on:
+ push:
+ branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
+
+jobs:
+ build-frontend:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+
+ - uses: pnpm/action-setup@v4.2.0
+ with:
+ version: 10
+ - uses: actions/setup-node@v6
+ with:
+ node-version: "24"
+ cache: pnpm
+ cache-dependency-path: "web/pnpm-lock.yaml"
+ - name: Get pnpm store directory
+ id: pnpm-cache
+ shell: bash
+ run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
+ - name: Setup pnpm cache
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
+ restore-keys: ${{ runner.os }}-pnpm-store-
+ - run: pnpm install --frozen-lockfile
+ working-directory: web
+ - name: Run frontend build
+ run: pnpm release
+ working-directory: web
+
+ - name: Upload frontend artifacts
+ uses: actions/upload-artifact@v6
+ with:
+ name: frontend-dist
+ path: server/router/frontend/dist
+ retention-days: 1
+
+ build-push:
+ needs: build-frontend
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ strategy:
+ fail-fast: false
+ matrix:
+ platform:
+ - linux/amd64
+ - linux/arm64
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Download frontend artifacts
+ uses: actions/download-artifact@v7
+ with:
+ name: frontend-dist
+ path: server/router/frontend/dist
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
+ password: ${{ secrets.DOCKER_HUB_TOKEN }}
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+
+ - name: Build and push by digest
+ id: build
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: ./scripts/Dockerfile
+ platforms: ${{ matrix.platform }}
+ cache-from: type=gha,scope=build-${{ matrix.platform }}
+ cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
+ outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
+
+ - name: Export digest
+ run: |
+ mkdir -p /tmp/digests
+ digest="${{ steps.build.outputs.digest }}"
+ touch "/tmp/digests/${digest#sha256:}"
+
+ - name: Upload digest
+ uses: actions/upload-artifact@v6
+ with:
+ name: digests-${{ strategy.job-index }}
+ path: /tmp/digests/*
+ if-no-files-found: error
+ retention-days: 1
+
+ merge:
+ needs: build-push
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - name: Download digests
+ uses: actions/download-artifact@v7
+ with:
+ pattern: digests-*
+ merge-multiple: true
+ path: /tmp/digests
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: |
+ neosmemo/memos
+ ghcr.io/usememos/memos
+ flavor: |
+ latest=false
+ tags: |
+ type=raw,value=canary
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
+ password: ${{ secrets.DOCKER_HUB_TOKEN }}
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+
+ - name: Create manifest list and push
+ working-directory: /tmp/digests
+ run: |
+ docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
+ $(printf 'neosmemo/memos@sha256:%s ' *)
+ env:
+ DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
+
+ - name: Inspect images
+ run: |
+ docker buildx imagetools inspect neosmemo/memos:canary
+ docker buildx imagetools inspect ghcr.io/usememos/memos:canary
diff --git a/.github/workflows/demo-deploy.yml b/.github/workflows/demo-deploy.yml
index 4ff6a3742..fba639683 100644
--- a/.github/workflows/demo-deploy.yml
+++ b/.github/workflows/demo-deploy.yml
@@ -1,17 +1,17 @@
-name: Demo Deploy
-
-on:
- workflow_dispatch:
-
-jobs:
- deploy-demo:
- runs-on: ubuntu-latest
- steps:
- - name: Trigger Render Deploy
- run: |
- curl -X POST "${{ secrets.RENDER_DEPLOY_HOOK }}" \
- -H "Content-Type: application/json" \
- -d '{"trigger": "github_action"}'
-
- - name: Deployment Status
- run: echo "Demo deployment triggered successfully on Render"
+name: Demo Deploy
+
+on:
+ workflow_dispatch:
+
+jobs:
+ deploy-demo:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Trigger Render Deploy
+ run: |
+ curl -X POST "${{ secrets.RENDER_DEPLOY_HOOK }}" \
+ -H "Content-Type: application/json" \
+ -d '{"trigger": "github_action"}'
+
+ - name: Deployment Status
+ run: echo "Demo deployment triggered successfully on Render"
diff --git a/.github/workflows/frontend-tests.yml b/.github/workflows/frontend-tests.yml
index d1fe8a613..3b294e750 100644
--- a/.github/workflows/frontend-tests.yml
+++ b/.github/workflows/frontend-tests.yml
@@ -1,72 +1,72 @@
-name: Frontend Tests
-
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
- paths:
- - "web/**"
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- NODE_VERSION: "24"
- PNPM_VERSION: "10"
-
-jobs:
- lint:
- name: Lint
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup pnpm
- uses: pnpm/action-setup@v4.2.0
- with:
- version: ${{ env.PNPM_VERSION }}
-
- - name: Setup Node.js
- uses: actions/setup-node@v6
- with:
- node-version: ${{ env.NODE_VERSION }}
- cache: pnpm
- cache-dependency-path: web/pnpm-lock.yaml
-
- - name: Install dependencies
- working-directory: web
- run: pnpm install --frozen-lockfile
-
- - name: Run lint
- working-directory: web
- run: pnpm lint
-
- build:
- name: Build
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup pnpm
- uses: pnpm/action-setup@v4.2.0
- with:
- version: ${{ env.PNPM_VERSION }}
-
- - name: Setup Node.js
- uses: actions/setup-node@v6
- with:
- node-version: ${{ env.NODE_VERSION }}
- cache: pnpm
- cache-dependency-path: web/pnpm-lock.yaml
-
- - name: Install dependencies
- working-directory: web
- run: pnpm install --frozen-lockfile
-
- - name: Build frontend
- working-directory: web
- run: pnpm build
+name: Frontend Tests
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ paths:
+ - "web/**"
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ NODE_VERSION: "24"
+ PNPM_VERSION: "10"
+
+jobs:
+ lint:
+ name: Lint
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.2.0
+ with:
+ version: ${{ env.PNPM_VERSION }}
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: pnpm
+ cache-dependency-path: web/pnpm-lock.yaml
+
+ - name: Install dependencies
+ working-directory: web
+ run: pnpm install --frozen-lockfile
+
+ - name: Run lint
+ working-directory: web
+ run: pnpm lint
+
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.2.0
+ with:
+ version: ${{ env.PNPM_VERSION }}
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: pnpm
+ cache-dependency-path: web/pnpm-lock.yaml
+
+ - name: Install dependencies
+ working-directory: web
+ run: pnpm install --frozen-lockfile
+
+ - name: Build frontend
+ working-directory: web
+ run: pnpm build
diff --git a/.github/workflows/proto-linter.yml b/.github/workflows/proto-linter.yml
index a6422349c..bbc9b3dce 100644
--- a/.github/workflows/proto-linter.yml
+++ b/.github/workflows/proto-linter.yml
@@ -1,40 +1,40 @@
-name: Proto Linter
-
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
- paths:
- - "proto/**"
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- lint:
- name: Lint Protos
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
- with:
- fetch-depth: 0
-
- - name: Setup buf
- uses: bufbuild/buf-setup-action@v1
- with:
- github_token: ${{ github.token }}
-
- - name: Run buf lint
- uses: bufbuild/buf-lint-action@v1
- with:
- input: proto
-
- - name: Check buf format
- run: |
- if [[ $(buf format -d) ]]; then
- echo "❌ Proto files are not formatted. Run 'buf format -w' to fix."
- exit 1
- fi
+name: Proto Linter
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ paths:
+ - "proto/**"
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ lint:
+ name: Lint Protos
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Setup buf
+ uses: bufbuild/buf-setup-action@v1
+ with:
+ github_token: ${{ github.token }}
+
+ - name: Run buf lint
+ uses: bufbuild/buf-lint-action@v1
+ with:
+ input: proto
+
+ - name: Check buf format
+ run: |
+ if [[ $(buf format -d) ]]; then
+ echo "❌ Proto files are not formatted. Run 'buf format -w' to fix."
+ exit 1
+ fi
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7e946a7b9..3b5ec0853 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,352 +1,352 @@
-name: Release
-
-on:
- push:
- tags:
- - "v*.*.*"
- workflow_dispatch:
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- GO_VERSION: "1.26.1"
- NODE_VERSION: "24"
- PNPM_VERSION: "10"
- ARTIFACT_RETENTION_DAYS: 60
- ARTIFACT_PREFIX: memos
-
-jobs:
- prepare:
- name: Extract Version
- runs-on: ubuntu-latest
- outputs:
- version: ${{ steps.version.outputs.version }}
- tag: ${{ steps.version.outputs.tag }}
- steps:
- - name: Extract version
- id: version
- env:
- REF_NAME: ${{ github.ref_name }}
- EVENT_NAME: ${{ github.event_name }}
- run: |
- if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
- echo "tag=" >> "$GITHUB_OUTPUT"
- echo "version=manual-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
- exit 0
- fi
-
- echo "tag=${REF_NAME}" >> "$GITHUB_OUTPUT"
- echo "version=${REF_NAME#v}" >> "$GITHUB_OUTPUT"
-
- build-frontend:
- name: Build Frontend
- needs: prepare
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup pnpm
- uses: pnpm/action-setup@v4.2.0
- with:
- version: ${{ env.PNPM_VERSION }}
-
- - name: Setup Node.js
- uses: actions/setup-node@v6
- with:
- node-version: ${{ env.NODE_VERSION }}
- cache: pnpm
- cache-dependency-path: web/pnpm-lock.yaml
-
- - name: Get pnpm store directory
- id: pnpm-cache
- shell: bash
- run: echo "STORE_PATH=$(pnpm store path)" >> "$GITHUB_OUTPUT"
-
- - name: Setup pnpm cache
- uses: actions/cache@v4
- with:
- path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
- key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
- restore-keys: ${{ runner.os }}-pnpm-store-
-
- - name: Install dependencies
- working-directory: web
- run: pnpm install --frozen-lockfile
-
- - name: Build frontend release assets
- working-directory: web
- run: pnpm release
-
- - name: Upload frontend artifacts
- uses: actions/upload-artifact@v4
- with:
- name: frontend-dist
- path: server/router/frontend/dist
- retention-days: 1
-
- build-binaries:
- name: Build ${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('v{0}', matrix.goarm) || '' }}
- needs: [prepare, build-frontend]
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- include:
- - goos: linux
- goarch: amd64
- - goos: linux
- goarch: arm64
- - goos: linux
- goarch: arm
- goarm: "7"
- - goos: darwin
- goarch: amd64
- - goos: darwin
- goarch: arm64
- - goos: windows
- goarch: amd64
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup Go
- uses: actions/setup-go@v6
- with:
- go-version: ${{ env.GO_VERSION }}
- cache: true
-
- - name: Download frontend artifacts
- uses: actions/download-artifact@v4
- with:
- name: frontend-dist
- path: server/router/frontend/dist
-
- - name: Build binary
- env:
- GOOS: ${{ matrix.goos }}
- GOARCH: ${{ matrix.goarch }}
- GOARM: ${{ matrix.goarm }}
- CGO_ENABLED: "0"
- run: |
- output_name="memos"
- if [ "$GOOS" = "windows" ]; then
- output_name="memos.exe"
- fi
-
- mkdir -p build
-
- go build \
- -trimpath \
- -ldflags="-s -w -X github.com/usememos/memos/internal/version.Version=${{ needs.prepare.outputs.version }} -extldflags '-static'" \
- -tags netgo,osusergo \
- -o "build/${output_name}" \
- ./cmd/memos
-
- - name: Package binary
- env:
- VERSION: ${{ needs.prepare.outputs.version }}
- GOOS: ${{ matrix.goos }}
- GOARCH: ${{ matrix.goarch }}
- GOARM: ${{ matrix.goarm }}
- run: |
- cd build
-
- package_name="${ARTIFACT_PREFIX}_${VERSION}_${GOOS}_${GOARCH}"
- if [ -n "$GOARM" ]; then
- package_name="${package_name}v${GOARM}"
- fi
-
- if [ "$GOOS" = "windows" ]; then
- artifact_name="${package_name}.zip"
- zip -q "${artifact_name}" memos.exe
- else
- artifact_name="${package_name}.tar.gz"
- tar czf "${artifact_name}" memos
- fi
-
- echo "artifact_name=${artifact_name}" >> "$GITHUB_ENV"
-
- - name: Upload binary artifact
- uses: actions/upload-artifact@v4
- with:
- name: ${{ env.artifact_name }}
- path: build/${{ env.artifact_name }}
- retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
-
- checksums:
- name: Generate Checksums
- needs: [prepare, build-binaries]
- runs-on: ubuntu-latest
- steps:
- - name: Download binary artifacts
- uses: actions/download-artifact@v4
- with:
- path: artifacts
- pattern: ${{ env.ARTIFACT_PREFIX }}_*
- merge-multiple: true
-
- - name: Generate checksums
- working-directory: artifacts
- run: sha256sum * > checksums.txt
-
- - name: Upload checksum artifact
- uses: actions/upload-artifact@v4
- with:
- name: checksums
- path: artifacts/checksums.txt
- retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
-
- release:
- name: Publish GitHub Release
- needs: [prepare, build-binaries, checksums]
- if: github.event_name != 'workflow_dispatch'
- runs-on: ubuntu-latest
- permissions:
- contents: write
- steps:
- - name: Download binary artifacts
- uses: actions/download-artifact@v4
- with:
- path: artifacts
- pattern: ${{ env.ARTIFACT_PREFIX }}_*
- merge-multiple: true
-
- - name: Download checksum artifact
- uses: actions/download-artifact@v4
- with:
- name: checksums
- path: artifacts
-
- - name: Publish release assets
- uses: softprops/action-gh-release@v2
- with:
- tag_name: ${{ needs.prepare.outputs.tag }}
- name: ${{ needs.prepare.outputs.tag }}
- generate_release_notes: true
- files: artifacts/*
-
- build-push:
- name: Build Image ${{ matrix.platform }}
- needs: [prepare, build-frontend]
- if: github.event_name != 'workflow_dispatch'
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- strategy:
- fail-fast: false
- matrix:
- platform:
- - linux/amd64
- - linux/arm/v7
- - linux/arm64
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Download frontend artifacts
- uses: actions/download-artifact@v4
- with:
- name: frontend-dist
- path: server/router/frontend/dist
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_HUB_USERNAME }}
- password: ${{ secrets.DOCKER_HUB_TOKEN }}
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ github.token }}
-
- - name: Build and push by digest
- id: build
- uses: docker/build-push-action@v6
- with:
- context: .
- file: ./scripts/Dockerfile
- platforms: ${{ matrix.platform }}
- build-args: |
- VERSION=${{ needs.prepare.outputs.version }}
- COMMIT=${{ github.sha }}
- cache-from: type=gha,scope=release-${{ matrix.platform }}
- cache-to: type=gha,mode=max,scope=release-${{ matrix.platform }}
- outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
-
- - name: Export digest
- run: |
- mkdir -p /tmp/digests
- digest="${{ steps.build.outputs.digest }}"
- touch "/tmp/digests/${digest#sha256:}"
-
- - name: Upload digest
- uses: actions/upload-artifact@v4
- with:
- name: digests-${{ strategy.job-index }}
- path: /tmp/digests/*
- if-no-files-found: error
- retention-days: 1
-
- merge-images:
- name: Publish Stable Image Tags
- needs: [prepare, build-push]
- if: github.event_name != 'workflow_dispatch'
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- steps:
- - name: Download digests
- uses: actions/download-artifact@v4
- with:
- pattern: digests-*
- merge-multiple: true
- path: /tmp/digests
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_HUB_USERNAME }}
- password: ${{ secrets.DOCKER_HUB_TOKEN }}
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ github.token }}
-
- - name: Create manifest list and push
- working-directory: /tmp/digests
- run: |
- version="${{ needs.prepare.outputs.version }}"
- major_minor=$(echo "$version" | cut -d. -f1,2)
- docker buildx imagetools create \
- -t "neosmemo/memos:${version}" \
- -t "neosmemo/memos:${major_minor}" \
- -t "neosmemo/memos:stable" \
- -t "ghcr.io/usememos/memos:${version}" \
- -t "ghcr.io/usememos/memos:${major_minor}" \
- -t "ghcr.io/usememos/memos:stable" \
- $(printf 'neosmemo/memos@sha256:%s ' *)
-
- - name: Inspect images
- run: |
- docker buildx imagetools inspect neosmemo/memos:${{ needs.prepare.outputs.version }}
- docker buildx imagetools inspect neosmemo/memos:stable
+name: Release
+
+on:
+ push:
+ tags:
+ - "v*.*.*"
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ GO_VERSION: "1.26.1"
+ NODE_VERSION: "24"
+ PNPM_VERSION: "10"
+ ARTIFACT_RETENTION_DAYS: 60
+ ARTIFACT_PREFIX: memos
+
+jobs:
+ prepare:
+ name: Extract Version
+ runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.version.outputs.version }}
+ tag: ${{ steps.version.outputs.tag }}
+ steps:
+ - name: Extract version
+ id: version
+ env:
+ REF_NAME: ${{ github.ref_name }}
+ EVENT_NAME: ${{ github.event_name }}
+ run: |
+ if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
+ echo "tag=" >> "$GITHUB_OUTPUT"
+ echo "version=manual-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
+ exit 0
+ fi
+
+ echo "tag=${REF_NAME}" >> "$GITHUB_OUTPUT"
+ echo "version=${REF_NAME#v}" >> "$GITHUB_OUTPUT"
+
+ build-frontend:
+ name: Build Frontend
+ needs: prepare
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.2.0
+ with:
+ version: ${{ env.PNPM_VERSION }}
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: pnpm
+ cache-dependency-path: web/pnpm-lock.yaml
+
+ - name: Get pnpm store directory
+ id: pnpm-cache
+ shell: bash
+ run: echo "STORE_PATH=$(pnpm store path)" >> "$GITHUB_OUTPUT"
+
+ - name: Setup pnpm cache
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
+ restore-keys: ${{ runner.os }}-pnpm-store-
+
+ - name: Install dependencies
+ working-directory: web
+ run: pnpm install --frozen-lockfile
+
+ - name: Build frontend release assets
+ working-directory: web
+ run: pnpm release
+
+ - name: Upload frontend artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: frontend-dist
+ path: server/router/frontend/dist
+ retention-days: 1
+
+ build-binaries:
+ name: Build ${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('v{0}', matrix.goarm) || '' }}
+ needs: [prepare, build-frontend]
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - goos: linux
+ goarch: amd64
+ - goos: linux
+ goarch: arm64
+ - goos: linux
+ goarch: arm
+ goarm: "7"
+ - goos: darwin
+ goarch: amd64
+ - goos: darwin
+ goarch: arm64
+ - goos: windows
+ goarch: amd64
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup Go
+ uses: actions/setup-go@v6
+ with:
+ go-version: ${{ env.GO_VERSION }}
+ cache: true
+
+ - name: Download frontend artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: frontend-dist
+ path: server/router/frontend/dist
+
+ - name: Build binary
+ env:
+ GOOS: ${{ matrix.goos }}
+ GOARCH: ${{ matrix.goarch }}
+ GOARM: ${{ matrix.goarm }}
+ CGO_ENABLED: "0"
+ run: |
+ output_name="memos"
+ if [ "$GOOS" = "windows" ]; then
+ output_name="memos.exe"
+ fi
+
+ mkdir -p build
+
+ go build \
+ -trimpath \
+ -ldflags="-s -w -X github.com/usememos/memos/internal/version.Version=${{ needs.prepare.outputs.version }} -extldflags '-static'" \
+ -tags netgo,osusergo \
+ -o "build/${output_name}" \
+ ./cmd/memos
+
+ - name: Package binary
+ env:
+ VERSION: ${{ needs.prepare.outputs.version }}
+ GOOS: ${{ matrix.goos }}
+ GOARCH: ${{ matrix.goarch }}
+ GOARM: ${{ matrix.goarm }}
+ run: |
+ cd build
+
+ package_name="${ARTIFACT_PREFIX}_${VERSION}_${GOOS}_${GOARCH}"
+ if [ -n "$GOARM" ]; then
+ package_name="${package_name}v${GOARM}"
+ fi
+
+ if [ "$GOOS" = "windows" ]; then
+ artifact_name="${package_name}.zip"
+ zip -q "${artifact_name}" memos.exe
+ else
+ artifact_name="${package_name}.tar.gz"
+ tar czf "${artifact_name}" memos
+ fi
+
+ echo "artifact_name=${artifact_name}" >> "$GITHUB_ENV"
+
+ - name: Upload binary artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.artifact_name }}
+ path: build/${{ env.artifact_name }}
+ retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+ checksums:
+ name: Generate Checksums
+ needs: [prepare, build-binaries]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download binary artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: artifacts
+ pattern: ${{ env.ARTIFACT_PREFIX }}_*
+ merge-multiple: true
+
+ - name: Generate checksums
+ working-directory: artifacts
+ run: sha256sum * > checksums.txt
+
+ - name: Upload checksum artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: checksums
+ path: artifacts/checksums.txt
+ retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
+
+ release:
+ name: Publish GitHub Release
+ needs: [prepare, build-binaries, checksums]
+ if: github.event_name != 'workflow_dispatch'
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Download binary artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: artifacts
+ pattern: ${{ env.ARTIFACT_PREFIX }}_*
+ merge-multiple: true
+
+ - name: Download checksum artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: checksums
+ path: artifacts
+
+ - name: Publish release assets
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ needs.prepare.outputs.tag }}
+ name: ${{ needs.prepare.outputs.tag }}
+ generate_release_notes: true
+ files: artifacts/*
+
+ build-push:
+ name: Build Image ${{ matrix.platform }}
+ needs: [prepare, build-frontend]
+ if: github.event_name != 'workflow_dispatch'
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ strategy:
+ fail-fast: false
+ matrix:
+ platform:
+ - linux/amd64
+ - linux/arm/v7
+ - linux/arm64
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Download frontend artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: frontend-dist
+ path: server/router/frontend/dist
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
+ password: ${{ secrets.DOCKER_HUB_TOKEN }}
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+
+ - name: Build and push by digest
+ id: build
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: ./scripts/Dockerfile
+ platforms: ${{ matrix.platform }}
+ build-args: |
+ VERSION=${{ needs.prepare.outputs.version }}
+ COMMIT=${{ github.sha }}
+ cache-from: type=gha,scope=release-${{ matrix.platform }}
+ cache-to: type=gha,mode=max,scope=release-${{ matrix.platform }}
+ outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
+
+ - name: Export digest
+ run: |
+ mkdir -p /tmp/digests
+ digest="${{ steps.build.outputs.digest }}"
+ touch "/tmp/digests/${digest#sha256:}"
+
+ - name: Upload digest
+ uses: actions/upload-artifact@v4
+ with:
+ name: digests-${{ strategy.job-index }}
+ path: /tmp/digests/*
+ if-no-files-found: error
+ retention-days: 1
+
+ merge-images:
+ name: Publish Stable Image Tags
+ needs: [prepare, build-push]
+ if: github.event_name != 'workflow_dispatch'
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - name: Download digests
+ uses: actions/download-artifact@v4
+ with:
+ pattern: digests-*
+ merge-multiple: true
+ path: /tmp/digests
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
+ password: ${{ secrets.DOCKER_HUB_TOKEN }}
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+
+ - name: Create manifest list and push
+ working-directory: /tmp/digests
+ run: |
+ version="${{ needs.prepare.outputs.version }}"
+ major_minor=$(echo "$version" | cut -d. -f1,2)
+ docker buildx imagetools create \
+ -t "neosmemo/memos:${version}" \
+ -t "neosmemo/memos:${major_minor}" \
+ -t "neosmemo/memos:stable" \
+ -t "ghcr.io/usememos/memos:${version}" \
+ -t "ghcr.io/usememos/memos:${major_minor}" \
+ -t "ghcr.io/usememos/memos:stable" \
+ $(printf 'neosmemo/memos@sha256:%s ' *)
+
+ - name: Inspect images
+ run: |
+ docker buildx imagetools inspect neosmemo/memos:${{ needs.prepare.outputs.version }}
+ docker buildx imagetools inspect neosmemo/memos:stable
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 18991fec3..ca75e318e 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -1,24 +1,24 @@
-name: Close Stale
-
-on:
- schedule:
- - cron: "0 */8 * * *" # Every 8 hours
-
-jobs:
- close-stale:
- name: Close Stale Issues and PRs
- runs-on: ubuntu-latest
- permissions:
- issues: write
- pull-requests: write
- steps:
- - name: Mark and close stale issues and PRs
- uses: actions/stale@v10.1.1
- with:
- # Issues: mark stale after 14 days of inactivity, close after 3 more days
- days-before-issue-stale: 14
- days-before-issue-close: 3
-
- # Pull requests: mark stale after 14 days of inactivity, close after 3 more days
- days-before-pr-stale: 14
- days-before-pr-close: 3
+name: Close Stale
+
+on:
+ schedule:
+ - cron: "0 */8 * * *" # Every 8 hours
+
+jobs:
+ close-stale:
+ name: Close Stale Issues and PRs
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ steps:
+ - name: Mark and close stale issues and PRs
+ uses: actions/stale@v10.1.1
+ with:
+ # Issues: mark stale after 14 days of inactivity, close after 3 more days
+ days-before-issue-stale: 14
+ days-before-issue-close: 3
+
+ # Pull requests: mark stale after 14 days of inactivity, close after 3 more days
+ days-before-pr-stale: 14
+ days-before-pr-close: 3
diff --git a/.gitignore b/.gitignore
index abd9d94fc..f6b5a2396 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,29 +1,29 @@
-# temp folder
-tmp
-
-# Frontend asset
-web/dist
-
-# Build artifacts
-build/
-bin/
-memos
-
-# Plan/design documents
-docs/plans/
-
-.DS_Store
-
-# Jetbrains
-.idea
-
-# Docker Compose Environment File
-.env
-
-dist
-
-# VSCode settings
-.vscode
-
-# Git worktrees
-.worktrees/
+# temp folder
+tmp
+
+# Frontend asset
+web/dist
+
+# Build artifacts
+build/
+bin/
+memos
+
+# Plan/design documents
+docs/plans/
+
+.DS_Store
+
+# Jetbrains
+.idea
+
+# Docker Compose Environment File
+.env
+
+dist
+
+# VSCode settings
+.vscode
+
+# Git worktrees
+.worktrees/
diff --git a/.golangci.yaml b/.golangci.yaml
index b97938f08..3c4f6f9f6 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -1,101 +1,101 @@
-version: "2"
-
-linters:
- enable:
- - revive
- - govet
- - staticcheck
- - misspell
- - gocritic
- - sqlclosecheck
- - rowserrcheck
- - nilerr
- - godot
- - forbidigo
- - mirror
- - bodyclose
- disable:
- - errcheck
- settings:
- exhaustive:
- explicit-exhaustive-switch: false
- staticcheck:
- checks:
- - all
- - -ST1000
- - -ST1003
- - -ST1021
- - -QF1003
- revive:
- # Default to run all linters so that new rules in the future could automatically be added to the static check.
- enable-all-rules: true
- rules:
- # The following rules are too strict and make coding harder. We do not enable them for now.
- - name: file-header
- disabled: true
- - name: line-length-limit
- disabled: true
- - name: function-length
- disabled: true
- - name: max-public-structs
- disabled: true
- - name: function-result-limit
- disabled: true
- - name: banned-characters
- disabled: true
- - name: argument-limit
- disabled: true
- - name: cognitive-complexity
- disabled: true
- - name: cyclomatic
- disabled: true
- - name: confusing-results
- disabled: true
- - name: add-constant
- disabled: true
- - name: flag-parameter
- disabled: true
- - name: nested-structs
- disabled: true
- - name: import-shadowing
- disabled: true
- - name: early-return
- disabled: true
- - name: use-any
- disabled: true
- - name: exported
- disabled: true
- - name: unhandled-error
- disabled: true
- - name: if-return
- disabled: true
- - name: max-control-nesting
- disabled: true
- - name: redefines-builtin-id
- disabled: true
- - name: package-comments
- disabled: true
- gocritic:
- disabled-checks:
- - ifElseChain
- govet:
- settings:
- printf: # The name of the analyzer, run `go tool vet help` to see the list of all analyzers
- funcs: # Run `go tool vet help printf` to see the full configuration of `printf`.
- - common.Errorf
- enable-all: true
- disable:
- - fieldalignment
- - shadow
- forbidigo:
- forbid:
- - pattern: 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?'
- - pattern: 'ioutil\.ReadDir(# Please use os\.ReadDir)?'
-
-formatters:
- enable:
- - goimports
- settings:
- goimports:
- local-prefixes:
- - github.com/usememos/memos
+version: "2"
+
+linters:
+ enable:
+ - revive
+ - govet
+ - staticcheck
+ - misspell
+ - gocritic
+ - sqlclosecheck
+ - rowserrcheck
+ - nilerr
+ - godot
+ - forbidigo
+ - mirror
+ - bodyclose
+ disable:
+ - errcheck
+ settings:
+ exhaustive:
+ explicit-exhaustive-switch: false
+ staticcheck:
+ checks:
+ - all
+ - -ST1000
+ - -ST1003
+ - -ST1021
+ - -QF1003
+ revive:
+ # Default to run all linters so that new rules in the future could automatically be added to the static check.
+ enable-all-rules: true
+ rules:
+ # The following rules are too strict and make coding harder. We do not enable them for now.
+ - name: file-header
+ disabled: true
+ - name: line-length-limit
+ disabled: true
+ - name: function-length
+ disabled: true
+ - name: max-public-structs
+ disabled: true
+ - name: function-result-limit
+ disabled: true
+ - name: banned-characters
+ disabled: true
+ - name: argument-limit
+ disabled: true
+ - name: cognitive-complexity
+ disabled: true
+ - name: cyclomatic
+ disabled: true
+ - name: confusing-results
+ disabled: true
+ - name: add-constant
+ disabled: true
+ - name: flag-parameter
+ disabled: true
+ - name: nested-structs
+ disabled: true
+ - name: import-shadowing
+ disabled: true
+ - name: early-return
+ disabled: true
+ - name: use-any
+ disabled: true
+ - name: exported
+ disabled: true
+ - name: unhandled-error
+ disabled: true
+ - name: if-return
+ disabled: true
+ - name: max-control-nesting
+ disabled: true
+ - name: redefines-builtin-id
+ disabled: true
+ - name: package-comments
+ disabled: true
+ gocritic:
+ disabled-checks:
+ - ifElseChain
+ govet:
+ settings:
+ printf: # The name of the analyzer, run `go tool vet help` to see the list of all analyzers
+ funcs: # Run `go tool vet help printf` to see the full configuration of `printf`.
+ - common.Errorf
+ enable-all: true
+ disable:
+ - fieldalignment
+ - shadow
+ forbidigo:
+ forbid:
+ - pattern: 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?'
+ - pattern: 'ioutil\.ReadDir(# Please use os\.ReadDir)?'
+
+formatters:
+ enable:
+ - goimports
+ settings:
+ goimports:
+ local-prefixes:
+ - github.com/usememos/memos
diff --git a/AGENTS.md b/AGENTS.md
index 892553282..332f27b2e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,102 +1,102 @@
-# AGENTS.md
-
-This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
-
-Self-hosted note-taking tool. Go 1.26 backend (Echo v5, Connect RPC + gRPC-Gateway), React 18 + TypeScript 5.9 + Vite 7 frontend, Protocol Buffers API, SQLite/MySQL/PostgreSQL.
-
-## Commands
-
-```bash
-# Backend
-go run ./cmd/memos --port 8081 # Start dev server
-go test ./... # Run all tests
-go test -v ./store/... # Run store tests (all 3 DB drivers via TestContainers)
-go test -v -race ./server/... # Run server tests with race detection
-go test -v -run TestFoo ./pkg/... # Run a single test
-golangci-lint run # Lint (v2, config: .golangci.yaml)
-golangci-lint run --fix # Auto-fix lint issues (includes goimports)
-
-# Frontend (cd web)
-pnpm install # Install deps
-pnpm dev # Dev server (:3001, proxies API to :8081)
-pnpm lint # Type check + Biome lint
-pnpm lint:fix # Auto-fix lint issues
-pnpm format # Format code
-pnpm build # Production build
-pnpm release # Build to server/router/frontend/dist
-
-# Protocol Buffers (cd proto)
-buf generate # Regenerate Go + TypeScript + OpenAPI
-buf lint # Lint proto files
-buf format -w # Format proto files
-```
-
-## Architecture
-
-```
-cmd/memos/main.go # Cobra CLI + Viper config, server init
-
-server/
-├── server.go # Echo v5 HTTP server, background runners
-├── auth/ # JWT access (15min) + refresh (30d) tokens, PAT
-├── router/
-│ ├── api/v1/ # 8 gRPC services (Connect + Gateway)
-│ │ ├── acl_config.go # Public endpoints whitelist
-│ │ ├── sse_hub.go # Server-Sent Events (live updates)
-│ │ └── mcp/ # MCP server for AI assistants
-│ ├── frontend/ # SPA static file serving
-│ ├── fileserver/ # Native HTTP file server (thumbnails, range requests)
-│ └── rss/ # RSS feeds
-└── runner/ # Background: memo payload processing, S3 presign refresh
-
-store/
-├── driver.go # Database driver interface
-├── store.go # Store wrapper + in-memory cache (TTL 10min, max 1000)
-├── migrator.go # Migration logic (LATEST.sql for fresh, incremental for upgrades)
-└── db/{sqlite,mysql,postgres}/ # Driver implementations
-
-proto/
-├── api/v1/ # Service definitions
-├── store/ # Internal storage messages
-└── gen/ # Generated Go, TypeScript, OpenAPI
-
-plugin/ # scheduler, cron, email, filter (CEL), webhook,
- # markdown (Goldmark), httpgetter, idp (OAuth2), storage/s3
-
-web/src/
-├── connect.ts # Connect RPC client + auth interceptor + token refresh
-├── auth-state.ts # Token storage (localStorage + BroadcastChannel cross-tab)
-├── contexts/ # AuthContext, InstanceContext, ViewContext, MemoFilterContext
-├── hooks/ # React Query hooks (useMemoQueries, useUserQueries, etc.)
-├── lib/query-client.ts # React Query v5 (staleTime: 30s, gcTime: 5min)
-├── router/index.tsx # Route definitions
-├── components/ # UI components (Radix UI primitives, MemoEditor, Settings, etc.)
-├── themes/ # CSS themes (default, dark, paper) — OKLch color tokens
-└── pages/ # Page components
-```
-
-## Conventions
-
-### Go
-- **Errors:** `errors.Wrap(err, "context")` from `github.com/pkg/errors`. Never `fmt.Errorf` (lint-enforced via forbidigo).
-- **gRPC errors:** `status.Errorf(codes.X, "message")` from service methods.
-- **Imports:** stdlib, then third-party, then local (`github.com/usememos/memos`). Enforced by goimports (runs as golangci-lint formatter).
-- **Comments:** All exported functions must have doc comments (godot enforced).
-
-### Frontend
-- **Imports:** Use `@/` alias for absolute imports.
-- **Formatting:** Biome — 140 char lines, double quotes, always semicolons, 2-space indent.
-- **State:** Server data via React Query hooks (`hooks/`). Client state via React Context (`contexts/`).
-- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite`), `cn()` utility (clsx + tailwind-merge), CVA for variants.
-
-### Database & Proto
-- **DB changes:** Migration files for all 3 drivers + update `LATEST.sql`.
-- **Proto changes:** Run `buf generate`. Generated code: `proto/gen/` and `web/src/types/proto/`.
-- **Public endpoints:** Add to `server/router/api/v1/acl_config.go`.
-
-## CI/CD
-
-- **backend-tests.yml:** Go 1.26.1, golangci-lint v2.4.0, tests parallelized by group (store, server, plugin, other)
-- **frontend-tests.yml:** Node 24, pnpm 10, lint + build
-- **proto-linter.yml:** buf lint + format check
-- **Docker:** Multi-stage (`scripts/Dockerfile`), Alpine 3.21, non-root user, port 5230, multi-arch (amd64/arm64/arm/v7)
+# AGENTS.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+Self-hosted note-taking tool. Go 1.26 backend (Echo v5, Connect RPC + gRPC-Gateway), React 18 + TypeScript 5.9 + Vite 7 frontend, Protocol Buffers API, SQLite/MySQL/PostgreSQL.
+
+## Commands
+
+```bash
+# Backend
+go run ./cmd/memos --port 8081 # Start dev server
+go test ./... # Run all tests
+go test -v ./store/... # Run store tests (all 3 DB drivers via TestContainers)
+go test -v -race ./server/... # Run server tests with race detection
+go test -v -run TestFoo ./pkg/... # Run a single test
+golangci-lint run # Lint (v2, config: .golangci.yaml)
+golangci-lint run --fix # Auto-fix lint issues (includes goimports)
+
+# Frontend (cd web)
+pnpm install # Install deps
+pnpm dev # Dev server (:3001, proxies API to :8081)
+pnpm lint # Type check + Biome lint
+pnpm lint:fix # Auto-fix lint issues
+pnpm format # Format code
+pnpm build # Production build
+pnpm release # Build to server/router/frontend/dist
+
+# Protocol Buffers (cd proto)
+buf generate # Regenerate Go + TypeScript + OpenAPI
+buf lint # Lint proto files
+buf format -w # Format proto files
+```
+
+## Architecture
+
+```
+cmd/memos/main.go # Cobra CLI + Viper config, server init
+
+server/
+├── server.go # Echo v5 HTTP server, background runners
+├── auth/ # JWT access (15min) + refresh (30d) tokens, PAT
+├── router/
+│ ├── api/v1/ # 8 gRPC services (Connect + Gateway)
+│ │ ├── acl_config.go # Public endpoints whitelist
+│ │ ├── sse_hub.go # Server-Sent Events (live updates)
+│ │ └── mcp/ # MCP server for AI assistants
+│ ├── frontend/ # SPA static file serving
+│ ├── fileserver/ # Native HTTP file server (thumbnails, range requests)
+│ └── rss/ # RSS feeds
+└── runner/ # Background: memo payload processing, S3 presign refresh
+
+store/
+├── driver.go # Database driver interface
+├── store.go # Store wrapper + in-memory cache (TTL 10min, max 1000)
+├── migrator.go # Migration logic (LATEST.sql for fresh, incremental for upgrades)
+└── db/{sqlite,mysql,postgres}/ # Driver implementations
+
+proto/
+├── api/v1/ # Service definitions
+├── store/ # Internal storage messages
+└── gen/ # Generated Go, TypeScript, OpenAPI
+
+plugin/ # scheduler, cron, email, filter (CEL), webhook,
+ # markdown (Goldmark), httpgetter, idp (OAuth2), storage/s3
+
+web/src/
+├── connect.ts # Connect RPC client + auth interceptor + token refresh
+├── auth-state.ts # Token storage (localStorage + BroadcastChannel cross-tab)
+├── contexts/ # AuthContext, InstanceContext, ViewContext, MemoFilterContext
+├── hooks/ # React Query hooks (useMemoQueries, useUserQueries, etc.)
+├── lib/query-client.ts # React Query v5 (staleTime: 30s, gcTime: 5min)
+├── router/index.tsx # Route definitions
+├── components/ # UI components (Radix UI primitives, MemoEditor, Settings, etc.)
+├── themes/ # CSS themes (default, dark, paper) — OKLch color tokens
+└── pages/ # Page components
+```
+
+## Conventions
+
+### Go
+- **Errors:** `errors.Wrap(err, "context")` from `github.com/pkg/errors`. Never `fmt.Errorf` (lint-enforced via forbidigo).
+- **gRPC errors:** `status.Errorf(codes.X, "message")` from service methods.
+- **Imports:** stdlib, then third-party, then local (`github.com/usememos/memos`). Enforced by goimports (runs as golangci-lint formatter).
+- **Comments:** All exported functions must have doc comments (godot enforced).
+
+### Frontend
+- **Imports:** Use `@/` alias for absolute imports.
+- **Formatting:** Biome — 140 char lines, double quotes, always semicolons, 2-space indent.
+- **State:** Server data via React Query hooks (`hooks/`). Client state via React Context (`contexts/`).
+- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite`), `cn()` utility (clsx + tailwind-merge), CVA for variants.
+
+### Database & Proto
+- **DB changes:** Migration files for all 3 drivers + update `LATEST.sql`.
+- **Proto changes:** Run `buf generate`. Generated code: `proto/gen/` and `web/src/types/proto/`.
+- **Public endpoints:** Add to `server/router/api/v1/acl_config.go`.
+
+## CI/CD
+
+- **backend-tests.yml:** Go 1.26.1, golangci-lint v2.4.0, tests parallelized by group (store, server, plugin, other)
+- **frontend-tests.yml:** Node 24, pnpm 10, lint + build
+- **proto-linter.yml:** buf lint + format check
+- **Docker:** Multi-stage (`scripts/Dockerfile`), Alpine 3.21, non-root user, port 5230, multi-arch (amd64/arm64/arm/v7)
diff --git a/CLAUDE.md b/CLAUDE.md
index 4e1576140..e9e0d7505 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,5 +1,5 @@
-# CLAUDE.md
-
-This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
-
-See `AGENTS.md` for full architecture, workflows, conventions, and patterns.
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+See `AGENTS.md` for full architecture, workflows, conventions, and patterns.
diff --git a/CODEOWNERS b/CODEOWNERS
index b75ef1700..c9321e3cb 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,2 +1,2 @@
-# These owners will be the default owners for everything in the repo.
-* @usememos/moderators
+# These owners will be the default owners for everything in the repo.
+* @usememos/moderators
diff --git a/LICENSE b/LICENSE
index ad324eef2..bb1ffb327 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,21 @@
-MIT License
-
-Copyright (c) 2025 Memos
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+MIT License
+
+Copyright (c) 2025 Memos
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index a71e7f891..730841645 100644
--- a/README.md
+++ b/README.md
@@ -1,120 +1,120 @@
-
-
-# Memos
-
-
-
-Open-source, self-hosted note-taking tool built for quick capture. Markdown-native, lightweight, and fully yours.
-
-[](https://usememos.com)
-[](https://demo.usememos.com/)
-[](https://usememos.com/docs)
-[](https://discord.gg/tfPJa4UmAv)
-[](https://hub.docker.com/r/neosmemo/memos)
-
-
-
-### 💎 Featured Sponsors
-
-[**Warp** — The AI-powered terminal built for speed and collaboration](https://go.warp.dev/memos)
-
-
-
-
-
-
-
-[**TestMu AI** - The world’s first full-stack Agentic AI Quality Engineering platform](https://www.testmuai.com/?utm_medium=sponsor&utm_source=memos)
-
-
-
-
-
-
-
-[**SSD Nodes** - Affordable VPS hosting for self-hosters](https://ssdnodes.com/?utm_source=memos&utm_medium=sponsor)
-
-
-
-
-
-## Features
-
-- **Instant Capture** — Timeline-first UI. Open, write, done — no folders to navigate.
-- **Total Data Ownership** — Self-hosted on your infrastructure. Notes stored in Markdown, always portable. Zero telemetry.
-- **Radical Simplicity** — Single Go binary, ~20MB Docker image. One command to deploy with SQLite, MySQL, or PostgreSQL.
-- **Open & Extensible** — MIT-licensed with full REST and gRPC APIs for integration.
-
-## Quick Start
-
-### Docker (Recommended)
-
-```bash
-docker run -d \
- --name memos \
- -p 5230:5230 \
- -v ~/.memos:/var/opt/memos \
- neosmemo/memos:stable
-```
-
-Open `http://localhost:5230` and start writing!
-
-### Native Binary
-
-```bash
-curl -fsSL https://raw.githubusercontent.com/usememos/memos/main/scripts/install.sh | sh
-```
-
-### Try the Live Demo
-
-Don't want to install yet? Try our [live demo](https://demo.usememos.com/) first!
-
-### Other Installation Methods
-
-- **Docker Compose** - Recommended for production deployments
-- **Pre-built Binaries** - Available for Linux, macOS, and Windows
-- **Kubernetes** - Helm charts and manifests available
-- **Build from Source** - For development and customization
-
-See our [installation guide](https://usememos.com/docs/deploy) for detailed instructions.
-
-## Contributing
-
-Contributions are welcome — bug reports, feature suggestions, pull requests, documentation, and translations.
-
-- [Report bugs](https://github.com/usememos/memos/issues/new?template=bug_report.md)
-- [Suggest features](https://github.com/usememos/memos/issues/new?template=feature_request.md)
-- [Submit pull requests](https://github.com/usememos/memos/pulls)
-- [Improve documentation](https://github.com/usememos/dotcom)
-- [Help with translations](https://github.com/usememos/memos/tree/main/web/src/locales)
-
-## Sponsors
-
-Love Memos? [Sponsor us on GitHub](https://github.com/sponsors/usememos) to help keep the project growing!
-
-## Star History
-
-[](https://star-history.com/#usememos/memos&Date)
-
-## License
-
-Memos is open-source software licensed under the [MIT License](LICENSE). See our [Privacy Policy](https://usememos.com/privacy) for details on data handling.
-
----
-
-**[Website](https://usememos.com)** • **[Documentation](https://usememos.com/docs)** • **[Demo](https://demo.usememos.com/)** • **[Discord](https://discord.gg/tfPJa4UmAv)** • **[X/Twitter](https://x.com/usememos)**
-
-
-
-
+
+
+# Memos
+
+
+
+Open-source, self-hosted note-taking tool built for quick capture. Markdown-native, lightweight, and fully yours.
+
+[](https://usememos.com)
+[](https://demo.usememos.com/)
+[](https://usememos.com/docs)
+[](https://discord.gg/tfPJa4UmAv)
+[](https://hub.docker.com/r/neosmemo/memos)
+
+
+
+### 💎 Featured Sponsors
+
+[**Warp** — The AI-powered terminal built for speed and collaboration](https://go.warp.dev/memos)
+
+
+
+
+
+
+
+[**TestMu AI** - The world’s first full-stack Agentic AI Quality Engineering platform](https://www.testmuai.com/?utm_medium=sponsor&utm_source=memos)
+
+
+
+
+
+
+
+[**SSD Nodes** - Affordable VPS hosting for self-hosters](https://ssdnodes.com/?utm_source=memos&utm_medium=sponsor)
+
+
+
+
+
+## Features
+
+- **Instant Capture** — Timeline-first UI. Open, write, done — no folders to navigate.
+- **Total Data Ownership** — Self-hosted on your infrastructure. Notes stored in Markdown, always portable. Zero telemetry.
+- **Radical Simplicity** — Single Go binary, ~20MB Docker image. One command to deploy with SQLite, MySQL, or PostgreSQL.
+- **Open & Extensible** — MIT-licensed with full REST and gRPC APIs for integration.
+
+## Quick Start
+
+### Docker (Recommended)
+
+```bash
+docker run -d \
+ --name memos \
+ -p 5230:5230 \
+ -v ~/.memos:/var/opt/memos \
+ neosmemo/memos:stable
+```
+
+Open `http://localhost:5230` and start writing!
+
+### Native Binary
+
+```bash
+curl -fsSL https://raw.githubusercontent.com/usememos/memos/main/scripts/install.sh | sh
+```
+
+### Try the Live Demo
+
+Don't want to install yet? Try our [live demo](https://demo.usememos.com/) first!
+
+### Other Installation Methods
+
+- **Docker Compose** - Recommended for production deployments
+- **Pre-built Binaries** - Available for Linux, macOS, and Windows
+- **Kubernetes** - Helm charts and manifests available
+- **Build from Source** - For development and customization
+
+See our [installation guide](https://usememos.com/docs/deploy) for detailed instructions.
+
+## Contributing
+
+Contributions are welcome — bug reports, feature suggestions, pull requests, documentation, and translations.
+
+- [Report bugs](https://github.com/usememos/memos/issues/new?template=bug_report.md)
+- [Suggest features](https://github.com/usememos/memos/issues/new?template=feature_request.md)
+- [Submit pull requests](https://github.com/usememos/memos/pulls)
+- [Improve documentation](https://github.com/usememos/dotcom)
+- [Help with translations](https://github.com/usememos/memos/tree/main/web/src/locales)
+
+## Sponsors
+
+Love Memos? [Sponsor us on GitHub](https://github.com/sponsors/usememos) to help keep the project growing!
+
+## Star History
+
+[](https://star-history.com/#usememos/memos&Date)
+
+## License
+
+Memos is open-source software licensed under the [MIT License](LICENSE). See our [Privacy Policy](https://usememos.com/privacy) for details on data handling.
+
+---
+
+**[Website](https://usememos.com)** • **[Documentation](https://usememos.com/docs)** • **[Demo](https://demo.usememos.com/)** • **[Discord](https://discord.gg/tfPJa4UmAv)** • **[X/Twitter](https://x.com/usememos)**
+
+
+
+
diff --git a/SECURITY.md b/SECURITY.md
index 1818991e9..d7b81bee2 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,46 +1,46 @@
-# Security Policy
-
-## Project Status
-
-Memos is currently in beta (v0.x). While we take security seriously, we are not yet ready for formal CVE assignments or coordinated disclosure programs.
-
-## Reporting Security Issues
-
-### For All Security Concerns:
-Please report via **email only**: dev@usememos.com
-
-**DO NOT open public GitHub issues for security vulnerabilities.**
-
-Include in your report:
-- Description of the issue
-- Steps to reproduce
-- Affected versions
-- Your assessment of severity
-
-### What to Expect:
-- We will acknowledge your report as soon as we can
-- Fixes will be included in regular releases without special security advisories
-- No CVEs will be assigned during the beta phase
-- Credit will be given in release notes if you wish
-
-### For Non-Security Bugs:
-Use GitHub issues for functionality bugs, feature requests, and general questions.
-
-## Philosophy
-
-As a beta project, we prioritize:
-1. **Rapid iteration** over lengthy disclosure timelines
-2. **Quick patches** over formal security processes
-3. **Transparency** about our beta status
-
-We plan to implement formal vulnerability disclosure and CVE handling after reaching v1.0 stable.
-
-## Self-Hosting Security
-
-Since Memos is self-hosted software:
-- Keep your instance updated to the latest release
-- Don't expose your instance directly to the internet without authentication
-- Use reverse proxies (nginx, Caddy) with rate limiting
-- Review the deployment documentation for security best practices
-
-Thank you for helping improve Memos!
+# Security Policy
+
+## Project Status
+
+Memos is currently in beta (v0.x). While we take security seriously, we are not yet ready for formal CVE assignments or coordinated disclosure programs.
+
+## Reporting Security Issues
+
+### For All Security Concerns:
+Please report via **email only**: dev@usememos.com
+
+**DO NOT open public GitHub issues for security vulnerabilities.**
+
+Include in your report:
+- Description of the issue
+- Steps to reproduce
+- Affected versions
+- Your assessment of severity
+
+### What to Expect:
+- We will acknowledge your report as soon as we can
+- Fixes will be included in regular releases without special security advisories
+- No CVEs will be assigned during the beta phase
+- Credit will be given in release notes if you wish
+
+### For Non-Security Bugs:
+Use GitHub issues for functionality bugs, feature requests, and general questions.
+
+## Philosophy
+
+As a beta project, we prioritize:
+1. **Rapid iteration** over lengthy disclosure timelines
+2. **Quick patches** over formal security processes
+3. **Transparency** about our beta status
+
+We plan to implement formal vulnerability disclosure and CVE handling after reaching v1.0 stable.
+
+## Self-Hosting Security
+
+Since Memos is self-hosted software:
+- Keep your instance updated to the latest release
+- Don't expose your instance directly to the internet without authentication
+- Use reverse proxies (nginx, Caddy) with rate limiting
+- Review the deployment documentation for security best practices
+
+Thank you for helping improve Memos!
diff --git a/cmd/memos/main.go b/cmd/memos/main.go
index bf0a67373..48ea74610 100644
--- a/cmd/memos/main.go
+++ b/cmd/memos/main.go
@@ -1,191 +1,191 @@
-package main
-
-import (
- "context"
- "fmt"
- "log/slog"
- "net/http"
- "os"
- "os/signal"
- "strings"
- "syscall"
-
- "github.com/spf13/cobra"
- "github.com/spf13/viper"
-
- "github.com/usememos/memos/internal/profile"
- "github.com/usememos/memos/internal/version"
- "github.com/usememos/memos/plugin/webhook"
- "github.com/usememos/memos/server"
- "github.com/usememos/memos/store"
- "github.com/usememos/memos/store/db"
-)
-
-var (
- rootCmd = &cobra.Command{
- Use: "memos",
- Short: `An open source, lightweight note-taking service. Easily capture and share your great thoughts.`,
- Run: func(_ *cobra.Command, _ []string) {
- instanceProfile := &profile.Profile{
- Demo: viper.GetBool("demo"),
- Addr: viper.GetString("addr"),
- Port: viper.GetInt("port"),
- UNIXSock: viper.GetString("unix-sock"),
- Data: viper.GetString("data"),
- Driver: viper.GetString("driver"),
- DSN: viper.GetString("dsn"),
- InstanceURL: viper.GetString("instance-url"),
- }
- instanceProfile.Version = version.GetCurrentVersion()
- webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks")
-
- if err := instanceProfile.Validate(); err != nil {
- slog.Error("failed to validate profile", "error", err)
- return
- }
-
- ctx, cancel := context.WithCancel(context.Background())
- dbDriver, err := db.NewDBDriver(instanceProfile)
- if err != nil {
- cancel()
- slog.Error("failed to create db driver", "error", err)
- return
- }
-
- storeInstance := store.New(dbDriver, instanceProfile)
- if err := storeInstance.Migrate(ctx); err != nil {
- cancel()
- slog.Error("failed to migrate", "error", err)
- return
- }
-
- s, err := server.NewServer(ctx, instanceProfile, storeInstance)
- if err != nil {
- cancel()
- slog.Error("failed to create server", "error", err)
- return
- }
-
- c := make(chan os.Signal, 1)
- // Trigger graceful shutdown on SIGINT or SIGTERM.
- // The default signal sent by the `kill` command is SIGTERM,
- // which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
- signal.Notify(c, os.Interrupt, syscall.SIGTERM)
-
- if err := s.Start(ctx); err != nil {
- if err != http.ErrServerClosed {
- slog.Error("failed to start server", "error", err)
- cancel()
- return
- }
- }
-
- printGreetings(instanceProfile)
-
- go func() {
- <-c
- s.Shutdown(ctx)
- cancel()
- }()
-
- // Wait for CTRL-C.
- <-ctx.Done()
- },
- }
- versionCmd = &cobra.Command{
- Use: "version",
- Short: "Print the current Memos version",
- Run: func(_ *cobra.Command, _ []string) {
- fmt.Println(version.GetCurrentVersion())
- },
- }
-)
-
-func init() {
- viper.SetDefault("demo", false)
- viper.SetDefault("driver", "sqlite")
- viper.SetDefault("port", 8081)
-
- rootCmd.PersistentFlags().Bool("demo", false, "enable demo mode")
- rootCmd.PersistentFlags().String("addr", "", "address of server")
- rootCmd.PersistentFlags().Int("port", 8081, "port of server")
- rootCmd.PersistentFlags().String("unix-sock", "", "path to the unix socket, overrides --addr and --port")
- rootCmd.PersistentFlags().String("data", "", "data directory")
- rootCmd.PersistentFlags().String("driver", "sqlite", "database driver")
- rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)")
- rootCmd.PersistentFlags().String("instance-url", "", "the url of your memos instance")
- rootCmd.PersistentFlags().Bool("allow-private-webhooks", false, "allow webhook URLs to resolve to private/reserved IP addresses")
-
- if err := viper.BindPFlag("demo", rootCmd.PersistentFlags().Lookup("demo")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("addr", rootCmd.PersistentFlags().Lookup("addr")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("unix-sock", rootCmd.PersistentFlags().Lookup("unix-sock")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("driver", rootCmd.PersistentFlags().Lookup("driver")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("dsn", rootCmd.PersistentFlags().Lookup("dsn")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("instance-url", rootCmd.PersistentFlags().Lookup("instance-url")); err != nil {
- panic(err)
- }
- if err := viper.BindPFlag("allow-private-webhooks", rootCmd.PersistentFlags().Lookup("allow-private-webhooks")); err != nil {
- panic(err)
- }
-
- viper.SetEnvPrefix("memos")
- viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
- viper.AutomaticEnv()
-
- rootCmd.AddCommand(versionCmd)
-}
-
-func printGreetings(profile *profile.Profile) {
- fmt.Printf("Memos %s started successfully!\n", profile.Version)
-
- if profile.Demo {
- fmt.Fprint(os.Stderr, "Development mode is enabled\n")
- if profile.DSN != "" {
- fmt.Fprintf(os.Stderr, "Database: %s\n", profile.DSN)
- }
- }
-
- // Server information
- fmt.Printf("Data directory: %s\n", profile.Data)
- fmt.Printf("Database driver: %s\n", profile.Driver)
-
- // Connection information
- if len(profile.UNIXSock) == 0 {
- if len(profile.Addr) == 0 {
- fmt.Printf("Server running on port %d\n", profile.Port)
- fmt.Printf("Access your memos at: http://localhost:%d\n", profile.Port)
- } else {
- fmt.Printf("Server running on %s:%d\n", profile.Addr, profile.Port)
- fmt.Printf("Access your memos at: http://%s:%d\n", profile.Addr, profile.Port)
- }
- } else {
- fmt.Printf("Server running on unix socket: %s\n", profile.UNIXSock)
- }
-
- fmt.Println()
- fmt.Printf("Documentation: %s\n", "https://usememos.com")
- fmt.Printf("Source code: %s\n", "https://github.com/usememos/memos")
- fmt.Println("\nHappy note-taking!")
-}
-
-func main() {
- if err := rootCmd.Execute(); err != nil {
- os.Exit(1)
- }
-}
+package main
+
+import (
+ "context"
+ "fmt"
+ "log/slog"
+ "net/http"
+ "os"
+ "os/signal"
+ "strings"
+ "syscall"
+
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
+
+ "github.com/usememos/memos/internal/profile"
+ "github.com/usememos/memos/internal/version"
+ "github.com/usememos/memos/plugin/webhook"
+ "github.com/usememos/memos/server"
+ "github.com/usememos/memos/store"
+ "github.com/usememos/memos/store/db"
+)
+
+var (
+ rootCmd = &cobra.Command{
+ Use: "memos",
+ Short: `An open source, lightweight note-taking service. Easily capture and share your great thoughts.`,
+ Run: func(_ *cobra.Command, _ []string) {
+ instanceProfile := &profile.Profile{
+ Demo: viper.GetBool("demo"),
+ Addr: viper.GetString("addr"),
+ Port: viper.GetInt("port"),
+ UNIXSock: viper.GetString("unix-sock"),
+ Data: viper.GetString("data"),
+ Driver: viper.GetString("driver"),
+ DSN: viper.GetString("dsn"),
+ InstanceURL: viper.GetString("instance-url"),
+ }
+ instanceProfile.Version = version.GetCurrentVersion()
+ webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks")
+
+ if err := instanceProfile.Validate(); err != nil {
+ slog.Error("failed to validate profile", "error", err)
+ return
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ dbDriver, err := db.NewDBDriver(instanceProfile)
+ if err != nil {
+ cancel()
+ slog.Error("failed to create db driver", "error", err)
+ return
+ }
+
+ storeInstance := store.New(dbDriver, instanceProfile)
+ if err := storeInstance.Migrate(ctx); err != nil {
+ cancel()
+ slog.Error("failed to migrate", "error", err)
+ return
+ }
+
+ s, err := server.NewServer(ctx, instanceProfile, storeInstance)
+ if err != nil {
+ cancel()
+ slog.Error("failed to create server", "error", err)
+ return
+ }
+
+ c := make(chan os.Signal, 1)
+ // Trigger graceful shutdown on SIGINT or SIGTERM.
+ // The default signal sent by the `kill` command is SIGTERM,
+ // which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+
+ if err := s.Start(ctx); err != nil {
+ if err != http.ErrServerClosed {
+ slog.Error("failed to start server", "error", err)
+ cancel()
+ return
+ }
+ }
+
+ printGreetings(instanceProfile)
+
+ go func() {
+ <-c
+ s.Shutdown(ctx)
+ cancel()
+ }()
+
+ // Wait for CTRL-C.
+ <-ctx.Done()
+ },
+ }
+ versionCmd = &cobra.Command{
+ Use: "version",
+ Short: "Print the current Memos version",
+ Run: func(_ *cobra.Command, _ []string) {
+ fmt.Println(version.GetCurrentVersion())
+ },
+ }
+)
+
+func init() {
+ viper.SetDefault("demo", false)
+ viper.SetDefault("driver", "sqlite")
+ viper.SetDefault("port", 8081)
+
+ rootCmd.PersistentFlags().Bool("demo", false, "enable demo mode")
+ rootCmd.PersistentFlags().String("addr", "", "address of server")
+ rootCmd.PersistentFlags().Int("port", 8081, "port of server")
+ rootCmd.PersistentFlags().String("unix-sock", "", "path to the unix socket, overrides --addr and --port")
+ rootCmd.PersistentFlags().String("data", "", "data directory")
+ rootCmd.PersistentFlags().String("driver", "sqlite", "database driver")
+ rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)")
+ rootCmd.PersistentFlags().String("instance-url", "", "the url of your memos instance")
+ rootCmd.PersistentFlags().Bool("allow-private-webhooks", false, "allow webhook URLs to resolve to private/reserved IP addresses")
+
+ if err := viper.BindPFlag("demo", rootCmd.PersistentFlags().Lookup("demo")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("addr", rootCmd.PersistentFlags().Lookup("addr")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("unix-sock", rootCmd.PersistentFlags().Lookup("unix-sock")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("driver", rootCmd.PersistentFlags().Lookup("driver")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("dsn", rootCmd.PersistentFlags().Lookup("dsn")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("instance-url", rootCmd.PersistentFlags().Lookup("instance-url")); err != nil {
+ panic(err)
+ }
+ if err := viper.BindPFlag("allow-private-webhooks", rootCmd.PersistentFlags().Lookup("allow-private-webhooks")); err != nil {
+ panic(err)
+ }
+
+ viper.SetEnvPrefix("memos")
+ viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
+ viper.AutomaticEnv()
+
+ rootCmd.AddCommand(versionCmd)
+}
+
+func printGreetings(profile *profile.Profile) {
+ fmt.Printf("Memos %s started successfully!\n", profile.Version)
+
+ if profile.Demo {
+ fmt.Fprint(os.Stderr, "Development mode is enabled\n")
+ if profile.DSN != "" {
+ fmt.Fprintf(os.Stderr, "Database: %s\n", profile.DSN)
+ }
+ }
+
+ // Server information
+ fmt.Printf("Data directory: %s\n", profile.Data)
+ fmt.Printf("Database driver: %s\n", profile.Driver)
+
+ // Connection information
+ if len(profile.UNIXSock) == 0 {
+ if len(profile.Addr) == 0 {
+ fmt.Printf("Server running on port %d\n", profile.Port)
+ fmt.Printf("Access your memos at: http://localhost:%d\n", profile.Port)
+ } else {
+ fmt.Printf("Server running on %s:%d\n", profile.Addr, profile.Port)
+ fmt.Printf("Access your memos at: http://%s:%d\n", profile.Addr, profile.Port)
+ }
+ } else {
+ fmt.Printf("Server running on unix socket: %s\n", profile.UNIXSock)
+ }
+
+ fmt.Println()
+ fmt.Printf("Documentation: %s\n", "https://usememos.com")
+ fmt.Printf("Source code: %s\n", "https://github.com/usememos/memos")
+ fmt.Println("\nHappy note-taking!")
+}
+
+func main() {
+ if err := rootCmd.Execute(); err != nil {
+ os.Exit(1)
+ }
+}
diff --git a/go.mod b/go.mod
index 64ccbfc03..938fa9f33 100644
--- a/go.mod
+++ b/go.mod
@@ -1,141 +1,141 @@
-module github.com/usememos/memos
-
-go 1.26.1
-
-require (
- connectrpc.com/connect v1.19.1
- github.com/aws/aws-sdk-go-v2 v1.41.4
- github.com/aws/aws-sdk-go-v2/config v1.32.12
- github.com/aws/aws-sdk-go-v2/credentials v1.19.12
- github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1
- github.com/docker/docker v28.5.2+incompatible
- github.com/go-sql-driver/mysql v1.9.3
- github.com/google/cel-go v0.27.0
- github.com/google/uuid v1.6.0
- github.com/gorilla/feeds v1.2.0
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0
- github.com/joho/godotenv v1.5.1
- github.com/labstack/echo/v5 v5.0.4
- github.com/lib/pq v1.11.2
- github.com/lithammer/shortuuid/v4 v4.2.0
- github.com/mark3labs/mcp-go v0.45.0
- github.com/pkg/errors v0.9.1
- github.com/spf13/cobra v1.10.2
- github.com/spf13/viper v1.21.0
- github.com/stretchr/testify v1.11.1
- github.com/testcontainers/testcontainers-go v0.41.0
- github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0
- github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0
- github.com/yuin/goldmark v1.7.16
- golang.org/x/crypto v0.49.0
- golang.org/x/mod v0.34.0
- golang.org/x/net v0.52.0
- golang.org/x/oauth2 v0.36.0
- golang.org/x/sync v0.20.0
- google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5
- google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d
- google.golang.org/grpc v1.79.2
- modernc.org/sqlite v1.46.1
-)
-
-require (
- cel.dev/expr v0.25.1 // indirect
- dario.cat/mergo v1.0.2 // indirect
- filippo.io/edwards25519 v1.1.0 // indirect
- github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
- github.com/Microsoft/go-winio v0.6.2 // indirect
- github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect
- github.com/bahlo/generic-list-go v0.2.0 // indirect
- github.com/buger/jsonparser v1.1.1 // indirect
- github.com/cenkalti/backoff/v4 v4.3.0 // indirect
- github.com/cespare/xxhash/v2 v2.3.0 // indirect
- github.com/containerd/errdefs v1.0.0 // indirect
- github.com/containerd/errdefs/pkg v0.3.0 // indirect
- github.com/containerd/log v0.1.0 // indirect
- github.com/containerd/platforms v0.2.1 // indirect
- github.com/cpuguy83/dockercfg v0.3.2 // indirect
- github.com/distribution/reference v0.6.0 // indirect
- github.com/docker/go-connections v0.6.0 // indirect
- github.com/docker/go-units v0.5.0 // indirect
- github.com/dustin/go-humanize v1.0.1 // indirect
- github.com/ebitengine/purego v0.10.0 // indirect
- github.com/felixge/httpsnoop v1.0.4 // indirect
- github.com/fsnotify/fsnotify v1.9.0 // indirect
- github.com/go-logr/logr v1.4.3 // indirect
- github.com/go-logr/stdr v1.2.2 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
- github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
- github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/invopop/jsonschema v0.13.0 // indirect
- github.com/klauspost/compress v1.18.2 // indirect
- github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
- github.com/magiconair/properties v1.8.10 // indirect
- github.com/mailru/easyjson v0.7.7 // indirect
- github.com/moby/docker-image-spec v1.3.1 // indirect
- github.com/moby/go-archive v0.2.0 // indirect
- github.com/moby/patternmatcher v0.6.0 // indirect
- github.com/moby/sys/sequential v0.6.0 // indirect
- github.com/moby/sys/user v0.4.0 // indirect
- github.com/moby/sys/userns v0.1.0 // indirect
- github.com/moby/term v0.5.2 // indirect
- github.com/morikuni/aec v1.0.0 // indirect
- github.com/ncruces/go-strftime v1.0.0 // indirect
- github.com/opencontainers/go-digest v1.0.0 // indirect
- github.com/opencontainers/image-spec v1.1.1 // indirect
- github.com/pelletier/go-toml/v2 v2.2.4 // indirect
- github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
- github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
- github.com/sagikazarmark/locafero v0.11.0 // indirect
- github.com/shirou/gopsutil/v4 v4.26.2 // indirect
- github.com/sirupsen/logrus v1.9.3 // indirect
- github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
- github.com/spf13/afero v1.15.0 // indirect
- github.com/spf13/cast v1.10.0 // indirect
- github.com/spf13/pflag v1.0.10 // indirect
- github.com/subosito/gotenv v1.6.0 // indirect
- github.com/tklauser/go-sysconf v0.3.16 // indirect
- github.com/tklauser/numcpus v0.11.0 // indirect
- github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
- github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
- github.com/yusufpapurcu/wmi v1.2.4 // indirect
- go.opentelemetry.io/auto/sdk v1.2.1 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
- go.opentelemetry.io/otel v1.41.0 // indirect
- go.opentelemetry.io/otel/metric v1.41.0 // indirect
- go.opentelemetry.io/otel/trace v1.41.0 // indirect
- go.yaml.in/yaml/v3 v3.0.4 // indirect
- golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
- golang.org/x/image v0.30.0 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect
- modernc.org/libc v1.67.6 // indirect
- modernc.org/mathutil v1.7.1 // indirect
- modernc.org/memory v1.11.0 // indirect
-)
-
-require (
- github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect
- github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect
- github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect
- github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect
- github.com/aws/smithy-go v1.24.2 // indirect
- github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
- github.com/disintegration/imaging v1.6.2
- github.com/golang-jwt/jwt/v5 v5.3.1
- github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
- golang.org/x/sys v0.42.0 // indirect
- golang.org/x/text v0.35.0
- golang.org/x/time v0.14.0 // indirect
- google.golang.org/protobuf v1.36.11
- gopkg.in/yaml.v3 v3.0.1 // indirect
-)
+module github.com/usememos/memos
+
+go 1.26.1
+
+require (
+ connectrpc.com/connect v1.19.1
+ github.com/aws/aws-sdk-go-v2 v1.41.4
+ github.com/aws/aws-sdk-go-v2/config v1.32.12
+ github.com/aws/aws-sdk-go-v2/credentials v1.19.12
+ github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1
+ github.com/docker/docker v28.5.2+incompatible
+ github.com/go-sql-driver/mysql v1.9.3
+ github.com/google/cel-go v0.27.0
+ github.com/google/uuid v1.6.0
+ github.com/gorilla/feeds v1.2.0
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0
+ github.com/joho/godotenv v1.5.1
+ github.com/labstack/echo/v5 v5.0.4
+ github.com/lib/pq v1.11.2
+ github.com/lithammer/shortuuid/v4 v4.2.0
+ github.com/mark3labs/mcp-go v0.45.0
+ github.com/pkg/errors v0.9.1
+ github.com/spf13/cobra v1.10.2
+ github.com/spf13/viper v1.21.0
+ github.com/stretchr/testify v1.11.1
+ github.com/testcontainers/testcontainers-go v0.41.0
+ github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0
+ github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0
+ github.com/yuin/goldmark v1.7.16
+ golang.org/x/crypto v0.49.0
+ golang.org/x/mod v0.34.0
+ golang.org/x/net v0.52.0
+ golang.org/x/oauth2 v0.36.0
+ golang.org/x/sync v0.20.0
+ google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5
+ google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d
+ google.golang.org/grpc v1.79.2
+ modernc.org/sqlite v1.46.1
+)
+
+require (
+ cel.dev/expr v0.25.1 // indirect
+ dario.cat/mergo v1.0.2 // indirect
+ filippo.io/edwards25519 v1.1.0 // indirect
+ github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
+ github.com/Microsoft/go-winio v0.6.2 // indirect
+ github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
+ github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect
+ github.com/bahlo/generic-list-go v0.2.0 // indirect
+ github.com/buger/jsonparser v1.1.1 // indirect
+ github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/containerd/errdefs v1.0.0 // indirect
+ github.com/containerd/errdefs/pkg v0.3.0 // indirect
+ github.com/containerd/log v0.1.0 // indirect
+ github.com/containerd/platforms v0.2.1 // indirect
+ github.com/cpuguy83/dockercfg v0.3.2 // indirect
+ github.com/distribution/reference v0.6.0 // indirect
+ github.com/docker/go-connections v0.6.0 // indirect
+ github.com/docker/go-units v0.5.0 // indirect
+ github.com/dustin/go-humanize v1.0.1 // indirect
+ github.com/ebitengine/purego v0.10.0 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
+ github.com/fsnotify/fsnotify v1.9.0 // indirect
+ github.com/go-logr/logr v1.4.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect
+ github.com/invopop/jsonschema v0.13.0 // indirect
+ github.com/klauspost/compress v1.18.2 // indirect
+ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+ github.com/magiconair/properties v1.8.10 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/moby/docker-image-spec v1.3.1 // indirect
+ github.com/moby/go-archive v0.2.0 // indirect
+ github.com/moby/patternmatcher v0.6.0 // indirect
+ github.com/moby/sys/sequential v0.6.0 // indirect
+ github.com/moby/sys/user v0.4.0 // indirect
+ github.com/moby/sys/userns v0.1.0 // indirect
+ github.com/moby/term v0.5.2 // indirect
+ github.com/morikuni/aec v1.0.0 // indirect
+ github.com/ncruces/go-strftime v1.0.0 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
+ github.com/opencontainers/image-spec v1.1.1 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.4 // indirect
+ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
+ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
+ github.com/sagikazarmark/locafero v0.11.0 // indirect
+ github.com/shirou/gopsutil/v4 v4.26.2 // indirect
+ github.com/sirupsen/logrus v1.9.3 // indirect
+ github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
+ github.com/spf13/afero v1.15.0 // indirect
+ github.com/spf13/cast v1.10.0 // indirect
+ github.com/spf13/pflag v1.0.10 // indirect
+ github.com/subosito/gotenv v1.6.0 // indirect
+ github.com/tklauser/go-sysconf v0.3.16 // indirect
+ github.com/tklauser/numcpus v0.11.0 // indirect
+ github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
+ github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
+ github.com/yusufpapurcu/wmi v1.2.4 // indirect
+ go.opentelemetry.io/auto/sdk v1.2.1 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
+ go.opentelemetry.io/otel v1.41.0 // indirect
+ go.opentelemetry.io/otel/metric v1.41.0 // indirect
+ go.opentelemetry.io/otel/trace v1.41.0 // indirect
+ go.yaml.in/yaml/v3 v3.0.4 // indirect
+ golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
+ golang.org/x/image v0.30.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect
+ modernc.org/libc v1.67.6 // indirect
+ modernc.org/mathutil v1.7.1 // indirect
+ modernc.org/memory v1.11.0 // indirect
+)
+
+require (
+ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect
+ github.com/aws/smithy-go v1.24.2 // indirect
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+ github.com/disintegration/imaging v1.6.2
+ github.com/golang-jwt/jwt/v5 v5.3.1
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+ golang.org/x/sys v0.42.0 // indirect
+ golang.org/x/text v0.35.0
+ golang.org/x/time v0.14.0 // indirect
+ google.golang.org/protobuf v1.36.11
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/go.sum b/go.sum
index 1ed2415ca..e12a14dda 100644
--- a/go.sum
+++ b/go.sum
@@ -1,355 +1,355 @@
-cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
-cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
-connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
-connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
-dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
-dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
-filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
-filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
-github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
-github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
-github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
-github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
-github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
-github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
-github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k=
-github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 h1:3kGOqnh1pPeddVa/E37XNTaWJ8W6vrbYV9lJEkCnhuY=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI=
-github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0=
-github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g=
-github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8=
-github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 h1:SwGMTMLIlvDNyhMteQ6r8IJSBPlRdXX5d4idhIGbkXA=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21/go.mod h1:UUxgWxofmOdAMuqEsSppbDtGKLfR04HGsD0HXzvhI1k=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 h1:qtJZ70afD3ISKWnoX3xB0J2otEqu3LqicRcDBqsj0hQ=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12/go.mod h1:v2pNpJbRNl4vEUWEh5ytQok0zACAKfdmKS51Hotc3pQ=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 h1:2HvVAIq+YqgGotK6EkMf+KIEqTISmTYh5zLpYyeTo1Y=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20/go.mod h1:V4X406Y666khGa8ghKmphma/7C0DAtEQYhkq9z4vpbk=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 h1:siU1A6xjUZ2N8zjTHSXFhB9L/2OY8Dqs0xXiLjF30jA=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20/go.mod h1:4TLZCmVJDM3FOu5P5TJP0zOlu9zWgDWU7aUxWbr+rcw=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1 h1:csi9NLpFZXb9fxY7rS1xVzgPRGMt7MSNWeQ6eo247kE=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1/go.mod h1:qXVal5H0ChqXP63t6jze5LmFalc7+ZE7wOdLtZ0LCP0=
-github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow=
-github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE=
-github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o=
-github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA=
-github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU=
-github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk=
-github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
-github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
-github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
-github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
-github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
-github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
-github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
-github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
-github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
-github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
-github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
-github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
-github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
-github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
-github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
-github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
-github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
-github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
-github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
-github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
-github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
-github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
-github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
-github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
-github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
-github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
-github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
-github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
-github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
-github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
-github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
-github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
-github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU=
-github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
-github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
-github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
-github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
-github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
-github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
-github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
-github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
-github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
-github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
-github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
-github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
-github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
-github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
-github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
-github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
-github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
-github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo=
-github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
-github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
-github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
-github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
-github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
-github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
-github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
-github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
-github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
-github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
-github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
-github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
-github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
-github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
-github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
-github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8=
-github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
-github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
-github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
-github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
-github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
-github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
-github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
-github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
-github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/labstack/echo/v5 v5.0.4 h1:ll3I/O8BifjMztj9dD1vx/peZQv8cR2CTUdQK6QxGGc=
-github.com/labstack/echo/v5 v5.0.4/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
-github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
-github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
-github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c=
-github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y=
-github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
-github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
-github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
-github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mark3labs/mcp-go v0.45.0 h1:s0S8qR/9fWaQ3pHxz7pm1uQ0DrswoSnRIxKIjbiQtkc=
-github.com/mark3labs/mcp-go v0.45.0/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw=
-github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
-github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
-github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o=
-github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
-github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
-github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
-github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU=
-github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
-github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
-github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
-github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
-github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
-github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
-github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
-github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
-github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
-github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
-github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
-github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
-github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
-github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
-github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
-github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
-github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
-github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
-github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
-github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
-github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
-github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
-github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
-github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
-github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
-github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
-github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
-github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
-github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
-github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI=
-github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
-github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
-github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
-github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
-github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
-github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
-github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
-github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
-github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
-github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
-github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
-github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
-github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
-github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
-github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
-github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
-github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/testcontainers/testcontainers-go v0.41.0 h1:mfpsD0D36YgkxGj2LrIyxuwQ9i2wCKAD+ESsYM1wais=
-github.com/testcontainers/testcontainers-go v0.41.0/go.mod h1:pdFrEIfaPl24zmBjerWTTYaY0M6UHsqA1YSvsoU40MI=
-github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0 h1:5rwejaJr5nIfw8NK99eKPX7O6k27lnSMklTj5DbYybM=
-github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0/go.mod h1:iMO/aFWnbjYkqHw8VPsJB3rVTOD9hKDsUtV0PvzD0DA=
-github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 h1:AOtFXssrDlLm84A2sTTR/AhvJiYbrIuCO59d+Ro9Tb0=
-github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0/go.mod h1:k2a09UKhgSp6vNpliIY0QSgm4Hi7GXVTzWvWgUemu/8=
-github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
-github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
-github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
-github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
-github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
-github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
-github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
-github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
-github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
-github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
-github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
-github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
-go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
-go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
-go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c=
-go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0 h1:inYW9ZhgqiDqh6BioM7DVHHzEGVq76Db5897WLGZ5Go=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0/go.mod h1:Izur+Wt8gClgMJqO/cZ8wdeeMryJ/xxiOVgFSSfpDTY=
-go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ=
-go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps=
-go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8=
-go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90=
-go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
-go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
-go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0=
-go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis=
-go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
-go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
-go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
-go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
-golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
-golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
-golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
-golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
-golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4=
-golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c=
-golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
-golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
-golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
-golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
-golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
-golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
-golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
-golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
-golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
-golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
-golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
-golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
-golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
-golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
-golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
-golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
-gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
-google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE=
-google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw=
-google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d h1:RdWlPmVySdTF0IBIZzvZJvSD0ZocPBNUsnE+uGBxj+4=
-google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d/go.mod h1:X2gu9Qwng7Nn009s/r3RUxqkzQNqOrAy79bluY7ojIg=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c h1:xgCzyF2LFIO/0X2UAoVRiXKU5Xg6VjToG4i2/ecSswk=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
-google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
-google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
-google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
-google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
-gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
-modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
-modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
-modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
-modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM=
-modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
-modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
-modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
-modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
-modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
-modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
-modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
-modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
-modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
-modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
-modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
-modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
-modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
-modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
-modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
-modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
-modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
-modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
-modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
-modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
-modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
-modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
-modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
-modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
+cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
+cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
+connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
+connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
+dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
+dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
+github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
+github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k=
+github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 h1:3kGOqnh1pPeddVa/E37XNTaWJ8W6vrbYV9lJEkCnhuY=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI=
+github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0=
+github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g=
+github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8=
+github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY=
+github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 h1:SwGMTMLIlvDNyhMteQ6r8IJSBPlRdXX5d4idhIGbkXA=
+github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21/go.mod h1:UUxgWxofmOdAMuqEsSppbDtGKLfR04HGsD0HXzvhI1k=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 h1:qtJZ70afD3ISKWnoX3xB0J2otEqu3LqicRcDBqsj0hQ=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12/go.mod h1:v2pNpJbRNl4vEUWEh5ytQok0zACAKfdmKS51Hotc3pQ=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 h1:2HvVAIq+YqgGotK6EkMf+KIEqTISmTYh5zLpYyeTo1Y=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20/go.mod h1:V4X406Y666khGa8ghKmphma/7C0DAtEQYhkq9z4vpbk=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 h1:siU1A6xjUZ2N8zjTHSXFhB9L/2OY8Dqs0xXiLjF30jA=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20/go.mod h1:4TLZCmVJDM3FOu5P5TJP0zOlu9zWgDWU7aUxWbr+rcw=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1 h1:csi9NLpFZXb9fxY7rS1xVzgPRGMt7MSNWeQ6eo247kE=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1/go.mod h1:qXVal5H0ChqXP63t6jze5LmFalc7+ZE7wOdLtZ0LCP0=
+github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow=
+github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA=
+github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU=
+github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk=
+github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
+github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
+github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
+github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
+github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
+github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
+github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
+github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
+github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
+github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
+github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
+github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
+github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
+github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
+github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
+github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
+github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
+github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
+github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU=
+github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
+github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
+github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
+github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
+github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo=
+github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
+github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
+github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
+github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
+github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
+github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8=
+github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
+github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
+github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labstack/echo/v5 v5.0.4 h1:ll3I/O8BifjMztj9dD1vx/peZQv8cR2CTUdQK6QxGGc=
+github.com/labstack/echo/v5 v5.0.4/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
+github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
+github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
+github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c=
+github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
+github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mark3labs/mcp-go v0.45.0 h1:s0S8qR/9fWaQ3pHxz7pm1uQ0DrswoSnRIxKIjbiQtkc=
+github.com/mark3labs/mcp-go v0.45.0/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
+github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
+github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU=
+github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
+github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
+github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
+github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
+github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
+github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
+github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
+github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
+github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
+github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
+github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
+github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
+github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
+github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
+github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
+github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
+github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
+github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
+github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI=
+github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
+github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
+github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
+github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
+github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
+github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
+github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
+github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
+github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
+github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
+github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
+github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
+github.com/testcontainers/testcontainers-go v0.41.0 h1:mfpsD0D36YgkxGj2LrIyxuwQ9i2wCKAD+ESsYM1wais=
+github.com/testcontainers/testcontainers-go v0.41.0/go.mod h1:pdFrEIfaPl24zmBjerWTTYaY0M6UHsqA1YSvsoU40MI=
+github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0 h1:5rwejaJr5nIfw8NK99eKPX7O6k27lnSMklTj5DbYybM=
+github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0/go.mod h1:iMO/aFWnbjYkqHw8VPsJB3rVTOD9hKDsUtV0PvzD0DA=
+github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 h1:AOtFXssrDlLm84A2sTTR/AhvJiYbrIuCO59d+Ro9Tb0=
+github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0/go.mod h1:k2a09UKhgSp6vNpliIY0QSgm4Hi7GXVTzWvWgUemu/8=
+github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
+github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
+github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
+github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
+github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
+github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
+github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
+github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
+github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
+github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
+github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
+github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
+go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c=
+go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0 h1:inYW9ZhgqiDqh6BioM7DVHHzEGVq76Db5897WLGZ5Go=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0/go.mod h1:Izur+Wt8gClgMJqO/cZ8wdeeMryJ/xxiOVgFSSfpDTY=
+go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ=
+go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps=
+go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8=
+go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90=
+go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
+go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
+go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0=
+go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis=
+go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
+go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
+go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
+golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
+golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
+golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
+golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
+golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4=
+golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c=
+golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
+golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
+golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
+golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
+golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
+golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
+golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
+golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
+golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
+golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
+golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
+golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE=
+google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw=
+google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d h1:RdWlPmVySdTF0IBIZzvZJvSD0ZocPBNUsnE+uGBxj+4=
+google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d/go.mod h1:X2gu9Qwng7Nn009s/r3RUxqkzQNqOrAy79bluY7ojIg=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c h1:xgCzyF2LFIO/0X2UAoVRiXKU5Xg6VjToG4i2/ecSswk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
+google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
+google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
+gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
+modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
+modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
+modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
+modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM=
+modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
+modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
+modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
+modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
+modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
+modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
+modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
+modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
+modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
+modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
+modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
+modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
+modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
+modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
+modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
+modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
+modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
+modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
+modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
+modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
+modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
+modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
+modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
+modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
diff --git a/internal/base/resource_name.go b/internal/base/resource_name.go
index 828bfa366..504faec43 100644
--- a/internal/base/resource_name.go
+++ b/internal/base/resource_name.go
@@ -1,7 +1,7 @@
-package base
-
-import "regexp"
-
-var (
- UIDMatcher = regexp.MustCompile("^[a-zA-Z0-9]([a-zA-Z0-9-]{0,30}[a-zA-Z0-9])?$")
-)
+package base
+
+import "regexp"
+
+var (
+ UIDMatcher = regexp.MustCompile("^[a-zA-Z0-9]([a-zA-Z0-9-]{0,30}[a-zA-Z0-9])?$")
+)
diff --git a/internal/base/resource_name_test.go b/internal/base/resource_name_test.go
index cef922ac0..76bddf37f 100644
--- a/internal/base/resource_name_test.go
+++ b/internal/base/resource_name_test.go
@@ -1,35 +1,35 @@
-package base
-
-import (
- "testing"
-)
-
-func TestUIDMatcher(t *testing.T) {
- tests := []struct {
- input string
- expected bool
- }{
- {"", false},
- {"-abc123", false},
- {"012345678901234567890123456789", true},
- {"1abc-123", true},
- {"A123B456C789", true},
- {"a", true},
- {"ab", true},
- {"a*b&c", false},
- {"a--b", true},
- {"a-1b-2c", true},
- {"a1234567890123456789012345678901", true},
- {"abc123", true},
- {"abc123-", false},
- }
-
- for _, test := range tests {
- t.Run(test.input, func(*testing.T) {
- result := UIDMatcher.MatchString(test.input)
- if result != test.expected {
- t.Errorf("For input '%s', expected %v but got %v", test.input, test.expected, result)
- }
- })
- }
-}
+package base
+
+import (
+ "testing"
+)
+
+func TestUIDMatcher(t *testing.T) {
+ tests := []struct {
+ input string
+ expected bool
+ }{
+ {"", false},
+ {"-abc123", false},
+ {"012345678901234567890123456789", true},
+ {"1abc-123", true},
+ {"A123B456C789", true},
+ {"a", true},
+ {"ab", true},
+ {"a*b&c", false},
+ {"a--b", true},
+ {"a-1b-2c", true},
+ {"a1234567890123456789012345678901", true},
+ {"abc123", true},
+ {"abc123-", false},
+ }
+
+ for _, test := range tests {
+ t.Run(test.input, func(*testing.T) {
+ result := UIDMatcher.MatchString(test.input)
+ if result != test.expected {
+ t.Errorf("For input '%s', expected %v but got %v", test.input, test.expected, result)
+ }
+ })
+ }
+}
diff --git a/internal/profile/profile.go b/internal/profile/profile.go
index 30579a313..fddeb96cb 100644
--- a/internal/profile/profile.go
+++ b/internal/profile/profile.go
@@ -1,107 +1,107 @@
-package profile
-
-import (
- "fmt"
- "log/slog"
- "os"
- "path/filepath"
- "runtime"
- "strings"
-
- "github.com/pkg/errors"
-)
-
-// Profile is the configuration to start main server.
-type Profile struct {
- // Demo indicates if the server is in demo mode
- Demo bool
- // Addr is the binding address for server
- Addr string
- // Port is the binding port for server
- Port int
- // UNIXSock is the IPC binding path. Overrides Addr and Port
- UNIXSock string
- // Data is the data directory
- Data string
- // DSN points to where memos stores its own data
- DSN string
- // Driver is the database driver
- // sqlite, mysql
- Driver string
- // Version is the current version of server
- Version string
- // InstanceURL is the url of your memos instance.
- InstanceURL string
-}
-
-func checkDataDir(dataDir string) (string, error) {
- // Convert to absolute path if relative path is supplied.
- if !filepath.IsAbs(dataDir) {
- // Use current working directory, not the binary's directory
- // This ensures we use the actual working directory where the process runs
- absDir, err := filepath.Abs(dataDir)
- if err != nil {
- return "", err
- }
- dataDir = absDir
- }
-
- // Trim trailing \ or / in case user supplies
- dataDir = strings.TrimRight(dataDir, "\\/")
- if _, err := os.Stat(dataDir); err != nil {
- return "", errors.Wrapf(err, "unable to access data folder %s", dataDir)
- }
- return dataDir, nil
-}
-
-func (p *Profile) Validate() error {
- // Set default data directory if not specified
- if p.Data == "" {
- if runtime.GOOS == "windows" {
- p.Data = filepath.Join(os.Getenv("ProgramData"), "memos")
- } else {
- // On Linux/macOS, check if /var/opt/memos exists and is writable (Docker scenario)
- if info, err := os.Stat("/var/opt/memos"); err == nil && info.IsDir() {
- // Check if we can write to this directory
- testFile := filepath.Join("/var/opt/memos", ".write-test")
- if err := os.WriteFile(testFile, []byte("test"), 0600); err == nil {
- os.Remove(testFile)
- p.Data = "/var/opt/memos"
- } else {
- // /var/opt/memos exists but is not writable, use current directory
- slog.Warn("/var/opt/memos is not writable, using current directory")
- p.Data = "."
- }
- } else {
- // /var/opt/memos doesn't exist, use current directory (local development)
- p.Data = "."
- }
- }
- }
-
- // Create data directory if it doesn't exist
- if _, err := os.Stat(p.Data); os.IsNotExist(err) {
- if err := os.MkdirAll(p.Data, 0770); err != nil {
- slog.Error("failed to create data directory", slog.String("data", p.Data), slog.String("error", err.Error()))
- return err
- }
- }
-
- dataDir, err := checkDataDir(p.Data)
- if err != nil {
- slog.Error("failed to check dsn", slog.String("data", dataDir), slog.String("error", err.Error()))
- return err
- }
-
- p.Data = dataDir
- if p.Driver == "sqlite" && p.DSN == "" {
- mode := "prod"
- if p.Demo {
- mode = "demo"
- }
- dbFile := fmt.Sprintf("memos_%s.db", mode)
- p.DSN = filepath.Join(dataDir, dbFile)
- }
-
- return nil
-}
+package profile
+
+import (
+ "fmt"
+ "log/slog"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+
+ "github.com/pkg/errors"
+)
+
+// Profile is the configuration to start main server.
+type Profile struct {
+ // Demo indicates if the server is in demo mode
+ Demo bool
+ // Addr is the binding address for server
+ Addr string
+ // Port is the binding port for server
+ Port int
+ // UNIXSock is the IPC binding path. Overrides Addr and Port
+ UNIXSock string
+ // Data is the data directory
+ Data string
+ // DSN points to where memos stores its own data
+ DSN string
+ // Driver is the database driver
+ // sqlite, mysql
+ Driver string
+ // Version is the current version of server
+ Version string
+ // InstanceURL is the url of your memos instance.
+ InstanceURL string
+}
+
+func checkDataDir(dataDir string) (string, error) {
+ // Convert to absolute path if relative path is supplied.
+ if !filepath.IsAbs(dataDir) {
+ // Use current working directory, not the binary's directory
+ // This ensures we use the actual working directory where the process runs
+ absDir, err := filepath.Abs(dataDir)
+ if err != nil {
+ return "", err
+ }
+ dataDir = absDir
+ }
+
+ // Trim trailing \ or / in case user supplies
+ dataDir = strings.TrimRight(dataDir, "\\/")
+ if _, err := os.Stat(dataDir); err != nil {
+ return "", errors.Wrapf(err, "unable to access data folder %s", dataDir)
+ }
+ return dataDir, nil
+}
+
+func (p *Profile) Validate() error {
+ // Set default data directory if not specified
+ if p.Data == "" {
+ if runtime.GOOS == "windows" {
+ p.Data = filepath.Join(os.Getenv("ProgramData"), "memos")
+ } else {
+ // On Linux/macOS, check if /var/opt/memos exists and is writable (Docker scenario)
+ if info, err := os.Stat("/var/opt/memos"); err == nil && info.IsDir() {
+ // Check if we can write to this directory
+ testFile := filepath.Join("/var/opt/memos", ".write-test")
+ if err := os.WriteFile(testFile, []byte("test"), 0600); err == nil {
+ os.Remove(testFile)
+ p.Data = "/var/opt/memos"
+ } else {
+ // /var/opt/memos exists but is not writable, use current directory
+ slog.Warn("/var/opt/memos is not writable, using current directory")
+ p.Data = "."
+ }
+ } else {
+ // /var/opt/memos doesn't exist, use current directory (local development)
+ p.Data = "."
+ }
+ }
+ }
+
+ // Create data directory if it doesn't exist
+ if _, err := os.Stat(p.Data); os.IsNotExist(err) {
+ if err := os.MkdirAll(p.Data, 0770); err != nil {
+ slog.Error("failed to create data directory", slog.String("data", p.Data), slog.String("error", err.Error()))
+ return err
+ }
+ }
+
+ dataDir, err := checkDataDir(p.Data)
+ if err != nil {
+ slog.Error("failed to check dsn", slog.String("data", dataDir), slog.String("error", err.Error()))
+ return err
+ }
+
+ p.Data = dataDir
+ if p.Driver == "sqlite" && p.DSN == "" {
+ mode := "prod"
+ if p.Demo {
+ mode = "demo"
+ }
+ dbFile := fmt.Sprintf("memos_%s.db", mode)
+ p.DSN = filepath.Join(dataDir, dbFile)
+ }
+
+ return nil
+}
diff --git a/internal/util/util.go b/internal/util/util.go
index cdb211fb6..6091c30ab 100644
--- a/internal/util/util.go
+++ b/internal/util/util.go
@@ -1,73 +1,73 @@
-package util //nolint:revive // util namespace is intentional for shared helpers
-
-import (
- "crypto/rand"
- "math/big"
- "net/mail"
- "strconv"
- "strings"
-
- "github.com/google/uuid"
-)
-
-// ConvertStringToInt32 converts a string to int32.
-func ConvertStringToInt32(src string) (int32, error) {
- parsed, err := strconv.ParseInt(src, 10, 32)
- if err != nil {
- return 0, err
- }
- return int32(parsed), nil
-}
-
-// HasPrefixes returns true if the string s has any of the given prefixes.
-func HasPrefixes(src string, prefixes ...string) bool {
- for _, prefix := range prefixes {
- if strings.HasPrefix(src, prefix) {
- return true
- }
- }
- return false
-}
-
-// ValidateEmail validates the email.
-func ValidateEmail(email string) bool {
- if _, err := mail.ParseAddress(email); err != nil {
- return false
- }
- return true
-}
-
-func GenUUID() string {
- return uuid.New().String()
-}
-
-var letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
-
-// RandomString returns a random string with length n.
-func RandomString(n int) (string, error) {
- var sb strings.Builder
- sb.Grow(n)
- for i := 0; i < n; i++ {
- // The reason for using crypto/rand instead of math/rand is that
- // the former relies on hardware to generate random numbers and
- // thus has a stronger source of random numbers.
- randNum, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
- if err != nil {
- return "", err
- }
- if _, err := sb.WriteRune(letters[randNum.Uint64()]); err != nil {
- return "", err
- }
- }
- return sb.String(), nil
-}
-
-// ReplaceString replaces all occurrences of old in slice with new.
-func ReplaceString(slice []string, old, new string) []string {
- for i, s := range slice {
- if s == old {
- slice[i] = new
- }
- }
- return slice
-}
+package util //nolint:revive // util namespace is intentional for shared helpers
+
+import (
+ "crypto/rand"
+ "math/big"
+ "net/mail"
+ "strconv"
+ "strings"
+
+ "github.com/google/uuid"
+)
+
+// ConvertStringToInt32 converts a string to int32.
+func ConvertStringToInt32(src string) (int32, error) {
+ parsed, err := strconv.ParseInt(src, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return int32(parsed), nil
+}
+
+// HasPrefixes returns true if the string s has any of the given prefixes.
+func HasPrefixes(src string, prefixes ...string) bool {
+ for _, prefix := range prefixes {
+ if strings.HasPrefix(src, prefix) {
+ return true
+ }
+ }
+ return false
+}
+
+// ValidateEmail validates the email.
+func ValidateEmail(email string) bool {
+ if _, err := mail.ParseAddress(email); err != nil {
+ return false
+ }
+ return true
+}
+
+func GenUUID() string {
+ return uuid.New().String()
+}
+
+var letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
+
+// RandomString returns a random string with length n.
+func RandomString(n int) (string, error) {
+ var sb strings.Builder
+ sb.Grow(n)
+ for i := 0; i < n; i++ {
+ // The reason for using crypto/rand instead of math/rand is that
+ // the former relies on hardware to generate random numbers and
+ // thus has a stronger source of random numbers.
+ randNum, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
+ if err != nil {
+ return "", err
+ }
+ if _, err := sb.WriteRune(letters[randNum.Uint64()]); err != nil {
+ return "", err
+ }
+ }
+ return sb.String(), nil
+}
+
+// ReplaceString replaces all occurrences of old in slice with new.
+func ReplaceString(slice []string, old, new string) []string {
+ for i, s := range slice {
+ if s == old {
+ slice[i] = new
+ }
+ }
+ return slice
+}
diff --git a/internal/util/util_test.go b/internal/util/util_test.go
index 9dbdd34b3..d8ee5f83d 100644
--- a/internal/util/util_test.go
+++ b/internal/util/util_test.go
@@ -1,31 +1,31 @@
-package util //nolint:revive // util is an appropriate package name for utility functions
-
-import (
- "testing"
-)
-
-func TestValidateEmail(t *testing.T) {
- tests := []struct {
- email string
- want bool
- }{
- {
- email: "t@gmail.com",
- want: true,
- },
- {
- email: "@usememos.com",
- want: false,
- },
- {
- email: "1@gmail",
- want: true,
- },
- }
- for _, test := range tests {
- result := ValidateEmail(test.email)
- if result != test.want {
- t.Errorf("Validate Email %s: got result %v, want %v.", test.email, result, test.want)
- }
- }
-}
+package util //nolint:revive // util is an appropriate package name for utility functions
+
+import (
+ "testing"
+)
+
+func TestValidateEmail(t *testing.T) {
+ tests := []struct {
+ email string
+ want bool
+ }{
+ {
+ email: "t@gmail.com",
+ want: true,
+ },
+ {
+ email: "@usememos.com",
+ want: false,
+ },
+ {
+ email: "1@gmail",
+ want: true,
+ },
+ }
+ for _, test := range tests {
+ result := ValidateEmail(test.email)
+ if result != test.want {
+ t.Errorf("Validate Email %s: got result %v, want %v.", test.email, result, test.want)
+ }
+ }
+}
diff --git a/internal/version/version.go b/internal/version/version.go
index 685f0c979..64d0a82aa 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -1,54 +1,54 @@
-package version
-
-import (
- "fmt"
- "strings"
-
- "golang.org/x/mod/semver"
-)
-
-// Version is the service current released version.
-// Semantic versioning: https://semver.org/
-var Version = "0.27.0"
-
-func GetCurrentVersion() string {
- return Version
-}
-
-// GetMinorVersion extracts the minor version (e.g., "0.25") from a full version string (e.g., "0.25.1").
-// Returns the minor version string or empty string if the version format is invalid.
-// Version format should be "major.minor.patch" (e.g., "0.25.1").
-func GetMinorVersion(version string) string {
- versionList := strings.Split(version, ".")
- if len(versionList) < 2 {
- return ""
- }
- // Return major.minor only (first two components)
- return versionList[0] + "." + versionList[1]
-}
-
-// IsVersionGreaterOrEqualThan returns true if version is greater than or equal to target.
-func IsVersionGreaterOrEqualThan(version, target string) bool {
- return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > -1
-}
-
-// IsVersionGreaterThan returns true if version is greater than target.
-func IsVersionGreaterThan(version, target string) bool {
- return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > 0
-}
-
-type SortVersion []string
-
-func (s SortVersion) Len() int {
- return len(s)
-}
-
-func (s SortVersion) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-
-func (s SortVersion) Less(i, j int) bool {
- v1 := fmt.Sprintf("v%s", s[i])
- v2 := fmt.Sprintf("v%s", s[j])
- return semver.Compare(v1, v2) == -1
-}
+package version
+
+import (
+ "fmt"
+ "strings"
+
+ "golang.org/x/mod/semver"
+)
+
+// Version is the service current released version.
+// Semantic versioning: https://semver.org/
+var Version = "0.27.0"
+
+func GetCurrentVersion() string {
+ return Version
+}
+
+// GetMinorVersion extracts the minor version (e.g., "0.25") from a full version string (e.g., "0.25.1").
+// Returns the minor version string or empty string if the version format is invalid.
+// Version format should be "major.minor.patch" (e.g., "0.25.1").
+func GetMinorVersion(version string) string {
+ versionList := strings.Split(version, ".")
+ if len(versionList) < 2 {
+ return ""
+ }
+ // Return major.minor only (first two components)
+ return versionList[0] + "." + versionList[1]
+}
+
+// IsVersionGreaterOrEqualThan returns true if version is greater than or equal to target.
+func IsVersionGreaterOrEqualThan(version, target string) bool {
+ return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > -1
+}
+
+// IsVersionGreaterThan returns true if version is greater than target.
+func IsVersionGreaterThan(version, target string) bool {
+ return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > 0
+}
+
+type SortVersion []string
+
+func (s SortVersion) Len() int {
+ return len(s)
+}
+
+func (s SortVersion) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s SortVersion) Less(i, j int) bool {
+ v1 := fmt.Sprintf("v%s", s[i])
+ v2 := fmt.Sprintf("v%s", s[j])
+ return semver.Compare(v1, v2) == -1
+}
diff --git a/internal/version/version_test.go b/internal/version/version_test.go
index 0222748d2..8d23ea96a 100644
--- a/internal/version/version_test.go
+++ b/internal/version/version_test.go
@@ -1,106 +1,106 @@
-package version
-
-import (
- "slices"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "golang.org/x/mod/semver"
-)
-
-func TestIsVersionGreaterOrEqualThan(t *testing.T) {
- tests := []struct {
- version string
- target string
- want bool
- }{
- {
- version: "0.9.1",
- target: "0.9.1",
- want: true,
- },
- {
- version: "0.10.0",
- target: "0.9.1",
- want: true,
- },
- {
- version: "0.9.0",
- target: "0.9.1",
- want: false,
- },
- }
- for _, test := range tests {
- result := IsVersionGreaterOrEqualThan(test.version, test.target)
- if result != test.want {
- t.Errorf("got result %v, want %v.", result, test.want)
- }
- }
-}
-
-func TestIsVersionGreaterThan(t *testing.T) {
- tests := []struct {
- version string
- target string
- want bool
- }{
- {
- version: "0.9.1",
- target: "0.9.1",
- want: false,
- },
- {
- version: "0.10.0",
- target: "0.8.0",
- want: true,
- },
- {
- version: "0.23",
- target: "0.22",
- want: true,
- },
- {
- version: "0.8.0",
- target: "0.10.0",
- want: false,
- },
- {
- version: "0.9.0",
- target: "0.9.1",
- want: false,
- },
- {
- version: "0.22",
- target: "0.22",
- want: false,
- },
- }
- for _, test := range tests {
- result := IsVersionGreaterThan(test.version, test.target)
- if result != test.want {
- t.Errorf("got result %v, want %v.", result, test.want)
- }
- }
-}
-
-func TestSortVersion(t *testing.T) {
- tests := []struct {
- versionList []string
- want []string
- }{
- {
- versionList: []string{"0.9.1", "0.10.0", "0.8.0"},
- want: []string{"0.8.0", "0.9.1", "0.10.0"},
- },
- {
- versionList: []string{"1.9.1", "0.9.1", "0.10.0", "0.8.0"},
- want: []string{"0.8.0", "0.9.1", "0.10.0", "1.9.1"},
- },
- }
- for _, test := range tests {
- slices.SortFunc(test.versionList, func(a, b string) int {
- return semver.Compare("v"+a, "v"+b)
- })
- assert.Equal(t, test.versionList, test.want)
- }
-}
+package version
+
+import (
+ "slices"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "golang.org/x/mod/semver"
+)
+
+func TestIsVersionGreaterOrEqualThan(t *testing.T) {
+ tests := []struct {
+ version string
+ target string
+ want bool
+ }{
+ {
+ version: "0.9.1",
+ target: "0.9.1",
+ want: true,
+ },
+ {
+ version: "0.10.0",
+ target: "0.9.1",
+ want: true,
+ },
+ {
+ version: "0.9.0",
+ target: "0.9.1",
+ want: false,
+ },
+ }
+ for _, test := range tests {
+ result := IsVersionGreaterOrEqualThan(test.version, test.target)
+ if result != test.want {
+ t.Errorf("got result %v, want %v.", result, test.want)
+ }
+ }
+}
+
+func TestIsVersionGreaterThan(t *testing.T) {
+ tests := []struct {
+ version string
+ target string
+ want bool
+ }{
+ {
+ version: "0.9.1",
+ target: "0.9.1",
+ want: false,
+ },
+ {
+ version: "0.10.0",
+ target: "0.8.0",
+ want: true,
+ },
+ {
+ version: "0.23",
+ target: "0.22",
+ want: true,
+ },
+ {
+ version: "0.8.0",
+ target: "0.10.0",
+ want: false,
+ },
+ {
+ version: "0.9.0",
+ target: "0.9.1",
+ want: false,
+ },
+ {
+ version: "0.22",
+ target: "0.22",
+ want: false,
+ },
+ }
+ for _, test := range tests {
+ result := IsVersionGreaterThan(test.version, test.target)
+ if result != test.want {
+ t.Errorf("got result %v, want %v.", result, test.want)
+ }
+ }
+}
+
+func TestSortVersion(t *testing.T) {
+ tests := []struct {
+ versionList []string
+ want []string
+ }{
+ {
+ versionList: []string{"0.9.1", "0.10.0", "0.8.0"},
+ want: []string{"0.8.0", "0.9.1", "0.10.0"},
+ },
+ {
+ versionList: []string{"1.9.1", "0.9.1", "0.10.0", "0.8.0"},
+ want: []string{"0.8.0", "0.9.1", "0.10.0", "1.9.1"},
+ },
+ }
+ for _, test := range tests {
+ slices.SortFunc(test.versionList, func(a, b string) int {
+ return semver.Compare("v"+a, "v"+b)
+ })
+ assert.Equal(t, test.versionList, test.want)
+ }
+}
diff --git a/memos_prod.db b/memos_prod.db
new file mode 100644
index 0000000000000000000000000000000000000000..159e90adb13561c0365c22e76084c658383a62f1
GIT binary patch
literal 4096
zcmWFz^vNtqRY=P(%1ta$FlG>7U}9o$P*7lCU|@t|AVoG{WYFvV#S79dK(-m98b?E5
nGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nC=3Arqf-Z%
literal 0
HcmV?d00001
diff --git a/memos_prod.db-shm b/memos_prod.db-shm
new file mode 100644
index 0000000000000000000000000000000000000000..ad56e3d1518a97455c9c74ddb8980f0fdb0e32c7
GIT binary patch
literal 32768
zcmeI*$8OY66o>JTWYPnKgc5r1Frn9w&>TL#uOHvP
znHZ~%f9e0n{#fcqrFE;3Z@=p2zrTOu*)&C(Bb7)?q&3nOX^(V7IwM_??#T4WjL6JL
zPh?i4H_{iG9hnoE8<`hL^JHtMW4-m$v$AKTXV&I#*J}G}&uj0=-Z{ITu4V7~=Xv%H
z***2v`JeuaQ7i=%P(T3%6i`3`1r$&~0R-Q3tQR7c6P9j{aLF=
z1qvq6&a#3{)FK-PI8(HjB}F-9`Y>j0`@7;umYW|WCOc7$_Qt;$W?AJ
z$s?XO>_on}0(k|x*uybSah6M5<2Ltr%v9c+?Ngwk1-jYGaYi}EWv+9F`#d4-$zdr_
ze1WuEjHN(11=2oAmICDzNIQgC3Y1eI?Tu$CP)>ogE2O1BIR$z-z`=5k?$o6h=wpaO
YrB@K3oC0YNY)gT13Z&iNtvmwX0V;n$p#T5?
literal 0
HcmV?d00001
diff --git a/memos_prod.db-wal b/memos_prod.db-wal
new file mode 100644
index 0000000000000000000000000000000000000000..63af6c02669a0eff2cc5087a0fb102af05850e34
GIT binary patch
literal 453232
zcmeI*3w&HP*Q4w8HZp*&!^PI`tl9`lV
zXfFMo<|Jp%{rR5foSFIeIsfClvhZMz>G^YVa?Z$+-G)b6o*7+x@oV>)k8JVxe9I?B
z=~BnP_v*j&|G$U+>(%ZpZGot291Mj=m8j7smd?%1dB4#p=FJtoSYM(m6+`)nS5xat
zd7Wu6H)qYq-zX4MbcQ$O^m7bvF8O)crKJ;Pl|_Fn?bQFK=z)SO_4nti1^s#Ly5Hr!
zTlb*u!AvV+T$+IG?81tsmAafj(68=|>>3fra6lQ4hP2lMqv~jAATq3k)d5R#c-cYI
znfi(qD|ClUQN=r=hE>HE4TOU6zh}9-JoP;uV^4iUo5vU*Yg}DkVl)Q)#+HsAPm`z1
z*xA+6Uf;FN*y`D4tncmF+|nVIYxi{Y)W{iqV!5d5ABaYb4J}P#8Dqz0(f78s88>wDXJjH@Hj@L)7Bs;;hD6{)H*Rs}&!G-ZPclCji{ocWM>VlJ~gm=mKh>ZB|09-U^=QsBFfM-
z?Zlz3+PA+-Kpq%dqOVxGRCiTV%*8(z@Q)eNP5fiWC^A014j5y{SE~v^Wpvs;X`{1L
zjDTO%slZ@B01O63qG~w3pvmG?#Vg@pU?|%>u_CWB6jr#FW~)1*_yZR4>x@ITGJVC$
zmAb1fnv4>SD!$=Su{X(~@-(O9_>;+%JS7sRdHQL0VrTXEnEymB3gVckGY{zWqv9P2
zd5sNin;Q}nVNv}vTyYW$Pi-Nr
z4vH&o&^N7GPM>W|nHUKv)2?pGnPQd8RzBO+KUqZvEXm;|2U<$>6;)NbgIlz!rj;hF
zjwtdiAniqIT7^rS6svR7AQD%2O+;IzcmtSqrYz^-)CGEKQF%ocyO&&7jZrQqugtE}
z!ix5)Y-d;6E>FD!#!Fgu=&~Yx#j<6(YnCS%8qr2JTZZ)n>
zncmW2TwT?%xvRatO}=y2ce$Hewt6;-x9?;fjZfA-4#eJHvt27=C*STsB;XB*&oC3y
z=9}7n%5-h}oxKfhEpEB}&aTZp9(Rw}0qsT0R`K~IZC}KP6>XeWHOB(Mpql(36Tia6
ziJOAI-saaKASh0TDtTj{nNLF&-!a{w;s#Us!2CW{BN5q>?M2$uR
z!J*V)eOkRtof4~`+L+`;Dg9jBsZJBs7N9FY-8C*Rg413Wrj>Hq#MScJUn7>RKC~uJJ9n?X
zBw;4En4h+^9CM84?g@TqJ;ArPl+!EiGi|(Hrc6K9(@$Dtc;`&{pcD>`OsfmY6S=qB
z(-k{I)lnrdGVSDyf1ICse+veDJ2Px*+FWBwB(f(I_74mzk>T_eYIRWAtwfdZzqI1~j>gZ&NZPC1
zwAz+FEmrSlGR%73y`8e8o}hB|^2A)9TUfEVI@^hvzGDNH^w)W@Zu~32>qC)@y1Q0*~0R#|0009ILKmdWoDWJs&;_V0?e5?9_x6b>@
z<0Z1J#03`T5vNoLAbo%;xq
zKnx*(00IagfB*srAb8AzkmM^K7Zul
zA=(Qhffzyn0R#|0009ILKmY**5I|rN3usLP;&FlZeX272+aLbNb+i{)#7CT>A%Fk^
z2q1s}0tg_000IagkQ7)V2jg*pQs*tdH$A+wj`jjcAchb?009ILKmY**5I_I{1Q1xn
z0tQ*OcwFH63qEl7weE+8XfLpck2pm`009ILKmY**5I_I{1Q0+VDR71yjK>8W6%{qV
zc;Mi3v=>MMF@yjD2q1s}0tg_000IagfWRUaI8&A_9v8Uy;`ZMMF@yjD2q1s}0tg_000IagfWRUaSSHIBj|(Vw9NBU316%%q_5zFe
zh*LBK5I_I{1Q0*~0R#|0009J&0`HQ8@wmW!+s6u@{I~9(l()zQ#EWLOEO44v)n^3?Zuj6L-YZ60HC4&&FBAE3yde1=<)RT$b~yL_ZT~R+uDr19W7gWJ=$#Ac4D)}
z*BhTro9+v%N;DK65VK^TuKEX}5o1G3lb9uCGaEgP^}TI9#?_H%crY3mRaaN7id5AY
ztAe3DRn^tn`qjN-fv_4$T|T~;+*NI!#?4)xmZlD^psS~LxZ2p|Y4mh?I^3Ra4QqA4
zUv1pnVch6x^9V(EeYd-Qqo=&2T7Q4u<4r4dIf0;G-5c385{Rk;%6K%Sy&gz94_K1J
z%MO~()K{!np*v*Kj+a32MFXK={O?(5$0|NHairo>vmYUiHjOSWFA8yVxuYJLP%x?n
zqw>gU6(GKHjWoW?1JQ{wHN*5+4OyMsMvc*zSYM4XZSiUiIoIc2kqtR9yCpuf^x(2H
z^c58qxA5RaBJh6+W!`)WGgpW{58KisC_~e<
z6NkEL-~K8Ad0=dbzGCT8-BnF77ynqmKW0cb@sAy&h`bi0)q&J2Ku{T-woh6O$x<-_
zeo?0ag8>0B7#NAF;b|+5*W9WqZ7rhG3%@Zr~Dnns~YiYK+BZ@y@5x>qjWGmAy
zp;ucp86_H3e8Zz+Z<0ghX->)UCzC6AO1#|*V*JEQ9O~JwhvQ>@C3^f91#wK&nFlnn
z<*B3M9SM1j4Q-nn5)%^F+L?zvG0)V(k-(%nqv(m5%-Ug(zpG4L2(@t$@iro=e}*eg
zV&SPRgw;VctOkA4s^#?A#*~SXkTShyCn{j9av5IBab&;xC#%SSB{{t0Kud|fqN+-F
zaEn&ew98@FxV36|{&nWcibAE+Gdj>LH
z;EnEPkGs{lI%RrGhjDdP$L6l~`ZoEQr@qVG+_KfPQGD=8R^<3(`GIZf{WaUQGIl-P
z9f$O&x8K>dxyR$~5j&v0XxS=0Yo_gs_^_gl)2i24
zAQ)6YX`l)6U)mef~8odtyz7hR;=rj>8%GipTLH7+lL(_R*)m2%p|)$-b3BbKZ_v?fnG
zcdx!AVJ5ejpSH9dbByQi34Ulj!MC@R(<}Y+%!!|V(jvnf_olW*
zoNCvh{n6TqR!sd@T1&@9PrqmlnrUv?{4u#iqNSwm?81udO<q&I-1!RlN!SY3No
zVa2hvrKGW{XwLlh8>`axbgCVAqQ${6HN-p(o2c5#XS;+ZTMnkRA{1|Fx$|qDWUCsEh+8iz*HxO=Sel+#Z_=h
zg8%{uAbr>2wN}ai~#yDGhfqdx^zmMQYPwLdzo%F6>sZdxPz*n?go<3mbV@ydrO
zSZnJywzqU#U{x-#m@jB`weGPgo1CNL6P`7Vb(3Rz$A-6#Z&MnZ+%0=u?p^(D+nTrg
zb~%UoJ6dXMJDaxjjSRVkQ-QRK#|5ryHhJ$d=YBnQAHmBxhL;z#Bs-4)0tg_000Iag
zfB*srAbm*H+Oj&yFA^^13jBtJssWqD#PkvSd9$#gm$XINaeaq_fgBB%lVP
zEy2N1<+^>9@~d+FkQgDh)E=4)jEpF29c#?S)qUbYt)V>;V@HqCVqRljZxkbH?dy$u
zYwgv>`mwPQwNLf72BK>nHs=~!t#Ng0b5DC)jd3KfQ#CfJzMY|JqkA|U8dcX??6qse
zD#Tj5l|dyOh%e&t4<)C`f&|9u{eDqy!B%Mzj}MRwS>y!2x;x-gdnU$IF~zS&c1A;E
za(qb68Q)Wjd96j8+Zz@;u7<@Vu?5wb*nH*w{g=z<5fq6&(O$s1^4U8txozwpWA_of
zlw)}5=!c#;5I_I{1Q0*~0R#|0009ILKwtp~oRwc(U7Q}c5qmA~BS^Ft`1NJ49KQ5>
zKiwzW3*;JpFP>8F6ihuwD2q1s}0tg_000IagfWV><=+u?wxQfN23eI0%
zbdjsA!M$TsbA!9zI%#uRqur6ocAqL9T(DmDv4YU5zm{?_izRTx%P&4w`IsuhnEXdli${tT;>#zr&(B
zymdai!z%OXWzRckbFQ=5*4Uj^v$@XUv>YYxU~+DotJY~I@1T}
zbiEcA;CTe|^xDU6A%Fk^2q1s}0tg_0KumzRz`RO;e>~44ATBT;o=1=t7dV_heB)1U
z{`f~|FTiyc0R#|0009ILKmY**=D)!4#0B^wI>%o`)7uNEiej&|dmSd#?{JvxgAS|7
zTkCL{oMyjW9aJ1Xo6A0XdjW@io!Pv`VXL**xvaHyM`nKmY**5I_I{1P~xDu;AMZ5Eq!^FpYK}LE3W)mFuqB
zko!RGQW+P>HM}IBQ}`0s8UzqP009ILKmY**5I_I{1Q1vR0!896g*y3|!rZLSDYVa*|)p9w=ZzyutoNgDS6h7xXXYEs4g1?r}DaoeIcb$*k}
zTxT(PEe^lcWp~;K&5qgf4%V$R*R8X<*3_CU4ztr~uAMdSVCvk?I;+dda|&lZr|`!;
zANaxg(p&SixB$;7JcZXYHiZBJ2q1s}0tg_000PG@KwMzK=N%+2Fvnq8@_M~ylh@@P^ws&jR>fzXy}f|dvd(5-&)g_yN&h&
zGvflk+Vbh&-uaJ@JxhCmQ++*Sdk7$a00IagfB*srAaLvg#03_7djaACa~!6b85dak
z?SuQa+fC!N7dZAS5=$U}00IagfB*srAb`NB7C4@`0AEDs_={+IdjX5;Fk9-(s%cQQ
znoV}qZ!;-%s?FqZsSc;l@AnNlEwi^5usPS+ENg5|r`>9;wOEdlUm!VmU7gcvr@g?;
zxWFBM{hnLj{N%e=(q7HyEiIZdwGI-g0j9#E|!V}RFZJ4$;2hk2d7c8$g9vf3@qx})V6NY3qYxtu(YVE@dx
zz@t}w?QatPxWF8TX=cU+Ui^t=
z?ehP4d@bz-j{SahfbHi=)m_YqL6hv$hv-tuxok_5!s|r`2II+Z?mz7f6}gW_7ykF7gY^
zj0^l~UqR2Me;9s~_5!E+ddBt;KmY**5I_I{1Q0;r*ae6SEco^U#0BO!OrymG3gx-C
z;gObSM%P~a+Gkh(_{Q&!-)59?fn38&IfhroFFFJeKmY**5I_I{1Q0*~0R#|O_yR?_
zdCPR8>S!oWughCjJRVWQqEN-MVDY%XU+(^!+{U5}Ka+8RJj2;JhPw=xi9d7*Ab)Q
zFPDAC=C1boHl?$xWovzpXJ6%5I5eh)qZ5_u_U+%_nLD+f^Tm3s{e!_Kf8$nnWRtto
z-xr+h+uhyU7dUd*BKz2ShLuE@WsSO&HM-gw+&eZkH@N$)lQx$%+8vo}_o;y+H?5a_
zY>nHLkrBn{Rf9@N<~53gS|a*$;&FjHzWJ96{Hxw7mm~8Gcjp+MFuWlC&>?^T0tg_0
z00IagfB*srAb`L;5I8T-rOOs|
z@(URLm?M7Z5I_I{1Q0*~0R#|0009ILKwz;5lW8;?9G+Y9K33oMqSPB{=j009ILKmY**5I_I{1Q3V`EGZCSf#TG-fL=^U#0Bn~
zyzS;|KQ{0wt-V0m!#U!I4gmxZKmY**5I_I{1Q3{~0>|?_0utcQaRU7G=M*{>#iH73
zZKgrHx7K7A&l)r-KC|6a>#Fq+TFk1?R$EtDW2{v7js?PMq&`}?uF`6@)|$jTR!fiB
zwa#i@XRljhx4RsU+B)meo>Q2Z+v%vQv)Xx1;mqe0e&-`ME&coEzpv2Z0!vzQ#19<;
z2q1s}0tg_000IagFi!=D3oQ8O6cQJh<1o$4=M=uDu`p6UQK!WP@(j;v&nXmt=ny~v
z0R#|0009ILKmY**5I|r73Y6yMttbwwiZ2=n1v5XV@GM!Zc;3PF-#hY(?wVGAEbrix
zIff?}V4>M%1Q0*~0R#|0009ILKmY**PFsN*U13gsvFF^tk^6o=s*Z*tYcoH;;Q3o_
zfBCDQ5KK!&pU5w8{&Sxm{KAX-|0QH?1xEk@1Q0*~0R#|0009ILKw!ZN
zR27KOK=Ip(3lz#i#@h>+dM~yqefR!Wwin1VJQKT*;F$%>z>Xt;00IagfB*srAb&WciW>x$>5dj0$UWZs2-;s<`Ky0<&ixqo5zLRn&0ZjY
z00IagfB*srAbxUnfae@3L
z-_9}IWw^|6wiuv8009ILKmY**5I_I{1Q0-A{tC3_m*%*N^YhO=cX`o88+#Og>(=qz
z!+TuKt!nqKUbTK=R0$k;;J;!i(Pjdn*S+kI-_$W7~IA6w%#Wn@G#dexv(
zl6j5dkjh&I63-*3zxbLTU8n!f&2nVE;f5T;6NVQIHyG}ozlWYZLjVB;5I_I{1Q0*~
z0R#|0V37%&m*>)D4sPVjNtr_xd2&+b=tJ(gd9LEjVFV#pD)r*+1#bOb+v=;X`^mmo
z-ofW{41Y8{zsPhc4gv@ufB*srAb&@By}7;J)6r9|lP~k)
zF9k%I=o9S)4(v>WJkXd``v%o;!`OC@KO7AbTcexy_H~3jeM7r9I{F)%$M-aJhzx;$mVIiLz&&9#sAf)|N8Z7cly~s;H=e%n
zmv4S@t-Oz*z%UulJ2*+^!IM+?^T0tg_000IagfB*srAb`L^5Qya&Ohg6pjxq0G
z@w;Dq^ETVp4v}|oAslS>5dj1cKmY**5I_I{1Q0*~fmsEzdKmY**5I_I{1Q0*~
z0R#|0VEzfj@(Lz`0{JJHcW`Lg(}gR(_QFc?4$i+r%^o3u00IagfB*srAba*q@eDRB4{L-%uzxqBI7tojgS6bdd@sbV!1Q0*~0R#|0009ILKwu#XH0o3G
z1@`yu9p32ai0<9f<=xV?v%Y(KPkpFI-B=2DNcwnf(vnLcda_{A`k8vqk
zvIOR)WC^tP4+fk3ja%K3P3}(ryv;lKi4Rrwe(2UqN9BD4dc(%lyn`FbJh%`~e)bsw
z1Q0*~0R#|0009ILK;WGgkQoFsM_cp@F7M!-q1#`}fBw2r*009IL
zKmY**5I_I{1Q0*~f%za%ULX?<>Jy0uPh#G|4{d0@;=A|Vy-v0lC@|cU$U7(o=@38w
z0R#|0009ILKmY**5I|tA1!8#x6ET5;lbm<(t^Q?O?s@uyP2?S%>jTa95kLR|1Q0*~
z0R#|0009ILIAMV-c?XNK<{d0sQm(t^&sTY6T%f4@mT7qh#RxhC5I_I{1Q0*~0R#|0
z0D)5{&{&j`FVHbGUaJO&Mu$R;jrLugf$)kyn~~PQ2KA#Po)YR
zR>Z%|`2rjBQrNd|>D(J?>e%J8dYrcLMW1)@fA4fu4Lv^kRe2vlk)c}V9jrFIV7S3B
zX&5k&dGOSo`)mmT1Q0*~0R#|0009ILKwy3e$P9v+Lo-E-DevHC{`~oGKDzamOJsY2
zLc<*?c?ZP{Is_0v009ILKmY**5I_I{1Q3`5f$~C`Xs{@eXz-oOJNV)^{&4dKV_17m
zVWHu0O5Q>7f(`)$5I_I{1Q0*~0R#|0009I}tw1cVU?LI)3-78&sVSN5~#
z3ncGgYL>t~VKt~`P8HaiKP7(d@}i42_9*_=t>e3g_qdu{)$U!rYW)Ox2Q$Nosw`6s
zp0nYRmS;xSUi{kgckYN>diERpuG_bNf2S@5&ehi7-m$5S=ig#RxhC5I_I{
z1Q0*~0R#|0009ILIOziAMKaM~Ng~nUT;&~n^ueb-{*{LxyGFJbC^8(FmUmE$phExw
z1Q0*~0R#|0009ILKmdW0ClJdkmueCI0(G*VN{2U;ISCti2Vb8x
zUtnWlN?yk9@%}FN#!c47=E)&tW7BBJwWDF%PLV6{RoTzF9`X+M1twHLou{KosE@4oAjAItUv#fFI)c?ZQPIs_0v
z009ILKmY**5I_I{1Q0k;f%0ORXs|SqXmFn79W4EF`#mpT^}!cpdx2uZt{Hg;#V9%i
z5I_I{1Q0*~0R#|0009ILI9`ERUcp2>pm?6;9lWZ&I(*yMP|J_WkJ
zckl2$0DHJ>(r64-7SU_JjgQ?!8?0F)k%bmcZO8
z_VYzPOl$vOu*u)J)g9U7?)1;wyn{QQyyZ$=^b22?_YssWc{EGjK{0_20R#|0009IL
zKmY**5I_Kdxfalp3ucTbm63NaCHjziZl0^y)z;wNv8lPi-EW;G@8Ii0j*b8Fcfb3-
zY%fq^*pVUcpcqMq00IagfB*srAb>y&ULq3>mL(Dm&d=16.8.0'
+ react-dom: '>=16.8.0'
+
+ react-dom@19.2.4:
+ resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
+ peerDependencies:
+ react: ^19.2.4
+
+ react@19.2.4:
+ resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
+ engines: {node: '>=0.10.0'}
+
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
+snapshots:
+
+ react-colorful@5.6.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+
+ react-dom@19.2.4(react@19.2.4):
+ dependencies:
+ react: 19.2.4
+ scheduler: 0.27.0
+
+ react@19.2.4: {}
+
+ scheduler@0.27.0: {}
diff --git a/node_modules/.pnpm/node_modules/react b/node_modules/.pnpm/node_modules/react
new file mode 120000
index 000000000..f3ed04ceb
--- /dev/null
+++ b/node_modules/.pnpm/node_modules/react
@@ -0,0 +1 @@
+/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/react@19.2.4/node_modules/react/
\ No newline at end of file
diff --git a/node_modules/.pnpm/node_modules/react-dom b/node_modules/.pnpm/node_modules/react-dom
new file mode 120000
index 000000000..379e71009
--- /dev/null
+++ b/node_modules/.pnpm/node_modules/react-dom
@@ -0,0 +1 @@
+/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/
\ No newline at end of file
diff --git a/node_modules/.pnpm/node_modules/scheduler b/node_modules/.pnpm/node_modules/scheduler
new file mode 120000
index 000000000..eff7d0290
--- /dev/null
+++ b/node_modules/.pnpm/node_modules/scheduler
@@ -0,0 +1 @@
+/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/
\ No newline at end of file
diff --git a/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react
new file mode 120000
index 000000000..f3ed04ceb
--- /dev/null
+++ b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react
@@ -0,0 +1 @@
+/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/react@19.2.4/node_modules/react/
\ No newline at end of file
diff --git a/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS
new file mode 100644
index 000000000..235b4c312
--- /dev/null
+++ b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS
@@ -0,0 +1,5 @@
+## Acknowledgements
+
+- Special thanks @RyanChristian4427 who has rewritten the library in TypeScript.
+- In order to avoid tree-shaking problems, and provide better TS support, `rgbToHex` and `hexToRgb` methods were copied from [@swiftcarrot/color-fns](https://github.com/swiftcarrot/color-fns) (MIT License).
+- `hsvToRgb` modified from https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c.
diff --git a/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md
new file mode 100644
index 000000000..8b77466d9
--- /dev/null
+++ b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md
@@ -0,0 +1,257 @@
+### 5.6.1
+
+- Update export settings to fix Jet 28 issues (via #191)
+
+### 5.6.0
+
+- Add new `HexAlphaColorPicker` component (via #186)
+- Fix types export for TYpeScript 4.7. Thanks to @AnotherHermit (via #189)
+- Improve ARIA attribute values for sliders. Thanks to @aitchiss (via #177)
+
+### 5.5.1
+
+- Fix embedding into `