|
| 1 | +# FileShot Virtual Drive (True Volume) — Spec + Implementation Plan |
| 2 | + |
| 3 | +Status: **Not implemented yet** (current app uses `SUBST` mapping to a local folder; that cannot report custom capacity/free space in Explorer). |
| 4 | + |
| 5 | +This document defines the **hard requirements** and a realistic implementation path for a true FileShot drive that appears in the OS file explorer as a mounted volume with a tier-based quota. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## 1) Hard requirements (non-negotiable) |
| 10 | + |
| 11 | +### 1.1 Appears as a real drive / volume |
| 12 | +- **Windows:** shows under **“This PC”** as a drive letter (e.g. `F:`). |
| 13 | +- **macOS:** shows in Finder as a mounted volume. |
| 14 | +- **Linux:** shows as a mounted filesystem (e.g. under `/mnt/fileshot` or user-chosen). |
| 15 | + |
| 16 | +### 1.2 Capacity + free space must reflect FileShot tier quota |
| 17 | +- Explorer/Finder must show: |
| 18 | + - **Total size** = tier quota (e.g. Free = **50 GB**) |
| 19 | + - **Free space** = quota remaining (quota - usage) |
| 20 | +- This must **not** mirror the host disk (no “it looks like C:” / “it’s just a folder”). |
| 21 | + |
| 22 | +### 1.3 File operations map to FileShot cloud (ZKE) |
| 23 | +- Creating/copying a file into the drive uploads it to FileShot. |
| 24 | +- Browsing the drive shows the user’s remote FileShot files/folders. |
| 25 | +- Opening/reading a file downloads and decrypts it locally. |
| 26 | +- Deleting a file deletes it remotely (with safety settings/confirmation behavior defined below). |
| 27 | + |
| 28 | +### 1.4 Optional password support |
| 29 | +- Users must be able to set an **optional password** per upload (or per folder default) from the drive workflow. |
| 30 | +- This must remain compatible with FileShot’s **zero-knowledge encryption** model. |
| 31 | + |
| 32 | +--- |
| 33 | + |
| 34 | +## 2) Constraints we must respect |
| 35 | + |
| 36 | +### 2.1 Filesystem drivers are OS-specific |
| 37 | +To report custom volume size/free space, we need a **real filesystem mount**: |
| 38 | +- Windows: **WinFsp** (chosen) or Dokan-style user-mode filesystem |
| 39 | +- macOS: macFUSE (or native FS APIs) |
| 40 | +- Linux: FUSE |
| 41 | + |
| 42 | +Electron alone cannot do this; it needs a companion native component. |
| 43 | + |
| 44 | +#### Windows choice (decision) |
| 45 | + |
| 46 | +We will implement the Windows “true drive” using **WinFsp**. |
| 47 | + |
| 48 | +Why: |
| 49 | +- It’s a mature, widely-used user-mode filesystem stack. |
| 50 | +- It supports filesystem statistics reporting (total/free bytes), which we must control to match tier quota. |
| 51 | +- It supports a FUSE-compatibility path, which helps keep the long-term cross-platform story coherent. |
| 52 | + |
| 53 | +Non-goal (explicit): `SUBST` can never meet the “Explorer shows tier quota capacity” requirement, because it inherits capacity from the underlying disk. |
| 54 | + |
| 55 | +### 2.2 Encryption model |
| 56 | +FileShot’s ZKE model means: |
| 57 | +- The server must never learn the plaintext |
| 58 | +- Client must encrypt before upload |
| 59 | +- Client must decrypt after download |
| 60 | + |
| 61 | +The current desktop app already has ZKE streaming container support in `utils/zke-stream.js`. |
| 62 | + |
| 63 | +### 2.3 Explorer/Finder cannot prompt for “password” mid-copy |
| 64 | +File managers don’t provide a standard UI to prompt for extra metadata when copying. |
| 65 | +So we need a deterministic UX mechanism (see §5). |
| 66 | + |
| 67 | +--- |
| 68 | + |
| 69 | +## 3) Proposed architecture (no compromises) |
| 70 | + |
| 71 | +### 3.1 Split responsibilities |
| 72 | + |
| 73 | +**A) Electron app (UI + auth + settings)** |
| 74 | +- Login, store auth token |
| 75 | +- Shows status (mounted/unmounted, quota used/remaining) |
| 76 | +- Starts/stops the mount service |
| 77 | +- Handles configuration (drive letter, mount point, sync rules) |
| 78 | + |
| 79 | +**B) `fileshot-drive` mount service (native executable)** |
| 80 | +- Implements filesystem callbacks (list/read/write/delete/etc) |
| 81 | +- Reports filesystem statistics (total bytes, free bytes) |
| 82 | +- Streams encryption/decryption |
| 83 | +- Talks to FileShot API using the user token |
| 84 | + |
| 85 | +Electron communicates with the service over a local IPC channel: |
| 86 | +- Windows named pipe / localhost loopback HTTP |
| 87 | +- macOS/Linux: Unix domain socket / localhost |
| 88 | + |
| 89 | +### 3.2 Why a separate service is required |
| 90 | +- Node/Electron cannot reliably implement a filesystem driver |
| 91 | +- A dedicated service can be: |
| 92 | + - restarted independently |
| 93 | + - kept minimal for security |
| 94 | + - packaged per OS |
| 95 | + |
| 96 | +--- |
| 97 | + |
| 98 | +## 4) Filesystem semantics |
| 99 | + |
| 100 | +### 4.1 Path layout |
| 101 | +Default layout: |
| 102 | +- `/` (root) |
| 103 | + - `My Files/` (remote user root) |
| 104 | + - `Shared With Me/` (optional, later) |
| 105 | + - `.fileshot/` (special config folder; see §5) |
| 106 | + |
| 107 | +We can start simpler: `/` == user’s file root. |
| 108 | + |
| 109 | +### 4.2 Upload behavior |
| 110 | +When a file is copied into the mounted drive: |
| 111 | +- The mount service receives write operations |
| 112 | +- It buffers to a local temp file |
| 113 | +- On close/flush, it: |
| 114 | + 1) encrypts to FSZK (streaming) |
| 115 | + 2) performs pre-upload |
| 116 | + 3) uploads chunks |
| 117 | + 4) finalizes |
| 118 | + 5) exposes a stable remote entry in the drive |
| 119 | + |
| 120 | +### 4.3 Download behavior |
| 121 | +When a file is opened: |
| 122 | +- Service downloads encrypted blob |
| 123 | +- Decrypts on the fly or to temp |
| 124 | +- Serves plaintext bytes to the filesystem reader |
| 125 | + |
| 126 | +### 4.4 Delete behavior |
| 127 | +Options (must be decided): |
| 128 | +- Immediate remote delete |
| 129 | +- Or move-to-trash semantics (special folder) |
| 130 | + |
| 131 | +### 4.5 Offline / caching |
| 132 | +- Minimal v1: small read cache + write staging only |
| 133 | +- Later: full offline pinning |
| 134 | + |
| 135 | +--- |
| 136 | + |
| 137 | +## 5) Optional password UX (works in file explorers) |
| 138 | + |
| 139 | +We need a mechanism that does not require interactive prompts. |
| 140 | + |
| 141 | +### Option A (recommended): folder-level config file |
| 142 | +- In any folder, user can create/edit: |
| 143 | + - `.fileshot/settings.json` |
| 144 | +- Example keys: |
| 145 | + - `defaultPassphrase` (or password hint; careful) |
| 146 | + - `requirePassphrase: true/false` |
| 147 | + - `defaultExpirationHours` |
| 148 | + - `defaultMaxDownloads` |
| 149 | + |
| 150 | +Security note: storing passphrases in plaintext on disk is risky. |
| 151 | +Better: store an identifier that tells Electron to fetch the secret from OS keychain. |
| 152 | + |
| 153 | +### Option B: sidecar metadata files |
| 154 | +- For `photo.jpg` allow `photo.jpg.fileshot.json` |
| 155 | +- Contains upload settings for that one file |
| 156 | + |
| 157 | +### Option C: extended attributes |
| 158 | +- Use xattrs/ADS where supported |
| 159 | +- Not cross-platform reliable; keep as later enhancement |
| 160 | + |
| 161 | +--- |
| 162 | + |
| 163 | +## 6) Cross-platform plan |
| 164 | + |
| 165 | +### Phase 1: Windows true drive (priority) |
| 166 | +- Implement `fileshot-drive.exe` using **WinFsp** (user-mode filesystem). |
| 167 | +- Must support: |
| 168 | + - directory listing |
| 169 | + - file read |
| 170 | + - file create/write/close->upload |
| 171 | + - delete |
| 172 | + - **disk free/total reporting based on tier quota** |
| 173 | + |
| 174 | +### Phase 2: macOS mount |
| 175 | +- Implement `fileshot-drive` via macFUSE |
| 176 | + |
| 177 | +### Phase 3: Linux mount |
| 178 | +- Implement via FUSE3 |
| 179 | + |
| 180 | +--- |
| 181 | + |
| 182 | +## 7) Release/build requirements |
| 183 | + |
| 184 | +- GitHub Actions builds installers for: |
| 185 | + - Windows (NSIS) |
| 186 | + - macOS (DMG/ZIP) |
| 187 | + - Linux (AppImage/DEB/RPM) |
| 188 | +- The mount service binaries must be included inside the Electron app bundle and signed/notarized later. |
| 189 | + |
| 190 | +--- |
| 191 | + |
| 192 | +## 8) Acceptance tests (what “done” means) |
| 193 | + |
| 194 | +### Windows |
| 195 | +- In Explorer, `FileShot (F:)` shows: |
| 196 | + - Capacity: **50 GB** for Free tier |
| 197 | + - Free space decreases as usage increases |
| 198 | +- Copying a file into `F:` uploads it to FileShot and the file appears in the user’s account |
| 199 | +- Opening a file in `F:` downloads/decrypts and opens correctly |
| 200 | +- No “C drive mirror” behavior |
| 201 | + |
| 202 | +### macOS/Linux |
| 203 | +- Same semantics, appropriate mount points |
| 204 | + |
| 205 | +--- |
| 206 | + |
| 207 | +## 9) Current state in this repo |
| 208 | + |
| 209 | +- There is an existing “FileShot Drive” feature implemented with `SUBST` mapping to `app.getPath('userData')/vault/drive-inbox`. |
| 210 | +- This is useful as a drop-folder workflow, but it **cannot** meet the quota/capacity requirement. |
| 211 | + |
| 212 | +Next step is implementing the native mount service and switching the UI to prefer the true mount. |
0 commit comments