OneSync, a drive-letter OneDrive/SharePoint sync client on Dokan + Graph (.NET 8), with three war stories
Side project that turned into a real thing. Wanted a Windows drive-letter sync client for OneDrive/SharePoint with a few specific things off-the-shelf options didn't quite combine (image thumbnails working in Explorer for cloud-mounted files, accurate cloud-quota numbers in the drive-properties dialog refreshed from Graph, local-first sync semantics where files exist as real NTFS first and sync in the background, zero telemetry). Was also curious whether I could build it. Sharing because the war stories along the way might save someone else the hours. Disclosure: I wrote it, MIT licence, link at the bottom.
Stack: .NET 8 single-file self-contained exe, DokanNet for the user-mode to kernel-mode FS bridge, MSAL + Microsoft.Graph SDK, LiteDB for the upload queue and metadata, WiX v6 for the MSI and Burn bundle.
Three engineering bits that were more interesting than I expected:
Office AutoSave for third-party providers doesn't have a documented API. Microsoft maintains an internal allowlist of cloud providers Office considers worthy of native AutoSave, and we are not on it. I spent the better part of two minor releases building full CFAPI integration (sync root registration, placeholder lifecycle, the callbacks) before discovering CFAPI registration alone doesn't get you in. The working bridge: register as the default handler for .docx/.xlsx/.pptx, intercept the open, launch Office with `ms-word:ofe|u|<direct SharePoint url>`. Office opens it from SharePoint and AutoSave + co-auth light up. Important detail if you try this: it's the DIRECT SharePoint file URL, not the Graph /_layouts/15/Doc.aspx URL (the latter opens Office Web Viewer, which is exactly what you don't want).
Dokan callbacks are synchronous from the kernel. FindFilesWithPattern enters synchronously, anything that blocks in there hangs Explorer. The first version called Graph synchronously during folder enumeration via .GetAwaiter().GetResult() (I know, I know). Worked fine until Graph went into 429 cooldown, at which point opening a folder hung Explorer for ten minutes. I learned a lot in those ten minutes about how Explorer's UI thread feels under those conditions. Current behaviour: if Graph is in cooldown, folder browse returns immediately with on-disk placeholders, file hydration kicks off via Task.Run, returns a 0-byte placeholder until cooldown lifts.
WAM broker fallback when client_id is invalid. Initialise MSAL with WithBroker(brokerOptions) and pass a bogus client_id (e.g. the placeholder GUIDs shipped in config.json that admins are supposed to replace), WAM can't complete the broker handoff and silently falls back to the system browser. User then sees an AAD error page (AADSTS700038) with no link back to "your config.json wasn't filled in". Fixed in 1.3.3 by validating config GUIDs at load time and popping an explicit dialog before MSAL ever runs. Should have done that from day one.
https://github.com/madeyouclickstudio/OneSync
Open to any feedback. Honest caveat: dogfooding with a handful of users, not a full estate, so the load-handling code is engineered but not yet load-tested. Anyone wanting to throw a real workload at it would teach me a lot.