<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Deevnet FileSync</title><link>https://deevnet.github.io/deevnet-filesync/</link><description>Recent content on Deevnet FileSync</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://deevnet.github.io/deevnet-filesync/index.xml" rel="self" type="application/rss+xml"/><item><title>Build Tooling</title><link>https://deevnet.github.io/deevnet-filesync/docs/development/tooling/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/development/tooling/</guid><description>&lt;h1 id="build-tooling">
 Build Tooling
 &lt;a class="anchor" href="#build-tooling">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Tracking list. Development so far happens on the Deevnet build server. This page
records every tool added there &lt;strong>beyond what the Ansible-built builder provides&lt;/strong>, so that it can
later become a &lt;code>filesync&lt;/code> builder role, or be handled in another way.&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Tool&lt;/th>
 &lt;th>Version installed&lt;/th>
 &lt;th>Installed how&lt;/th>
 &lt;th>Needed for&lt;/th>
 &lt;th>Since&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>rust&lt;/code>, &lt;code>cargo&lt;/code>&lt;/td>
 &lt;td>1.99.0 (Fedora 43 packages)&lt;/td>
 &lt;td>&lt;code>dnf install rust cargo&lt;/code>&lt;/td>
 &lt;td>Building the Rust workspace&lt;/td>
 &lt;td>Prototype&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>clippy&lt;/code>, &lt;code>rustfmt&lt;/code>&lt;/td>
 &lt;td>1.99.0 (Fedora 43 packages)&lt;/td>
 &lt;td>&lt;code>dnf install clippy rustfmt&lt;/code>&lt;/td>
 &lt;td>Linting and formatting&lt;/td>
 &lt;td>Prototype&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MinIO container image&lt;/td>
 &lt;td>&lt;code>quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z&lt;/code>&lt;/td>
 &lt;td>Already present in local podman storage; public pulls of MinIO images now fail&lt;/td>
 &lt;td>A disposable local S3 endpoint for end-to-end tests&lt;/td>
 &lt;td>Prototype&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>hugo&lt;/code> (extended)&lt;/td>
 &lt;td>0.140.1&lt;/td>
 &lt;td>Already present on the build server&lt;/td>
 &lt;td>Building the docs site&lt;/td>
 &lt;td>Docs&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Rust crates are fetched by Cargo from crates.io at build time and pinned in &lt;code>Cargo.lock&lt;/code>. They are
project dependencies, not host tooling, so they are not listed here.&lt;/p></description></item><item><title>Linux</title><link>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/linux/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/linux/</guid><description>&lt;h1 id="linux-client">
 Linux Client
 &lt;a class="anchor" href="#linux-client">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Draft. &lt;strong>Phase:&lt;/strong> 1–3 (MVP). Linux is the first platform and the reference platform for
the sync engine. Common client requirements are on the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/requirements/">Clients&lt;/a> page.&lt;/p>
&lt;h2 id="distributions-and-filesystems">
 Distributions and filesystems
 &lt;a class="anchor" href="#distributions-and-filesystems">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>LNX-1 (MVP, proposed):&lt;/strong> Fedora (the current release) is the primary, tested distribution.
Other distributions are expected to work but are not tested in the MVP.&lt;/li>
&lt;li>&lt;strong>LNX-2 (MVP):&lt;/strong> Roots on ext4, btrfs, and xfs are supported.&lt;/li>
&lt;li>&lt;strong>LNX-3 (MVP, proposed):&lt;/strong> Roots on network filesystems (NFS, SMB) are allowed, but get rescan
only: inotify does not report changes made by other machines. The client says so when the
root is mounted.&lt;/li>
&lt;li>&lt;strong>LNX-4 (MVP, proposed):&lt;/strong> Works with SELinux in enforcing mode, without policy changes.&lt;/li>
&lt;/ul>
&lt;h2 id="agent">
 Agent
 &lt;a class="anchor" href="#agent">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>LNX-5 (MVP):&lt;/strong> The background agent runs as a &lt;strong>systemd user service&lt;/strong>, starting at login.&lt;/li>
