Files
mesh-catalog/modules/mesh-files/README.md
T
jschoubben 5d98bcc0db
mesh/delivery-group group feat/900-node-files checking: composed check out of date: novox/mesh-controller@210f7cf5e64b was judged against trunk 611e2275cf7c, t…
mesh/merge-gate out of date: judged against trunk 3db85a0dde83, the trunk is now 8b53a3663244; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk 3db85a0dde83, the trunk is now 8b53a3663244; judged again on a recheck or when it is merged
mesh/delivery superseded: a newer head of the same pull request
mesh-files: the holder of node-files, reads and writes with trash, owned paths and an act log, so file work on a node needs no shell (issue 900, ADR 0394)
2026-10-16 14:50:03 +02:00

64 lines
3.5 KiB
Markdown

# mesh-files
The holder of the node seat `node-files` (novox/hq ADR 0394, issue 900; to-be 41 WP9). It reads and manages
the files and accounts of the node it runs on, through the mesh, so nothing about a node's files goes through
a shell.
It replaces `mesh-reads` (ADR 0310), which stays beside it until `mesh-files` is assigned on every node (ADR 0394 §9).
## Verbs
The seat's verbs, with the descriptions the controller defines (`internal/catalogue/files.go`).
- **Reads:** `stat`, `readlink`, `list`, `read`, `search`, `account`. As in mesh-reads: bounded answers, a place a
secret is kept refused by name before any read, a line shaped like a secret withheld.
- **Writes:** `write` (a text file whole, with an optional mode), `copy`, `move`, `delete` (recursive on
request), `mkdir` (parents on request), `chmod` (octal or `u+x,go-w`, recursive on request), `chown` (owner,
optional group, recursive on request).
- **Trash:** `trash` lists it, `restore` puts an item back.
Every write verb takes `reason` (required, for the audit trail) and `override` (a reason; needed only for a
path a module owns).
## Rights
It runs as the tool runner's account, the node's operator account, and declares no account of its own. An act
is tried with that account's rights first. Where that fails with a permission error, the act is repeated
through `sudo -n` with a fixed binary (cat, cp, mv, stat, chmod, chown, mkdir, rm under `/usr/bin`) and an
argument list built from fixed words and one path, never a shell (`sudo.go`). Tests use a fake runner.
Not yet through sudo: `stat`, `list`, `readlink` and `search` (they answer what the account reaches and say what it
may not); `read` and every write do.
## Owners and modes
- `copy` and `move` keep owner and mode (`cp -a`); a copy refuses a target that exists.
- A new file or folder takes its folder's owner and group.
- An overwrite keeps the overwritten file's owner and mode.
## Trash
`delete`, and the overwrite of `write`, first move the old item to `<state>/trash/<id>/item` with a
`meta.json` (original path, owner, group, mode, caller, reason, time). `restore` puts it back and refuses when
the path is taken now. Entries older than 7 days are emptied on every write call and every `trash` list.
## Owned paths
The controller gives the holder `MESH_OWNED_PATHS`, a JSON object from an absolute path to `module (tool)`. A
write, move or delete of such a path, anything under it, or (for delete, move and recursive chmod and chown) a
folder that holds it, is refused naming the module and tool, unless `override` gives a reason. The override is
recorded in the act log and told to the operator, in words without a path, through `operator-channel.tell`.
Without the word, the module starts and owns nothing.
## The act log
Each write act that was done is one JSON line in `<state>/acts.log`: time, caller, verb, paths, reason, and for
an override the override and the owned paths it went through. The caller is the bus user the runtime proved
(`stdio.CallerOf`), or `unproven`; it is never read from the arguments. A refused act is not logged.
## What it refuses
- A place a secret is kept (`MESH_SECRET_PLACES`, and the known credential files in `refuse.go`) is refused by
name for `read`, `list` and `search`. Copying or moving such a place is allowed: nothing is printed.
- A copy or move to or from `<node>:/path` is refused: copying between nodes comes in step 2 (issue 903).
- A write without a reason; a path that is not absolute; a mode that is not a mode.