Validate the writable tag namespace with a concrete prototype #6

Closed
opened 2026-07-22 22:12:34 +00:00 by phg · 2 comments
Owner

Blocked by: #2, #3, #5
Part of #1

Question

Using the cheapest disposable artifact that can exercise Dovecot against a FUSE or faithful fake namespace, what observable design correctly supports folder discovery, multiple Message projections, shared Seen and Flagged state, Deleted plus expunge, source cur/new transitions, external Dovecot metadata, dot and slash hierarchy separators, and rejection of unsupported writes?

Blocked by: #2, #3, #5 Part of #1 ## Question Using the cheapest disposable artifact that can exercise Dovecot against a FUSE or faithful fake namespace, what observable design correctly supports folder discovery, multiple Message projections, shared Seen and Flagged state, Deleted plus expunge, source cur/new transitions, external Dovecot metadata, dot and slash hierarchy separators, and rejection of unsupported writes?
phg added the
wayfinder:prototype
label 2026-07-22 22:12:34 +00:00
Author
Owner

Claimed by Claude Code for this wayfinding session.

Claimed by Claude Code for this wayfinding session.
Author
Owner

Verdict: viable, with two required architectural boundaries.

Prototype artifact: throwaway prototype/wayfinder-6 branch at a430dc1581ed7fcb4b653267bbef779f13f1bedb.

Evidence: one NixOS VM-test matrix passed all four combinations:

  • Dovecot 2.3.21.1 with .
  • Dovecot 2.3.21.1 with /
  • Dovecot 2.4.4 with .
  • Dovecot 2.4.4 with /

The matrix exercises Dovecot-driven discovery and reads, Unicode/canonical Tag encoding, multiple projection identities, global new -> cur, shared Seen/Flagged/Answered/Draft/Deleted state, EXPUNGE, COPY and MOVE out, synchronous rejection of APPEND/COPY/MOVE in and content writes with unchanged pre/post state, external Source delivery/rename/delete reconciliation, Dovecot metadata outside FUSE, and UID/UIDVALIDITY stability across flag changes, FUSE remount, and Dovecot restart. Six Rust unit tests pass; cargo fmt --check and Clippy with warnings denied pass.

Required boundaries:

  1. Only the current canonical Maildir filename may resolve to the projection inode. A broad lookup that resolves stale flag-filename aliases to that same inode lets Linux collapse Dovecot's rename(old, new) into a successful same-inode no-op before FUSE receives rename; Source flags then remain unchanged. Canonical misses force Dovecot to rescan and issue a real rename. Positive dentry caching must therefore be zero or explicitly invalidated around these transitions; stale aliases cannot naively share the canonical inode.
  2. Dovecot ACLs must remove structural rights k and x. FUSE receives indistinguishable Message unlinks for valid MOVE/EXPUNGE and mailbox deletion, so it cannot atomically reject mailbox deletion by itself. Dovecot 2.3 uses a global vfile ACL and 2.4 uses the namespace ACL; both retain message rights while denying mailbox create/rename/delete. Privileged local doveadm paths can explicitly ignore ACLs, so production must also exclude autocreation and equivalent administrative bypasses in this namespace.

Production omissions remain intentional: SQLite/persistence, direct inotify and recovery, scale testing, service-module packaging, full RFC parsing, Source Dovecot uidlist locking, production open-file-handle tracking, and coordinator serialization of scan publication against mutations. These are implementation concerns, not counterevidence to the filesystem/Dovecot contract validated here.

Verdict: **viable, with two required architectural boundaries**. Prototype artifact: [throwaway `prototype/wayfinder-6` branch](https://git.s1q.dev/phg/fuse-mail-dir-by-tag/src/branch/prototype/wayfinder-6/prototype/wayfinder-6) at [`a430dc1581ed7fcb4b653267bbef779f13f1bedb`](https://git.s1q.dev/phg/fuse-mail-dir-by-tag/commit/a430dc1581ed7fcb4b653267bbef779f13f1bedb). Evidence: one NixOS VM-test matrix passed all four combinations: - Dovecot 2.3.21.1 with `.` - Dovecot 2.3.21.1 with `/` - Dovecot 2.4.4 with `.` - Dovecot 2.4.4 with `/` The matrix exercises Dovecot-driven discovery and reads, Unicode/canonical Tag encoding, multiple projection identities, global `new -> cur`, shared Seen/Flagged/Answered/Draft/Deleted state, EXPUNGE, COPY and MOVE out, synchronous rejection of APPEND/COPY/MOVE in and content writes with unchanged pre/post state, external Source delivery/rename/delete reconciliation, Dovecot metadata outside FUSE, and UID/UIDVALIDITY stability across flag changes, FUSE remount, and Dovecot restart. Six Rust unit tests pass; `cargo fmt --check` and Clippy with warnings denied pass. Required boundaries: 1. **Only the current canonical Maildir filename may resolve to the projection inode.** A broad lookup that resolves stale flag-filename aliases to that same inode lets Linux collapse Dovecot's `rename(old, new)` into a successful same-inode no-op before FUSE receives `rename`; Source flags then remain unchanged. Canonical misses force Dovecot to rescan and issue a real rename. Positive dentry caching must therefore be zero or explicitly invalidated around these transitions; stale aliases cannot naively share the canonical inode. 2. **Dovecot ACLs must remove structural rights `k` and `x`.** FUSE receives indistinguishable Message unlinks for valid MOVE/EXPUNGE and mailbox deletion, so it cannot atomically reject mailbox deletion by itself. Dovecot 2.3 uses a global vfile ACL and 2.4 uses the namespace ACL; both retain message rights while denying mailbox create/rename/delete. Privileged local `doveadm` paths can explicitly ignore ACLs, so production must also exclude autocreation and equivalent administrative bypasses in this namespace. Production omissions remain intentional: SQLite/persistence, direct inotify and recovery, scale testing, service-module packaging, full RFC parsing, Source Dovecot uidlist locking, production open-file-handle tracking, and coordinator serialization of scan publication against mutations. These are implementation concerns, not counterevidence to the filesystem/Dovecot contract validated here.
phg closed this issue 2026-07-23 22:48:01 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: phg/fuse-mail-dir-by-tag#6
No description provided.