&lt;li>&lt;strong>LNX-6 (MVP, proposed):&lt;/strong> Optional &amp;ldquo;keep running while logged out&amp;rdquo;, via systemd lingering,
for always-on machines.&lt;/li>
&lt;/ul>
&lt;h2 id="change-detection">
 Change detection
 &lt;a class="anchor" href="#change-detection">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>LNX-7 (MVP):&lt;/strong> inotify for live changes, plus periodic full rescans as a safety net (PERF-1).&lt;/li>
&lt;li>&lt;strong>LNX-8 (MVP, proposed):&lt;/strong> When the inotify watch limit (&lt;code>max_user_watches&lt;/code>) is too low for a
root, the client says so, explains the fix, and falls back to rescans. It never silently misses
changes.&lt;/li>
&lt;/ul>
&lt;h2 id="keys-and-secrets">
 Keys and secrets
 &lt;a class="anchor" href="#keys-and-secrets">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>LNX-9 (MVP, proposed):&lt;/strong> The device private key is protected by one of: the Secret Service
(GNOME Keyring / KWallet), a TPM 2.0, or a passphrase-encrypted key file for headless machines.&lt;/li>
&lt;/ul>
&lt;h2 id="packaging">
 Packaging
 &lt;a class="anchor" href="#packaging">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>LNX-10 (MVP, proposed):&lt;/strong> Distributed as an RPM for Fedora, plus a standalone binary tarball.&lt;/li>
&lt;li>&lt;strong>LNX-11 (Non-goal, proposed):&lt;/strong> Flatpak and Snap. Their sandboxes restrict filesystem access,
which conflicts with &amp;ldquo;any folder can be a root&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;h2 id="desktop-integration-phase-4">
 Desktop integration (Phase 4)
 &lt;a class="anchor" href="#desktop-integration-phase-4">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>LNX-12 (Phase 4):&lt;/strong> The tray app uses the StatusNotifierItem standard. On GNOME this needs
the AppIndicator extension, which should be documented.&lt;/li>
&lt;li>&lt;strong>LNX-13 (Phase 4):&lt;/strong> Notifications use the freedesktop notification standard.&lt;/li>
&lt;/ul>
&lt;h2 id="open-questions">
 Open Questions
 &lt;a class="anchor" href="#open-questions">#&lt;/a>
&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>Other distributions:&lt;/strong> is Fedora-only testing right for the MVP, or does Debian/Ubuntu also
matter early?&lt;/li>
&lt;li>&lt;strong>Headless/server machines:&lt;/strong> should a machine without a desktop session (e.g. a Deevnet VM)
be a supported device?&lt;/li>
&lt;/ol></description></item><item><title>Metadata Matrix</title><link>https://deevnet.github.io/deevnet-filesync/docs/requirements/metadata/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/requirements/metadata/</guid><description>&lt;h1 id="metadata-matrix">
 Metadata Matrix
 &lt;a class="anchor" href="#metadata-matrix">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Decided (2026-10-15). This page backs requirements META-1 to META-7.&lt;/p>
&lt;p>A file is more than its bytes. Each platform keeps a different set of names, timestamps,
permissions, and extra data alongside the bytes. This page sets out what each platform can
represent, and records, for each kind of metadata, whether FileSync:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>syncs&lt;/strong> it,&lt;/li>
&lt;li>&lt;strong>maps&lt;/strong> it to an approximation on platforms that can&amp;rsquo;t represent it exactly,&lt;/li>
&lt;li>keeps it &lt;strong>local-only&lt;/strong> (it never leaves the device), or&lt;/li>
&lt;li>&lt;strong>skips&lt;/strong> the file (refuses to sync it, and tells the user).&lt;/li>
&lt;/ul>
&lt;p>The hub itself is not a constraint. Metadata is stored inside the encrypted file records, so the
hub can carry whatever we decide. The limits come from the &lt;em>receiving&lt;/em> platform.&lt;/p></description></item><item><title>Prototype</title><link>https://deevnet.github.io/deevnet-filesync/docs/development/prototype/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/development/prototype/</guid><description>&lt;h1 id="prototype">
 Prototype
 &lt;a class="anchor" href="#prototype">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Working (2026-10-15). This is the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/roadmap/#phase-p-prototype">Phase P&lt;/a> prototype:
