declaration: an access is mounted, and the host owns nothing about it

The tenth shape (novox/hq ADR 0051). Shared, pre-existing data — a media
library, a download spool several modules use — is the operator's, not
the mesh's. A `directory` resource is the host's own: it creates it,
chowns it, sets its mode and removes it when empty. An access is the
opposite on every axis.

Add the `access` type to the vocabulary. Its applier confirms the path is
present and changes nothing: it does not create, chown, reconcile or set
a mode. Absent is refused clearly — the operator must provide it — rather
than created, because a bind mount whose source is missing is made as
root by the container runtime with the wrong ownership (04-ISSUES/026).
Undeclaring an access forgets the record and never touches the path,
which is the data loss ADR 0030 prevents, on a directory the mesh never
made.

Full hosts speak it (it gates a bind mount, which needs the container
runtime); the vocabulary guard test records the decision that made it the
tenth shape. Unit tests cover present, absent-refused, and
undeclared-left-alone.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
2026-09-05 22:19:33 +02:00
parent 291cab1091
commit f06eea5fa3
5 changed files with 212 additions and 4 deletions
+49
View File
@@ -250,6 +250,8 @@ func applyOne(ctx context.Context, sys system.System, r declaration.Resource, ru
return applyAction(ctx, res, run)
case *declaration.Network:
return applyNetwork(ctx, res, run)
case *declaration.Access:
return applyAccess(res)
default:
// Unreachable: the declaration refused this already. Present because "unreachable"
// stops being true the moment someone adds a kind and forgets this switch.
@@ -336,6 +338,46 @@ func applyDirectory(r *declaration.Directory) (Outcome, error) {
return out, nil
}
// applyAccess confirms an operator-owned path is present, and owns nothing about it.
//
// **The mirror image of applyDirectory** (novox/hq ADR 0051). A directory the host makes, chmods,
// chowns and removes when empty. An access it does none of: the path is the operator's — a media
// library, a download spool that several modules share — and the host's only job is to be sure it
// is there before anything mounts it.
//
// **Absent is refused, not created.** A bind mount whose source does not exist is made for you by
// the container runtime, as root, with whatever mode it picks — which is exactly the silent
// wrong-ownership 04-ISSUES/026 records. So the host checks first and says plainly that the
// operator must provide the path, rather than conjuring a directory it does not own and cannot
// give the right owner. Nothing is written, so this never reports a change: the machine did not
// move, the host merely confirmed a fact about it.
func applyAccess(r *declaration.Access) (Outcome, error) {
out := begin(r)
info, err := os.Stat(r.Path)
if errors.Is(err, os.ErrNotExist) {
return out, fmt.Errorf(
"%s is not there, and the mesh does not own it — the operator must provide it. It is "+
"shared, pre-existing data (novox/hq ADR 0051): the host mounts it and creates "+
"nothing, so a missing one is said here rather than made as root by the container "+
"runtime", r.Path)
}
if err != nil {
return out, err
}
if !info.IsDir() {
return out, fmt.Errorf(
"%s is not a directory, and an access is a shared directory the operator provides",
r.Path)
}
mode := declaration.AccessRead
if r.Mode != "" {
mode = r.Mode
}
out.Action = "unchanged"
out.Detail = "operator-owned; present, " + mode + ", nothing managed"
return out, nil
}
func applyFile(r *declaration.File, previous store.Applied, unseal Unseal) (Outcome, error) {
out := begin(r)
@@ -705,6 +747,13 @@ func remove(ctx context.Context, sys system.System, a store.Applied, run Runner)
// to whatever it acted on.
return "forgotten", "an action leaves nothing the host owns", nil
case declaration.TypeAccess:
// The path is the operator's and the host never owned it (novox/hq ADR 0051). Undeclaring
// it says only that this module no longer reaches it — not that the media library should
// be touched. So the record is dropped and the path left exactly as it is; removing it
// would be the data loss ADR 0030 exists to prevent, on a directory the mesh never made.
return "forgotten", "an operator-owned path is never the host's to remove", nil
case declaration.TypeNetwork:
// **The reason this is a shape at all** (novox/hq ADR 0029). Orphans are removed in
// reverse declaration order, so a network written before the containers that join it is