WhatsVault is a local-first desktop app for browsing WhatsApp chats and media from iPhone backups. It runs on your computer and does not upload your messages, backups, contacts, or media.
Status: pre-alpha desktop viewer. WhatsApp export ZIP viewing works as the first local source path. The desktop app can scan default iPhone backup folders, show local backup/WhatsApp status, and route a selected ready backup into the shared chat-list/import UI path. Real local iPhone-backup proof has passed for Manifest.db, ChatStorage.sqlite, desktop chat rendering, bounded media preview, and bounded HTML export without committing private artifacts. Stable release remains blocked by signing/notarization and release hardening.
Screenshot and video use synthetic demo data only.
Watch the synthetic 18-second demo video
The intended product path is simple:
- Open WhatsVault.
- Pick a local iPhone Finder, iTunes, or Apple Devices backup.
- Browse WhatsApp chats and media locally.
- Search messages.
- Export a selected chat to self-contained HTML.
No terminal workflow, manual backup-ID hunting, or copying SQLite files by hand should be required in the finished app.
WhatsVault is designed around local-only processing:
- No account.
- No cloud sync.
- No message upload.
- No hosted parsing service.
- No analytics on private chat content.
Real backups, exported chats, SQLite databases, media, and private fixtures must stay out of the repository. See .gitignore before adding any sample data.
See SECURITY.md for the security reporting policy.
Pre-alpha desktop builds are published on GitHub Releases when release automation passes. Current bundles are not notarized or Developer ID signed on macOS and are not code signed on Windows, so they should be treated as early tester builds, not stable end-user releases.
Release assets include SHA-256 checksum manifests. New releases also publish GitHub artifact attestations, which can be checked with:
gh attestation verify "/path/to/WhatsVault_0.1.0_aarch64.dmg" \
--repo andreivince/WhatsVaultChecksums and attestations prove provenance, not platform trust. A stable release still requires signed and notarized macOS output, Windows code signing, and clean-machine install/open proof.
The selected app direction is Tauri v2 with React and TypeScript:
- Tauri keeps the app cross-platform for macOS and Windows while allowing a Rust core for local filesystem and SQLite work.
- React and TypeScript keep the interface portable, testable, and fast to iterate.
- Shared parser/model logic should sit behind stable internal APIs so the UI never depends directly on WhatsApp SQLite or export-file quirks.
The first supported source target remains iPhone local backups. A WhatsApp exported chat ZIP can be useful as a development source, but it must not replace the iPhone-backup roadmap.
The current desktop app uses the exported chat ZIP path first so the viewer, layout, search, media-preview, and HTML-export flow can be exercised without requiring a local iPhone backup.
See ROADMAP.md.
See docs/architecture.md.
See docs/supported-sources.md for the current source matrix.
See docs/proof-evidence.md for the public-safe evidence boundary behind local real-backup proof claims.
README demo videos must be generated from synthetic English demo data, not private chats or backups.
See docs/demo-video.md for the Playwright plus playwright-recast workflow that produces the committed synthetic MP4.
See CONTRIBUTING.md, CODE_OF_CONDUCT.md, CHANGELOG.md, docs/troubleshooting.md, and docs/ci-release.md.
- Public-safe repository foundation is in place.
- Shared Rust core crate exists at
crates/whatsvault-core. - WhatsApp export ZIP import is tested with synthetic fixtures.
- A private ignored test hook validates a local export ZIP without printing chat content.
- A Tauri desktop app exists at
apps/desktop. - The desktop app can open a WhatsApp export ZIP through a native file picker, parse the transcript in Rust into a bounded latest-message window, render the chat timeline, search loaded messages, preview bounded images, stickers, audio, video, and documents from the archive, open image previews, and export the loaded window to self-contained HTML.
- The desktop app can scan default iPhone backup folders and show safe display metadata plus WhatsApp file-detection status without showing local backup paths in the UI.
- Default iPhone backup root construction is tested for macOS, Windows Microsoft Store Apple Devices or iTunes, and Windows legacy iTunes locations.
- iPhone backup discovery and
Manifest.dbmapping are tested with synthetic fixtures. - Modern iPhone backup
fileIDvalues are resolved to physical backup files through the centralized core resolver. - Synthetic
ChatStorage.sqlitefiles can be summarized for message, chat, and media-item counts through the shared core crate. - Synthetic
ChatStorage.sqlitefiles can list chats by latest message and import one selected chat into the same normalizedChatImportmodel used by the desktop timeline. - The Tauri command layer can resolve a selected backup's
ChatStorage.sqlitethroughManifest.dband call the core chat-list/import API. - The React app can select a ready backup, show discovered chats in the sidebar and backup panel, and open one selected backup chat through the same normalized timeline used by export ZIP imports. This path is covered with synthetic tests and has passed local real-backup chat-rendering smoke without committing private artifacts.
- When macOS blocks automatic access to the default MobileSync backup folder, the desktop app shows a plain "Choose folder" fallback that accepts either the Backup folder or one specific device backup folder.
- Backup media preview can resolve
ChatStorage.sqlitemedia paths throughManifest.dbto hashed backup files and return bounded browser-readable previews. This is covered by synthetic tests and real local backup UI smoke. - Backup HTML export has a bounded implementation for selected backup chats, including media resolved through
Manifest.db; it is enabled in the desktop UI after real local backup export smoke. - The desktop source screen separates the available WhatsApp export ZIP viewer from iPhone-backup proof work.
- The desktop search field filters WhatsApp export ZIP messages through shared frontend domain helpers, searches iPhone-backup chat names through a bounded backend query, and searches selected iPhone-backup chats through a bounded backend query for latest matching messages.
- The desktop timeline renders a bounded recent-message window with a tested "show earlier" path and DOM virtualization for already-loaded chats, while source importers avoid returning unbounded message vectors for huge backup or ZIP histories.
- The public synthetic demo renders a safe inline image preview and image-preview modal without using private media files.
- The README links to a committed synthetic MP4 generated through the Playwright plus
playwright-recastworkflow. - The desktop visual suite covers keyboard focus visibility, accessible names for icon-only controls, contrast floors for core text, and removal of fake or unsupported action chrome.
- A private-safe proof CLI exists at
crates/whatsvault-proof. - The private-safe proof CLI has located WhatsApp
ChatStorage.sqlitethrough a real local iPhone backupManifest.db, confirmed the physical backup file exists, read nonzero aggregate database counts, read a bounded real chat-list sample, and imported a bounded real chat sample into the normalized model without printing paths, identifiers, names, message bodies, or filenames. - A macOS
.appbundle and DMG can be built locally with Tauri, and release checksum manifests can be generated from the bundle outputs. - Visible packaged-window smoke from the generated macOS app bundle opens to a nonblank source screen locally.
- CI and draft-release workflows are configured for macOS Apple Silicon, macOS Intel, and Windows Tauri builds.
- Release checksum manifests can be generated from Tauri bundle outputs and are uploaded by the draft-release workflow.
- Real local backup media preview and bounded HTML export smoke have passed from the packaged macOS app without committing private artifacts.
Public-safe proof details live in docs/proof-evidence.md. Do not add private proof dumps, paths, screenshots, media, or exported chats to the repository.
Install desktop app dependencies:
cd apps/desktop
npm installRun all Rust tests from the repository root:
cargo test --workspaceRun desktop frontend tests:
cd apps/desktop
npm testRun the public repository hygiene guard before publishing or opening a pull request:
cd apps/desktop
npm run hygiene:publicThe guard scans Git-tracked files plus local non-ignored new files for private backups, transcripts, databases, media, local paths, personal roadmap-only material, and unexpected changes to the committed synthetic demo assets.
Run the release-readiness status guard:
cd apps/desktop
npm run release:readinessThis command passes when the current pre-alpha blockers are documented honestly. Before a stable public release, npm run release:preflight must pass; today it is expected to fail until macOS notarized signing and Windows code signing are configured.
Inspect local signing inputs without printing secret values:
cd apps/desktop
npm run release:signingThe release workflow can generate platform signing config from GitHub secrets at runtime; certificate material and passwords must stay in GitHub Secrets or local ignored files.
Run desktop visual layout checks:
cd apps/desktop
npm run visual:checkRun Rust formatting and lint checks:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warningsRecord and render the synthetic README demo video:
cd apps/desktop
npm run demo:videoRun the desktop web preview:
cd apps/desktop
npm run devRun the Tauri desktop app:
cd apps/desktop
npm run tauri devBuild the macOS app and DMG:
cd apps/desktop
npm run tauri buildGenerate checksum manifests for the local Tauri bundle outputs:
cd apps/desktop
npm run release:checksumsThe checksum command scans target/release/bundle plus target-specific Tauri roots such as target/<target-triple>/release/bundle. Set WHATSVAULT_BUNDLE_DIR only when checking one explicit bundle directory.
Current HTML export behavior:
- Exports the loaded WhatsApp export ZIP chat or selected iPhone-backup chat to one
.htmlfile. - The WhatsApp export ZIP path imports the latest bounded message window for large transcripts instead of returning an unbounded in-memory message list.
- The iPhone-backup export path runs behind the Tauri command boundary with bounded recent-message export, synthetic tests, and real local backup smoke.
- Escapes message text, sender names, filenames, and titles.
- Embeds media as data URLs when the attachment has a known browser media type and fits within the local per-file and total export size limits.
- Lists media that cannot be embedded instead of failing the export.
Run the private-safe backup proof command against default backup roots:
cargo run -p whatsvault-proofRun the proof command against a specific backup root:
cargo run -p whatsvault-proof -- "/path/to/MobileSync/Backup"The proof command reports aggregate counts, sampled counts, sample limits, and booleans only. It does not print device IDs, backup paths, file IDs, contacts, message bodies, or media filenames.
Optionally validate a private local WhatsApp export ZIP without printing chat content:
WHATSVAULT_PRIVATE_EXPORT_ZIP="/path/to/private-export.zip" \
cargo test -p whatsvault-core --test whatsapp_export_zip -- \
--ignored imports_private_export_zip_without_printing_chat_contentThe exported ZIP viewer was the first fully proven desktop path. The first hard iPhone-backup gates now pass: WhatsVault can locate WhatsApp data from a real local iPhone backup through Manifest.db, read ChatStorage.sqlite, render a real backup chat, preview bounded media, and export a bounded chat HTML file from the packaged desktop app without committing private artifacts. The next hard gate is release hardening: signed/notarized macOS output, Windows signing, and clean-machine install/open proof.
Real private exports and backups must stay in ignored local paths. Committed tests use synthetic fixtures or ignored private samples.
