diff --git a/backend/internal/store/store.go b/backend/internal/store/store.go index eb0effc..70e5121 100644 --- a/backend/internal/store/store.go +++ b/backend/internal/store/store.go @@ -147,8 +147,6 @@ func scanUser(row pgx.Row) (User, error) { return u, err } - - // ---------- libraries ---------- func (s *Store) CreateLibrary(ctx context.Context, name, root string) (int64, error) { diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index dff0d81..55a6e63 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,6 +8,35 @@ The format loosely follows Keep a Changelog and can be adapted to the team's hab ## [Unreleased] +### Fixed / 修复 + +- Rate limiter `IncrWindow` uses atomic Lua script for INCR+EXPIRE, preventing permanent IP lockout on EXPIRE failure (B1). +- 限流器 `IncrWindow` 改用 Lua 脚本原子执行 INCR+EXPIRE,防止 EXPIRE 失败导致 IP 永久锁定(B1)。 +- Distributed lock `Lock` handles `rand.Read` failure by degrading to no-lock instead of using a zero token (B2). +- 分布式锁 `Lock` 在 `rand.Read` 失败时降级为无锁模式,而非使用全零 token(B2)。 +- Lock unlock uses `context.WithoutCancel` to survive caller cancellation (B3). +- 锁的解锁改用 `context.WithoutCancel`,在调用方上下文取消后仍能正常释放(B3)。 +- Upload part writes to `.tmp` then renames, preventing truncated parts from being reported as received (B4). +- 分片上传先写 `.tmp` 再 rename,防止崩溃截断的分片被误报为已接收(B4)。 +- `DeleteUser` last-admin check is now transactional, eliminating TOCTOU race (B5). +- `DeleteUser` 的最后管理员检查改为事务内执行,消除 TOCTOU 竞态(B5)。 +- Single-file upload `io.Copy` errors other than `MaxBytesError` return 500 instead of 413 (B6). +- 单文件上传中非 `MaxBytesError` 的 `io.Copy` 错误返回 500 而非 413(B6)。 +- `/auth/me` distinguishes `no rows` (401) from database errors (503) (B7). +- `/auth/me` 区分无记录(401)和数据库错误(503)(B7)。 +- Library creation rejects reserved names (`cache`, `.uploads`) with `400 reserved_name` (B8). +- 创建书库时拒绝保留名(`cache`、`.uploads`),返回 `400 reserved_name`(B8)。 +- Scanner lock auto-renews every TTL/2 during long scans; per-library single-flight prevents concurrent scans (B9). +- 扫描锁每 TTL/2 自动续期;库级 single-flight 防止并发扫描(B9)。 +- Scanner `SetBookState` errors are now logged instead of silently discarded (B10). +- 扫描器 `SetBookState` 的错误现在会记录日志而非静默丢弃(B10)。 +- Cover write errors fully checked; orphan `.tmp` files cleaned only on failure (B11). +- 封面写入错误全部检查;孤儿 `.tmp` 文件仅在失败路径清理(B11)。 +- Upload handler retries on `O_EXCL` collision for concurrent same-name uploads (B12). +- 上传处理器在 `O_EXCL` 冲突时重试,处理并发同名上传(B12)。 +- Bookmark methods check `err` before `RowsAffected` to avoid invalid reads on query failure (B13). +- 书签方法先检查 `err` 再读 `RowsAffected`,避免查询失败时的无效读取(B13)。 + ### Changed / 变更 - Add ordered migration system with `schema_migrations` tracking and pg advisory lock for safe multi-replica schema evolution. Existing databases are auto-baselined. To change the schema, add a new `NNNN_description.sql` file under `backend/internal/db/migrations/`; never modify an already-applied file. No down migrations — rollback via backup, fix-forward.