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?
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.