the &lt;code>filesync&lt;/code> CLI and the &lt;code>filesync-core&lt;/code> library, in &lt;code>crates/&lt;/code>.&lt;/p>
&lt;h2 id="what-it-does">
 What it does
 &lt;a class="anchor" href="#what-it-does">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>Encrypted hub on any S3-compatible store (tested against MinIO), or on a local directory.&lt;/li>
&lt;li>Roots, mounted at any path, with a different path on each device.&lt;/li>
&lt;li>&lt;code>status&lt;/code>, &lt;code>sync&lt;/code> (push now), and &lt;code>pull&lt;/code> (pull now), plus &lt;code>run --interval N&lt;/code> for unattended
polling.&lt;/li>
&lt;li>Three-way sync: changes flow both ways, conflicting edits keep both versions as a conflict copy,
and an edit beats a delete.&lt;/li>
&lt;li>Receive-only mounts (&lt;code>mount --receive-only&lt;/code>).&lt;/li>
&lt;li>Portable-name checks (Windows-invalid names and case/normalization collisions are skipped, with
a warning), symlinks skipped, a per-file size limit (100 MiB by default).&lt;/li>
&lt;li>Version history (&lt;code>history&lt;/code>) and restore of a whole root or one path from any snapshot
(&lt;code>restore&lt;/code>).&lt;/li>
&lt;li>Refuses to sync a root whose folder is missing, or to propagate &amp;ldquo;everything deleted&amp;rdquo; without
&lt;code>--allow-mass-delete&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h2 id="what-it-deliberately-does-not-do-yet">
 What it deliberately does not do (yet)
 &lt;a class="anchor" href="#what-it-deliberately-does-not-do-yet">#&lt;/a>
&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Shortcut&lt;/th>
 &lt;th>Final design&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>One shared hub key, copied to each device by hand&lt;/td>
 &lt;td>PKI device identity, enrollment, revocation (SEC-7, SEC-9..12)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Whole-file blobs, no chunking&lt;/td>
 &lt;td>Content-defined chunking (PERF-3)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Blob sizes visible to the hub&lt;/td>
 &lt;td>Padding or chunking to hide sizes (SEC-2)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Every snapshot lists every path&lt;/td>
 &lt;td>Incremental snapshots or a compacted index&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>No garbage collection or retention&lt;/td>
 &lt;td>VER-2, VER-6, HUB-7&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Polling only (&lt;code>run --interval&lt;/code>)&lt;/td>
 &lt;td>Filesystem watching plus rescans (LNX-7)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>One static S3 credential, with delete rights&lt;/td>
 &lt;td>Per-device, least-privilege credentials (HUB-6, HUB-7)&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="build-and-test">
 Build and test
 &lt;a class="anchor" href="#build-and-test">#&lt;/a>
&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>cargo build --release &lt;span style="color:#75715e"># target/release/filesync&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cargo test &lt;span style="color:#75715e"># unit tests, plus two-device tests on a directory hub&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="try-it-with-two-devices-on-one-machine">
 Try it with two &amp;ldquo;devices&amp;rdquo; on one machine
 &lt;a class="anchor" href="#try-it-with-two-devices-on-one-machine">#&lt;/a>
&lt;/h2>
&lt;p>Each device is a config directory plus a state directory. A directory hub needs no credentials:&lt;/p></description></item><item><title>Windows</title><link>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/windows/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/windows/</guid><description>&lt;h1 id="windows-client">
 Windows Client
 &lt;a class="anchor" href="#windows-client">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Draft. &lt;strong>Phase:&lt;/strong> 4. Common client requirements are on the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/requirements/">Clients&lt;/a> page.&lt;/p>
&lt;h2 id="versions-and-filesystems">
 Versions and filesystems
 &lt;a class="anchor" href="#versions-and-filesystems">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>WIN-1 (Phase 4, proposed):&lt;/strong> Windows 11. Windows 10 reached end of support in October 2025.&lt;/li>
