releases/v0.7.0.md
Rama master · réplica de lectura del repositorio original.
# v0.7.0
**Released:** 2026-07-24
Changes since v0.6.1 (`8f6f69b`..merge of #120–#124). A batch of security and robustness fixes plus one UX feature, all from @samirhvbr, integrated with additional hardening.
## Security
- **Path containment by ancestry, not string prefix** (PR #120 by @samirhvbr): The traversal guards in `NotesController#serve_asset`, `NotesService#safe_path`, and `ImagesService#safe_path` are consolidated into one `PathSafety.contain`. It fixes a sibling-prefix bypass (base `/data/notes` no longer accepts `/data/notes-backup/...`), rejects absolute-path and `../` escapes, and — via a realpath re-check — rejects symlinks inside the tree that resolve outside it. **Behavior note:** notes that are symlinks pointing outside the notes directory are now treated as out-of-bounds and can't be read/served; keep note content inside `NOTES_PATH`.
- **Enforce the image allow-list on base64 uploads** (PR #121 by @samirhvbr): The base64/AI-image upload path (`ImagesService.upload_base64_data`) previously skipped the extension allow-list, so an `image/svg+xml` mime or an `.html` filename could be stored under the notes dir and served inline (stored XSS) — the same class fixed for multipart uploads in v0.4.0, now closed for base64 too. Validation runs against the on-disk extension with no bypass; valid AI images are unaffected.
## Robustness
- **Atomic note writes** (PR #122 by @samirhvbr): Notes are written to a temp file in the destination's own directory and atomically renamed over the target, so an interrupted or failed write (crash, ENOSPC) never truncates the existing note. Integration adds **file-mode preservation** — the existing note's permission bits are carried across the rename instead of being reset to the umask default.
- **Content search survives invalid-UTF-8 files** (PR #123 by @samirhvbr): A single Latin-1/binary `.md` file no longer aborts the whole search — bad bytes are scrubbed per line, and an unreadable file (permission/TOCTOU) is skipped rather than failing the search.
## Features
- **Show where a new note/folder will be created** (PR #124 by @samirhvbr): The new-note / new-folder dialog now displays the destination path, so you're not guessing which folder is the target. New strings are translated across all 7 locales. Integration also fixes a pre-existing bug the feature surfaced: a root "New Note" after a cancelled "New Note in Folder" no longer inherits the stale folder.
## Chores
- SimpleCov `add_filter` → `skip` (silences the deprecation introduced by the simplecov 1.0 bump).
## Test Coverage
- 602 Ruby tests, 1,437 JavaScript tests (2,039 total).