Releases: dm807cam/rehydrate
reHydrate v1.0.2
Patch release on the v1.0 line. Fixes first-run macOS networking,
real Keychain persistence, and the new drag-out export path. No
on-disk format changes. The macOS bundle is still Apple-Silicon-only,
still unsigned, and still requires the right-click → Open dance on
first launch.
Added
- Export: hold Option while dragging a document row or tile to
drag a real file out of reHydrate into Finder, Desktop, Mail, or
another native drop target. PDF and EPUB documents are copied out
verbatim; notebooks render to a multi-page PDF via the same ink
renderer used by Preview (#57).
Fixed
- macOS bundle: ship
NSLocalNetworkUsageDescriptionin
Info.plist, so the OS prompts for Local Network access on
first connection to the tablet at10.11.99.1instead of
blocking the SSH socket silently. Affects macOS 15+ users
(rM2 and Paper Pro alike) (#60, #61). - App (keychain): "Remember password" now actually persists the
reMarkable SSH password across app restarts on macOS. Thekeyring
v3 dependency was missing itsapple-nativebackend feature, so the
crate was silently compiling to an in-memory mock store: writes
returnedOk(()), in-session reads worked, and the password
disappeared on next launch with no warning surfaced. Enabling the
feature routes credential I/O to the real macOS Keychain (#58, #59). - Export cache: drag-out export staging now checks the content-
keyed cache path before reading large PDF/EPUB blobs or rendering
notebooks. Hover prefetch therefore stays cheap on cache hits, and
the actual Option-drag can call into macOS' drag API inside the
short user-gesture window.
Credits
- Thanks to
u/shuusaku
for the Paper Pro report and follow-up root-cause notes that led
directly to the macOS Local Network permission fix and the Keychain
backend fix.
Download: macOS (Apple Silicon, 11.0+) — .dmg attached below.
macOS builds are unsigned and un-notarized. First launch needs
a right-click → Open to bypass Gatekeeper.
Verifying the download: shasum -a 256 reHydrate_*.dmg
and compare against SHA256SUMS (also attached). For tamper
evidence beyond the workflow log, see this run's
build provenance attestation.
Source: built from
e60039fe1ea160a8d01d47646a5cd9000009e578.
See SECURITY.md
for the threat model and the vulnerability-report channel.
reHydrate v1.0.1
Patch release on the v1.0 line. Bug fixes, hardening, and dependency
bumps that landed against main since v1.0.0. No on-disk format
changes; no user-facing behavioural changes outside the fixes below.
The macOS bundle is still Apple-Silicon-only, still unsigned, and
still requires the right-click → Open dance on first launch.
Fixed
- Sync (push side):
delete_document_treefailures now propagate
to the sync result so a failed folder delete stays queued and is
retried on the next push, rather than being silently swallowed
(#23). - Sync (pull side):
record_versionon an archived document is
rejected at the boundary, closing a race where a pull mid-archive
could resurrect a soft-deleted doc (#31). - Device layer:
put_document_treeis now a true replace —
stale tablet-side entries are removed when the library-side tree
shrinks, so a folder rename + child-removal in one push no longer
leaves orphan tablet entries (#22). - Device layer: SFTP entry names containing path separators or
parent references are rejected at the boundary instead of being
treated as leaf names (#33). - Core (blob store):
import_filefailures now unlink the
staged blob, so an interrupted import does not leak a partial
file under the blob fanout (#39). - Core (blob store): blob-fanout ancestor directories are
fsynced up to the blob root after a write, so a crash between
rename and parent-dir fsync cannot leave a blob that exists on
disk but is invisible after reboot (#30). - Core (library):
library.jsonis written atomically via a
tempfile + rename rather than truncated-in-place, so a crash mid-
write cannot leave a zero-byte stamp file (#32). - rm-parser: v3–v5 length-prefixed buffers cap their
preallocation, closing a parser-DoS where a hostile.rmfile
could request gigabyte allocations from a 32-bit length field
(#34). - rm-parser: unknown
SceneItemTypesubtypes are tolerated as
forward-compat skips rather than hard parse errors, so newer
tablet firmwares do not brick the import path (#35). - App (IPC):
open_libraryis allowlisted against the picker,
the recents list, and the default-library path, so a renderer
compromise cannot ask the host to open an attacker-controlled
directory as a library (#36). - App (import): dropped-file size is preflighted before the
bytes are read into memory, so a 5 GiB drag-and-drop is rejected
cheaply rather than after an OOM (#24). - UI: a
refreshLibraryrequest that arrives while another is
in flight is now queued (one pending slot) instead of being
dropped, so a sync-completion event during a manual refresh no
longer leaves the library view stale (#38). - UI: Tauri event listeners unbind cleanly when their owning
component unmounts before thelisten()promise resolves,
closing a leak where a long-running listener kept a reference to
a discarded component (#37). - UI: three v1.0.0 UX dead-ends are unblocked (move-to-folder
affordance, empty-state guidance, and one settings-tab focus bug)
(PR #16).
Changed
- CI: the supply-chain audit job (
cargo audit+cargo deny check) is now a hard gate onmain. A new advisory landing on a
transitive dep fails the build instead of producing a yellow warn
in the log (#19). The triage process is documented in
.cargo/audit.tomlanddeny.toml. - Tests: pull-side and push-side reconciliation now have
coverage at the sync layer (#17). No production-code changes;
these tests pin behaviour that was previously asserted only
end-to-end.
Dependencies
thiserror1.0.69 → 2.0.18 (#29)sha20.10.9 → 0.11.0 (#28)imageproc0.25.1 → 0.26.2 (#27)fs40.9.1 → 1.1.0 (#26)tokio1.52.2 → 1.52.3 (#15)rusqlite0.32.1 → 0.39.0 (#14)directories5.0.1 → 6.0.0 (#13)actions/checkout4 → 6 (#10)actions/setup-node4 → 6 (#9)actions/upload-artifact4 → 7 (#7)actions/attest-build-provenance2 → 4 (#8)tauri-apps/tauri-action0.5.20 → 0.6.2 (#6)
Release engineering
build.shnow removes stalerw.*.dmginterstitials from
bundle/macosbefore invoking the Tauri bundler, and asserts the
expected.dmgexists and passeshdiutil verifybefore
reporting success. Previously abundle_dmg.shfailure could
leave its temporary image inside the source folder, which then
caused the next bundle to try copying its own growing tempfile
into itself (#54).- The release workflow now runs the same gates as CI
(cargo fmt --check,clippy -D warnings, workspace tests,
cargo audit --deny warnings,cargo deny check, UI typecheck- lint + build) as a preflight job before the Tauri build, and
asserts that the tag version matchesCargo.toml,
tauri.conf.json,ui/package.json,ui/package-lock.json,
and a matchingCHANGELOG.mdsection. The release fails
loudly if any of those drift, instead of falling back to a
generic body (#55).
- lint + build) as a preflight job before the Tauri build, and
Download: macOS (Apple Silicon, 11.0+) — .dmg attached below.
macOS builds are unsigned and un-notarized. First launch needs
a right-click → Open to bypass Gatekeeper.
Verifying the download: shasum -a 256 reHydrate_*.dmg
and compare against SHA256SUMS (also attached). For tamper
evidence beyond the workflow log, see this run's
build provenance attestation.
Source: built from
538934be17f9ea34af7aa60e0a43589dd9fc84cb.
See SECURITY.md
for the threat model and the vulnerability-report channel.
reHydrate v1.0.0
First stable release. The goal of v1.0 was to ship the audit cleanups
the v0.9.x line accumulated and to land enough of the
"organise-your-library" UI for daily use against a reMarkable 2.
Added
- Folders, end-to-end. Create folders and subfolders from the
sidebar; drag-reorder rows in the sidebar (local-only ordering, not
pushed to the device); move documents into folders by drag-and-drop,
by a new "Move to folder…" item in the three-dot menus, or in bulk
from the selection bar. The "Move to folder…" picker also has an
inline "+ New folder here…" affordance so common workflows don't
dead-end in cancel-create-retry. - Drag PDFs and EPUBs from Finder / Explorer onto the window to
import. A full-window overlay shows the drop zone; bytes travel
over IPC into a tempfile and through the existing import path. Cap
is 512 MiB per file. - Render typed text in v6 notebook PDFs. Until now the renderer
only emitted ink strokes; typed text on a page was silently
dropped from the export. Now it lands as Helvetica at the recorded
position. - Respect erased strokes and hidden layers when rendering
notebooks. A stroke the user erased on the tablet no longer
reappears in the exported PDF; layers toggled off on the tablet
are skipped. - Retry button on a failed sync, plus a warning card for non-fatal
sync issues (e.g.xochitl restartfailed — files landed, the
tablet's UI just needs a reboot to pick them up). - Toast warnings for keyring write failures (Linux without
secret-service) and legacy-format notebook fallbacks (v3 / v5
.rmfiles that fall back to thumbnail previews). - OCR via a user-provided Ollama daemon. "Convert to text…" on
any document renders every.rmpage to PNG, ships it to
Ollama's/api/generate, and stores the transcript as a derived
artefact attached to the document's current version. The
Settings modal's Ollama tab lets the user point at a local or
remote Ollama (defaulthttp://localhost:11434) and pick from
the curatedqwen3.5:4b(default, fast) /qwen3.5:9b(sharper
at cursive + math) options, or supply a custom model tag.
Qwen 3.5 is Ollama's current unified vision-language family
(released ~one month before v1.0.0) and outperforms the older
Qwen3-VL / Qwen2.5-VL lines on OCRBench (93.1%) and
OmniDocBench1.5 (90.8%) — both directly relevant to the
handwritten-notebook workload. Test Connection probes
/api/tagsand reports which models are pulled. Background
progress is shown in a floating chip; the result lands in the
Transcript drawer with Save-as-.txt/ Save-as-.mdactions. - Auto-OCR at startup. Optional toggle in Settings → Ollama.
When enabled, every notebook without an existing transcript is
transcribed sequentially after the app opens. Silently skips
when Ollama is unreachable (no nagging at launch); per-doc
failures don't abort the sweep; the progress chip shows
"(N of M)" batch progress and × cancels the whole queue. Off
by default — opt-in keeps first-run users from unexpected
network traffic. - Publish transcripts as drafts to Ghost or WordPress. The
Transcript drawer's "Publish to Ghost" / "Publish to WordPress"
buttons convert the Markdown transcript to HTML and POST it
to the configured CMS as a draft. Credentials live in the OS
keychain; the Publishing tab in Settings handles entry, test
connection, and forget. Every request routes through a
host-pinnedRestrictedAgentwith redirects disabled, so a
hijacked CMS endpoint can't redirect transcript content
anywhere else. - Tabbed Settings modal. New gear icon in the toolbar (and
"Settings…" entry in the menu) opens a single modal with two
tabs: Ollama (OCR) and Publishing. Failed OCR / publish actions
auto-open the relevant tab with an explanatory banner instead
of dead-ending the user on a raw error toast. LICENSE-MITandLICENSE-APACHEat the repo root and a new
SECURITY.mddocumenting the v1.0 threat model.
Changed
- Tauri webview
devtoolsis disabled in release builds. Dev
builds still expose F12 / Cmd+Opt+I for local debugging; the
release workflow builds with--no-default-featuresso end users
can't open the inspector. - Manifest path validation now rejects control characters,
trailing dots/spaces, Windows reserved names (CON,PRN, etc.),
and NTFS alternate-data-stream colons. The export-filename
sanitiser applies the same rules so a doc titledCONexports as
doc-CON-…instead of failing silently on Windows. - Document cache keys now include the full content hash and the
document UUID. The previous 12-char hash prefix was inside
birthday-collision range; a malicious device could craft two
documents that collide in the cache. update_last_seen_manifestretries on transient SQLite errors
with backoff before propagating, so a momentary busy-lock doesn't
leave the next push silently overwriting tablet-side edits.- Single xochitl restart per push session instead of one per
document. A multi-doc push no longer blanks the tablet UI N times.
If the restart fails, the sync completes successfully but a
warning surfaces in the UI. - GC clock-skew guard: blobs whose filesystem mtime appears to
be in the future relative to wall-clock now are kept rather than
deleted, so an NTP backwards-jump can't sweep recent blobs.
Fixed
import_dropped_fileis now size-capped at 512 MiB, matching the
cap that already protected SFTP-side reads.Library::reorder_folderrejects cycles in a single transaction
and the UI short-circuits descendant drops in the folder picker.
Security
See SECURITY.md for the full v1.0 threat model. Summary: SSH host-
key verification remains TOFU-without-pinning (USB-cabled threat
model); credentials live in the OS keyring; logs are size-capped and
rotated; CSP locks script-src to 'self'; no HTTP egress in any
business crate, enforced by an integration test.
Download: macOS (Apple Silicon, 11.0+) — .dmg attached below.
macOS builds are unsigned and un-notarized. First launch needs
a right-click → Open to bypass Gatekeeper.
Verifying the download: shasum -a 256 reHydrate_*.dmg
and compare against SHA256SUMS (also attached). For tamper
evidence beyond the workflow log, see this run's
build provenance attestation.
Source: built from
07a767b20f325d4cfa298e928eabeafb66c81da9.
See SECURITY.md
for the threat model and the vulnerability-report channel.