nfs-share and smb-share share an intent, not a contract; one seat would be a union with every field optional. What the exemplar exposes is that a seat declared inside one module cannot be implemented by another without depending on it.
4.9 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | ||
|---|---|---|---|---|---|---|
| open | 2026-09-30 |
|
169 — A machine shares its files, and the mesh does not know
What was observed
ace serves the operator's media library to the home network with two host services no module declares and HAL never managed either:
/etc/exports: /storage/media 192.168.1.0/24(rw,sync,root_squash,…) nfs-server active, :2049
/etc/samba/smb.conf: [media] path = /storage/media/ valid users = media smb active, :139/:445
Two LAN clients were connected at survey (2026-09-30). The library itself is operator data (ADR 0051: ~40 TB on ZFS, the mesh owns nothing about it — issue 153 is about modules reaching it in place).
Under the mesh as it stands, this arrangement has no expression and one failure mode:
- Nothing declares the listens. At
converge acethe filter is the sum of what modules listen on (ADR 0045); 2049 and 445 are nobody's, so the shares close — silently, for the two clients that mount them. - Nothing owns the configuration.
/etc/exportsandsmb.confare hand-written files on one machine; a second machine sharing a directory would be written by hand again. - Nothing can consume it. A module on another node that wanted the library (a player, an
indexer, a backup) has no
requiresto state and no binding to read; it would mount by a hand-typed host and path. - The clients are LAN devices, so this also meets issue 154 (no reach for the machine's own network).
The proposal (the operator's, 2026-09-30, settled after two rounds)
Two module-defined seats, one per protocol, because NFS and SMB share an intent and not a contract. A seat in the mesh's sense is a contract — what it accepts, emits and serves, and the tools its holder must answer (ADR 0126, 0132) — and lined up, the two share almost none of it:
nfs-share |
smb-share |
|
|---|---|---|
| serves | export path(s); the client ranges allowed (sec=sys authorises by address) |
share name(s), path |
| pair credential | none | a user and password per consumer |
| consumer's mount | at:/path |
//at/share with credentials |
| holder's tools | export / unexport a path for a range | add / remove a share, create a user |
One file-share seat would be the union with every field optional — a consumer could bind it and
still not know how to mount what it got (the emptiness ADR 0129 warns against). "Export a path to
the network" is a category, and the mesh needs no seat category: a consumer requires the one it
can mount. If "give me the library, however" is ever needed, it is a provision an umbrella module
serves, not a seat.
Both are node-scoped, one holder per node (ADR 0110), so ace holds both. nfs and samba are the
first implementations; a second (Ganesha for nfs-share, ksmbd for smb-share) is what proves
0126's promise that "replacing the implementation changes nothing for any caller".
The holder module:
- declares the exported paths as
accesses(ADR 0051: it owns nothing about them — never creates, chowns or removes), and which paths as the assignment's settings (ADR 0046/0112); - writes the share configuration (
/etc/exports,smb.conf) as mesh-managed files and drives the units, likednsmasq/sshddo for theirs; - declares its endpoints (
nfs2049/tcp;smb445/tcp, …) so the reach — internal, or the LAN once 154 has an answer — is the assignment's, and converge keeps them open; - provides the seat's provision, so a consumer on another node
requires nfs-share(orsmb-share) and reads${bound:nfs-share:at}and the path from its binding instead of a hand-typed mount.
The design gap this exposes
A seat definition has no home outside the module that first declared it. Today a seat is
declared inside a manifest (showcase declares the-showcase, ca-trust its own). If nfs
declared nfs-share, Ganesha could hold it only by depending on nfs's manifest — the coupling
0126 removed for callers, reintroduced for implementations. The protocol needs a neutral place in
the catalogue beside the modules (a seat definition registered like a manifest), with a module
saying which seats it implements. This is the first role with an obvious second implementation,
which is what makes it the exemplar for that mechanism.
Open questions for the decision
- Whether an NFS export over the overlay is an
internalreach of the same endpoint or a second export line — NFS authorises by client address, so the mesh range and the LAN range are two entries in one file. - How a consumer's binding expresses a path to mount (today bindings carry
at,port,asand whatever the providerserves), and whether one share can serve several paths.