&lt;li>&lt;strong>WIN-2 (Phase 4):&lt;/strong> Roots on NTFS. ReFS, FAT32, and exFAT are not supported for roots.&lt;/li>
&lt;/ul>
&lt;h2 id="agent">
 Agent
 &lt;a class="anchor" href="#agent">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>WIN-3 (Phase 4, proposed):&lt;/strong> The agent runs &lt;strong>per user&lt;/strong>, started at sign-in, not as a
Windows Service. A service runs as a different account, which complicates access to the user&amp;rsquo;s
files and the user&amp;rsquo;s key store.&lt;/li>
&lt;/ul>
&lt;h2 id="change-detection">
 Change detection
 &lt;a class="anchor" href="#change-detection">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>WIN-4 (Phase 4):&lt;/strong> &lt;code>ReadDirectoryChangesW&lt;/code> for live changes, plus periodic rescans. The NTFS
change journal (USN) is not used, because it needs administrator rights.&lt;/li>
&lt;/ul>
&lt;h2 id="file-system-behavior">
 File system behavior
 &lt;a class="anchor" href="#file-system-behavior">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>WIN-5 (Phase 4):&lt;/strong> Long paths (over 260 characters) are handled whether or not the system&amp;rsquo;s
long-path setting is enabled.&lt;/li>
&lt;li>&lt;strong>WIN-6 (Phase 4):&lt;/strong> &lt;strong>Locked files.&lt;/strong> Office and other applications hold files open with
exclusive locks. The client reads with shared access, retries files it cannot read, and
delays applying an incoming change to a locked file. It never fails the whole sync because of
one locked file.&lt;/li>
&lt;li>&lt;strong>WIN-7 (Phase 4):&lt;/strong> Incoming changes are written to a temporary file and swapped into place
atomically, so applications never see a half-written file.&lt;/li>
&lt;li>&lt;strong>WIN-8 (Phase 4):&lt;/strong> Names follow the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/requirements/metadata/">Metadata Matrix&lt;/a> name policy: reserved
names, forbidden characters, trailing dots and spaces, and case-only collisions.&lt;/li>
&lt;li>&lt;strong>WIN-9 (Phase 4, proposed):&lt;/strong> Tolerates antivirus scanning (Microsoft Defender) briefly
locking newly written files.&lt;/li>
&lt;/ul>
&lt;h2 id="overlap-with-onedrive">
 Overlap with OneDrive
 &lt;a class="anchor" href="#overlap-with-onedrive">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>WIN-10 (Phase 4):&lt;/strong> Windows 11 often redirects Documents, Desktop, and Pictures into OneDrive
(&amp;ldquo;Known Folder Move&amp;rdquo;). The client detects a root inside a OneDrive-managed folder and warns
(ROOT-8).&lt;/li>
&lt;/ul>
&lt;h2 id="keys-and-secrets">
 Keys and secrets
 &lt;a class="anchor" href="#keys-and-secrets">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>WIN-11 (Phase 4, proposed):&lt;/strong> The device private key is held by the TPM (through the Windows
platform crypto provider) where available, or else protected with DPAPI.&lt;/li>
&lt;/ul>
&lt;h2 id="packaging-and-ui">
 Packaging and UI
 &lt;a class="anchor" href="#packaging-and-ui">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>WIN-12 (Phase 4, proposed):&lt;/strong> A per-user installer that does not need administrator rights.&lt;/li>
&lt;li>&lt;strong>WIN-13 (Phase 4):&lt;/strong> A notification-area (tray) icon and Windows toast notifications (UI-1).&lt;/li>
&lt;/ul>
&lt;h2 id="open-questions">
 Open Questions
 &lt;a class="anchor" href="#open-questions">#&lt;/a>
&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>Code signing:&lt;/strong> unsigned binaries trigger SmartScreen warnings. Is a code-signing
certificate worth buying for a personal tool, or are the warnings acceptable?&lt;/li>
&lt;/ol></description></item><item><title>Cloud Hub</title><link>https://deevnet.github.io/deevnet-filesync/docs/requirements/hub/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/requirements/hub/</guid><description>&lt;h1 id="cloud-hub">
 Cloud Hub
 &lt;a class="anchor" href="#cloud-hub">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Draft. Requirements for the storage side of the system: the hub that every device
