The assignment's own root is a place, and the manifest's maps are placed
Slice two of ADR 0112. A pathless directory saying place "." is the
assignment's one directory, <root>/<module> — to-be 27's shape — and
place never reaches the host, which parses strictly. The maps naming
where bindings, credentials and contributions land (binds, secrets,
own-secrets, receives, grants) fill against the placed directories at
composition, into fresh maps and a fresh module slice, because one
resolution composes for many nodes. The five absolute-path checks on
those maps accept a placed reference — resolution makes it absolute
before anything reads it — while certificate, operator-keeps and
accesses paths stay absolute-only: those are the operator's or another
vocabulary's. unknownDirRefs scans the maps too, and validates place
itself: only on a directory, only ".", never beside a stated path.
Found by the foundation tests validating the sibling catalogue: the
first conversion's blanket replace turned /var/lib/gitea/database.json
into ${dir:data}base.json — which resolves to the right path by pure
string concatenation. Production was saved by a coincidence; the
catalogue cleanup that follows spells it ${dir:state}/database.json.
This commit is contained in:
@@ -224,6 +224,21 @@ func (r Resolution) Compose(with Rendering) (Composed, error) {
|
||||
}
|
||||
|
||||
func (r Resolution) compose(with Rendering, owner map[string]string) ([]map[string]any, error) {
|
||||
// Every manifest is placed first (novox/hq ADR 0112): the maps naming where its bindings,
|
||||
// credentials and contributions land are resolved against this node's directories, so every
|
||||
// reader below — the binding files, the sealed secrets, the grant paths a contribution
|
||||
// names — sees a concrete place and none learns the vocabulary.
|
||||
// Into a fresh slice, never the caller's: one resolution may compose for many nodes, and a
|
||||
// slice element written in place would carry the first node's places into the second's.
|
||||
placed := make([]Manifest, len(r.Modules))
|
||||
for i, m := range r.Modules {
|
||||
var err error
|
||||
if placed[i], err = placedManifest(m, with); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
r.Modules = placed
|
||||
|
||||
// Where each provision's credentials land, so a contribution can name the file rather than
|
||||
// carry a value the mesh does not have.
|
||||
directories := map[string]string{}
|
||||
|
||||
Reference in New Issue
Block a user