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
+4
View File
@@ -169,6 +169,10 @@ func everyShape() []declaration.Type {
// A network needs the same runtime a container does, so a host that can run one can make
// the other. Not in portableShapes for exactly that reason.
declaration.TypeNetwork,
// An access is confirmed by a stat and needs only a filesystem — but it exists to gate a
// bind mount, and a bind mount needs the container runtime a full host has. So it sits
// here with the container it guards, not at the portable floor (novox/hq ADR 0051).
declaration.TypeAccess,
}
}