syncs through. Core requirements are on the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/">Requirements&lt;/a> page.&lt;/p>
&lt;p>The hub is &lt;strong>storage only&lt;/strong>. It holds encrypted objects and runs no FileSync code. All
intelligence (sync decisions, encryption, conflict handling) lives in the clients. That keeps the
provider replaceable and keeps it from ever needing to understand the data.&lt;/p>
&lt;h2 id="backend-model">
 Backend model
 &lt;a class="anchor" href="#backend-model">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>BE-0 (MVP):&lt;/strong> Only one backend is active at a time. That one backend is the hub.&lt;/li>
&lt;li>&lt;strong>BE-1 (MVP):&lt;/strong> AWS S3 is the MVP backend.&lt;/li>
&lt;li>&lt;strong>BE-2 (MVP):&lt;/strong> The backend interface is narrow and primitive: put, get, list, delete, and a
conditional write (compare-and-swap) for coordination. New backends implement only that
interface.&lt;/li>
&lt;li>&lt;strong>BE-4 (MVP):&lt;/strong> The sync engine, crypto, and hub format do not depend on anything AWS-specific.
Anything AWS-specific (authentication, request signing, provider quirks) stays inside the S3
backend adapter.&lt;/li>
&lt;li>&lt;strong>BE-3 (Later):&lt;/strong> Self-hosted storage, e.g. MinIO on Deevnet infrastructure, SFTP, or a local or
NAS path.&lt;/li>
&lt;li>&lt;strong>BE-5 (Later):&lt;/strong> Other S3-compatible providers (Backblaze B2, Cloudflare R2, Wasabi), and
consumer cloud drives (Google Drive, OneDrive, Dropbox) used as dumb storage.&lt;/li>
&lt;li>&lt;strong>BE-6 (Later):&lt;/strong> A &lt;strong>data migration process&lt;/strong> moves the hub from one backend to another (e.g.
AWS S3 → self-hosted) without re-uploading from every device.&lt;/li>
&lt;li>&lt;strong>BE-7 (Non-goal):&lt;/strong> Mirroring to multiple backends at the same time.&lt;/li>
&lt;/ul>
&lt;h2 id="what-the-hub-holds">
 What the hub holds
 &lt;a class="anchor" href="#what-the-hub-holds">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>HUB-1 (MVP):&lt;/strong> Everything stored in the hub is encrypted before it leaves a device. Object
names are opaque and reveal nothing about file names, paths, or roots (SEC-1, SEC-2).&lt;/li>
&lt;li>&lt;strong>HUB-2 (MVP):&lt;/strong> The hub layout and object formats are a versioned, documented specification
(IND-2). The hub records its format version, and a client refuses to write to a hub whose
format version it does not understand.&lt;/li>
&lt;li>&lt;strong>HUB-3 (MVP, proposed):&lt;/strong> The hub stores no plaintext metadata about the user beyond what the
provider inevitably sees: object count, object sizes, and access times and IP addresses.&lt;/li>
&lt;/ul>
&lt;h2 id="coordination">
 Coordination
 &lt;a class="anchor" href="#coordination">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>HUB-4 (MVP):&lt;/strong> Devices coordinate safely through plain object storage using conditional
writes. Two devices updating at the same time never silently lose one update. (AWS S3 supports
conditional writes; support among other S3-compatible providers varies, which BE-5 has to
check.)&lt;/li>
&lt;li>&lt;strong>HUB-5 (MVP, proposed):&lt;/strong> No server-side compute in the MVP: no Lambda functions, no event
notifications, no provider-specific services. Change detection is client polling (SYNC-3).&lt;/li>
&lt;/ul>
&lt;h2 id="access-control-and-protection">
 Access control and protection
 &lt;a class="anchor" href="#access-control-and-protection">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>HUB-6 (MVP, proposed):&lt;/strong> Every device has its own credential, scoped to only the FileSync
