What
Replace the placement path template as the thing a user declares with a declared layout: what the
folder is. GitTarget.spec.layout, a discriminated union on kind
(Auto | Kustomize | Tree | Flat | Template), plus byType overrides that stay valid under every
kind.
Full design, with seven worked examples and a mechanical migration for every current configuration:
docs/design/gittarget-layout-model.md.
Why
Placement today is a ladder of four rungs, three of which are path templates and one of which is not
(byType → default → the folder's one kustomize root → canonical). Every open placement question
traces to that one mismatch:
- a CRD default for
placement.default cannot be added, because a non-empty template consumes the
slot in front of the rung that is not a template;
byType: {v1/configmaps: "configmaps/{name}.yaml"} in a kustomize folder produces a file no
kustomization lists, so it is committed and never rendered (see the sibling issue on placement
correctness) — one line of user config;
placement.default on a kustomize folder does the same thing to every type at once;
- nothing in the model can create structure, so a repository that needs a
kustomization.yaml
before it can render cannot be bootstrapped by the thing that writes into it.
A path template cannot express "beside this folder's one kustomization", cannot be read at a glance,
and cannot bring a folder into existence.
The two rules that carry the value
- Whatever chose the path, the file is registered with the kustomization that governs it. That
makes the unrendered-file bug unstatable rather than fixed.
- A structural kind excludes a blanket
default, so a declared template can no longer silently
disable the render root.
kind: Auto is a safe CRD default precisely because it names the structural rule instead of
standing in front of it. It is declared inference, which is a different thing from the undeclared
sibling inference that was deleted in #291.
Scope notes
- Breaking (
feat(api)! on GitTarget), and cheaper as part of the API wave than alone. See the
wave issue.
- The layout is immutable except a widening transition: GitTarget has no finalizer, so recreating
one re-adopts every document by identity.
- It carries the namespace half too:
scope: SingleNamespace|MultiNamespace is a structural claim
that must agree with the authorization bound allowedSourceNamespaces, and writeNamespace: FromContext|Always|Never replaces the inference that decides whether metadata.namespace is
written — the one inference an empty folder cannot perform.
- Deliberately not its own CRD: a shared object changing where N folders write, with nothing on
the GitTarget recording it, is the same defect as sibling inference with a different actor.
Open
Whether scope should be derived and materialized at creation instead of declared.
Not in 0.41.0
Deliberately postponed. 0.41.0 is already a large breaking release (the whole attribution fact-stream
model plus the placement break), and this is the start of a separate wave.
What
Replace the placement path template as the thing a user declares with a declared layout: what the
folder is.
GitTarget.spec.layout, a discriminated union onkind(
Auto | Kustomize | Tree | Flat | Template), plusbyTypeoverrides that stay valid under everykind.
Full design, with seven worked examples and a mechanical migration for every current configuration:
docs/design/gittarget-layout-model.md.Why
Placement today is a ladder of four rungs, three of which are path templates and one of which is not
(
byType→default→ the folder's one kustomize root → canonical). Every open placement questiontraces to that one mismatch:
placement.defaultcannot be added, because a non-empty template consumes theslot in front of the rung that is not a template;
byType: {v1/configmaps: "configmaps/{name}.yaml"}in a kustomize folder produces a file nokustomization lists, so it is committed and never rendered (see the sibling issue on placement
correctness) — one line of user config;
placement.defaulton a kustomize folder does the same thing to every type at once;kustomization.yamlbefore it can render cannot be bootstrapped by the thing that writes into it.
A path template cannot express "beside this folder's one kustomization", cannot be read at a glance,
and cannot bring a folder into existence.
The two rules that carry the value
makes the unrendered-file bug unstatable rather than fixed.
default, so a declared template can no longer silentlydisable the render root.
kind: Autois a safe CRD default precisely because it names the structural rule instead ofstanding in front of it. It is declared inference, which is a different thing from the undeclared
sibling inference that was deleted in #291.
Scope notes
feat(api)!onGitTarget), and cheaper as part of the API wave than alone. See thewave issue.
one re-adopts every document by identity.
scope: SingleNamespace|MultiNamespaceis a structural claimthat must agree with the authorization bound
allowedSourceNamespaces, andwriteNamespace: FromContext|Always|Neverreplaces the inference that decides whethermetadata.namespaceiswritten — the one inference an empty folder cannot perform.
the GitTarget recording it, is the same defect as sibling inference with a different actor.
Open
Whether
scopeshould be derived and materialized at creation instead of declared.Not in 0.41.0
Deliberately postponed. 0.41.0 is already a large breaking release (the whole attribution fact-stream
model plus the placement break), and this is the start of a separate wave.