e9ecc4c1f7
CI / test (pull_request) Successful in 2m13s
Fix goroutine-unsafe ULID entropy by wrapping in LockedMonotonicReader. Move PRAGMA foreign_keys outside transaction in v3 migration where SQLite was silently ignoring it. Escape LIKE wildcards in link resolution to prevent false matches. Add non-localhost binding warning, log writeJSON encoder errors, add ?permanent=true for explicit hard delete, preserve title/description during absorb, use millisecond backup timestamps, add path.Clean to spaHandler. Frontend gains checkedJSON() for resp.ok validation, consistent stopPropagation, and shared renderCardSections() to eliminate duplicate rendering.
2.7 KiB
2.7 KiB
Code Review Fixes
Phase 1: Critical — Concurrency & Data Safety
1. ULID entropy not goroutine-safe
- Wrap MonotonicEntropy in LockedMonotonicReader (
internal/ulid/ulid.go) - Add concurrent uniqueness test (100 goroutines)
- Verify
go test -race ./internal/ulid/...
2. Migration PRAGMA bug
- Move
PRAGMA foreign_keys = OFFbefore transaction in v3 migration (internal/db/db.go) - Re-enable after commit
- Remove dead
currentSchemaconstant while here
3. LIKE wildcard injection in link resolution
- Escape
%and_in link text before LIKE query (internal/db/links.go) - Add
ESCAPE '\'clause - Test with
[[%]]and[[_]]link text
Phase 2: High — Security & API Hygiene
4. No auth warning for non-localhost binding
- Print loud warning when
--host != 127.0.0.1and no auth configured (cmd/serve.go) - Consider
--no-authflag requirement for non-localhost
5. writeJSON ignores encoder errors
- Log error from
json.Encoder.Encode()inwriteJSON(internal/api/helpers.go)
6. DELETE endpoint semantics
- Add
?permanent=truequery param for hard delete (internal/api/entities.go) - Add
HardDeletestore method (internal/db/entities.go) - Update frontend and CLI to match
- Keep backward compat: double-delete still works without param
Phase 3: Medium — Frontend Robustness
7. No resp.ok checks on fetch calls
- Add
checkedJSON()wrapper with error extraction (web/app.js) - All API methods use
checkedJSON(resp)instead ofresp.json() - Surface API errors to user via notification/toast
8. Inconsistent event.stopPropagation
- Add stopPropagation to all renderStreamPeek action buttons
- Add stopPropagation to all renderCardPeek action buttons and inline section buttons
9. Duplicate section rendering
- Extract
renderCardSections()shared function (web/app.js) - Refactor
renderInlineDetailto use shared function - Refactor
renderCardPeekto use shared function
Phase 4: Medium — Data Integrity
10. Absorb discards source title/description
- If target has no title, inherit from source (
internal/db/entities.go) - If target has no description, inherit from source
- Test title/description preservation
Phase 5: Low — Housekeeping & UX
11. Backup path collision
- Use millisecond-precision timestamps (
cmd/backup.go)
12. spaHandler path safety
- Add explicit
path.Cleanin spaHandler (internal/api/router.go)
13. Focus-peek escape hatch
- Add visible close/back button in focus-peek mode (
web/app.js)
14. Hard delete confirmation
- Add confirmation step or undo toast before permanent delete (
web/app.js)