bucket (or prefix). Revoking a device (SEC-5) also removes its storage access. A receive-only
device (ROOT-9), such as an Android phone, gets a read-only credential.&lt;/li>
&lt;li>&lt;strong>HUB-7 (MVP, proposed):&lt;/strong> &lt;strong>A compromised device cannot destroy the hub.&lt;/strong> Day-to-day device
credentials can add data but cannot permanently delete or overwrite history. Permanent
deletion (garbage collection, VER-6) uses a separate, more privileged credential. This
protects against ransomware or a stolen laptop wiping out every version.&lt;/li>
&lt;li>&lt;strong>HUB-8 (MVP, proposed):&lt;/strong> Provider-side encryption at rest (e.g. SSE-S3) is enabled as
defense in depth. It is &lt;em>in addition to&lt;/em> FileSync&amp;rsquo;s end-to-end encryption, never instead of it.&lt;/li>
&lt;/ul>
&lt;h2 id="setup-and-operation">
 Setup and operation
 &lt;a class="anchor" href="#setup-and-operation">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>HUB-9 (MVP, proposed):&lt;/strong> Setting up the hub (bucket, access policies, device credentials) is
documented and scriptable. The CLI can generate the policy documents; clicking through a
provider console is never required.&lt;/li>
&lt;li>&lt;strong>HUB-10 (MVP):&lt;/strong> The user chooses the provider account, region, and bucket. FileSync never
creates or requires an account with anyone else.&lt;/li>
&lt;/ul>
&lt;h2 id="cost">
 Cost
 &lt;a class="anchor" href="#cost">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>PERF-2 (MVP):&lt;/strong> Request counts and polling frequency are kept modest and configurable,
because cloud object storage bills per request as well as per GB.&lt;/li>
&lt;li>&lt;strong>HUB-11 (MVP, proposed):&lt;/strong> The docs include a cost model: expected monthly cost for a typical
workload (e.g. 20 GB, 3 devices, polling every few minutes).&lt;/li>
&lt;li>&lt;strong>HUB-12 (Later, proposed):&lt;/strong> The CLI reports hub usage (stored bytes, retained versions, trash),
so that retention policies can be tuned against cost.&lt;/li>
&lt;/ul>
&lt;h2 id="open-questions">
 Open Questions
 &lt;a class="anchor" href="#open-questions">#&lt;/a>
&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>Device credentials for AWS (HUB-6):&lt;/strong> short-lived credentials via &lt;strong>AWS IAM Roles
Anywhere&lt;/strong> (the device certificate from the FileSync CA is exchanged for temporary AWS
credentials, with no long-lived keys on devices), or a scoped static access key per device?
Roles Anywhere fits the PKI direction well, and is AWS-only, so it would live inside the S3
adapter.&lt;/li>
&lt;li>&lt;strong>Protection mechanism (HUB-7):&lt;/strong> S3 bucket versioning plus a no-delete policy for devices,
S3 Object Lock, or both? What is the privileged credential for garbage collection: the
offline CA, or one designated device?&lt;/li>
&lt;li>&lt;strong>Provisioning tool (HUB-9):&lt;/strong> CLI-generated policy documents applied by hand, or an
infrastructure-as-code definition (Terraform or Ansible, matching Deevnet practice)?&lt;/li>
&lt;/ol></description></item><item><title>macOS</title><link>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/macos/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/macos/</guid><description>&lt;h1 id="macos-client">
 macOS Client
 &lt;a class="anchor" href="#macos-client">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Draft. &lt;strong>Phase:&lt;/strong> 5. Common client requirements are on the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/requirements/">Clients&lt;/a> page.&lt;/p>
&lt;h2 id="versions-and-hardware">
 Versions and hardware
 &lt;a class="anchor" href="#versions-and-hardware">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-1 (Phase 5, proposed):&lt;/strong> The two most recent major macOS releases, on Apple Silicon. Intel
Macs are not supported.&lt;/li>
&lt;li>&lt;strong>MAC-2 (Phase 5):&lt;/strong> Roots on APFS. Both the default case-insensitive variant and the
case-sensitive variant are supported.&lt;/li>
&lt;/ul>
&lt;h2 id="agent">
 Agent
 &lt;a class="anchor" href="#agent">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-3 (Phase 5):&lt;/strong> The agent runs as a per-user &lt;strong>launchd agent&lt;/strong>, started at login.&lt;/li>
&lt;/ul>
&lt;h2 id="change-detection">
 Change detection
 &lt;a class="anchor" href="#change-detection">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-4 (Phase 5):&lt;/strong> FSEvents for live changes, plus periodic rescans.&lt;/li>
