catalogue: a module accesses operator-owned data, and does not own it
04-ISSUES/036: the media stack is several modules that must share the library and download directories on one machine, but the manifest could only say "a directory I own". Six modules each declared the same paths as their own resources, and the resolver's duplicate-owner refusal — right in general — would refuse the stack's only sensible assignment the first time two of them landed on one node. Add an `accesses` field: a pre-existing, operator-owned path a module is granted use of but does not own (novox/hq ADR 0051). Distinct from a `directory` resource on every axis the host acts on — the mesh creates, chowns and reconciles a directory; it mounts an access and owns nothing. An access is not a resource, so it never enters the duplicate-owner map and several modules may name one path with no conflict. What is refused is the contradiction: a path one module owns and another accesses. Rendered into the declaration as an `access` resource, before the container that mounts it, so the host can find it present or refuse clearly. Unit tests cover co-resolution (the exact 036 case), the unchanged owner-vs-owner refusal, the owner-vs-accessor refusal, and access validation. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
@@ -566,9 +566,18 @@ func checkClaims(modules []Manifest, node Node, elsewhere []Held) ([]Held, []str
|
||||
// This costs no manifest field: the mesh already holds every resource of every module, so two
|
||||
// declaring one path or one unit are visible without either having to know about the other. A
|
||||
// declared claim is only for the abstract conflicts nothing in the resources reveals.
|
||||
//
|
||||
// **The refusal is about ownership, not use** (novox/hq ADR 0051, 04-ISSUES/036). Two modules
|
||||
// owning one path is the fault this catches — the class of collision this repository keeps
|
||||
// recording. Two modules *accessing* one operator-owned path is not a collision: it is the whole
|
||||
// point of a media stack, where the library server, the managers and the download client must see
|
||||
// the same directories. An access is not a resource and never enters the owner map, so co-access
|
||||
// resolves with no refusal. What is refused is the contradiction — a path one module owns and
|
||||
// another merely accesses — because shared data is the operator's and nobody's to own.
|
||||
func checkResources(modules []Manifest) []string {
|
||||
var problems []string
|
||||
owner := map[string]string{}
|
||||
ownedPath := map[string]string{} // path → owning module, for the access check below
|
||||
|
||||
for _, m := range modules {
|
||||
for _, r := range m.Resources {
|
||||
@@ -583,6 +592,30 @@ func checkResources(modules []Manifest) []string {
|
||||
"%s and %s both declare the %s %q", other, m.Module, field, value))
|
||||
}
|
||||
owner[key] = m.Module
|
||||
if field == "path" {
|
||||
ownedPath[value] = m.Module
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An accessed path is the operator's, so no module may declare it as one of its own
|
||||
// (novox/hq ADR 0051). Refused here rather than silently tolerated: an owner would create and
|
||||
// chown the very directory another module was told to expect the operator to provide, and the
|
||||
// two intentions cannot both hold. Two modules *accessing* it, by contrast, is never checked,
|
||||
// which is what lets the stack in 04-ISSUES/036 co-resolve.
|
||||
for _, m := range modules {
|
||||
for _, a := range m.Accesses {
|
||||
switch other := ownedPath[a.Path]; other {
|
||||
case "":
|
||||
// Nobody owns it — the ordinary, correct case for shared data.
|
||||
case m.Module:
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s both owns and accesses %q — it is one or the other", m.Module, a.Path))
|
||||
default:
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%s accesses %q, which %s declares it owns — shared data is the operator's, "+
|
||||
"owned by no module (novox/hq ADR 0051)", m.Module, a.Path, other))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user