15 Commits

Author SHA1 Message Date
xfy
a6d30ed5d9 refactor(write): address code review feedback
- remove duplicate `use dioxus::prelude::*` (keep #[allow] inline with comment)
- update write_editor doc comment: callback-driven init, EditorHandle::drop cleanup
  (no more polling/globals)
- restore empty-url check in make_upload_closure (match original JS `success && url`):
  empty url on success now rejects with clear message instead of inserting broken image
- update AGENTS.md tiptap section: write.rs uses tiptap_bridge, no eval/polling
2026-06-23 13:32:34 +08:00
xfy
a3ed0a2b4e docs(env): document RATE_LIMIT_COMMENT_* and RATE_LIMIT_UNKNOWN_* vars
rate_limit.rs registers four limiters (strict/upload/image/comment) plus
an "unknown" fallback bucket for when the real client IP can't be
determined, but only the strict/upload/image tiers were listed in
.env.example and AGENTS.md. Add the missing comment and unknown tier
tunables so the documented surface matches the code.
2026-06-22 13:16:34 +08:00
xfy
b24cfdcabc fix(startup): replace migration panic with friendly exit + configurable retry window
DB migration failure at startup panicked via .expect() (main.rs:223),
dumping a raw backtrace for what is usually just "PostgreSQL isn't running
yet". Worse, the 1.6s runtime retry budget was reused at startup, so it
almost always failed against a cold/slow DB (docker-compose without
healthchecks, local Postgres not started, etc.).

Changes:
- pool: extract build_pg_config() (returns Result, no panic); add
  validate_database_url() so URL-format / DB_POOL_SIZE errors surface as
  friendly exit(1) instead of hitting the LazyLock's unreachable .expect()
- pool: add get_conn_for_startup() — a startup-only retry loop with a
  configurable total-duration window (MIGRATE_STARTUP_TIMEOUT_SECS,
  default 30s, 500ms interval), separate from the runtime get_conn()
  anti-avalanche fast retry (untouched)
- migrate: split run() into run_on_conn(&mut conn) so callers control the
  connection-acquisition strategy; main.rs pairs this with the startup
  retry. Advisory-lock release comment updated: exit(1) terminates the
  process just like panic, so the session-level lock is still freed
- main: startup fatal errors (bad URL, DB unreachable, migration failed)
  now each emit tracing::error! + eprintln! ERROR + targeted HINT, then
  exit(1) — no panic, no backtrace nudge
- .env.example / AGENTS.md: document MIGRATE_STARTUP_TIMEOUT_SECS

No runtime behavior change: get_conn() and its ~40 call sites are
unchanged. Advisory-lock safety preserved (documented in migrate.rs).
2026-06-22 11:24:13 +08:00
xfy
1e2e3c9332 perf(db): add statement_timeout; skip retry on pool Timeout errors
- 连接配置 statement_timeout(默认 30s,STATEMENT_TIMEOUT_SECS 可调),
  防慢查询长时间占用连接拖垮池(L6)
- get_conn 对 Timeout(池满)错误立即返回不再 sleep 重试,避免雪崩;
  仅 Backend/Postgres 错误才退避重试
2026-06-18 13:35:33 +08:00
xfy
82a3c12940 feat(security): add Origin-based CSRF protection for write endpoints
对所有 POST/PUT/PATCH/DELETE 请求校验 Origin(回退 Referer)等于本站,
堵住 login CSRF 与未来 GET 化写接口的盲区(SameSite=Lax 覆盖不到)。

- 新增 src/api/csrf.rs:纯函数 origin 解析(不引入 url crate)+ axum 中间件
- 挂载到 upload 路由与 Dioxus app 路由(最外层,先于超时/压缩)
- APP_BASE_URL 配置可信域名;未设置时回退 Host + X-Forwarded-Proto
- GET/OPTIONS 放行;拿不到本站 origin 时放行避免误杀
- 9 个单测覆盖写方法识别、origin 标准化、默认端口省略、头解析回退
2026-06-18 13:22:59 +08:00
xfy
7d713cabc2 docs: document server-only optional dependencies in AGENTS.md
Some checks failed
CI / check (push) Failing after 5m15s
CI / build (push) Has been skipped
2026-06-16 17:32:04 +08:00
xfy
d246adbb32 build: make rand optional and remove explicit getrandom dependency 2026-06-16 17:10:27 +08:00
xfy
cafbddb861 refactor: replace server-only dead_code allows with cfg(feature = "server")
Replace #[allow(dead_code)] on server-only helpers with #[cfg(feature = "server")]
to make the server/WASM split explicit and avoid compiling unused server logic
into the WASM frontend.

- Gate password/session/auth/comment helpers and model parsers with server feature
- Gate related imports and tests accordingly
- Remove genuinely unused CreatePostRequest and CreateCommentRequest
- Keep #[allow(dead_code)] for true dead code (stub methods, unused public APIs)
- Use #[cfg(any(target_arch = "wasm32", test))] for THEME_KEY
- Update AGENTS.md note
2026-06-16 16:45:08 +08:00
xfy
76ad4ec8fb ci: 修正 Tailwind CLI 包名并收敛重复的环境准备步骤
Some checks failed
CI / check (push) Failing after 2s
CI / build (push) Has been skipped
Tailwind v4 将 CLI 拆为独立包 @tailwindcss/cli,核心包 tailwindcss
不再注册 bin,导致 npx tailwindcss 报 "could not determine executable
to run"。CI 改为安装 @tailwindcss/cli。

同时将 check 与 build 两个 job 重复的 checkout、镜像、Rust/Node/dx/
tailwind 安装步骤抽到 .gitea/actions/setup 复合 action,顶层 env
统一管理 Rust 镜像配置。AGENTS.md 同步说明 v4 拆包这一坑。
2026-06-15 11:47:54 +08:00
xfy
fa6fa9a77c docs: document COOKIE_SECURE and TRUSTED_PROXY_COUNT 2026-06-12 17:31:20 +08:00
xfy
bd9e87128d perf(ssr): optimize request throughput by 32%
- Cache ammonia::Builder with LazyLock (was rebuilt per request)
- Enable tracing release_max_level_info to strip tracing overhead at compile time
- Remove TraceLayer and tower-http trace feature from production
- Increase DB pool size 10→20 (configurable via DB_POOL_SIZE)
- Increase SSR cache TTL 300s→3600s (configurable via SSR_CACHE_SECS)

Benchmark: 7,444 → 9,840 req/s, P99 latency 27.6ms → 11.1ms
2026-06-12 09:36:53 +08:00
xfy
efa41b42c2 feat(auth): add loading state to login/register forms and update AGENTS.md 2026-06-11 10:44:27 +08:00
xfy
9452c196fa docs: document why image crate excludes WebP decoder 2026-06-09 16:14:28 +08:00
xfy
9c5b09a278 chore: code cleanup - formatting, EOF newlines, model helper, and UI tweaks 2026-06-02 17:33:28 +08:00
xfy
e48253c6f7 添加 AGENTS.md 项目开发指南文档 2026-06-02 17:33:28 +08:00