Skip to content

Secure Files: encrypted .mydt file vault, shared format crate and CLI - #312

Open
itsmeakhil wants to merge 2 commits into
mainfrom
features/files
Open

Secure Files: encrypted .mydt file vault, shared format crate and CLI#312
itsmeakhil wants to merge 2 commits into
mainfrom
features/files

Conversation

@itsmeakhil

Copy link
Copy Markdown
Collaborator

Adds Files (Secure Files), an offline encrypted file vault, plus the .mydt format as a standalone crate and CLI.

Import files or folders and they are stored as opaque <32 random hex>.mydt objects in a storage folder you pick. Original names, folder paths, types and contents are encrypted — outside the app the folder is unreadable noise; inside, after unlocking, it looks like a normal file browser.

Format

Each .mydt is self-contained: Argon2id salt/params, a per-file DEK wrapped by the key derived from the master password, and XChaCha20-Poly1305 metadata + payload, with the header bound in as AAD. No index — listing scans the folder and decrypts headers, so a storage folder is portable and self-healing (a copied or corrupt object is reported, never fatal).

Spec: docs/MYDT_FORMAT.md. Implementation lives in crates/mydt — a library plus a mydt CLI (encrypt/decrypt/info/ls) behind --features cli, used unchanged by the desktop app so both sides read and write identical objects.

Desktop

  • /api/v1/secure-files/*: settings, list, import, patch, replace, export, delete, folder rename/delete; a raw-bytes secure_file_read command for previews.
  • After the webview verifies the master password it hands it to Rust once so Argon2id can derive the Secure Files key. That key lives in AppState only and is dropped on lock, including idle auto-lock.
  • Listing keeps a decrypted-metadata cache reconciled by an id-set diff; import encrypts across threads with one directory fsync per batch. Measured at 10k files: import 1.75s, cold list 0.30s, warm list 24ms.

UI

Folder tree, list and grid views (both virtualized), image thumbnails in grid, preview for text/code/images/PDF, export with a plaintext warning, rename/move/replace, and a dismissible warning for unreadable objects. Files up to 20 MB.

Also fixes a latent bug in the shared s3-drive FilePreviewDialog: it used Radix Tooltip without a TooltipProvider, which crashed the dialog subtree for any consumer that did not supply one.

Verification

cargo test (69, including a tamper/truncation/garbage mutation sweep over every byte of the container), mydt crate tests, jest, tsc, i18n:audit, and a manual pass in the desktop app: import, preview, rename, move, replace, export, lock/unlock, and confirming the storage folder holds only masked objects with no plaintext names.

Notes

  • pnpm i18n:sync also backfilled unrelated missing keys across the 26 non-English locales, which is why messages/ is broad.
  • Deferred: drag-and-drop import (Tauri's OS drag-drop would disable the HTML5 drop other tools rely on), multiple storage folders, streaming for files over 20 MB, PDF thumbnails, and a change-master-password flow — which, when it lands, must rewrap every object.
  • The security claims here deserve an independent review before they are advertised.

🤖 Generated with Claude Code

https://claude.ai/code/session_01No7es2PjF9SNQs22RYHcdM

itsmeakhil and others added 2 commits August 23, 2026 19:22
…nd CLI

Adds the Secure Files tool ("Files" in the UI): import files or folders and
store them as opaque `<32 random hex>.mydt` objects in a storage folder the
user picks. Original names, folder paths, types and contents are encrypted;
the app shows them only while the vault is unlocked.

Format (docs/MYDT_FORMAT.md, crates/mydt):
- Self-contained per file: Argon2id salt/params + per-file DEK wrapped by the
  key derived from the master password + XChaCha20-Poly1305 metadata and
  payload, with the header bound in as AAD. No index — listing scans the
  folder and decrypts headers, so a folder is portable and self-healing.
- Extracted into the standalone `mydt` crate: library plus a `mydt` CLI
  (encrypt/decrypt/info/ls) behind `--features cli`, so the desktop app and
  the CLI read and write identical objects. Wired into rust.yml.

Desktop:
- New `/api/v1/secure-files/*` routes: settings, list, import, patch, replace,
  export, delete, folder rename/delete; raw-bytes `secure_file_read` command
  for previews.
- The webview gate hands the verified master password to Rust once per unlock
  so Argon2id can derive the Secure Files key; it lives in AppState only and
  is dropped on lock (idle auto-lock included).
- Listing keeps a decrypted-metadata cache reconciled by an id-set diff, and
  import encrypts across threads with one directory fsync per batch. 10k
  files: import 1.75s, cold list 0.30s, warm list 24ms.

UI:
- Folder tree, list and grid views (both virtualized), preview for text,
  code, images and PDF, export with a plaintext warning, rename/move/replace,
  dismissible warning for unreadable objects. Files up to 20 MB.
- Fixes a latent bug in the shared s3-drive FilePreviewDialog, which used
  Radix Tooltip without a TooltipProvider and crashed the dialog subtree.

`pnpm i18n:sync` also backfilled unrelated missing keys across the 26
non-English locales, which is why messages/ is broad.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01No7es2PjF9SNQs22RYHcdM
Grid tiles show the actual image instead of a type icon, Drive-style.

Only the tiles currently on screen are decrypted (the hook is fed the same
visible window the virtualizer computes), at most three at a time, and the
queue re-prioritizes on scroll. Each image is downscaled to 256px and
re-encoded before it is kept, so the plaintext original is dropped right away
and the blob pool stays bounded — 150 thumbnails, oldest off-screen ones
revoked, everything revoked when the tool unmounts on lock.

Cache keys include size and mtime so Replace invalidates a stale thumbnail.
SVG skips the canvas (WKWebView cannot createImageBitmap it) and anything
that fails to decode falls back to its icon without retrying.

Also moves blobMime into lib/secure-files.ts so the preview and thumbnail
paths share one implementation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01No7es2PjF9SNQs22RYHcdM
@vercel

vercel Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mydevtools-tech Ready Ready Preview Aug 23, 2026 2:09pm

@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

0 finding(s)

No findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant