You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE] Residue of the layout and GitTarget API-wave work #339
The single issue that replaces #294 and #296, both closed as shipped. Everything larger has landed: spec.suspend, status.placement, the ambiguous-root refusal and the reconcile-request annotation
(#326), useKustomize and serializeNamespace (#328), the commitWindow / commit.message move and
the source-scope deletion (#330), the reference collapse onto meta.LocalObjectReference, the ClusterWatchRule.spec.rules[].scope removal and the by_type / default metric split (#333).
What is left is small and additive. None of it needs a breaking release.
Express the canonical path as a template constant rendered through RenderPlacementTemplate,
pinned byte-for-byte against ResourceIdentifier.ToGitPath() across cluster-scoped, core,
grouped and sensitive identities. Retires the hand-written canonicalPath in internal/manifestanalyzer/placement.go.
{kindLower} as a placement template variable, plus the single-namespace recipe and its
identity caveat in docs/configuration.md.
One name for the built-in path across docs/architecture.md, docs/configuration.md and the
CRD comments: "canonical", since placement.default is a user declaration.
The CommitRequest lifecycle hole: a TTL or an ownerRef, and the delete verb (F10).
The defaultClusterProvider not-found message (B6).
Decided, and dropped
No corev1.Event on the GitTarget for a fall-back to canonical. The metric names the target and
the missing byType key, and status.placement is the durable record. Two surfaces are enough.
Everything on this issue is now resolved; #400 closes it on merge.
Legibility
✅ The built-in path as a template constant.BuiltinPlacementTemplate = "{namespace}/{groupPath}/{resource}/{name}{sensitiveSuffix}", rendered through RenderPlacementTemplate. The placement ladder, the Git writer, the SOPS filename and the analyzer's plan output all call it, and a test pins it byte for byte against ToGitPath(). (feat!: expire finished CommitRequests and name the placement fallback the built-in path #400)
✅ One name for the built-in path. It is called the built-in path rather than "canonical". "Default path" was rejected because spec.placement.default is a user declaration. This changes one metric label value: gitopsreverser_placements_total{source="canonical"} is now source="builtin" (see docs/UPGRADING.md). (feat!: expire finished CommitRequests and name the placement fallback the built-in path #400)
Riders
❌ CommitRequest.spec.author is declined. The principle is now written down in docs/spec/attribution.md: authorship is established, never asserted. A commit names the identity the API server authenticated, or says it is unknown. A name in a spec is only a claim, even behind a permission check, and it travels with the object when it is applied from Git. To commit under your own name, authenticate as yourself, for example through OIDC.
✅ CommitRequest lifecycle. When a request finishes, the controller writes configbutler.ai/delete-after: <RFC 3339> onto it (--commit-request-ttl, default 48h) and deletes the request once that time has passed. Remove or edit the annotation to keep a request or move its deletion, or set it at creation. Requests that finished before the upgrade carry no annotation and are kept. (feat!: expire finished CommitRequests and name the placement fallback the built-in path #400)
Activity
docs: close the API wave and placement-visibility issues, and drop th…
sunib commentedon Sep 29, 2026
Everything on this issue is now resolved; #400 closes it on merge.
Legibility
BuiltinPlacementTemplate = "{namespace}/{groupPath}/{resource}/{name}{sensitiveSuffix}", rendered throughRenderPlacementTemplate. The placement ladder, the Git writer, the SOPS filename and the analyzer's plan output all call it, and a test pins it byte for byte againstToGitPath(). (feat!: expire finished CommitRequests and name the placement fallback the built-in path #400){kindLower}, with the single-namespace recipe and its identity caveat indocs/configuration.md. (feat!: expire finished CommitRequests and name the placement fallback the built-in path #400)spec.placement.defaultis a user declaration. This changes one metric label value:gitopsreverser_placements_total{source="canonical"}is nowsource="builtin"(seedocs/UPGRADING.md). (feat!: expire finished CommitRequests and name the placement fallback the built-in path #400)Riders
CommitRequest.spec.authoris declined. The principle is now written down indocs/spec/attribution.md: authorship is established, never asserted. A commit names the identity the API server authenticated, or says it is unknown. A name in a spec is only a claim, even behind a permission check, and it travels with the object when it is applied from Git. To commit under your own name, authenticate as yourself, for example through OIDC.configbutler.ai/delete-after: <RFC 3339>onto it (--commit-request-ttl, default48h) and deletes the request once that time has passed. Remove or edit the annotation to keep a request or move its deletion, or set it at creation. Requests that finished before the upgrade carry no annotation and are kept. (feat!: expire finished CommitRequests and name the placement fallback the built-in path #400)defaultClusterProvider not-found message already names the fix, since fix(watch): enforce ClusterProvider admission wherever rules compile #258.