Expose supported archives, filesystem images, and nested disk/container images as operating-system mounts. The UI and CLI must offer read-only or read-write mounting only when the selected image, its backing source, and the active mount backend can actually satisfy the requested semantics.
A writable offline rebuild is not automatically a writable mount. FormatCapabilities.CanModify answers whether an existing container can be modified through the archive/image API; mountability is determined by the mount-grade filesystem/provider contracts and their per-image probe result.
If CompressionWorkbench mounts it, CompressionWorkbench parses it. Every source layer must be decoded by CompressionWorkbench before an OS-facing backend receives the namespace. The only valid boundary is:
source bytes -> CompressionWorkbench container/archive/partition/filesystem parsers -> IFilesystemSession -> FUSE/Dokan
Never delegate source interpretation to the host's filesystem or mount stack. This applies even when the current host happens to support the filesystem natively: ext4, NTFS, FAT, XFS, APFS, Btrfs, ZFS, and every other mounted format still go through CompressionWorkbench's own layers. Host support is irrelevant because the same image must resolve on an OS that does not understand that format. FUSE/Dokan are transport adapters for an already-parsed namespace, not alternate filesystem decoders.
- Do not advertise writable mounting merely because a format can be recreated or rewritten offline.
- Do not emulate missing mutation primitives by silently replacing the entire image for every filesystem call.
- Do not put Dokan/FUSE-specific concepts into format implementations.
- Do not require a native kernel-mode IFS driver before the userspace filesystem contract is proven.
- Do not weaken filesystem-driver-safety or round-trip tests to gain mount checkmarks.
- Add
Compression.Mountingtargetingnet10.0. - Define
MountAccessMode(ReadOnly,ReadWrite). - Define
MountBackendCapabilities,MountRequest,MountPlan,IMountBackend, andIMountSession. - Add a capability resolver that combines:
- backend availability and supported operations;
- source stream/file writability;
IFilesystemDriverProvider.ProbeFilesystem;FilesystemDriverProfile.CanMount/CanMountWritable;- the exact
FilesystemDriverCapabilitiesneeded by the backend.
- Fail closed: unknown or partially supported semantics produce read-only or unsupported plans, never optimistic read-write.
- Keep mount lifecycle explicit: start, active session, flush, unmount, dispose.
- Normalize error mapping in the neutral layer so backends only translate neutral errors to NTSTATUS/errno.
- Filesystem adapter: map
IFilesystemSessiondirectly to the neutral mount namespace using stableFilesystemNodeIdhandles. - Archive adapter: expose archive entries as a synthetic namespace for read-only mounts.
- Writable archive adapter: only enable after add/replace/remove/rename/truncate semantics are explicitly modeled and round-trip tested; do not equate
IArchiveModifiablewith random-write file handles. - Disk/container adapter: resolve partition/container layers to an
IFilesystemDriverProviderwithout copying the complete image when a random-access block device is available. - Nested mounts: preserve the chain of outer container -> block device/partition -> filesystem and propagate writability from every layer.
- Add
Compression.Mounting.Dokantargetingnet10.0-windows. - Use DokanNet 2.x through a narrow backend adapter; keep the rest of the repository independent of Dokan types.
- Implement mount/unmount and dependency probing (Dokany installed/available).
- Map open/create/read/write/truncate/flush/enumerate/stat/rename/delete/directory operations to the neutral namespace.
- Track open handles by stable node ID, not pathname, so rename/unlink cannot invalidate an existing handle.
- Implement Windows sharing/delete-pending semantics deliberately instead of approximating them with path locks.
- Map timestamps and attributes without inventing unsupported metadata writes.
- Add read-only integration tests first; enable read-write integration tests only for driver profiles that advertise the complete required primitive set.
- Add
Compression.Mounting.Fusetargetingnet10.0. - Prefer a FUSE3 low-level/inode-oriented binding so stable
FilesystemNodeIdmaps naturally to FUSE inode/handle semantics. - Keep the binding behind
IMountBackend; if no maintained .NET binding satisfies the requirements, use a small source-owned native interop layer rather than leaking an abandoned package throughout the codebase. - Probe
libfuse3/fusermount3availability and report actionable backend limitations. - Implement errno mapping, inode lifetime, lookup/reference counts, file handles, readdir offsets, flush/fsync, rename and unlink semantics.
- Add Linux CI integration tests where
/dev/fuseis available; keep pure adapter contract tests runnable everywhere.
- Keep the neutral mount contract compatible with a future macFUSE/FUSE3 FSKit backend.
- Do not make macOS support depend on deprecated kernel extensions.
- Re-evaluate a native FSKit backend once the neutral namespace and FUSE backend are stable.
- Treat a native Windows IFS/minifilter-style implementation as a separate, later backend/bridge project.
- Reuse the same userspace protocol and conformance suite rather than reimplementing format logic in kernel mode.
- Define a narrow IPC protocol before any kernel code: requests, stable handles, cancellation, timeouts, buffer ownership, crash recovery, and forced unmount.
- Only pursue the kernel driver if Dokan cannot meet a measured requirement (performance, boot-time mounting, paging I/O, security model, etc.).
A filesystem image may advertise read-only mounting only when all are true:
- the descriptor provides
IFilesystemDriverProvider; -
ProbeFilesystemreturnsCanMount = truefor this image/profile; - the profile provides directory enumeration, data reads, random access, and stable node IDs required by the backend;
- the selected backend is available on the host;
- all outer container/partition layers can provide safe random reads.
Read-write additionally requires all of the following for the selected profile and mount policy:
-
CanMountWritable = true; - mutation model is not
NoneorWholeImageRebuildfor ordinary mounted writes; - backing source and every outer layer are writable;
- required data operations (
WriteData,Truncate,Flush) are present; - required namespace operations (
CreateFile,DeleteFile,CreateDirectory,RemoveDirectory,Rename) are present; - backend-specific metadata semantics are either supported or explicitly exposed as unsupported without corrupting data;
- writable driver safety and round-trip/conformance tests pass for that profile.
Optional primitives such as hard links, symlinks, sparse files, metadata writes and transactions are advertised independently and mapped only when present.
- Add a Mount action for a currently opened archive/image/filesystem when at least one backend returns a supported plan.
- Default to read-only.
- Offer read-write only when the resolver returns an allowed read-write plan for the concrete image.
- Show the reason when read-write is unavailable (format profile, backing file, outer container, backend, missing primitive, or dependency).
- Let the user choose a Windows drive letter or Unix mountpoint as appropriate.
- Show active mounts and provide explicit unmount/flush actions.
- Use the same resolver as the CLI; no duplicated UI capability rules.
- Add
mount <image> <target> [--read-only|--read-write] [--backend ...]. - Add
mount capabilities <image>to print the resolved per-image/backend plan and limitations. - Add
unmount <target>where the backend supports external unmount. - Make
--read-writefail with a precise reason instead of silently falling back to read-only.
- Resolver never offers read-write from
FormatCapabilities.CanModifyalone. - Resolver rejects writable mount for
WholeImageRebuildprofiles. - Resolver rejects writable mount when the backing stream is read-only.
- Resolver rejects a profile missing any required core mutation primitive.
- Resolver preserves optional capabilities independently.
- Open handles remain usable across rename in the fake filesystem session.
- Delete/open-handle lifetime behavior is deterministic and backend-independent.
- Concurrent positional reads do not share a mutable stream cursor.
- Flush/unmount calls are ordered and idempotent where required.
- Shared backend contract suite using an in-memory fake filesystem.
- Dokan read-only smoke mount on Windows CI when Dokany is available.
- Dokan read-write CRUD/rename/truncate/flush suite.
- FUSE read-only smoke mount on Linux CI when
/dev/fuseis available. - FUSE read-write CRUD/rename/truncate/fsync suite.
- Cancellation, forced-unmount and backend-crash cleanup tests.
For every format/profile promoted to mountable:
- probe is non-destructive and restores stream position;
- read-only namespace walk matches existing extraction/listing results;
- random reads match extracted content;
- writable CRUD operations survive close/reopen;
- rename/delete semantics preserve unrelated data;
- allocator/free-space metadata remains structurally valid;
- journal/checkpoint/recovery semantics are tested when applicable;
- capability advertising matches the tested profile, not the family name.
- Add
Compression.Mountingand the capability resolver. - Add pure resolver/contract tests.
- Integrate the project into the solution.
- Add
Compression.Mounting.Dokan. - Implement read-only filesystem mounting over
IFilesystemSession. - Wire UI Mount action and read-only/read-write selector to the resolver.
- Add a CLI
mountcommand using the same resolver/backend registry.
- Select the simplest already-qualified filesystem driver profiles with native granular mutation support.
- Complete missing mount-grade primitives where justified.
- Enable Dokan read-write only after conformance passes.
- Never promote EROFS/SquashFS/CramFS-style whole-image rebuild support to writable mount capability.
- Implement Linux FUSE3 backend against the same neutral namespace.
- Share the conformance suite with Dokan.
- Wire CLI backend selection and mountpoint handling.
- Read-only archive namespace adapter.
- Explicit writable archive filesystem semantics where safe.
- Partition/container chaining using
IRandomAccessBlockDevice. - Propagate access mode and limitations through nested layers.
- Qualify retro/exotic filesystems with simple allocation/namespace structures first.
- Expand to journaled/CoW filesystems only after allocator, transaction, crash-consistency and recovery semantics are real.
- Audit docs/UI/CLI capability tables from the same mechanical source used by runtime resolution.
The first code checkpoint is complete when the repository has a buildable mount-neutral project whose resolver can answer, for a concrete FilesystemDriverProfile and backend, whether read-only and read-write mounting are allowed and exactly why not. That checkpoint deliberately precedes Dokan/FUSE callbacks so backend code cannot accidentally invent its own capability policy.