&lt;/ul>
&lt;h2 id="privacy-permissions">
 Privacy permissions
 &lt;a class="anchor" href="#privacy-permissions">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-5 (Phase 5):&lt;/strong> macOS requires the user&amp;rsquo;s explicit consent before an app can read
Desktop, Documents, Downloads, iCloud Drive, or removable and network volumes. The client
asks for access when a root is mounted in one of these places, explains why, and reports
clearly when access is denied rather than treating the folder as empty. &lt;em>An empty-looking root
must never be synced as &amp;ldquo;everything was deleted&amp;rdquo;.&lt;/em>&lt;/li>
&lt;/ul>
&lt;h2 id="overlap-with-icloud">
 Overlap with iCloud
 &lt;a class="anchor" href="#overlap-with-icloud">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-6 (Phase 5):&lt;/strong> With &amp;ldquo;Desktop &amp;amp; Documents Folders&amp;rdquo; in iCloud Drive, those folders are
managed by iCloud, and &amp;ldquo;Optimize Mac Storage&amp;rdquo; can replace files with placeholders. The client
detects a root inside iCloud-managed storage and warns (ROOT-8). It skips placeholders rather
than triggering downloads.&lt;/li>
&lt;/ul>
&lt;h2 id="file-system-behavior">
 File system behavior
 &lt;a class="anchor" href="#file-system-behavior">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-7 (Phase 5):&lt;/strong> Names follow the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/requirements/metadata/">Metadata Matrix&lt;/a> name policy. In
particular, NFC and NFD forms of the same name are the same file on APFS.&lt;/li>
&lt;li>&lt;strong>MAC-8 (Phase 5):&lt;/strong> Package/bundle directories are synced as directories (see the Metadata
Matrix).&lt;/li>
&lt;/ul>
&lt;h2 id="keys-and-secrets">
 Keys and secrets
 &lt;a class="anchor" href="#keys-and-secrets">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-9 (Phase 5, proposed):&lt;/strong> The device private key is held in the Secure Enclave where the
key algorithm allows it (P-256 only), or in the Keychain otherwise.&lt;/li>
&lt;/ul>
&lt;h2 id="distribution-and-ui">
 Distribution and UI
 &lt;a class="anchor" href="#distribution-and-ui">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>MAC-10 (Phase 5):&lt;/strong> A menu bar app with status, push now, pull now, and notifications (UI-1).&lt;/li>
&lt;/ul>
&lt;h2 id="open-questions">
 Open Questions
 &lt;a class="anchor" href="#open-questions">#&lt;/a>
&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>Signing and notarization:&lt;/strong> distributing a macOS app without Gatekeeper warnings needs a
paid Apple Developer membership and Apple&amp;rsquo;s notarization service. That is a dependency on
Apple. For a personal tool, is building locally (or approving an unsigned app once) acceptable
instead?&lt;/li>
&lt;/ol></description></item><item><title>Android</title><link>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/android/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://deevnet.github.io/deevnet-filesync/docs/requirements/clients/android/</guid><description>&lt;h1 id="android-client">
 Android Client
 &lt;a class="anchor" href="#android-client">#&lt;/a>
&lt;/h1>
&lt;p>&lt;strong>Status:&lt;/strong> Draft. &lt;strong>Phase:&lt;/strong> 6. Common client requirements are on the 
 &lt;a href="https://deevnet.github.io/deevnet-filesync/deevnet-filesync/docs/requirements/">Clients&lt;/a> page.&lt;/p>
&lt;p>The Android client is an app built on the same Rust core, called from Kotlin.&lt;/p>
&lt;h2 id="role-read-only-access">
 Role: read-only access
 &lt;a class="anchor" href="#role-read-only-access">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>AND-10 (Phase 6):&lt;/strong> &lt;strong>Android is a read-only device&lt;/strong> (a receive-only device, ROOT-9). It
downloads and presents files from the hub; files never originate on, or are changed from,
Android.&lt;/li>
&lt;/ul>
&lt;p>This removes most of what makes Android hard:&lt;/p></description></item></channel></rss>