feat(fonts): add workspace font pipeline and resources UI#190
feat(fonts): add workspace font pipeline and resources UI#190sharkAndshark wants to merge 15 commits intomainfrom
Conversation
Introduce end-to-end font management with upload, async PBF glyph generation, publish/unpublish, and public glyph serving, while adding a resources section in the frontend with fonts as the first managed asset.
Drop inline Chinese defaultValue strings from main tab translations so the i18n CI detector no longer flags hardcoded Chinese text.
sharkAndshark
left a comment
There was a problem hiding this comment.
Round 1 self-review complete.\n\nWhat I checked:\n- CI failure root cause: frontend i18n detector flagged hardcoded Chinese fallback literals in App main tab labels.\n- Fix: removed Chinese fallbacks and rely on locale keys (, ) present in both and .\n- Re-validation: local === i18n Detection ===
Check 1: Hardcoded Chinese strings...
�[0;32mPASS: No hardcoded Chinese strings found�[0m
Check 2: t() key completeness...
�[0;32mPASS: All t() keys exist in both locale files�[0m
=== Summary ===
�[0;32mPASSED: All i18n checks passed�[0m now passes; unit tests and formatting checks pass.\n\nNo further code issues found in this round.
sharkAndshark
left a comment
There was a problem hiding this comment.
Round 1 self-review complete.
What I checked:
- CI failure root cause: frontend i18n detector flagged hardcoded Chinese fallback literals in App main tab labels.
- Fix: removed defaultValue Chinese fallbacks and rely on locale keys (app.mainTabData, app.mainTabResources) present in both en.json and zh.json.
- Re-validation: local
bash scripts/ci/check_i18n.shnow passes; unit tests and formatting checks pass.
No further code issues found in this round.
sharkAndshark
left a comment
There was a problem hiding this comment.
Round 2 self-review complete.
What I verified after the i18n fix commit:
- All CI checks are green (backend tests/clippy/fmt/postgis integration, frontend unit/e2e, dependency-review).
- The previous frontend_unit failure is resolved by removing hardcoded Chinese fallback literals.
- Local parity checks remain green, including scripts/ci/check_i18n.sh.
No further changes required from my side.
|
Addressed the two high-priority review findings in c7e095e:\n\n- API contract fix: font responses now serialize in camelCase (, ) to match frontend expectations (, , , , etc.).\n- Security hardening: public glyph endpoint now strictly validates range format (), rejects slash/backslash patterns, canonicalizes resolved file path, and enforces upload-dir containment before file reads.\n- Added backend unit tests for both range parsing and camelCase serialization regression coverage.\n\nValidation: pre-commit + pre-push suites passed (cargo test/clippy/fmt, frontend unit, frontend e2e). |
|
Addressed the two high-priority review findings in
Validation: pre-commit + pre-push suites passed (cargo test/clippy/fmt, frontend unit, frontend e2e). |
|
Follow-up fix from review applied in
Validation passed via hooks and reruns (backend tests/clippy/fmt, frontend unit, frontend e2e). |
|
Applied the latest review findings in
Validation passed through hooks and reruns: backend fmt/clippy/tests + frontend unit/e2e. |
|
按你的要求,我把这轮 review 相关修复做了完整解释性补强,并补上了回归测试,已同步到 PR。 新增测试(commit
验证结果:
|
|
按你的要求,已使用开源字体补齐自动化测试(不依赖手工测试):
提交: 验证:
|
|
继续按“破坏可发现性”目标补强了字体自动化回归(commit 新增/补强用例(
验证结果:
这轮后,字体模块对于“主链路 + 关键失败分支 + 字段契约回退”的破坏检出能力显著提升。 |
…aram - Merge status check into UPDATE WHERE clause for atomic operation - Remove unused onProgress parameter from uploadFont function
…ug edit validation
…red helpers, improve robustness - Use CURRENT_TIMESTAMP for font created_at and published_at instead of Rust-side Utc::now(), consistent with the rest of the codebase - Extract test-mode workspace bootstrap from font_handlers.rs and upload.rs into workspace::ensure_test_mode_workspace(), eliminating ~100 lines of duplicated code - Extract read_font_row() helper to deduplicate the 13-column FontItem row mapping used in list_fonts and get_font - Log DB errors in update_font_error instead of silently discarding them - Save uploaded font with original file extension (e.g. original.ttf) for easier filesystem inspection
…workspace archive Defense-in-depth: LIMIT 1 prevents query_row().optional() from erroring if multiple rows somehow match the public glyph query. Workspace archive now unpublishes fonts (is_public=FALSE, slug=NULL, published_at=NULL) in the same transaction as file unpublish, closing a gap where fonts remained publicly accessible after archival.
… dynamic path computation Fix 1: upload_font now returns 201 Created (matching upload_file semantics). Fix 2: Extract get_active_workspace_id() into workspace.rs — eliminates ~60 lines of duplicated workspace authorization logic between font_handlers and upload. Fix 3: Font stored paths are now computed dynamically relative to upload_dir instead of hardcoding './uploads/' prefix, preventing silent breakage if upload directory config changes.
…fix start, use index names for error classification
Fix 1: upload_font now cleans up uploaded file and directory if DB INSERT fails,
preventing orphan files on disk.
Fix 2: Unify slug collision suffix to start at 1 (was 2 in workspace_handlers.rs),
consistent with db.rs.
Fix 3: Replace fragile string-matching error classification (err.contains("slug"),
err.contains("UNIQUE")) with explicit index name checks
(idx_workspaces_slug, idx_fonts_workspace_slug). DuckDB error messages include
constraint/index names, making this more robust than generic keyword matching.
Summary
Why
Testing
cargo clippy --manifest-path backend/Cargo.toml --all-targets --all-featurescargo test --manifest-path backend/Cargo.tomlcargo fmt --manifest-path backend/Cargo.toml -- --checknpm --prefix frontend run format:checknpm --prefix frontend run test:unitnpm --prefix frontend run buildnpm --prefix frontend run test:e2e