Issue 169: the consumer half is a module (network-share), not a host resource kind; the access-on-a-mountpoint check is the data-loss case

This commit is contained in:
2026-09-30 13:56:07 +02:00
parent 90b89aa1c9
commit ee801a6441
@@ -82,29 +82,38 @@ the catalogue beside the modules (a seat definition registered like a manifest),
saying which seats it implements. This is the first role with an obvious second implementation, 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. which is what makes it the exemplar for that mechanism.
## The consumer's half: the machine mounts it (2026-09-30, third round) ## The consumer's half: a module mounts it (2026-09-30, third and fourth round)
A binding tells a consumer *where* the share is; it does not put the files on its machine. A A binding tells a consumer *where* the share is; it does not put the files on its machine. Mounting
consumer on another node needs the export **mounted by the host, at a directory the consumer is something done on a machine, and something done on a machine is a module's work — not the host's
declares, before its container starts**, and unmounted when the requirement goes. That is a host (the vocabulary stays closed; no `mount` resource kind).
action, not something a container reads from a file.
**Not a client module.** A node-wide `nfs-client` with a list of mounts in its settings is fstab **A consumer-side module, `network-share`,** assigned on the node that wants the files:
with a manifest around it: consumers would stop requiring `nfs-share` and couple on a path again,
unassigning a consumer would leave its mount behind, and a person is back in the loop deciding
which machine mounts what — the thing the binding removes.
**A mount is a resource of the consuming module.** The vocabulary (directory, file, package, - `requires nfs-share` (or `smb-share`); several shares on one node are several local names of
container, service, process, network, archive, user, access) has no `mount`. It can be assembled the requirement (ADR 0094);
today — a `package` (nfs-utils), a `file` writing a systemd `.mount` unit with - its manifest is a `package` (nfs-utils), a `file` writing a systemd `.mount` unit filled from
`What=${bound:nfs-share:at}:${bound:nfs-share:path}` and `Where=${dir:library}`, a `service` the binding — `What=${bound:nfs-share:at}:${bound:nfs-share:path}` — and a `service` enabling it
enabling it after the overlay is up — but the honest form is a **`mount` resource kind**: the host after the overlay is up: the same shape as `resolv-conf` or `sshd`, files and a unit;
mounts from the binding, refuses a mountpoint the module did not declare (ADR 0091's three ways a - *where* it mounts is the assignment's setting (`/srv/media` on one machine, elsewhere on
path can be), and unmounts on undeclare. The nfs and samba modules are then the *server* side only. another); which machine mounts what is an operator decision made at assignment, exactly as which
paths a machine shares is.
**The modules that use the files never learn about NFS.** A player, an indexer, a backup declares
the mounted path as an `access` — an operator-chosen, pre-existing path the mesh never owns
(ADR 0051), exactly as `/storage/media` is on ace. The same app manifest then runs on ace against
the local library and on another node against the mounted one, with only its assignment differing.
**The one check to add, because it is the data-loss case.** An `access` is confirmed today by the
path being present. For a mountpoint that is not enough: a writer whose container starts before the
mount is up writes into the empty directory underneath it, and the files vanish when the mount
lands. The access check must confirm the path is *a mountpoint* when the module says so (or the
module's unit is ordered before the consumer's container — which crosses modules and is exactly
what the mesh does not order). Which of the two is the decision's.
**Identity crosses the wire.** `sec=sys` NFS trusts the client's uid, so a consumer must run as the **Identity crosses the wire.** `sec=sys` NFS trusts the client's uid, so a consumer must run as the
library's owner on the server (ace: `media`, 1001:2000) — hq 153's `${access:<id>:uid}` proposal library's owner on the server (ace: `media`, 1001:2000) — hq 153's `${access:<id>:uid}`, read from
extended to a mount, `${mount:<id>:uid}`, read from the mounted tree. the mounted tree, answers it on the consumer's side too.
## Open questions for the decision ## Open questions for the decision