--- status: open opened: 2026-09-30 located-in: - mesh-catalog (no module shares a path over the network) - hq 02-DECISIONS (a file-share seat, per ADR 0126, is a module's own to define) fixed-by: amended-design: --- # 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](../153-an-adopted-machines-data-cannot-be-placed-where-it-is/00-report.md) 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 ace` the 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/exports` and `smb.conf` are 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 `requires` to 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](../154-a-machines-own-network-is-not-a-reach/00-report.md) (no reach for the machine's own network). ## The proposal (the operator's, 2026-09-30) **File sharing is a core seat — a role each machine has, defined by the control plane — and, as with package registries (ADR 0109), one seat per protocol, so several modules occupy the family:** | seat | scope | delivers | held by | |---|---|---|---| | `node-nfs-share` | node | `nfs-share` | an `nfs` module | | `node-smb-share` | node | `smb-share` | a `samba` module | | … (`node-webdav-share`) | node | … | whatever comes next | Named for their scope (ADR 0121), one holder per node (ADR 0110), each carrying its protocol (ADR 0129). A machine may hold both — nfs and samba on ace — and one module may hold several (0109: "gitea may hold several seats at once"). Adding a protocol is adding a seat and a provision, not widening one. 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, like `dnsmasq`/`sshd` do for theirs; - declares its endpoints (`nfs` 2049/tcp; `smb` 445/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, serving the export path(s), so a consumer on another node `requires nfs-share` (or `smb-share`) and reads `${bound:nfs-share:at}` and the path from its binding instead of a hand-typed mount — a pair credential where the protocol has one (a Samba user), none for `sec=sys` NFS. What it would settle: ace's library becomes reachable from the mesh by declaration, the two host services get an owner, converge stops being a trap for them, and a media module on another machine (or a backup on novox) can mount the library the way it binds a database today. ## Open questions for the decision - Whether an NFS export over the overlay is an `internal` reach 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`, `as` and whatever the provider `serves`), and whether one share can serve several paths. - Whether the seat should exist before its first module (a system seat is a decision, ADR 0110) — the decision that adds the two seats can be the one that accepts this proposal.